summaryrefslogtreecommitdiff
path: root/spec/ruby/library/stringio/getc_spec.rb
blob: 263d41831663b99a7b0d98e392c9d0a09d37ff88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
require_relative '../../spec_helper'
require 'stringio'
require_relative 'shared/getc'

describe "StringIO#getc" do
  it_behaves_like :stringio_getc, :getc

  it "returns the character at the current position" do
    io = StringIO.new("example")

    io.getc.should == ?e
    io.getc.should == ?x
    io.getc.should == ?a
  end
end

describe "StringIO#getc when self is not readable" do
  it_behaves_like :stringio_getc_not_readable, :getc
end
64d8580609c25542126bcae5'>Makefile.in30
-rw-r--r--NEWS586
-rw-r--r--README6
-rw-r--r--README.EXT5
-rw-r--r--README.EXT.ja6
-rw-r--r--README.ja6
-rw-r--r--array.c1172
-rw-r--r--bcc32/Makefile.sub66
-rwxr-xr-xbcc32/configure.bat92
-rw-r--r--bcc32/setup.mak78
-rw-r--r--bignum.c272
-rw-r--r--class.c47
-rw-r--r--common.mk96
-rw-r--r--configure.in235
-rw-r--r--defines.h25
-rw-r--r--dir.c15
-rw-r--r--dln.c86
-rw-r--r--enum.c1246
-rw-r--r--enumerator.c450
-rw-r--r--error.c31
-rw-r--r--eval.c806
-rw-r--r--ext/Win32API/lib/win32/registry.rb2
-rw-r--r--ext/Win32API/lib/win32/resolv.rb2
-rw-r--r--ext/bigdecimal/bigdecimal.c59
-rw-r--r--ext/bigdecimal/extconf.rb8
-rw-r--r--ext/dbm/dbm.c2
-rw-r--r--ext/dl/dl.c16
-rw-r--r--ext/dl/ptr.c38
-rw-r--r--ext/dl/sym.c1
-rw-r--r--ext/enumerator/.cvsignore2
-rw-r--r--ext/enumerator/enumerator.c298
-rw-r--r--ext/enumerator/enumerator.txt102
-rw-r--r--ext/enumerator/extconf.rb2
-rw-r--r--ext/etc/etc.c2
-rw-r--r--ext/extmk.rb34
-rw-r--r--ext/iconv/iconv.c59
-rw-r--r--ext/io/wait/wait.c4
-rw-r--r--ext/openssl/extconf.rb5
-rw-r--r--ext/openssl/lib/openssl.rb1
-rw-r--r--ext/openssl/lib/openssl/cipher.rb33
-rw-r--r--ext/openssl/lib/openssl/digest.rb14
-rw-r--r--ext/openssl/lib/openssl/pkcs7.rb25
-rw-r--r--ext/openssl/lib/openssl/ssl.rb90
-rw-r--r--ext/openssl/openssl_missing.c12
-rw-r--r--ext/openssl/openssl_missing.h60
-rw-r--r--ext/openssl/ossl.c32
-rw-r--r--ext/openssl/ossl.h21
-rw-r--r--ext/openssl/ossl_asn1.c60
-rw-r--r--ext/openssl/ossl_bio.c23
-rw-r--r--ext/openssl/ossl_bn.c163
-rw-r--r--ext/openssl/ossl_bn.h5
-rw-r--r--ext/openssl/ossl_cipher.c247
-rw-r--r--ext/openssl/ossl_cipher.h1
-rw-r--r--ext/openssl/ossl_config.c12
-rw-r--r--ext/openssl/ossl_digest.c195
-rw-r--r--ext/openssl/ossl_digest.h1
-rw-r--r--ext/openssl/ossl_engine.c10
-rw-r--r--ext/openssl/ossl_hmac.c68
-rw-r--r--ext/openssl/ossl_ns_spki.c12
-rw-r--r--ext/openssl/ossl_ocsp.c24
-rw-r--r--ext/openssl/ossl_pkcs12.c76
-rw-r--r--ext/openssl/ossl_pkcs12.h1
-rw-r--r--ext/openssl/ossl_pkcs5.c96
-rw-r--r--ext/openssl/ossl_pkcs7.c62
-rw-r--r--ext/openssl/ossl_pkcs7.h1
-rw-r--r--ext/openssl/ossl_pkey.c24
-rw-r--r--ext/openssl/ossl_pkey.h21
-rw-r--r--ext/openssl/ossl_pkey_dh.c101
-rw-r--r--ext/openssl/ossl_pkey_dsa.c92
-rw-r--r--ext/openssl/ossl_pkey_ec.c1582
-rw-r--r--ext/openssl/ossl_pkey_rsa.c119
-rw-r--r--ext/openssl/ossl_rand.c88
-rw-r--r--ext/openssl/ossl_ssl.c645
-rw-r--r--ext/openssl/ossl_ssl.h15
-rw-r--r--ext/openssl/ossl_ssl_session.c298
-rw-r--r--ext/openssl/ossl_x509attr.c36
-rw-r--r--ext/openssl/ossl_x509cert.c109
-rw-r--r--ext/openssl/ossl_x509crl.c16
-rw-r--r--ext/openssl/ossl_x509ext.c24
-rw-r--r--ext/openssl/ossl_x509name.c42
-rw-r--r--ext/openssl/ossl_x509req.c10
-rw-r--r--ext/openssl/ossl_x509revoked.c8
-rw-r--r--ext/openssl/ossl_x509store.c17
-rw-r--r--ext/openssl/ruby_missing.h27
-rw-r--r--ext/pty/expect_sample.rb15
-rw-r--r--ext/pty/lib/expect.rb2
-rw-r--r--ext/pty/pty.c70
-rw-r--r--ext/purelib.rb9
-rw-r--r--ext/readline/readline.c21
-rw-r--r--ext/socket/addrinfo.h5
-rw-r--r--ext/socket/socket.c111
-rw-r--r--ext/stringio/stringio.c63
-rw-r--r--ext/syck/rubyext.c16
-rw-r--r--ext/syslog/syslog.c3
-rw-r--r--ext/syslog/syslog.txt5
-rw-r--r--ext/thread/thread.c29
-rw-r--r--ext/tk/ChangeLog.tkextlib6
-rw-r--r--ext/tk/MANUAL_tcltklib.eng24
-rw-r--r--ext/tk/MANUAL_tcltklib.eucj22
-rw-r--r--ext/tk/README.1st13
-rw-r--r--ext/tk/README.tcltklib20
-rw-r--r--ext/tk/extconf.rb166
-rw-r--r--ext/tk/lib/multi-tk.rb200
-rw-r--r--ext/tk/lib/tcltk.rb2
-rw-r--r--ext/tk/lib/tk.rb1226
-rw-r--r--ext/tk/lib/tk/autoload.rb358
-rw-r--r--ext/tk/lib/tk/bindtag.rb83
-rw-r--r--ext/tk/lib/tk/button.rb5
-rw-r--r--ext/tk/lib/tk/canvas.rb54
-rw-r--r--ext/tk/lib/tk/canvastag.rb117
-rw-r--r--ext/tk/lib/tk/checkbutton.rb9
-rw-r--r--ext/tk/lib/tk/composite.rb70
-rw-r--r--ext/tk/lib/tk/encodedstr.rb84
-rw-r--r--ext/tk/lib/tk/entry.rb6
-rw-r--r--ext/tk/lib/tk/event.rb62
-rw-r--r--ext/tk/lib/tk/font.rb732
-rw-r--r--ext/tk/lib/tk/frame.rb5
-rw-r--r--ext/tk/lib/tk/grid.rb49
-rw-r--r--ext/tk/lib/tk/image.rb62
-rw-r--r--ext/tk/lib/tk/itemconfig.rb164
-rw-r--r--ext/tk/lib/tk/itemfont.rb33
-rw-r--r--ext/tk/lib/tk/label.rb5
-rw-r--r--ext/tk/lib/tk/labelframe.rb8
-rw-r--r--ext/tk/lib/tk/listbox.rb5
-rw-r--r--ext/tk/lib/tk/macpkg.rb9
-rw-r--r--ext/tk/lib/tk/menu.rb91
-rw-r--r--ext/tk/lib/tk/menubar.rb2
-rw-r--r--ext/tk/lib/tk/menuspec.rb26
-rw-r--r--ext/tk/lib/tk/message.rb5
-rw-r--r--ext/tk/lib/tk/msgcat.rb6
-rw-r--r--ext/tk/lib/tk/namespace.rb149
-rw-r--r--ext/tk/lib/tk/optiondb.rb16
-rw-r--r--ext/tk/lib/tk/pack.rb17
-rw-r--r--ext/tk/lib/tk/package.rb4
-rw-r--r--ext/tk/lib/tk/palette.rb2
-rw-r--r--ext/tk/lib/tk/panedwindow.rb32
-rw-r--r--ext/tk/lib/tk/radiobutton.rb9
-rw-r--r--ext/tk/lib/tk/root.rb37
-rw-r--r--ext/tk/lib/tk/scale.rb33
-rw-r--r--ext/tk/lib/tk/scrollbar.rb65
-rw-r--r--ext/tk/lib/tk/scrollbox.rb7
-rw-r--r--ext/tk/lib/tk/spinbox.rb24
-rw-r--r--ext/tk/lib/tk/text.rb178
-rw-r--r--ext/tk/lib/tk/textimage.rb14
-rw-r--r--ext/tk/lib/tk/textmark.rb102
-rw-r--r--ext/tk/lib/tk/texttag.rb113
-rw-r--r--ext/tk/lib/tk/textwindow.rb13
-rw-r--r--ext/tk/lib/tk/timer.rb55
-rw-r--r--ext/tk/lib/tk/toplevel.rb13
-rw-r--r--ext/tk/lib/tk/ttk_selector.rb76
-rw-r--r--ext/tk/lib/tk/validation.rb25
-rw-r--r--ext/tk/lib/tk/variable.rb488
-rw-r--r--ext/tk/lib/tk/virtevent.rb77
-rw-r--r--ext/tk/lib/tk/winpkg.rb18
-rw-r--r--ext/tk/lib/tk/wm.rb476
-rw-r--r--ext/tk/lib/tkextlib/SUPPORT_STATUS2
-rw-r--r--ext/tk/lib/tkextlib/blt/bitmap.rb21
-rw-r--r--ext/tk/lib/tkextlib/blt/busy.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/component.rb452
-rw-r--r--ext/tk/lib/tkextlib/blt/dragdrop.rb54
-rw-r--r--ext/tk/lib/tkextlib/blt/eps.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/htext.rb1
-rw-r--r--ext/tk/lib/tkextlib/blt/table.rb17
-rw-r--r--ext/tk/lib/tkextlib/blt/tabset.rb81
-rw-r--r--ext/tk/lib/tkextlib/blt/ted.rb9
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/button.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/checkbutton.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/frame.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/label.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/radiobutton.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/scrollbar.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tile/toplevel.rb2
-rw-r--r--ext/tk/lib/tkextlib/blt/tree.rb341
-rw-r--r--ext/tk/lib/tkextlib/blt/treeview.rb228
-rw-r--r--ext/tk/lib/tkextlib/blt/unix_dnd.rb16
-rw-r--r--ext/tk/lib/tkextlib/blt/vector.rb37
-rw-r--r--ext/tk/lib/tkextlib/blt/watch.rb47
-rw-r--r--ext/tk/lib/tkextlib/bwidget/button.rb2
-rw-r--r--ext/tk/lib/tkextlib/bwidget/buttonbox.rb20
-rw-r--r--ext/tk/lib/tkextlib/bwidget/combobox.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dialog.rb33
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dynamichelp.rb7
-rw-r--r--ext/tk/lib/tkextlib/bwidget/entry.rb2
-rw-r--r--ext/tk/lib/tkextlib/bwidget/label.rb2
-rw-r--r--ext/tk/lib/tkextlib/bwidget/labelentry.rb2
-rw-r--r--ext/tk/lib/tkextlib/bwidget/labelframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/listbox.rb37
-rw-r--r--ext/tk/lib/tkextlib/bwidget/mainframe.rb48
-rw-r--r--ext/tk/lib/tkextlib/bwidget/messagedlg.rb16
-rw-r--r--ext/tk/lib/tkextlib/bwidget/notebook.rb24
-rw-r--r--ext/tk/lib/tkextlib/bwidget/pagesmanager.rb16
-rw-r--r--ext/tk/lib/tkextlib/bwidget/panedwindow.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/panelframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/progressdlg.rb4
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrollableframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/selectcolor.rb28
-rw-r--r--ext/tk/lib/tkextlib/bwidget/selectfont.rb7
-rw-r--r--ext/tk/lib/tkextlib/bwidget/spinbox.rb2
-rw-r--r--ext/tk/lib/tkextlib/bwidget/statusbar.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/titleframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/tree.rb37
-rw-r--r--ext/tk/lib/tkextlib/bwidget/widget.rb20
-rw-r--r--ext/tk/lib/tkextlib/itcl/incr_tcl.rb12
-rw-r--r--ext/tk/lib/tkextlib/itk/incr_tk.rb44
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/buttonbox.rb5
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/calendar.rb19
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/checkbox.rb21
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/dialogshell.rb5
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/entryfield.rb19
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/hierarchy.rb58
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/menubar.rb5
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/messagebox.rb5
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/notebook.rb16
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/panedwindow.rb5
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/radiobox.rb16
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb12
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb2
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb30
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/selectionbox.rb2
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb2
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/spinner.rb19
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb21
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/tabset.rb49
-rw-r--r--ext/tk/lib/tkextlib/tcllib/autoscroll.rb2
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ctext.rb2
-rw-r--r--ext/tk/lib/tkextlib/tcllib/datefield.rb2
-rw-r--r--ext/tk/lib/tkextlib/tcllib/getstring.rb5
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ico.rb6
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ip_entry.rb2
-rw-r--r--ext/tk/lib/tkextlib/tcllib/plotchart.rb77
-rw-r--r--ext/tk/lib/tkextlib/tcllib/swaplist.rb5
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tablelist_core.rb16
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tkpiechart.rb14
-rw-r--r--ext/tk/lib/tkextlib/tile.rb257
-rw-r--r--ext/tk/lib/tkextlib/tile/dialog.rb14
-rw-r--r--ext/tk/lib/tkextlib/tile/sizegrip.rb4
-rw-r--r--ext/tk/lib/tkextlib/tile/style.rb239
-rw-r--r--ext/tk/lib/tkextlib/tile/tbutton.rb7
-rw-r--r--ext/tk/lib/tkextlib/tile/tcheckbutton.rb8
-rw-r--r--ext/tk/lib/tkextlib/tile/tcombobox.rb3
-rw-r--r--ext/tk/lib/tkextlib/tile/tentry.rb12
-rw-r--r--ext/tk/lib/tkextlib/tile/tframe.rb7
-rw-r--r--ext/tk/lib/tkextlib/tile/tlabel.rb7
-rw-r--r--ext/tk/lib/tkextlib/tile/tlabelframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/tile/tmenubutton.rb12
-rw-r--r--ext/tk/lib/tkextlib/tile/tnotebook.rb31
-rw-r--r--ext/tk/lib/tkextlib/tile/tpaned.rb55
-rw-r--r--ext/tk/lib/tkextlib/tile/tprogressbar.rb3
-rw-r--r--ext/tk/lib/tkextlib/tile/tradiobutton.rb8
-rw-r--r--ext/tk/lib/tkextlib/tile/treeview.rb193
-rw-r--r--ext/tk/lib/tkextlib/tile/tscale.rb7
-rw-r--r--ext/tk/lib/tkextlib/tile/tscrollbar.rb28
-rw-r--r--ext/tk/lib/tkextlib/tile/tseparator.rb3
-rw-r--r--ext/tk/lib/tkextlib/tkDND/shape.rb32
-rw-r--r--ext/tk/lib/tkextlib/tkDND/tkdnd.rb18
-rw-r--r--ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb17
-rw-r--r--ext/tk/lib/tkextlib/tktable/tktable.rb188
-rw-r--r--ext/tk/lib/tkextlib/tktrans/tktrans.rb4
-rw-r--r--ext/tk/lib/tkextlib/treectrl/tktreectrl.rb300
-rw-r--r--ext/tk/lib/tkextlib/version.rb2
-rw-r--r--ext/tk/lib/tkextlib/vu/pie.rb77
-rw-r--r--ext/tk/lib/tkextlib/vu/spinbox.rb2
-rw-r--r--ext/tk/lib/tkextlib/winico/winico.rb57
-rw-r--r--ext/tk/sample/binstr_usage.rb12
-rw-r--r--ext/tk/sample/demos-en/anilabel.rb10
-rw-r--r--ext/tk/sample/demos-en/aniwave.rb9
-rw-r--r--ext/tk/sample/demos-en/arrow.rb26
-rw-r--r--ext/tk/sample/demos-en/bind.rb33
-rw-r--r--ext/tk/sample/demos-en/bitmap.rb10
-rw-r--r--ext/tk/sample/demos-en/button.rb2
-rw-r--r--ext/tk/sample/demos-en/check.rb14
-rw-r--r--ext/tk/sample/demos-en/check2.rb14
-rw-r--r--ext/tk/sample/demos-en/clrpick.rb22
-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.rb14
-rw-r--r--ext/tk/sample/demos-en/ctext.rb53
-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.rb50
-rw-r--r--ext/tk/sample/demos-en/filebox.rb17
-rw-r--r--ext/tk/sample/demos-en/floor.rb14
-rw-r--r--ext/tk/sample/demos-en/floor2.rb14
-rw-r--r--ext/tk/sample/demos-en/form.rb8
-rw-r--r--ext/tk/sample/demos-en/goldberg.rb23
-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.rb20
-rw-r--r--ext/tk/sample/demos-en/image1.rb13
-rw-r--r--ext/tk/sample/demos-en/image2.rb22
-rw-r--r--ext/tk/sample/demos-en/image3.rb29
-rw-r--r--ext/tk/sample/demos-en/items.rb17
-rw-r--r--ext/tk/sample/demos-en/knightstour.rb271
-rw-r--r--ext/tk/sample/demos-en/label.rb13
-rw-r--r--ext/tk/sample/demos-en/labelframe.rb8
-rw-r--r--ext/tk/sample/demos-en/mclist.rb117
-rw-r--r--ext/tk/sample/demos-en/menu.rb12
-rw-r--r--ext/tk/sample/demos-en/menu84.rb8
-rw-r--r--ext/tk/sample/demos-en/menubu.rb10
-rw-r--r--ext/tk/sample/demos-en/msgbox.rb10
-rw-r--r--ext/tk/sample/demos-en/msgbox2.rb91
-rw-r--r--ext/tk/sample/demos-en/paned1.rb14
-rw-r--r--ext/tk/sample/demos-en/paned2.rb8
-rw-r--r--ext/tk/sample/demos-en/patch_1.1c193
-rw-r--r--ext/tk/sample/demos-en/pendulum.rb43
-rw-r--r--ext/tk/sample/demos-en/plot.rb8
-rw-r--r--ext/tk/sample/demos-en/puzzle.rb32
-rw-r--r--ext/tk/sample/demos-en/radio.rb12
-rw-r--r--ext/tk/sample/demos-en/radio2.rb17
-rw-r--r--ext/tk/sample/demos-en/radio3.rb19
-rw-r--r--ext/tk/sample/demos-en/rolodex-j323
-rw-r--r--ext/tk/sample/demos-en/ruler.rb8
-rw-r--r--ext/tk/sample/demos-en/sayings.rb8
-rw-r--r--ext/tk/sample/demos-en/search.rb19
-rw-r--r--ext/tk/sample/demos-en/spin.rb12
-rw-r--r--ext/tk/sample/demos-en/states.rb8
-rw-r--r--ext/tk/sample/demos-en/style.rb42
-rw-r--r--ext/tk/sample/demos-en/text.rb8
-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.rb14
-rw-r--r--ext/tk/sample/demos-en/twind2.rb6
-rw-r--r--ext/tk/sample/demos-en/unicodeout.rb14
-rw-r--r--ext/tk/sample/demos-en/vscale.rb29
-rw-r--r--ext/tk/sample/demos-en/widget232
-rw-r--r--ext/tk/sample/demos-jp/anilabel.rb11
-rw-r--r--ext/tk/sample/demos-jp/aniwave.rb10
-rw-r--r--ext/tk/sample/demos-jp/arrow.rb27
-rw-r--r--ext/tk/sample/demos-jp/bind.rb34
-rw-r--r--ext/tk/sample/demos-jp/bitmap.rb11
-rw-r--r--ext/tk/sample/demos-jp/button.rb4
-rw-r--r--ext/tk/sample/demos-jp/check.rb15
-rw-r--r--ext/tk/sample/demos-jp/check2.rb15
-rw-r--r--ext/tk/sample/demos-jp/clrpick.rb21
-rw-r--r--ext/tk/sample/demos-jp/colors.rb19
-rw-r--r--ext/tk/sample/demos-jp/combo.rb98
-rw-r--r--ext/tk/sample/demos-jp/cscroll.rb15
-rw-r--r--ext/tk/sample/demos-jp/ctext.rb54
-rw-r--r--ext/tk/sample/demos-jp/dialog1.rb1
-rw-r--r--ext/tk/sample/demos-jp/dialog2.rb1
-rw-r--r--ext/tk/sample/demos-jp/entry1.rb13
-rw-r--r--ext/tk/sample/demos-jp/entry2.rb9
-rw-r--r--ext/tk/sample/demos-jp/entry3.rb49
-rw-r--r--ext/tk/sample/demos-jp/filebox.rb18
-rw-r--r--ext/tk/sample/demos-jp/floor.rb15
-rw-r--r--ext/tk/sample/demos-jp/floor2.rb15
-rw-r--r--ext/tk/sample/demos-jp/form.rb9
-rw-r--r--ext/tk/sample/demos-jp/goldberg.rb24
-rw-r--r--ext/tk/sample/demos-jp/hello1
-rw-r--r--ext/tk/sample/demos-jp/hscale.rb29
-rw-r--r--ext/tk/sample/demos-jp/icon.rb21
-rw-r--r--ext/tk/sample/demos-jp/image1.rb14
-rw-r--r--ext/tk/sample/demos-jp/image2.rb24
-rw-r--r--ext/tk/sample/demos-jp/image3.rb18
-rw-r--r--ext/tk/sample/demos-jp/items.rb18
-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.rb14
-rw-r--r--ext/tk/sample/demos-jp/labelframe.rb10
-rw-r--r--ext/tk/sample/demos-jp/mclist.rb121
-rw-r--r--ext/tk/sample/demos-jp/menu.rb15
-rw-r--r--ext/tk/sample/demos-jp/menu84.rb9
-rw-r--r--ext/tk/sample/demos-jp/menu8x.rb13
-rw-r--r--ext/tk/sample/demos-jp/menubu.rb11
-rw-r--r--ext/tk/sample/demos-jp/msgbox.rb15
-rw-r--r--ext/tk/sample/demos-jp/msgbox2.rb90
-rw-r--r--ext/tk/sample/demos-jp/paned1.rb16
-rw-r--r--ext/tk/sample/demos-jp/paned2.rb10
-rw-r--r--ext/tk/sample/demos-jp/pendulum.rb44
-rw-r--r--ext/tk/sample/demos-jp/plot.rb15
-rw-r--r--ext/tk/sample/demos-jp/puzzle.rb33
-rw-r--r--ext/tk/sample/demos-jp/radio.rb13
-rw-r--r--ext/tk/sample/demos-jp/radio2.rb19
-rw-r--r--ext/tk/sample/demos-jp/radio3.rb21
-rw-r--r--ext/tk/sample/demos-jp/rolodex-j1
-rw-r--r--ext/tk/sample/demos-jp/ruler.rb9
-rw-r--r--ext/tk/sample/demos-jp/sayings.rb9
-rw-r--r--ext/tk/sample/demos-jp/search.rb20
-rw-r--r--ext/tk/sample/demos-jp/spin.rb16
-rw-r--r--ext/tk/sample/demos-jp/states.rb9
-rw-r--r--ext/tk/sample/demos-jp/style.rb42
-rw-r--r--ext/tk/sample/demos-jp/tcolor1
-rw-r--r--ext/tk/sample/demos-jp/text.rb9
-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.rb13
-rw-r--r--ext/tk/sample/demos-jp/twind2.rb7
-rw-r--r--ext/tk/sample/demos-jp/unicodeout.rb16
-rw-r--r--ext/tk/sample/demos-jp/vscale.rb30
-rw-r--r--ext/tk/sample/demos-jp/widget278
-rw-r--r--ext/tk/sample/encstr_usage.rb5
-rw-r--r--ext/tk/sample/figmemo_sample.rb456
-rw-r--r--ext/tk/sample/irbtkw.rbw24
-rw-r--r--ext/tk/sample/tcltklib/sample2.rb2
-rw-r--r--ext/tk/sample/tkextlib/tile/demo.rb39
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl2
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc.rb30
-rw-r--r--ext/tk/sample/tkextlib/treectrl/demo.rb7
-rw-r--r--ext/tk/sample/tkextlib/vu/canvSticker2.rb12
-rw-r--r--ext/tk/sample/tkrttimer.rb13
-rw-r--r--ext/tk/sample/tksleep_sample.rb29
-rw-r--r--ext/tk/sample/tktextio.rb12
-rw-r--r--ext/tk/sample/ttk_wrapper.rb154
-rw-r--r--ext/tk/stubs.c78
-rw-r--r--ext/tk/tcltklib.c2692
-rw-r--r--ext/tk/tkutil/extconf.rb2
-rw-r--r--ext/tk/tkutil/tkutil.c708
-rw-r--r--ext/win32ole/tests/testOLEEVENT.rb91
-rw-r--r--ext/win32ole/tests/testWIN32OLE.rb3
-rw-r--r--ext/win32ole/tests/test_win32ole_event.rb133
-rw-r--r--ext/win32ole/tests/testall.rb1
-rw-r--r--ext/win32ole/win32ole.c188
-rw-r--r--ext/zlib/extconf.rb4
-rw-r--r--ext/zlib/zlib.c15
-rw-r--r--file.c152
-rw-r--r--gc.c136
-rw-r--r--hash.c518
-rw-r--r--inits.c2
-rwxr-xr-xinstruby.rb176
-rw-r--r--intern.h28
-rw-r--r--io.c411
-rw-r--r--keywords2
-rw-r--r--lex.c2
-rw-r--r--lib/README4
-rw-r--r--lib/benchmark.rb9
-rw-r--r--lib/cgi.rb19
-rw-r--r--lib/cgi/session.rb28
-rw-r--r--lib/cgi/session/pstore.rb2
-rw-r--r--lib/complex.rb32
-rw-r--r--lib/date.rb171
-rw-r--r--lib/date/format.rb386
-rw-r--r--lib/delegate.rb48
-rw-r--r--lib/drb/drb.rb25
-rw-r--r--lib/drb/extservm.rb41
-rw-r--r--lib/erb.rb304
-rw-r--r--lib/forwardable.rb2
-rw-r--r--lib/generator.rb38
-rw-r--r--lib/ipaddr.rb146
-rw-r--r--lib/irb.rb18
-rw-r--r--lib/irb/extend-command.rb2
-rw-r--r--lib/irb/help.rb2
-rw-r--r--lib/irb/notifier.rb2
-rw-r--r--lib/irb/ruby-lex.rb2
-rw-r--r--lib/irb/slex.rb2
-rw-r--r--lib/logger.rb2
-rw-r--r--lib/matrix.rb18
-rw-r--r--lib/mkmf.rb327
-rw-r--r--lib/net/ftp.rb11
-rw-r--r--lib/net/https.rb4
-rw-r--r--lib/net/imap.rb6
-rw-r--r--lib/net/pop.rb230
-rw-r--r--lib/net/protocol.rb4
-rw-r--r--lib/net/smtp.rb635
-rw-r--r--lib/net/telnet.rb20
-rw-r--r--lib/open-uri.rb2
-rw-r--r--lib/optparse.rb15
-rw-r--r--lib/pp.rb13
-rw-r--r--lib/pstore.rb4
-rw-r--r--lib/rational.rb78
-rw-r--r--lib/rdoc/options.rb2
-rw-r--r--lib/rdoc/parsers/parse_c.rb8
-rw-r--r--lib/rdoc/parsers/parse_f95.rb8
-rw-r--r--lib/rdoc/parsers/parse_rb.rb8
-rw-r--r--lib/rdoc/ri/ri_options.rb34
-rw-r--r--lib/rdoc/ri/ri_paths.rb27
-rw-r--r--lib/resolv-replace.rb3
-rw-r--r--lib/resolv.rb1244
-rw-r--r--lib/rexml/attlistdecl.rb2
-rw-r--r--lib/rexml/document.rb2
-rw-r--r--lib/rexml/element.rb6
-rw-r--r--lib/rexml/formatters/pretty.rb2
-rw-r--r--lib/rexml/functions.rb2
-rw-r--r--lib/rexml/node.rb2
-rw-r--r--lib/rexml/text.rb2
-rw-r--r--lib/rexml/xpath.rb2
-rw-r--r--lib/rinda/ring.rb4
-rw-r--r--lib/rinda/tuplespace.rb100
-rw-r--r--lib/rss.rb7
-rw-r--r--lib/rss/0.9.rb22
-rw-r--r--lib/rss/1.0.rb13
-rw-r--r--lib/rss/2.0.rb2
-rw-r--r--lib/rss/atom.rb749
-rw-r--r--lib/rss/content.rb25
-rw-r--r--lib/rss/content/1.0.rb10
-rw-r--r--lib/rss/content/2.0.rb12
-rw-r--r--lib/rss/converter.rb8
-rw-r--r--lib/rss/dublincore.rb39
-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.rb10
-rw-r--r--lib/rss/itunes.rb410
-rw-r--r--lib/rss/maker.rb25
-rw-r--r--lib/rss/maker/0.9.rb375
-rw-r--r--lib/rss/maker/1.0.rb332
-rw-r--r--lib/rss/maker/2.0.rb147
-rw-r--r--lib/rss/maker/atom.rb172
-rw-r--r--lib/rss/maker/base.rb844
-rw-r--r--lib/rss/maker/content.rb14
-rw-r--r--lib/rss/maker/dublincore.rb145
-rw-r--r--lib/rss/maker/entry.rb163
-rw-r--r--lib/rss/maker/feed.rb429
-rw-r--r--lib/rss/maker/image.rb116
-rw-r--r--lib/rss/maker/itunes.rb242
-rw-r--r--lib/rss/maker/slash.rb33
-rw-r--r--lib/rss/maker/syndication.rb13
-rw-r--r--lib/rss/maker/taxonomy.rb118
-rw-r--r--lib/rss/maker/trackback.rb115
-rw-r--r--lib/rss/parser.rb167
-rw-r--r--lib/rss/rss.rb735
-rw-r--r--lib/rss/slash.rb49
-rw-r--r--lib/rss/syndication.rb9
-rw-r--r--lib/rss/taxonomy.rb2
-rw-r--r--lib/rss/utils.rb78
-rw-r--r--lib/rss/xml-stylesheet.rb4
-rw-r--r--lib/rss/xml.rb71
-rw-r--r--lib/securerandom.rb137
-rw-r--r--lib/set.rb48
-rw-r--r--lib/shellwords.rb146
-rw-r--r--lib/singleton.rb61
-rw-r--r--lib/tempfile.rb26
-rw-r--r--lib/time.rb18
-rw-r--r--lib/timeout.rb23
-rw-r--r--lib/tmpdir.rb104
-rw-r--r--lib/uri.rb1
-rw-r--r--lib/uri/ftp.rb86
-rw-r--r--lib/uri/generic.rb104
-rw-r--r--lib/uri/ldaps.rb12
-rw-r--r--lib/webrick/httpproxy.rb2
-rw-r--r--lib/webrick/httpresponse.rb2
-rw-r--r--lib/webrick/httpservlet/cgihandler.rb4
-rw-r--r--lib/webrick/httputils.rb16
-rw-r--r--lib/xmlrpc/client.rb10
-rw-r--r--lib/yaml.rb4
-rw-r--r--lib/yaml/baseemitter.rb2
-rw-r--r--lib/yaml/basenode.rb2
-rw-r--r--lib/yaml/encoding.rb6
-rw-r--r--lib/yaml/rubytypes.rb20
-rw-r--r--lib/yaml/store.rb20
-rw-r--r--lib/yaml/types.rb8
-rw-r--r--marshal.c65
-rw-r--r--math.c4
-rw-r--r--misc/README3
-rw-r--r--misc/rdebug.el136
-rw-r--r--misc/ruby-mode.el37
-rw-r--r--misc/ruby-style.el66
-rw-r--r--missing.h2
-rw-r--r--missing/crypt.c34
-rw-r--r--missing/vsnprintf.c2
-rwxr-xr-xmkconfig.rb6
-rw-r--r--node.h16
-rw-r--r--numeric.c467
-rw-r--r--object.c102
-rw-r--r--pack.c30
-rw-r--r--parse.y190
-rw-r--r--process.c45
-rw-r--r--random.c20
-rw-r--r--range.c96
-rw-r--r--re.c147
-rw-r--r--regex.c60
-rw-r--r--regex.h4
-rw-r--r--ruby.c94
-rw-r--r--ruby.h27
-rw-r--r--rubyio.h25
-rw-r--r--rubysig.h8
-rwxr-xr-xrunruby.rb14
-rw-r--r--sample/README3
-rw-r--r--sample/cal.rb84
-rw-r--r--sample/cbreak.rb4
-rw-r--r--sample/dualstack-httpd.rb2
-rw-r--r--sample/erb/erb4html.rb60
-rw-r--r--sample/eval.rb2
-rw-r--r--sample/from.rb2
-rw-r--r--sample/goodfriday.rb48
-rw-r--r--sample/philos.rb2
-rw-r--r--sample/regx.rb2
-rwxr-xr-xsample/rss/blend.rb6
-rwxr-xr-xsample/rss/convert.rb2
-rwxr-xr-x[-rw-r--r--]sample/rss/list_description.rb13
-rwxr-xr-xsample/rss/re_read.rb10
-rwxr-xr-x[-rw-r--r--]sample/rss/rss_recent.rb20
-rw-r--r--sample/test.rb64
-rw-r--r--sample/time.rb16
-rw-r--r--signal.c64
-rw-r--r--sprintf.c17
-rw-r--r--string.c468
-rw-r--r--struct.c28
-rw-r--r--test/drb/drbtest.rb2
-rw-r--r--test/erb/hello.erb4
-rw-r--r--test/erb/test_erb.rb386
-rw-r--r--test/gdbm/test_gdbm.rb4
-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/net/http/test_https_proxy.rb9
-rw-r--r--test/openssl/test_ec.rb113
-rw-r--r--test/openssl/test_ssl.rb348
-rw-r--r--test/pathname/test_pathname.rb26
-rw-r--r--test/rinda/test_rinda.rb97
-rw-r--r--test/rss/dot.pngbin0 -> 111 bytes-rw-r--r--test/rss/rss-assertions.rb1894
-rw-r--r--test/rss/rss-testcase.rb199
-rw-r--r--test/rss/test_1.0.rb61
-rw-r--r--test/rss/test_2.0.rb28
-rw-r--r--test/rss/test_atom.rb681
-rw-r--r--test/rss/test_content.rb68
-rw-r--r--test/rss/test_dublincore.rb316
-rw-r--r--test/rss/test_image.rb22
-rw-r--r--test/rss/test_inherit.rb5
-rw-r--r--test/rss/test_itunes.rb347
-rw-r--r--test/rss/test_maker_0.9.rb147
-rw-r--r--test/rss/test_maker_1.0.rb205
-rw-r--r--test/rss/test_maker_2.0.rb56
-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.rb13
-rw-r--r--test/rss/test_maker_dc.rb9
-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.rb1
-rw-r--r--test/rss/test_maker_xml-stylesheet.rb8
-rw-r--r--test/rss/test_parser.rb26
-rw-r--r--test/rss/test_parser_1.0.rb1
-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.rb25
-rw-r--r--test/rss/test_setup_maker_1.0.rb26
-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.rb4
-rw-r--r--test/rss/test_to_s.rb232
-rw-r--r--test/rss/test_version.rb2
-rw-r--r--test/rss/test_xml-stylesheet.rb6
-rw-r--r--test/ruby/test_array.rb1159
-rw-r--r--test/ruby/test_beginendblock.rb18
-rw-r--r--test/ruby/test_bignum.rb19
-rw-r--r--test/ruby/test_enum.rb258
-rw-r--r--test/ruby/test_enumerator.rb105
-rw-r--r--test/ruby/test_fixnum.rb26
-rw-r--r--test/ruby/test_float.rb34
-rw-r--r--test/ruby/test_hash.rb3
-rw-r--r--test/ruby/test_integer.rb653
-rw-r--r--test/ruby/test_method.rb18
-rw-r--r--test/ruby/test_proc.rb5
-rw-r--r--test/ruby/test_settracefunc.rb6
-rw-r--r--test/ruby/test_sleep.rb10
-rw-r--r--test/ruby/test_symbol.rb15
-rw-r--r--test/ruby/test_time.rb21
-rw-r--r--test/thread/test_thread.rb38
-rw-r--r--test/uri/test_common.rb5
-rw-r--r--test/uri/test_ftp.rb22
-rw-r--r--test/uri/test_generic.rb80
-rw-r--r--[-rwxr-xr-x]test/webrick/webrick_long_filename.cgi0
-rw-r--r--test/xmlrpc/test_cookie.rb96
-rw-r--r--test/yaml/test_yaml.rb8
-rw-r--r--test/yaml/test_yamlstore.rb74
-rw-r--r--time.c17
-rw-r--r--util.c3444
-rw-r--r--variable.c90
-rw-r--r--version.c31
-rw-r--r--version.h32
-rw-r--r--win32/Makefile.sub221
-rwxr-xr-xwin32/resource.rb8
-rw-r--r--win32/setup.mak17
-rw-r--r--win32/win32.c352
-rw-r--r--win32/win32.h25
-rw-r--r--wince/Makefile.sub489
-rw-r--r--wince/mkconfig_wce.rb7
-rw-r--r--wince/mkexports.rb35
-rw-r--r--wince/resource.rb96
688 files changed, 53852 insertions, 11907 deletions
diff --git a/ChangeLog b/ChangeLog
index f65ef39def..6432869b78 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,51 +1,2694 @@
-Wed Jun 11 15:23:13 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
+ 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.
-Wed Jun 11 15:00:55 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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].
-Mon Jun 9 18:09:20 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 06:08:26 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 06:04:41 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 06:02:11 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 05:59:36 2008 Tadayoshi Funaba <tadf@dotrb.org>
+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]
-Sun Jun 8 05:54:44 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 05:37:10 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Wed Dec 19 12:01:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (f_rest_arg): check if duplicated. [ruby-core:14140]
-Sun Jun 8 05:32:45 2008 Tanaka Akira <akr@fsij.org>
+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
+ __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>
-Sun Jun 8 05:24:19 2008 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.
@@ -59,98 +2702,264 @@ Sun Jun 8 05:24:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/readline/extconf.rb: should use have_func for functions instead
of have_var.
-Sun Jun 8 05:08:35 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 05:02:25 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 Jun 8 04:58:05 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 Jun 8 04:55:26 2008 James Edward Gray II <jeg2@ruby-lang.org>
+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.
-Sun Jun 8 04:49:43 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 04:37:34 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 04:16:35 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 Jun 8 04:14:16 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+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]
-Sun Jun 8 03:59:31 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+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]
-Sun Jun 8 03:52:53 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+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]
-Sun Jun 8 03:49:15 2008 Tanaka Akira <akr@fsij.org>
+Wed Nov 14 01:52:59 2007 Tanaka Akira <akr@fsij.org>
* missing/isinf.c (isinf): don't define if the macro is defined.
-Sun Jun 8 03:42:10 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 03:42:10 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 03:42:10 2008 URABE Shyouhei <shyouhei@ice.uec.ac.jp>
+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 ]
-Sun Jun 8 03:28:53 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+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]
-Sun Jun 8 03:07:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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].
-Sun Jun 8 03:04:38 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 02:58:19 2008 James Edward Gray II <jeg2@ruby-lang.org>
+Wed Oct 25 07:18:09 2007 James Edward Gray II <jeg2@ruby-lang.org>
Merged 13781 from trunk.
@@ -164,11 +2973,11 @@ Wed Oct 25 06:46:21 2007 James Edward Gray II <jeg2@ruby-lang.org>
* lib/net/telnet.rb (Net::Telnet#login): Making the password prompt
pattern case insensitive. [ruby-Bugs-10746]
-Sun Jun 8 02:55:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 01:53:50 2008 James Edward Gray II <jeg2@ruby-lang.org>
+Wed Oct 25 08:03:53 2007 James Edward Gray II <jeg2@ruby-lang.org>
Merged 13767, 13768, 13769, and 13770 from trunk.
@@ -185,37 +2994,125 @@ Sun Jun 8 01:53:50 2008 James Edward Gray II <jeg2@ruby-lang.org>
* lib/xmlrpc/utils.rb (XMLRPC::ParseContentType#parse_content_type):
Making Content-Type checks case insensitive. [ruby-Bugs-3367]
-Sun Jun 8 01:50:07 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 01:50:07 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Sun Jun 8 01:41:19 2008 Tanaka Akira <akr@fsij.org>
+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 Jun 8 01:36:26 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 Jun 8 01:31:17 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sun Oct 14 03:55:52 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* win32/mkexports.rb: deal with __fastcall name decorations.
[ruby-list:44111]
-Sun Jun 8 01:27:06 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sat Oct 13 09:02:16 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* {bcc,win}32/mkexports.rb: explicit data. [ruby-list:44108]
-Sun Jun 8 01:15:50 2008 GOTOU Yuuzou <gotoyuzo@notwork.org>
+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]
@@ -225,12 +3122,40 @@ Sun Jun 8 01:15:50 2008 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/lib/net/telnets.rb, ext/openssl/lib/net/ftptls.rb: ditto.
-Thu Jun 5 16:21:16 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+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)
-Thu Jun 5 12:26:45 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+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)
@@ -240,215 +3165,254 @@ Thu Jun 5 12:26:45 2008 NAKAMURA Usaku <usa@ruby-lang.org>
* configure.in, win32/Makefile.sub (LIBS): need to link shell32
library for SH* functions on mswin32 and mingw32.
-Thu Jun 5 12:22:28 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+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 Jun 4 16:41:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Tue Jun 3 16:15:27 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 Jun 3 15:45:00 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
-
- * gc.c (os_obj_of, os_each_obj): hide objects to be finalized.
- [ruby-dev:31810]
-
-Wed Jun 4 19:16:40 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+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]
-Tue Jun 3 15:22:47 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Mon Sep 24 16:52:11 2007 Urabe Shyouhei <shyouhei@ruby-lang.org>
- * process.c (struct rb_exec_arg): proc should be a VALUE.
+ * lib/net/http.rb: fix typo.
- * process.c (rb_f_exec): suppress a warning.
+Sun Sep 23 21:57:25 2007 GOTOU Yuuzou <gotoyuzo@notwork.org>
- * process.c (rb_detach_process): cast for the platforms where size of
- pointer differs from size of int.
+ * 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>
- * process.c (rb_f_exec, rb_f_system): should not exceptions after
- fork. [ruby-core:08262]
+ * lib/net/open-uri.rb: use Net::HTTP#enable_post_connection_check to
+ perform SSL post connection check.
-Wed May 21 01:32:56 2008 GOTOU Yuuzou <gotoyuzo@notwork.org>
+ * ext/openssl/lib/openssl/ssl.c
+ (OpenSSL::SSL::SSLSocket#post_connection_check): refine error message.
- * 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.
+Sun Sep 23 09:05:05 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * lib/webrick/httpservlet/abstract.rb
- (WEBrick::HTTPServlet::AbstracServlet#redirect_to_directory_uri):
- should escape the value of Location: header.
+ * gc.c (os_obj_of, os_each_obj): hide objects to be finalized.
+ [ruby-dev:31810]
- * lib/webrick/httpservlet/cgi_runner.rb: accept interpreter
- command line arguments.
+Sun Sep 23 08:58:01 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
-Sun May 18 01:57:44 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+ * eval_method.ci (rb_attr): should not use alloca for unknowen size
+ input. [ruby-dev:31816]
- * file.c (isdirsep): backslash is valid path separator on cygwin too.
- backported from 1.8 HEAD.
+ * parse.y (rb_intern_str): prevent str from optimization.
-Sat May 17 23:53:57 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sun Sep 23 05:42:35 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
- * file.c (file_expand_path): fix for short file name on Cygwin.
+ * lib/rdoc/options.rb (Options::check_diagram): dot -V output
+ changed. [ ruby-Bugs-11978 ], Thanks Florian Frank.
-Sat May 17 23:50:29 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sat Sep 22 06:02:11 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * file.c (OpenFile): prevent conflict on Windows.
+ * lib/optparse.rb (OptionParser::List::summarize): use each_line if
+ defined rather than each. [ruby-Patches-14096]
- * file.c (USE_NTFS): fixed merge miss.
+Sat Sep 22 05:19:49 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
-Sat May 17 12:36:46 2008 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]
- * file.c (file_expand_path): rb_str_set_len is not backported.
+Fri Sep 21 15:46:20 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
-Sat May 17 12:15:48 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+ * process.c (struct rb_exec_arg): proc should be a VALUE.
- * file.c (file_expand_path): support for alternative data stream
- and ignored trailing garbages of NTFS.
+ * process.c (rb_f_exec): suppress a warning.
- * file.c (rb_file_s_basename): ditto.
+Fri Sep 21 03:05:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * file.c (rb_file_s_extname): ditto.
+ * eval.c, intern.h, ext/thread/thread.c: should not free queue while
+ any live threads are waiting. [ruby-dev:30653]
-Mon Mar 3 23:34:13 2008 GOTOU Yuuzou <gotoyuzo@notwork.org>
+Thu Sep 20 17:24:59 2007 Nobuyoshi Nakada <nobu@ruby-lang.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].
+ * process.c (rb_detach_process): cast for the platforms where size of
+ pointer differs from size of int.
- * lib/webrick/httpservlet/filehandler.rb: pathnames which have
- not to be published should be checked case-insensitively.
+ * process.c (rb_f_exec, rb_f_system): should not exceptions after
+ fork. [ruby-core:08262]
-Mon Dec 3 08:13:52 2007 Kouhei Sutou <kou@cozmixng.org>
+Fri Sep 14 00:34:25 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
- * test/rss/test_taxonomy.rb, test/rss/test_parser_1.0.rb,
- test/rss/test_image.rb, test/rss/rss-testcase.rb: ensured
- declaring XML namespaces.
+ * lib/drb/extservm.rb (invoke_service): use Thread.exclusive instead of
+ Thread.critical
-Sun Sep 23 21:57:25 2007 GOTOU Yuuzou <gotoyuzo@notwork.org>
+Wed Sep 12 23:12:22 2007 Yukihiro Matsumoto <matz@ruby-lang.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>
+ * ruby.c (proc_options): -W should be allowed in RUBYOPT
+ environment variable. [ruby-core:12118]
- * lib/net/open-uri.rb: use Net::HTTP#enable_post_connection_check to
- perform SSL post connection check.
+Mon Sep 10 01:05:25 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
- * ext/openssl/lib/openssl/ssl.c
- (OpenSSL::SSL::SSLSocket#post_connection_check): refine error message.
+ * range.c (range_step): fixed integer overflow. [ruby-dev:31763]
-Sun Sep 23 07:49:49 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sun Sep 9 09:14:45 2007 Tadayoshi Funaba <tadf@dotrb.org>
- * eval.c, intern.h, ext/thread/thread.c: should not free queue while
- any live threads are waiting. [ruby-dev:30653]
+ * lib/date/format.rb (_strptime): now also attaches an element
+ which denotes leftover substring if exists.
-Sun Sep 23 06:05:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sat Sep 8 10:22:20 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
- * ext/stringio/stringio.c (strio_init): separate from strio_initialize
- to share with strio_reopen properly. [ruby-Bugs-13919]
+ * struct.c (rb_struct_s_members): should raise TypeError instead
+ of call rb_bug(). [ruby-dev:31709]
-Sun Sep 23 05:42:35 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+ * marshal.c (r_object0): no nil check require any more.
- * lib/rdoc/options.rb (Options::check_diagram): dot -V output
- changed. [ ruby-Bugs-11978 ], Thanks Florian Frank.
+Sat Sep 8 09:38:19 2007 Tadayoshi Funaba <tadf@dotrb.org>
-Wed Sep 19 11:13:07 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+ * lib/date/format.rb (str[fp]time): now check specifications more
+ strictly.
- * bignum.c (bigtrunc): RBIGNUM(x)->len may be zero. out of bound
- access. [ruby-dev:31404]
+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]
-Mon Sep 17 05:24:13 2007 Sylvain Joyeux <sylvain.joyeux@m4x.org>
+Wed Sep 5 22:02:27 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
- * ext/thread/thread.c (lock_mutex): should take care of threads
- not waiting any longer; there cases of a thread raising
- exceptions. [ ruby-Bugs-11901 ]
+ * array.c (rb_ary_subseq): need integer overflow check.
+ [ruby-dev:31736]
- * test/thread/test_thread.rb (test_mutex_exception_handling):
- test for above.
+ * array.c (rb_ary_splice): ditto. [ruby-dev:31737]
-Mon Sep 17 05:01:55 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+ * array.c (rb_ary_fill): ditto. [ruby-dev:31738]
- * runruby.rb: fix incomplete backport r12339.
+ * string.c (rb_str_splice): integer overflow for length.
+ [ruby-dev:31739]
-Mon Sep 17 04:56:28 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sun Sep 2 00:48:15 2007 Tadayoshi Funaba <tadf@dotrb.org>
- * test/thread/test_thread.rb (test_local_barrier),
- test/thread/lbtest.rb: test for [ruby-dev:30653].
+ * lib/date/format.rb (_parse): improved parsing of ordinal dates.
-Mon Sep 17 04:52:21 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+ * lib/date/format.rb (_parse): use named character classes in some
+ regular expressions.
- * ruby.c (proc_options): -W should be allowed in RUBYOPT
- environment variable. [ruby-core:12118]
+Sat Sep 1 08:13:36 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
-Mon Sep 17 04:37:10 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+ * ext/win32ole/win32ole.c: add WIN32OLE#ole_activex_initialize.
- * range.c (range_step): fixed integer overflow. [ruby-dev:31763]
+Thu Aug 30 13:13:13 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
-Fri Sep 7 17:06:16 2007 Vincent Isambart <vincent.isambart@gmail.com>
+ * lib/mkmf.rb (try_const, have_const): check for a const is defined.
+ [ruby-core:04422]
- * eval.c (rb_thread_start_0): should unset time_thread_alive_p.
- [ruby-talk:257219], [ruby-core:11542], [ruby-dev:31253]
+Thu Aug 30 13:10:57 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
-Fri Sep 7 16:39:23 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+ * configure.in (group_member): check if presents.
- * array.c (rb_ary_subseq): need integer overflow check.
- [ruby-dev:31736]
+ * configure.in (XCFLAGS): add _GNU_SOURCE on linux.
- * array.c (rb_ary_splice): ditto. [ruby-dev:31737]
+ * file.c (group_member): use system routine if available.
- * array.c (rb_ary_fill): ditto. [ruby-dev:31738]
+Thu Aug 30 08:24:18 2007 Tanaka Akira <akr@fsij.org>
- * string.c (rb_str_splice): integer overflow for length.
- [ruby-dev:31739]
+ * ruby.h (RHASH_TBL): defined for compatibility to 1.9.
+ * (RHASH_ITER_LEV): ditto.
+ * (RHASH_IFNONE): ditto.
+ * (RHASH_SIZE): ditto.
+ * (RHASH_EMPTY_P): ditto.
-Fri Sep 7 16:33:23 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+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]
-Fri Sep 7 16:09:39 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+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.
+ * ext/win32ole/win32ole.c (ole_type_progid, reg_enum_key,
+ reg_get_val, ole_wc2mb): fix the bug. Thanks, arton.
[ruby-dev:31576]
-Fri Sep 7 15:50:50 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+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..
-Fri Sep 7 15:43:43 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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().
-Fri Sep 7 15:42:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Fri Sep 7 15:40:47 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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.
-Wed Aug 22 12:40:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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.
@@ -460,24 +3424,36 @@ Wed Aug 22 12:40:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
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]
+ the thread is started too early. [ruby-talk:264062]
* test/rinda/test_rinda.rb: ditto.
-Wed Aug 22 12:31:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed Aug 22 12:30:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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.
-Wed Aug 22 12:29:36 2007 Tadayoshi Funaba <tadf@dotrb.org>
-
- * lib/README: fixed a typo.
-
-Wed Aug 22 12:13:54 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Fri Aug 3 11:05:54 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/extmk.rb (extmake): save all CONFIG values.
@@ -487,20 +3463,37 @@ Wed Aug 22 12:13:54 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/extmk.rb: remove rdoc at clean, and installed list file at
distclean, respectively.
-Wed Aug 22 11:49:00 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed Aug 22 11:47:11 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
+ [ruby-dev:31271]
+
+Sat Jul 28 09:35:41 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
-Wed Aug 22 11:41:44 2007 Nobuyoshi Nakada <nobu@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.
@@ -509,26 +3502,77 @@ Wed Aug 22 11:41:44 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ruby.c (ruby_init_loadpath): not convert built-in paths.
-Wed Aug 22 11:39:31 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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.
-Wed Aug 22 11:00:20 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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.
-Wed Aug 22 10:57:50 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed Aug 22 10:55:00 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed Aug 22 10:36:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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
@@ -536,35 +3580,48 @@ Wed Aug 22 10:36:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* numeric.c (rb_fix_lshift, rb_fix_rshift): ditto.
-Wed Aug 22 10:29:45 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 Aug 22 10:26:59 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+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]
-Wed Aug 22 10:24:00 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+Tue Jul 17 00:50:53 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
- * numeric.c (fix_pow): integer power calculation: 0**n => 0,
+ * 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.
-Wed Aug 22 10:23:01 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+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]
-Wed Aug 22 10:20:32 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed Aug 22 10:13:45 2007 pegacorn <subscriber.jp AT gmail.com>
+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,
@@ -590,101 +3647,198 @@ Wed Aug 22 10:13:45 2007 pegacorn <subscriber.jp AT gmail.com>
* win32.h (rb_w32_getcwd): prototype added. [ruby-dev:31232]
-Wed Aug 22 10:11:59 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed Aug 22 10:07:48 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sun Jul 15 04:42:20 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * bignum.c (rb_big_neg): SIGNED_VALUE isn't in 1.8.
+ * bignum.c (get2comp): do nothing for empty Bignum. [ruby-dev:31225]
- * bignum.c (bigtrunc): do not empty Bignum. [ruby-dev:31229]
+Sat Jul 14 14:04:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
-Wed Aug 22 10:02:42 2007 Yukihiro Matsumoto <matz@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]
-Wed Aug 22 10:01:08 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed Aug 22 09:58:30 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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.
-Wed Aug 22 09:55:08 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 Aug 22 09:54:28 2007 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
+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.
-Wed Aug 22 09:53:14 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Tue Jul 10 14:50:01 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* bcc32/{Makefile.sub,setup.mak}: remove surplus slash from srcdir.
-Wed Aug 22 09:46:25 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed Aug 22 09:41:56 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+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]
-Wed Aug 22 09:40:25 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 from Yusuke ENDOH
+ instance/class variable name. a patch from Yusuke ENDOH
<mame AT tsg.ne.jp>. [ruby-dev:31095]
-Wed Aug 22 09:39:26 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 from Yusuke ENDOH <mame AT tsg.ne.jp>. [ruby-dev:31085]
+ patch from Yusuke ENDOH <mame AT tsg.ne.jp>. [ruby-dev:31085]
-Wed Aug 22 09:38:43 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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.
-Wed Aug 22 09:00:23 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed Aug 22 08:52:02 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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.
-Wed Aug 22 08:51:20 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+ * 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].
-Wed Aug 22 08:49:47 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 Aug 22 08:34:20 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed Aug 22 08:32:32 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Tue Jun 12 14:53:51 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * process.c (ruby_setreuid, ruby_setregid): rename to get rid of name
- clash.
-Wed Aug 22 08:27:53 2007 Shugo Maeda <shugo@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)
@@ -693,28 +3847,20 @@ Wed Aug 22 08:27:53 2007 Shugo Maeda <shugo@ruby-lang.org>
the condition not to refer @token.symbol unexpectedly.
Thanks, Dick Monahan. (backported from HEAD)
-Wed Aug 22 08:26:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
-
- * marshal.c (w_extended): erroneous check condition when dump
- method is defined. [ruby-core:10646]
-
-Mon Jun 18 11:29:49 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
-
- * intern.h, ext/thread/thread.c: moved prototype of rb_thread_status()
- to get rid of error in C++. [ruby-list:43615]
+Thu May 31 17:27:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
-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]
+ * lib/benchmark.rb (Benchmark::Job::item): avoid modifying the
+ argument unintentionally. [ruby-talk:253676]
-Sat Jun 9 10:40:00 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+Thu May 31 02:12:32 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
- * stable version 1.8.6-p36 released.
+ * lib/rinda/tuplespace.rb (Rinda::TupleBag): create index on tuple bag
+ by first column.
-Fri Jun 8 17:50:17 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+Wed May 30 13:27:40 2007 Shugo Maeda <shugo@ruby-lang.org>
- * eval.c (rb_thread_cancel_timer): fix undefined function
+ * 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>
@@ -739,34 +3885,16 @@ Tue May 29 11:01:06 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* win32/win32.c (rb_w32_opendir, rb_w32_readdir): eliminate magic
numbers.
-Thu Jun 7 20:10:51 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 Jun 7 14:53:46 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+Mon May 28 02:54:05 2007 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
- * eval.c (method_inspect): show proper class name.
- [ruby-talk:248647], Thanks Calamitas.
+ * lib/rinda/tuplespace.rb (Rinda::TupleBag#delete): use rindex and
+ delete_at instead of delete for little improvement.
-Sun May 27 05:24:56 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
+Sat May 26 00:05:22 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * runruby.rb: eliminate uninitialized variable.
- [ruby-core:11255]
-
-Sun May 27 05:19:03 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
-
- * eval.c (mnew): call of super via a method object should work again.
- [ruby-talk:248647], Thanks Calamitas.
-
- * test/ruby/test_method.rb (TestMethod::test_method_super): test for
- above fix.
-
-Wed May 23 07:29:53 2007 URABE Shyouhei <shyouhei@ruby-lang.org>
-
- * process.c (proc_exec_v): terminate timer thread in advance.
- [ruby-dev:30581], Thanks H. Holon.
+ * 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>
@@ -779,35 +3907,119 @@ Wed May 23 05:49:49 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
load path to get rid of load pre-installed extensions/libraries.
[ruby-core:11017]
-Wed May 23 06:14:15 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed May 23 05:55:04 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+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.
-Wed May 23 05:35:42 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Mon May 14 13:28:03 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * bignum.c (rb_big_pow): truncate all zero BDIGITs. [ruby-dev:30733]
+ * ext/thread/thread.c (wait_list): supress a warning.
-Wed May 23 05:17:33 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+Thu May 10 15:21:51 2007 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/iconv/iconv.c (iconv_s_conv): rdoc fix.
-Wed May 23 05:10:02 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 23 04:22:57 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed May 23 03:50:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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.
@@ -817,16 +4029,29 @@ Wed May 23 03:50:35 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/mkmf.rb (LINK_SO): LIBPATH to be placed before DLDFLAGS.
-Wed May 23 03:33:55 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 May 23 03:25:13 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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 May 23 03:12:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
@@ -834,7 +4059,7 @@ Wed May 23 03:12:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* configure.in (Makefile): remove $U for automake from MISSING.
[ruby-talk:248171]
-Wed May 23 02:09:32 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+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]
@@ -842,25 +4067,66 @@ Wed May 23 02:09:32 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (proc_invoke): handle TAG_NEXT which would be caused by
next in the lambda body as well.
-Wed May 23 01:55:49 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+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().
-Wed May 23 01:42:29 2007 Shugo Maeda <shugo@ruby-lang.org>
+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.
-Wed May 23 01:28:14 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Wed May 23 00:03:42 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+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.
@@ -878,7 +4144,7 @@ Sat Mar 24 23:40:29 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* io.c (io_fread): ditto.
-Tue May 22 23:27:16 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
@@ -889,26 +4155,55 @@ Tue May 22 23:27:16 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* test/ruby/test_beginendblock.rb (test_should_propagate_signaled):
test for signal in END block.
-Tue May 22 23:14:19 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Tue May 22 21:29:08 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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]
-Tue May 22 20:53:02 2007 Akinori MUSHA <knu@iDaemons.org>
+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;
@@ -949,11 +4244,24 @@ 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 04:04:04 2007 Akinori MUSHA <knu@iDaemons.org>
+Tue Mar 13 09:25:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (clear-installed-list): separated from install-prereq.
- * stable version 1.8.6 released.
+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:54:17 2007 Akinori MUSHA <knu@iDaemons.org>
+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
@@ -985,7 +4293,7 @@ Mon Mar 12 11:07:44 2007 Akinori MUSHA <knu@iDaemons.org>
* ext/openssl/ossl_ssl.c (Init_ossl_ssl): Ditto.
-Mon Mar 12 01:23:50 2007 Akinori MUSHA <knu@iDaemons.org>
+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
@@ -994,14 +4302,16 @@ Mon Mar 12 01:23:50 2007 Akinori MUSHA <knu@iDaemons.org>
* 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 19:04:29 2007 Akinori MUSHA <knu@iDaemons.org>
+Sun Mar 11 18:57:50 2007 Akinori MUSHA <knu@iDaemons.org>
- * misc/README: Add a note about ruby-electric.el.
+ * 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]
@@ -1012,14 +4322,14 @@ Sun Mar 11 19:04:29 2007 Akinori MUSHA <knu@iDaemons.org>
interface based on rubydb3x.el; submitted by Martin Nordholts
<enselic AT gmail.com> in [ruby-bugs:PR#9023].
-Sun Mar 11 17:51:46 2007 Akinori MUSHA <knu@iDaemons.org>
+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 17:30:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sun Mar 11 12:09:37 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (error_handle): no message when exiting by signal.
@@ -1042,63 +4352,83 @@ Sun Mar 11 17:30:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
* signal.c (rb_signal_exec, trap): handle SIGTERM. [ruby-dev:30505]
-Tue Mar 6 19:03:42 2007 Akinori MUSHA <knu@iDaemons.org>
+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:26:10 2007 Akinori MUSHA <knu@iDaemons.org>
+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:53:27 2007 Minero Aoki <aamine@loveruby.net>
-
- * lib/fileutils.rb (mv): could not move a directory between
- different filesystems. [ruby-dev:30411]
-
-Sun Mar 4 23:46:40 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Sun Mar 4 23:38:07 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * file.c (rb_file_s_utime): allow nil to set the current time.
+ * file.c (rb_stat_s_utime): fixed a commit miss for the platforms
+ where utimes() does not exist.
- * lib/fileutils.rb (touch): ditto, and added :mtime and :nocreate
- options. fixed: [ruby-talk:219037]
+ * lib/fileutils.rb (touch): ditto.
-Sun Mar 4 23:19:00 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+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:06:55 2007 Akinori MUSHA <knu@iDaemons.org>
+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 21:41:31 2007 Akinori MUSHA <knu@iDaemons.org>
+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:07:05 2007 Akinori MUSHA <knu@iDaemons.org>
+Sat Mar 3 19:05:31 2007 Akinori MUSHA <knu@iDaemons.org>
* ext/thread/thread.c (push_list): Use ALLOC().
@@ -1106,21 +4436,11 @@ Sat Mar 3 19:07:05 2007 Akinori MUSHA <knu@iDaemons.org>
* ext/thread/thread.c (rb_condvar_alloc): Ditto.
-Sat Mar 3 18:56:40 2007 Akinori MUSHA <knu@iDaemons.org>
+Sat Mar 3 18:53:11 2007 Akinori MUSHA <knu@iDaemons.org>
* NEWS: Add a note for String#intern.
-Sat Mar 3 18:36:35 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]
-
- * 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.
-
-Sat Mar 3 16:30:39 2007 Akinori MUSHA <knu@iDaemons.org>
+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
@@ -1133,78 +4453,108 @@ Sat Mar 3 16:30:39 2007 Akinori MUSHA <knu@iDaemons.org>
* parse.y (top_local_setup_gen): Ditto.
-Sat Mar 3 16:09:27 2007 Akinori MUSHA <knu@iDaemons.org>
+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]
-Sat Mar 3 15:41:33 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+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:30452]
+ empty. [ruby-dev:30455]
-Thu Mar 1 04:08:30 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Thu Mar 1 08:55:38 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * mkconfig.rb (patchlevel): read from version.h.
+ * eval.c (rb_feature_p): check loading_tbl if the given ext is
+ empty. [ruby-dev:30452]
-Thu Mar 1 03:42:09 2007 Akinori MUSHA <knu@iDaemons.org>
+ * 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.
-Wed Feb 28 22:10:55 2007 Akinori MUSHA <knu@iDaemons.org>
+Thu Mar 1 02:05:17 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * doc/NEWS-1.8.0: Rename NEWS to NEWS-1.8.0. This is way too old
- NEWS.
+ * mkconfig.rb (patchlevel): read from version.h.
- * NEWS: Add NEWS, a document file to keep user visible feature
- changes between releases.
+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].
-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]
-
-Tue Feb 27 21:50:10 2007 WATANABE Hirofumi <eban@ruby-lang.org>
+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 20:49:19 2007 Akinori MUSHA <knu@iDaemons.org>
+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>
@@ -1222,6 +4572,8 @@ Tue Feb 27 20:49:19 2007 Akinori MUSHA <knu@iDaemons.org>
* 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].
@@ -1232,28 +4584,35 @@ Tue Feb 27 20:49:19 2007 Akinori MUSHA <knu@iDaemons.org>
* 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:50:51 2007 Akinori MUSHA <knu@iDaemons.org>
+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 17:04:01 2007 Tadayoshi Funaba <tadf@dotrb.org>
-
- * lib/date/format.rb: updated based on date2 4.0.3.
-
-Sat Feb 24 17:01:02 2007 Minero Aoki <aamine@loveruby.net>
+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]
-Sat Feb 24 16:53:09 2007 NAKAMURA Usaku <usa@ruby-lang.org>
+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.
@@ -1261,19 +4620,14 @@ Sat Feb 24 16:53:09 2007 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.[ch] (rb_win32_interrupted): new function to listen
interrupt.
- * 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 13:04:43 2007 Akinori MUSHA <knu@iDaemons.org>
+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:47:13 2007 James Edward Gray II <james@grayproductions.net>
+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
@@ -1283,22 +4637,22 @@ Fri Feb 23 12:47:13 2007 James Edward Gray II <james@grayproductions.net>
* lib/xmlrpc/create.rb (XMLRPC::Create::conv2value): Add DateTime
support to xmlrpc; approved by the maintainer.
-Mon Feb 19 18:33:30 2007 Akinori MUSHA <knu@iDaemons.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]
-
-Mon Feb 19 18:27:42 2007 Akinori MUSHA <knu@iDaemons.org>
+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]
-Thu Feb 15 20:31:07 2007 Akinori MUSHA <knu@iDaemons.org>
+Mon Feb 19 17:14:28 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
- * lib/uri/ftp.rb: Revert the previous change pending discussion.
+ * 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>
@@ -1307,14 +4661,19 @@ Fri Feb 16 11:18:21 2007 Eric Hodel <drbrain@segment7.net>
* lib/prettyprint.rb: Suppress RDoc for PrettyPrint test suite.
-Thu Feb 15 18:10:09 2007 Akinori MUSHA <knu@iDaemons.org>
+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 16:55:33 2007 Akinori MUSHA <knu@iDaemons.org>
+Thu Feb 15 17:13:32 2007 Akinori MUSHA <knu@iDaemons.org>
- * version.h: Branch off ruby_1_8_6 from ruby_1_8 in preparation
- for the forthcoming 1.8.6 release.
+ * 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>
@@ -1445,15 +4804,15 @@ Fri Feb 9 15:46:09 2007 Akinori MUSHA <knu@iDaemons.org>
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]
+ * 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>
@@ -1502,7 +4861,7 @@ Wed Jan 24 18:05:39 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
Tue Jan 23 11:02:33 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
- * lib/webrick/httprequest.rb (WEBrick::HTTPRequest::read_line):
+ * lib/webrick/httprequest.rb (WEBrick::HTTPRequest::read_line):
Tue Jan 23 18:26:12 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -2924,7 +6283,7 @@ Thu Jul 20 15:07:14 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
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]
+ number. [ruby-dev: 29038]
Wed Jul 19 23:53:05 2006 Kouhei Sutou <kou@cozmixng.org>
@@ -6870,6 +10229,7 @@ Mon Aug 1 01:17:40 2005 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
* 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>
@@ -7354,6 +10714,7 @@ Fri Jul 1 00:18:40 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
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.
@@ -8325,7 +11686,6 @@ Sat Apr 9 11:59:57 2005 Kouhei Sutou <kou@cozmixng.org>
- 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
@@ -8353,34 +11713,28 @@ Sat Apr 9 11:59:57 2005 Kouhei Sutou <kou@cozmixng.org>
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.
@@ -8396,7 +11750,6 @@ Sat Apr 9 11:59:57 2005 Kouhei Sutou <kou@cozmixng.org>
* 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.
@@ -12054,7 +15407,6 @@ 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.
@@ -12640,7 +15992,6 @@ Thu Jul 15 10:15:04 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* 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
@@ -15117,7 +18468,6 @@ Tue Dec 30 12:30:30 2003 Dave Thomas <dave@pragprog.com>
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):
@@ -15125,7 +18475,6 @@ Tue Dec 30 08:32:32 2003 Dave Thomas <dave@pragprog.com>
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):
@@ -17031,6 +20380,7 @@ 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>
+
* ext/dl/sym.c: Add DL.win32_last_error and DL.last_error.
Thanks, Kaoru Shirai.
@@ -19868,6 +23218,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>.
@@ -20068,9 +23419,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/Makefile.in b/Makefile.in
index 314e1ed256..a37bcf65fb 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -35,6 +35,9 @@ 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 =
@@ -54,7 +57,7 @@ EXEEXT = @EXEEXT@
PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
RUBY = $(RUBY_INSTALL_NAME)
MINIRUBY = @MINIRUBY@ $(MINIRUBYOPT)
-RUNRUBY = @RUNRUBY@
+RUNRUBY = @RUNRUBY@ $(RUNRUBYOPT) --
#### End of system configuration section. ####
@@ -155,9 +158,12 @@ $(srcdir)/configure: $(srcdir)/configure.in
cd $(srcdir) && $(AUTOCONF)
lex.c: keywords
- @-$(RM) $@
- 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) $<
@@ -178,3 +184,19 @@ distclean-local::
ext/extinit.$(OBJEXT): ext/extinit.c $(SETUP)
$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ -c ext/extinit.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
+
+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)
+
diff --git a/NEWS b/NEWS
index de1dafb533..61373187e5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,55 +1,532 @@
= NEWS
This document is a list of user visible feature changes made between
-releases excluding bug fixes.
+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.
-== Changes with Ruby 1.8.5
+== Changes since the 1.8.6 release
-=== New platforms/build tools support
+=== Configuration changes
-* IA64 HP-UX
+* vendor_ruby directory
-* Visual C++ 8 SP1
+ 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')
-* autoconf 2.6x
+ 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
- * Updated based on date2 4.0.3.
+ * Date.parse
-* digest
+ '##.##.##' (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.
- * New internal APIs for C and Ruby.
+* stringio
- * Support for autoloading.
+ * StringIO#each_byte
- * See below for new features and compatibility issues.
+ The return value changed from nil to self. This is what the
+ document says and the same as each_line() does.
-* nkf
+* tempfile
- * Updated based on nkf as of 2007-01-28.
+ * 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.
-* tk
+* uri
- * 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.
+ * See above for details.
- * Updated Tile extension support based on Tile 0.7.8.
+== Changes since the 1.8.5 release
- * Support --without-X11 configure option for non-X11 versions of
- Tcl/Tk (e.g. Tcl/Tk Aqua).
+=== New platforms/build tools support
- * New sample script: irbtkw.rbw -- IRB on Ruby/Tk. It has no trouble
- about STDIN blocking on Windows.
+* IA64 HP-UX
+
+* Visual C++ 8 SP1
+
+* autoconf 2.6x
+
+=== Global constants
+
+* RUBY_PATCHLEVEL
+
+ New constant since 1.8.5-p1.
-=== New methods and features
+=== Library updates (outstanding ones only)
* builtin classes
@@ -59,13 +536,25 @@ with all sufficient information, see the ChangeLog file.
* 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 digest instance methods: clone, reset, new, inspect,
+ digest_length (alias size or length), block_length()
* New library: digest/bubblebabble
@@ -75,11 +564,25 @@ with all sufficient information, see the ChangeLog file.
* 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 is available with a
- configure option `--disable-fastthread'.
+ * 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
@@ -92,17 +595,17 @@ with all sufficient information, see the ChangeLog file.
* String#intern now raises SecurityError when $SAFE level is greater
than zero.
-* fileutils
+* date
- * A minor implementation change breaks Rake <=0.7.1.
- Updating Rake to 0.7.2 fixes the problem.
+ * 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; digest() and hexdigest() now do,
- instead. The following examples show how to
- migrate:
+ * The constructor does no longer take an initial string to feed.
+ The following examples show how to migrate:
# Before
md = Digest::MD5.new("string")
@@ -113,3 +616,14 @@ with all sufficient information, see the ChangeLog file.
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 cf836415ad..1b79781367 100644
--- a/README
+++ b/README
@@ -29,7 +29,7 @@ The Ruby distribution files can be found in the following FTP site:
The latest source code of this version series can be checked out
through SVN with the following command:
- $ svn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8_6/
+ $ 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:
@@ -70,6 +70,10 @@ This is what you need to do to compile and install Ruby:
2. Run ./configure, which will generate config.h and Makefile.
+ 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
diff --git a/README.EXT b/README.EXT
index 2fc2fd606a..637b19d25b 100644
--- a/README.EXT
+++ b/README.EXT
@@ -662,6 +662,11 @@ 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.
diff --git a/README.EXT.ja b/README.EXT.ja
index 30c4d520ba..73425c2cdb 100644
--- a/README.EXT.ja
+++ b/README.EXT.ja
@@ -765,6 +765,12 @@ Makefile¤ò¼ÂºÝ¤ËÀ¸À®¤¹¤ë¤¿¤á¤Ë¤Ï
¤È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+site_ruby ¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤Ê¤¯¡¢
+vendor_ruby ¥Ç¥£¥ì¥¯¥È¥ê¤Ë¥¤¥ó¥¹¥È¡¼¥ë¤¹¤ë¾ì¹ç¤Ë¤Ï
+°Ê²¼¤Î¤è¤¦¤Ë --vendor ¥ª¥×¥·¥ç¥ó¤ò²Ã¤¨¤Æ¤¯¤À¤µ¤¤¡¥
+
+ ruby extconf.rb --vendor
+
¥Ç¥£¥ì¥¯¥È¥ê¤òext°Ê²¼¤ËÍѰդ·¤¿¾ì¹ç¤Ë¤ÏRubyÁ´ÂΤÎmake¤Î»þ¤Ë
¼«Æ°Åª¤ËMakefile¤¬À¸À®¤µ¤ì¤Þ¤¹¤Î¤Ç¡¤¤³¤Î¥¹¥Æ¥Ã¥×¤ÏÉÔÍפǤ¹¡¥
diff --git a/README.ja b/README.ja
index df8cfc03f4..71ce4ee12c 100644
--- a/README.ja
+++ b/README.ja
@@ -36,7 +36,7 @@ Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤Perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
ËÜ¥Ö¥é¥ó¥Á¤ÎRuby¤ÎºÇ¿·¤Î¥½¡¼¥¹¥³¡¼¥É¤Ï¼¡¤Î¥³¥Þ¥ó¥É¤Ç¼èÆÀ¤Ç¤­¤Þ¤¹¡¥
- $ svn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8_6/
+ $ svn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8/
³«È¯Àèü¤Î¥½¡¼¥¹¥³¡¼¥É¤Ï¼¡¤Î¥³¥Þ¥ó¥É¤Ç¼èÆÀ¤Ç¤­¤Þ¤¹¡¥
@@ -92,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 fbca3c193e..7e8c12b683 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)
@@ -120,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++;
@@ -195,6 +196,27 @@ rb_ary_new4(n, elts)
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;
@@ -293,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) {
@@ -358,6 +380,9 @@ 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) {
@@ -366,10 +391,10 @@ rb_ary_store(ary, idx, val)
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;
}
@@ -384,6 +409,50 @@ 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
@@ -431,18 +500,6 @@ rb_ary_push_m(argc, argv, ary)
return ary;
}
-/*
- * call-seq:
- * array.pop -> obj or nil
- *
- * Removes the last element from <i>self</i> and returns it, or
- * <code>nil</code> if the array is empty.
- *
- * a = [ "a", "m", "z" ]
- * a.pop #=> "z"
- * a #=> ["a", "m"]
- */
-
VALUE
rb_ary_pop(ary)
VALUE ary;
@@ -450,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);
@@ -458,62 +515,112 @@ rb_ary_pop(ary)
return RARRAY(ary)->ptr[--RARRAY(ary)->len];
}
+/*
+ * 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
-ary_make_shared(ary)
+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);
- OBJ_FREEZE(shared);
- return (VALUE)shared;
+ if (argc == 0) {
+ return rb_ary_pop(ary);
}
- else {
- return RARRAY(ary)->aux.shared;
+
+ rb_ary_modify_check(ary);
+ result = ary_shared_first(argc, argv, ary, Qtrue);
+ RARRAY(ary)->len -= RARRAY(result)->len;
+ return result;
+}
+
+VALUE
+rb_ary_shift(ary)
+ VALUE ary;
+{
+ VALUE top;
+
+ rb_ary_modify_check(ary);
+ if (RARRAY(ary)->len == 0) return Qnil;
+ top = RARRAY(ary)->ptr[0];
+ 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 -> 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.shift #=> "-m"
+ * args #=> ["-q", "filename"]
+ *
+ * args = [ "-m", "-q", "filename" ]
+ * args.shift(2) #=> ["-m", "-q"]
+ * args #=> ["filename"]
*/
-VALUE
-rb_ary_shift(ary)
+static VALUE
+rb_ary_shift_m(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
{
- VALUE top;
+ VALUE result;
+ long n;
- rb_ary_modify_check(ary);
- if (RARRAY(ary)->len == 0) return Qnil;
- top = RARRAY(ary)->ptr[0];
- if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE && !FL_TEST(ary, ELTS_SHARED)) {
- MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+1, VALUE, RARRAY_LEN(ary)-1);
+ if (argc == 0) {
+ return rb_ary_shift(ary);
}
- else {
- if (!FL_TEST(ary, ELTS_SHARED)) {
- RARRAY(ary)->ptr[0] = Qnil;
+
+ 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;
}
- ary_make_shared(ary);
- RARRAY(ary)->ptr++; /* shift ptr */
+ else {
+ MEMMOVE(RARRAY(ary)->ptr, RARRAY(ary)->ptr+n, VALUE, RARRAY(ary)->len-n);
+ RARRAY(ary)->len -= n;
}
- RARRAY(ary)->len--;
- return top;
+ return result;
}
VALUE
@@ -748,17 +855,7 @@ 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);
}
}
@@ -784,17 +881,7 @@ 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);
}
}
@@ -850,24 +937,41 @@ rb_ary_fetch(argc, argv, ary)
/*
* call-seq:
- * array.index(obj) -> int or nil
+ * 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>. Returns <code>nil</code> if
- * no match is found.
+ * 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("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);
@@ -879,29 +983,44 @@ rb_ary_index(ary, val)
* 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>. Returns <code>nil</code> if
- * no match is found.
+ * 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("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;
- continue;
}
- if (rb_equal(RARRAY(ary)->ptr[i], val))
- return LONG2NUM(i);
}
return Qnil;
}
@@ -975,6 +1094,9 @@ rb_ary_splice(ary, beg, len, rpl)
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);
@@ -1134,6 +1256,7 @@ rb_ary_each(ary)
{
long i;
+ RETURN_ENUMERATOR(ary, 0, 0);
for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(RARRAY(ary)->ptr[i]);
}
@@ -1161,6 +1284,7 @@ rb_ary_each_index(ary)
{
long i;
+ RETURN_ENUMERATOR(ary, 0, 0);
for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(LONG2NUM(i));
}
@@ -1186,8 +1310,10 @@ 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) {
@@ -1734,6 +1860,7 @@ rb_ary_collect_bang(ary)
{
long i;
+ RETURN_ENUMERATOR(ary, 0, 0);
rb_ary_modify(ary);
for (i = 0; i < RARRAY(ary)->len; i++) {
rb_ary_store(ary, i, rb_yield(RARRAY(ary)->ptr[i]));
@@ -1818,6 +1945,7 @@ rb_ary_select(ary)
VALUE result;
long i;
+ 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]))) {
@@ -1957,22 +2085,42 @@ rb_ary_slice_bang(argc, argv, ary)
VALUE ary;
{
VALUE arg1, arg2;
- long pos, len;
+ long pos, len, orig_len;
+ 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;
}
- arg2 = rb_ary_subseq(ary, pos, len);
- rb_ary_splice(ary, pos, len, Qnil); /* Qnil/rb_ary_new2(0) */
+ else if (orig_len < pos) return Qnil;
+ if (orig_len < pos + len) {
+ len = orig_len - pos;
+ }
+ 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));
@@ -1994,6 +2142,7 @@ rb_ary_reject_bang(ary)
{
long i1, i2;
+ RETURN_ENUMERATOR(ary, 0, 0);
rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
VALUE v = RARRAY(ary)->ptr[i1];
@@ -2022,6 +2171,7 @@ 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;
@@ -2042,6 +2192,7 @@ static VALUE
rb_ary_delete_if(ary)
VALUE ary;
{
+ RETURN_ENUMERATOR(ary, 0, 0);
rb_ary_reject_bang(ary);
return ary;
}
@@ -2265,10 +2416,13 @@ rb_ary_fill(argc, argv, ary)
break;
}
rb_ary_modify(ary);
- end = beg + len;
- if (end < 0) {
+ 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);
@@ -2378,7 +2532,7 @@ rb_ary_times(ary, times)
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;
@@ -2422,9 +2576,8 @@ rb_ary_assoc(ary, key)
VALUE v;
for (i = 0; i < RARRAY(ary)->len; ++i) {
- v = RARRAY(ary)->ptr[i];
- if (TYPE(v) == T_ARRAY &&
- RARRAY(v)->len > 0 &&
+ 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;
}
@@ -2462,6 +2615,22 @@ rb_ary_rassoc(ary, value)
return Qnil;
}
+static VALUE recursive_equal _((VALUE, VALUE, int));
+static VALUE
+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
@@ -2480,8 +2649,6 @@ static VALUE
rb_ary_equal(ary1, ary2)
VALUE ary1, ary2;
{
- long i;
-
if (ary1 == ary2) return Qtrue;
if (TYPE(ary2) != T_ARRAY) {
if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
@@ -2490,8 +2657,20 @@ 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(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
+ if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
return Qfalse;
}
return Qtrue;
@@ -2509,33 +2688,26 @@ 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(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
- return Qfalse;
- }
- return Qtrue;
+ return rb_exec_recursive(recursive_eql, ary1, ary2);
}
-/*
- * 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 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);
@@ -2547,6 +2719,21 @@ rb_ary_hash(ary)
/*
* 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
@@ -2574,6 +2761,29 @@ rb_ary_includes(ary, item)
}
+static VALUE recursive_cmp _((VALUE, VALUE, int));
+static VALUE
+recursive_cmp(ary1, ary2, recur)
+ VALUE ary1;
+ VALUE ary2;
+ int recur;
+{
+ long i, len;
+
+ 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(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
@@ -2598,19 +2808,13 @@ VALUE
rb_ary_cmp(ary1, ary2)
VALUE ary1, ary2;
{
- long i, len;
+ long len;
+ VALUE v;
ary2 = to_ary(ary2);
- len = RARRAY(ary1)->len;
- if (len > RARRAY(ary2)->len) {
- len = RARRAY(ary2)->len;
- }
- for (i=0; i<len; i++) {
- VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
- if (v != INT2FIX(0)) {
- return v;
- }
- }
+ 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);
@@ -2850,6 +3054,7 @@ rb_ary_compact(ary)
* array.nitems -> int
*
* Returns the number of non-<code>nil</code> elements in _self_.
+ *
* May be zero.
*
* [ 1, nil, 3, nil, 5 ].nitems #=> 3
@@ -2862,111 +3067,692 @@ 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_splice(ary, idx, 1, ary2);
- while (i < lim) {
- VALUE tmp;
+ else {
+ VALUE obj, *p, *pend;
- tmp = rb_check_array_type(rb_ary_elt(ary, i));
- if (!NIL_P(tmp)) {
- n = flatten(ary, i, tmp, memo);
- i += n; lim += n;
+ 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++;
+ }
+ }
+
+ return LONG2NUM(n);
+}
+
+static VALUE
+flatten(ary, level, modified)
+ VALUE ary;
+ int level;
+ int *modified;
+{
+ long i = 0;
+ 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;
}
- i++;
+ id = (st_data_t)ary;
+ st_delete(memo, &id, 0);
+ tmp = rb_ary_pop(stack);
+ i = NUM2LONG(tmp);
+ ary = rb_ary_pop(stack);
}
- rb_ary_pop(memo);
- return lim - idx - 1; /* returns number of increased items */
+ 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.)
+ * <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(ary)
+rb_ary_flatten_bang(argc, argv, ary)
+ int argc;
+ VALUE *argv;
VALUE ary;
{
- long i = 0;
- int mod = 0;
- VALUE memo = Qnil;
+ int mod = 0, level = -1;
+ VALUE result, lv;
- while (i<RARRAY(ary)->len) {
- VALUE ary2 = RARRAY(ary)->ptr[i];
- VALUE tmp;
+ rb_scan_args(argc, argv, "01", &lv);
+ if (!NIL_P(lv)) level = NUM2INT(lv);
+ if (level == 0) return ary;
- tmp = rb_check_array_type(ary2);
- if (!NIL_P(tmp)) {
- if (NIL_P(memo)) {
- memo = rb_ary_new();
- }
- i += flatten(ary, i, tmp, memo);
- mod = 1;
- }
- i++;
- }
+ 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.
+ * 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.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(ary)
+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) {
+ 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;
+}
+
+
+/*
+ * 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_flatten_bang(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);
+ }
+ }
+ }
+}
+
+/*
+ * 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_combination(ary, num)
+ VALUE ary;
+ VALUE num;
+{
+ 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
@@ -3004,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);
@@ -3014,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);
@@ -3059,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 b5546104d0..713b5c69df 100644
--- a/bcc32/Makefile.sub
+++ b/bcc32/Makefile.sub
@@ -4,8 +4,12 @@ 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
@@ -137,7 +141,7 @@ STACK = 0x2000000
XCFLAGS = -DRUBY_EXPORT -I. -I$(srcdir) -I$(srcdir)/missing
-ARFLAGS = /a
+ARFLAGS = /a /p32
LD = ilink32 -q -Gn
LDSHARED = $(LD)
XLDFLAGS = -Tpe c0x32.obj
@@ -153,8 +157,8 @@ EXEEXT = .exe
PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
WPROGRAM=$(RUBYW_INSTALL_NAME)$(EXEEXT)
RUBYDEF = $(RUBY_SO_NAME).def
-MINIRUBY = .\miniruby$(EXEEXT) $(MINIRUBYOPT)
-RUNRUBY = .\ruby$(EXEEXT) "$(srcdir)/runruby.rb" --extout="$(EXTOUT)" --
+MINIRUBY = .\miniruby$(EXEEXT) -I$(srcdir)/lib $(MINIRUBYOPT)
+RUNRUBY = .\$(PROGRAM) "$(srcdir)/runruby.rb" --extout="$(EXTOUT)" --
ORGLIBPATH = $(LIB)
@@ -197,7 +201,13 @@ rubyw: $(WPROGRAM)
!include $(srcdir)/common.mk
-PHONY: Makefile
+$(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
@@ -253,6 +263,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/bcc32/Makefile.sub
\#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
@@ -272,6 +283,9 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/bcc32/Makefile.sub
\#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
@@ -280,9 +294,12 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/bcc32/Makefile.sub
\#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 RUBY_VENDOR_ARCHLIB "/lib/ruby/vendor_ruby/$(MAJOR).$(MINOR)/$(ARCH)-$(OS)"
|
@exit > $@
@@ -336,7 +353,7 @@ 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
@@ -395,6 +412,7 @@ 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
@@ -449,14 +467,46 @@ post-install-doc::
@$(NULLCMD)
clean-local::
- @$(RM) ext\extinit.c ext\extinit.$(OBJEXT) *.tds *.il? $(RUBY_SO_NAME).lib
+ @$(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) *.map *.pdb *.ilk *.exp $(RUBYDEF)
@$(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
diff --git a/bcc32/configure.bat b/bcc32/configure.bat
index 143ad947f0..95575cbc60 100755
--- a/bcc32/configure.bat
+++ b/bcc32/configure.bat
@@ -6,70 +6,110 @@
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 \
+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
if "%1" == "--with-static-linked-ext" goto :extstatic
if "%1" == "--program-suffix" goto :suffix
-if "%1" == "--program-name" goto :progname
+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>> ~tmp~.mak "%1" \
+ echo>>confargs.tmp %1 \
shift
goto :loop
:srcdir
- echo>> ~tmp~.mak -D"srcdir=%2" \
+ echo>> ~tmp~.mak -Dsrcdir=%2 \
+ echo>>confargs.tmp --srcdir=%2 \
shift
shift
goto :loop
:prefix
- echo>> ~tmp~.mak -D"prefix=%2" \
+ echo>> ~tmp~.mak -Dprefix=%2 \
+ echo>>confargs.tmp %1=%2 \
shift
shift
goto :loop
:suffix
- echo>> ~tmp~.mak -D"RUBY_SUFFIX=%2" \
+ 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>> ~tmp~.mak -D"RUBY_INSTALL_NAME=%2" \
+ 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>> ~tmp~.mak -D"RUBY_SO_NAME=%2" \
+ 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>> ~tmp~.mak -D"EXTSTATIC=static" \
+ echo>>confargs.mk !ifndef EXTSTATIC
+ echo>>confargs.mk EXTSTATIC = static
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1 \
shift
goto :loop
:enable-rdoc
- echo>> ~tmp~.mak -D"RDOCTARGET=install-doc" \
+ 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>> ~tmp~.mak -D"RDOCTARGET=install-nodoc" \
+ echo>>confargs.mk !ifndef RDOCTARGET
+ echo>>confargs.mk RDOCTARGET = install-nodoc
+ echo>>confargs.mk !endif
+ echo>>confargs.tmp %1 \
shift
goto :loop
:extout
- echo>> ~tmp~.mak -D"EXTOUT=%2" \
+ 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
@@ -83,10 +123,30 @@ goto :loop
echo --target=TARGET configure for TARGET [i386-bccwin32]
echo Optional Package:
echo --with-static-linked-ext link external modules statically
- echo --enable-install-doc install rdoc indexes during install
+ echo --disable-install-doc install rdoc indexes during install
+ del *.tmp
del ~tmp~.mak
goto :exit
:end
-echo>> ~tmp~.mak -Dbcc32dir="$(@D)"
-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/setup.mak b/bcc32/setup.mak
index b7a2539d0a..483292ed51 100644
--- a/bcc32/setup.mak
+++ b/bcc32/setup.mak
@@ -30,7 +30,9 @@ 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) \#\#\#
@@ -40,36 +42,68 @@ $(BANG)endif
$(BANG)ifndef prefix
prefix = $(prefix:\=/)
$(BANG)endif
-$(BANG)ifndef EXTSTATIC
-EXTSTATIC = $(EXTSTATIC)
-$(BANG)endif
-!if defined(RDOCTARGET)
-$(BANG)ifndef RDOCTARGET
-RDOCTARGET = $(RDOCTARGET)
-$(BANG)endif
-!endif
-!if defined(EXTOUT)
-$(BANG)ifndef EXTOUT
-EXTOUT = $(EXTOUT)
-$(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;}
|
- @type > usebormm.bat &&|
-@echo off
-ilink32 -Gn -x usebormm.lib > nul
-if exist usebormm.tds echo MEMLIB = usebormm.lib
+ 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
|
- @usebormm.bat >> $(MAKEFILE)
- @del usebormm.*
+ @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)
@@ -84,7 +118,6 @@ $(BANG)ifndef PROCESSOR_LEVEL
PROCESSOR_LEVEL = $(PROCESSOR_LEVEL)
$(BANG)endif
!endif
-
|
!endif
@@ -117,8 +150,6 @@ $(BANG)endif
-epilogue-: nul
@type >> $(MAKEFILE) &&|
-\# OS = $(OS)
-\# RT = $(RT)
\# RUBY_INSTALL_NAME = ruby
\# RUBY_SO_NAME = $$(RT)-$$(RUBY_INSTALL_NAME)$$(MAJOR)$$(MINOR)
\# CFLAGS = -q $$(DEBUGFLAGS) $$(OPTFLAGS) $$(PROCESSOR_FLAG) -w- -wsus -wcpt -wdup -wext -wrng -wrpt -wzdi
@@ -129,5 +160,4 @@ $(BANG)endif
\# EXTLIBS = cw32.lib import32.lib user32.lib kernel32.lib
$(BANG)include $$(srcdir)/bcc32/Makefile.sub
|
- @$(srcdir:/=\)\win32\rm.bat config.h config.status
@echo type "`$(MAKE)'" to make ruby for $(OS).
diff --git a/bignum.c b/bignum.c
index 9a5b3c154a..7f14aee709 100644
--- a/bignum.c
+++ b/bignum.c
@@ -11,8 +11,10 @@
**********************************************************************/
#include "ruby.h"
+#include "rubysig.h"
#include <math.h>
+#include <float.h>
#include <ctype.h>
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
@@ -36,7 +38,21 @@ 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)
@@ -110,7 +126,8 @@ bigtrunc(x)
}
static VALUE
-bigfixize(VALUE x)
+bigfixize(x)
+ VALUE x;
{
long len = RBIGNUM(x)->len;
BDIGIT *ds = BDIGITS(x);
@@ -133,7 +150,8 @@ bigfixize(VALUE x)
}
static VALUE
-bignorm(VALUE x)
+bignorm(x)
+ VALUE x;
{
if (!FIXNUM_P(x) && TYPE(x) == T_BIGNUM) {
x = bigfixize(bigtrunc(x));
@@ -445,7 +463,14 @@ rb_cstr_to_inum(str, base, badcheck)
break;
}
if (*str == '0') { /* squeeze preceeding 0s */
- while (*++str == '0');
+ 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;
@@ -488,10 +513,11 @@ rb_cstr_to_inum(str, base, badcheck)
for (i=len;i--;) zds[i]=0;
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 ((c = conv_digit(c)) < 0) {
@@ -553,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
@@ -615,7 +641,7 @@ rb_ll2inum(n)
}
#endif /* HAVE_LONG_LONG */
-
+
VALUE
rb_cstr2inum(str, base)
const char *str;
@@ -652,6 +678,9 @@ rb_big2str0(x, base, trim)
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;
@@ -692,6 +721,7 @@ rb_big2str0(x, base, trim)
s = RSTRING(ss)->ptr;
s[0] = RBIGNUM(x)->sign ? '+' : '-';
+ TRAP_BEG;
while (i && j > 1) {
long k = i;
BDIGIT_DBL num = 0;
@@ -721,6 +751,7 @@ rb_big2str0(x, base, trim)
RSTRING(ss)->len = i;
}
s[RSTRING(ss)->len] = '\0';
+ TRAP_END;
return ss;
}
@@ -734,10 +765,10 @@ rb_big2str(VALUE x, int base)
/*
* 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"
@@ -781,15 +812,15 @@ big2ulong(x, type)
}
unsigned long
-rb_big2ulong_pack(x)
- VALUE x;
-{
+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)
@@ -907,8 +938,8 @@ rb_dbl2big(d)
return bignorm(dbl2big(d));
}
-double
-rb_big2dbl(x)
+static double
+big2dbl(x)
VALUE x;
{
double d = 0.0;
@@ -918,21 +949,30 @@ 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
@@ -945,11 +985,11 @@ rb_big_to_f(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
@@ -990,11 +1030,11 @@ rb_big_cmp(x, y)
/*
* 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
*/
@@ -1029,11 +1069,11 @@ rb_big_eq(x, y)
/*
* 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
*/
@@ -1074,7 +1114,7 @@ rb_big_uminus(x)
* 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"
*/
@@ -1105,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 */
@@ -1126,11 +1166,11 @@ bigsub(x, y)
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);
@@ -1140,7 +1180,7 @@ bigsub(x, y)
zds[i] = BDIGITS(x)[i];
i++;
}
-
+
return z;
}
@@ -1271,7 +1311,7 @@ rb_big_mul0(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++) {
@@ -1348,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++;
}
@@ -1472,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);
}
@@ -1517,9 +1554,9 @@ rb_big_modulo(x, y)
/*
* 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
*/
@@ -1545,6 +1582,27 @@ 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));
@@ -1562,9 +1620,9 @@ static VALUE big_shift(x, n)
/*
* call-seq:
* big.divmod(numeric) => array
- *
+ *
* See <code>Numeric#divmod</code>.
- *
+ *
*/
VALUE
rb_big_divmod(x, y)
@@ -1591,22 +1649,51 @@ rb_big_divmod(x, y)
/*
* 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);
@@ -1626,6 +1713,52 @@ 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
@@ -1645,7 +1778,7 @@ rb_big_pow(x, y)
{
double d;
long yy;
-
+
if (y == INT2FIX(0)) return INT2FIX(1);
switch (TYPE(y)) {
case T_FLOAT:
@@ -1660,7 +1793,8 @@ rb_big_pow(x, y)
case T_FIXNUM:
yy = FIX2LONG(y);
if (yy > 0) {
- VALUE z = x;
+ VALUE z = 0;
+ long mask;
const long BIGLEN_LIMIT = 1024*1024 / SIZEOF_BDIGITS;
if ((RBIGNUM(x)->len > BIGLEN_LIMIT) ||
@@ -1669,16 +1803,11 @@ rb_big_pow(x, y)
d = (double)yy;
break;
}
- for (;;) {
- yy -= 1;
- if (yy == 0) break;
- while (yy % 2 == 0) {
- yy /= 2;
- x = rb_big_mul0(x, x);
- bigtrunc(x);
+ 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_mul0(z, x);
- bigtrunc(z);
}
return bignorm(z);
}
@@ -1903,7 +2032,7 @@ rb_big_lshift(x, y)
if (!NIL_P(t)) return t;
neg = 1;
}
- shift = big2ulong(y, "long", Qtrue);
+ shift = big2ulong(y, "long");
break;
}
y = rb_to_int(y);
@@ -1972,7 +2101,7 @@ rb_big_rshift(x, y)
else {
neg = 1;
}
- shift = big2ulong(y, "long", Qtrue);
+ shift = big2ulong(y, "long");
break;
}
y = rb_to_int(y);
@@ -2030,20 +2159,20 @@ big_rshift(x, shift)
/*
* 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
@@ -2062,7 +2191,7 @@ rb_big_aref(x, y)
out_of_range:
return RBIGNUM(x)->sign ? INT2FIX(0) : INT2FIX(1);
}
- shift = big2ulong(y, "long", Qfalse);
+ shift = big2ulong(y, "long");
}
else {
i = NUM2LONG(y);
@@ -2134,9 +2263,9 @@ rb_big_coerce(x, y)
/*
* call-seq:
* big.abs -> aBignum
- *
+ *
* Returns the absolute value of <i>big</i>.
- *
+ *
* -1234567890987654321.abs #=> 1234567890987654321
*/
@@ -2164,7 +2293,7 @@ rb_big_rand(max, rand_buf)
}
v = bignew(len,1);
len--;
- BDIGITS(v)[len] = BDIGITS(max)[len] * rand_buf[len];
+ BDIGITS(v)[len] = BDIGITS(max)[len] * rand_buf[len];
while (len--) {
BDIGITS(v)[len] = ((BDIGIT)~0) * rand_buf[len];
}
@@ -2175,10 +2304,10 @@ rb_big_rand(max, rand_buf)
/*
* 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
@@ -2198,15 +2327,15 @@ rb_big_size(big)
* 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
@@ -2227,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/class.c b/class.c
index 80dc9e4b2d..096c7fbdf1 100644
--- a/class.c
+++ b/class.c
@@ -48,13 +48,23 @@ 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) {
+ fbody = rb_copy_node_scope(fbody, ruby_cref);
+ }
+ st_insert(data->tbl, mid, (st_data_t)NEW_METHOD(fbody, body->nd_noex));
return ST_CONTINUE;
}
@@ -65,7 +75,8 @@ rb_mod_init_copy(clone, orig)
{
rb_obj_init_copy(clone, orig);
if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
- RBASIC(clone)->klass = rb_singleton_class_clone(orig);
+ 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) {
@@ -78,9 +89,12 @@ 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;
@@ -126,9 +140,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;
diff --git a/common.mk b/common.mk
index f751fecfb5..bf49aade4a 100644
--- a/common.mk
+++ b/common.mk
@@ -2,7 +2,12 @@ bin: $(PROGRAM) $(WPROGRAM)
lib: $(LIBRUBY)
dll: $(LIBRUBY_SO)
-RUBYOPT =
+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
@@ -23,6 +28,7 @@ OBJS = array.$(OBJEXT) \
dir.$(OBJEXT) \
dln.$(OBJEXT) \
enum.$(OBJEXT) \
+ enumerator.$(OBJEXT) \
error.$(OBJEXT) \
eval.$(OBJEXT) \
file.$(OBJEXT) \
@@ -56,11 +62,15 @@ OBJS = array.$(OBJEXT) \
SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \
--extout="$(EXTOUT)" \
- --make="$(MAKE)" \
--mflags="$(MFLAGS)" \
--make-flags="$(MAKEFLAGS)"
EXTMK_ARGS = $(SCRIPT_ARGS) --extension $(EXTS) --extstatic $(EXTSTATIC) --
-INSTRUBY_ARGS = $(SCRIPT_ARGS) --installed-list $(INSTALLED_LIST)
+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)
@@ -69,7 +79,7 @@ TESTSDIR = $(srcdir)/test
TESTWORKDIR = testwork
all: $(MKFILES) $(PREP) $(RBCONFIG) $(LIBRUBY)
- @$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS)
+ @$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS)
prog: $(PROGRAM) $(WPROGRAM)
miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) $(MINIOBJS) $(OBJS) $(DMYEXT)
@@ -96,65 +106,68 @@ 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 $(INSTRUBY_ARGS) --mantype="$(MANTYPE)"
+ $(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 $(INSTRUBY_ARGS) --install=local --mantype="$(MANTYPE)"
+ $(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 $(INSTRUBY_ARGS) --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 $(INSTRUBY_ARGS) --install=bin --install=ext-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 $(INSTRUBY_ARGS) --install=lib --install=ext-comm --install=man
+ $(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 $(INSTRUBY_ARGS) --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 $(INSTRUBY_ARGS) --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 $(INSTRUBY_ARGS) --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 $(INSTRUBY_ARGS) --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 $(INSTRUBY_ARGS) --install=man --mantype="$(MANTYPE)"
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=man --mantype="$(MANTYPE)"
post-install-man::
@$(NULLCMD)
@@ -167,42 +180,42 @@ 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 $(INSTRUBY_ARGS) --mantype="$(MANTYPE)"
+ $(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 $(INSTRUBY_ARGS) --install=local --mantype="$(MANTYPE)"
+ $(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 $(INSTRUBY_ARGS) --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 $(INSTRUBY_ARGS) --install=bin --install=ext-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 $(INSTRUBY_ARGS) --install=lib --install=ext-comm --install=man
+ $(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 $(INSTRUBY_ARGS) --install=bin
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=bin
post-no-install-bin::
@$(NULLCMD)
@@ -210,7 +223,7 @@ 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 $(INSTRUBY_ARGS) --install=lib
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=lib
post-no-install-lib::
@$(NULLCMD)
@@ -218,7 +231,7 @@ 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 $(INSTRUBY_ARGS) --install=ext-comm
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext-comm
post-no-install-ext-comm::
@$(NULLCMD)
@@ -226,7 +239,7 @@ 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 $(INSTRUBY_ARGS) --install=ext-arch
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=ext-arch
post-no-install-ext-arch::
@$(NULLCMD)
@@ -234,14 +247,14 @@ 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 $(INSTRUBY_ARGS) --install=man --mantype="$(MANTYPE)"
+ $(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 $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)"
+ $(MINIRUBY) $(srcdir)/instruby.rb --make="$(MAKE)" $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)"
post-install-doc::
@$(NULLCMD)
@@ -253,30 +266,38 @@ 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 $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)"
+ $(MINIRUBY) $(srcdir)/instruby.rb -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=rdoc --rdoc-output="$(RDOCOUT)"
post-no-install-doc::
@$(NULLCMD)
-install-prereq:
+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) $(MAINOBJ) $(WINMAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES)
+ @$(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 $(EXTMK_ARGS) clean
+ @-$(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 y.tab.c y.output $(PREP)
+ @$(RM) *~ *.bak *.stackdump core *.core gmon.out $(PREP)
distclean-ext:
- @-$(MINIRUBY) $(srcdir)/ext/extmk.rb $(EXTMK_ARGS) distclean
+ @-$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS) distclean
-realclean:: 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
@@ -287,7 +308,7 @@ test-all:
$(RUNRUBY) "$(srcdir)/test/runner.rb" --basedir="$(TESTSDIR)" --runner=$(TESTUI) $(TESTS)
extconf:
- $(MINIRUBY) -I$(srcdir)/lib -run -e mkdir -- -p "$(EXTCONFDIR)"
+ $(MINIRUBY) -run -e mkdir -- -p "$(EXTCONFDIR)"
$(RUNRUBY) -C "$(EXTCONFDIR)" $(EXTCONF) $(EXTCONFARGS)
$(RBCONFIG): $(srcdir)/mkconfig.rb config.status $(PREP)
@@ -341,7 +362,8 @@ 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)}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
@@ -353,13 +375,13 @@ dir.$(OBJEXT): {$(VPATH)}dir.c {$(VPATH)}ruby.h config.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 {$(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
diff --git a/configure.in b/configure.in
index 8621cef90a..5633bc3c44 100644
--- a/configure.in
+++ b/configure.in
@@ -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)
@@ -75,6 +85,7 @@ 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
@@ -128,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;;
@@ -370,7 +382,22 @@ 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
@@ -422,6 +449,8 @@ msdosdjgpp*) LIBS="-lm $LIBS"
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],
@@ -472,6 +501,7 @@ 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
@@ -530,19 +560,90 @@ esac
AC_FUNC_MEMCMP
AC_FUNC_FSEEKO
AC_CHECK_FUNCS(ftello)
+
+# 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_broken_glibc_ia64_erfc,
+ [AC_TRY_RUN([
+#include <math.h>
+int
+main()
+{
+ erfc(10000.0);
+ return 0;
+}
+],
+ rb_broken_glibc_ia64_erfc=no,
+ rb_broken_glibc_ia64_erfc=yes,
+ rb_broken_glibc_ia64_erfc=no)])
+case $rb_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\
isnan finite isinf hypot acosh erf)
AC_CHECK_FUNCS(fmod killpg wait4 waitpid syscall chroot fsync getcwd eaccess\
- truncate chsize times utimes fcntl lockf lstat symlink link\
+ 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 _setjmp setsid telldir seekdir fchmod\
+ 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])
@@ -571,15 +672,23 @@ 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([#define _XOPEN_SOURCE 1
- $2
- const volatile void *volatile t;],
+ 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([#define _XOPEN_SOURCE 1
- $2
- extern $t $1;
- const volatile void *volatile t;],
+ 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])])
@@ -587,13 +696,13 @@ 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])
+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
+ 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>],
+ [AC_TRY_COMPILE([@%:@include <time.h>],
[(void)timezone(0, 0);],
[rb_cv_func_timezone_void=no],
[rb_cv_func_timezone_void=yes])]
@@ -645,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>
@@ -667,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
@@ -1003,7 +1113,7 @@ AC_SUBST(DLEXT2)dnl
AC_SUBST(LIBEXT)dnl
STATIC=
-: ${LIBPATHFLAG=' -L"%s"'}
+: ${LIBPATHFLAG=' -L%s'}
: ${PATHFLAG=''}
if test "$with_dln_a_out" != yes; then
@@ -1028,11 +1138,23 @@ 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) -shared'}
@@ -1067,7 +1189,7 @@ if test "$with_dln_a_out" != yes; then
rb_cv_dlopen=yes ;;
interix*) : ${LDSHARED="$CC -shared"}
XLDFLAGS="$XLDFLAGS -Wl,-E"
- LIBPATHFLAG=" -L'%1\$-s'"
+ LIBPATHFLAG=" -L%1\$-s"
rb_cv_dlopen=yes ;;
freebsd*|dragonfly*) : ${LDSHARED="$CC -shared"}
if test "$rb_cv_binary_elf" = yes; then
@@ -1098,11 +1220,11 @@ if test "$with_dln_a_out" != yes; then
aix*) if test "$GCC" = yes; then
: ${LDSHARED='$(CC) -shared'}
else
- : ${LDSHARED='/usr/ccs/bin/ld'}
+ : ${LDSHARED='$(CC)'}
fi
- DLDFLAGS="${linker_flag}-G"' -eInit_$(TARGET)'
- LDFLAGS="${LDFLAGS} ${linker_flag}-brtl"
- XLDFLAGS="${linker_flag}-bE:ruby.imp"
+ 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)'
@@ -1142,14 +1264,6 @@ if test "$with_dln_a_out" != yes; then
*) : ${LDSHARED='ld'} ;;
esac
AC_MSG_RESULT($rb_cv_dlopen)
-
- 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
fi
AC_SUBST(LINK_SO)
AC_SUBST(LIBPATHFLAG)
@@ -1309,9 +1423,10 @@ if test x"$cross_compiling" = xyes; then
PREP=fake.rb
RUNRUBY='$(MINIRUBY) -I`cd $(srcdir)/lib; pwd`'
else
- MINIRUBY='./miniruby$(EXEEXT)'
+ 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) --'
+ RUNRUBY='$(MINIRUBY) $(srcdir)/runruby.rb --extout=$(EXTOUT)'
fi
AC_SUBST(MINIRUBY)
AC_SUBST(PREP)
@@ -1398,7 +1513,7 @@ if test "$enable_shared" = 'yes'; then
LIBRUBY_ALIASES='lib$(RUBY_SO_NAME).sl.$(MAJOR).$(MINOR) lib$(RUBY_SO_NAME).sl'
;;
aix*)
- LIBRUBY_DLDFLAGS="${linker_flag}-G ${linker_flag}-bnoentry $XLDFLAGS"
+ LIBRUBY_DLDFLAGS="${linker_flag}-bnoentry $XLDFLAGS"
LIBRUBYARG_SHARED='-L${libdir} -l${RUBY_SO_NAME}'
SOLIBS='-lm -lc'
;;
@@ -1542,6 +1657,12 @@ case "$build_os" 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)
@@ -1586,37 +1707,53 @@ case "$target_os" in
rubyw_install_name="$RUBYW_INSTALL_NAME"
;;
esac
-case "$target_os" in
- cygwin*|mingw*|*djgpp*|os2-emx*)
- RUBY_LIB_PREFIX="/lib/ruby"
- ;;
- *)
- RUBY_LIB_PREFIX="${prefix}/lib/ruby"
- ;;
-esac
-RUBY_LIB_PATH="${RUBY_LIB_PREFIX}/${MAJOR}.${MINOR}"
+RUBY_LIB_PREFIX=`eval echo \\"${libdir}/ruby\\"`
AC_ARG_WITH(sitedir,
- [ --with-sitedir=DIR site libraries in DIR [PREFIX/lib/ruby/site_ruby]],
+ [ --with-sitedir=DIR site libraries in DIR [[LIBDIR/ruby/site_ruby]]],
[sitedir=$withval],
- [sitedir='${prefix}/lib/ruby/site_ruby'])
+ [sitedir='${libdir}/ruby/site_ruby'])
SITE_DIR=`eval echo \\"${sitedir}\\"`
+
case "$target_os" in
cygwin*|mingw*|*djgpp*|os2-emx*)
- RUBY_SITE_LIB_PATH="`expr "$SITE_DIR" : "$prefix\(/.*\)"`" ||
- RUBY_SITE_LIB_PATH="$SITE_DIR";;
+ 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_SITE_LIB_PATH="$SITE_DIR";;
+ 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_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_VENDOR_LIB_PATH="`eval echo "$VENDOR_DIR" | sed 's|^NONE/|/|;s|^'"$prefix"'/|/|'`"
+ ;;
+ *)
+ RUBY_VENDOR_LIB_PATH="`eval echo \\"$VENDOR_DIR\\" | sed 's|^NONE/|'"$prefix"'/|'`"
+ ;;
+esac
+RUBY_VENDOR_LIB_PATH2="${RUBY_VENDOR_LIB_PATH}/${MAJOR}.${MINOR}"
+
+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
@@ -1629,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}"
@@ -1636,12 +1775,13 @@ else
fi
case "$target_os" in
- mingw*) sitearch="i386-$rb_cv_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],
@@ -1679,6 +1819,7 @@ else
tr -d '\015' < confdefs.h > config.h
fi
tr -d '\015' < largefile.h > confdefs.h
+rm largefile.h
AC_CONFIG_FILES($FIRSTMAKEFILE)
AC_CONFIG_FILES(Makefile, [{
diff --git a/defines.h b/defines.h
index 6b1fd68740..f39097fea4 100644
--- a/defines.h
+++ b/defines.h
@@ -102,6 +102,16 @@ 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__
/* NextStep, OpenStep, Rhapsody */
#ifndef S_IRUSR
@@ -155,13 +165,6 @@ void xfree _((void*));
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & (0170000)) == (0100000))
#endif
-/* 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
#ifndef __APPLE__
/* NextStep, OpenStep (but not Rhapsody) */
#ifndef GETPGRP_VOID
@@ -251,6 +254,14 @@ void rb_ia64_flushrs(void);
#define ENV_IGNORECASE
#endif
+#ifndef CASEFOLD_FILESYSTEM
+# if defined DOSISH || defined __VMS
+# define CASEFOLD_FILESYSTEM 1
+# else
+# define CASEFOLD_FILESYSTEM 0
+# endif
+#endif
+
#ifndef DLEXT_MAXLEN
#define DLEXT_MAXLEN 4
#endif
diff --git a/dir.c b/dir.c
index 0dd12ffd7d..c2c3f9452f 100644
--- a/dir.c
+++ b/dir.c
@@ -268,7 +268,7 @@ fnmatch_helper(pcur, scur, flags)
const char *t;
if (ISEND(s))
RETURN(FNM_NOMATCH);
- if (t = bracket(p + 1, s, flags)) {
+ if ((t = bracket(p + 1, s, flags)) != 0) {
p = t;
Inc(s);
continue;
@@ -473,9 +473,9 @@ dir_inspect(dir)
{
struct dir_data *dirp;
- GetDIR(dir, dirp);
+ Data_Get_Struct(dir, struct dir_data, dirp);
if (dirp->path) {
- char *c = rb_obj_classname(dir);
+ 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);
@@ -499,7 +499,7 @@ dir_path(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);
}
@@ -562,6 +562,7 @@ 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)) {
@@ -1008,7 +1009,7 @@ has_magic(s, flags)
register const char *p = s;
register char c;
- while (c = *p++) {
+ while ((c = *p++) != 0) {
switch (c) {
case '*':
case '?':
@@ -1041,7 +1042,7 @@ find_dirsep(const char *s, int flags)
register char c;
int open = 0;
- while (c = *p++) {
+ while ((c = *p++) != 0) {
switch (c) {
case '[':
open = 1;
@@ -1814,6 +1815,7 @@ dir_foreach(io, dirname)
{
VALUE dir;
+ RETURN_ENUMERATOR(io, 1, &dirname);
dir = dir_open_dir(dirname);
rb_ensure(dir_each, dir, dir_close, dir);
return Qnil;
@@ -1970,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);
diff --git a/dln.c b/dln.c
index 9fd605e32e..5ba25b6415 100644
--- a/dln.c
+++ b/dln.c
@@ -81,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
#ifndef NO_DLN_LOAD
-#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(_AIX) && !defined(__APPLE__) && !defined(_UNICOSMP)
+#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"
@@ -636,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;
@@ -1141,7 +1150,7 @@ dln_sym(name)
#endif
#endif
#else
-#ifdef __APPLE__
+#ifdef MACOSX_DYLD
#include <mach-o/dyld.h>
#endif
#endif
@@ -1403,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
@@ -1527,7 +1536,7 @@ dln_load(file)
}
#endif /* __BEOS__*/
-#ifdef __MACOS__
+#ifdef __MACOS__ /* Mac OS 9 or before */
# define DLN_DEFINED
{
OSErr err;
@@ -1680,31 +1689,31 @@ 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) {
@@ -1772,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)
@@ -1804,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);
@@ -1825,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') {
diff --git a/enum.c b/enum.c
index 2a29272ae9..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)
@@ -48,18 +84,18 @@ grep_iter_i(i, arg)
* 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
@@ -73,10 +109,99 @@ 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;
@@ -93,15 +218,15 @@ find_i(i, memo)
* 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
@@ -114,6 +239,7 @@ enum_find(argc, argv, obj)
VALUE if_none;
rb_scan_args(argc, argv, "01", &if_none);
+ RETURN_ENUMERATOR(obj, argc, argv);
rb_iterate(rb_each, obj, find_i, (VALUE)&memo);
if (memo != Qundef) {
return memo;
@@ -124,6 +250,81 @@ enum_find(argc, argv, obj)
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;
@@ -138,13 +339,13 @@ find_all_i(i, ary)
* 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
@@ -152,7 +353,8 @@ 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;
@@ -171,12 +373,12 @@ reject_i(i, ary)
/*
* 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
@@ -184,7 +386,8 @@ 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;
@@ -212,13 +415,13 @@ collect_all(i, ary)
* 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
@@ -236,80 +439,135 @@ enum_collect(obj)
* 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;
- VALUE *memo;
+ VALUE p;
{
- if (*memo == Qundef) {
- *memo = i;
+ VALUE *memo = (VALUE *)p;
+ if (memo[0] == Qundef) {
+ memo[0] = i;
+ }
+ else {
+ memo[0] = rb_yield_values(2, memo[0], i);
+ }
+ return Qnil;
+}
+
+static VALUE inject_op_i _((VALUE, VALUE));
+static VALUE
+inject_op_i(i, p)
+ VALUE i;
+ VALUE p;
+{
+ VALUE *memo = (VALUE *)p;
+
+ if (memo[0] == Qundef) {
+ memo[0] = i;
}
else {
- *memo = rb_yield_values(2, *memo, i);
+ 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
- *
- * Combines the elements of <i>enum</i> by applying the block to an
- * accumulator value (<i>memo</i>) and each element in turn. At each
- * step, <i>memo</i> is set to the value returned by the block. The
- * first form lets you supply an initial value for <i>memo</i>. The
- * second form uses the first element of the collection as a the
- * initial value (and skips that element while iterating).
- *
+ *
+ * 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).inject {|sum, n| sum + n } #=> 45
+ * (5..10).reduce(:+) #=> 45
+ * # Same using a block and inject
+ * (5..10).inject {|sum, n| sum + n } #=> 45
* # Multiply some numbers
- * (5..10).inject(1) {|product, n| product * n } #=> 151200
- *
+ * (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"
- *
- * # find the length of the longest word
- * longest = %w{ cat sheep bear }.inject(0) do |memo,word|
- * memo >= word.length ? memo : word.length
- * end
- * longest #=> 5
- *
+ * longest #=> "sheep"
+ *
*/
-
static VALUE
enum_inject(argc, argv, obj)
int argc;
- VALUE *argv, obj;
+ VALUE *argv;
+ VALUE obj;
{
- VALUE memo = Qundef;
-
- if (rb_scan_args(argc, argv, "01", &memo) == 0)
- memo = Qundef;
- rb_iterate(rb_each, obj, inject_i, (VALUE)&memo);
- if (memo == Qundef) return Qnil;
- return memo;
+ 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_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
+ if (memo[0] == Qundef) return Qnil;
+ return memo[0];
}
static VALUE
@@ -328,13 +586,13 @@ partition_i(i, ary)
/*
* 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
@@ -343,6 +601,8 @@ enum_partition(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);
@@ -350,11 +610,111 @@ enum_partition(obj)
return rb_assoc_new(ary[0], ary[1]);
}
+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
@@ -362,7 +722,7 @@ enum_partition(obj)
* 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]
*/
@@ -371,7 +731,7 @@ 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
@@ -391,65 +751,70 @@ sort_by_i(i, ary)
}
static int
-sort_by_cmp(aa, bb)
+sort_by_cmp(aa, bb, data)
NODE **aa, **bb;
+ void *data;
{
VALUE a = aa[0]->u1.value;
VALUE b = bb[0]->u1.value;
+ VALUE ary = (VALUE)data;
+ 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
@@ -457,14 +822,14 @@ sort_by_cmp(aa, bb)
* 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"]
*/
@@ -476,6 +841,8 @@ 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);
}
@@ -485,7 +852,8 @@ enum_sort_by(obj)
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, 0);
+ 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");
@@ -498,11 +866,11 @@ enum_sort_by(obj)
}
static VALUE
-all_iter_i(i, memo)
+all_i(i, memo)
VALUE i;
VALUE *memo;
{
- if (!RTEST(rb_yield(i))) {
+ if (!RTEST(i)) {
*memo = Qfalse;
rb_iter_break();
}
@@ -510,32 +878,28 @@ all_iter_i(i, memo)
}
static VALUE
-all_i(i, memo)
+all_iter_i(i, memo)
VALUE i;
VALUE *memo;
{
- if (!RTEST(i)) {
- *memo = Qfalse;
- rb_iter_break();
- }
- return Qnil;
+ 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
@@ -549,11 +913,11 @@ enum_all(obj)
}
static VALUE
-any_iter_i(i, memo)
+any_i(i, memo)
VALUE i;
VALUE *memo;
{
- if (RTEST(rb_yield(i))) {
+ if (RTEST(i)) {
*memo = Qtrue;
rb_iter_break();
}
@@ -561,21 +925,17 @@ any_iter_i(i, memo)
}
static VALUE
-any_i(i, memo)
+any_iter_i(i, memo)
VALUE i;
VALUE *memo;
{
- if (RTEST(i)) {
- *memo = Qtrue;
- rb_iter_break();
- }
- return Qnil;
+ 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
@@ -583,11 +943,11 @@ any_i(i, memo)
* 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
@@ -601,6 +961,105 @@ enum_any(obj)
}
static VALUE
+one_i(i, memo)
+ VALUE i;
+ VALUE *memo;
+{
+ if (RTEST(i)) {
+ if (*memo == Qundef) {
+ *memo = Qtrue;
+ }
+ else if (*memo == Qtrue) {
+ *memo = Qfalse;
+ rb_iter_break();
+ }
+ }
+ return Qnil;
+}
+
+static VALUE
+one_iter_i(i, memo)
+ VALUE i;
+ 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 = Qfalse;
+ rb_iter_break();
+ }
+ return Qnil;
+}
+
+static VALUE
+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 = Qtrue;
+
+ 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;
VALUE *memo;
@@ -643,11 +1102,11 @@ min_ii(i, memo)
* 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"
@@ -668,11 +1127,11 @@ enum_min(obj)
* 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"
@@ -720,15 +1179,15 @@ max_ii(i, memo)
* 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)
@@ -742,6 +1201,240 @@ enum_max(obj)
}
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;
VALUE *memo;
@@ -757,13 +1450,13 @@ member_i(item, memo)
* 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
@@ -791,29 +1484,56 @@ each_with_index_i(val, memo)
/*
* 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;
{
- VALUE memo = 0;
+ VALUE memo;
- rb_need_block();
+ 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;
@@ -843,7 +1563,7 @@ zip_i(val, memo)
* 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
@@ -852,14 +1572,14 @@ zip_i(val, memo)
* <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
@@ -884,6 +1604,227 @@ enum_zip(argc, argv, obj)
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
@@ -900,32 +1841,51 @@ 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/error.c b/error.c
index 608d1fa558..a991f55e57 100644
--- a/error.c
+++ b/error.c
@@ -29,7 +29,7 @@
#define EXIT_SUCCESS 0
#endif
-extern const char ruby_version[], ruby_release_date[], ruby_platform[];
+extern const char *ruby_description;
int ruby_nerrs;
@@ -208,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();
}
@@ -258,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";
@@ -334,7 +333,7 @@ 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);
}
/*
@@ -499,7 +498,7 @@ 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);
@@ -728,7 +727,7 @@ name_err_mesg_to_str(obj)
mesg = ptr[0];
if (NIL_P(mesg)) return Qnil;
else {
- char *desc = 0;
+ const char *desc = 0;
VALUE d = 0, args[3];
obj = ptr[1];
@@ -882,7 +881,7 @@ syserr_initialize(argc, argv, self)
#if !defined(_WIN32) && !defined(__VMS)
char *strerror();
#endif
- char *err;
+ const char *err;
VALUE mesg, error;
VALUE klass = rb_obj_class(self);
@@ -952,18 +951,16 @@ 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))
diff --git a/eval.c b/eval.c
index 28384488ad..d2a2556494 100644
--- a/eval.c
+++ b/eval.c
@@ -72,6 +72,8 @@ char *strrchr _((const char*,const char));
#include <unistd.h>
#endif
+#include <time.h>
+
#ifdef __BEOS__
#include <net/socket.h>
#endif
@@ -193,14 +195,11 @@ static int volatile freebsd_clear_carry_flag = 0;
POST_GETCONTEXT, \
(j)->status)
#else
-# if !defined(setjmp) && defined(HAVE__SETJMP)
-# define ruby_setjmp(just_before_setjmp, env) \
- ((just_before_setjmp), _setjmp(env))
-# define ruby_longjmp(env,val) _longjmp(env,val)
-# else
-# define ruby_setjmp(just_before_setjmp, env) \
- ((just_before_setjmp), setjmp(env))
-# define ruby_longjmp(env,val) longjmp(env,val)
+# 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
@@ -470,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*
@@ -490,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;
@@ -558,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);
@@ -570,10 +570,11 @@ remove_method(klass, mid)
if (mid == __id__ || mid == __send__ || mid == init) {
rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
}
- if (st_lookup(RCLASS(klass)->m_tbl, mid, (st_data_t *)&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, (st_data_t *)&body);
+ st_delete(RCLASS(klass)->m_tbl, &mid, &data);
}
}
if (!body) {
@@ -759,7 +760,7 @@ 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; \
@@ -1028,7 +1029,7 @@ static struct tag *prot_tag;
#define PROT_LAMBDA INT2FIX(2) /* 5 */
#define PROT_YIELD INT2FIX(3) /* 7 */
-#define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, ruby_setjmp(((void)0), prot_tag->buf))
+#define EXEC_TAG() ruby_setjmp(((void)0), prot_tag->buf)
#define JUMP_TAG(st) do { \
ruby_frame = prot_tag->frame; \
@@ -1056,7 +1057,7 @@ 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; \
@@ -1104,8 +1105,8 @@ 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));
@@ -1114,6 +1115,7 @@ static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int));
#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,VALUE));
static VALUE module_setup _((VALUE,NODE*));
@@ -1227,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;
@@ -1288,7 +1290,7 @@ error_print()
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 */
}
@@ -1309,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
@@ -1319,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;
@@ -1440,9 +1443,6 @@ int ruby_in_eval;
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;
@@ -1461,8 +1461,10 @@ 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;
@@ -1515,7 +1517,7 @@ error_handle(ex)
rb_bug("Unknown longjmp status %d", ex);
break;
}
- thread_reset_raised();
+ rb_thread_reset_raised(th);
return status;
}
@@ -2031,7 +2033,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))
@@ -2069,7 +2071,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)) {
@@ -2160,9 +2162,10 @@ rb_alias(klass, name, def)
VALUE klass;
ID name, def;
{
- VALUE origin;
+ VALUE origin = 0;
NODE *orig, *body, *node;
VALUE singleton = 0;
+ st_data_t data;
rb_frozen_class_p(klass);
if (name == def) return;
@@ -2190,7 +2193,8 @@ rb_alias(klass, name, def)
}
rb_clear_cache_by_id(name);
- if (RTEST(ruby_verbose) && st_lookup(RCLASS(klass)->m_tbl, name, (st_data_t *)&node)) {
+ 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));
}
@@ -2239,8 +2243,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;
{
@@ -2319,9 +2323,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;
@@ -2348,7 +2352,7 @@ arg_defined(self, node, buf, type)
return type;
}
-static char*
+static const char*
is_defined(self, node, buf)
VALUE self;
NODE *node; /* OK */
@@ -2441,6 +2445,8 @@ 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:
@@ -2666,27 +2672,27 @@ set_trace_func(obj, trace)
return trace;
}
-static char *
+static const char *
get_event_name(rb_event_t event)
{
switch (event) {
- case RUBY_EVENT_LINE:
+ case RUBY_EVENT_LINE:
return "line";
- case RUBY_EVENT_CLASS:
+ case RUBY_EVENT_CLASS:
return "class";
- case RUBY_EVENT_END:
+ case RUBY_EVENT_END:
return "end";
- case RUBY_EVENT_CALL:
+ case RUBY_EVENT_CALL:
return "call";
- case RUBY_EVENT_RETURN:
+ case RUBY_EVENT_RETURN:
return "return";
- case RUBY_EVENT_C_CALL:
+ case RUBY_EVENT_C_CALL:
return "c-call";
- case RUBY_EVENT_C_RETURN:
+ case RUBY_EVENT_C_RETURN:
return "c-return";
- case RUBY_EVENT_RAISE:
+ case RUBY_EVENT_RAISE:
return "raise";
- default:
+ default:
return "unknown";
}
}
@@ -2703,7 +2709,8 @@ call_trace_func(event, node, self, id, klass)
struct FRAME *prev;
NODE *node_save;
VALUE srcfile;
- char *event_name;
+ const char *event_name;
+ rb_thread_t th = curr_thread;
if (!trace_func) return;
if (tracing) return;
@@ -2735,7 +2742,7 @@ call_trace_func(event, node, self, id, klass)
}
}
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)");
event_name = get_event_name(event);
@@ -2747,7 +2754,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();
@@ -2939,6 +2946,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); \
@@ -3038,13 +3046,16 @@ rb_eval(self, n)
RETURN(Qfalse);
case NODE_IF:
- EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
- ruby_frame->last_func,
- ruby_frame->last_class);
if (RTEST(rb_eval(self, node->nd_cond))) {
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
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;
@@ -3912,7 +3923,7 @@ rb_eval(self, n)
case NODE_DEFN:
if (node->nd_defn) {
NODE *body, *defn;
- VALUE origin;
+ VALUE origin = 0;
int noex;
if (NIL_P(ruby_class)) {
@@ -3946,7 +3957,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),
@@ -3974,7 +3985,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");
}
@@ -3982,7 +3994,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;
@@ -4126,7 +4138,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;
@@ -4223,7 +4235,7 @@ rb_obj_respond_to(obj, id, priv)
int n = 0;
args[n++] = ID2SYM(id);
if (priv) args[n++] = Qtrue;
- return rb_funcall2(obj, respond_to, n, args);
+ return RTEST(rb_funcall2(obj, respond_to, n, args));
}
}
@@ -4561,8 +4573,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);
}
@@ -4576,6 +4589,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);
}
}
@@ -4601,7 +4617,7 @@ rb_longjmp(tag, mesg)
ruby_errinfo = mesg;
}
else if (status) {
- thread_reset_raised();
+ rb_thread_reset_raised(th);
JUMP_TAG(status);
}
}
@@ -4616,11 +4632,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;
{
@@ -4637,7 +4662,8 @@ rb_exc_fatal(mesg)
void
rb_interrupt()
{
- rb_raise(rb_eInterrupt, "");
+ static const char fmt[1] = {'\0'};
+ rb_raise(rb_eInterrupt, fmt);
}
/*
@@ -4793,7 +4819,7 @@ proc_jump_error(state, result)
VALUE result;
{
char mesg[32];
- char *statement;
+ const char *statement;
switch (state) {
case TAG_BREAK:
@@ -4907,7 +4933,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;
@@ -4949,27 +4975,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 || */
+ 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, lambda);
+ massign(self, var, val, lambda);
}
else {
int len = 0;
@@ -4990,13 +5024,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, lambda);
+ 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();
@@ -5013,12 +5055,18 @@ rb_yield_0(val, self, klass, flags, avalue)
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 = 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);
}
@@ -5156,6 +5204,16 @@ rb_yield_splat(values)
return rb_yield_0(values, 0, 0, 0, avalue);
}
+static VALUE
+loop_i()
+{
+ for (;;) {
+ rb_yield_0(Qundef, 0, 0, 0, Qfalse);
+ CHECK_INTS;
+ }
+ return Qnil;
+}
+
/*
* call-seq:
* loop {|| block }
@@ -5168,15 +5226,14 @@ rb_yield_splat(values)
* break if !line or line =~ /^qQ/
* # ...
* end
+ *
+ * StopIteration raised in the block breaks the loop.
*/
static VALUE
rb_f_loop()
{
- for (;;) {
- rb_yield_0(Qundef, 0, 0, 0, Qfalse);
- CHECK_INTS;
- }
+ rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
return Qnil; /* dummy */
}
@@ -5421,7 +5478,7 @@ rb_rescue2(b_proc, data1, r_proc, data2, va_alist)
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;
@@ -5500,7 +5557,7 @@ rb_ensure(b_proc, data1, e_proc, data2)
POP_TAG();
retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */
if (!thread_no_ensure()) {
- (*e_proc)(data2);
+ (*e_proc)(data2);
}
if (prot_tag) return_value(retval);
if (state) JUMP_TAG(state);
@@ -5536,18 +5593,11 @@ rb_with_disable_interrupt(proc, data)
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);
}
}
@@ -5596,7 +5646,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])) {
@@ -5786,8 +5836,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
TMP_PROTECT;
volatile int safe = -1;
- if (NOEX_SAFE(flags) > ruby_safe_level &&
- ruby_safe_level == 0 && NOEX_SAFE(flags) > 2) {
+ if (NOEX_SAFE(flags) > ruby_safe_level && NOEX_SAFE(flags) > 2) {
rb_raise(rb_eSecurityError, "calling insecure method: %s",
rb_id2name(id));
}
@@ -5890,7 +5939,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
}
result = proc_invoke(body->nd_cval, rb_ary_new4(argc, argv), recv, klass);
if (event_hooks) {
- EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, body, recv, id, klass);
+ EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, ruby_current_node, recv, id, klass);
}
break;
@@ -6013,7 +6062,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, flags)
}
POP_TAG();
if (event_hooks) {
- EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, body, recv, id, klass);
+ EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, ruby_current_node, recv, id, klass);
}
POP_VARS();
POP_CLASS();
@@ -6397,10 +6446,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;
@@ -6420,7 +6475,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;
@@ -6539,12 +6594,12 @@ eval(self, src, scope, file, line)
errat = get_backtrace(ruby_errinfo);
mesg = rb_attr_get(ruby_errinfo, rb_intern("mesg"));
if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
- (bt2 = backtrace(-2), RARRAY(bt2)->len > 0)) {
+ (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(errat)->ptr[0]);
+ rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]);
}
- RARRAY(errat)->ptr[0] = RARRAY(bt2)->ptr[0];
+ RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0];
}
}
rb_exc_raise(ruby_errinfo);
@@ -6581,7 +6636,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);
@@ -6698,12 +6753,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
@@ -6716,10 +6787,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) {
@@ -6788,6 +6859,41 @@ rb_obj_instance_eval(argc, argv, 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
*
@@ -6819,6 +6925,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)));
@@ -7180,7 +7315,7 @@ search_required(fname, featurep, path)
#else
rb_str_cat2(tmp, DLEXT);
OBJ_FREEZE(tmp);
- if (*path = rb_find_file(tmp)) {
+ if ((*path = rb_find_file(tmp)) != 0) {
return 's';
}
#endif
@@ -7980,6 +8115,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()
{
@@ -8001,11 +8167,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);
@@ -8018,7 +8184,7 @@ Init_eval()
rb_define_method(rb_mKernel, "respond_to?", obj_respond_to, -1);
respond_to = rb_intern("respond_to?");
- rb_global_variable((VALUE*)&basic_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);
@@ -8036,9 +8202,12 @@ Init_eval()
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);
@@ -8054,7 +8223,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");
@@ -8343,20 +8514,42 @@ proc_clone(self)
* 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
@@ -8414,9 +8607,34 @@ rb_f_binding(self)
return bind;
}
-#define PROC_TSHIFT (FL_USHIFT+1)
-#define PROC_TMASK (FL_USER1|FL_USER2|FL_USER3)
-#define PROC_TMAX (PROC_TMASK >> PROC_TSHIFT)
+/*
+ * 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
@@ -8579,13 +8797,12 @@ proc_invoke(proc, args, self, klass)
volatile VALUE old_wrapper = ruby_wrapper;
volatile int pcall, avalue = Qtrue;
volatile VALUE tmp = args;
+ VALUE bvar = Qnil;
if (rb_block_given_p() && ruby_frame->last_func) {
if (klass != ruby_frame->last_class)
klass = rb_obj_class(proc);
- rb_warning("block for %s#%s is useless",
- rb_class2name(klass),
- rb_id2name(ruby_frame->last_func));
+ bvar = rb_block_proc();
}
Data_Get_Struct(proc, struct BLOCK, data);
@@ -8601,6 +8818,7 @@ proc_invoke(proc, args, self, klass)
/* 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;
@@ -8621,7 +8839,8 @@ proc_invoke(proc, args, self, klass)
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 (TAG_DST()) {
result = prot_tag->retval;
@@ -8690,8 +8909,8 @@ proc_invoke(proc, args, self, klass)
* from prog.rb:5
*/
-static VALUE
-proc_call(proc, args)
+VALUE
+rb_proc_call(proc, args)
VALUE proc, args; /* OK */
{
return proc_invoke(proc, args, Qundef, 0);
@@ -8725,30 +8944,36 @@ 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);
}
}
@@ -8796,7 +9021,7 @@ proc_to_s(self)
{
struct BLOCK *data;
NODE *node;
- char *cname = rb_obj_classname(self);
+ 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;
@@ -9010,6 +9235,7 @@ mnew(klass, obj, id, mklass)
(FL_TEST(rklass, FL_SINGLETON) || TYPE(rklass) == T_ICLASS)) {
rklass = RCLASS(rklass)->super;
}
+ if (TYPE(klass) == T_ICLASS) klass = RBASIC(klass)->klass;
method = Data_Make_Struct(mklass, struct METHOD, bm_mark, free, data);
data->klass = klass;
data->recv = obj;
@@ -9109,6 +9335,57 @@ method_unbind(obj)
/*
* 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
@@ -9135,7 +9412,7 @@ method_unbind(obj)
* m.call #=> "Hello, @iv = Fred"
*/
-static VALUE
+VALUE
rb_obj_method(obj, vid)
VALUE obj;
VALUE vid;
@@ -9202,6 +9479,29 @@ 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
@@ -9455,7 +9755,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("#<");
@@ -9484,12 +9784,8 @@ method_inspect(method)
else {
rb_str_buf_cat2(str, rb_class2name(data->rklass));
if (data->rklass != data->klass) {
- VALUE klass = data -> klass;
- if (TYPE(klass) == T_ICLASS) {
- klass = RBASIC(klass)->klass;
- }
rb_str_buf_cat2(str, "(");
- rb_str_buf_cat2(str, rb_class2name(klass));
+ rb_str_buf_cat2(str, rb_class2name(data->klass));
rb_str_buf_cat2(str, ")");
}
}
@@ -9538,7 +9834,8 @@ 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;
}
@@ -9697,12 +9994,17 @@ Init_Proc()
rb_define_method(rb_eLocalJumpError, "reason", localjump_reason, 0);
rb_global_variable(&exception_error);
- exception_error = rb_exc_new2(rb_eFatal, "exception reentered");
+ 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);
rb_global_variable(&sysstack_error);
- sysstack_error = rb_exc_new2(rb_eSysStackError, "stack level too deep");
+ 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);
@@ -9710,9 +10012,9 @@ Init_Proc()
rb_define_method(rb_cProc, "clone", proc_clone, 0);
rb_define_method(rb_cProc, "dup", proc_dup, 0);
- rb_define_method(rb_cProc, "call", proc_call, -2);
+ 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);
@@ -9732,6 +10034,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);
@@ -9743,6 +10048,8 @@ 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);
}
@@ -9790,6 +10097,7 @@ Init_Binding()
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);
}
@@ -9874,10 +10182,9 @@ extern VALUE rb_last_status;
# endif
#endif
-#define THREAD_RAISED 0x200 /* temporary flag */
#define THREAD_TERMINATING 0x400 /* persistent flag */
-#define THREAD_NO_ENSURE 0x800 /* persistent flag */
-#define THREAD_FLAGS_MASK 0xc00 /* 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)
@@ -9929,19 +10236,25 @@ 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;
}
@@ -10052,6 +10365,13 @@ 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;
}
@@ -10332,7 +10652,7 @@ rb_thread_switch(n)
}
#define THREAD_SAVE_CONTEXT(th) \
- (rb_thread_switch((FLUSH_REGISTER_WINDOWS, ruby_setjmp(rb_thread_save_context(th), (th)->context))))
+ (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,void*)));
@@ -10637,6 +10957,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;
@@ -11079,7 +11400,7 @@ 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);
@@ -11686,15 +12007,6 @@ rb_thread_abort_exc_set(thread, val)
}
-enum rb_thread_status
-rb_thread_status(thread)
- VALUE thread;
-{
- rb_thread_t th = rb_thread_check(thread);
- return th->status;
-}
-
-
/*
* call-seq:
* thr.group => thgrp or nil
@@ -11788,7 +12100,7 @@ rb_thread_alloc(klass)
return th;
}
-static int thread_init = 0;
+static int thread_init;
#if defined(_THREAD_SAFE)
static void
@@ -11801,19 +12113,12 @@ catch_timer(sig)
/* cause EINTR */
}
-static int time_thread_alive_p = 0;
static pthread_t time_thread;
static void*
thread_timer(dummy)
void *dummy;
{
-#ifdef _THREAD_SAFE
-#define test_cancel() pthread_testcancel()
-#else
-#define test_cancel() /* void */
-#endif
-
sigset_t all_signals;
sigfillset(&all_signals);
@@ -11823,14 +12128,11 @@ thread_timer(dummy)
#ifdef HAVE_NANOSLEEP
struct timespec req, rem;
- test_cancel();
req.tv_sec = 0;
req.tv_nsec = 10000000;
nanosleep(&req, &rem);
#else
struct timeval tv;
-
- test_cancel();
tv.tv_sec = 0;
tv.tv_usec = 10000;
select(0, NULL, NULL, NULL, &tv);
@@ -11842,7 +12144,6 @@ thread_timer(dummy)
}
}
}
-#undef test_cancel
}
void
@@ -11854,26 +12155,6 @@ void
rb_thread_stop_timer()
{
}
-
-void
-rb_child_atfork()
-{
- time_thread_alive_p = 0;
-}
-
-void
-rb_thread_cancel_timer()
-{
-#ifdef _THREAD_SAFE
- if( time_thread_alive_p )
- {
- pthread_cancel( time_thread );
- pthread_join( time_thread, NULL );
- time_thread_alive_p = 0;
- }
- thread_init = 0;
-#endif
-}
#elif defined(HAVE_SETITIMER)
static void
catch_timer(sig)
@@ -11911,19 +12192,8 @@ rb_thread_stop_timer()
tval.it_value = tval.it_interval;
setitimer(ITIMER_VIRTUAL, &tval, NULL);
}
-
-void
-rb_thread_cancel_timer()
-{
-}
-
#else /* !(_THREAD_SAFE || HAVE_SETITIMER) */
int rb_thread_tick = THREAD_TICK;
-
-void
-rb_thread_cancel_timer()
-{
-}
#endif
static VALUE
@@ -11954,8 +12224,6 @@ rb_thread_start_0(fn, arg, th)
#ifdef _THREAD_SAFE
pthread_create(&time_thread, 0, thread_timer, 0);
- time_thread_alive_p = 1;
- pthread_atfork(0, 0, rb_child_atfork);
#else
rb_thread_start_timer();
#endif
@@ -12008,7 +12276,7 @@ rb_thread_start_0(fn, arg, th)
}
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;
@@ -12045,7 +12313,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));
}
@@ -12220,13 +12488,13 @@ rb_thread_value(thread)
*/
static VALUE
-rb_thread_status_name(thread)
+rb_thread_status(thread)
VALUE 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;
}
@@ -12680,7 +12948,7 @@ 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;
@@ -13035,6 +13303,109 @@ thgroup_add(group, thread)
}
+/* 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.
@@ -13049,6 +13420,7 @@ 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);
@@ -13081,7 +13453,7 @@ Init_Thread()
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_name, 0);
+ rb_define_method(rb_cThread, "status", rb_thread_status, 0);
rb_define_method(rb_cThread, "join", rb_thread_join_m, -1);
rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0);
rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0);
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 6534d20760..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
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index a4b769e8cf..636c0907d6 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -586,19 +586,22 @@ 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)))) {
+ 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
@@ -1051,7 +1054,7 @@ 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);
@@ -1505,7 +1508,7 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
} 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 */
@@ -1962,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 */
@@ -2089,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)
{
@@ -2362,16 +2375,15 @@ VpNumOfChars(Real *vp,const 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(
@@ -2388,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");
@@ -2396,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);
@@ -2507,7 +2512,7 @@ VpAlloc(U_LONG mx, const char *szVal)
psz = ALLOCA_N(char,strlen(szVal)+1);
i = 0;
ipn = 0;
- while(psz[i]=szVal[ipn]) {
+ while((psz[i]=szVal[ipn])!=0) {
if(ISDIGIT(psz[i])) ++ni;
if(psz[i]=='_') {
if(ni>0) {ipn++;continue;}
@@ -2550,7 +2555,7 @@ VpAlloc(U_LONG mx, const 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;
@@ -2564,7 +2569,7 @@ VpAlloc(U_LONG mx, const 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;
@@ -2582,7 +2587,7 @@ VpAlloc(U_LONG mx, const 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;
@@ -4434,7 +4439,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/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/dbm/dbm.c b/ext/dbm/dbm.c
index 69b7a6e7a7..0247387fdc 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -812,5 +812,7 @@ Init_dbm()
#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/dl/dl.c b/ext/dl/dl.c
index 5ba3646ea3..f65247be86 100644
--- a/ext/dl/dl.c
+++ b/ext/dl/dl.c
@@ -522,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
@@ -545,13 +548,18 @@ 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);
@@ -563,7 +571,7 @@ rb_io_to_ptr(VALUE self)
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/ptr.c b/ext/dl/ptr.c
index 5112151733..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;
@@ -1010,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;
}
@@ -1062,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 01e0474f58..933fb7f4f0 100644
--- a/ext/dl/sym.c
+++ b/ext/dl/sym.c
@@ -492,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);
}
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/enumerator.c b/ext/enumerator/enumerator.c
deleted file mode 100644
index 1c6e1d1ace..0000000000
--- a/ext/enumerator/enumerator.c
+++ /dev/null
@@ -1,298 +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"
-
-/*
- * Document-class: Enumerable::Enumerator
- *
- * A class which provides a method `each' to be used as an Enumerable
- * object.
- */
-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;
-
-/*
- * 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(obj, enum_args)
- VALUE obj, enum_args;
-{
- rb_ary_unshift(enum_args, obj);
-
- return rb_apply(rb_cEnumerator, id_new, enum_args);
-}
-
-/*
- * call-seq:
- * enum_with_index
- *
- * Returns Enumerable::Enumerator.new(self, :each_with_index).
- *
- */
-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;
-}
-
-/*
- * call-seq:
- * e.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]
- *
- */
-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);
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * e.enum_slice(n)
- *
- * Returns Enumerable::Enumerator.new(self, :each_slice, n).
- *
- */
-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;
-
- if (RARRAY(ary)->len == size) {
- rb_ary_shift(ary);
- }
- rb_ary_push(ary, val);
- if (RARRAY(ary)->len == size) {
- rb_yield(rb_ary_dup(ary));
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * 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]
- *
- */
-static VALUE
-enum_each_cons(obj, n)
- VALUE obj, n;
-{
- long size = NUM2LONG(n);
- NODE *memo;
-
- 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);
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * e.enum_cons(n)
- *
- * Returns Enumerable::Enumerator.new(self, :each_cons, n).
- *
- */
-static VALUE
-enumerator_enum_cons(obj, n)
- VALUE obj, n;
-{
- return rb_funcall(rb_cEnumerator, id_new, 3, obj, sym_each_cons, n);
-}
-
-/*
- * 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.
- *
- * e.g.:
- * str = "xyz"
- *
- * enum = Enumerable::Enumerator.new(str, :each_byte)
- * a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
- *
- */
-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);
-}
-
-/*
- * call-seq:
- * enum.each {...}
- *
- * Iterates the given block using the object and the method specified
- * in the first place.
- *
- */
-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);
- 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/enumerator/extconf.rb b/ext/enumerator/extconf.rb
deleted file mode 100644
index 94e2ee38b2..0000000000
--- a/ext/enumerator/extconf.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require 'mkmf'
-create_makefile('enumerator')
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index 486963378b..ecb9e16411 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -35,6 +35,8 @@ char *getenv();
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'
diff --git a/ext/extmk.rb b/ext/extmk.rb
index cf7944679c..64746552c1 100644
--- a/ext/extmk.rb
+++ b/ext/extmk.rb
@@ -79,7 +79,7 @@ def extract_makefile(makefile, keep = true)
$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] || "")
+ $DLDFLAGS += " " + (m[/^dldflags[ \t]*=[ \t]*(.*)/, 1] || "")
if s = m[/^LIBS[ \t]*=[ \t]*(.*)/, 1]
s.sub!(/^#{Regexp.quote($LIBRUBYARG)} */, "")
s.sub!(/ *#{Regexp.quote($LIBS)}$/, "")
@@ -135,7 +135,6 @@ def extmake(target)
"topdir" => $topdir,
}
mkconfig = {
- "top_srcdir" => ($hdrdir == top_srcdir) ? top_srcdir : "$(topdir)"+top_srcdir[2..-1],
"hdrdir" => "$(top_srcdir)",
"srcdir" => "$(top_srcdir)/ext/#{$mdir}",
"topdir" => $topdir,
@@ -299,7 +298,7 @@ def parse_args()
$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)
@@ -326,9 +325,9 @@ parse_args()
if target = ARGV.shift and /^[a-z-]+$/ =~ target
$mflags.push(target)
- target = target.sub(/^(dist|real)(?=(?:clean)?$)/, '')
case target
- when /clean/
+ when /^(dist|real)?(clean)$/
+ target = $2
$ignore ||= true
$clean = $1 ? $1[0] : true
when /^install\b/
@@ -355,12 +354,16 @@ elsif sep = config_string('BUILD_FILE_SEPARATOR')
else
$ruby = '$(topdir)/miniruby' + EXEEXT
end
-$ruby << " -I'$(topdir)' -I'$(top_srcdir)/lib'"
-$ruby << " -I'$(extout)/$(arch)' -I'$(extout)/common'" if $extout
-$ruby << " -I'$(hdrdir)/ext' -rpurelib.rb"
+$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'
-ENV["RUBYLIB"] = "-"
-ENV["RUBYOPT"] = "-rpurelib.rb"
+$mflags << "ruby=#$ruby"
MTIMES = [__FILE__, 'rbconfig.rb', srcdir+'/lib/mkmf.rb'].collect {|f| File.mtime(f)}
@@ -455,7 +458,16 @@ if $ignore
Dir.chdir ".."
if $clean
Dir.rmdir('ext') rescue nil
- FileUtils.rm_rf(extout) if $extout
+ 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
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
index 65fed33bd2..d989b97df2 100644
--- a/ext/iconv/iconv.c
+++ b/ext/iconv/iconv.c
@@ -43,7 +43,11 @@
*
* == Examples
*
- * 1. Instantiate a new Iconv and use method Iconv#iconv.
+ * 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
@@ -53,20 +57,16 @@
* cd.close
* end
*
- * 2. Invoke Iconv.open with a block.
+ * 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
*
- * 3. Shorthand for (2).
+ * 4. Shorthand for (3).
*
* Iconv.iconv(to, from, *input.to_a)
- *
- * 4. Simple conversion between two charsets.
- *
- * converted_text = Iconv.new('iso-8859-15', 'utf-8').iconv(text)
*/
/* Invalid value for iconv_t is -1 but 0 for VALUE, I hope VALUE is
@@ -101,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));
@@ -170,7 +170,7 @@ iconv_create
}
if (cd == (iconv_t)-1) {
int inval = errno == EINVAL;
- char *s = inval ? "invalid encoding " : "iconv";
+ const char *s = inval ? "invalid encoding " : "iconv";
volatile VALUE msg = rb_str_new(0, strlen(s) + RSTRING(to)->len +
RSTRING(from)->len + 8);
@@ -362,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 */
{
@@ -417,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;
@@ -606,7 +601,7 @@ iconv_s_convert
}
/*
- * Document-method: iconv
+ * Document-method: Iconv::iconv
* call-seq: Iconv.iconv(to, from, *strs)
*
* Shorthand for
@@ -715,7 +710,7 @@ iconv_finish
}
/*
- * Document-method: iconv
+ * Document-method: Iconv#iconv
* call-seq: iconv(str, start=0, length=-1)
*
* Converts string and returns the result.
@@ -754,14 +749,22 @@ 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(n2),
- NULL);
+ return iconv_convert(VALUE2ICONV(cd), str, start, length, NULL);
}
/*
@@ -825,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);
diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c
index 61d6527b36..02cb54a014 100644
--- a/ext/io/wait/wait.c
+++ b/ext/io/wait/wait.c
@@ -56,7 +56,7 @@ static VALUE
io_ready_p(io)
VALUE io;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
FILE *fp;
ioctl_arg n;
@@ -84,7 +84,7 @@ io_wait(argc, argv, io)
VALUE *argv;
VALUE io;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
fd_set rd;
FILE *fp;
int fd;
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index 98921bc468..02e06b7149 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -59,6 +59,8 @@ unless have_header("openssl/conf_api.h")
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("ERR_peek_last_error")
have_func("BN_mod_add")
@@ -81,6 +83,8 @@ have_func("HMAC_CTX_cleanup")
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")
@@ -90,6 +94,7 @@ have_func("X509_CRL_sort")
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")
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/cipher.rb b/ext/openssl/lib/openssl/cipher.rb
index 049533d06b..290e9c1d2d 100644
--- a/ext/openssl/lib/openssl/cipher.rb
+++ b/ext/openssl/lib/openssl/cipher.rb
@@ -19,7 +19,7 @@
#require 'openssl'
module OpenSSL
- module Cipher
+ class Cipher
%w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name|
klass = Class.new(Cipher){
define_method(:initialize){|*args|
@@ -41,18 +41,25 @@ module OpenSSL
const_set("AES#{keylen}", 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
+ # 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 b3e4484805..4810f0121b 100644
--- a/ext/openssl/lib/openssl/digest.rb
+++ b/ext/openssl/lib/openssl/digest.rb
@@ -19,13 +19,17 @@
#require 'openssl'
module OpenSSL
- module Digest
+ 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|
@@ -44,6 +48,14 @@ module OpenSSL
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 9e9a9448ba..f722cb0c45 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -20,6 +20,33 @@ 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
@@ -59,36 +86,49 @@ module OpenSSL
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)
- check_common_name = true
- cert = peer_cert
- cert.extensions.each{|ext|
- next if ext.oid != "subjectAltName"
- ext.value.split(/,\s+/).each{|general_name|
- if /\ADNS:(.*)/ =~ general_name
- check_common_name = false
- reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
- return true if /\A#{reg}\z/i =~ hostname
- elsif /\AIP Address:(.*)/ =~ general_name
- check_common_name = false
- return true if $1 == hostname
- end
- }
- }
- if check_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
- }
+ unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
+ raise SSLError, "hostname was not match with the server certificate"
end
- raise SSLError, "hostname was not match with the server certificate"
+ return true
+ end
+
+ def session
+ SSL::Session.new(self)
+ rescue SSL::Session::SessionError
+ nil
end
end
@@ -114,6 +154,10 @@ module OpenSSL
@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/openssl_missing.c b/ext/openssl/openssl_missing.c
index f77731ed65..724f36b8ae 100644
--- a/ext/openssl/openssl_missing.c
+++ b/ext/openssl/openssl_missing.c
@@ -22,17 +22,15 @@
#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 */
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
index e8c75ca42c..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,14 +60,33 @@ extern "C" {
(char *(*)())d2i_PKCS7_RECIP_INFO, (char *)ri)
#endif
+#if !defined(HAVE_EVP_MD_CTX_INIT)
void HMAC_CTX_init(HMAC_CTX *ctx);
-int HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
+#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);
@@ -107,19 +130,54 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in);
#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 a98f2641cc..53f476fd65 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -59,7 +59,7 @@ 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);
@@ -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;
@@ -310,6 +310,14 @@ ossl_raise(VALUE exc, const char *fmt, ...)
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()
{
@@ -345,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)
{
@@ -427,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
@@ -454,6 +473,7 @@ Init_openssl()
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 598bfb69da..3cc30ae2e8 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -17,6 +17,11 @@
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!
*/
@@ -40,8 +45,12 @@ 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>
@@ -64,9 +73,6 @@ extern "C" {
# define OSSL_OCSP_ENABLED
# include <openssl/ocsp.h>
#endif
-#if defined(_WIN32)
-# undef OpenFile
-#endif
/*
* Common Module
@@ -117,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)
/*
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 3614f470d9..8ceea95021 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -214,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);
@@ -229,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;
}
@@ -253,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;
@@ -295,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;
}
@@ -445,7 +445,7 @@ decode_time(unsigned char* der, int length)
/********/
typedef struct {
- char *name;
+ const char *name;
VALUE *klass;
} ossl_asn1_info_t;
@@ -678,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;
}
@@ -699,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;
@@ -824,8 +824,8 @@ ossl_asn1_traverse(VALUE self, VALUE obj)
obj = ossl_to_der_if_possible(obj);
tmp = rb_str_new4(StringValue(obj));
- p = RSTRING(tmp)->ptr;
- ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 1);
+ p = RSTRING_PTR(tmp);
+ ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 1);
return Qnil;
}
@@ -840,8 +840,8 @@ ossl_asn1_decode(VALUE self, VALUE obj)
obj = ossl_to_der_if_possible(obj);
tmp = rb_str_new4(StringValue(obj));
- p = RSTRING(tmp)->ptr;
- ary = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 1, 0);
+ p = RSTRING_PTR(tmp);
+ ary = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 1, 0);
ret = rb_ary_entry(ary, 0);
return ret;
@@ -857,8 +857,8 @@ ossl_asn1_decode_all(VALUE self, VALUE obj)
obj = ossl_to_der_if_possible(obj);
tmp = rb_str_new4(StringValue(obj));
- p = RSTRING(tmp)->ptr;
- ret = ossl_asn1_decode0(&p, RSTRING(tmp)->len, &offset, 0, 0, 0);
+ p = RSTRING_PTR(tmp);
+ ret = ossl_asn1_decode0(&p, RSTRING_LEN(tmp), &offset, 0, 0, 0);
return ret;
}
@@ -973,21 +973,21 @@ ossl_asn1cons_to_der(VALUE 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;
@@ -1007,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;
@@ -1112,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);
@@ -1166,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_bio.c b/ext/openssl/ossl_bio.c
index 9c9aa24197..6db1fb9a62 100644
--- a/ext/openssl/ossl_bio.c
+++ b/ext/openssl/ossl_bio.c
@@ -19,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 cc7689eef5..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)
{
@@ -124,22 +131,22 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
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;
@@ -149,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)
{
@@ -165,13 +185,13 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
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:
@@ -189,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)
{
@@ -233,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) \
{ \
@@ -248,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) \
{ \
@@ -267,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) \
{ \
@@ -287,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) \
{ \
@@ -310,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)
{
@@ -337,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) \
{ \
@@ -360,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) \
{ \
@@ -374,6 +432,10 @@ 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)
{
@@ -389,6 +451,11 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
}
#define BIGNUM_SHIFT(func) \
+ /* \
+ * call-seq: \
+ * bn.##func(bits) -> aBN \
+ * \
+ */ \
static VALUE \
ossl_bn_##func(VALUE self, VALUE bits) \
{ \
@@ -410,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) \
{ \
@@ -423,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())) { \
@@ -440,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) \
{ \
@@ -458,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)
{
@@ -473,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);
@@ -489,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) \
{ \
@@ -522,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) \
{ \
@@ -541,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)
{
@@ -564,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)
{
@@ -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 57b7976617..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;
@@ -84,6 +83,14 @@ ossl_cipher_alloc(VALUE klass)
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)
{
@@ -124,6 +131,12 @@ add_cipher_name_to_ary(const OBJ_NAME *name, VALUE ary)
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)
{
@@ -141,6 +154,12 @@ ossl_s_ciphers(VALUE self)
#endif
}
+/*
+ * call-seq:
+ * cipher.reset -> self
+ *
+ * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1).
+ */
static VALUE
ossl_cipher_reset(VALUE self)
{
@@ -167,22 +186,23 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
* 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{
- char *cname = rb_class2name(rb_obj_class(self));
- rb_warning("key derivation by %s#encrypt is deprecated; "
- "use %s::pkcs5_keyivgen instead", cname, cname);
StringValue(init_v);
- if (EVP_MAX_IV_LENGTH > RSTRING(init_v)->len) {
+ if (EVP_MAX_IV_LENGTH > RSTRING_LEN(init_v)) {
memset(iv, 0, EVP_MAX_IV_LENGTH);
- memcpy(iv, RSTRING(init_v)->ptr, RSTRING(init_v)->len);
+ memcpy(iv, RSTRING_PTR(init_v), RSTRING_LEN(init_v));
}
- else memcpy(iv, RSTRING(init_v)->ptr, sizeof(iv));
+ else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv));
}
EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
- RSTRING(pass)->ptr, RSTRING(pass)->len, 1, key, NULL);
+ RSTRING_PTR(pass), RSTRING_LEN(pass), 1, key, NULL);
p_key = key;
p_iv = iv;
}
@@ -196,18 +216,54 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
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)
{
return ossl_cipher_init(argc, argv, self, 0);
}
+/*
+ * 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)
{
@@ -221,15 +277,15 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
StringValue(vpass);
if(!NIL_P(vsalt)){
StringValue(vsalt);
- if(RSTRING(vsalt)->len != PKCS5_SALT_LEN)
+ if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN)
rb_raise(eCipherError, "salt must be an 8-octet string");
- salt = RSTRING(vsalt)->ptr;
+ 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(vpass)->ptr, RSTRING(vpass)->len, iter, key, iv);
+ 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);
@@ -238,39 +294,75 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
return Qnil;
}
+
+/*
+ * 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;
+
+ 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);
StringValue(data);
- in = RSTRING(data)->ptr;
- if ((in_len = RSTRING(data)->len) == 0)
+ in = RSTRING_PTR(data);
+ if ((in_len = RSTRING_LEN(data)) == 0)
rb_raise(rb_eArgError, "data must not be empty");
GetCipher(self, ctx);
- 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))
- ossl_raise(eCipherError, NULL);
- assert(out_len < RSTRING(str)->len);
- RSTRING(str)->len = out_len;
- RSTRING(str)->ptr[out_len] = 0;
+ out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
- return str;
-}
+ if (NIL_P(str)) {
+ str = rb_str_new(0, out_len);
+ } else {
+ StringValue(str);
+ rb_str_resize(str, out_len);
+ }
-static VALUE
-ossl_cipher_update_deprecated(VALUE self, VALUE data)
-{
- char *cname;
+ if (!EVP_CipherUpdate(ctx, RSTRING_PTR(str), &out_len, in, in_len))
+ ossl_raise(eCipherError, NULL);
+ assert(out_len < RSTRING_LEN(str));
+ rb_str_set_len(str, out_len);
- cname = rb_class2name(rb_obj_class(self));
- rb_warning("%s#<< is deprecated; use %s#update instead", cname, cname);
- return ossl_cipher_update(self, data);
+ 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)
{
@@ -280,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_ex(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)
{
@@ -299,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)
{
@@ -307,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_ex(ctx, NULL, 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)
{
@@ -324,20 +437,32 @@ 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_ex(ctx, NULL, NULL, NULL, RSTRING(iv)->ptr, -1) != 1)
+ 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)
{
- EVP_CIPHER_CTX *ctx;
int len = NUM2INT(key_length);
+ EVP_CIPHER_CTX *ctx;
GetCipher(self, ctx);
if (EVP_CIPHER_CTX_set_key_length(ctx, len) != 1)
@@ -346,6 +471,16 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length)
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)
{
@@ -374,6 +509,27 @@ 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
*/
@@ -383,21 +539,21 @@ Init_ossl_cipher(void)
#if 0 /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
#endif
-
- mCipher = rb_define_module_under(mOSSL, "Cipher");
- eCipherError = rb_define_class_under(mOSSL, "CipherError", eOSSLError);
- cCipher = rb_define_class_under(mCipher, "Cipher", rb_cObject);
+ 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_copy_func(cCipher, ossl_cipher_copy);
- rb_define_module_function(mCipher, "ciphers", ossl_s_ciphers, 0);
+ 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, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1);
- rb_define_method(cCipher, "update", ossl_cipher_update, 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);
@@ -408,3 +564,4 @@ Init_ossl_cipher(void)
rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
}
+
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 f1d6a98253..cc8e324029 100644
--- a/ext/openssl/ossl_config.c
+++ b/ext/openssl/ossl_config.c
@@ -171,16 +171,16 @@ ossl_config_add_value(VALUE self, VALUE section, VALUE name, VALUE value)
StringValue(name);
StringValue(value);
GetConfig(self, conf);
- if(!(sv = _CONF_get_section(conf, RSTRING(section)->ptr))){
- if(!(sv = _CONF_new_section(conf, RSTRING(section)->ptr))){
+ 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);
@@ -201,7 +201,7 @@ ossl_config_get_value(VALUE self, VALUE section, VALUE name)
StringValue(section);
StringValue(name);
GetConfig(self, conf);
- str = NCONF_get_string(conf, RSTRING(section)->ptr, RSTRING(name)->ptr);
+ str = NCONF_get_string(conf, RSTRING_PTR(section), RSTRING_PTR(name));
if(!str){
ERR_clear_error();
return Qnil;
@@ -249,7 +249,7 @@ ossl_config_set_section(VALUE self, VALUE section, VALUE hash)
arg[0] = self;
arg[1] = section;
- rb_iterate(rb_each, hash, set_conf_section_i, (VALUE)arg);
+ rb_block_call(hash, rb_intern("each"), 0, 0, set_conf_section_i, (VALUE)arg);
return hash;
}
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index 4096b097a2..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);
+
+ md = EVP_get_digestbyname(name);
+ if (!md)
+ ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
+ } else {
+ EVP_MD_CTX *ctx;
- SafeGetDigest(obj, ctx);
+ SafeGetDigest(obj, ctx);
- return EVP_MD_CTX_md(ctx); /*== ctx->digest*/
+ md = EVP_MD_CTX_md(ctx);
+ }
+
+ return md;
}
VALUE
@@ -51,7 +62,6 @@ ossl_digest_new(const EVP_MD *md)
ret = ossl_digest_alloc(cDigest);
GetDigest(ret, ctx);
- EVP_MD_CTX_init(ctx);
EVP_DigestInit_ex(ctx, md, NULL);
return ret;
@@ -69,14 +79,18 @@ ossl_digest_alloc(VALUE klass)
ctx = EVP_MD_CTX_create();
if (ctx == NULL)
ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed");
- EVP_MD_CTX_init(ctx);
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)
{
@@ -86,14 +100,9 @@ ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
VALUE type, data;
rb_scan_args(argc, argv, "11", &type, &data);
- StringValue(type);
+ md = GetDigestPtr(type);
if (!NIL_P(data)) StringValue(data);
- name = StringValuePtr(type);
-
- md = EVP_get_digestbyname(name);
- if (!md) {
- ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%s).", name);
- }
+
GetDigest(self, ctx);
EVP_DigestInit_ex(ctx, md, NULL);
@@ -118,6 +127,11 @@ ossl_digest_copy(VALUE self, VALUE other)
return self;
}
+/*
+ * call-seq:
+ * digest.reset -> self
+ *
+ */
static VALUE
ossl_digest_reset(VALUE self)
{
@@ -129,6 +143,11 @@ ossl_digest_reset(VALUE self)
return self;
}
+/*
+ * call-seq:
+ * digest.update(string) -> aString
+ *
+ */
VALUE
ossl_digest_update(VALUE self, VALUE data)
{
@@ -136,126 +155,77 @@ ossl_digest_update(VALUE self, VALUE data)
StringValue(data);
GetDigest(self, ctx);
- EVP_DigestUpdate(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+ 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)))) {
- EVP_MD_CTX_cleanup(&final);
- ossl_raise(eDigestError, "Cannot allocate mem for digest");
- }
- EVP_DigestFinal_ex(&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;
- if (rb_obj_is_kind_of(other, cDigest) == Qtrue) {
- str2 = ossl_digest_digest(other);
- } else {
- StringValue(other);
- str2 = other;
- }
GetDigest(self, ctx);
- 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));
}
/*
@@ -264,35 +234,26 @@ ossl_digest_size(VALUE self)
void
Init_ossl_digest()
{
+ rb_require("openssl");
+ rb_require("digest");
+
#if 0 /* let rdoc know about mOSSL */
mOSSL = rb_define_module("OpenSSL");
#endif
- mDigest = rb_define_module_under(mOSSL, "Digest");
-
- eDigestError = rb_define_class_under(mDigest, "DigestError", eOSSLError);
-
- cDigest = rb_define_class_under(mDigest, "Digest", rb_cObject);
+ 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 71586e3620..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;\
}\
@@ -75,7 +75,7 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto);
#endif
OSSL_ENGINE_LOAD_IF_MATCH(openssl);
- rb_warning("no such builtin loader for `%s'", RSTRING(name)->ptr);
+ rb_warning("no such builtin loader for `%s'", RSTRING_PTR(name));
return Qnil;
#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
}
@@ -112,7 +112,7 @@ 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);
@@ -281,8 +281,8 @@ ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &cmd, &val);
StringValue(cmd);
if (!NIL_P(val)) StringValue(val);
- ret = ENGINE_ctrl_cmd_string(e, RSTRING(cmd)->ptr,
- NIL_P(val) ? NULL : RSTRING(val)->ptr, 0);
+ 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;
diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
index 312343e03d..ef77d6c427 100644
--- a/ext/openssl/ossl_hmac.c
+++ b/ext/openssl/ossl_hmac.c
@@ -57,6 +57,12 @@ ossl_hmac_alloc(VALUE klass)
return obj;
}
+
+/*
+ * call-seq:
+ * HMAC.new(key, digest) -> hmac
+ *
+ */
static VALUE
ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
{
@@ -64,7 +70,7 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
StringValue(key);
GetHMAC(self, ctx);
- HMAC_Init_ex(ctx, RSTRING(key)->ptr, RSTRING(key)->len,
+ HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LEN(key),
GetDigestPtr(digest), NULL);
return self;
@@ -81,12 +87,15 @@ 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)
{
@@ -94,7 +103,7 @@ ossl_hmac_update(VALUE self, VALUE data)
StringValue(data);
GetHMAC(self, ctx);
- HMAC_Update(ctx, RSTRING(data)->ptr, RSTRING(data)->len);
+ HMAC_Update(ctx, RSTRING_PTR(data), RSTRING_LEN(data));
return self;
}
@@ -104,9 +113,7 @@ 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));
@@ -116,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)
{
@@ -131,6 +143,11 @@ ossl_hmac_digest(VALUE self)
return digest;
}
+/*
+ * call-seq:
+ * hmac.hexdigest -> aString
+ *
+ */
static VALUE
ossl_hmac_hexdigest(VALUE self)
{
@@ -151,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)
{
@@ -159,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)
{
@@ -175,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");
}
@@ -206,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 66e28374cc..738a203d93 100644
--- a/ext/openssl/ossl_ns_spki.c
+++ b/ext/openssl/ossl_ns_spki.c
@@ -62,9 +62,9 @@ ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
StringValue(buffer);
- if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING(buffer)->ptr, -1))) {
- p = RSTRING(buffer)->ptr;
- if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING(buffer)->len))) {
+ 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);
}
}
@@ -87,7 +87,7 @@ ossl_spki_to_der(VALUE self)
if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0)
ossl_raise(eX509CertError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if (i2d_NETSCAPE_SPKI(spki, &p) <= 0)
ossl_raise(eX509CertError, NULL);
ossl_str_adjust(str, p);
@@ -183,8 +183,8 @@ ossl_spki_set_challenge(VALUE self, VALUE str)
StringValue(str);
GetSPKI(self, spki);
- if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING(str)->ptr,
- RSTRING(str)->len)) {
+ if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING_PTR(str),
+ RSTRING_LEN(str))) {
ossl_raise(eSPKIError, NULL);
}
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index b5ea9dadf5..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");
}
}
@@ -134,7 +134,7 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
else{
StringValue(val);
GetOCSPReq(self, req);
- ret = OCSP_request_add1_nonce(req, RSTRING(val)->ptr, RSTRING(val)->len);
+ ret = OCSP_request_add1_nonce(req, RSTRING_PTR(val), RSTRING_LEN(val));
}
if(!ret) ossl_raise(eOCSPError, NULL);
@@ -265,7 +265,7 @@ ossl_ocspreq_to_der(VALUE self)
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);
@@ -316,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");
}
}
@@ -377,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);
@@ -436,7 +436,7 @@ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
else{
StringValue(val);
GetOCSPBasicRes(self, bs);
- ret = OCSP_basic_add1_nonce(bs, RSTRING(val)->ptr, RSTRING(val)->len);
+ ret = OCSP_basic_add1_nonce(bs, RSTRING_PTR(val), RSTRING_LEN(val));
}
if(!ret) ossl_raise(eOCSPError, NULL);
@@ -461,8 +461,8 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
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;
@@ -490,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;
diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c
index e7d9954c5a..2ec69ba8db 100644
--- a/ext/openssl/ossl_pkcs12.c
+++ b/ext/openssl/ossl_pkcs12.c
@@ -30,7 +30,6 @@
/*
* Classes
*/
-VALUE mPKCS12;
VALUE cPKCS12;
VALUE ePKCS12Error;
@@ -49,32 +48,85 @@ ossl_pkcs12_s_allocate(VALUE klass)
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;
+ 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, "41", &pass, &name, &pkey, &cert, &ca);
+ 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,
- 0, 0, 0, 0, 0);
+ 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)
{
@@ -94,7 +146,7 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
pkey = cert = ca = Qnil;
if(!PKCS12_parse((PKCS12*)DATA_PTR(self), passphrase, &key, &x509, &x509s))
- ossl_raise(ePKCS12Error, NULL);
+ ossl_raise(ePKCS12Error, "PKCS12_parse");
pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key,
&st); /* NO DUP */
if(st) goto err;
@@ -129,7 +181,7 @@ ossl_pkcs12_to_der(VALUE self)
if((len = i2d_PKCS12(p12, NULL)) <= 0)
ossl_raise(ePKCS12Error, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_PKCS12(p12, &p) <= 0)
ossl_raise(ePKCS12Error, NULL);
ossl_str_adjust(str, p);
@@ -140,10 +192,14 @@ ossl_pkcs12_to_der(VALUE self)
void
Init_ossl_pkcs12()
{
- mPKCS12 = rb_define_module_under(mOSSL, "PKCS12");
- cPKCS12 = rb_define_class_under(mPKCS12, "PKCS12", rb_cObject);
- ePKCS12Error = rb_define_class_under(mPKCS12, "PKCS12Error", eOSSLError);
- rb_define_module_function(mPKCS12, "create", ossl_pkcs12_s_create, -1);
+ /*
+ * 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);
diff --git a/ext/openssl/ossl_pkcs12.h b/ext/openssl/ossl_pkcs12.h
index 01dde2bc30..24d25d00bb 100644
--- a/ext/openssl/ossl_pkcs12.h
+++ b/ext/openssl/ossl_pkcs12.h
@@ -6,7 +6,6 @@
#if !defined(_OSSL_PKCS12_H_)
#define _OSSL_PKCS12_H_
-extern VALUE mPKCS12;
extern VALUE cPKCS12;
extern VALUE ePKCS12Error;
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_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index 0fcabd7777..6918844779 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -71,7 +71,6 @@
/*
* Classes
*/
-VALUE mPKCS7;
VALUE cPKCS7;
VALUE cPKCS7Signer;
VALUE cPKCS7Recipient;
@@ -134,7 +133,8 @@ DupPKCS7RecipientPtr(VALUE obj)
}
/*
- * Private
+ * call-seq:
+ * PKCS7.read_smime(string) => pkcs7
*/
static VALUE
ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
@@ -156,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)
{
@@ -187,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)
{
@@ -226,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)
{
@@ -287,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)
{
@@ -335,7 +354,7 @@ static int
ossl_pkcs7_sym2typeid(VALUE sym)
{
int i, ret = Qnil;
- char *s;
+ const char *s;
static struct {
const char *name;
@@ -364,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)
{
@@ -376,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)
{
@@ -583,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;
}
@@ -623,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;
}
@@ -751,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);
@@ -926,15 +953,12 @@ ossl_pkcs7ri_get_enc_key(VALUE self)
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);
@@ -964,8 +988,8 @@ 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, "SignerInfo", rb_cObject);
- rb_define_const(mPKCS7, "Signer", cPKCS7Signer);
+ 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, "issuer", ossl_pkcs7si_get_issuer, 0);
@@ -973,14 +997,14 @@ Init_ossl_pkcs7()
rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0);
rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0);
- cPKCS7Recipient = rb_define_class_under(mPKCS7,"RecipientInfo",rb_cObject);
+ 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 f5942d65db..371c421103 100644
--- a/ext/openssl/ossl_pkcs7.h
+++ b/ext/openssl/ossl_pkcs7.h
@@ -11,7 +11,6 @@
#if !defined(_OSSL_PKCS7_H_)
#define _OSSL_PKCS7_H_
-extern VALUE mPKCS7;
extern VALUE cPKCS7;
extern VALUE cPKCS7Signer;
extern VALUE cPKCS7Recipient;
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index d54f5b938e..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));
}
@@ -108,7 +112,7 @@ EVP_PKEY *
DupPKeyPtr(VALUE obj)
{
EVP_PKEY *pkey;
-
+
SafeGetPKey(obj, pkey);
CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
@@ -169,13 +173,12 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
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;
}
@@ -190,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:
@@ -227,10 +230,11 @@ Init_ossl_pkey()
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 880a104675..67ff1fddd0 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -77,7 +77,24 @@ 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; \
@@ -89,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; \
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index e16ede8bba..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)
{
@@ -134,7 +158,7 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
}
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);
@@ -158,19 +182,26 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
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)
{
@@ -181,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)
{
@@ -201,6 +237,11 @@ ossl_dh_export(VALUE self)
return str;
}
+/*
+ * call-seq:
+ * dh.to_der -> aString
+ *
+ */
static VALUE
ossl_dh_to_der(VALUE self)
{
@@ -213,7 +254,7 @@ ossl_dh_to_der(VALUE self)
if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0)
ossl_raise(eDHError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_DHparams(pkey->pkey.dh, &p) < 0)
ossl_raise(eDHError, NULL);
ossl_str_adjust(str, p);
@@ -222,6 +263,9 @@ ossl_dh_to_der(VALUE self)
}
/*
+ * 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)
@@ -245,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)
@@ -270,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)
@@ -290,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)
{
@@ -307,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)
{
@@ -321,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)
{
@@ -335,11 +407,10 @@ 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;
}
@@ -367,7 +438,7 @@ static unsigned char DEFAULT_DH_512_PRIM[] = {
};
static unsigned char DEFAULT_DH_512_GEN[] = { 0x02 };
DH *OSSL_DEFAULT_DH_512 = NULL;
-
+
/*
* -----BEGIN DH PARAMETERS-----
* MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ
@@ -406,7 +477,7 @@ ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
dh->g = BN_bin2bn(g, glen, NULL);
if (dh->p == NULL || dh->g == NULL){
DH_free(dh);
- ossl_raise(eDHError, NULL);
+ ossl_raise(eDHError, NULL);
}
return dh;
@@ -453,11 +524,9 @@ Init_ossl_dh()
}
#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 fdf23aa496..d9c7fcbe78 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -99,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) {
@@ -113,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)
{
@@ -163,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)
{
@@ -170,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,6 +217,19 @@ ossl_dsa_is_private(VALUE self)
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)
{
@@ -224,6 +267,11 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
return str;
}
+/*
+ * call-seq:
+ * dsa.to_der -> aString
+ *
+ */
static VALUE
ossl_dsa_to_der(VALUE self)
{
@@ -241,7 +289,7 @@ ossl_dsa_to_der(VALUE self)
if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0)
ossl_raise(eDSAError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_func(pkey->pkey.dsa, &p) < 0)
ossl_raise(eDSAError, NULL);
ossl_str_adjust(str, p);
@@ -250,6 +298,9 @@ ossl_dsa_to_der(VALUE self)
}
/*
+ * 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)
@@ -274,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)
@@ -299,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
@@ -321,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)
{
@@ -334,16 +396,20 @@ ossl_dsa_sign(VALUE self, VALUE data)
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)
{
@@ -354,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);
}
@@ -411,12 +477,8 @@ Init_ossl_dsa()
}
#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 0afdcf8d01..9ac69e7ded 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -84,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;
@@ -104,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)
{
@@ -157,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)
{
@@ -164,12 +195,16 @@ 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)
{
@@ -180,6 +215,18 @@ ossl_rsa_is_private(VALUE self)
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)
{
@@ -219,6 +266,11 @@ 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)
{
@@ -236,7 +288,7 @@ ossl_rsa_to_der(VALUE self)
if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0)
ossl_raise(eRSAError, NULL);
str = rb_str_new(0, len);
- p = RSTRING(str)->ptr;
+ p = RSTRING_PTR(str);
if(i2d_func(pkey->pkey.rsa, &p) < 0)
ossl_raise(eRSAError, NULL);
ossl_str_adjust(str, p);
@@ -246,6 +298,11 @@ ossl_rsa_to_der(VALUE self)
#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(int argc, VALUE *argv, VALUE self)
{
@@ -258,16 +315,20 @@ ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
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,
+ 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(int argc, VALUE *argv, VALUE self)
{
@@ -280,16 +341,20 @@ ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
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,
+ 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);
- RSTRING(str)->len = buf_len;
- RSTRING(str)->ptr[buf_len] = 0;
+ rb_str_set_len(str, buf_len);
return str;
}
+/*
+ * call-seq:
+ * rsa.private_encrypt(string [, padding]) -> aString
+ *
+ */
static VALUE
ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
{
@@ -305,16 +370,21 @@ ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
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,
+ 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(int argc, VALUE *argv, VALUE self)
{
@@ -330,17 +400,19 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
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,
+ 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)
@@ -368,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)
@@ -393,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
@@ -415,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)
@@ -508,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 71bb3bedd5..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);
@@ -124,11 +190,13 @@ Init_ossl_rand()
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 8e632b526b..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))
@@ -65,11 +63,12 @@ VALUE cSSLSocket;
#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",
"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")
@@ -86,8 +85,10 @@ static char *ossl_sslctx_attrs[] = {
#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 char *ossl_ssl_attr_readers[] = { "io", "context", };
-static char *ossl_ssl_attrs[] = { "sync_close", };
+static const char *ossl_ssl_attr_readers[] = { "io", "context", };
+static const char *ossl_ssl_attrs[] = { "sync_close", };
+
+ID ID_callback_state;
/*
* SSLContext class
@@ -141,22 +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;
- 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
@@ -175,6 +167,33 @@ ossl_sslctx_initialize(int argc, VALUE *argv, VALUE self)
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;
}
@@ -251,6 +270,8 @@ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
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;
@@ -274,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;
@@ -288,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)
{
@@ -307,10 +473,10 @@ ossl_sslctx_setup(VALUE self)
SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
}
else{
- rb_warning("using default DH parameters.");
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)){
@@ -327,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. */
@@ -352,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");
@@ -397,12 +563,24 @@ ossl_sslctx_setup(VALUE self)
val = ossl_sslctx_get_sess_id_ctx(self);
if (!NIL_P(val)){
StringValue(val);
- if (!SSL_CTX_set_session_id_context(ctx, RSTRING(val)->ptr,
- RSTRING(val)->len)){
- ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:");
+ 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;
}
@@ -422,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)
{
@@ -450,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)
{
@@ -462,12 +650,12 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
return v;
else if (TYPE(v) == T_ARRAY) {
str = rb_str_new(0, 0);
- for (i = 0; i < RARRAY(v)->len; i++) {
+ 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;
@@ -479,13 +667,173 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
ossl_raise(eSSLError, "SSL_CTX is not initialized.");
return Qnil;
}
- if (!SSL_CTX_set_cipher_list(ctx, RSTRING(str)->ptr)) {
+ if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) {
ossl_raise(eSSLError, "SSL_CTX_set_cipher_list:");
}
return v;
}
+
+/*
+ * call-seq:
+ * ctx.session_add(session) -> true | false
+ *
+ */
+static VALUE
+ossl_sslctx_session_add(VALUE self, VALUE arg)
+{
+ SSL_CTX *ctx;
+ SSL_SESSION *sess;
+
+ Data_Get_Struct(self, SSL_CTX, ctx);
+ SafeGetSSLSession(arg, sess);
+
+ 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
*/
@@ -511,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)
{
@@ -536,7 +898,7 @@ ossl_ssl_setup(VALUE self)
VALUE io, v_ctx, cb;
SSL_CTX *ctx;
SSL *ssl;
- OpenFile *fptr;
+ rb_io_t *fptr;
Data_Get_Struct(self, SSL, ssl);
if(!ssl){
@@ -553,7 +915,7 @@ 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);
@@ -567,61 +929,85 @@ ossl_ssl_setup(VALUE self)
}
#ifdef _WIN32
-#define ssl_get_error(ssl, ret) \
- (errno = WSAGetLastError(), SSL_get_error(ssl, ret))
+#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_start_ssl(VALUE self, int (*func)())
+ossl_start_ssl(VALUE self, int (*func)(), const char *funcname)
{
SSL *ssl;
- OpenFile *fptr;
- int ret;
+ rb_io_t *fptr;
+ int ret, ret2;
+ VALUE cb_state;
+
+ rb_ivar_set(self, ID_callback_state, Qnil);
Data_Get_Struct(self, SSL, ssl);
GetOpenFile(ossl_ssl_get_io(self), fptr);
for(;;){
if((ret = func(ssl)) > 0) break;
- switch(ssl_get_error(ssl, ret)){
+ switch((ret2 = ssl_get_error(ssl, ret))){
case SSL_ERROR_WANT_WRITE:
- rb_io_wait_writable(fileno(fptr->f));
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_WANT_READ:
- rb_io_wait_readable(fileno(fptr->f));
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_SYSCALL:
- if (errno) rb_sys_fail(0);
+ 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, NULL);
+ 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_connect(VALUE self)
{
ossl_ssl_setup(self);
- return ossl_start_ssl(self, SSL_connect);
+ return ossl_start_ssl(self, SSL_connect, "SSL_connect");
}
+/*
+ * call-seq:
+ * ssl.accept => self
+ */
static VALUE
ossl_ssl_accept(VALUE self)
{
ossl_ssl_setup(self);
- return ossl_start_ssl(self, SSL_accept);
+ 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(int argc, VALUE *argv, VALUE self)
{
SSL *ssl;
int ilen, nread = 0;
VALUE len, str;
- OpenFile *fptr;
+ rb_io_t *fptr;
rb_scan_args(argc, argv, "11", &len, &str);
ilen = NUM2INT(len);
@@ -637,19 +1023,19 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
GetOpenFile(ossl_ssl_get_io(self), fptr);
if (ssl) {
if(SSL_pending(ssl) <= 0)
- rb_thread_wait_fd(fileno(fptr->f));
+ rb_thread_wait_fd(FPTR_TO_FD(fptr));
for (;;){
- nread = SSL_read(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
+ 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(fileno(fptr->f));
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_WANT_READ:
- rb_io_wait_readable(fileno(fptr->f));
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_SYSCALL:
if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
@@ -666,19 +1052,22 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
}
end:
- RSTRING(str)->len = nread;
- RSTRING(str)->ptr[nread] = 0;
+ 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;
+ rb_io_t *fptr;
StringValue(str);
Data_Get_Struct(self, SSL, ssl);
@@ -686,15 +1075,15 @@ ossl_ssl_write(VALUE self, VALUE str)
if (ssl) {
for (;;){
- nwrite = SSL_write(ssl, RSTRING(str)->ptr, RSTRING(str)->len);
+ 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(fileno(fptr->f));
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_WANT_READ:
- rb_io_wait_readable(fileno(fptr->f));
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
continue;
case SSL_ERROR_SYSCALL:
if (errno) rb_sys_fail(0);
@@ -713,6 +1102,10 @@ ossl_ssl_write(VALUE self, VALUE str)
return INT2NUM(nwrite);
}
+/*
+ * call-seq:
+ * ssl.sysclose => nil
+ */
static VALUE
ossl_ssl_close(VALUE self)
{
@@ -726,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)
{
@@ -750,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)
{
@@ -775,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)
{
@@ -801,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)
{
@@ -817,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)
{
@@ -836,6 +1249,10 @@ ossl_ssl_get_state(VALUE self)
return ret;
}
+/*
+ * call-seq:
+ * ssl.pending => integer
+ */
static VALUE
ossl_ssl_pending(VALUE self)
{
@@ -850,15 +1267,83 @@ ossl_ssl_pending(VALUE self)
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);
@@ -870,16 +1355,60 @@ Init_ossl_ssl()
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++)
@@ -899,6 +1428,9 @@ Init_ossl_ssl()
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))
@@ -934,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 7b88e294a9..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)
{
@@ -95,9 +99,9 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){
oid = ossl_to_der_if_possible(oid);
StringValue(oid);
- p = RSTRING(oid)->ptr;
+ p = RSTRING_PTR(oid);
if(!d2i_X509_ATTRIBUTE((X509_ATTRIBUTE**)&DATA_PTR(self),
- &p, RSTRING(oid)->len)){
+ &p, RSTRING_LEN(oid))){
ossl_raise(eX509AttrError, NULL);
}
return self;
@@ -108,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)
{
@@ -125,6 +133,10 @@ ossl_x509attr_set_oid(VALUE self, VALUE oid)
return oid;
}
+/*
+ * call-seq:
+ * attr.oid => string
+ */
static VALUE
ossl_x509attr_get_oid(VALUE self)
{
@@ -156,6 +168,10 @@ 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)
{
@@ -179,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)
{
@@ -192,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);
}
@@ -200,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);
@@ -210,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)
{
@@ -222,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 fc587a31f3..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,6 +283,10 @@ 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)
{
@@ -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)
{
@@ -322,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)
{
@@ -336,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)
{
@@ -349,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)
{
@@ -363,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)
{
@@ -376,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)
{
@@ -390,6 +447,10 @@ 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)
{
@@ -405,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)
{
@@ -419,6 +484,10 @@ 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)
{
@@ -434,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)
{
@@ -448,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)
{
@@ -461,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)
{
@@ -479,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
@@ -501,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
@@ -521,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)
@@ -546,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)
@@ -557,14 +646,14 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
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);
@@ -576,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 0dc22416e7..be9ddacf48 100644
--- a/ext/openssl/ossl_x509crl.c
+++ b/ext/openssl/ossl_x509crl.c
@@ -287,14 +287,14 @@ ossl_x509crl_set_revoked(VALUE self, VALUE ary)
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,14 +461,14 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary)
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 31ffec48fa..aa9366f901 100644
--- a/ext/openssl/ossl_x509ext.c
+++ b/ext/openssl/ossl_x509ext.c
@@ -229,23 +229,23 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
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);
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(valstr)->ptr);
+ 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(valstr)->ptr);
+ 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);
@@ -280,9 +280,9 @@ ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){
oid = ossl_to_der_if_possible(oid);
StringValue(oid);
- p = RSTRING(oid)->ptr;
+ p = RSTRING_PTR(oid);
if(!d2i_X509_EXTENSION((X509_EXTENSION**)&DATA_PTR(self),
- &p, RSTRING(oid)->len))
+ &p, RSTRING_LEN(oid)))
ossl_raise(eX509ExtError, NULL);
return self;
}
@@ -319,14 +319,14 @@ ossl_x509ext_set_value(VALUE self, VALUE data)
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);
@@ -409,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 076d61fb96..b4434d2a34 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -109,6 +109,13 @@ ossl_x509name_init_i(VALUE i, VALUE args)
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)
{
@@ -125,14 +132,14 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
VALUE args;
if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
args = rb_ary_new3(2, self, template);
- rb_iterate(rb_each, tmp, ossl_x509name_init_i, args);
+ rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
}
else{
unsigned char *p;
VALUE str = ossl_to_der_if_possible(arg);
StringValue(str);
- p = RSTRING(str)->ptr;
- if(!d2i_X509_NAME((X509_NAME**)&DATA_PTR(self), &p, RSTRING(str)->len)){
+ p = RSTRING_PTR(str);
+ if(!d2i_X509_NAME((X509_NAME**)&DATA_PTR(self), &p, RSTRING_LEN(str))){
ossl_raise(eX509NameError, NULL);
}
}
@@ -141,6 +148,10 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/*
+ * call-seq:
+ * name.add_entry(oid, value [, type]) => self
+ */
static
VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
{
@@ -152,8 +163,8 @@ VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
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(oid)->ptr, NUM2INT(type),
- RSTRING(value)->ptr, RSTRING(value)->len, -1, 0)) {
+ 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);
}
@@ -175,9 +186,14 @@ ossl_x509name_to_s_old(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;
@@ -199,6 +215,10 @@ ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
return str;
}
+/*
+ * call-seq:
+ * name.to_a => [[name, data, type], ...]
+ */
static VALUE
ossl_x509name_to_a(VALUE self)
{
@@ -266,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)
{
@@ -279,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)
{
@@ -291,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);
diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c
index d644250433..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);
@@ -403,14 +403,14 @@ ossl_x509req_set_attributes(VALUE self, VALUE ary)
VALUE item;
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 3ccac8d26a..d0f816bad4 100644
--- a/ext/openssl/ossl_x509revoked.c
+++ b/ext/openssl/ossl_x509revoked.c
@@ -175,14 +175,14 @@ ossl_x509revoked_set_extensions(VALUE self, VALUE ary)
VALUE item;
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 cea845a1cc..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);
@@ -206,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());
@@ -227,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());
@@ -451,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;
}
@@ -550,6 +557,10 @@ ossl_x509stctx_set_trust(VALUE self, VALUE trust)
return trust;
}
+/*
+ * call-seq:
+ * storectx.time = time => time
+ */
static VALUE
ossl_x509stctx_set_time(VALUE self, VALUE time)
{
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/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 206d4cd131..939335242f 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -39,10 +39,10 @@
#if !defined(HAVE_OPENPTY)
#if defined(__hpux)
-static
-char *MasterDevice = "/dev/ptym/pty%s",
- *SlaveDevice = "/dev/pty/tty%s",
- *deviceNo[] = {
+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",
@@ -62,10 +62,10 @@ char *MasterDevice = "/dev/ptym/pty%s",
0,
};
#elif defined(_IBMESA) /* AIX/ESA */
-static
-char *MasterDevice = "/dev/ptyp%s",
- *SlaveDevice = "/dev/ttyp%s",
- *deviceNo[] = {
+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,10 +84,10 @@ char *MasterDevice = "/dev/ptyp%s",
"f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff",
};
#elif !defined(HAVE_PTSNAME)
-static
-char *MasterDevice = "/dev/pty%s",
- *SlaveDevice = "/dev/tty%s",
- *deviceNo[] = {
+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",
@@ -101,8 +101,6 @@ char *MasterDevice = "/dev/pty%s",
#endif
#endif /* !defined(HAVE_OPENPTY) */
-static char SlaveName[DEVICELEN];
-
#ifndef HAVE_SETEUID
# ifdef HAVE_SETREUID
# define seteuid(e) setreuid(-1, (e))
@@ -155,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);
}
@@ -176,7 +172,7 @@ pty_syswait(info)
}
}
-static void getDevice _((int*, int*));
+static void getDevice _((int*, int*, char [DEVICELEN]));
struct exec_info {
int argc;
@@ -194,10 +190,11 @@ pty_exec(v)
}
static void
-establishShell(argc, argv, info)
+establishShell(argc, argv, info, SlaveName)
int argc;
VALUE *argv;
struct pty_info *info;
+ char SlaveName[DEVICELEN];
{
int i,master,slave;
char *p, tmp, *getenv();
@@ -223,7 +220,7 @@ establishShell(argc, argv, info)
argc = 1;
argv = &v;
}
- getDevice(&master,&slave);
+ getDevice(&master, &slave, SlaveName);
info->thread = rb_thread_current();
if((i = fork()) < 0) {
@@ -307,8 +304,9 @@ pty_finalize_syswait(info)
}
static int
-get_device_once(master, slave, fail)
+get_device_once(master, slave, SlaveName, fail)
int *master, *slave, fail;
+ char SlaveName[DEVICELEN];
{
#if defined HAVE_OPENPTY
/*
@@ -331,7 +329,7 @@ get_device_once(master, slave, fail)
}
*slave = open(name, O_RDWR);
- strcpy(SlaveName, name);
+ strncpy(SlaveName, name, sizeof SlaveName);
return 0;
#else /* HAVE__GETPTY */
@@ -359,7 +357,7 @@ get_device_once(master, slave, fail)
#endif
*master = i;
*slave = j;
- strcpy(SlaveName, pn);
+ strncpy(SlaveName, pn, sizeof SlaveName);
return 0;
#if defined I_PUSH && !defined linux
}
@@ -378,10 +376,10 @@ get_device_once(master, slave, fail)
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());
@@ -398,12 +396,13 @@ get_device_once(master, slave, fail)
}
static void
-getDevice(master, slave)
+getDevice(master, slave, slavename)
int *master, *slave;
+ char slavename[DEVICELEN];
{
- if (get_device_once(master, slave, 0)) {
+ if (get_device_once(master, slave, slavename, 0)) {
rb_gc();
- get_device_once(master, slave, 1);
+ get_device_once(master, slave, slavename, 1);
}
}
@@ -417,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
index 10ee06176c..dbe514c34a 100644
--- a/ext/purelib.rb
+++ b/ext/purelib.rb
@@ -1,3 +1,10 @@
-if nul = $:.index("-")
+nul = nil
+$:.each_with_index {|path, index|
+ if /\A(?:\.\/)*-\z/ =~ path
+ nul = index
+ break
+ end
+}
+if nul
$:[nul..-1] = ["."]
end
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index 559e1c677b..c9acaadac9 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -42,17 +42,32 @@ static ID completion_proc, completion_case_fold;
# define rl_completion_matches completion_matches
#endif
-static int readline_event(void);
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)
@@ -64,7 +79,7 @@ readline_readline(argc, argv, self)
char *prompt = NULL;
char *buff;
int status;
- OpenFile *ofp, *ifp;
+ rb_io_t *ofp, *ifp;
rb_secure(4);
if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
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/socket.c b/ext/socket/socket.c
index 22e178a4c8..1dcc7160e9 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -244,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");
@@ -259,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);
@@ -275,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");
@@ -300,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");
@@ -319,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");
@@ -384,7 +384,7 @@ 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;
@@ -467,7 +467,7 @@ 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);
@@ -491,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)
@@ -505,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)
@@ -521,7 +521,7 @@ bsock_send(argc, argv, sock)
{
VALUE mesg, to;
VALUE flags;
- OpenFile *fptr;
+ rb_io_t *fptr;
FILE *f;
int fd, n;
@@ -574,7 +574,7 @@ 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;
@@ -644,7 +644,7 @@ s_recvfrom(sock, argc, argv, from)
static VALUE
s_recvfrom_nonblock(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE str;
char buf[1024];
socklen_t alen = sizeof buf;
@@ -1350,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");
@@ -1483,7 +1483,7 @@ make_fd_nonblock(int fd)
}
static VALUE
-s_accept_nonblock(VALUE klass, OpenFile *fptr, struct sockaddr *sockaddr, socklen_t *len)
+s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen_t *len)
{
int fd2;
@@ -1542,7 +1542,7 @@ static VALUE
tcp_accept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage from;
socklen_t fromlen;
@@ -1565,7 +1565,7 @@ tcp_accept(sock)
* serv = TCPServer.new(2202)
* begin
* sock = serv.accept_nonblock
- * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
* IO.select([serv])
* retry
* end
@@ -1585,7 +1585,7 @@ static VALUE
tcp_accept_nonblock(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage from;
socklen_t fromlen;
@@ -1599,7 +1599,7 @@ static VALUE
tcp_sysaccept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_storage from;
socklen_t fromlen;
@@ -1630,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);
@@ -1682,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;
@@ -1697,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;
@@ -1778,7 +1778,7 @@ static VALUE
udp_connect(sock, host, port)
VALUE sock, host, port;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct udp_arg arg;
VALUE ret;
@@ -1796,7 +1796,7 @@ static VALUE
udp_bind(sock, host, port)
VALUE sock, host, port;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct addrinfo *res0, *res;
rb_secure(3);
@@ -1821,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;
@@ -1920,7 +1920,7 @@ static VALUE
unix_path(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
GetOpenFile(sock, fptr);
if (fptr->path == 0) {
@@ -1967,7 +1967,7 @@ unix_send_io(sock, val)
{
#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];
@@ -1975,12 +1975,12 @@ unix_send_io(sock, val)
#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);
}
@@ -2005,12 +2005,13 @@ unix_send_io(sock, val)
#if FD_PASSING_BY_MSG_CONTROL
msg.msg_control = (caddr_t)&cmsg;
- msg.msg_controllen = CMSG_SPACE(sizeof(int));
+ msg.msg_controllen = CMSG_LEN(sizeof(int));
msg.msg_flags = 0;
+ 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);
@@ -2047,7 +2048,7 @@ unix_recv_io(argc, argv, sock)
{
#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];
@@ -2056,7 +2057,7 @@ unix_recv_io(argc, argv, sock)
#if FD_PASSING_BY_MSG_CONTROL
struct {
struct cmsghdr hdr;
- int fd;
+ char pad[8+sizeof(int)+8];
} cmsg;
#endif
@@ -2085,7 +2086,7 @@ unix_recv_io(argc, argv, sock)
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);
@@ -2098,22 +2099,22 @@ unix_recv_io(argc, argv, sock)
#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)",
+ "file descriptor was not passed (msg_controllen=%d, %d expected)",
msg.msg_controllen, CMSG_SPACE(sizeof(int)));
}
- if (cmsg.hdr.cmsg_len != CMSG_SPACE(0) + sizeof(int)) {
+ if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) {
rb_raise(rb_eSocket,
- "file descriptor was not passed (cmsg_len : %d != %d)",
- cmsg.hdr.cmsg_len, CMSG_SPACE(0) + sizeof(int));
+ "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)",
+ "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)",
+ "file descriptor was not passed (cmsg_type=%d, %d expected)",
cmsg.hdr.cmsg_type, SCM_RIGHTS);
}
#else
@@ -2125,7 +2126,7 @@ unix_recv_io(argc, argv, sock)
#endif
#if FD_PASSING_BY_MSG_CONTROL
- fd = cmsg.fd;
+ fd = *(int *)CMSG_DATA(&cmsg.hdr);
#endif
if (klass == Qnil)
@@ -2151,7 +2152,7 @@ static VALUE
unix_accept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un from;
socklen_t fromlen;
@@ -2174,7 +2175,7 @@ unix_accept(sock)
* serv = UNIXServer.new("/tmp/sock")
* begin
* sock = serv.accept_nonblock
- * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
* IO.select([serv])
* retry
* end
@@ -2194,7 +2195,7 @@ static VALUE
unix_accept_nonblock(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un from;
socklen_t fromlen;
@@ -2208,7 +2209,7 @@ static VALUE
unix_sysaccept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un from;
socklen_t fromlen;
@@ -2230,7 +2231,7 @@ static VALUE
unix_addr(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un addr;
socklen_t len = sizeof addr;
@@ -2245,7 +2246,7 @@ static VALUE
unix_peeraddr(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
struct sockaddr_un addr;
socklen_t len = sizeof addr;
@@ -2525,7 +2526,7 @@ static VALUE
sock_connect(sock, addr)
VALUE sock, addr;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
int fd;
StringValue(addr);
@@ -2581,7 +2582,7 @@ static VALUE
sock_connect_nonblock(sock, addr)
VALUE sock, addr;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
int n;
StringValue(addr);
@@ -2679,7 +2680,7 @@ static VALUE
sock_bind(sock, addr)
VALUE sock, addr;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
StringValue(addr);
GetOpenFile(sock, fptr);
@@ -2763,7 +2764,7 @@ static VALUE
sock_listen(sock, log)
VALUE sock, log;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
int backlog;
rb_secure(4);
@@ -2920,7 +2921,7 @@ sock_recvfrom(argc, argv, sock)
* client, client_sockaddr = socket.accept
* begin
* pair = client.recvfrom_nonblock(20)
- * rescue Errno::EAGAIN
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK
* IO.select([client])
* retry
* end
@@ -3039,7 +3040,7 @@ static VALUE
sock_accept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE sock2;
char buf[1024];
socklen_t len = sizeof buf;
@@ -3071,7 +3072,7 @@ sock_accept(sock)
* socket.listen(5)
* begin
* client_socket, client_sockaddr = socket.accept_nonblock
- * rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
+ * rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
* IO.select([socket])
* retry
* end
@@ -3102,7 +3103,7 @@ static VALUE
sock_accept_nonblock(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE sock2;
char buf[1024];
socklen_t len = sizeof buf;
@@ -3155,7 +3156,7 @@ static VALUE
sock_sysaccept(sock)
VALUE sock;
{
- OpenFile *fptr;
+ rb_io_t *fptr;
VALUE sock2;
char buf[1024];
socklen_t len = sizeof buf;
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index 7355afd770..537fc19a4e 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -14,6 +14,7 @@
#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)
@@ -162,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));
@@ -657,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;
@@ -667,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);
@@ -707,11 +712,14 @@ 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;
}
/*
@@ -800,6 +808,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;
@@ -947,7 +990,7 @@ strio_readline(argc, argv, self)
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;
}
@@ -968,6 +1011,8 @@ 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);
}
@@ -1291,11 +1336,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/syck/rubyext.c b/ext/syck/rubyext.c
index 078de4f78d..76e8279601 100644
--- a/ext/syck/rubyext.c
+++ b/ext/syck/rubyext.c
@@ -268,9 +268,13 @@ rb_syck_mktime(str, len)
{
char padded[] = "000000";
char *end = ptr + 1;
+ char *p = end;
while ( isdigit( *end ) ) end++;
- MEMCPY(padded, ptr + 1, char, end - (ptr + 1));
- usec = strtol(padded, NULL, 10);
+ if (end - p < sizeof(padded)) {
+ MEMCPY(padded, ptr + 1, char, end - (ptr + 1));
+ p = padded;
+ }
+ usec = strtol(p, NULL, 10);
}
else
{
@@ -913,7 +917,6 @@ static VALUE
syck_resolver_initialize( self )
VALUE self;
{
- VALUE tags = rb_hash_new();
rb_ivar_set(self, s_tags, rb_hash_new());
return self;
}
@@ -948,7 +951,6 @@ VALUE
syck_resolver_detect_implicit( self, val )
VALUE self, val;
{
- char *type_id;
return rb_str_new2( "" );
}
@@ -1304,7 +1306,6 @@ syck_genericresolver_node_import( self, node )
break;
case syck_seq_kind:
- rb_iv_set(obj, "@kind", sym_seq);
v = rb_ary_new2( syck_seq_count( n ) );
for ( i = 0; i < syck_seq_count( n ); i++ )
{
@@ -1315,10 +1316,10 @@ syck_genericresolver_node_import( self, node )
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:
- rb_iv_set(obj, "@kind", sym_map);
v = rb_hash_new();
for ( i = 0; i < syck_map_count( n ); i++ )
{
@@ -1329,6 +1330,7 @@ syck_genericresolver_node_import( self, node )
style = sym_inline;
}
obj = rb_funcall( cMap, s_new, 3, t, v, style );
+ rb_iv_set(obj, "@kind", sym_map);
break;
}
@@ -2024,7 +2026,6 @@ syck_emitter_emit( argc, argv, self )
VALUE self;
{
VALUE oid, proc;
- char *anchor_name;
SyckEmitter *emitter;
struct emitter_xtra *bonus;
SYMID symple;
@@ -2280,7 +2281,6 @@ Init_syck()
*/
cScalar = rb_define_class_under( rb_syck, "Scalar", cNode );
rb_define_alloc_func( cScalar, syck_scalar_alloc );
- rb_define_attr( cNode, "value", 1, 0 );
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 );
diff --git a/ext/syslog/syslog.c b/ext/syslog/syslog.c
index 477489ddfe..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");
}
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/thread/thread.c b/ext/thread/thread.c
index bca807725e..68f172220a 100644
--- a/ext/thread/thread.c
+++ b/ext/thread/thread.c
@@ -12,9 +12,6 @@
#include <ruby.h>
#include <intern.h>
#include <rubysig.h>
-#include <node.h>
-
-enum rb_thread_status rb_thread_status _((VALUE));
static VALUE rb_cMutex;
static VALUE rb_cConditionVariable;
@@ -230,9 +227,7 @@ wake_one(List *list)
waking = Qnil;
while (list->entries && !RTEST(waking)) {
- waking = shift_list(list);
- if (waking == Qundef) break;
- waking = wake_thread(waking);
+ waking = wake_thread(shift_list(list));
}
return waking;
@@ -263,10 +258,10 @@ wait_list_cleanup(List *list)
return Qnil;
}
-static void
+static VALUE
wait_list(List *list)
{
- rb_ensure(wait_list_inner, (VALUE)list, wait_list_cleanup, (VALUE)list);
+ return rb_ensure(wait_list_inner, (VALUE)list, wait_list_cleanup, (VALUE)list);
}
static void
@@ -438,22 +433,6 @@ rb_mutex_lock(VALUE self)
return self;
}
-static VALUE
-relock_mutex(Mutex *mutex)
-{
- VALUE current = rb_thread_current();
-
- switch (rb_thread_status(current)) {
- case THREAD_RUNNABLE:
- case THREAD_STOPPED:
- lock_mutex(mutex);
- break;
- default:
- break;
- }
- return Qundef;
-}
-
/*
* Document-method: unlock
*
@@ -664,7 +643,7 @@ wait_condvar(ConditionVariable *condvar, Mutex *mutex)
if (RTEST(waking)) {
wake_thread(waking);
}
- rb_ensure(wait_list, (VALUE)&condvar->waiting, relock_mutex, (VALUE)mutex);
+ rb_ensure(wait_list, (VALUE)&condvar->waiting, lock_mutex, (VALUE)mutex);
}
static VALUE
diff --git a/ext/tk/ChangeLog.tkextlib b/ext/tk/ChangeLog.tkextlib
index 359b466a32..8c5d01a954 100644
--- a/ext/tk/ChangeLog.tkextlib
+++ b/ext/tk/ChangeLog.tkextlib
@@ -1,3 +1,9 @@
+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.
diff --git a/ext/tk/MANUAL_tcltklib.eng b/ext/tk/MANUAL_tcltklib.eng
index 1db61f228e..6fa775b7de 100644
--- a/ext/tk/MANUAL_tcltklib.eng
+++ b/ext/tk/MANUAL_tcltklib.eng
@@ -125,7 +125,24 @@ module TclTklib
: 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.
@@ -431,6 +448,10 @@ class TclTkIp
: 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
@@ -441,5 +462,8 @@ class TkCallbackContinue < StandardError
: 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
index 5dd36726ba..7df42997b4 100644
--- a/ext/tk/MANUAL_tcltklib.eucj
+++ b/ext/tk/MANUAL_tcltklib.eucj
@@ -221,7 +221,23 @@ require "tcltklib" ¤¹¤ë¤È, °Ê²¼¤Î¥â¥¸¥å¡¼¥ë, ¥¯¥é¥¹¤¬ÍøÍѲÄǽ¤Ç¤¹.
: ¤«¤éÃê½Ð¤µ¤ì¤ë¤Ï¤º¤Ç¤¢¤ë¤«¤é¡¤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 ¤¬Â¸ºß¤¹¤ë¸Â¤ê¡¤¤³¤Î¥á¥½¥Ã¥É¤Ï½ªÎ»¤·¤Ê¤¤¡¥
@@ -543,6 +559,9 @@ require "tcltklib" ¤¹¤ë¤È, °Ê²¼¤Î¥â¥¸¥å¡¼¥ë, ¥¯¥é¥¹¤¬ÍøÍѲÄǽ¤Ç¤¹.
: ¥¹¥ì¡¼¥Ö IP ¤Î¾ì¹ç¤Ë¤ÏÃͤÎÀßÄ꤬µö¤µ¤ì¤Ê¤¤ (̵»ë¤µ¤ì¤ë)¡¥
: ¤½¤ì°Ê³°¤ÎÅÀ¤Ç¤Ï°ú¿ô¤ò´Þ¤á¤Æ TclTkLib ¤ÎƱ̾¥á¥½¥Ã¥É¤ËƱ¤¸¡¥
+ encoding_table
+ : Ruby m17n ÍÑ¤Ë Ruby ¤È Tk ¤È¤Î´Ö¤Î encoding Âбþɽ¤òÊÖ¤¹¡¥
+
¥¯¥é¥¹ TkCallbackBreak < StandardError
¥¯¥é¥¹ TkCallbackContinue < StandardError
: ¤³¤ì¤é¤Ï¥¤¥Ù¥ó¥È¥³¡¼¥ë¥Ð¥Ã¥¯¤Ë¤ª¤¤¤Æ¡¤¥³¡¼¥ë¥Ð¥Ã¥¯½èÍý¤òŬÀÚ¤ËÃæ
@@ -553,5 +572,8 @@ require "tcltklib" ¤¹¤ë¤È, °Ê²¼¤Î¥â¥¸¥å¡¼¥ë, ¥¯¥é¥¹¤¬ÍøÍѲÄǽ¤Ç¤¹.
: ¥É¤òÊÖ¤¹É¬Íפ¬¤¢¤ë¡¥Ruby ¤Î¼ê³¤­¤¬ÉáÄ̤ËÃͤòÊÖ¤¹¤Î¤Ç¤Ï¡¤¤½¤ì¤¬Éá
: Ä̤ÎÌá¤êÃͤǤ¢¤ë¤Î¤«Èݤ«¤ò¶èÊ̤¬¤Ç¤­¤Ê¤¤¤¿¤á¡¤Î㳰ȯÀ¸¤òÍøÍѤ·¤¿
: ¼ÂÁõ¤ò¹Ô¤Ã¤Æ¤¤¤ë¡¥
+ : ¤¿¤À¤·¸½ºß¤Ç¤Ï¡¤¥³¡¼¥ë¥Ð¥Ã¥¯¼ê³¤­¤ò Ruby ¤Î break, next ¤Ç½ªÎ»¤¹
+ : ¤ë¤³¤È¤ÇƱÅù¤Î·ë²Ì¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤ë¡¥¤½¤ì¤æ¤¨¡¤
+ : ¤³¤ì¤é¤ÏɬÍפʤ¤¤â¤Î¤Ç¤Ï¤¢¤ë¤¬¡¤¸ß´¹À­¤Î¤¿¤á¤Ë»Ä¤·¤Æ¤¢¤ë¡¥
(eof)
diff --git a/ext/tk/README.1st b/ext/tk/README.1st
index df6c819d26..fce5b0242b 100644
--- a/ext/tk/README.1st
+++ b/ext/tk/README.1st
@@ -1,7 +1,6 @@
If you want to use Ruby/Tk (tk.rb and so on), you must have tcltklib.so
-which is working correctly. If you fail to call 'require "tcltklib"',
-you may not have tcltklib.so. When you have some troubles on compiling
-tcltklib, please read README files on tcltklib.
+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.
@@ -9,11 +8,9 @@ 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 ¤¬¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Æ¤¤¤Ê¤¤¤Î¤«¤â¤·¤ì¤Þ¤»¤ó¡¥tcltklib ¤Î
-¥³¥ó¥Ñ¥¤¥ë»þ¤Ë²¿¤«ÌäÂ꤬À¸¤¸¤Æ¤¤¤ë¾ì¹ç¤Ï¡¤tcltklib ¤Î README ¥Õ¥¡¥¤¥ë
-¤ò¸«¤Æ¤¯¤À¤µ¤¤¡¥
+Ruby/Tk (tk.rb ¤Ê¤É) ¤ò»È¤¤¤¿¤¤¾ì¹ç¤Ë¤Ï¡¤tcltklib.so ¤¬Àµ¤·¤¯Æ°¤¤¤Æ¤¤¤Ê
+¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó¡¥¥³¥ó¥Ñ¥¤¥ë»þ¤Ë²¿¤«ÌäÂ꤬À¸¤¸¤¿¾ì¹ç¤Ï¡¤README.tcltklib
+¤ä README.ActiveTcl ¤ò¸«¤Æ¤¯¤À¤µ¤¤¡¥
¤¿¤È¤¨ Ruby ¤Î¥é¥¤¥Ö¥é¥ê¥Ç¥£¥ì¥¯¥È¥ê¤Ë tcltklib.so ¤¬Â¸ºß¤·¤Æ¤¤¤¿¤È¤·¤Æ
¤â¡¤¼Â¹Ô´Ä¶­¤Ë Tcl/Tk ¥é¥¤¥Ö¥é¥ê (libtcl8.4.so ¤Ê¤É) ¤¬¤Ê¤±¤ì¤Ðµ¡Ç½¤·¤Þ
¤»¤ó¡¥Tcl/Tk ¤¬Àµ¤·¤¯¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Æ¤¤¤ë¤«¤â¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡¥
diff --git a/ext/tk/README.tcltklib b/ext/tk/README.tcltklib
index e939ba1f51..8c6dd5178f 100644
--- a/ext/tk/README.tcltklib
+++ b/ext/tk/README.tcltklib
@@ -5,10 +5,14 @@ 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)
+ --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"
@@ -16,18 +20,18 @@ some or all of the following options.
--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-include=<dir> the directry contains 'tcl.h'
+ --with-tk-include=<dir> the directry contains 'tk.h'
- --with-tcl-lib=<dir> the directry containts 'libtcl<version>.so'
- --with-tk-lib=<dir> the directry containts 'libtk<version>.so'
+ --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 containts 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.
@@ -46,8 +50,8 @@ some or all of the following options.
--with-X11-dir=<path>
equal to "--with-X11-include=<path>/include --with-X11-lib=<path>/lib"
- --with-X11-include=<dir> the directry contains X11 header files
- --with-X11-lib=<dir> the directry contains X11 libraries
+ --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
diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb
index 5ed86a8b76..4807ea7b40 100644
--- a/ext/tk/extconf.rb
+++ b/ext/tk/extconf.rb
@@ -2,7 +2,8 @@
require 'mkmf'
-is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM)
+#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)
@@ -39,18 +40,68 @@ unless is_win32
have_library("m", "log")
end
-dir_config("tk")
-dir_config("tcl")
-dir_config("X11")
+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 find_tcl(tcllib, stubs)
- paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+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"
@@ -58,22 +109,42 @@ def find_tcl(tcllib, stubs)
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
- find_library(tcllib, func, *paths)
- elsif find_library(lib, func, *paths)
- true
+ st = find_library(tcllib, func, *paths)
else
- %w[8.5 8.4 8.3 8.2 8.1 8.0 7.6].find { |ver|
- find_library("#{lib}#{ver}", func, *paths) or
- find_library("#{lib}#{ver.delete('.')}", func, *paths) or
- find_library("tcl#{ver}", func, *paths) or
- find_library("tcl#{ver.delete('.')}", func, *paths)
- }
+ 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)
- paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+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"
@@ -81,20 +152,45 @@ def find_tk(tklib, stubs)
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
- find_library(tklib, func, *paths)
- elsif find_library(lib, func, *paths)
- true
+ st = find_library(tklib, func, *paths)
else
- %w[8.5 8.4 8.3 8.2 8.1 8.0 4.2].find { |ver|
- find_library("#{lib}#{ver}", func, *paths) or
- find_library("#{lib}#{ver.delete('.')}", func, *paths) or
- find_library("tk#{ver}", func, *paths) or
- find_library("tk#{ver.delete('.')}", func, *paths)
- }
+ 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
@@ -273,13 +369,13 @@ EOF
end
end
-if tcltk_framework ||
- (have_header("tcl.h") && have_header("tk.h") &&
- ( !use_X || find_library("X11", "XOpenDisplay",
- "/usr/X11/lib", "/usr/lib/X11",
- "/usr/X11R6/lib", "/usr/openwin/lib")) &&
- find_tcl(tcllib, stubs) &&
- find_tk(tklib, stubs))
+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
@@ -306,7 +402,11 @@ if tcltk_framework ||
$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/multi-tk.rb b/ext/tk/lib/multi-tk.rb
index 78ed1aa6ee..ec718678f0 100644
--- a/ext/tk/lib/multi-tk.rb
+++ b/ext/tk/lib/multi-tk.rb
@@ -114,7 +114,14 @@ MultiTkIp_OK.freeze
class MultiTkIp
BASE_DIR = File.dirname(__FILE__)
- @@SLAVE_IP_ID = ['slave'.freeze, '0'.taint].freeze
+ 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)
@@ -126,14 +133,18 @@ class MultiTkIp
unless defined?(@@TK_CMD_TBL)
@@TK_CMD_TBL = Object.new.taint
- @@TK_CMD_TBL.instance_variable_set('@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?',
+ '__send__', '__id__', 'freeze', 'inspect', 'kind_of?', 'object_id',
'[]', '[]=', 'delete', 'each', 'has_key?'
]
- instance_methods.each{|m| undef_method(m) unless allow.index(m)}
+ instance_methods.each{|m| undef_method(m) unless allow.index(m.to_s)}
def kind_of?(klass)
@tbl.kind_of?(klass)
@@ -206,7 +217,7 @@ class MultiTkIp
def initialize(ip, cmd)
@ip = ip
@cmd = cmd
- freeze
+ self.freeze
end
attr_reader :ip, :cmd
def inspect
@@ -573,7 +584,11 @@ class MultiTkIp
# raise exception
begin
bt = _toUTF8(e.backtrace.join("\n"))
- bt.instance_variable_set(:@encoding, 'utf-8')
+ 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
@@ -695,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
@@ -723,7 +743,41 @@ class MultiTkIp
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
@@ -853,22 +907,26 @@ class MultiTkIp
Thread.new{
current = Thread.current
loop {
- mtx, ret, table, script = @init_ip_env_queue.deq
- begin
+ 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.unlock
+ mtx.synchronize{ cond.signal }
end
+ mtx = cond = ret = table = script = nil # clear variables for GC
}
}
def self.__init_ip_env__(table, script)
ret = []
- mtx = Mutex.new.lock
- @init_ip_env_queue.enq([mtx, ret, table, script])
- mtx.lock
+ 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
@@ -947,9 +1005,11 @@ class MultiTkIp
private :_parse_slaveopts
def _create_slave_ip_name
- name = @@SLAVE_IP_ID.join('')
- @@SLAVE_IP_ID[1].succ!
- name.freeze
+ @@SLAVE_IP_ID.mutex.synchronize{
+ name = @@SLAVE_IP_ID.join('')
+ @@SLAVE_IP_ID[1].succ!
+ name.freeze
+ }
end
private :_create_slave_ip_name
@@ -1206,7 +1266,20 @@ class MultiTkIp
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
@@ -1221,6 +1294,8 @@ class MultiTkIp
@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]
@@ -1229,6 +1304,8 @@ class MultiTkIp
end
else
@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]
@@ -1263,11 +1340,11 @@ class MultiTkIp
@@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
@@ -1345,8 +1422,13 @@ class << MultiTkIp
alias __new new
private :__new
-
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)
@@ -1563,8 +1645,13 @@ class MultiTkIp
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
}
}
@@ -1614,11 +1701,16 @@ class MultiTkIp
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
@@ -2338,6 +2430,11 @@ end
class MultiTkIp
def mainloop(check_root = true, restart_on_dead = true)
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
@@ -2746,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
@@ -3187,15 +3285,44 @@ end
# encoding convert
+class << MultiTkIp
+ def encoding_table
+ __getip.encoding_table
+ end
+end
class MultiTkIp
- def encoding
+ def encoding_table
+ @interp.encoding_table
+ end
+
+ def force_default_encoding=(mode)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.encoding
+ @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 default_encoding=(enc)
+ raise SecurityError, "no permission to manipulate" unless self.manipulable?
+ @interp.default_encoding = enc
+ end
+
def encoding=(enc)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@interp.encoding = enc
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 encoding_convertfrom(str, enc=None)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
@@ -3212,13 +3339,30 @@ 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_variable_get
undef_method :instance_variable_set
end
-
-
# end of MultiTkIp definition
# defend against modification
diff --git a/ext/tk/lib/tcltk.rb b/ext/tk/lib/tcltk.rb
index 1a6694dbff..7f6f41605d 100644
--- a/ext/tk/lib/tcltk.rb
+++ b/ext/tk/lib/tcltk.rb
@@ -265,7 +265,7 @@ class TclTkWidget < TclTkCommand
# (used in TclTkInterpreter#initialize())
# need two arguments
- fail("illegal # of parameter") if args.size != 2
+ fail("invalid # of parameter") if args.size != 2
# ip: interpreter(TclTkIp)
# exp: tcl/tk representation
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index 32b5e20bc5..c5d5b804d2 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -1,6 +1,5 @@
#
# tk.rb - Tk interface module using tcltklib
-# $Date$
# by Yukihiro Matsumoto <matz@netlab.jp>
# use Shigehiro's tcltklib
@@ -10,6 +9,9 @@ require 'tkutil'
# autoload
require 'tk/autoload'
+# for Mutex
+require 'thread'
+
class TclTkIp
# backup original (without encoding) _eval and _invoke
alias _eval_without_enc _eval
@@ -37,7 +39,12 @@ module TkComm
#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
@@ -218,7 +225,9 @@ module TkComm
TkCore::INTERP.tk_windows[val]?
TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
when /\Ai(_\d+_)?\d+\z/
- TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ TkImage::Tk_IMGTBL.mutex.synchronize{
+ TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ }
when /\A-?\d+\.?\d*(e[-+]?\d+)?\z/
val.to_f
when /\\ /
@@ -335,6 +344,8 @@ if USE_TCLs_LIST_FUNCTIONS
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
@@ -347,11 +358,20 @@ if USE_TCLs_LIST_FUNCTIONS
if sys_enc && dst_enc
dst.map!{|s| _toUTF8(s)}
ret = TkCore::INTERP._merge_tklist(*dst)
- 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')
+ 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
@@ -411,46 +431,6 @@ else
tk_split_sublist(token, depth - 1)
}
end
-=begin
- def tk_split_list(str)
- 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
- escape = false
- brace = 1
- str.each_byte {|c|
- i += 1
- brace += 1 if c == ?{ && !escape
- brace -= 1 if c == ?} && !escape
- escape = (c == ?\\)
- break if brace == 0
- }
- if str.size == i + 1
- return tk_split_list(str[0, i])
- end
- if str[0, i] == ' '
- list.push ' '
- else
- list.push tk_split_list(str[0, i])
- end
- list += tk_split_list(str[i+1..-1])
- list
- end
-=end
def tk_split_simplelist(str, src_enc=true, dst_enc=true)
return [] if str == ""
@@ -601,7 +581,9 @@ end
end
def image_obj(val)
if val =~ /^i(_\d+_)?\d+$/
- TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ TkImage::Tk_IMGTBL.mutex.synchronize{
+ TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ }
else
val
end
@@ -783,15 +765,17 @@ end
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')
@@ -810,6 +794,15 @@ end
@cmdtbl = [] unless defined? @cmdtbl
@cmdtbl.taint unless @cmdtbl.tainted?
@cmdtbl.push 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
@@ -817,14 +810,30 @@ end
'rb_out' << TkCore::INTERP._ip_id_ << ' ' << id
end
end
- def uninstall_cmd(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, :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)
@@ -856,8 +865,10 @@ end
return TkCore::INTERP.tk_windows[@path] = self
end
else
- name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
- Tk_IDs[1].succ!
+ Tk_IDs.mutex.synchronize{
+ name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
+ Tk_IDs[1].succ!
+ }
end
if !ppath or ppath == '.'
@path = '.' + name
@@ -936,7 +947,12 @@ module TkComm
def _bindinfo(what, context=nil)
if context
- tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]) .collect {|cmdline|
+ 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]
@@ -1082,6 +1098,14 @@ 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
@@ -1099,14 +1123,49 @@ module TkCore
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"
@@ -1157,6 +1216,10 @@ module TkCore
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)
@@ -1235,7 +1298,7 @@ module TkCore
}) << ' %W')
INTERP.add_tk_procs(TclTkLib::FINALIZE_PROC_NAME, '',
- "bind all <#{WIDGET_DESTROY_HOOK}> {}")
+ "catch { bind all <#{WIDGET_DESTROY_HOOK}> {} }")
INTERP.add_tk_procs('rb_out', 'ns args', <<-'EOL')
if [regexp {^::} $ns] {
@@ -1342,7 +1405,11 @@ module TkCore
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
+ 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" +
@@ -1398,6 +1465,13 @@ module TkCore
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
@@ -1420,8 +1494,16 @@ module TkCore
# tk_call("after",ms,cmdid)
# end
end
+=end
def after_idle(cmd=Proc.new)
+ 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
@@ -1432,9 +1514,15 @@ module TkCore
tk_call_without_enc('after','idle',cmdid)
end
+=end
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
+ afterId
end
def windowingsystem
@@ -1554,7 +1642,27 @@ 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?
@@ -1562,7 +1670,12 @@ module TkCore
# nil : there is no mainloop
# false : mainloop is running on the other thread
# ( At then, it is dangerous to call Tk interpreter directly. )
- TclTkLib.mainloop_thread?
+ 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?
@@ -1914,7 +2027,7 @@ module Tk
end
def root
- TkRoot.new
+ Tk::Root.new
end
def Tk.load_tclscript(file, enc=nil)
@@ -2030,6 +2143,27 @@ module Tk
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.wakeup(id)
+ ((id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s)).value = 0
+ nil
+ end
+
+ ################################################
+
def Tk.pack(*args)
TkPack.configure(*args)
end
@@ -2205,16 +2339,432 @@ end
# convert kanji string to/from utf-8
###########################################
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
+
+ #############################################
+
+ if TkCore::WITH_ENCODING ### Ruby 1.9
+ RubyEncoding = ::Encoding
+
+ # 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
+
+ BINARY = RubyEncoding.find(BINARY_NAME)
+ UNKNOWN = RubyEncoding.find('ASCII-8BIT')
+
+ ### start of creating ENCODING_TABLE
+ ENCODING_TABLE = TkCore::INTERP.encoding_table
+=begin
+ ENCODING_TABLE = {
+ 'binary' => BINARY,
+ # 'UNKNOWN-8BIT' => UNKNOWN,
+ }
+
+ 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
+
+ end
+
+ #############################################
+
+ if TkCore::WITH_ENCODING
+ ################################
+ ### Ruby 1.9
+ ################################
+ def force_default_encoding(mode)
+ TkCore::INTERP.force_default_encoding = mode
+ end
+
+ def force_default_encoding?
+ TkCore::INTERP.force_default_encoding?
+ end
+
+ def default_encoding=(enc)
+ TkCore::INTERP.default_encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ end
+
+ def encoding=(enc)
+ TkCore::INTERP.encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ end
+
+ 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_system=(enc)
+ TclTkLib.encoding_system = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ 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
+
+ ################################
+ else
+ ################################
+ ### Ruby 1.8-
+ ################################
+ def force_default_encoding=(mode)
+ true
+ end
+
+ def force_default_encoding?
+ true
+ end
+
+ def default_encoding=(enc)
+ TkCore::INTERP.default_encoding = enc
+ end
+
+ def encoding=(enc)
+ TkCore::INTERP.encoding = enc
+ end
+
+ def encoding_obj
+ TkCore::INTERP.encoding
+ end
+ def encoding_name
+ TkCore::INTERP.encoding
+ end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
+
+ 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
+
+ def encoding_system=(enc)
+ TclTkLib.encoding_system = enc
+ end
+
+ def encoding_system_name
+ TclTkLib.encoding_system
+ end
+ def encoding_system_obj
+ TclTkLib.encoding_system
+ end
+ alias encoding_system encoding_system_name
+
+ ################################
+ 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
+
+ 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 encoding_dirs
+ # Tcl8.5 feature
+ TkComm.simplelist(Tk.tk_call_without_enc('encoding', 'dirs'))
+ 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
+
+ extend Encoding
+ end
+
class TclTkIp
+ def force_default_encoding=(mode)
+ @force_default_encoding = (mode)? true: false
+ end
+
+ def force_default_encoding?
+ @force_default_encoding ||= false
+ end
+
+ def default_encoding=(name)
+ name = name.name if name.kind_of?(::Encoding) if Tk::WITH_ENCODING
+ @encoding = name
+ end
+
# from tkencoding.rb by ttate@jaist.ac.jp
- attr_accessor :encoding
+ #attr_accessor :encoding
+ def encoding=(name)
+ self.force_default_encoding = true # for comaptibility
+ self.default_encoding = name
+ end
- alias __eval _eval
- alias __invoke _invoke
+ def encoding_name
+ (@encoding)? @encoding.dup: nil
+ end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
+
+ 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
+
+ enc_name ||= str.instance_variable_get(:@encoding)
+
+ enc_name ||=
+ Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil
+
+ 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
+
+ #enc_name ||=
+ # Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding) rescue nil
+ enc_name ||= Tk::Encoding::ENCODING_TABLE.get_name(nil)
+
+ # is 'binary' encoding?
+ if enc_name == Tk::Encoding::BINARY_NAME
+ return str.dup.force_encoding(Tk::Encoding::BINARY_NAME)
+ end
+
+ # 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
+
+ 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
+
+ # 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
+ # without Encoding (Ruby 1.8)
+ def _toUTF8(str, encoding = nil)
+ __toUTF8(str, encoding)
+ end
+ def _fromUTF8(str, encoding = nil)
+ __fromUTF8(str, encoding)
+ end
+ ###
+ end
+
+ alias __eval _eval
+ alias __invoke _invoke
+
+ def _eval(cmd)
+ _fromUTF8(__eval(_toUTF8(cmd)))
+ end
+
+ def _invoke(*cmds)
+ _fromUTF8(__invoke(*(cmds.collect{|cmd| _toUTF8(cmd)})))
+ end
+
+ alias _eval_with_enc _eval
+ alias _invoke_with_enc _invoke
+
=begin
#### --> definition is moved to TclTkIp module
@@ -2264,17 +2814,6 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
end
=end
- def _eval(cmd)
- _fromUTF8(__eval(_toUTF8(cmd)))
- end
-
- def _invoke(*cmds)
- _fromUTF8(__invoke(*(cmds.collect{|cmd| _toUTF8(cmd)})))
- end
-
- alias _eval_with_enc _eval
- alias _invoke_with_enc _invoke
-
=begin
def _eval(cmd)
if defined?(@encoding) && @encoding != 'utf-8'
@@ -2331,127 +2870,214 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
module TclTkLib
class << self
- alias _encoding encoding
- alias _encoding= encoding=
- def encoding=(name)
- TkCore::INTERP.encoding = name
+ def force_default_encoding=(mode)
+ TkCore::INTERP.force_default_encoding = mode
end
- def encoding
- TkCore::INTERP.encoding
- end
- end
- end
- module Tk
- module Encoding
- extend Encoding
+ def force_default_encoding?
+ TkCore::INTERP.force_default_encoding?
+ end
- TkCommandNames = ['encoding'.freeze].freeze
+ def default_encoding=(name)
+ TkCore::INTERP.default_encoding = name
+ 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 encoding
+ def encoding_name
TkCore::INTERP.encoding
end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
- def encoding_names
- TkComm.simplelist(Tk.tk_call('encoding', 'names'))
+ def encoding_obj
+ if Tk::WITH_ENCODING
+ Tk::Encoding.tcl2rb_encoding(TkCore::INTERP.encoding)
+ else
+ TkCore::INTERP.encoding
+ end
end
+ end
+ end
- def encoding_system
- Tk.tk_call('encoding', 'system')
+ # 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
+ 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
-
- def encoding_system=(enc)
- Tk.tk_call('encoding', 'system', enc)
+ 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
-
- def encoding_convertfrom(str, enc=nil)
- # str is an usual enc string or a Tcl's internal string expression
- # in enc (which is returned from 'encoding_convertto' method).
- # the return value is a UTF-8 string.
- enc = encoding_system unless enc
- ret = TkCore::INTERP.__invoke('encoding', 'convertfrom', enc, str)
- ret.instance_variable_set('@encoding', 'utf-8')
- ret
+ begin
+ Tk.encoding = Tk.encoding_system
+ rescue StandardError, NameError
+ Tk.encoding = 'utf-8'
+ Tk.encoding_system = 'utf-8'
end
- alias encoding_convert_from encoding_convertfrom
+ end
- def encoding_convertto(str, enc=nil)
- # str must be a UTF-8 string.
- # The return value is a Tcl's internal string expression in enc.
- # To get an usual enc string, use Tk.fromUTF8(ret_val, enc).
- enc = encoding_system unless enc
- ret = TkCore::INTERP.__invoke('encoding', 'convertto', enc, str)
- ret.instance_variable_set('@encoding', 'binary')
- ret
- end
- alias encoding_convert_to encoding_convertto
+ 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 encoding_dirs
- # Tcl8.5 feature
- TkComm.simplelist(Tk.tk_call_without_enc('encoding', 'dirs'))
+=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
+ tk_enc_name = ext_enc_obj.name
+ tksys_enc_name = ext_enc_obj.name
+ 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)
+ # Tk.encoding = tk_enc_name
+ Tk.default_encoding = tk_enc_name
+ Tk.encoding_system = tksys_enc_name
+=end
+
+ 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
+ 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
+ Tk.encoding_system = ext_enc_name
+ else
+ # use Tk.encoding_system
+ end
+ rescue ArgumentError
+ # unsupported encoding on Tk -> use Tk.encoding_system
end
end
- extend Encoding
- end
+ # setup Tk.encoding
+ enc_name = nil
- # estimate encoding
- case $KCODE
- when /^e/i # EUC
- Tk.encoding = 'euc-jp'
- Tk.encoding_system = 'euc-jp'
- when /^s/i # SJIS
begin
- if Tk.encoding_system == 'cp932'
- Tk.encoding = 'cp932'
- else
- Tk.encoding = 'shiftjis'
- Tk.encoding_system = 'shiftjis'
+ 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 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
+ rescue NameError
+ # ignore
+ enc_name = nil
+ rescue ArgumentError
+ enc_name = nil
+ fail ArgumentError,
+ "DEFAULT_TK_ENCODING has an unknown encoding #{default_def}"
end
- begin
- Tk.encoding = Tk.encoding_system
- rescue StandardError, NameError
- Tk.encoding = 'utf-8'
- Tk.encoding_system = 'utf-8'
+
+ 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
end
+
+ Tk.default_encoding = (enc_name)? enc_name: tksys_enc_name
end
else
# dummy methods
- class TclTkIp
- attr_accessor :encoding
-
- alias __eval _eval
- alias __invoke _invoke
-
- alias _eval_with_enc _eval
- alias _invoke_with_enc _invoke
- end
-
module Tk
module Encoding
extend Encoding
+ def force_default_encoding=(mode)
+ nil
+ end
+
+ def force_default_encoding?
+ nil
+ end
+
+ def default_encoding=(enc)
+ nil
+ end
+ def default_encoding
+ nil
+ end
+
def encoding=(name)
nil
end
@@ -2487,6 +3113,16 @@ else
extend Encoding
end
+
+ class TclTkIp
+ attr_accessor :encoding
+
+ alias __eval _eval
+ alias __invoke _invoke
+
+ alias _eval_with_enc _eval
+ alias _invoke_with_enc _invoke
+ end
end
@@ -2609,7 +3245,15 @@ module TkTreatFont
next
else
fnt = hash_kv(fnt) if fnt.kind_of?(Hash)
- tk_call(*(__config_cmd << "-#{optkey}" << fnt))
+ 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
@@ -2663,7 +3307,15 @@ module TkTreatFont
fobj = fontobj # create a new TkFont object
else
ltn = hash_kv(ltn) if ltn.kind_of?(Hash)
- tk_call(*(__config_cmd << "-#{optkey}" << ltn))
+ 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
@@ -2715,7 +3367,15 @@ module TkTreatFont
fobj = fontobj # create a new TkFont object
else
knj = hash_kv(knj) if knj.kind_of?(Hash)
- tk_call(*(__config_cmd << "-#{optkey}" << knj))
+ 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
@@ -2816,6 +3476,14 @@ module TkConfigMethod
include TkUtil
include TkTreatFont
+ def TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ @mode || false
+ end
+ def TkConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode)
+ fail SecurityError, "can't change the mode" if $SAFE>=4
+ @mode = (mode)? true: false
+ end
+
def __cget_cmd
[self.path, 'cget']
end
@@ -2837,6 +3505,11 @@ module TkConfigMethod
end
private :__configinfo_struct
+ def __optkey_aliases
+ {}
+ end
+ private :__optkey_aliases
+
def __numval_optkeys
[]
end
@@ -2943,7 +3616,7 @@ module TkConfigMethod
val
end
- def cget(slot)
+ def __cget_core(slot)
orig_slot = slot
slot = slot.to_s
@@ -2951,6 +3624,11 @@ module TkConfigMethod
fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
end
+ alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
if ( method = _symbolkey2str(__val2ruby_optkeys())[slot] )
optval = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
begin
@@ -3019,11 +3697,41 @@ module TkConfigMethod
tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true)
end
end
+ private :__cget_core
- def configure(slot, value=None)
+ def cget(slot)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __cget_core(slot)
+ else
+ 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 cget_strict(slot)
+ # never use TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __cget_core(slot)
+ end
+
+ def __configure_core(slot, value=None)
if slot.kind_of? Hash
slot = _symbolkey2str(slot)
+ __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
+ }
+
__methodcall_optkeys.each{|key, method|
value = slot.delete(key.to_s)
self.__send__(method, value) if value
@@ -3060,6 +3768,11 @@ module TkConfigMethod
fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
end
+ alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
+ if real_name
+ slot = real_name.to_s
+ end
+
if ( conf = __keyonly_optkeys.find{|k, v| k.to_s == slot} )
defkey, undefkey = conf
if value
@@ -3083,12 +3796,55 @@ module TkConfigMethod
end
self
end
+ private :__configure_core
+
+ def __check_available_configure_options(keys)
+ availables = self.current_configinfo.keys
+
+ # 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}
+
+ keys = _symbolkey2str(keys)
+ keys.delete_if{|k, v| !(availables.include?(k))}
+ 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
+ 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
+ self
+ end
def configure_cmd(slot, value)
configure(slot, install_cmd(value))
end
- def configinfo(slot = nil)
+ def __configinfo_core(slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if (slot &&
slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
@@ -3099,6 +3855,10 @@ module TkConfigMethod
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 \
@@ -3110,6 +3870,12 @@ module TkConfigMethod
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]
@@ -3435,6 +4201,11 @@ module TkConfigMethod
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
@@ -3459,6 +4230,10 @@ module TkConfigMethod
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] \
@@ -3474,6 +4249,12 @@ module TkConfigMethod
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]
@@ -3806,6 +4587,11 @@ module TkConfigMethod
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
@@ -3820,6 +4606,19 @@ module TkConfigMethod
end
end
end
+ private :__configinfo_core
+
+ 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
+ __configinfo_core(slot)
+ end
+ end
def current_configinfo(slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
@@ -3919,7 +4718,12 @@ class TkObject<TkKernel
begin
cget(name)
rescue
- super(id, *args)
+ 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
@@ -3974,6 +4778,15 @@ 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),
@@ -4037,6 +4850,13 @@ class TkWindow<TkObject
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)
@@ -4069,13 +4889,48 @@ class TkWindow<TkObject
end
if keys and keys != None
- tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ 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
@@ -4197,6 +5052,15 @@ class TkWindow<TkObject
self
end
+ 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)
@@ -4228,12 +5092,14 @@ class TkWindow<TkObject
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))
TkGrid.rowconfigure(self, index, keys)
end
alias grid_rowconfigure grid_rowconfig
+ alias grid_row grid_rowconfig
def grid_columnconfiginfo(index, slot=nil)
#if slot
@@ -4476,11 +5342,13 @@ class TkWindow<TkObject
end
children.each{|path, obj|
- if defined?(@cmdtbl)
- for id in @cmdtbl
- uninstall_cmd id
+ obj.instance_eval{
+ if defined?(@cmdtbl)
+ for id in @cmdtbl
+ uninstall_cmd id
+ end
end
- end
+ }
TkCore::INTERP.tk_windows.delete(path)
}
@@ -4585,7 +5453,7 @@ class TkWindow<TkObject
bindtags(bindtags().unshift(tag))
end
end
-
+TkWidget = TkWindow
# freeze core modules
#TclTkLib.freeze
@@ -4598,7 +5466,7 @@ end
#Tk.freeze
module Tk
- RELEASE_DATE = '2007-01-26'.freeze
+ RELEASE_DATE = '2008-05-23'.freeze
autoload :AUTO_PATH, 'tk/variable'
autoload :TCL_PACKAGE_PATH, 'tk/variable'
diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb
index 6b3773f4ea..0773f7708d 100644
--- a/ext/tk/lib/tk/autoload.rb
+++ b/ext/tk/lib/tk/autoload.rb
@@ -1,9 +1,19 @@
#
# 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
@@ -14,19 +24,117 @@ autoload :TkPlace, 'tk/place'
def TkPlace(*args); TkPlace.configure(*args); end
-#######################
-# others
+############################################
+# 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 :TkButton, 'tk/button'
-
autoload :TkConsole, 'tk/console'
-autoload :TkCanvas, 'tk/canvas'
+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'
@@ -36,9 +144,6 @@ autoload :TkcTagAll, 'tk/canvastag'
autoload :TkcTagCurrent, 'tk/canvastag'
autoload :TkcTagGroup, 'tk/canvastag'
-autoload :TkCheckButton, 'tk/checkbutton'
-autoload :TkCheckbutton, 'tk/checkbutton'
-
autoload :TkClipboard, 'tk/clipboard'
autoload :TkComposite, 'tk/composite'
@@ -52,14 +157,10 @@ autoload :TkWarning, 'tk/dialog'
autoload :TkWarning2, 'tk/dialog'
autoload :TkWarningObj, 'tk/dialog'
-autoload :TkEntry, 'tk/entry'
-
autoload :TkEvent, 'tk/event'
autoload :TkFont, 'tk/font'
-autoload :TkTreatTagFont, 'tk/font'
-
-autoload :TkFrame, 'tk/frame'
+autoload :TkNamedFont, 'tk/font'
autoload :TkImage, 'tk/image'
autoload :TkBitmapImage, 'tk/image'
@@ -71,30 +172,12 @@ autoload :TkTreatItemFont, 'tk/itemfont'
autoload :TkKinput, 'tk/kinput'
-autoload :TkLabel, 'tk/label'
-
-autoload :TkLabelFrame, 'tk/labelframe'
-autoload :TkLabelframe, 'tk/labelframe'
-
-autoload :TkListbox, 'tk/listbox'
-
-autoload :TkMacResource, 'tk/macpkg'
-
-autoload :TkMenu, 'tk/menu'
-autoload :TkMenuClone, 'tk/menu'
autoload :TkSystemMenu, 'tk/menu'
-autoload :TkSysMenu_Help, 'tk/menu'
-autoload :TkSysMenu_System, 'tk/menu'
-autoload :TkSysMenu_Apple, 'tk/menu'
-autoload :TkMenubutton, 'tk/menu'
-autoload :TkOptionMenubutton, 'tk/menu'
autoload :TkMenubar, 'tk/menubar'
autoload :TkMenuSpec, 'tk/menuspec'
-autoload :TkMessage, 'tk/message'
-
autoload :TkManageFocus, 'tk/mngfocus'
autoload :TkMsgCatalog, 'tk/msgcat'
@@ -110,53 +193,46 @@ autoload :TkPackage, 'tk/package'
autoload :TkPalette, 'tk/palette'
-autoload :TkPanedWindow, 'tk/panedwindow'
-autoload :TkPanedwindow, 'tk/panedwindow'
-
-autoload :TkRadioButton, 'tk/radiobutton'
-autoload :TkRadiobutton, 'tk/radiobutton'
-
autoload :TkRoot, 'tk/root'
-autoload :TkScale, 'tk/scale'
-
-autoload :TkScrollbar, 'tk/scrollbar'
-autoload :TkXScrollbar, 'tk/scrollbar'
-autoload :TkYScrollbar, 'tk/scrollbar'
-
autoload :TkScrollbox, 'tk/scrollbox'
autoload :TkSelection, 'tk/selection'
-autoload :TkSpinbox, 'tk/spinbox'
-
autoload :TkTreatTagFont, 'tk/tagfont'
-autoload :TkText, 'tk/text'
-
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 :TkToplevel, 'tk/toplevel'
-
autoload :TkTextWin, 'tk/txtwin_abst'
autoload :TkValidation, 'tk/validation'
+autoload :TkValidateCommand, 'tk/validation'
autoload :TkVariable, 'tk/variable'
autoload :TkVarAccess, 'tk/variable'
@@ -166,31 +242,173 @@ autoload :TkNamedVirtualEvent,'tk/virtevent'
autoload :TkWinfo, 'tk/winfo'
-autoload :TkWinDDE, 'tk/winpkg'
-autoload :TkWinRegistry, 'tk/winpkg'
-
autoload :TkXIM, 'tk/xim'
-#######################
-# sub-module of Tk
+############################################
+# toplevel classes/modules (switchable)
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'
+ @TOPLEVEL_ALIAS_TABLE = {}
+ @TOPLEVEL_ALIAS_TABLE[:Tk] = {
+ :TkButton => 'tk/button',
- autoload :ValidateConfigure, 'tk/validation'
- autoload :ItemValidateConfigure, 'tk/validation'
+ :TkCanvas => 'tk/canvas',
- autoload :EncodedString, 'tk/encodedstr'
- def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end
+ :TkCheckButton => 'tk/checkbutton',
+ :TkCheckbutton => 'tk/checkbutton',
- autoload :BinaryString, 'tk/encodedstr'
- def Tk.BinaryString(str); Tk::BinaryString.new(str); end
+ # :TkDialog => 'tk/dialog',
+ # :TkDialog2 => 'tk/dialog',
+ # :TkDialogObj => 'tk/dialog',
+ # :TkWarning => 'tk/dialog',
+ # :TkWarning2 => 'tk/dialog',
+ # :TkWarningObj => 'tk/dialog',
- autoload :UTF8_String, 'tk/encodedstr'
- def Tk.UTF8_String(str); Tk::UTF8_String.new(str); end
+ :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/bindtag.rb b/ext/tk/lib/tk/bindtag.rb
index 9023a08e06..88c8367a88 100644
--- a/ext/tk/lib/tk/bindtag.rb
+++ b/ext/tk/lib/tk/bindtag.rb
@@ -8,30 +8,64 @@ class TkBindTag
#BTagID_TBL = {}
BTagID_TBL = TkCore::INTERP.create_table
- Tk_BINDTAG_ID = ["btag".freeze, "00000".taint].freeze
- TkCore::INTERP.init_ip_env{ BTagID_TBL.clear }
+ (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[id]? BTagID_TBL[id]: id
+ BTagID_TBL.mutex.synchronize{
+ (BTagID_TBL[id])? BTagID_TBL[id]: id
+ }
end
+=begin
def TkBindTag.new_by_name(name, *args, &b)
- return BTagID_TBL[name] if BTagID_TBL[name]
+ BTagID_TBL.mutex.synchronize{
+ return BTagID_TBL[name] if BTagID_TBL[name]
+ }
+
self.new.instance_eval{
- BTagID_TBL.delete @id
- @id = name
- BTagID_TBL[@id] = self
+ 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)
- # @id = Tk_BINDTAG_ID.join('')
- @id = Tk_BINDTAG_ID.join(TkCore::INTERP._ip_id_)
- Tk_BINDTAG_ID[1].succ!
- BTagID_TBL[@id] = self
+ 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
@@ -63,14 +97,37 @@ end
class TkDatabaseClass<TkBindTag
+=begin
def self.new(name, *args, &b)
- return BTagID_TBL[name] if BTagID_TBL[name]
+ 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[@id] = self
+ 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
diff --git a/ext/tk/lib/tk/button.rb b/ext/tk/lib/tk/button.rb
index 407a47c400..770a5785bb 100644
--- a/ext/tk/lib/tk/button.rb
+++ b/ext/tk/lib/tk/button.rb
@@ -4,7 +4,7 @@
require 'tk'
require 'tk/label'
-class TkButton<TkLabel
+class Tk::Button<Tk::Label
TkCommandNames = ['button'.freeze].freeze
WidgetClassName = 'Button'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -25,3 +25,6 @@ class TkButton<TkLabel
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
index c30fd79bb9..36ea008a17 100644
--- a/ext/tk/lib/tk/canvas.rb
+++ b/ext/tk/lib/tk/canvas.rb
@@ -1,6 +1,5 @@
#
# tk/canvas.rb - Tk canvas classes
-# $Date$
# by Yukihiro Matsumoto <matz@caelum.co.jp>
#
require 'tk'
@@ -40,7 +39,7 @@ module TkCanvasItemConfig
private :__item_pathname
end
-class TkCanvas<TkWindow
+class Tk::Canvas<TkWindow
include TkCanvasItemConfig
include Tk::Scrollable
@@ -169,6 +168,8 @@ class TkCanvas<TkWindow
#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 == []
@@ -186,11 +187,17 @@ class TkCanvas<TkWindow
end
def delete(*args)
- if TkcItem::CItemID_TBL[self.path]
+ 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[self.path].delete(item.id)
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl.delete(item.id)
+ }
end
}
}
@@ -573,6 +580,10 @@ class TkCanvas<TkWindow
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
@@ -581,9 +592,12 @@ class TkcItem<TkObject
CItemTypeName = nil
CItemTypeToClass = {}
+
CItemID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ CItemID_TBL.clear }
+ TkCore::INTERP.init_ip_env{
+ CItemID_TBL.mutex.synchronize{ CItemID_TBL.clear }
+ }
def TkcItem.type2class(type)
CItemTypeToClass[type]
@@ -591,8 +605,13 @@ class TkcItem<TkObject
def TkcItem.id2obj(canvas, id)
cpath = canvas.path
- return id unless CItemID_TBL[cpath]
- CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id
+ CItemID_TBL.mutex.synchronize{
+ if CItemID_TBL[cpath]
+ CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id
+ else
+ id
+ end
+ }
end
########################################
@@ -625,6 +644,13 @@ class TkcItem<TkObject
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)
@@ -658,15 +684,17 @@ class TkcItem<TkObject
########################################
def initialize(parent, *args)
- #unless parent.kind_of?(TkCanvas)
- # fail ArgumentError, "expect TkCanvas for 1st argument"
+ #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[@path] = {} unless CItemID_TBL[@path]
- CItemID_TBL[@path][@id] = self
+ 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'
@@ -687,7 +715,9 @@ class TkcItem<TkObject
def delete
@c.delete @id
- CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ }
self
end
alias remove delete
diff --git a/ext/tk/lib/tk/canvastag.rb b/ext/tk/lib/tk/canvastag.rb
index a5650ee68b..49796d80b2 100644
--- a/ext/tk/lib/tk/canvastag.rb
+++ b/ext/tk/lib/tk/canvastag.rb
@@ -63,6 +63,9 @@ module TkcTagAccess
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)
@@ -199,14 +202,26 @@ 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 }
+ (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
- return id unless CTagID_TBL[cpath]
- CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
+ 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)
@@ -215,11 +230,15 @@ class TkcTag<TkObject
#end
@c = parent
@cpath = parent.path
- # @path = @id = Tk_CanvasTag_ID.join('')
- @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_)
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- Tk_CanvasTag_ID[1].succ!
+ 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
@@ -238,7 +257,9 @@ class TkcTag<TkObject
def delete
@c.delete @id
- CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath]
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath]
+ }
self
end
alias remove delete
@@ -288,23 +309,38 @@ class TkcTag<TkObject
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)
+ 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
- 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
@@ -312,7 +348,11 @@ class TkcTagString<TkcTag
end
TkcNamedTag = TkcTagString
-class TkcTagAll<TkcTag
+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"
@@ -320,12 +360,19 @@ class TkcTagAll<TkcTag
@c = parent
@cpath = parent.path
@path = @id = 'all'
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
end
+=end
end
-class TkcTagCurrent<TkcTag
+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"
@@ -333,13 +380,21 @@ class TkcTagCurrent<TkcTag
@c = parent
@cpath = parent.path
@path = @id = 'current'
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
+ 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].freeze
+ (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)
@@ -347,11 +402,15 @@ class TkcGroup<TkcTag
#end
@c = parent
@cpath = parent.path
- # @path = @id = Tk_cGroup_ID.join('')
- @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_)
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- Tk_cGroup_ID[1].succ!
+ 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
diff --git a/ext/tk/lib/tk/checkbutton.rb b/ext/tk/lib/tk/checkbutton.rb
index d76d99c0f2..b1186a87ed 100644
--- a/ext/tk/lib/tk/checkbutton.rb
+++ b/ext/tk/lib/tk/checkbutton.rb
@@ -4,7 +4,7 @@
require 'tk'
require 'tk/radiobutton'
-class TkCheckButton<TkRadioButton
+class Tk::CheckButton<Tk::RadioButton
TkCommandNames = ['checkbutton'.freeze].freeze
WidgetClassName = 'Checkbutton'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -22,4 +22,9 @@ class TkCheckButton<TkRadioButton
self
end
end
-TkCheckbutton = TkCheckButton
+
+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/composite.rb b/ext/tk/lib/tk/composite.rb
index eaed8ed363..883d43c3ea 100644
--- a/ext/tk/lib/tk/composite.rb
+++ b/ext/tk/lib/tk/composite.rb
@@ -34,7 +34,8 @@ module TkComposite
if klass
# WidgetClassName is a known class
- if klass <= TkFrame || klass < TkComposite
+ #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
@@ -50,7 +51,8 @@ module TkComposite
else
# klass is invalid for the base frame
- if self.class < TkFrame || self.class.superclass < TkComposite
+ #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 == ''
@@ -69,7 +71,8 @@ module TkComposite
else
# no valid WidgetClassName
- if self.class < TkFrame || self.class.superclass < TkComposite
+ #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 == ''
@@ -108,8 +111,12 @@ module TkComposite
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
@@ -133,6 +140,11 @@ module TkComposite
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
@@ -169,6 +181,57 @@ module TkComposite
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
@@ -200,6 +263,7 @@ module TkComposite
super(slot)
end
+=end
def configure(slot, value=None)
if slot.kind_of? Hash
diff --git a/ext/tk/lib/tk/encodedstr.rb b/ext/tk/lib/tk/encodedstr.rb
index 797e514a4c..02de0b0d85 100644
--- a/ext/tk/lib/tk/encodedstr.rb
+++ b/ext/tk/lib/tk/encodedstr.rb
@@ -70,13 +70,89 @@ module Tk
# @encoding = ( enc ||
# ((self.class::Encoding)?
# self.class::Encoding : Tk.encoding_system) )
- @encoding = ( enc ||
- ((self.class::Encoding)?
+ enc ||= (self.class::Encoding)?
self.class::Encoding :
- ((Tk.encoding)? Tk.encoding : Tk.encoding_system) ) )
+ ((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
- attr_reader :encoding
+ 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)
diff --git a/ext/tk/lib/tk/entry.rb b/ext/tk/lib/tk/entry.rb
index 4ac3f28229..8ce8def1e7 100644
--- a/ext/tk/lib/tk/entry.rb
+++ b/ext/tk/lib/tk/entry.rb
@@ -1,6 +1,5 @@
#
# tk/entry.rb - Tk entry classes
-# $Date$
# by Yukihiro Matsumoto <matz@caelum.co.jp>
require 'tk'
@@ -8,7 +7,7 @@ require 'tk/label'
require 'tk/scrollable'
require 'tk/validation'
-class TkEntry<TkLabel
+class Tk::Entry<Tk::Label
include X_Scrollable
include TkValidation
@@ -115,3 +114,6 @@ class TkEntry<TkLabel
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
index 70a1e38bbe..d8aad6248b 100644
--- a/ext/tk/lib/tk/event.rb
+++ b/ext/tk/lib/tk/event.rb
@@ -39,7 +39,9 @@ module TkEvent
RESIZEREQ = 0x200000
CIRCREQ = 0x400000
- MWHEEL = 0x10000000
+ MWHEEL = KEY
+
+ STRING_DATA = 0x80000000 # special flag for 'data' field
ALL = 0xFFFFFFFF
@@ -155,7 +157,7 @@ module TkEvent
'borderwidth' => (Grp::CREATE|Grp::CONFIG),
'button' => Grp::BUTTON,
'count' => Grp::EXPOSE,
- 'data' => Grp::VIRTUAL,
+ 'data' => (Grp::VIRTUAL|Grp::STRING_DATA),
'delta' => Grp::MWHEEL,
'detail' => (Grp::FOCUS|Grp::CROSSING),
'focus' => Grp::CROSSING,
@@ -223,7 +225,8 @@ module TkEvent
rescue
next
end
- next if !val || val == '??'
+ # next if !val || val == '??'
+ next if !val || (val == '??' && (flag & Grp::STRING_DATA))
fields[key] = val
}
@@ -298,34 +301,65 @@ module TkEvent
[ ?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) ],
@@ -345,6 +379,24 @@ module TkEvent
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
@@ -357,7 +409,8 @@ module TkEvent
# ( which are Tcl strings ) to ruby objects based on the key string
# that is generated by _get_subst_key() or _get_all_subst_keys().
#
- _setup_subst_table(KEY_TBL, PROC_TBL);
+ _setup_subst_table(KEY_TBL, PROC_TBL)
+ # _setup_subst_table(KEY_TBL, LONGKEY_TBL, PROC_TBL) # if use longname-keys
#
# NOTE: The order of parameters which passed to callback procedure is
@@ -405,6 +458,7 @@ module TkEvent
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)
diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb
index ab58ac5762..62d628c132 100644
--- a/ext/tk/lib/tk/font.rb
+++ b/ext/tk/lib/tk/font.rb
@@ -11,13 +11,18 @@ class TkFont
TkCommandNames = ['font'.freeze].freeze
- Tk_FontID = ["@font".freeze, "00000".taint].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.clear
- Tk_FontUseTBL.clear
+ Tk_FontNameTBL.mutex.synchronize{ Tk_FontNameTBL.clear }
+ Tk_FontUseTBL.mutex.synchronize{ Tk_FontUseTBL.clear }
}
# option_type : default => string
@@ -31,13 +36,26 @@ class TkFont
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\.*/
+ when /^4\..*/
DEFAULT_LATIN_FONT_NAME = 'a14'.freeze
DEFAULT_KANJI_FONT_NAME = 'k14'.freeze
- when /^8\.*/
+ when /^8\.[0-4]/
if JAPANIZED_TK
begin
fontnames = tk_call('font', 'names')
@@ -103,6 +121,15 @@ class TkFont
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
@@ -121,6 +148,7 @@ class TkFont
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'
@@ -145,6 +173,9 @@ class TkFont
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)
@@ -163,6 +194,14 @@ class TkFont
###################################
# 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)
@@ -171,6 +210,9 @@ class TkFont
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 == ''
@@ -181,6 +223,9 @@ class TkFont
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)
@@ -234,6 +279,33 @@ class TkFont
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 == ''
@@ -244,13 +316,40 @@ class TkFont
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\.*/
+ when /^4\..*/
['fixed']
- when /^8\.*/
+ when /^8\..*/
if win
tk_split_simplelist(tk_call('font', 'families', '-displayof', win))
else
@@ -261,13 +360,16 @@ class TkFont
def TkFont.names
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
r = ['fixed']
r += ['a14', 'k14'] if JAPANIZED_TK
- Tk_FontNameTBL.each_value{|obj| r.push(obj)}
- r | []
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL.each_value{|obj| r.push(obj)}
+ }
+ #r | []
+ r.uniq
- when /^8\.*/
+ when /^8\..*/
tk_split_simplelist(tk_call('font', 'names'))
end
@@ -285,10 +387,15 @@ class TkFont
end
def TkFont.get_obj(name)
+ name = name.to_s
if name =~ /^(@font[0-9]+)(|c|l|k)$/
- Tk_FontNameTBL[$1]
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[$1]
+ }
else
- nil
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[name]
+ }
end
end
@@ -298,7 +405,7 @@ class TkFont
path = [win, tag, key].join(';')
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
regexp = /^-(|kanji)#{key} /
conf_list = tk_split_simplelist(tk_call(*args)).
@@ -324,7 +431,7 @@ class TkFont
TkFont.new(ltn, knj).call_font_configure([path, key], *args)
- when /^8\.*/
+ when /^8\.[0-4]/
regexp = /^-#{key} /
conf_list = tk_split_simplelist(tk_call(*args)).
@@ -360,26 +467,66 @@ class TkFont
compound = []
end
if compound == []
- TkFont.new(fnt).call_font_configure([path, key], *args)
+ 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)
- if path
- Tk_FontUseTBL[path]
- else
- Tk_FontUseTBL.values | []
- end
+ 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
+ if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK
tk_call('font', 'failsafe', font)
end
rescue
@@ -392,15 +539,20 @@ class TkFont
private
###################################
def init_dummy_fontobj
- @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
- Tk_FontID[1].succ!
- Tk_FontNameTBL[@id] = self
+ 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
+ # @latin_desscendant = nil
+ # @kanji_desscendant = nil
+ @descendant = [nil, nil] # [latin, kanji]
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
@latinfont = ""
@kanjifont = ""
if JAPANIZED_TK
@@ -436,13 +588,23 @@ class TkFont
ltn = '{}' if ltn == ''
knj = '{}' if knj == ''
- # @id = Tk_FontID.join('')
- @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
- Tk_FontID[1].succ!
- Tk_FontNameTBL[@id] = self
+ 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]
- @latin_desscendant = nil
- @kanji_desscendant = nil
+ # @latinfont = @id + 'l'
+ # @kanjifont = @id + 'k'
+ # @compoundfont = @id + 'c'
+ # @fontslot = {}
if knj.kind_of?(Hash) && !keys
keys = knj
@@ -474,7 +636,7 @@ class TkFont
if ltn
if JAPANIZED_TK && !knj
- if Tk::TK_VERSION =~ /^4.*/
+ if Tk::TK_VERSION =~ /^4..*/
knj = DEFAULT_KANJI_FONT_NAME
else
knj = ltn
@@ -625,9 +787,14 @@ class TkFont
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
@@ -753,6 +920,7 @@ class TkFont
end
@fontslot = {'font'=>@compoundfont}
+ # @fontslot['font'] = @compoundfont
begin
tk_call('font', 'create', @compoundfont,
'-compound', [@latinfont, @kanjifont], *hash_kv(keys))
@@ -833,6 +1001,7 @@ class TkFont
end
@fontslot = {'font'=>@compoundfont}
+ # @fontslot['font'] = @compoundfont
tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
end
end
@@ -887,25 +1056,39 @@ class TkFont
keys = _symbolkey2str(args.pop).update(fontslot)
args.concat(hash_kv(keys))
- tk_call(*args)
- Tk_FontUseTBL[[win, tag, optkey].join(';')] = self
+ 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 = []
- Tk_FontUseTBL.each{|key,value|
+ 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
+ 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
+ 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])
@@ -925,7 +1108,8 @@ class TkFont
ret.push([winobj, tag])
end
end
- elsif winobj.kind_of? TkMenu
+ #elsif winobj.kind_of? TkMenu
+ elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu)
if optkey
ret.push([winobj, tag, optkey])
else
@@ -957,6 +1141,8 @@ class TkFont
@compoundfont
end
alias font_id font
+ alias name font
+ alias to_s font
def latin_font_id
@latinfont
@@ -964,11 +1150,18 @@ class TkFont
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
@@ -978,50 +1171,87 @@ class TkFont
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)
- actual_core(@latinfont, nil, option)
+ 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
- actual_core(@latinfont, win, option)
+ 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 != ""
+ 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 != ""
+ 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
@@ -1065,10 +1295,15 @@ class TkFont
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 != ""
+ 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
@@ -1080,13 +1315,18 @@ class TkFont
def kanji_configinfo(slot=nil)
#if JAPANIZED_TK
- if @kanjifont != ""
+ 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
@@ -1096,12 +1336,30 @@ class TkFont
end
def latin_replace(ltn)
- latin_replace_core(ltn)
- reset_pointadjust
+ 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
@@ -1119,41 +1377,215 @@ class TkFont
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)
- metrics_core(@latinfont, nil, option)
+ 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
- metrics_core(@latinfont, win, option)
+ 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 JAPANIZED_TK
+ 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)
- if JAPANIZED_TK
- win = '.' unless win
+ 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
+ if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK
configure('pointadjust' => latin_actual.assoc('size')[1].to_f /
kanji_actual.assoc('size')[1].to_f )
end
@@ -1166,7 +1598,7 @@ class TkFont
# private alias
###################################
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
alias create_latinfont create_latinfont_tk4x
alias create_kanjifont create_kanjifont_tk4x
alias create_compoundfont create_compoundfont_tk4x
@@ -1471,32 +1903,44 @@ module TkFont::CoreMethods
end
def delete_core_tk4x
- TkFont::Tk_FontNameTBL.delete(@id)
- TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
+ 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)
+ tk_call('font', 'delete', @latinfont) if @latinfont
rescue
end
begin
- tk_call('font', 'delete', @kanjifont)
+ tk_call('font', 'delete', @kanjifont) if @kanjifont
rescue
end
begin
- tk_call('font', 'delete', @compoundfont)
+ tk_call('font', 'delete', @compoundfont) if @compoundfont
rescue
end
- TkFont::Tk_FontNameTBL.delete(@id)
- TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
+ 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
- TkFont::Tk_FontUseTBL.dup.each{|w, fobj|
+ table = nil
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ table = TkFont::Tk_FontUseTBL.clone
+ }
+ table.each{|w, fobj|
if self == fobj
begin
if w.include?(';')
@@ -1504,11 +1948,14 @@ module TkFont::CoreMethods
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
+ 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
+ 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
+ elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu)
tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont)
else
raise RuntimeError, "unknown widget type"
@@ -1518,7 +1965,9 @@ module TkFont::CoreMethods
tk_call(w, 'configure', '-font', @latinfont)
end
rescue
- TkFont::Tk_FontUseTBL.delete(w)
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete(w)
+ }
end
end
}
@@ -1531,7 +1980,11 @@ module TkFont::CoreMethods
create_kanjifont_tk4x(knj)
@compoundfont[1] = [@kanjifont]
@fontslot['kanjifont'] = @kanjifont
- TkFont::Tk_FontUseTBL.dup.each{|w, fobj|
+ table = nil
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ table = TkFont::Tk_FontUseTBL.clone
+ }
+ table.dup.each{|w, fobj|
if self == fobj
begin
if w.include?(';')
@@ -1539,11 +1992,14 @@ module TkFont::CoreMethods
optkey = 'kanjifont' unless optkey
winobj = tk_tcl2ruby(win)
# winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont})
- if winobj.kind_of? TkText
+ #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
+ 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
+ elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu)
tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont)
else
raise RuntimeError, "unknown widget type"
@@ -1553,7 +2009,9 @@ module TkFont::CoreMethods
tk_call(w, 'configure', '-kanjifont', @kanjifont)
end
rescue
- TkFont::Tk_FontUseTBL.delete(w)
+ Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete(w)
+ }
end
end
}
@@ -1618,8 +2076,11 @@ module TkFont::CoreMethods
rescue
latinkeys = {}
end
- if latinkeys != {}
+ 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
@@ -1711,6 +2172,13 @@ module TkFont::CoreMethods
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
@@ -1720,7 +2188,7 @@ module TkFont::CoreMethods
# private alias
###################################
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
alias actual_core actual_core_tk4x
alias configure_core configure_core_tk4x
alias configinfo_core configinfo_core_tk4x
@@ -1760,3 +2228,117 @@ 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
index 6636fef5b5..263b160f29 100644
--- a/ext/tk/lib/tk/frame.rb
+++ b/ext/tk/lib/tk/frame.rb
@@ -3,7 +3,7 @@
#
require 'tk'
-class TkFrame<TkWindow
+class Tk::Frame<TkWindow
TkCommandNames = ['frame'.freeze].freeze
WidgetClassName = 'Frame'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -126,3 +126,6 @@ class TkFrame<TkWindow
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
index 10fdf3569b..0dfd7263a7 100644
--- a/ext/tk/lib/tk/grid.rb
+++ b/ext/tk/lib/tk/grid.rb
@@ -22,6 +22,7 @@ module TkGrid
list(tk_call_without_enc('grid', 'bbox', *args))
end
+=begin
def configure(win, *args)
if args[-1].kind_of?(Hash)
opts = args.pop
@@ -53,6 +54,48 @@ module TkGrid
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)
@@ -61,12 +104,14 @@ module TkGrid
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)
@@ -189,10 +234,10 @@ module TkGrid
list(tk_call_without_enc('grid', 'slaves', master, *hash_kv(args)))
end
- module_function :bbox, :forget, :propagate, :info
+ module_function :anchor, :bbox, :add, :forget, :propagate, :info
module_function :remove, :size, :slaves, :location
module_function :grid, :configure, :columnconfigure, :rowconfigure
- module_function :columnconfiginfo, :rowconfiginfo
+ module_function :column, :row, :columnconfiginfo, :rowconfiginfo
end
=begin
def TkGrid(win, *args)
diff --git a/ext/tk/lib/tk/image.rb b/ext/tk/lib/tk/image.rb
index 35e2c4e394..dffdc19644 100644
--- a/ext/tk/lib/tk/image.rb
+++ b/ext/tk/lib/tk/image.rb
@@ -10,9 +10,16 @@ class TkImage<TkObject
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 }
+ (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)
@@ -27,7 +34,10 @@ class TkImage<TkObject
obj = name
else
name = _get_eval_string(name)
- obj = Tk_IMGTBL[name]
+ obj = nil
+ Tk_IMGTBL.mutex.synchronize{
+ obj = Tk_IMGTBL[name]
+ }
end
if obj
if !(keys[:without_creating] || keys['without_creating'])
@@ -43,7 +53,13 @@ class TkImage<TkObject
end
end
end
- super(keys)
+ (obj = self.allocate).instance_eval{
+ Tk_IMGTBL.mutex.synchronize{
+ initialize(keys)
+ Tk_IMGTBL[@path] = self
+ }
+ }
+ obj
end
def initialize(keys=nil)
@@ -55,19 +71,22 @@ class TkImage<TkObject
without_creating = keys.delete('without_creating')
end
unless @path
- # @path = Tk_Image_ID.join('')
- @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
- Tk_Image_ID[1].succ!
+ 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
- Tk_IMGTBL[@path] = self
end
def delete
- Tk_IMGTBL.delete(@id) if @id
+ Tk_IMGTBL.mutex.synchronize{
+ Tk_IMGTBL.delete(@id) if @id
+ }
tk_call_without_enc('image', 'delete', @path)
self
end
@@ -85,8 +104,10 @@ class TkImage<TkObject
end
def TkImage.names
- Tk.tk_call_without_enc('image', 'names').split.collect!{|id|
- (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
+ Tk_IMGTBL.mutex.synchronize{
+ Tk.tk_call_without_enc('image', 'names').split.collect!{|id|
+ (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
+ }
}
end
@@ -135,7 +156,7 @@ class TkPhotoImage<TkImage
self
end
- def cget(option)
+ def cget_strict(option)
case option.to_s
when 'data', 'file'
tk_send 'cget', '-' << option.to_s
@@ -143,6 +164,23 @@ class TkPhotoImage<TkImage
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
diff --git a/ext/tk/lib/tk/itemconfig.rb b/ext/tk/lib/tk/itemconfig.rb
index a7885e74f3..9c6a98d0f8 100644
--- a/ext/tk/lib/tk/itemconfig.rb
+++ b/ext/tk/lib/tk/itemconfig.rb
@@ -8,6 +8,11 @@ require 'tk/itemfont.rb'
module TkItemConfigOptkeys
include TkUtil
+ def __item_optkey_aliases(id)
+ {}
+ end
+ private :__item_optkey_aliases
+
def __item_numval_optkeys(id)
[]
end
@@ -115,6 +120,14 @@ module TkItemConfigMethod
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]
@@ -149,7 +162,7 @@ module TkItemConfigMethod
################################################
- def itemcget(tagOrId, option)
+ def __itemcget_core(tagOrId, option)
orig_opt = option
option = option.to_s
@@ -157,6 +170,11 @@ module TkItemConfigMethod
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
@@ -224,11 +242,45 @@ module TkItemConfigMethod
tk_tcl2ruby(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")), true)
end
end
+ private :__itemcget_core
- def itemconfigure(tagOrId, slot, value=None)
+ 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
@@ -265,6 +317,11 @@ module TkItemConfigMethod
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
@@ -288,6 +345,56 @@ module TkItemConfigMethod
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
@@ -299,6 +406,10 @@ module TkItemConfigMethod
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 \
@@ -310,6 +421,12 @@ module TkItemConfigMethod
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]
@@ -635,6 +752,10 @@ module TkItemConfigMethod
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
@@ -658,7 +779,11 @@ module TkItemConfigMethod
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = fontobj(tagid(tagOrId), fontkey)
+ 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 )
@@ -673,6 +798,12 @@ module TkItemConfigMethod
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]
@@ -1006,6 +1137,10 @@ module TkItemConfigMethod
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
@@ -1023,10 +1158,24 @@ module TkItemConfigMethod
private :__itemconfiginfo_core
def itemconfiginfo(tagOrId, slot = nil)
- __itemconfiginfo_core(tagOrId, slot)
+ 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)
+ def __current_itemconfiginfo(tagOrId, slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if slot
org_slot = slot
@@ -1048,6 +1197,7 @@ module TkItemConfigMethod
ret[conf[0]] = conf[-1]
end
}
+
ret
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
@@ -1058,4 +1208,8 @@ module TkItemConfigMethod
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
index ab9e3ff6c9..4c5c917c57 100644
--- a/ext/tk/lib/tk/itemfont.rb
+++ b/ext/tk/lib/tk/itemfont.rb
@@ -94,7 +94,16 @@ module TkTreatItemFont
*(__item_config_cmd(tagid(tagOrId)) << {}))
next
else
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << fnt))
+ 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
@@ -147,7 +156,16 @@ module TkTreatItemFont
elsif Tk::JAPANIZED_TK
fobj = fontobj # create a new TkFont object
else
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << ltn))
+ 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
@@ -198,7 +216,16 @@ module TkTreatItemFont
elsif Tk::JAPANIZED_TK
fobj = fontobj # create a new TkFont object
else
- tk_call(*(__item_config_cmd(tagid(tagOrId)) << "-#{optkey}" << knj))
+ 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
diff --git a/ext/tk/lib/tk/label.rb b/ext/tk/lib/tk/label.rb
index 8b45db9b30..80b3d778f1 100644
--- a/ext/tk/lib/tk/label.rb
+++ b/ext/tk/lib/tk/label.rb
@@ -3,7 +3,7 @@
#
require 'tk'
-class TkLabel<TkWindow
+class Tk::Label<TkWindow
TkCommandNames = ['label'.freeze].freeze
WidgetClassName = 'Label'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -16,3 +16,6 @@ class TkLabel<TkWindow
#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
index 73d5603200..995b5b7e72 100644
--- a/ext/tk/lib/tk/labelframe.rb
+++ b/ext/tk/lib/tk/labelframe.rb
@@ -4,7 +4,7 @@
require 'tk'
require 'tk/frame'
-class TkLabelFrame<TkFrame
+class Tk::LabelFrame<Tk::Frame
TkCommandNames = ['labelframe'.freeze].freeze
WidgetClassName = 'Labelframe'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -22,4 +22,8 @@ class TkLabelFrame<TkFrame
end
private :__val2ruby_optkeys
end
-TkLabelframe = TkLabelFrame
+
+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
index 41d02d279e..bb039ffb0e 100644
--- a/ext/tk/lib/tk/listbox.rb
+++ b/ext/tk/lib/tk/listbox.rb
@@ -15,7 +15,7 @@ module TkListItemConfig
private :__item_listval_optkeys
end
-class TkListbox<TkTextWin
+class Tk::Listbox<TkTextWin
include TkListItemConfig
include Scrollable
@@ -277,3 +277,6 @@ class TkListbox<TkTextWin
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
index 1802073f46..67b0a4bb60 100644
--- a/ext/tk/lib/tk/macpkg.rb
+++ b/ext/tk/lib/tk/macpkg.rb
@@ -20,9 +20,14 @@ module Tk
end
end
-module TkMacResource
+module Tk::MacResource
+end
+#TkMacResource = Tk::MacResource
+Tk.__set_toplevel_aliases__(:Tk, Tk::MacResource, :TkMacResource)
+
+module Tk::MacResource
extend Tk
- extend TkMacResource
+ extend Tk::MacResource
TkCommandNames = ['resource'.freeze].freeze
diff --git a/ext/tk/lib/tk/menu.rb b/ext/tk/lib/tk/menu.rb
index ddddc8e53e..3ae0548dd1 100644
--- a/ext/tk/lib/tk/menu.rb
+++ b/ext/tk/lib/tk/menu.rb
@@ -34,15 +34,16 @@ module TkMenuEntryConfig
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, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
end
-class TkMenu<TkWindow
+class Tk::Menu<TkWindow
include Wm
include TkMenuEntryConfig
extend TkMenuSpec
@@ -140,9 +141,9 @@ class TkMenu<TkWindow
type = keys.delete('type') if keys.has_key?('type')
if keys.empty?
- TkMenuClone.new(self, parent, type)
+ Tk::MenuClone.new(self, parent, type)
else
- TkMenuClone.new(self, parent, type, keys)
+ Tk::MenuClone.new(self, parent, type, keys)
end
end
@@ -202,6 +203,9 @@ class TkMenu<TkWindow
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
@@ -381,8 +385,11 @@ class TkMenu<TkWindow
=end
end
+#TkMenu = Tk::Menu unless Object.const_defined? :TkMenu
+Tk.__set_toplevel_aliases__(:Tk, Tk::Menu, :TkMenu)
+
-class TkMenuClone<TkMenu
+class Tk::MenuClone<Tk::Menu
=begin
def initialize(parent, type=None)
widgetname = nil
@@ -436,9 +443,12 @@ class TkMenuClone<TkMenu
@src_menu
end
end
-TkCloneMenu = TkMenuClone
+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 TkSystemMenu
+module Tk::SystemMenu
def initialize(parent, keys=nil)
if parent.kind_of? Hash
keys = _symbolkey2str(parent)
@@ -461,38 +471,60 @@ module TkSystemMenu
end
end
end
+TkSystemMenu = Tk::SystemMenu
-class TkSysMenu_Help<TkMenu
+class Tk::SysMenu_Help<Tk::Menu
# for all platform
- include TkSystemMenu
+ 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 TkSysMenu_System<TkMenu
+class Tk::SysMenu_System<Tk::Menu
# for Windows
- include TkSystemMenu
+ 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 TkSysMenu_Apple<TkMenu
+class Tk::SysMenu_Apple<Tk::Menu
# for Machintosh
- include TkSystemMenu
+ 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 TkMenubutton<TkLabel
+class Tk::Menubutton<Tk::Label
TkCommandNames = ['menubutton'.freeze].freeze
WidgetClassName = 'Menubutton'.freeze
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
- # tk_call_without_enc('menubutton', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
+ 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)
@@ -506,10 +538,13 @@ class TkMenubutton<TkLabel
private :__boolval_optkeys
end
-TkMenuButton = TkMenubutton
+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 TkOptionMenubutton<TkMenubutton
+class Tk::OptionMenubutton<Tk::Menubutton
TkCommandNames = ['tk_optionMenu'.freeze].freeze
class OptionMenu<TkMenu
@@ -596,6 +631,9 @@ class TkOptionMenubutton<TkMenubutton
@menu.delete(index, last)
self
end
+ def xposition(index)
+ @menu.xposition(index)
+ end
def yposition(index)
@menu.yposition(index)
end
@@ -605,6 +643,9 @@ class TkOptionMenubutton<TkMenubutton
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
@@ -618,6 +659,9 @@ class TkOptionMenubutton<TkMenubutton
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
@@ -629,4 +673,9 @@ class TkOptionMenubutton<TkMenubutton
@menu.current_entryconfiginfo(index, key)
end
end
-TkOptionMenuButton = TkOptionMenubutton
+
+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
index 392b6fbd4e..ef9da809b9 100644
--- a/ext/tk/lib/tk/menubar.rb
+++ b/ext/tk/lib/tk/menubar.rb
@@ -89,7 +89,7 @@ require 'tk/frame'
require 'tk/composite'
require 'tk/menuspec'
-class TkMenubar<TkFrame
+class TkMenubar<Tk::Frame
include TkComposite
include TkMenuSpec
diff --git a/ext/tk/lib/tk/menuspec.rb b/ext/tk/lib/tk/menuspec.rb
index 118a4f42b1..2a2eb9ba3c 100644
--- a/ext/tk/lib/tk/menuspec.rb
+++ b/ext/tk/lib/tk/menuspec.rb
@@ -61,8 +61,12 @@ module TkMenuSpec
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
@@ -150,21 +154,22 @@ module TkMenuSpec
def _use_menubar?(parent)
use_menubar = false
- if parent.kind_of?(TkRoot) || parent.kind_of?(TkToplevel)
- return true
+ if parent.kind_of?(Tk::Root) || parent.kind_of?(Tk::Toplevel)
+ true
+ elsif parent.current_configinfo.has_key?('menu')
+ true
else
- begin
- parent.cget('menu')
- return true
- rescue
- end
+ false
end
- false
end
private :_use_menubar?
def _create_menu_for_menubar(parent)
- unless (mbar = parent.menu).kind_of?(TkMenu)
+ #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
@@ -190,7 +195,6 @@ module TkMenuSpec
if _use_menubar?(parent)
# menubar by menu entries
-
mbar = _create_menu_for_menubar(parent)
menu_name = nil
@@ -221,6 +225,8 @@ module TkMenuSpec
else
# menubar by menubuttons
+ #mbtn = Tk::Menubutton.new(parent)
+ # --> use current TkMenubutton class
mbtn = TkMenubutton.new(parent)
menu_name = nil
diff --git a/ext/tk/lib/tk/message.rb b/ext/tk/lib/tk/message.rb
index 79121bebb3..946b68c704 100644
--- a/ext/tk/lib/tk/message.rb
+++ b/ext/tk/lib/tk/message.rb
@@ -4,7 +4,7 @@
require 'tk'
require 'tk/label'
-class TkMessage<TkLabel
+class Tk::Message<Tk::Label
TkCommandNames = ['message'.freeze].freeze
WidgetClassName = 'Message'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -17,3 +17,6 @@ class TkMessage<TkLabel
#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/msgcat.rb b/ext/tk/lib/tk/msgcat.rb
index 061e43fd89..162953f425 100644
--- a/ext/tk/lib/tk/msgcat.rb
+++ b/ext/tk/lib/tk/msgcat.rb
@@ -74,7 +74,11 @@ class TkMsgCatalog < TkObject
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
+ 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" +
diff --git a/ext/tk/lib/tk/namespace.rb b/ext/tk/lib/tk/namespace.rb
index 5bf6474c5b..20a8d65215 100644
--- a/ext/tk/lib/tk/namespace.rb
+++ b/ext/tk/lib/tk/namespace.rb
@@ -12,17 +12,24 @@ class TkNamespace < TkObject
].freeze
Tk_Namespace_ID_TBL = TkCore::INTERP.create_table
- Tk_Namespace_ID = ["ns".freeze, "00000".taint].freeze
+
+ (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.clear
- Tk_NsCode_RetObjID_TBL.clear
+ 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[id]? Tk_Namespace_ID_TBL[id]: id
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id
+ }
end
#####################################
@@ -65,11 +72,27 @@ class TkNamespace < TkObject
def cget(slot)
if slot == :namespace || slot == 'namespace'
ns = super(slot)
- if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
- TkNamespace::Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ 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
@@ -79,9 +102,11 @@ class TkNamespace < TkObject
if slot
if slot == :namespace || slot == 'namespace'
val = super(slot)
- if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
- val = TkNamespace::Tk_Namespace_ID_TBL[val]
- end
+ 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
@@ -96,19 +121,23 @@ class TkNamespace < TkObject
info = super()
if TkComm::GET_CONFIGINFO_AS_ARRAY
- 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
+ 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']
- if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
- info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val]
- end
+ 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
@@ -215,9 +244,11 @@ class TkNamespace < TkObject
def initialize(name = nil, parent = nil)
unless name
- # name = Tk_Namespace_ID.join('')
- name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_)
- Tk_Namespace_ID[1].succ!
+ 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
@@ -252,7 +283,9 @@ class TkNamespace < TkObject
# create namespace
__tk_call('namespace', 'eval', @fullname, '')
- Tk_Namespace_ID_TBL[@fullname] = self
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ Tk_Namespace_ID_TBL[@fullname] = self
+ }
end
def self.children(*args)
@@ -260,11 +293,13 @@ class TkNamespace < TkObject
# <pattern> must be glob-style pattern
tk_split_simplelist(tk_call('namespace', 'children', *args)).collect{|ns|
# ns is fullname
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ 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)
@@ -290,14 +325,24 @@ class TkNamespace < TkObject
def code(script = Proc.new)
if script.kind_of?(String)
cmd = proc{|*args|
- ret = ScopeArgs.new(@fullname,*args).instance_eval(script)
+ 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|
- ret = ScopeArgs.new(@fullname,*args).instance_eval(&script)
+ 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
@@ -319,11 +364,13 @@ class TkNamespace < TkObject
def self.current
ns = self.current_path
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ 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')
@@ -335,11 +382,13 @@ class TkNamespace < TkObject
def self.delete(*ns_list)
tk_call('namespace', 'delete', *ns_list)
ns_list.each{|ns|
- if ns.kind_of?(TkNamespace)
- Tk_Namespace_ID_TBL.delete(ns.path)
- else
- Tk_Namespace_ID_TBL.delete(ns.to_s)
- end
+ 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
@@ -371,7 +420,7 @@ class TkNamespace < TkObject
def self.eval(namespace, cmd = Proc.new, *args)
#tk_call('namespace', 'eval', namespace, cmd, *args)
- TkNamespace.new(namespece).eval(cmd, *args)
+ TkNamespace.new(namespace).eval(cmd, *args)
end
=begin
def eval(cmd = Proc.new, *args)
@@ -444,11 +493,13 @@ class TkNamespace < TkObject
def self.parent(namespace=None)
ns = tk_call('namespace', 'parent', namespace)
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ 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)
diff --git a/ext/tk/lib/tk/optiondb.rb b/ext/tk/lib/tk/optiondb.rb
index a806f3971d..186811d37d 100644
--- a/ext/tk/lib/tk/optiondb.rb
+++ b/ext/tk/lib/tk/optiondb.rb
@@ -8,7 +8,11 @@ module TkOptionDB
extend Tk
TkCommandNames = ['option'.freeze].freeze
- CmdClassID = ['CMD_CLASS'.freeze, '00000'.taint].freeze
+ (CmdClassID = ['CMD_CLASS'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
module Priority
WidgetDefault = 20
@@ -250,8 +254,10 @@ module TkOptionDB
def __create_new_class(klass, func, safe = 4, add = false, parent = nil)
if klass.kind_of?(TkWindow)
carrier = klass.path
- klass = CmdClassID.join(TkCore::INTERP._ip_id_)
- CmdClassID[1].succ!
+ 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)
@@ -312,7 +318,7 @@ module TkOptionDB
: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_variables, :kind_of?, :is_a?,
+ :instance_eval, :instance_exec, :instance_variables, :kind_of?, :is_a?,
:private_methods, :protected_methods, :public_methods ].each{|m|
alias_method(m, :__null_method)
}
@@ -362,7 +368,7 @@ module TkOptionDB
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)
+ TkOptionDB.new_proc_class(klass, func, safe, add, self, &b)
}
end
module_function :new_proc_class_random
diff --git a/ext/tk/lib/tk/pack.rb b/ext/tk/lib/tk/pack.rb
index 8fab363121..220a38e524 100644
--- a/ext/tk/lib/tk/pack.rb
+++ b/ext/tk/lib/tk/pack.rb
@@ -9,6 +9,7 @@ module TkPack
TkCommandNames = ['pack'.freeze].freeze
+=begin
def configure(win, *args)
if args[-1].kind_of?(Hash)
opts = args.pop
@@ -29,6 +30,22 @@ module TkPack
}
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)
diff --git a/ext/tk/lib/tk/package.rb b/ext/tk/lib/tk/package.rb
index d1eb27674d..0c329732f5 100644
--- a/ext/tk/lib/tk/package.rb
+++ b/ext/tk/lib/tk/package.rb
@@ -136,4 +136,8 @@ module TkPackage
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
index 2b6fdf5d90..2d08d50f6a 100644
--- a/ext/tk/lib/tk/palette.rb
+++ b/ext/tk/lib/tk/palette.rb
@@ -15,7 +15,7 @@ module TkPalette
].freeze
def TkPalette.set(*args)
- args = args.to_a.flatten if args.kind_of? Hash
+ args = args[0].to_a.flatten if args[0].kind_of? Hash
tk_call('tk_setPalette', *args)
end
def TkPalette.setPalette(*args)
diff --git a/ext/tk/lib/tk/panedwindow.rb b/ext/tk/lib/tk/panedwindow.rb
index c6cf3cd11f..030144e677 100644
--- a/ext/tk/lib/tk/panedwindow.rb
+++ b/ext/tk/lib/tk/panedwindow.rb
@@ -3,7 +3,7 @@
#
require 'tk'
-class TkPanedWindow<TkWindow
+class Tk::PanedWindow<TkWindow
TkCommandNames = ['panedwindow'.freeze].freeze
WidgetClassName = 'Panedwindow'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -76,11 +76,32 @@ class TkPanedWindow<TkWindow
self
end
- def panecget(win, key)
+ 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)
@@ -229,4 +250,9 @@ class TkPanedWindow<TkWindow
list(tk_send_without_enc('panes'))
end
end
-TkPanedwindow = TkPanedWindow
+
+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/radiobutton.rb b/ext/tk/lib/tk/radiobutton.rb
index f8f67d709a..1f864ec06b 100644
--- a/ext/tk/lib/tk/radiobutton.rb
+++ b/ext/tk/lib/tk/radiobutton.rb
@@ -4,7 +4,7 @@
require 'tk'
require 'tk/button'
-class TkRadioButton<TkButton
+class Tk::RadioButton<Tk::Button
TkCommandNames = ['radiobutton'.freeze].freeze
WidgetClassName = 'Radiobutton'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -63,4 +63,9 @@ class TkRadioButton<TkButton
end
end
end
-TkRadiobutton = TkRadioButton
+
+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
index 0e5584c7c1..7237b4c614 100644
--- a/ext/tk/lib/tk/root.rb
+++ b/ext/tk/lib/tk/root.rb
@@ -5,7 +5,7 @@ require 'tk'
require 'tk/wm'
require 'tk/menuspec'
-class TkRoot<TkWindow
+class Tk::Root<TkWindow
include Wm
include TkMenuSpec
@@ -14,28 +14,7 @@ class TkRoot<TkWindow
end
private :__methodcall_optkeys
-=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)
+ def Root.new(keys=nil, &b)
unless TkCore::INTERP.tk_windows['.']
TkCore::INTERP.tk_windows['.'] =
super(:without_creating=>true, :widgetname=>'.'){}
@@ -62,7 +41,13 @@ class TkRoot<TkWindow
}
end
- root.instance_eval(&b) if block_given?
+ 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
@@ -102,7 +87,9 @@ class TkRoot<TkWindow
self.menu
end
- def TkRoot.destroy
+ 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
index 0b703aa055..7e758d92f4 100644
--- a/ext/tk/lib/tk/scale.rb
+++ b/ext/tk/lib/tk/scale.rb
@@ -3,7 +3,7 @@
#
require 'tk'
-class TkScale<TkWindow
+class Tk::Scale<TkWindow
TkCommandNames = ['scale'.freeze].freeze
WidgetClassName = 'Scale'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -14,9 +14,31 @@ class TkScale<TkWindow
cmd = keys.delete('command')
keys['command'] = proc{|val| cmd.call(val.to_f)}
end
- #tk_call_without_enc('scale', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
+ 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)
@@ -84,3 +106,6 @@ class TkScale<TkWindow
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/scrollbar.rb b/ext/tk/lib/tk/scrollbar.rb
index 70aadfdd4c..87db46a9f9 100644
--- a/ext/tk/lib/tk/scrollbar.rb
+++ b/ext/tk/lib/tk/scrollbar.rb
@@ -3,7 +3,7 @@
#
require 'tk'
-class TkScrollbar<TkWindow
+class Tk::Scrollbar<TkWindow
TkCommandNames = ['scrollbar'.freeze].freeze
WidgetClassName = 'Scrollbar'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -19,9 +19,31 @@ class TkScrollbar<TkWindow
}
if keys and keys != None
- #tk_call_without_enc('scrollbar', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
+ 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)
@@ -103,9 +125,33 @@ class TkScrollbar<TkWindow
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
-class TkXScrollbar<TkScrollbar
+#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'
@@ -114,7 +160,11 @@ class TkXScrollbar<TkScrollbar
private :create_self
end
-class TkYScrollbar<TkScrollbar
+#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'
@@ -122,3 +172,6 @@ class TkYScrollbar<TkScrollbar
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
index fd04057fb6..d20742a666 100644
--- a/ext/tk/lib/tk/scrollbox.rb
+++ b/ext/tk/lib/tk/scrollbox.rb
@@ -1,16 +1,19 @@
#
# tk/scrollbox.rb - Tk Listbox with Scrollbar
# as an example of Composite Widget
-# $Date$
# by Yukihiro Matsumoto <matz@netlab.co.jp>
#
require 'tk'
require 'tk/listbox'
-class TkScrollbox<TkListbox
+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
diff --git a/ext/tk/lib/tk/spinbox.rb b/ext/tk/lib/tk/spinbox.rb
index 9a10977d12..34dc1904f7 100644
--- a/ext/tk/lib/tk/spinbox.rb
+++ b/ext/tk/lib/tk/spinbox.rb
@@ -1,12 +1,11 @@
#
# tk/spinbox.rb - Tk spinbox classes
-# $Date$
# by Yukihiro Matsumoto <matz@caelum.co.jp>
#
require 'tk'
require 'tk/entry'
-class TkSpinbox<TkEntry
+class Tk::Spinbox<Tk::Entry
TkCommandNames = ['spinbox'.freeze].freeze
WidgetClassName = 'Spinbox'.freeze
WidgetClassNames[WidgetClassName] = self
@@ -38,6 +37,24 @@ class TkSpinbox<TkEntry
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)
@@ -97,3 +114,6 @@ class TkSpinbox<TkEntry
_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/text.rb b/ext/tk/lib/tk/text.rb
index 49d4b5625b..4ec82bed1d 100644
--- a/ext/tk/lib/tk/text.rb
+++ b/ext/tk/lib/tk/text.rb
@@ -1,6 +1,5 @@
#
# tk/text.rb - Tk text classes
-# $Date$
# by Yukihiro Matsumoto <matz@caelum.co.jp>
require 'tk'
require 'tk/itemfont'
@@ -33,34 +32,40 @@ module TkTextTagConfig
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)
- itemconfigure(['tag', tagOrId], slot)
+ itemconfiginfo(['tag', tagOrId], slot)
end
def current_tag_configinfo(tagOrId, slot=nil)
- itemconfigure(['tag', tagOrId], slot)
+ 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)
- itemconfigure(['window', tagOrId], slot)
+ itemconfiginfo(['window', tagOrId], slot)
end
def current_window_configinfo(tagOrId, slot=nil)
- itemconfigure(['window', tagOrId], slot)
+ current_itemconfiginfo(['window', tagOrId], slot)
end
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
end
-class TkText<TkTextWin
+class Tk::Text<TkTextWin
ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze
#include TkTreatTextTagFont
include TkTextTagConfig
@@ -74,9 +79,9 @@ class TkText<TkTextWin
mod = mod.to_s
if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(String.new(id) << ' + ' << mod)
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod)
else
- TkText::IndexString.new(String.new(id) << ' ' << mod)
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod)
end
end
@@ -85,20 +90,20 @@ class TkText<TkTextWin
mod = mod.to_s
if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(String.new(id) << ' - ' << mod)
+ Tk::Text::IndexString.new(String.new(id) << ' - ' << mod)
elsif mod =~ /^\s*[-]\s+(\d.*)$/
- TkText::IndexString.new(String.new(id) << ' - -' << $1)
+ Tk::Text::IndexString.new(String.new(id) << ' - -' << $1)
else
- TkText::IndexString.new(String.new(id) << ' ' << mod)
+ 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
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' chars')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' chars')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' chars')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' chars')
end
end
alias char chars
@@ -107,9 +112,9 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display chars')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display chars')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display chars')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display chars')
end
end
alias display_char display_chars
@@ -118,9 +123,9 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any chars')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any chars')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any chars')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any chars')
end
end
alias any_char any_chars
@@ -129,9 +134,9 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' indices')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' indices')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' indices')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' indices')
end
end
@@ -139,9 +144,9 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display indices')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display indices')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display indices')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display indices')
end
end
@@ -149,18 +154,18 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any indices')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any indices')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any indices')
+ 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
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' lines')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' lines')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' lines')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' lines')
end
end
alias line lines
@@ -169,9 +174,9 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display_lines')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display_lines')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display lines')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display lines')
end
end
alias display_line display_lines
@@ -180,43 +185,43 @@ class TkText<TkTextWin
# Tk8.5 feature
fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
if mod < 0
- TkText::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any_lines')
+ Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any_lines')
else
- TkText::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any lines')
+ Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any lines')
end
end
alias any_line any_lines
def linestart
- TkText::IndexString.new(String.new(id) << ' linestart')
+ Tk::Text::IndexString.new(String.new(id) << ' linestart')
end
def lineend
- TkText::IndexString.new(String.new(id) << ' lineend')
+ Tk::Text::IndexString.new(String.new(id) << ' lineend')
end
def display_linestart
# Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display linestart')
+ Tk::Text::IndexString.new(String.new(id) << ' display linestart')
end
def display_lineend
# Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display lineend')
+ Tk::Text::IndexString.new(String.new(id) << ' display lineend')
end
def wordstart
- TkText::IndexString.new(String.new(id) << ' wordstart')
+ Tk::Text::IndexString.new(String.new(id) << ' wordstart')
end
def wordend
- TkText::IndexString.new(String.new(id) << ' wordend')
+ Tk::Text::IndexString.new(String.new(id) << ' wordend')
end
def display_wordstart
# Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display wordstart')
+ Tk::Text::IndexString.new(String.new(id) << ' display wordstart')
end
def display_wordend
# Tk8.5 feature
- TkText::IndexString.new(String.new(id) << ' display wordend')
+ Tk::Text::IndexString.new(String.new(id) << ' display wordend')
end
end
@@ -251,7 +256,11 @@ class TkText<TkTextWin
def self.new(*args, &block)
obj = super(*args){}
obj.init_instance_variable
- obj.instance_eval(&block) if defined? yield
+ 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
@@ -261,8 +270,12 @@ class TkText<TkTextWin
end
def __destroy_hook__
- TkTextTag::TTagID_TBL.delete(@path)
- TkTextMark::TMarkID_TBL.delete(@path)
+ 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)
@@ -285,16 +298,16 @@ class TkText<TkTextWin
private :__strval_optkeys
def self.at(x, y)
- TkText::IndexString.at(x, y)
+ Tk::Text::IndexString.at(x, y)
end
def at(x, y)
- TkText::IndexString.at(x, y)
+ Tk::Text::IndexString.at(x, y)
end
def index(idx)
- TkText::IndexString.new(tk_send_without_enc('index',
- _get_eval_enc_str(idx)))
+ Tk::Text::IndexString.new(tk_send_without_enc('index',
+ _get_eval_enc_str(idx)))
end
def get_displaychars(*index)
@@ -396,7 +409,7 @@ class TkText<TkTextWin
end
alias previous_mark mark_previous
- def image_cget(index, slot)
+ def image_cget_strict(index, slot)
case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
_fromUTF8(tk_send_without_enc('image', 'cget',
@@ -408,6 +421,28 @@ class TkText<TkTextWin
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',
@@ -713,15 +748,17 @@ class TkText<TkTextWin
def tag_delete(*tags)
tk_send_without_enc('tag', 'delete',
*(tags.collect{|tag| _get_eval_enc_str(tag)}))
- 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
+ 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
@@ -968,7 +1005,7 @@ class TkText<TkTextWin
false, true)
r = []
while key=l.shift
- r.push [TkText::IndexString.new(key), TkText::IndexString.new(l.shift)]
+ r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)]
end
r
end
@@ -978,7 +1015,7 @@ class TkText<TkTextWin
_get_eval_enc_str(tag),
_get_eval_enc_str(first),
_get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
+ Tk::Text::IndexString.new(idx)
}
end
@@ -987,7 +1024,7 @@ class TkText<TkTextWin
_get_eval_enc_str(tag),
_get_eval_enc_str(first),
_get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
+ Tk::Text::IndexString.new(idx)
}
end
@@ -1183,6 +1220,11 @@ class TkText<TkTextWin
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
@@ -1232,7 +1274,7 @@ class TkText<TkTextWin
if ret == ""
nil
else
- TkText::IndexString.new(ret)
+ Tk::Text::IndexString.new(ret)
end
end
@@ -1267,7 +1309,7 @@ class TkText<TkTextWin
if ret == ""
nil
else
- TkText::IndexString.new(ret)
+ Tk::Text::IndexString.new(ret)
end
end
@@ -1456,10 +1498,10 @@ class TkText<TkTextWin
# retrieve index
idx = str.index(/ /, i)
if idx
- result.push(TkText::IndexString.new(str[i..(idx-1)]))
+ result.push(Tk::Text::IndexString.new(str[i..(idx-1)]))
i = idx + 1
else
- result.push(TkText::IndexString.new(str[i..-1]))
+ result.push(Tk::Text::IndexString.new(str[i..-1]))
break
end
end
@@ -1527,13 +1569,17 @@ class TkText<TkTextWin
end
end
+#TkText = Tk::Text unless Object.const_defined? :TkText
+Tk.__set_toplevel_aliases__(:Tk, Tk::Text, :TkText)
+
+
#######################################
-class TkText::Peer < TkText
+class Tk::Text::Peer < Tk::Text
# Tk8.5 feature
def initialize(text, parent=nil, keys={})
- unless text.kind_of?(TkText)
- fail ArgumentError, "TkText is expected for 1st argument"
+ unless text.kind_of?(Tk::Text)
+ fail ArgumentError, "Tk::Text is expected for 1st argument"
end
@src_text = text
super(parent, keys)
diff --git a/ext/tk/lib/tk/textimage.rb b/ext/tk/lib/tk/textimage.rb
index a29b23c7dd..fb306a9c17 100644
--- a/ext/tk/lib/tk/textimage.rb
+++ b/ext/tk/lib/tk/textimage.rb
@@ -5,11 +5,11 @@ require 'tk'
require 'tk/text'
class TkTextImage<TkObject
- include TkText::IndexModMethods
+ include Tk::Text::IndexModMethods
def initialize(parent, index, keys)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
#end
@t = parent
if index == 'end' || index == :end
@@ -34,7 +34,7 @@ class TkTextImage<TkObject
end
def id
- TkText::IndexString.new(@id)
+ Tk::Text::IndexString.new(@id)
end
def mark
@path
@@ -52,6 +52,10 @@ class TkTextImage<TkObject
@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
@@ -80,3 +84,5 @@ class TkTextImage<TkObject
value
end
end
+
+TktImage = TkTextImage
diff --git a/ext/tk/lib/tk/textmark.rb b/ext/tk/lib/tk/textmark.rb
index 650d95af70..72c1ce1ab4 100644
--- a/ext/tk/lib/tk/textmark.rb
+++ b/ext/tk/lib/tk/textmark.rb
@@ -5,38 +5,54 @@ require 'tk'
require 'tk/text'
class TkTextMark<TkObject
- include TkText::IndexModMethods
+ include Tk::Text::IndexModMethods
TMarkID_TBL = TkCore::INTERP.create_table
- Tk_TextMark_ID = ['mark'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TMarkID_TBL.clear }
+ (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
- return id unless TMarkID_TBL[tpath]
- TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id
+ 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?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
#end
@parent = @t = parent
@tpath = parent.path
- # @path = @id = Tk_TextMark_ID.join('')
- @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_).freeze
- TMarkID_TBL[@id] = self
- TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
- TMarkID_TBL[@tpath][@id] = self
- Tk_TextMark_ID[1].succ!
+ 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
- TkText::IndexString.new(@id)
+ Tk::Text::IndexString.new(@id)
end
def exist?
@@ -49,15 +65,15 @@ class TkTextMark<TkObject
end
=begin
- # move to TkText::IndexModMethods module
+ # move to Tk::Text::IndexModMethods module
def +(mod)
return chars(mod) if mod.kind_of?(Numeric)
mod = mod.to_s
if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(@id + ' + ' + mod)
+ Tk::Text::IndexString.new(@id + ' + ' + mod)
else
- TkText::IndexString.new(@id + ' ' + mod)
+ Tk::Text::IndexString.new(@id + ' ' + mod)
end
end
@@ -66,11 +82,11 @@ class TkTextMark<TkObject
mod = mod.to_s
if mod =~ /^\s*[+-]?\d/
- TkText::IndexString.new(@id + ' - ' + mod)
+ Tk::Text::IndexString.new(@id + ' - ' + mod)
elsif mod =~ /^\s*[-]\s+(\d.*)$/
- TkText::IndexString.new(@id + ' - -' + $1)
+ Tk::Text::IndexString.new(@id + ' - -' + $1)
else
- TkText::IndexString.new(@id + ' ' + mod)
+ Tk::Text::IndexString.new(@id + ' ' + mod)
end
end
=end
@@ -121,46 +137,68 @@ class TkTextMark<TkObject
end
end
end
+TktMark = TkTextMark
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
+ 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)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
+ # 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
- TMarkID_TBL[@id] = self
- TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
- TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id]
tk_call_without_enc(@t.path, 'mark', 'set', @id,
_get_eval_enc_str(index)) if index
- @t._addtag id, self
+ @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
index cc2c56210f..b08d923ea1 100644
--- a/ext/tk/lib/tk/texttag.rb
+++ b/ext/tk/lib/tk/texttag.rb
@@ -7,17 +7,29 @@ require 'tk/tagfont'
class TkTextTag<TkObject
include TkTreatTagFont
- include TkText::IndexModMethods
+ include Tk::Text::IndexModMethods
TTagID_TBL = TkCore::INTERP.create_table
- Tk_TextTag_ID = ['tag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TTagID_TBL.clear }
+ (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
- return id unless TTagID_TBL[tpath]
- TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id
+ 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)
@@ -26,12 +38,16 @@ class TkTextTag<TkObject
#end
@parent = @t = parent
@tpath = parent.path
- # @path = @id = Tk_TextTag_ID.join('')
- @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_).freeze
- # TTagID_TBL[@id] = self
- TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
- TTagID_TBL[@tpath][@id] = self
- Tk_TextTag_ID[1].succ!
+ 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
@@ -47,7 +63,7 @@ class TkTextTag<TkObject
end
def id
- TkText::IndexString.new(@id)
+ Tk::Text::IndexString.new(@id)
end
def exist?
@@ -60,11 +76,11 @@ class TkTextTag<TkObject
end
def first
- TkText::IndexString.new(@id + '.first')
+ Tk::Text::IndexString.new(@id + '.first')
end
def last
- TkText::IndexString.new(@id + '.last')
+ Tk::Text::IndexString.new(@id + '.last')
end
def add(*indices)
@@ -83,7 +99,7 @@ class TkTextTag<TkObject
l = tk_split_simplelist(tk_call_without_enc(@t.path, 'tag', 'ranges', @id))
r = []
while key=l.shift
- r.push [TkText::IndexString.new(key), TkText::IndexString.new(l.shift)]
+ r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)]
end
r
end
@@ -92,7 +108,7 @@ class TkTextTag<TkObject
simplelist(tk_call_without_enc(@t.path, 'tag', 'nextrange', @id,
_get_eval_enc_str(first),
_get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
+ Tk::Text::IndexString.new(idx)
}
end
@@ -100,7 +116,7 @@ class TkTextTag<TkObject
simplelist(tk_call_without_enc(@t.path, 'tag', 'prevrange', @id,
_get_eval_enc_str(first),
_get_eval_enc_str(last))).collect{|idx|
- TkText::IndexString.new(idx)
+ Tk::Text::IndexString.new(idx)
}
end
@@ -116,6 +132,9 @@ class TkTextTag<TkObject
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
@@ -221,40 +240,58 @@ class TkTextTag<TkObject
def destroy
tk_call_without_enc(@t.path, 'tag', 'delete', @id)
- TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath]
+ 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)
- if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name]
- tagobj = TTagID_TBL[parent.path][name]
- 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
+ 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
- return tagobj
- else
- super(parent, name, *args)
end
+
+ tagobj
end
def initialize(parent, name, *args)
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
+ # 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
- 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
@@ -268,12 +305,14 @@ class TkTextNamedTag<TkTextTag
add(*args)
end
end
- @t._addtag id, self
+ @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
index 605c40addd..004422e4f3 100644
--- a/ext/tk/lib/tk/textwindow.rb
+++ b/ext/tk/lib/tk/textwindow.rb
@@ -5,11 +5,11 @@ require 'tk'
require 'tk/text'
class TkTextWindow<TkObject
- include TkText::IndexModMethods
+ include Tk::Text::IndexModMethods
def initialize(parent, index, keys = {})
- #unless parent.kind_of?(TkText)
- # fail ArgumentError, "expect TkText for 1st argument"
+ #unless parent.kind_of?(Tk::Text)
+ # fail ArgumentError, "expect Tk::Text for 1st argument"
#end
@t = parent
if index == 'end' || index == :end
@@ -55,7 +55,7 @@ class TkTextWindow<TkObject
end
def id
- TkText::IndexString.new(_epath(@id))
+ Tk::Text::IndexString.new(_epath(@id))
end
def mark
@path
@@ -72,6 +72,9 @@ class TkTextWindow<TkObject
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)
@@ -147,3 +150,5 @@ class TkTextWindow<TkObject
value
end
end
+
+TktWindow = TkTextWindow
diff --git a/ext/tk/lib/tk/timer.rb b/ext/tk/lib/tk/timer.rb
index 47f2b79350..91840d0575 100644
--- a/ext/tk/lib/tk/timer.rb
+++ b/ext/tk/lib/tk/timer.rb
@@ -11,7 +11,12 @@ class TkTimer
TkCommandNames = ['after'.freeze].freeze
- Tk_CBID = ['a'.freeze, '00000'.taint].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')
@@ -96,9 +101,9 @@ class TkTimer
return self
end
@after_script = "rb_after #{@id}"
- @after_id = tk_call_without_enc('after', sleep, @after_script)
@current_args = args
@current_script = [sleep, @after_script]
+ @after_id = tk_call_without_enc('after', sleep, @after_script)
self
end
@@ -106,7 +111,8 @@ class TkTimer
if @running == false || @proc_max == 0 || @do_loop == 0
Tk_CBTBL.delete(@id) ;# for GC
@running = false
- @wait_var.value = 0
+ # @wait_var.value = 0
+ __at_end__
return
end
if @current_pos >= @proc_max
@@ -115,7 +121,8 @@ class TkTimer
else
Tk_CBTBL.delete(@id) ;# for GC
@running = false
- @wait_var.value = 0
+ # @wait_var.value = 0
+ __at_end__
return
end
end
@@ -138,12 +145,16 @@ class TkTimer
end
def initialize(*args, &b)
- # @id = Tk_CBID.join('')
- @id = Tk_CBID.join(TkCore::INTERP._ip_id_)
- Tk_CBID[1].succ!
+ 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
@@ -203,6 +214,12 @@ class TkTimer
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
@@ -420,7 +437,8 @@ class TkTimer
def cancel
@running = false
- @wait_var.value = 0
+ # @wait_var.value = 0
+ __at_end__
tk_call 'after', 'cancel', @after_id if @after_id
@after_id = nil
@@ -464,6 +482,21 @@ class TkTimer
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"
@@ -562,7 +595,8 @@ class TkRTTimer < TkTimer
if @running == false || @proc_max == 0 || @do_loop == 0
Tk_CBTBL.delete(@id) ;# for GC
@running = false
- @wait_var.value = 0
+ # @wait_var.value = 0
+ __at_end__
return
end
if @current_pos >= @proc_max
@@ -571,7 +605,8 @@ class TkRTTimer < TkTimer
else
Tk_CBTBL.delete(@id) ;# for GC
@running = false
- @wait_var.value = 0
+ # @wait_var.value = 0
+ __at_end__
return
end
end
diff --git a/ext/tk/lib/tk/toplevel.rb b/ext/tk/lib/tk/toplevel.rb
index 5e199e1330..bd6e8307f5 100644
--- a/ext/tk/lib/tk/toplevel.rb
+++ b/ext/tk/lib/tk/toplevel.rb
@@ -5,7 +5,7 @@ require 'tk'
require 'tk/wm'
require 'tk/menuspec'
-class TkToplevel<TkWindow
+class Tk::Toplevel<TkWindow
include Wm
include TkMenuSpec
@@ -72,7 +72,7 @@ class TkToplevel<TkWindow
conf_methods = _symbolkey2str(__methodcall_optkeys())
- keys.each{|k,v|
+ keys.each{|k,v| # k is a String
if conf_methods.key?(k)
wm_cmds[conf_methods[k]] = v
elsif Wm.method_defined?(k)
@@ -117,9 +117,10 @@ class TkToplevel<TkWindow
end
if @classname.kind_of? TkBindTag
@db_class = @classname
- @classname = @classname.id
+ keys['class'] = @classname = @classname.id
elsif @classname
@db_class = TkDatabaseClass.new(@classname)
+ keys['class'] = @classname
else
@db_class = self.class
@classname = @db_class::WidgetClassName
@@ -165,9 +166,10 @@ class TkToplevel<TkWindow
end
if @classname.kind_of? TkBindTag
@db_class = @classname
- @classname = @classname.id
+ keys['class'] = @classname = @classname.id
elsif @classname
@db_class = TkDatabaseClass.new(@classname)
+ keys['class'] = @classname
else
@db_class = self.class
@classname = @db_class::WidgetClassName
@@ -255,3 +257,6 @@ class TkToplevel<TkWindow
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/validation.rb b/ext/tk/lib/tk/validation.rb
index 0c5b5c61b9..60bd433cdc 100644
--- a/ext/tk/lib/tk/validation.rb
+++ b/ext/tk/lib/tk/validation.rb
@@ -50,7 +50,8 @@ module Tk
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.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])
@@ -151,7 +152,8 @@ module Tk
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.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])
@@ -249,6 +251,24 @@ class TkValidateCommand
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);
#
@@ -277,6 +297,7 @@ class TkValidateCommand
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)
diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb
index e5cacadc1a..f738a96ee7 100644
--- a/ext/tk/lib/tk/variable.rb
+++ b/ext/tk/lib/tk/variable.rb
@@ -16,11 +16,22 @@ class TkVariable
#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
+ (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')
+ 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} {
@@ -44,10 +55,10 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
def TkVariable.callback(id, name1, name2, op)
#name1,name2,op = tk_split_list(args)
#name1,name2,op = tk_split_simplelist(args)
- if TkVar_CB_TBL[id]
+ if cb_obj = TkVar_CB_TBL[id]
#_get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
begin
- _get_eval_string(TkVar_CB_TBL[id].trace_callback(name2, op))
+ _get_eval_string(cb_obj.trace_callback(name2, op))
rescue SystemExit
exit(0)
rescue Interrupt
@@ -59,7 +70,11 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
+ 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" +
@@ -267,11 +282,15 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
def initialize(val="", type=nil)
# @id = Tk_VARIABLE_ID.join('')
begin
- @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_)
- Tk_VARIABLE_ID[1].succ!
+ 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[@id] = self
+ TkVar_ID_TBL.mutex.synchronize{
+ TkVar_ID_TBL[@id] = self
+ }
@var = @id
@elem = nil
@@ -1263,56 +1282,101 @@ 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)
- @trace_var = [] if @trace_var == nil
- #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- @trace_var.unshift([opts,cmd])
+ opts = _check_trace_opt(opts)
+ (@trace_var ||= []).unshift([opts,cmd])
+
if @trace_opts == nil
TkVar_CB_TBL[@id] = self
- @trace_opts = opts.dup
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
+ @trace_opts = opts
+ if USE_OLD_TRACE_OPTION_STYLE
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var')
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
else
newopts = @trace_opts.dup
- #opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
- opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- 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)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ 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, 'rb_var ' << @id)
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @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
end
+
self
end
@@ -1321,65 +1385,54 @@ end
fail(RuntimeError,
"invalid for a TkVariable which denotes an element of Tcl's array")
end
- @trace_elem = {} if @trace_elem == nil
- @trace_elem[elem] = [] if @trace_elem[elem] == nil
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- @trace_elem[elem].unshift([opts,cmd])
+
+ opts = _check_trace_opt(opts)
+
+ ((@trace_elem ||= {})[elem] ||= []).unshift([opts,cmd])
+
if @trace_opts == nil
TkVar_CB_TBL[@id] = self
- @trace_opts = opts.dup
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
+ @trace_opts = opts
+ if USE_OLD_TRACE_OPTION_STYLE
Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
else
- # TCL_VERSION <= 8.3
Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
else
newopts = @trace_opts.dup
- # opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
- opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- 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)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ 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, 'rb_var ' << @id)
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @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
end
+
self
end
- def trace_vinfo
+ def trace_info
return [] unless @trace_var
@trace_var.dup
end
+ alias trace_vinfo trace_info
- def _trace_vinfo_for_element(elem)
+ def trace_info_for_element(elem)
if @elem
fail(RuntimeError,
"invalid for a TkVariable which denotes an element of Tcl's array")
@@ -1388,141 +1441,180 @@ end
return [] unless @trace_elem[elem]
@trace_elem[elem].dup
end
+ alias trace_vinfo_for_element trace_info_for_element
- def trace_vdelete(opts,cmd)
+ def trace_remove(opts,cmd)
return self unless @trace_var.kind_of? Array
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+
+ opts = _check_trace_opt(opts)
+
idx = -1
- newopts = ''
- @trace_var.each_with_index{|e,i|
- if idx < 0 && e[0] == opts && e[1] == cmd
- idx = i
- next
- end
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- }
+ 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 ||= {}).each{|elem|
@trace_elem[elem].each{|e|
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
+ 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
}
}
- newopts = newopts.to_s
- newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ 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, '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
-=end
- @trace_opts.replace(newopts)
- if @trace_opts != ''
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
+ 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')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
end
end
self
end
+ alias trace_delete trace_remove
+ alias trace_vdelete trace_remove
- def trace_vdelete_for_element(elem,opts,cmd)
+ 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 = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+
+ opts = _check_trace_opt(opts)
+
idx = -1
- @trace_elem[elem].each_with_index{|e,i|
- if idx < 0 && e[0] == opts && e[1] == cmd
- idx = i
- next
- end
- }
+ 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
- newopts = ''
- @trace_var.each{|e|
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(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)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
+ 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
- newopts = newopts.to_s
- newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ 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, '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
-=end
- @trace_opts.replace(newopts)
- if @trace_opts != ''
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
+ 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')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable', @id,
- @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=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
@@ -1532,12 +1624,23 @@ class TkVarAccess<TkVariable
return name
end
- if v = TkVar_ID_TBL[name]
- v.value = args[0] unless args.empty?
- return v
- 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
+ }
- super(name, *args)
+ v.instance_eval{ initialize(name, *args) }
+ v
end
def self.new_hash(name, *args)
@@ -1549,27 +1652,38 @@ class TkVarAccess<TkVariable
return name
end
- if v = TkVar_ID_TBL[name]
- unless v.is_hash?
- fail ArgumentError, "already exist as a scalar variable"
+ 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
- v.value = args[0] unless args.empty?
- return v
- end
+ }
INTERP._invoke_without_enc('global', name)
if args.empty? && INTERP._invoke_without_enc('array', 'exist', name) == '0'
- self.new(name, {}) # force creating
+ v.instance_eval{ initialize(name, {}) } # force creating
else
- self.new(name, *args)
+ v.instance_eval{ initialize(name, *args) }
end
+ v
end
def initialize(varname, val=nil)
- @id = varname
- TkVar_ID_TBL[@id] = self
+ # @id = varname
+ # TkVar_ID_TBL[@id] = self
- @var = @id
+ # @var = @id
@elem = nil
@def_default = false
diff --git a/ext/tk/lib/tk/virtevent.rb b/ext/tk/lib/tk/virtevent.rb
index d47e80aecd..ae31ac1f8f 100644
--- a/ext/tk/lib/tk/virtevent.rb
+++ b/ext/tk/lib/tk/virtevent.rb
@@ -9,10 +9,17 @@ class TkVirtualEvent<TkObject
TkCommandNames = ['event'.freeze].freeze
- TkVirtualEventID = ["VirtEvent".freeze, "00000".taint].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.clear }
+ TkCore::INTERP.init_ip_env{
+ TkVirtualEventTBL.mutex.synchronize{ TkVirtualEventTBL.clear }
+ }
class PreDefVirtEvent<self
def self.new(event, *sequences)
@@ -21,22 +28,30 @@ class TkVirtualEvent<TkObject
elsif event !~ /^<.*>$/
event = '<' + event + '>'
end
- if TkVirtualEvent::TkVirtualEventTBL.has_key?(event)
- TkVirtualEvent::TkVirtualEventTBL[event]
- else
- super(event, *sequences)
- 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
- TkVirtualEvent::TkVirtualEventTBL[@id] = self
- add(*sequences)
+ _add_sequences(sequences)
end
end
def TkVirtualEvent.getobj(event)
- obj = TkVirtualEventTBL[event]
+ obj = nil
+ TkVirtualEventTBL.mutex.synchronize{
+ obj = TkVirtualEventTBL[event]
+ }
if obj
obj
else
@@ -55,19 +70,31 @@ class TkVirtualEvent<TkObject
end
def initialize(*sequences)
- # @path = @id = '<' + TkVirtualEventID.join('') + '>'
- @path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>'
- TkVirtualEventID[1].succ!
- add(*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)
- if sequences != []
+ def _add_sequences(seq_ary)
+ unless seq_ary.empty?
tk_call_without_enc('event', 'add', "<#{@id}>",
- *(sequences.collect{|seq|
+ *(seq_ary.collect{|seq|
"<#{tk_event_sequence(seq)}>"
}) )
- TkVirtualEventTBL[@id] = self
+ end
+ self
+ end
+ private :_add_sequences
+
+ def add(*sequences)
+ if sequences != []
+ _add_sequences(sequences)
+ TkVirtualEventTBL.mutex.synchronize{
+ TkVirtualEventTBL[@id] = self
+ }
end
self
end
@@ -75,20 +102,26 @@ class TkVirtualEvent<TkObject
def delete(*sequences)
if sequences == []
tk_call_without_enc('event', 'delete', "<#{@id}>")
- TkVirtualEventTBL.delete(@id)
+ TkVirtualEventTBL.mutex.synchronize{
+ TkVirtualEventTBL.delete(@id)
+ }
else
tk_call_without_enc('event', 'delete', "<#{@id}>",
*(sequences.collect{|seq|
"<#{tk_event_sequence(seq)}>"
}) )
- TkVirtualEventTBL.delete(@id) if info == []
+ 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|
- l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
+ lst = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
case (subseq)
when /^<<[^<>]+>>$/
TkVirtualEvent.getobj(subseq[1..-2])
@@ -98,7 +131,7 @@ class TkVirtualEvent<TkObject
subseq.split('')
end
}.flatten
- (l.size == 1) ? l[0] : l
+ (lst.size == 1) ? lst[0] : lst
}
end
end
diff --git a/ext/tk/lib/tk/winpkg.rb b/ext/tk/lib/tk/winpkg.rb
index 737fb959b5..89fb391c77 100644
--- a/ext/tk/lib/tk/winpkg.rb
+++ b/ext/tk/lib/tk/winpkg.rb
@@ -7,9 +7,14 @@
#
require 'tk'
-module TkWinDDE
+module Tk::WinDDE
+end
+#TkWinDDE = Tk::WinDDE
+Tk.__set_toplevel_aliases__(:Tk, Tk::WinDDE, :TkWinDDE)
+
+module Tk::WinDDE
extend Tk
- extend TkWinDDE
+ extend Tk::WinDDE
TkCommandNames = ['dde'.freeze].freeze
@@ -85,9 +90,14 @@ module TkWinDDE
:poke, :request, :services, :eval
end
-module TkWinRegistry
+module Tk::WinRegistry
+end
+#TkWinRegistry = Tk::WinRegistry
+Tk.__set_toplevel_aliases__(:Tk, Tk::WinRegistry, :TkWinRegistry)
+
+module Tk::WinRegistry
extend Tk
- extend TkWinRegistry
+ extend Tk::WinRegistry
TkCommandNames = ['registry'.freeze].freeze
diff --git a/ext/tk/lib/tk/wm.rb b/ext/tk/lib/tk/wm.rb
index 1f432a3848..0394296189 100644
--- a/ext/tk/lib/tk/wm.rb
+++ b/ext/tk/lib/tk/wm.rb
@@ -5,273 +5,407 @@ require 'tk'
module Tk
module Wm
- include TkComm
+ #include TkComm
+ extend TkCore
TkCommandNames = ['wm'.freeze].freeze
TOPLEVEL_METHODCALL_OPTKEYS = {}
- def aspect(*args)
+ def Wm.aspect(win, *args)
if args.length == 0
- list(tk_call_without_enc('wm', 'aspect', path))
+ 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', path, *args)
- self
+ 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 attributes(slot=nil,value=None)
+ def Wm.attributes(win, slot=nil,value=TkComm::None)
if slot == nil
- lst = tk_split_list(tk_call('wm', 'attributes', path))
+ 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', path, *hash_kv(slot))
- self
- elsif value == None
- tk_call('wm', 'attributes', path, "-#{slot}")
+ 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', path, "-#{slot}", value)
- self
+ 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 client(name=None)
- if name == None
- tk_call('wm', 'client', path)
+ 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', path, name)
- self
+ 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 colormapwindows(*args)
+ def Wm.colormapwindows(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'colormapwindows', path))
+ 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', path, *args)
- self
+ 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(value=nil)
+ def Wm.command(win, value=nil)
if value
- tk_call('wm', 'command', path, value)
- self
+ tk_call('wm', 'command', epath, value)
+ win
else
- #procedure(tk_call('wm', 'command', path))
- tk_call('wm', 'command', path)
+ #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 deiconify(ex = true)
+ def Wm.deiconify(win, ex = true)
if ex
- tk_call_without_enc('wm', 'deiconify', path)
+ tk_call_without_enc('wm', 'deiconify', win.epath)
else
- self.iconify
+ Wm.iconify(win)
end
- self
+ win
end
+ def deiconify(ex = true)
+ Wm.deiconify(self, ex)
+ end
+ alias wm_deiconify deiconify
- def focusmodel(mode = nil)
+ def Wm.focusmodel(win, mode = nil)
if mode
- tk_call_without_enc('wm', 'focusmodel', path, mode)
- self
+ tk_call_without_enc('wm', 'focusmodel', win.epath, mode)
+ win
else
- tk_call_without_enc('wm', 'focusmodel', path)
+ 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
- tk_call_without_enc('wm', 'frame', path)
+ Wm.frame(self)
end
+ alias wm_frame frame
- def geometry(geom=nil)
+ def Wm.geometry(win, geom=nil)
if geom
- tk_call_without_enc('wm', 'geometry', path, geom)
- self
+ tk_call_without_enc('wm', 'geometry', win.epath, geom)
+ win
else
- tk_call_without_enc('wm', 'geometry', path)
+ 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(*args)
+ def Wm.grid(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'grid', path))
+ 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', path, *args)
- self
+ 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 group(leader = nil)
+ def Wm.group(win, leader = nil)
if leader
- tk_call('wm', 'group', path, leader)
- self
+ tk_call('wm', 'group', win.epath, leader)
+ win
else
- window(tk_call('wm', 'group', path))
+ 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 iconbitmap(bmp=nil)
+ def Wm.iconbitmap(win, bmp=nil)
if bmp
- tk_call_without_enc('wm', 'iconbitmap', path, bmp)
- self
+ tk_call_without_enc('wm', 'iconbitmap', win.epath, bmp)
+ win
else
- image_obj(tk_call_without_enc('wm', 'iconbitmap', path))
+ 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 iconphoto(*imgs)
+ def Wm.iconphoto(win, *imgs)
if imgs.empty?
- @wm_iconphoto = nil unless defined? @wm_iconphoto
- return @wm_iconphoto
+ 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', path, *imgs)
- @wm_iconphoto = imgs
- self
+ 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 iconphoto_default(*imgs)
+ def Wm.iconphoto_default(win, *imgs)
imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array)
- tk_call_without_enc('wm', 'iconphoto', path, '-default', *imgs)
- self
+ 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 iconify(ex = true)
+ def Wm.iconify(win, ex = true)
if ex
- tk_call_without_enc('wm', 'iconify', path)
+ tk_call_without_enc('wm', 'iconify', win.epath)
else
- self.deiconify
+ Wm.deiconify(win)
end
- self
+ win
+ end
+ def iconify(ex = true)
+ Wm.iconify(self, ex)
end
+ alias wm_iconify iconify
- def iconmask(bmp=nil)
+ def Wm.iconmask(win, bmp=nil)
if bmp
- tk_call_without_enc('wm', 'iconmask', path, bmp)
- self
+ tk_call_without_enc('wm', 'iconmask', win.epath, bmp)
+ win
else
- image_obj(tk_call_without_enc('wm', 'iconmask', path))
+ 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 iconname(name=nil)
+ def Wm.iconname(win, name=nil)
if name
- tk_call('wm', 'iconname', path, name)
- self
+ tk_call('wm', 'iconname', win.epath, name)
+ win
else
- tk_call('wm', 'iconname', path)
+ 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 iconposition(*args)
+ def Wm.iconposition(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'iconposition', path))
+ 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', path, *args)
- self
+ 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 iconwindow(win = nil)
- if win
- tk_call_without_enc('wm', 'iconwindow', path, win)
- self
+ 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', path)
+ 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 maxsize(*args)
+ 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', path))
+ 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', path, *args)
- self
+ 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 minsize(*args)
+ def Wm.minsize(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'minsize', path))
+ 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', path, *args)
- self
+ 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 overrideredirect(mode=None)
- if mode == None
- bool(tk_call_without_enc('wm', 'overrideredirect', path))
+ 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', path, mode)
- self
+ 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 positionfrom(who=None)
- if who == None
- r = tk_call_without_enc('wm', 'positionfrom', path)
+ 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', path, who)
- self
+ 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 protocol(name=nil, cmd=nil, &b)
+ def Wm.protocol(win, name=nil, cmd=nil, &b)
if cmd
- tk_call_without_enc('wm', 'protocol', path, name, cmd)
- self
+ tk_call_without_enc('wm', 'protocol', win.epath, name, cmd)
+ win
elsif b
- tk_call_without_enc('wm', 'protocol', path, name, proc(&b))
- self
+ tk_call_without_enc('wm', 'protocol', win.epath, name, proc(&b))
+ win
elsif name
- result = tk_call_without_enc('wm', 'protocol', path, 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', path))
+ 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 protocols(kv=nil)
+ def Wm.protocols(win, kv=nil)
unless kv
ret = {}
- self.protocol.each{|name|
- ret[name] = self.protocol(name)
+ Wm.protocol(win).each{|name|
+ ret[name] = Wm.protocol(win, name)
}
return ret
end
@@ -279,82 +413,140 @@ module Tk
unless kv.kind_of?(Hash)
fail ArgumentError, 'expect a hash of protocol=>command'
end
- kv.each{|k, v| self.protocol(k, v)}
- self
+ 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 resizable(*args)
+ def Wm.resizable(win, *args)
if args.length == 0
- list(tk_call_without_enc('wm', 'resizable', path)).collect{|e| bool(e)}
+ 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', path, *args)
- self
+ 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 sizefrom(who=None)
- if who == None
- r = tk_call_without_enc('wm', 'sizefrom', path)
+ 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', path, who)
- self
+ 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
- list(tk_call('wm', 'stackorder', path))
+ Wm.stackorder(self)
end
+ alias wm_stackorder stackorder
- def stackorder_isabove(win)
- bool(tk_call('wm', 'stackorder', path, 'isabove', win))
+ 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 stackorder_isbelow(win)
- bool(tk_call('wm', 'stackorder', path, 'isbelow', win))
+ 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 state(st=nil)
+ def Wm.state(win, st=nil)
if st
- tk_call_without_enc('wm', 'state', path, st)
- self
+ tk_call_without_enc('wm', 'state', win.epath, st)
+ win
else
- tk_call_without_enc('wm', 'state', path)
+ 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 title(str=nil)
+ def Wm.title(win, str=nil)
if str
- tk_call('wm', 'title', path, str)
- self
+ tk_call('wm', 'title', win.epath, str)
+ win
else
- tk_call('wm', 'title', path)
+ 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 transient(master=nil)
+ def Wm.transient(win, master=nil)
if master
- tk_call_without_enc('wm', 'transient', path, master)
- self
+ tk_call_without_enc('wm', 'transient', win.epath, master)
+ win
else
- window(tk_call_without_enc('wm', 'transient', path))
+ 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 withdraw(ex = true)
+ def Wm.withdraw(win, ex = true)
if ex
- tk_call_without_enc('wm', 'withdraw', path)
+ tk_call_without_enc('wm', 'withdraw', win.epath)
else
- self.deiconify
+ Wm.deiconify(win)
end
- self
+ 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/tkextlib/SUPPORT_STATUS b/ext/tk/lib/tkextlib/SUPPORT_STATUS
index 15925cba72..cfbe274c86 100644
--- a/ext/tk/lib/tkextlib/SUPPORT_STATUS
+++ b/ext/tk/lib/tkextlib/SUPPORT_STATUS
@@ -83,7 +83,7 @@ BLT 2.4z http://sourceforge.net/projects/blt
TkTreeCtrl CVS/Hd(2005-12-02)
http://sourceforge.net/projects/tktreectrl ==> treectrl
-Tile 0.7.8
+Tile 0.8.0/8.5.1
http://sourceforge.net/projects/tktable ==> tile
diff --git a/ext/tk/lib/tkextlib/blt/bitmap.rb b/ext/tk/lib/tkextlib/blt/bitmap.rb
index 31cf8d4229..23c6d2d064 100644
--- a/ext/tk/lib/tkextlib/blt/bitmap.rb
+++ b/ext/tk/lib/tkextlib/blt/bitmap.rb
@@ -13,7 +13,16 @@ module Tk::BLT
TkCommandNames = ['::blt::bitmap'.freeze].freeze
BITMAP_ID_TBL = TkCore::INTERP.create_table
- BITMAP_ID = ['blt_bitmap_id'.freeze, '00000'.taint].freeze
+
+ (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))
@@ -64,9 +73,13 @@ module Tk::BLT
if name
@id = name
else
- @id = BITMAP_ID.join(TkCore::INTERP._ip_id_)
- BITMAP_ID[1].succ!
- BITMAP_ID_TBL[@id] = self
+ 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
diff --git a/ext/tk/lib/tkextlib/blt/busy.rb b/ext/tk/lib/tkextlib/blt/busy.rb
index 4726e466f4..2f807fcd9c 100644
--- a/ext/tk/lib/tkextlib/blt/busy.rb
+++ b/ext/tk/lib/tkextlib/blt/busy.rb
@@ -19,7 +19,7 @@ module Tk::BLT
class Shield < TkWindow
def self.shield_path(win)
win = window(win) unless win.kind_of?(TkWindow)
- if win.kind_of?(TkToplevel)
+ if win.kind_of?(Tk::Toplevel)
win.path + '._Busy'
else
win.path + '_Busy'
diff --git a/ext/tk/lib/tkextlib/blt/component.rb b/ext/tk/lib/tkextlib/blt/component.rb
index ad78a5430b..b2005b2f2b 100644
--- a/ext/tk/lib/tkextlib/blt/component.rb
+++ b/ext/tk/lib/tkextlib/blt/component.rb
@@ -85,6 +85,9 @@ module Tk::BLT
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)
@@ -118,6 +121,9 @@ module Tk::BLT
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
@@ -131,6 +137,9 @@ module Tk::BLT
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)
@@ -152,6 +161,9 @@ module Tk::BLT
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)
@@ -173,6 +185,9 @@ module Tk::BLT
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)
@@ -194,6 +209,9 @@ module Tk::BLT
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
@@ -207,6 +225,9 @@ module Tk::BLT
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
@@ -220,6 +241,9 @@ module Tk::BLT
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)
@@ -241,6 +265,9 @@ module Tk::BLT
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
@@ -254,6 +281,9 @@ module Tk::BLT
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)
@@ -273,11 +303,12 @@ module Tk::BLT
end
alias __itemcget itemcget
+ alias __itemcget_strict itemcget_strict
alias __itemconfiginfo itemconfiginfo
alias __current_itemconfiginfo current_itemconfiginfo
private :__itemcget, :__itemconfiginfo, :__current_itemconfiginfo
- def itemcget(tagOrId, option)
+ def itemcget_strict(tagOrId, option)
ret = __itemcget(tagid(tagOrId), option)
if option == 'bindtags' || option == :bindtags
ret.collect{|tag| TkBindTag.id2obj(tag)}
@@ -285,6 +316,27 @@ module Tk::BLT
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)
@@ -321,19 +373,30 @@ module Tk::BLT
ret
end
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
#################
class Axis < TkObject
- OBJ_ID = ['blt_chart_axis'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
+ (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
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
+ 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={})
@@ -341,12 +404,48 @@ module Tk::BLT
keys = axis
axis = nil
end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- return OBJ_TBL[chart.path][axis] if axis && OBJ_TBL[chart.path][axis]
- super(chart, axis, keys)
+ 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
@@ -354,13 +453,15 @@ module Tk::BLT
if axis
@axis = @id = axis.to_s
else
- @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
+ 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::OBJ_TBL[@cpath][@axis] = self
+ # Axis::AxisID_TBL[@cpath][@axis] = self
keys = _symbolkey2str(keys)
unless keys.delete('without_creating')
# @chart.axis_create(@axis, keys)
@@ -379,6 +480,9 @@ module Tk::BLT
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
@@ -438,17 +542,34 @@ module Tk::BLT
#################
class Crosshairs < TkObject
- OBJ_TBL={}
+ CrosshairsID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ CrosshairsID_TBL.mutex.synchronize{ CrosshairsID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(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::OBJ_TBL[@cpath] = self
+ # Crosshairs::CrosshairsID_TBL[@cpath] = self
@chart.crosshair_configure(keys) unless keys.empty?
@path = @id = 'crosshairs'
end
@@ -464,6 +585,9 @@ module Tk::BLT
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
@@ -500,12 +624,18 @@ module Tk::BLT
ElementTypeName = 'element'
ElementTypeToClass = { ElementTypeName=>self }
+
ElementID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ ElementID_TBL.clear }
+ TkCore::INTERP.init_ip_env{
+ ElementID_TBL.mutex.synchronize{ ElementID_TBL.clear }
+ }
- OBJ_ID = ['blt_chart_element'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
+ (OBJ_ID = ['blt_chart_element'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
def Element.type2class(type)
ElementTypeToClass[type]
@@ -513,8 +643,10 @@ module Tk::BLT
def Element.id2obj(chart, id)
cpath = chart.path
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
+ 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={})
@@ -522,14 +654,49 @@ module Tk::BLT
keys = element
element = nil
end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- if element && OBJ_TBL[chart.path][element]
- return OBJ_TBL[chart.path][element]
+ if keys
+ keys = _symbolkey2str(keys)
+ not_create = keys.delete('without_creating')
+ else
+ not_create = false
end
- super(chart, element, keys)
+
+ 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
@@ -537,14 +704,16 @@ module Tk::BLT
if element
@element = @id = element.to_s
else
- @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
+ 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::OBJ_TBL[@cpath][@element] = self
+ # Element::ElementID_TBL[@cpath][@element] = self
keys = _symbolkey2str(keys)
unless keys.delete('without_creating')
# @chart.element_create(@element, keys)
@@ -564,6 +733,9 @@ module Tk::BLT
# @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)
@@ -622,17 +794,33 @@ module Tk::BLT
#################
class GridLine < TkObject
- OBJ_TBL={}
+ GridLineID_TBL = TkCore::INTERP.create_table
+ TkCore::INTERP.init_ip_env{
+ GridLineID_TBL.mutex.synchronize{ GridLineID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(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::OBJ_TBL[@cpath] = self
+ # GridLine::GridLineID_TBL[@cpath] = self
@chart.gridline_configure(keys) unless keys.empty?
@path = @id = 'grid'
end
@@ -648,6 +836,9 @@ module Tk::BLT
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
@@ -676,18 +867,35 @@ module Tk::BLT
#################
class Legend < TkObject
- OBJ_TBL={}
+ LegendID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ LegendID_TBL.mutex.synchronize{ LegendID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(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
- Crosshairs::OBJ_TBL[@cpath] = self
- @chart.crosshair_configure(keys) unless keys.empty?
+ # Legend::LegendID_TBL[@cpath] = self
+ @chart.legend_configure(keys) unless keys.empty?
@path = @id = 'legend'
end
@@ -702,6 +910,9 @@ module Tk::BLT
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
@@ -729,13 +940,24 @@ module Tk::BLT
#################
class Pen < TkObject
- OBJ_ID = ['blt_chart_pen'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
+ (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
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
+ 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={})
@@ -743,9 +965,43 @@ module Tk::BLT
keys = pen
pen = nil
end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- return OBJ_TBL[chart.path][pen] if pen && OBJ_TBL[chart.path][pen]
- super(chart, pen, keys)
+ 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={})
@@ -756,13 +1012,15 @@ module Tk::BLT
if pen
@pen = @id = pen.to_s
else
- @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
+ 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::OBJ_TBL[@cpath][@pen] = self
+ Pen::PenID_TBL[@cpath][@pen] = self
keys = _symbolkey2str(keys)
unless keys.delete('without_creating')
# @chart.pen_create(@pen, keys)
@@ -781,6 +1039,9 @@ module Tk::BLT
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
@@ -805,17 +1066,34 @@ module Tk::BLT
#################
class Postscript < TkObject
- OBJ_TBL={}
+ PostscriptID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ PostscriptID_TBL.mutex.synchronize{ PostscriptID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(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::OBJ_TBL[@cpath] = self
+ # Postscript::PostscriptID_TBL[@cpath] = self
@chart.postscript_configure(keys) unless keys.empty?
@path = @id = 'postscript'
end
@@ -831,6 +1109,9 @@ module Tk::BLT
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
@@ -870,7 +1151,9 @@ module Tk::BLT
MarkerTypeToClass = {}
MarkerID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ MarkerID_TBL.clear }
+ TkCore::INTERP.init_ip_env{
+ MarkerID_TBL.mutex.synchronize{ MarkerID_TBL.clear }
+ }
def Marker.type2class(type)
MarkerTypeToClass[type]
@@ -878,8 +1161,13 @@ module Tk::BLT
def Marker.id2obj(chart, id)
cpath = chart.path
- return id unless MarkerID_TBL[cpath]
- MarkerID_TBL[cpath][id]? MarkerID_TBL[cpath][id]: id
+ 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)
@@ -902,6 +1190,13 @@ module Tk::BLT
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)
@@ -943,10 +1238,10 @@ module Tk::BLT
@parent = @chart = chart
@cpath = chart.path
@id = id
- unless Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath]
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] = {}
- end
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ 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
@@ -956,10 +1251,10 @@ module Tk::BLT
@cpath = parent.path
@path = @id = create_self(*args) # an integer number as 'item id'
- unless Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath]
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] = {}
- end
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ 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'
@@ -977,6 +1272,9 @@ module Tk::BLT
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
@@ -1037,14 +1335,14 @@ module Tk::BLT
#################
def __destroy_hook__
- Axis::OBJ_TBL.delete(@path)
- Crosshairs::OBJ_TBL.delete(@path)
- Element::OBJ_TBL.delete(@path)
- GridLine::OBJ_TBL.delete(@path)
- Legend::OBJ_TBL.delete(@path)
- Pen::OBJ_TBL.delete(@path)
- Postscript::OBJ_TBL.delete(@path)
- Marker::OBJ_TBL.delete(@path)
+ 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
@@ -1559,6 +1857,9 @@ module Tk::BLT
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)
@@ -1628,6 +1929,9 @@ module Tk::BLT
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)
@@ -1697,6 +2001,9 @@ module Tk::BLT
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)
@@ -1766,6 +2073,9 @@ module Tk::BLT
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)
diff --git a/ext/tk/lib/tkextlib/blt/dragdrop.rb b/ext/tk/lib/tkextlib/blt/dragdrop.rb
index 68fb9e591a..201548504a 100644
--- a/ext/tk/lib/tkextlib/blt/dragdrop.rb
+++ b/ext/tk/lib/tkextlib/blt/dragdrop.rb
@@ -81,6 +81,24 @@ module Tk::BLT
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)
@@ -107,6 +125,24 @@ module Tk::BLT
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)
@@ -145,6 +181,24 @@ module Tk::BLT
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
diff --git a/ext/tk/lib/tkextlib/blt/eps.rb b/ext/tk/lib/tkextlib/blt/eps.rb
index 586a42470c..0dba87a7cc 100644
--- a/ext/tk/lib/tkextlib/blt/eps.rb
+++ b/ext/tk/lib/tkextlib/blt/eps.rb
@@ -14,7 +14,7 @@ module Tk::BLT
end
end
-class TkCanvas
+class Tk::Canvas
alias __BLT_EPS_item_strval_optkeys __item_strval_optkeys
def __item_strval_optkeys(id)
__BLT_EPS_item_strval_optkeys(id) + [
diff --git a/ext/tk/lib/tkextlib/blt/htext.rb b/ext/tk/lib/tkextlib/blt/htext.rb
index a0cf3dc036..0d9cb30185 100644
--- a/ext/tk/lib/tkextlib/blt/htext.rb
+++ b/ext/tk/lib/tkextlib/blt/htext.rb
@@ -22,6 +22,7 @@ module Tk::BLT
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
diff --git a/ext/tk/lib/tkextlib/blt/table.rb b/ext/tk/lib/tkextlib/blt/table.rb
index 0be9d8d42a..dfa10269ed 100644
--- a/ext/tk/lib/tkextlib/blt/table.rb
+++ b/ext/tk/lib/tkextlib/blt/table.rb
@@ -29,6 +29,9 @@ module Tk::BLT
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)
@@ -92,6 +95,9 @@ module Tk::BLT
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)
@@ -136,12 +142,13 @@ class << Tk::BLT::Table
private :__item_pathname
alias __itemcget itemcget
+ alias __itemcget_strict itemcget_strict
alias __itemconfigure itemconfigure
alias __itemconfiginfo itemconfiginfo
alias __current_itemconfiginfo current_itemconfiginfo
- private :__itemcget, :__itemconfigure
- private :__itemconfiginfo, :__current_itemconfiginfo
+ private :__itemcget, :__itemcget_strict
+ private :__itemconfigure, :__itemconfiginfo, :__current_itemconfiginfo
def __boolval_optkeys
super() << 'propagate'
@@ -176,6 +183,9 @@ class << Tk::BLT::Table
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)
@@ -192,6 +202,9 @@ class << Tk::BLT::Table
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)
diff --git a/ext/tk/lib/tkextlib/blt/tabset.rb b/ext/tk/lib/tkextlib/blt/tabset.rb
index c26b6ee001..ca81ad8f95 100644
--- a/ext/tk/lib/tkextlib/blt/tabset.rb
+++ b/ext/tk/lib/tkextlib/blt/tabset.rb
@@ -12,14 +12,26 @@ module Tk::BLT
include TkTreatItemFont
TabID_TBL = TkCore::INTERP.create_table
- TabsetTab_ID = ['blt_tabset_tab'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TabID_TBL.clear }
+ (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
- return id unless TabID_TBL[tpath]
- TabID_TBL[tpath][id]? TabID_TBL[tpath]: id
+ 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={})
@@ -32,12 +44,20 @@ module Tk::BLT
keys = name
name = nil
end
-
- if name && TabID_TBL[parent.path] && TabID_TBL[parent.path][name]
- TabID_TBL[parent.path][name]
- else
- super(parent, pos, name, keys)
- 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)
@@ -45,9 +65,6 @@ module Tk::BLT
@tpath = parent.path
if name
@path = @id = name
- TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath]
- TabID_TBL[@tpath][@id] = self
-
unless (list(tk_call(@tpath, 'tab', 'names', @id)).empty?)
if pos
idx = tk_call(@tpath, 'index', '-name', @id)
@@ -58,18 +75,18 @@ module Tk::BLT
end
end
tk_call(@tpath, 'tab', 'configure', @id, keys)
- return
+ else
+ pos = 'end' unless pos
+ tk_call(@tpath, 'insert', pos, @id, keys)
end
-
else
- @path = @id = TabsetTab_ID.join(TkCore::INTERP._ip_id_)
- TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath]
- TabID_TBL[@tpath][@id] = self
- TabsetTab_ID[1].succ!
+ 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
-
- pos = 'end' unless pos
- tk_call(@tpath, 'insert', pos, @id, keys)
end
#def bind(context, cmd=Proc.new, *args)
@@ -111,6 +128,9 @@ module Tk::BLT
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
@@ -123,7 +143,9 @@ module Tk::BLT
def delete()
@t.delete(@id)
- TabID_TBL[@tpath].delete(@id)
+ TabID_TBL.mutex.synchronize{
+ TabID_TBL[@tpath].delete(@id)
+ }
self
end
@@ -184,7 +206,9 @@ module Tk::BLT
WidgetClassNames[WidgetClassName] = self
def __destroy_hook__
- Tk::BLT::Tabset::Tab::TabID_TBL.delete(@path)
+ Tk::BLT::Tabset::Tab::TabID_TBL.mutex.synchronize{
+ Tk::BLT::Tabset::Tab::TabID_TBL.delete(@path)
+ }
end
########################################
@@ -219,6 +243,7 @@ module Tk::BLT
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
@@ -291,11 +316,15 @@ module Tk::BLT
def delete(first, last=None)
tk_send('delete', tagindex(first), tagindex(last))
if first.kind_of?(Tk::BLT::Tabset::Tab)
- TabID_TBL[@path].delete(first.id)
+ 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[@path].delete(last.id)
+ TabID_TBL.mutex.synchronize{
+ TabID_TBL[@path].delete(last.id)
+ }
end
self
end
diff --git a/ext/tk/lib/tkextlib/blt/ted.rb b/ext/tk/lib/tkextlib/blt/ted.rb
index 39495842b4..670265fc78 100644
--- a/ext/tk/lib/tkextlib/blt/ted.rb
+++ b/ext/tk/lib/tkextlib/blt/ted.rb
@@ -30,11 +30,14 @@ module Tk::BLT
end
private :__item_config_cmd
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
def cget(master, option)
- itemconfigure(master, slot, value)
+ itemcget(master, option)
+ end
+ def cget_strict(master, option)
+ itemcget_strict(master, option)
end
def configure(master, slot, value=None)
itemconfigure(master, slot, value)
diff --git a/ext/tk/lib/tkextlib/blt/tile/button.rb b/ext/tk/lib/tkextlib/blt/tile/button.rb
index dd715c8b98..2e0863cfbe 100644
--- a/ext/tk/lib/tkextlib/blt/tile/button.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/button.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Button < TkButton
+ class Button < Tk::Button
TkCommandNames = ['::blt::tile::button'.freeze].freeze
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb b/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb
index ad58999d86..da230b5925 100644
--- a/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/checkbutton.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class CheckButton < TkCheckButton
+ class CheckButton < Tk::CheckButton
TkCommandNames = ['::blt::tile::checkbutton'.freeze].freeze
end
Checkbutton = CheckButton
diff --git a/ext/tk/lib/tkextlib/blt/tile/frame.rb b/ext/tk/lib/tkextlib/blt/tile/frame.rb
index 10469fd35f..5434af4b72 100644
--- a/ext/tk/lib/tkextlib/blt/tile/frame.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/frame.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Frame < TkFrame
+ class Frame < Tk::Frame
TkCommandNames = ['::blt::tile::frame'.freeze].freeze
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tile/label.rb b/ext/tk/lib/tkextlib/blt/tile/label.rb
index ec67babd58..f370c1403b 100644
--- a/ext/tk/lib/tkextlib/blt/tile/label.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/label.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Label < TkLabel
+ class Label < Tk::Label
TkCommandNames = ['::blt::tile::label'.freeze].freeze
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb b/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb
index 2316923b19..814f9a5cc4 100644
--- a/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/radiobutton.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class RadioButton < TkRadioButton
+ class RadioButton < Tk::RadioButton
TkCommandNames = ['::blt::tile::radiobutton'.freeze].freeze
end
Radiobutton = RadioButton
diff --git a/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb b/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb
index ba3bf316f0..2ae871d518 100644
--- a/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/scrollbar.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Scrollbar < TkScrollbar
+ class Scrollbar < Tk::Scrollbar
TkCommandNames = ['::blt::tile::scrollbar'.freeze].freeze
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tile/toplevel.rb b/ext/tk/lib/tkextlib/blt/tile/toplevel.rb
index 6cc2c91415..76d5f86b1b 100644
--- a/ext/tk/lib/tkextlib/blt/tile/toplevel.rb
+++ b/ext/tk/lib/tkextlib/blt/tile/toplevel.rb
@@ -9,7 +9,7 @@ require 'tkextlib/blt/tile.rb'
module Tk::BLT
module Tile
- class Toplevel < TkToplevel
+ class Toplevel < Tk::Toplevel
TkCommandNames = ['::blt::tile::toplevel'.freeze].freeze
end
end
diff --git a/ext/tk/lib/tkextlib/blt/tree.rb b/ext/tk/lib/tkextlib/blt/tree.rb
index 07dc7ef7e8..77b85f1717 100644
--- a/ext/tk/lib/tkextlib/blt/tree.rb
+++ b/ext/tk/lib/tkextlib/blt/tree.rb
@@ -12,53 +12,77 @@ module Tk::BLT
###################################
- class Node < TkObject
+ class Node < TkObject
TreeNodeID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TreeNodeID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ TreeNodeID_TBL.mutex.synchronize{ TreeNodeID_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TreeNodeID_TBL[tpath]
- if TreeNodeID_TBL[tpath][id]
- TreeNodeID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, 'node'=>Integer(id))
- rescue
+ 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
+ }
end
def self.new(tree, parent, keys={})
keys = _symbolkey2str(keys)
tpath = tree.path
- 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
+ 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
- super(tree, parent, keys)
+ (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
- parent = tk_call(@tpath, 'root') unless parent
-
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
-
- TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath]
- TreeNodeID_TBL[@tpath][@id] = self
end
def id
@@ -243,17 +267,42 @@ module Tk::BLT
class Tag < TkObject
TreeTagID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TreeTagID_TBL.clear }
- TreeTag_ID = ['blt_tree_tag'.freeze, '00000'.taint].freeze
+
+ 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
- return id unless TreeTagID_TBL[tpath]
- if TreeTagID_TBL[tpath][id]
- TreeTagID_TBL[tpath][id]
- else
- self.new(tree, id)
- end
+ 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)
@@ -263,12 +312,15 @@ module Tk::BLT
if tag_str
@path = @id = tag_str.dup.freeze
else
- @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_)
- TreeTagID_TBL[@id] = self
- TreeTag_ID[1].succ!
+ TreeTag_ID.mutex.synchronize{
+ @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_)
+ TreeTag_ID[1].succ!
+ }
end
- TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
- TreeTagID_TBL[@tpath][@id] = self
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
end
def id
@@ -287,7 +339,9 @@ module Tk::BLT
def forget()
tk_call(@tpath, 'tag', 'forget', @id)
- TreeTagID_TBL[@tpath].delete(@id)
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@tpath].delete(@id)
+ }
self
end
@@ -312,44 +366,63 @@ module Tk::BLT
class Notify < TkObject
NotifyID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ NotifyID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ NotifyID_TBL.mutex.synchronize{ NotifyID_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless NotifyID_TBL[tpath]
- if NotifyID_TBL[tpath][id]
- NotifyID_TBL[tpath][id]
- else
- begin
- self.new([tree, id])
- rescue
- id
+ 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
+ }
end
def self.new(tree, *args, &b)
- if tree.kind_of?(Array)
- # not create
- if obj = NotifyID_TBL[tree[0].path][tree[1]]
+ 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
- else
- return super(false, tree[0], tree[1])
end
- end
- super(true, tree, *args, &b)
+ (obj = self.allocate).instance_eval{
+ initialize(tree, *args, &b)
+ NotifyID_TBL[@tpath] ||= {}
+ NotifyID_TBL[@tpath][@id] = self
+ }
+ return obj
+ }
end
- def initialize(create, tree, *args, &b)
+ def initialize(tree, *args, &b)
@parent = @tree = tree
@tpath = @parent.path
- unless create
- @path = @id = args[0]
- return
- end
-
# if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
if TkComm._callback_entry?(args[0])
cmd = args.shift
@@ -378,7 +451,9 @@ module Tk::BLT
def delete()
tk_call(@tpath, 'notify', 'delete', @id)
- NotifyID_TBL[tpath].delete(@id)
+ NotifyID_TBL.mutex.synchronize{
+ NotifyID_TBL[@tpath].delete(@id)
+ }
self
end
@@ -395,44 +470,69 @@ module Tk::BLT
class Trace < TkObject
TraceID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TraceID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ TraceID_TBL.mutex.synchronize{ TraceID_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TraceID_TBL[tpath]
- if TraceID_TBL[tpath][id]
- TraceID_TBL[tpath][id]
- else
- begin
- self.new([tree, id])
- rescue
+ 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
+ }
end
def self.new(tree, *args, &b)
- if tree.kind_of?(Array)
- # not create
- if obj = TraceID_TBL[tree[0].path][tree[1]]
+ 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
- else
- return super(false, tree[0], tree[1])
end
- end
- super(true, tree, *args, &b)
+ # 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(create, tree, node, key, opts, cmd=nil, &b)
+ def initialize(tree, node, key, opts, cmd=nil, &b)
@parent = @tree = tree
@tpath = @parent.path
- unless create
- @path = @id = node # == traceID
- return
- end
-
if !cmd
if b
cmd = Proc.new(&b)
@@ -459,7 +559,9 @@ module Tk::BLT
def delete()
tk_call(@tpath, 'trace', 'delete', @id)
- TraceID_TBL[tpath].delete(@id)
+ TraceID_TBL.mutex.synchronize{
+ TraceID_TBL[tpath].delete(@id)
+ }
self
end
@@ -475,7 +577,12 @@ module Tk::BLT
###################################
TreeID_TBL = TkCore::INTERP.create_table
- Tree_ID = ['blt_tree'.freeze, '00000'.taint].freeze
+
+ (Tree_ID = ['blt_tree'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
def __keyonly_optkeys
{
@@ -498,7 +605,9 @@ module Tk::BLT
end
def self.id2obj(id)
- TreeID_TBL[id]? TreeID_TBL[id]: id
+ TreeID_TBL.mutex.synchronize{
+ TreeID_TBL[id]? TreeID_TBL[id]: id
+ }
end
def self.names(pat = None)
@@ -513,27 +622,45 @@ module Tk::BLT
end
def self.new(name = nil)
- return TreeID_TBL[name] if name && TreeID_TBL[name]
- super(name)
+ 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
- @path = @id = Tree_ID.join(TkCore::INTERP._ip_id_)
- TreeID_TBL[@id] = self
- Tree_ID[1].succ!
+ Tree_ID.mutex.synchronize{
+ @path = @id = Tree_ID.join(TkCore::INTERP._ip_id_)
+ Tree_ID[1].succ!
+ }
end
- TreeID_TBL[@id] = self
+
tk_call('::blt::tree', 'create', @id)
end
def __destroy_hook__
- Tk::BLT::Tree::Node::TreeNodeID_TBL.delete(@path)
- Tk::BLT::Tree::Tag::TreeTagID_TBL.delete(@path)
- Tk::BLT::Tree::Notify::NotifyID_TBL.delete(@path)
- Tk::BLT::Tree::Trace::TraceID_TBL.delete(@path)
+ 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)
@@ -592,12 +719,14 @@ module Tk::BLT
def delete(*nodes)
tk_call('::blt::tree', 'delete', *(nodes.collect{|node| tagid(node)}))
- 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
+ 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
@@ -728,7 +857,9 @@ module Tk::BLT
id.delete
else
tk_call(@path, 'notify', 'delete', id)
- Tk::BLT::Tree::Notify::NotifyID_TBL[@path].delete(id.to_s)
+ Tk::BLT::Tree::Notify::NotifyID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Notify::NotifyID_TBL[@path].delete(id.to_s)
+ }
end
self
end
@@ -835,7 +966,9 @@ module Tk::BLT
def tag_forget(tag)
tag = tag.id if tag.kind_of?(Tk::BLT::Tree::Tag)
tk_call(@path, 'tag', 'forget', tag)
- TreeTagID_TBL[@path].delete(tag)
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@path].delete(tag)
+ }
self
end
@@ -889,7 +1022,9 @@ module Tk::BLT
def trace_delete(*args)
args = args.collect{|id| tagid(id)}
tk_call(@path, 'trace', 'delete', *args)
- args.each{|id| Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s)}
+ Tk::BLT::Tree::Trace::TraceID_TBL.mutex.synchronize{
+ args.each{|id| Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s)}
+ }
self
end
diff --git a/ext/tk/lib/tkextlib/blt/treeview.rb b/ext/tk/lib/tkextlib/blt/treeview.rb
index 0343d28b9c..c5a5697186 100644
--- a/ext/tk/lib/tkextlib/blt/treeview.rb
+++ b/ext/tk/lib/tkextlib/blt/treeview.rb
@@ -98,6 +98,9 @@ module Tk::BLT::Treeview::ConfigMethod
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
@@ -111,6 +114,9 @@ module Tk::BLT::Treeview::ConfigMethod
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
@@ -129,6 +135,14 @@ module Tk::BLT::Treeview::ConfigMethod
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
@@ -170,6 +184,9 @@ module Tk::BLT::Treeview::ConfigMethod
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
@@ -183,6 +200,9 @@ module Tk::BLT::Treeview::ConfigMethod
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
@@ -193,8 +213,8 @@ module Tk::BLT::Treeview::ConfigMethod
current_itemconfiginfo('text', slot)
end
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
end
class Tk::BLT::Treeview
@@ -239,6 +259,24 @@ class Tk::BLT::Treeview
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)
@@ -273,8 +311,12 @@ class Tk::BLT::Treeview
########################
def __destroy_hook__
- Tk::BLT::Treeview::Node::TreeNodeID_TBL.delete(@path)
- Tk::BLT::Treeview::Tag::TreeTagID_TBL.delete(@path)
+ 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)
@@ -472,6 +514,24 @@ class Tk::BLT::Treeview
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)
@@ -487,7 +547,8 @@ class Tk::BLT::Treeview
def _find_exec_flag_value(val)
if val.kind_of?(Array)
cmd, *args = val
- FindExecFlagValue.new(cmd, args.join(' '))
+ #FindExecFlagValue.new(cmd, args.join(' '))
+ FindExecFlagValue.new(cmd, *args)
elsif TkComm._callback_entry?(val)
FindExecFlagValue.new(val)
else
@@ -967,22 +1028,47 @@ 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].freeze
- TkCore::INTERP.init_ip_env{ TreeNodeID_TBL.clear }
+ (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
- return id unless TreeNodeID_TBL[tpath]
- if TreeNodeID_TBL[tpath][id]
- TreeNodeID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, nil, 'node'=>Integer(id))
- rescue
+ 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
+ }
end
def self.new(tree, pos, parent=nil, keys={})
@@ -994,13 +1080,21 @@ class Tk::BLT::Treeview::Node < TkObject
keys = _symbolkey2str(keys)
tpath = tree.path
- 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
+ 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)
+ #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)
@@ -1008,11 +1102,18 @@ class Tk::BLT::Treeview::Node < TkObject
@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 = TreeNode_ID.join(TkCore::INTERP._ip_id_).freeze
- TreeNode_ID[1].succ!
+ name = nil
+ TreeNode_ID.mutex.synchronize{
+ name = TreeNode_ID.join(TkCore::INTERP._ip_id_).freeze
+ TreeNode_ID[1].succ!
+ }
at = keys.delete['at']
@@ -1035,9 +1136,6 @@ class Tk::BLT::Treeview::Node < TkObject
end
@path = @id
end
-
- TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath]
- TreeNodeID_TBL[@tpath][@id] = self
end
def id
@@ -1051,37 +1149,66 @@ 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].freeze
- TkCore::INTERP.init_ip_env{ TreeTagID_TBL.clear }
+ (TreeTag_ID = ['blt_treeview_tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
- def self.id2obj(tree, id)
+ TkCore::INTERP.init_ip_env{
+ TreeTagID_TBL.mutex.synchronize{ TreeTagID_TBL.clear }
+ }
+
+ def self.id2obj(tree, name)
tpath = tree.path
- return id unless TreeTagID_TBL[tpath]
- if TreeTagID_TBL[tpath][id]
- TreeTagID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, nil, 'name'=>Integer(id))
- rescue
+ 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
+ }
end
def self.new_by_name(tree, name, *ids)
- if (obj = TreeTagID_TBL[tree.path][name])
- return obj
- end
- new([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)
- if tree.kind_of?(Array)
- super(tree[0], tree[1], ids)
- else
- super(tree, nil, ids)
- end
+ 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)
@@ -1091,13 +1218,12 @@ class Tk::BLT::Treeview::Tag < TkObject
if name
@path = @id = name
else
- @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_).freeze
- TreeTag_ID[1].succ!
+ TreeTag_ID.mutex.synchronize{
+ @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_).freeze
+ TreeTag_ID[1].succ!
+ }
end
- TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
- TreeTagID_TBL[@tpath][@id] = self
-
unless ids.empty?
tk_call(@tpath, 'tag', 'add', @id, *(ids.collect{|id| tagid(id)}))
end
diff --git a/ext/tk/lib/tkextlib/blt/unix_dnd.rb b/ext/tk/lib/tkextlib/blt/unix_dnd.rb
index 3130c1e56f..445002d7a5 100644
--- a/ext/tk/lib/tkextlib/blt/unix_dnd.rb
+++ b/ext/tk/lib/tkextlib/blt/unix_dnd.rb
@@ -30,11 +30,14 @@ module Tk::BLT
end
private :__item_config_cmd
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
def cget(win, option)
- itemconfigure(['cget', win], slot, value)
+ 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)
@@ -46,8 +49,11 @@ module Tk::BLT
current_itemconfiginfo(['configure', win], slot)
end
- def tokwn_cget(win, option)
- itemconfigure(['token', 'cget', win], slot, value)
+ 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)
diff --git a/ext/tk/lib/tkextlib/blt/vector.rb b/ext/tk/lib/tkextlib/blt/vector.rb
index 540b6b9102..76c12a24e8 100644
--- a/ext/tk/lib/tkextlib/blt/vector.rb
+++ b/ext/tk/lib/tkextlib/blt/vector.rb
@@ -23,14 +23,17 @@ module Tk::BLT
end
def self.names(pat=None)
- simplelist(tk_call('::blt::vector', 'names', pat)).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
+ 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
@@ -53,7 +56,9 @@ module Tk::BLT
"#auto", *hash_kv(keys))
end
- TkVar_ID_TBL[@id] = self
+ TkVar_ID_TBL.mutex.synchronize{
+ TkVar_ID_TBL[@id] = self
+ }
@def_default = false
@default_val = nil
@@ -221,13 +226,21 @@ module Tk::BLT
class VectorAccess < Vector
def self.new(name)
- return TkVar_ID_TBL[name] if TkVar_ID_TBL[name]
- super(name, size=nil, keys={})
+ 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
- TkVar_ID_TBL[@id] = self
@def_default = false
@default_val = nil
diff --git a/ext/tk/lib/tkextlib/blt/watch.rb b/ext/tk/lib/tkextlib/blt/watch.rb
index ae5e50f126..219ff78e97 100644
--- a/ext/tk/lib/tkextlib/blt/watch.rb
+++ b/ext/tk/lib/tkextlib/blt/watch.rb
@@ -13,11 +13,23 @@ module Tk::BLT
TkCommandNames = ['::blt::watch'.freeze].freeze
WATCH_ID_TBL = TkCore::INTERP.create_table
- BLT_WATCH_ID = ['blt_watch_id'.freeze, '00000'.taint].freeze
+
+ (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)
- tk_split_list(tk_call('::blt::watch', 'names', state)).collect{|name|
- WATCH_ID_TBL[name] || name
+ lst = tk_split_list(tk_call('::blt::watch', 'names', state))
+ WATCH_ID_TBL.mutex.synchronize{
+ lst.collect{|name|
+ WATCH_ID_TBL[name] || name
+ }
}
end
@@ -45,13 +57,17 @@ module Tk::BLT
if name
@id = name.to_s
else
- @id = BLT_WATCH_ID.join(TkCore::INTERP._ip_id_)
- BLT_WATCH_ID[1].succ!
+ 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[@id] = self
+ WATCH_ID_TBL.mutex.synchronize{
+ WATCH_ID_TBL[@id] = self
+ }
tk_call('::blt::watch', 'create', @id, *hash_kv(keys))
end
@@ -130,7 +146,7 @@ module Tk::BLT
end
end
end
- def cget(key)
+ def cget_strict(key)
key = key.to_s
begin
info.assoc(key)[1]
@@ -138,5 +154,22 @@ module Tk::BLT
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/bwidget/button.rb b/ext/tk/lib/tkextlib/bwidget/button.rb
index 4a9d4a7948..8f3087d098 100644
--- a/ext/tk/lib/tkextlib/bwidget/button.rb
+++ b/ext/tk/lib/tkextlib/bwidget/button.rb
@@ -9,7 +9,7 @@ require 'tkextlib/bwidget.rb'
module Tk
module BWidget
- class Button < TkButton
+ class Button < Tk::Button
end
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/buttonbox.rb b/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
index ef999239f9..8d6d212189 100644
--- a/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
+++ b/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
@@ -31,7 +31,7 @@ class Tk::BWidget::ButtonBox
name = tagOrId[:name]
return index(name) unless name.empty?
end
- if tagOrId.kind_of?(TkButton)
+ if tagOrId.kind_of?(Tk::Button)
return index(tagOrId[:text])
end
# index(tagOrId.to_s)
@@ -40,7 +40,13 @@ class Tk::BWidget::ButtonBox
def add(keys={}, &b)
win = window(tk_send('add', *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -54,7 +60,7 @@ class Tk::BWidget::ButtonBox
name = idx[:name]
idx = name unless name.empty?
end
- if idx.kind_of?(TkButton)
+ if idx.kind_of?(Tk::Button)
idx = idx[:text]
end
number(tk_send('index', idx.to_s))
@@ -62,7 +68,13 @@ class Tk::BWidget::ButtonBox
def insert(idx, keys={}, &b)
win = window(tk_send('insert', tagid(idx), *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/combobox.rb b/ext/tk/lib/tkextlib/bwidget/combobox.rb
index 31f71c3aaf..1c58a4ccb0 100644
--- a/ext/tk/lib/tkextlib/bwidget/combobox.rb
+++ b/ext/tk/lib/tkextlib/bwidget/combobox.rb
@@ -25,7 +25,13 @@ class Tk::BWidget::ComboBox
def get_listbox(&b)
win = window(tk_send_without_enc('getlistbox'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/dialog.rb b/ext/tk/lib/tkextlib/bwidget/dialog.rb
index 2790d88d24..291ca4a962 100644
--- a/ext/tk/lib/tkextlib/bwidget/dialog.rb
+++ b/ext/tk/lib/tkextlib/bwidget/dialog.rb
@@ -59,6 +59,13 @@ class Tk::BWidget::Dialog
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')
@@ -103,7 +110,7 @@ class Tk::BWidget::Dialog
name = tagOrId[:name]
return index(name) unless name.empty?
end
- if tagOrId.kind_of?(TkButton)
+ if tagOrId.kind_of?(Tk::Button)
return index(tagOrId[:text])
end
# index(tagOrId.to_s)
@@ -112,19 +119,37 @@ class Tk::BWidget::Dialog
def add(keys={}, &b)
win = window(tk_send('add', *hash_kv(keys)))
- win.instance_eval(&b) if b
+ 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'))
- win.instance_eval(&b) if b
+ 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')
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb b/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb
index 224304f2ab..846e58062d 100644
--- a/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb
+++ b/ext/tk/lib/tkextlib/bwidget/dynamichelp.rb
@@ -34,6 +34,13 @@ module Tk::BWidget::DynamicHelp
['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
diff --git a/ext/tk/lib/tkextlib/bwidget/entry.rb b/ext/tk/lib/tkextlib/bwidget/entry.rb
index aafb4aa7ff..a56890f4e3 100644
--- a/ext/tk/lib/tkextlib/bwidget/entry.rb
+++ b/ext/tk/lib/tkextlib/bwidget/entry.rb
@@ -9,7 +9,7 @@ require 'tkextlib/bwidget.rb'
module Tk
module BWidget
- class Entry < TkEntry
+ class Entry < Tk::Entry
end
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/label.rb b/ext/tk/lib/tkextlib/bwidget/label.rb
index ce10ecaf8b..88a504aa50 100644
--- a/ext/tk/lib/tkextlib/bwidget/label.rb
+++ b/ext/tk/lib/tkextlib/bwidget/label.rb
@@ -9,7 +9,7 @@ require 'tkextlib/bwidget.rb'
module Tk
module BWidget
- class Label < TkLabel
+ class Label < Tk::Label
end
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/labelentry.rb b/ext/tk/lib/tkextlib/bwidget/labelentry.rb
index 931feb9b48..95b40946a6 100644
--- a/ext/tk/lib/tkextlib/bwidget/labelentry.rb
+++ b/ext/tk/lib/tkextlib/bwidget/labelentry.rb
@@ -11,7 +11,7 @@ require 'tkextlib/bwidget/entry'
module Tk
module BWidget
- class LabelEntry < TkEntry
+ class LabelEntry < Tk::Entry
end
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/labelframe.rb b/ext/tk/lib/tkextlib/bwidget/labelframe.rb
index f7b267eebb..dc221806e4 100644
--- a/ext/tk/lib/tkextlib/bwidget/labelframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/labelframe.rb
@@ -40,7 +40,13 @@ class Tk::BWidget::LabelFrame
end
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ 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
index 1267500661..093fcb6fb3 100644
--- a/ext/tk/lib/tkextlib/bwidget/listbox.rb
+++ b/ext/tk/lib/tkextlib/bwidget/listbox.rb
@@ -211,14 +211,26 @@ class Tk::BWidget::ListBox::Item
include TkTreatTagFont
ListItem_TBL = TkCore::INTERP.create_table
- ListItem_ID = ['bw:item'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ ListItem_TBL.clear }
+ (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
- return id unless ListItem_TBL[lpath]
- ListItem_TBL[lpath][id]? ListItem_TBL[lpath][id]: id
+ 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)
@@ -250,13 +262,17 @@ class Tk::BWidget::ListBox::Item
if keys.key?('itemname')
@path = @id = keys.delete('itemname')
else
- @path = @id = ListItem_ID.join(TkCore::INTERP._ip_id_)
- ListItem_ID[1].succ!
+ ListItem_ID.mutex.synchronize{
+ @path = @id = ListItem_ID.join(TkCore::INTERP._ip_id_)
+ ListItem_ID[1].succ!
+ }
end
- ListItem_TBL[@id] = self
- ListItem_TBL[@lpath] = {} unless ListItem_TBL[@lpath]
- ListItem_TBL[@lpath][@id] = self
+ 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
@@ -281,6 +297,9 @@ class Tk::BWidget::ListBox::Item
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)
diff --git a/ext/tk/lib/tkextlib/bwidget/mainframe.rb b/ext/tk/lib/tkextlib/bwidget/mainframe.rb
index c54e878557..de66eaf81e 100644
--- a/ext/tk/lib/tkextlib/bwidget/mainframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/mainframe.rb
@@ -41,37 +41,73 @@ class Tk::BWidget::MainFrame
def add_indicator(keys={}, &b)
win = window(tk_send('addindicator', *hash_kv(keys)))
- win.instance_eval(&b) if b
+ 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'))
- win.instance_eval(&b) if b
+ 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'))
- win.instance_eval(&b) if b
+ 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))
- win.instance_eval(&b) if b
+ 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))
- win.instance_eval(&b) if b
+ 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))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/messagedlg.rb b/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
index 9c946d0630..b88461baf7 100644
--- a/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
+++ b/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
@@ -65,6 +65,17 @@ class Tk::BWidget::MessageDlg
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?
@@ -173,6 +184,9 @@ class Tk::BWidget::MessageDlg
end
def create
- num_or_str(tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys)))
+ # 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
index 5146d4915d..423943619c 100644
--- a/ext/tk/lib/tkextlib/bwidget/notebook.rb
+++ b/ext/tk/lib/tkextlib/bwidget/notebook.rb
@@ -89,7 +89,13 @@ class Tk::BWidget::NoteBook
def add(page, &b)
win = window(tk_send('add', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -105,7 +111,13 @@ class Tk::BWidget::NoteBook
def get_frame(page, &b)
win = window(tk_send('getframe', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -115,7 +127,13 @@ class Tk::BWidget::NoteBook
def insert(index, page, keys={}, &b)
win = window(tk_send('insert', index, tagid(page), *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb b/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
index fc01284be6..fbc2c11255 100644
--- a/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
+++ b/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
@@ -26,7 +26,13 @@ class Tk::BWidget::PagesManager
def add(page, &b)
win = window(tk_send('add', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -42,7 +48,13 @@ class Tk::BWidget::PagesManager
def get_frame(page, &b)
win = window(tk_send('getframe', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/panedwindow.rb b/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
index 19982c6095..4d979fd523 100644
--- a/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
+++ b/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
@@ -25,7 +25,13 @@ class Tk::BWidget::PanedWindow
def get_frame(idx, &b)
win = window(tk_send_without_enc('getframe', idx))
- win.instance_eval(&b) if b
+ 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
index 13f8817d74..84bae0768b 100644
--- a/ext/tk/lib/tkextlib/bwidget/panelframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/panelframe.rb
@@ -36,7 +36,13 @@ class Tk::BWidget::PanelFrame
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/progressdlg.rb b/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
index fbf00f3b00..32600255d5 100644
--- a/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
+++ b/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
@@ -51,4 +51,8 @@ class Tk::BWidget::ProgressDlg
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
index a3986681a5..010c960ec5 100644
--- a/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
@@ -23,7 +23,13 @@ class Tk::BWidget::ScrollableFrame
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb b/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
index e9e53235b7..3599fd8459 100644
--- a/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
+++ b/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
@@ -21,7 +21,13 @@ class Tk::BWidget::ScrolledWindow
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/selectcolor.rb b/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
index 742a84cd84..0f9014f8de 100644
--- a/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
+++ b/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
@@ -10,6 +10,11 @@ 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
@@ -43,3 +48,26 @@ class Tk::BWidget::SelectColor
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
index 478787602a..e53eb3b5bc 100644
--- a/ext/tk/lib/tkextlib/bwidget/selectfont.rb
+++ b/ext/tk/lib/tkextlib/bwidget/selectfont.rb
@@ -66,7 +66,7 @@ class Tk::BWidget::SelectFont::Dialog
end
def create
- @keys['type'] = 'dialog'
+ @keys['type'] = 'dialog' # 'dialog' type returns font name
tk_call(Tk::BWidget::SelectFont::TkCommandNames[0], @path, *hash_kv(@keys))
end
end
@@ -79,7 +79,8 @@ class Tk::BWidget::SelectFont::Toolbar
def create_self(keys)
keys = {} unless keys
keys = _symbolkey2str(keys)
- keys['type'] = 'toolbar'
- tk_call(Tk::BWidget::SelectFont::TkCommandNames[0], @path, *hash_kv(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/spinbox.rb b/ext/tk/lib/tkextlib/bwidget/spinbox.rb
index ca4c046e5c..48358baa5c 100644
--- a/ext/tk/lib/tkextlib/bwidget/spinbox.rb
+++ b/ext/tk/lib/tkextlib/bwidget/spinbox.rb
@@ -10,7 +10,7 @@ require 'tkextlib/bwidget/entry'
module Tk
module BWidget
- class SpinBox < TkEntry
+ class SpinBox < Tk::Entry
end
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/statusbar.rb b/ext/tk/lib/tkextlib/bwidget/statusbar.rb
index df16e4c0b7..39c678d37e 100644
--- a/ext/tk/lib/tkextlib/bwidget/statusbar.rb
+++ b/ext/tk/lib/tkextlib/bwidget/statusbar.rb
@@ -36,7 +36,13 @@ class Tk::BWidget::StatusBar
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/titleframe.rb b/ext/tk/lib/tkextlib/bwidget/titleframe.rb
index f519490430..68534e66e9 100644
--- a/ext/tk/lib/tkextlib/bwidget/titleframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/titleframe.rb
@@ -21,7 +21,13 @@ class Tk::BWidget::TitleFrame
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ 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
index e7178debe2..aed4512a73 100644
--- a/ext/tk/lib/tkextlib/bwidget/tree.rb
+++ b/ext/tk/lib/tkextlib/bwidget/tree.rb
@@ -263,14 +263,26 @@ class Tk::BWidget::Tree::Node
include TkTreatTagFont
TreeNode_TBL = TkCore::INTERP.create_table
- TreeNode_ID = ['bw:node'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TreeNode_TBL.clear }
+ (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
- return id unless TreeNode_TBL[tpath]
- TreeNode_TBL[tpath][id]? TreeNode_TBL[tpath][id]: id
+ 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)
@@ -311,13 +323,17 @@ class Tk::BWidget::Tree::Node
if keys.key?('nodename')
@path = @id = keys.delete('nodename')
else
- @path = @id = TreeNode_ID.join(TkCore::INTERP._ip_id_)
- TreeNode_ID[1].succ!
+ TreeNode_ID.mutex.synchronize{
+ @path = @id = TreeNode_ID.join(TkCore::INTERP._ip_id_)
+ TreeNode_ID[1].succ!
+ }
end
- TreeNode_TBL[@id] = self
- TreeNode_TBL[@tpath] = {} unless TreeNode_TBL[@tpath]
- TreeNode_TBL[@tpath][@id] = self
+ 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
@@ -342,6 +358,9 @@ class Tk::BWidget::Tree::Node
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)
diff --git a/ext/tk/lib/tkextlib/bwidget/widget.rb b/ext/tk/lib/tkextlib/bwidget/widget.rb
index 568e503a8b..a93364b567 100644
--- a/ext/tk/lib/tkextlib/bwidget/widget.rb
+++ b/ext/tk/lib/tkextlib/bwidget/widget.rb
@@ -29,6 +29,13 @@ module Tk::BWidget::Widget
['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
@@ -43,7 +50,13 @@ module Tk::BWidget::Widget
def self.create(klass, path, rename=None, &b)
win = window(tk_call('Widget::create', klass, path, rename))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -99,9 +112,12 @@ module Tk::BWidget::Widget
tk_call('Widget::setoption', win, option, value)
end
- def self.sub_cget(win, subwidget)
+ 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)
diff --git a/ext/tk/lib/tkextlib/itcl/incr_tcl.rb b/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
index 07abf3a7bf..2b75d62eb9 100644
--- a/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
+++ b/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
@@ -40,16 +40,22 @@ module Tk
class ItclObject < TkObject
ITCL_CLASSNAME = ''.freeze
- ITCL_OBJ_ID = ['itclobj'.freeze, '00000'.taint].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
- @id = Tk::Itcl::ItclObject::TCL_OBJ_ID.join(TkCore::INTERP._ip_id_)
+ 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
- Tk::Itcl::ItclObject::ITCL_OBJ_ID[1].succ!
end
def self.call_proc(name, *args)
diff --git a/ext/tk/lib/tkextlib/itk/incr_tk.rb b/ext/tk/lib/tkextlib/itk/incr_tk.rb
index 0626536e36..e06deb552c 100644
--- a/ext/tk/lib/tkextlib/itk/incr_tk.rb
+++ b/ext/tk/lib/tkextlib/itk/incr_tk.rb
@@ -145,9 +145,16 @@ module Tk
private :__config_cmd
ComponentID_TBL = TkCore::INTERP.create_table
- Itk_Component_ID = ['itk:component'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ ComponentID_TBL.clear }
+ (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)
@@ -155,8 +162,13 @@ module Tk
else
master = master.to_s
end
- return id unless ComponentID_TBL.key?(master)
- (ComponentID_TBL.key?(id))? ComponentID_TBL[master][id]: id
+ 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)
@@ -171,17 +183,21 @@ module Tk
elsif component
component = component.to_s
else
- component = Itk_Component_ID.join(TkCore::INTERP._ip_id_)
- Itk_Component_ID[1].succ!
+ Itk_Component_ID.mutex.synchronize{
+ component = Itk_Component_ID.join(TkCore::INTERP._ip_id_)
+ Itk_Component_ID[1].succ!
+ }
end
- if ComponentID_TBL.key?(master)
- if ComponentID_TBL[master].key?(component)
- return ComponentID_TBL[master][component]
+ 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
- else
- ComponentID_TBL[master] = {}
- end
+ }
super(master, component)
end
@@ -190,7 +206,9 @@ module Tk
@master = master
@component = component
- ComponentID_TBL[@master][@component] = self
+ ComponentID_TBL.mutex.synchronize{
+ ComponentID_TBL[@master][@component] = self
+ }
begin
@widget = window(tk_call(@master, 'component', @component))
diff --git a/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb b/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb
index a055e07ac9..05d58c386f 100644
--- a/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/buttonbox.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Buttonbox
end
alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
alias buttonconfigure itemconfigure
alias buttonconfiginfo itemconfiginfo
alias current_buttonconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
diff --git a/ext/tk/lib/tkextlib/iwidgets/calendar.rb b/ext/tk/lib/tkextlib/iwidgets/calendar.rb
index 0152f8593a..8495f0e29b 100644
--- a/ext/tk/lib/tkextlib/iwidgets/calendar.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/calendar.rb
@@ -45,6 +45,25 @@ class Tk::Iwidgets::Calendar
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)
diff --git a/ext/tk/lib/tkextlib/iwidgets/checkbox.rb b/ext/tk/lib/tkextlib/iwidgets/checkbox.rb
index 46ca389db2..c85d356c55 100644
--- a/ext/tk/lib/tkextlib/iwidgets/checkbox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/checkbox.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Checkbox
end
alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
alias buttonconfigure itemconfigure
alias buttonconfiginfo itemconfiginfo
alias current_buttonconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
@@ -85,12 +86,24 @@ class Tk::Iwidgets::Checkbox
self
end
- def get(idx)
- simplelist(tk_call(@path, 'get', index(idx))).collect{|id|
+ 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
diff --git a/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb b/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb
index d6c668621d..8d43cc07ab 100644
--- a/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/dialogshell.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Dialogshell
end
alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
alias buttonconfigure itemconfigure
alias buttonconfiginfo itemconfiginfo
alias current_buttonconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
diff --git a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
index 6aa933ce06..d53df216bf 100644
--- a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
@@ -42,6 +42,25 @@ class Tk::Iwidgets::Entryfield
[ ?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
diff --git a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
index 4cc6aeecbd..d9220fecbf 100644
--- a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
@@ -30,6 +30,25 @@ class Tk::Iwidgets::Hierarchy
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)
@@ -57,6 +76,24 @@ class Tk::Iwidgets::Hierarchy
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)
@@ -78,6 +115,25 @@ class Tk::Iwidgets::Hierarchy
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)
@@ -207,7 +263,7 @@ class Tk::Iwidgets::Hierarchy
self
end
- # based on TkText widget
+ # based on Tk::Text widget
def bbox(index)
list(tk_send_without_enc('bbox', _get_eval_enc_str(index)))
diff --git a/ext/tk/lib/tkextlib/iwidgets/menubar.rb b/ext/tk/lib/tkextlib/iwidgets/menubar.rb
index dea3d34c2a..5aaefbe50d 100644
--- a/ext/tk/lib/tkextlib/iwidgets/menubar.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/menubar.rb
@@ -62,12 +62,13 @@ class Tk::Iwidgets::Menubar
end
alias menucget itemcget
+ alias menucget_strict itemcget_strict
alias menuconfigure itemconfigure
alias menuconfiginfo itemconfiginfo
alias current_menuconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
diff --git a/ext/tk/lib/tkextlib/iwidgets/messagebox.rb b/ext/tk/lib/tkextlib/iwidgets/messagebox.rb
index 2bbbec7666..98ac32900c 100644
--- a/ext/tk/lib/tkextlib/iwidgets/messagebox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/messagebox.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Messagebox
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, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
diff --git a/ext/tk/lib/tkextlib/iwidgets/notebook.rb b/ext/tk/lib/tkextlib/iwidgets/notebook.rb
index 0f9d713ea1..03b50633df 100644
--- a/ext/tk/lib/tkextlib/iwidgets/notebook.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/notebook.rb
@@ -42,12 +42,13 @@ class Tk::Iwidgets::Notebook
end
alias pagecget itemcget
+ alias pagecget_strict itemcget_strict
alias pageconfigure itemconfigure
alias pageconfiginfo itemconfiginfo
alias current_pageconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
@@ -146,7 +147,12 @@ class Tk::Iwidgets::Notebook
def view(*idxs)
if idxs.size == 0
- window(tk_send_without_enc('view'))
+ 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
@@ -160,8 +166,8 @@ class Tk::Iwidgets::Notebook
end
alias xview_moveto view_moveto
alias yview_moveto view_moveto
- def view_scroll(*idxs)
- view('scroll', *idxs)
+ def view_scroll(index, what='pages')
+ view('scroll', index, what)
end
alias xview_scroll view_scroll
alias yview_scroll view_scroll
diff --git a/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb b/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb
index 035df0a5b8..3bf73d69fe 100644
--- a/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/panedwindow.rb
@@ -42,12 +42,13 @@ class Tk::Iwidgets::Panedwindow
end
alias panecget itemcget
+ alias panecget_strict itemcget_strict
alias paneconfigure itemconfigure
alias paneconfiginfo itemconfiginfo
alias current_paneconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
diff --git a/ext/tk/lib/tkextlib/iwidgets/radiobox.rb b/ext/tk/lib/tkextlib/iwidgets/radiobox.rb
index 1a2821bd6a..e9d9521252 100644
--- a/ext/tk/lib/tkextlib/iwidgets/radiobox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/radiobox.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Radiobox
end
alias buttoncget itemcget
+ alias buttoncget_strict itemcget_strict
alias buttonconfigure itemconfigure
alias buttonconfiginfo itemconfiginfo
alias current_buttonconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
@@ -85,10 +86,13 @@ class Tk::Iwidgets::Radiobox
self
end
- def get(idx)
- simplelist(tk_call(@path, 'get', index(idx))).collect{|id|
- Tk::Itk::Component.id2obj(self, id)
- }
+ 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)
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
index 407c8f2aad..67ad67d07e 100644
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
@@ -37,7 +37,7 @@ class Tk::Iwidgets::Scrolledcanvas
end
def method_missing(id, *args)
- if @canvas.methods.include?(id.id2name)
+ if @canvas.respond_to?(id)
@canvas.__send__(id, *args)
else
super(id, *args)
@@ -171,10 +171,16 @@ class Tk::Iwidgets::Scrolledcanvas
end
def delete(*args)
- if TkcItem::CItemID_TBL[self.path]
+ 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[self.path].delete(item.id)
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl.delete(item.id)
+ }
end
}
end
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb
index cd1f6f0f79..7543d557e3 100644
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledlistbox.rb
@@ -42,7 +42,7 @@ class Tk::Iwidgets::Scrolledlistbox
end
def method_missing(id, *args)
- if @listbox.methods.include?(id.id2name)
+ if @listbox.respond_to?(id)
@listbox.__send__(id, *args)
else
super(id, *args)
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb
index fdafc8dc7f..d6436d202a 100644
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledtext.rb
@@ -37,7 +37,7 @@ class Tk::Iwidgets::Scrolledtext
end
def method_missing(id, *args)
- if @text.methods.include?(id.id2name)
+ if @text.respond_to?(id)
@text.__send__(id, *args)
else
super(id, *args)
@@ -116,7 +116,7 @@ class Tk::Iwidgets::Scrolledtext
get('-displaychars', *index)
end
- def image_cget(index, slot)
+ def image_cget_strict(index, slot)
case slot.to_s
when 'text', 'label', 'show', 'data', 'file'
_fromUTF8(tk_send_without_enc('image', 'cget',
@@ -127,6 +127,27 @@ class Tk::Iwidgets::Scrolledtext
"-#{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
@@ -322,6 +343,11 @@ class Tk::Iwidgets::Scrolledtext
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
diff --git a/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb b/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb
index bb81fcca5e..bf9b5ec30a 100644
--- a/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/selectionbox.rb
@@ -59,7 +59,7 @@ class Tk::Iwidgets::Selectionbox
self
end
- # based on TkListbox ( and TkTextWin )
+ # based on Tk::Listbox ( and TkTextWin )
def curselection
list(tk_send_without_enc('curselection'))
end
diff --git a/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb b/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb
index ab790e97a6..f772ecf8c2 100644
--- a/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/selectiondialog.rb
@@ -49,7 +49,7 @@ class Tk::Iwidgets::Selectiondialog
self
end
- # based on TkListbox ( and TkTextWin )
+ # based on Tk::Listbox ( and TkTextWin )
def curselection
list(tk_send_without_enc('curselection'))
end
diff --git a/ext/tk/lib/tkextlib/iwidgets/spinner.rb b/ext/tk/lib/tkextlib/iwidgets/spinner.rb
index 174b9bd506..aeee5c9038 100644
--- a/ext/tk/lib/tkextlib/iwidgets/spinner.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/spinner.rb
@@ -37,6 +37,25 @@ class Tk::Iwidgets::Spinner
[ ?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
diff --git a/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb b/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb
index 0d9715f87b..dbb90e5102 100644
--- a/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/tabnotebook.rb
@@ -47,12 +47,13 @@ class Tk::Iwidgets::Tabnotebook
end
alias pagecget itemcget
+ alias pagecget_strict itemcget_strict
alias pageconfigure itemconfigure
alias pageconfiginfo itemconfiginfo
alias current_pageconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
@@ -116,6 +117,11 @@ class Tk::Iwidgets::Tabnotebook
self
end
+ def show_tab(idx)
+ @tabset.show_tab(idx)
+ self
+ end
+
def scrollcommand(cmd=Proc.new)
configure_cmd 'scrollcommand', cmd
self
@@ -147,7 +153,12 @@ class Tk::Iwidgets::Tabnotebook
def view(*index)
if index.size == 0
- window(tk_send_without_enc('view'))
+ 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
@@ -161,8 +172,8 @@ class Tk::Iwidgets::Tabnotebook
end
alias xview_moveto view_moveto
alias yview_moveto view_moveto
- def view_scroll(*index)
- view('scroll', *index)
+ def view_scroll(index, what='pages')
+ view('scroll', index, what)
end
alias xview_scroll view_scroll
alias yview_scroll view_scroll
diff --git a/ext/tk/lib/tkextlib/iwidgets/tabset.rb b/ext/tk/lib/tkextlib/iwidgets/tabset.rb
index 54e56d0514..300ba9dee0 100644
--- a/ext/tk/lib/tkextlib/iwidgets/tabset.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/tabset.rb
@@ -42,12 +42,13 @@ class Tk::Iwidgets::Tabset
end
alias tabcget itemcget
+ alias tabcget_strict itemcget_strict
alias tabconfigure itemconfigure
alias tabconfiginfo itemconfiginfo
alias current_tabconfiginfo current_itemconfiginfo
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
####################################
@@ -96,4 +97,48 @@ class Tk::Iwidgets::Tabset
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/tcllib/autoscroll.rb b/ext/tk/lib/tkextlib/tcllib/autoscroll.rb
index 6940a9174c..7db3c2e2b7 100644
--- a/ext/tk/lib/tkextlib/tcllib/autoscroll.rb
+++ b/ext/tk/lib/tkextlib/tcllib/autoscroll.rb
@@ -108,7 +108,7 @@ module Tk
end
end
-class TkScrollbar
+class Tk::Scrollbar
def autoscroll
# Arranges for the already existing scrollbar to be mapped
# and unmapped as needed.
diff --git a/ext/tk/lib/tkextlib/tcllib/ctext.rb b/ext/tk/lib/tkextlib/tcllib/ctext.rb
index 70a45dd8e7..9014037f3d 100644
--- a/ext/tk/lib/tkextlib/tcllib/ctext.rb
+++ b/ext/tk/lib/tkextlib/tcllib/ctext.rb
@@ -15,7 +15,7 @@ TkPackage.require('ctext')
module Tk
module Tcllib
- class CText < TkText
+ class CText < Tk::Text
PACKAGE_NAME = 'ctext'.freeze
def self.package_name
PACKAGE_NAME
diff --git a/ext/tk/lib/tkextlib/tcllib/datefield.rb b/ext/tk/lib/tkextlib/tcllib/datefield.rb
index bd84488101..2244dd7a9a 100644
--- a/ext/tk/lib/tkextlib/tcllib/datefield.rb
+++ b/ext/tk/lib/tkextlib/tcllib/datefield.rb
@@ -24,7 +24,7 @@ TkPackage.require('datefield')
module Tk
module Tcllib
- class Datefield < TkEntry
+ class Datefield < Tk::Entry
PACKAGE_NAME = 'datefield'.freeze
def self.package_name
PACKAGE_NAME
diff --git a/ext/tk/lib/tkextlib/tcllib/getstring.rb b/ext/tk/lib/tkextlib/tcllib/getstring.rb
index bf5e54e8cf..fc5d8b26d9 100644
--- a/ext/tk/lib/tkextlib/tcllib/getstring.rb
+++ b/ext/tk/lib/tkextlib/tcllib/getstring.rb
@@ -87,7 +87,7 @@ class Tk::Tcllib::GetString_Dialog
@variable.value
end
- def cget(slot)
+ def cget_strict(slot)
slot = slot.to_s
if slot == 'text'
@text
@@ -95,6 +95,9 @@ class Tk::Tcllib::GetString_Dialog
@keys[slot]
end
end
+ def cget(slot)
+ cget_strict(slot)
+ end
def configure(slot, value=None)
if slot.kind_of?(Hash)
diff --git a/ext/tk/lib/tkextlib/tcllib/ico.rb b/ext/tk/lib/tkextlib/tcllib/ico.rb
index 3beeb11a4d..8c92926a4c 100644
--- a/ext/tk/lib/tkextlib/tcllib/ico.rb
+++ b/ext/tk/lib/tkextlib/tcllib/ico.rb
@@ -94,8 +94,10 @@ class Tk::Tcllib::ICO
if keys.key?('name')
@path = keys['name'].to_s
else
- @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
- Tk_Image_ID[1].succ!
+ 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))
diff --git a/ext/tk/lib/tkextlib/tcllib/ip_entry.rb b/ext/tk/lib/tkextlib/tcllib/ip_entry.rb
index 8c9e0bd683..c4b8240c04 100644
--- a/ext/tk/lib/tkextlib/tcllib/ip_entry.rb
+++ b/ext/tk/lib/tkextlib/tcllib/ip_entry.rb
@@ -18,7 +18,7 @@ TkPackage.require('ipentry')
module Tk
module Tcllib
- class IP_Entry < TkEntry
+ class IP_Entry < Tk::Entry
PACKAGE_NAME = 'ipentry'.freeze
def self.package_name
PACKAGE_NAME
diff --git a/ext/tk/lib/tkextlib/tcllib/plotchart.rb b/ext/tk/lib/tkextlib/tcllib/plotchart.rb
index f5f344ceb3..06ab20f3e6 100644
--- a/ext/tk/lib/tkextlib/tcllib/plotchart.rb
+++ b/ext/tk/lib/tkextlib/tcllib/plotchart.rb
@@ -225,7 +225,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class XYPlot < TkCanvas
+ class XYPlot < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -247,7 +247,7 @@ module Tk::Tcllib::Plotchart
@xaxis = args.shift
@yaxis = args.shift
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -265,7 +265,9 @@ module Tk::Tcllib::Plotchart
private :_create_chart
def __destroy_hook__
- Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
end
def plot(series, x, y)
@@ -337,7 +339,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class PolarPlot < TkCanvas
+ class PolarPlot < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -356,7 +358,7 @@ module Tk::Tcllib::Plotchart
@radius_data = args.shift
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -374,7 +376,9 @@ module Tk::Tcllib::Plotchart
private :_create_chart
def __destroy_hook__
- Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
end
def plot(series, radius, angle)
@@ -395,7 +399,7 @@ module Tk::Tcllib::Plotchart
Polarplot = PolarPlot
############################
- class IsometricPlot < TkCanvas
+ class IsometricPlot < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -430,7 +434,7 @@ module Tk::Tcllib::Plotchart
@stepsize = args.shift
end
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -475,7 +479,7 @@ module Tk::Tcllib::Plotchart
Isometricplot = IsometricPlot
############################
- class Plot3D < TkCanvas
+ class Plot3D < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -500,7 +504,7 @@ module Tk::Tcllib::Plotchart
@yaxis = args.shift
@zaxis = args.shift
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -557,7 +561,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class Piechart < TkCanvas
+ class Piechart < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -566,7 +570,7 @@ module Tk::Tcllib::Plotchart
].freeze
def initialize(*args) # args := ([parent] [, keys])
- if args[0].kind_of?(TkCanvas)
+ if args[0].kind_of?(Tk::Canvas)
parent = args.shift
@path = parent.path
else
@@ -588,7 +592,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class Barchart < TkCanvas
+ class Barchart < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -626,7 +630,7 @@ module Tk::Tcllib::Plotchart
@series_size = args.shift
end
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -645,7 +649,9 @@ module Tk::Tcllib::Plotchart
private :_create_chart
def __destroy_hook__
- Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
end
def plot(series, dat, col=None)
@@ -672,7 +678,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class Timechart < TkCanvas
+ class Timechart < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -699,7 +705,7 @@ module Tk::Tcllib::Plotchart
@time_end = args.shift
@items = args.shift
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -733,7 +739,7 @@ module Tk::Tcllib::Plotchart
end
############################
- class Gnattchart < TkCanvas
+ class Gnattchart < Tk::Canvas
include ChartMethod
TkCommandNames = [
@@ -772,7 +778,7 @@ module Tk::Tcllib::Plotchart
@text_width = None
end
- if parent.kind_of?(TkCanvas)
+ if parent.kind_of?(Tk::Canvas)
@path = parent.path
else
super(parent, *args) # create canvas widget
@@ -834,23 +840,38 @@ module Tk::Tcllib::Plotchart
############################
class PlotSeries < TkObject
SeriesID_TBL = TkCore::INTERP.create_table
- Series_ID = ['series'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ SeriesID_TBL.clear }
+
+ (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
- return id unless SeriesID_TBL[path]
- SeriesID_TBL[path][id]? SeriesID_TBL[path][id]: id
+ 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
- @path = @series = @id = Series_ID.join(TkCore::INTERP._ip_id_)
- # SeriesID_TBL[@id] = self
- SeriesID_TBL[@ppath] = {} unless SeriesID_TBL[@ppath]
- SeriesID_TBL[@ppath][@id] = self
- Series_ID[1].succ!
+ 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
diff --git a/ext/tk/lib/tkextlib/tcllib/swaplist.rb b/ext/tk/lib/tkextlib/tcllib/swaplist.rb
index 97de0a27c1..1c813e36da 100644
--- a/ext/tk/lib/tkextlib/tcllib/swaplist.rb
+++ b/ext/tk/lib/tkextlib/tcllib/swaplist.rb
@@ -90,7 +90,7 @@ class Tk::Tcllib::Swaplist_Dialog
end
alias selected value
- def cget(slot)
+ def cget_strict(slot)
slot = slot.to_s
if slot == 'complete_list'
@complete_list
@@ -100,6 +100,9 @@ class Tk::Tcllib::Swaplist_Dialog
@keys[slot]
end
end
+ def cget(slot)
+ cget_strict(slot)
+ end
def configure(slot, value=None)
if slot.kind_of?(Hash)
diff --git a/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb b/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb
index a939a58331..d7a6c97210 100644
--- a/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb
+++ b/ext/tk/lib/tkextlib/tcllib/tablelist_core.rb
@@ -70,6 +70,9 @@ module Tk::Tcllib::TablelistItemConfig
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
@@ -80,6 +83,7 @@ module Tk::Tcllib::TablelistItemConfig
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
@@ -87,6 +91,9 @@ module Tk::Tcllib::TablelistItemConfig
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
@@ -97,6 +104,7 @@ module Tk::Tcllib::TablelistItemConfig
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
@@ -104,6 +112,9 @@ module Tk::Tcllib::TablelistItemConfig
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
@@ -114,12 +125,13 @@ module Tk::Tcllib::TablelistItemConfig
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, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
end
class Tk::Tcllib::Tablelist
diff --git a/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb b/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb
index 92dde65ce7..b366e0198b 100644
--- a/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb
+++ b/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb
@@ -125,7 +125,9 @@ module Tk::Tcllib::Tkpiechart
def delete
tk_call_without_enc('::stooop::delete', @tag_key)
- CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ }
self
end
@@ -184,8 +186,10 @@ module Tk::Tcllib::Tkpiechart
@id = "slices(#{@tag_key})"
@tag = TkcNamedTag.new(@pie.canvas, @id)
- CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
- CItemID_TBL[@path][@id] = self
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
+ CItemID_TBL[@path][@id] = self
+ }
end
def tag_key
@@ -200,7 +204,9 @@ module Tk::Tcllib::Tkpiechart
def delete
tk_call_without_enc('pie::deleteSlice', @pie.tag_key, @tag_key)
- CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ }
@pie._delete_slice(self)
self
end
diff --git a/ext/tk/lib/tkextlib/tile.rb b/ext/tk/lib/tkextlib/tile.rb
index acc7bebe4e..60ea012cc0 100644
--- a/ext/tk/lib/tkextlib/tile.rb
+++ b/ext/tk/lib/tkextlib/tile.rb
@@ -4,6 +4,7 @@
#
require 'tk'
+require 'tk/ttk_selector'
# call setup script for general 'tkextlib' libraries
require 'tkextlib/setup.rb'
@@ -15,33 +16,66 @@ require 'tkextlib/tile/setup.rb'
# TkPackage.require('tile', '0.4')
# TkPackage.require('tile', '0.6')
# TkPackage.require('tile', '0.7')
-verstr = TkPackage.require('tile')
+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 && 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
+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
- end
-elsif ver[0].to_i == 0 && 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
+ 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
- # version 0.7 or later
+ # 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 = 7
+ TILE_SPEC_VERSION_ID = 8
+
+ PACKAGE_NAME = 'Ttk'.freeze
end
end
end
@@ -51,30 +85,114 @@ module Tk
module Tile
TkComm::TkExtlibAutoloadModule.unshift(self)
- PACKAGE_NAME = 'tile'.freeze
def self.package_name
PACKAGE_NAME
end
def self.package_version
begin
- TkPackage.require('tile')
+ 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.load_images(imgdir, pat=TkComm::None)
- images = Hash[*TkComm.simplelist(Tk.tk_call('::tile::LoadImages',
- imgdir, pat))]
- images.keys.each{|k|
- images[k] = TkPhotoImage.new(:imagename=>images[k],
- :without_creating=>true)
+ 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
@@ -83,12 +201,53 @@ module Tk
args.map!{|arg| TkComm._get_eval_string(arg)}.join('.')
end
- module KeyNav
- def self.enableMnemonics(w)
- Tk.tk_call('::keynav::enableMnemonics', w)
+ 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
- def self.defaultButton(w)
- Tk.tk_call('::keynav::defaultButton', w)
+
+ 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
@@ -103,6 +262,12 @@ module Tk
Menu = 'TkMenuFont'
SmallCaption = 'TkSmallCaptionFont'
Icon = 'TkIconFont'
+
+ TkFont::SYSTEM_FONT_NAMES.add [
+ 'TkDefaultFont', 'TkTextFont', 'TkHeadingFont',
+ 'TkCaptionFont', 'TkTooltipFont', 'TkFixedFont',
+ 'TkMenuFont', 'TkSmallCaptionFont', 'TkIconFont'
+ ]
end
module ParseStyleLayout
@@ -141,7 +306,7 @@ module Tk
end
private :__val2ruby_optkeys
- def instate(state, script=nil, &b)
+ def ttk_instate(state, script=nil, &b)
if script
tk_send('instate', state, script)
elsif b
@@ -150,19 +315,30 @@ module Tk
bool(tk_send('instate', state))
end
end
+ alias tile_instate ttk_instate
- def state(state=nil)
+ def ttk_state(state=nil)
if state
tk_send('state', state)
else
list(tk_send('state'))
end
end
+ alias tile_state ttk_state
- def identify(x, y)
+ 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
######################################
@@ -188,18 +364,24 @@ module Tk
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'
@@ -216,6 +398,8 @@ module Tk
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'
@@ -223,8 +407,13 @@ module Tk
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
index b10378d7de..ef2d1fe577 100644
--- a/ext/tk/lib/tkextlib/tile/dialog.rb
+++ b/ext/tk/lib/tkextlib/tile/dialog.rb
@@ -54,9 +54,21 @@ class Tk::Tile::Dialog
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)
- @keys[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)
diff --git a/ext/tk/lib/tkextlib/tile/sizegrip.rb b/ext/tk/lib/tkextlib/tile/sizegrip.rb
index ea796583b0..c5068919a4 100644
--- a/ext/tk/lib/tkextlib/tile/sizegrip.rb
+++ b/ext/tk/lib/tkextlib/tile/sizegrip.rb
@@ -9,9 +9,13 @@ 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
diff --git a/ext/tk/lib/tkextlib/tile/style.rb b/ext/tk/lib/tkextlib/tile/style.rb
index 59bc4b0d78..ca7ee99c32 100644
--- a/ext/tk/lib/tkextlib/tile/style.rb
+++ b/ext/tk/lib/tkextlib/tile/style.rb
@@ -17,6 +17,145 @@ module Tk::Tile::Style
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
@@ -31,9 +170,9 @@ class << Tk::Tile::Style
end
if keys && keys != None
- tk_call('style', sub_cmd, style, *hash_kv(keys))
+ tk_call(TkCommandNames[0], sub_cmd, style, *hash_kv(keys))
else
- tk_call('style', sub_cmd, style)
+ tk_call(TkCommandNames[0], sub_cmd, style)
end
end
alias default configure
@@ -46,14 +185,33 @@ class << Tk::Tile::Style
style = '.' unless style
if keys && keys != None
- tk_call('style', 'map', style, *hash_kv(keys))
+ 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
- tk_call('style', 'map', style)
+ 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('style', 'lookup', style, '-' << opt.to_s, state, fallback_value)
+ tk_call(TkCommandNames[0], 'lookup', style,
+ '-' << opt.to_s, state, fallback_value)
end
include Tk::Tile::ParseStyleLayout
@@ -66,42 +224,93 @@ class << Tk::Tile::Style
style = '.' unless style
if spec
- tk_call('style', 'layout', style, spec)
+ tk_call(TkCommandNames[0], 'layout', style, spec)
else
- _style_layout(list(tk_call('style', 'layout', style)))
+ _style_layout(list(tk_call(TkCommandNames[0], 'layout', style)))
end
end
def element_create(name, type, *args)
- tk_call('style', '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('style', 'element', 'names'))
+ list(tk_call(TkCommandNames[0], 'element', 'names'))
end
def element_options(elem)
- simplelist(tk_call('style', '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('style', 'theme', 'create', name, *hash_kv(keys))
+ tk_call(TkCommandNames[0], 'theme', 'create', name, *hash_kv(keys))
else
- tk_call('style', 'theme', 'create', name)
+ 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('style', 'theme', 'settings', name, cmd)
+ tk_call(TkCommandNames[0], 'theme', 'settings', name, cmd)
+ name
end
def theme_names()
- list(tk_call('style', 'theme', 'names'))
+ list(tk_call(TkCommandNames[0], 'theme', 'names'))
end
def theme_use(name)
- tk_call('style', '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
index 1142a27100..5d7db10fe9 100644
--- a/ext/tk/lib/tkextlib/tile/tbutton.rb
+++ b/ext/tk/lib/tkextlib/tile/tbutton.rb
@@ -7,13 +7,16 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TButton < TkButton
+ class TButton < Tk::Button
end
Button = TButton
end
end
-class Tk::Tile::TButton < TkButton
+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
diff --git a/ext/tk/lib/tkextlib/tile/tcheckbutton.rb b/ext/tk/lib/tkextlib/tile/tcheckbutton.rb
index fce799683d..172225fcec 100644
--- a/ext/tk/lib/tkextlib/tile/tcheckbutton.rb
+++ b/ext/tk/lib/tkextlib/tile/tcheckbutton.rb
@@ -7,7 +7,7 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TCheckButton < TkCheckButton
+ class TCheckButton < Tk::CheckButton
end
TCheckbutton = TCheckButton
CheckButton = TCheckButton
@@ -15,7 +15,11 @@ module Tk
end
end
-class Tk::Tile::TCheckButton < TkCheckButton
+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
diff --git a/ext/tk/lib/tkextlib/tile/tcombobox.rb b/ext/tk/lib/tkextlib/tile/tcombobox.rb
index e8e042fbd9..b64372f1c9 100644
--- a/ext/tk/lib/tkextlib/tile/tcombobox.rb
+++ b/ext/tk/lib/tkextlib/tile/tcombobox.rb
@@ -13,6 +13,9 @@ module Tk
end
end
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Combobox, :TkCombobox)
+
+
class Tk::Tile::TCombobox < Tk::Tile::TEntry
include Tk::Tile::TileWidget
diff --git a/ext/tk/lib/tkextlib/tile/tentry.rb b/ext/tk/lib/tkextlib/tile/tentry.rb
index 4d57ce7756..0bea98dcd9 100644
--- a/ext/tk/lib/tkextlib/tile/tentry.rb
+++ b/ext/tk/lib/tkextlib/tile/tentry.rb
@@ -7,13 +7,16 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TEntry < TkEntry
+ class TEntry < Tk::Entry
end
Entry = TEntry
end
end
-class Tk::Tile::TEntry < TkEntry
+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
@@ -24,6 +27,11 @@ class Tk::Tile::TEntry < TkEntry
WidgetClassName = 'TEntry'.freeze
WidgetClassNames[WidgetClassName] = self
+ def __optkey_aliases
+ {:vcmd=>:validatecommand, :invcmd=>:invalidcommand}
+ end
+ private :__optkey_aliases
+
def __boolval_optkeys
super() << 'exportselection'
end
diff --git a/ext/tk/lib/tkextlib/tile/tframe.rb b/ext/tk/lib/tkextlib/tile/tframe.rb
index 691c9c42af..3b5f98bb6e 100644
--- a/ext/tk/lib/tkextlib/tile/tframe.rb
+++ b/ext/tk/lib/tkextlib/tile/tframe.rb
@@ -7,13 +7,16 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TFrame < TkFrame
+ class TFrame < Tk::Frame
end
Frame = TFrame
end
end
-class Tk::Tile::TFrame < TkFrame
+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
diff --git a/ext/tk/lib/tkextlib/tile/tlabel.rb b/ext/tk/lib/tkextlib/tile/tlabel.rb
index 4111d1906a..7d074d3842 100644
--- a/ext/tk/lib/tkextlib/tile/tlabel.rb
+++ b/ext/tk/lib/tkextlib/tile/tlabel.rb
@@ -7,13 +7,16 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TLabel < TkLabel
+ class TLabel < Tk::Label
end
Label = TLabel
end
end
-class Tk::Tile::TLabel < TkLabel
+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
diff --git a/ext/tk/lib/tkextlib/tile/tlabelframe.rb b/ext/tk/lib/tkextlib/tile/tlabelframe.rb
index 8981232b25..cff66d8658 100644
--- a/ext/tk/lib/tkextlib/tile/tlabelframe.rb
+++ b/ext/tk/lib/tkextlib/tile/tlabelframe.rb
@@ -9,10 +9,16 @@ module Tk
module Tile
class TLabelframe < Tk::Tile::TFrame
end
- Labelframe = TLabelframe
+ 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
diff --git a/ext/tk/lib/tkextlib/tile/tmenubutton.rb b/ext/tk/lib/tkextlib/tile/tmenubutton.rb
index 4b81fa1c81..7c6ab28e52 100644
--- a/ext/tk/lib/tkextlib/tile/tmenubutton.rb
+++ b/ext/tk/lib/tkextlib/tile/tmenubutton.rb
@@ -7,13 +7,19 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TMenubutton < TkMenubutton
+ class TMenubutton < Tk::Menubutton
end
- Menubutton = TMenubutton
+ TMenuButton = TMenubutton
+ Menubutton = TMenubutton
+ MenuButton = TMenubutton
end
end
-class Tk::Tile::TMenubutton < TkMenubutton
+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
diff --git a/ext/tk/lib/tkextlib/tile/tnotebook.rb b/ext/tk/lib/tkextlib/tile/tnotebook.rb
index a928e64b61..4d65e363da 100644
--- a/ext/tk/lib/tkextlib/tile/tnotebook.rb
+++ b/ext/tk/lib/tkextlib/tile/tnotebook.rb
@@ -13,6 +13,9 @@ module Tk
end
end
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Notebook, :TkNotebook)
+
+
class Tk::Tile::TNotebook < TkWindow
################################
include TkItemConfigMethod
@@ -38,13 +41,35 @@ class Tk::Tile::TNotebook < TkWindow
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(tagOrId, option)
+ 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
@@ -74,9 +99,9 @@ class Tk::Tile::TNotebook < TkWindow
def add(child, keys=nil)
if keys && keys != None
- tk_send_without_enc('add', _epath(child), *hash_kv(keys))
+ tk_send('add', _epath(child), *hash_kv(keys))
else
- tk_send_without_enc('add', _epath(child))
+ tk_send('add', _epath(child))
end
self
end
diff --git a/ext/tk/lib/tkextlib/tile/tpaned.rb b/ext/tk/lib/tkextlib/tile/tpaned.rb
index 11178b19d3..d96ff43973 100644
--- a/ext/tk/lib/tkextlib/tile/tpaned.rb
+++ b/ext/tk/lib/tkextlib/tile/tpaned.rb
@@ -9,15 +9,23 @@ module Tk
module Tile
class TPaned < TkWindow
end
- Paned = TPaned
+ 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
- TkCommandNames = ['::ttk::paned'.freeze].freeze
+ 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
@@ -28,9 +36,21 @@ class Tk::Tile::TPaned < TkWindow
[self::WidgetClassName, *(args.map!{|a| _get_eval_string(a)})].join('.')
end
- def add(win, keys)
- win = _epath(win)
- tk_send_without_enc('add', win, *hash_kv(keys))
+ 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
@@ -46,10 +66,33 @@ class Tk::Tile::TPaned < TkWindow
self
end
- def panecget(pane, slot)
+ 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)
diff --git a/ext/tk/lib/tkextlib/tile/tprogressbar.rb b/ext/tk/lib/tkextlib/tile/tprogressbar.rb
index 36c1c75c23..f786d370dd 100644
--- a/ext/tk/lib/tkextlib/tile/tprogressbar.rb
+++ b/ext/tk/lib/tkextlib/tile/tprogressbar.rb
@@ -13,6 +13,9 @@ module Tk
end
end
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Progressbar, :TkProgressbar)
+
+
class Tk::Tile::TProgressbar
include Tk::Tile::TileWidget
diff --git a/ext/tk/lib/tkextlib/tile/tradiobutton.rb b/ext/tk/lib/tkextlib/tile/tradiobutton.rb
index e2f614cb97..d653a6d256 100644
--- a/ext/tk/lib/tkextlib/tile/tradiobutton.rb
+++ b/ext/tk/lib/tkextlib/tile/tradiobutton.rb
@@ -7,7 +7,7 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TRadioButton < TkRadioButton
+ class TRadioButton < Tk::RadioButton
end
TRadiobutton = TRadioButton
RadioButton = TRadioButton
@@ -15,7 +15,11 @@ module Tk
end
end
-class Tk::Tile::TRadioButton < TkRadioButton
+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
diff --git a/ext/tk/lib/tkextlib/tile/treeview.rb b/ext/tk/lib/tkextlib/tile/treeview.rb
index 68e478896c..c978a1a07b 100644
--- a/ext/tk/lib/tkextlib/tile/treeview.rb
+++ b/ext/tk/lib/tkextlib/tile/treeview.rb
@@ -12,6 +12,9 @@ module Tk
end
end
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Treeview, :TkTreeview)
+
+
module Tk::Tile::TreeviewConfig
include TkItemConfigMethod
@@ -30,6 +33,12 @@ module Tk::Tile::TreeviewConfig
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
@@ -195,6 +204,12 @@ module Tk::Tile::TreeviewConfig
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
@@ -378,7 +393,7 @@ module Tk::Tile::TreeviewConfig
when :item, 'item'
['width']
when :column, 'column'
- super(id[1])
+ super(id[1]) + ['minwidth']
when :tag, 'tag'
super(id[1])
when :heading, 'heading'
@@ -410,7 +425,7 @@ module Tk::Tile::TreeviewConfig
when :item, 'item'
['open']
when :column, 'column'
- super(id[1])
+ super(id[1]) + ['stretch']
when :tag, 'tag'
super(id[1])
when :heading, 'heading'
@@ -505,17 +520,21 @@ module Tk::Tile::TreeviewConfig
end
alias __itemcget itemcget
+ alias __itemcget_strict itemcget_strict
alias __itemconfigure itemconfigure
alias __itemconfiginfo itemconfiginfo
alias __current_itemconfiginfo current_itemconfiginfo
- private :__itemcget, :__itemconfigure
- private :__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
@@ -530,6 +549,9 @@ module Tk::Tile::TreeviewConfig
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
@@ -540,12 +562,13 @@ module Tk::Tile::TreeviewConfig
__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(tagOrId, option)
+ 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.
@@ -555,7 +578,28 @@ module Tk::Tile::TreeviewConfig
tk_call(*(__item_cget_cmd([:heading, tagOrId]) << "-#{option}"))
end
else
- __itemcget([:heading, tagOrId], option)
+ __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)
@@ -587,6 +631,7 @@ module Tk::Tile::TreeviewConfig
__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
@@ -595,6 +640,9 @@ module Tk::Tile::TreeviewConfig
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
@@ -605,6 +653,7 @@ module Tk::Tile::TreeviewConfig
__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
@@ -614,30 +663,43 @@ end
class Tk::Tile::Treeview::Item < TkObject
ItemID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ Tk::Tile::Treeview::Item::ItemID_TBL.clear }
+
+ 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
- return id unless Tk::Tile::Treeview::Item::ItemID_TBL[tpath]
- (Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id])? \
- Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]: id
+ 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
- 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 = 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
+ 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
}
- ItemID_TBL[tpath] = {} unless ItemID_TBL[tpath]
- Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id] = obj
obj
end
@@ -666,8 +728,10 @@ class Tk::Tile::Treeview::Item < TkObject
@parent = @t = tree
@tpath = tree.path
@path = @id = _insert_item(@t, parent_item, idx, keys)
- ItemID_TBL[@tpath] = {} unless ItemID_TBL[@tpath]
- ItemID_TBL[@tpath][@id] = self
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ ItemID_TBL[@tpath] = {} unless ItemID_TBL[@tpath]
+ ItemID_TBL[@tpath][@id] = self
+ }
end
def id
@id
@@ -676,6 +740,9 @@ class Tk::Tile::Treeview::Item < TkObject
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)
@@ -801,22 +868,35 @@ end
class Tk::Tile::Treeview::Root < Tk::Tile::Treeview::Item
def self.new(tree, keys = {})
tpath = tree.path
- if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] &&
- Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
- Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
- else
- super(tree, keys)
- end
+ 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 = ''
- unless Tk::Tile::Treeview::Item::ItemID_TBL[@tpath]
- Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] = {}
- end
- Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self
+ 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
@@ -826,24 +906,42 @@ class Tk::Tile::Treeview::Tag < TkObject
include TkTreatTagFont
TagID_TBL = TkCore::INTERP.create_table
- Tag_ID = ['tile_treeview_tag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ Tk::Tile::Treeview::Tag::TagID_TBL.clear }
+ (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
- return id unless Tk::Tile::Treeview::Tag::TagID_TBL[tpath]
- (Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id])? \
- Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id]: id
+ 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
- @path = @id = Tag_ID.join(TkCore::INTERP._ip_id_)
- TagID_TBL[@tpath] = {} unless TagID_TBL[@tpath]
- TagID_TBL[@tpath][@id] = self
- Tag_ID[1].succ!
+ 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
@@ -884,6 +982,9 @@ class Tk::Tile::Treeview::Tag < TkObject
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)
@@ -916,8 +1017,12 @@ class Tk::Tile::Treeview < TkWindow
WidgetClassNames[WidgetClassName] = self
def __destroy_hook__
- Tk::Tile::Treeview::Item::ItemID_TBL.delete(@path)
- Tk::Tile::Treeview::Tag::ItemID_TBL.delete(@path)
+ 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)
diff --git a/ext/tk/lib/tkextlib/tile/tscale.rb b/ext/tk/lib/tkextlib/tile/tscale.rb
index 7ec72e3515..2c46fd9bd4 100644
--- a/ext/tk/lib/tkextlib/tile/tscale.rb
+++ b/ext/tk/lib/tkextlib/tile/tscale.rb
@@ -7,7 +7,7 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TScale < TkScale
+ class TScale < Tk::Scale
end
Scale = TScale
@@ -17,7 +17,10 @@ module Tk
end
end
-class Tk::Tile::TScale < TkScale
+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
diff --git a/ext/tk/lib/tkextlib/tile/tscrollbar.rb b/ext/tk/lib/tkextlib/tile/tscrollbar.rb
index bd49ae18e3..163b8f4713 100644
--- a/ext/tk/lib/tkextlib/tile/tscrollbar.rb
+++ b/ext/tk/lib/tkextlib/tile/tscrollbar.rb
@@ -7,13 +7,16 @@ require 'tkextlib/tile.rb'
module Tk
module Tile
- class TScrollbar < TkScrollbar
+ class TScrollbar < Tk::Scrollbar
end
Scrollbar = TScrollbar
end
end
-class Tk::Tile::TScrollbar < TkScrollbar
+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
@@ -28,3 +31,24 @@ class Tk::Tile::TScrollbar < TkScrollbar
[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
index ca731d4e5b..30fae2c525 100644
--- a/ext/tk/lib/tkextlib/tile/tseparator.rb
+++ b/ext/tk/lib/tkextlib/tile/tseparator.rb
@@ -13,6 +13,9 @@ module Tk
end
end
+Tk.__set_toplevel_aliases__(:Ttk, Tk::Tile::Separator, :TkSeparator)
+
+
class Tk::Tile::TSeparator < TkWindow
include Tk::Tile::TileWidget
diff --git a/ext/tk/lib/tkextlib/tkDND/shape.rb b/ext/tk/lib/tkextlib/tkDND/shape.rb
index 570c93b0d9..d44068ed33 100644
--- a/ext/tk/lib/tkextlib/tkDND/shape.rb
+++ b/ext/tk/lib/tkextlib/tkDND/shape.rb
@@ -11,15 +11,15 @@ require 'tkextlib/setup.rb'
# call setup script
require 'tkextlib/tkDND/setup.rb'
-# TkPackage.require('shape', '0.3')
-TkPackage.require('shape')
+# TkPackage.require('Shape', '0.3')
+TkPackage.require('Shape')
module Tk
module TkDND
module Shape
extend TkCore
- PACKAGE_NAME = 'shape'.freeze
+ PACKAGE_NAME = 'Shape'.freeze
def self.package_name
PACKAGE_NAME
end
@@ -27,26 +27,28 @@ module Tk
=begin
def self.package_version
begin
- TkPackage.require('shape')
+ TkPackage.require('Shape')
rescue
''
end
end
=end
- def self.package_version
- Tk.tk_call('set', 'shape_version')
- end
- alias shape_version package_version
+ class << self
+ def package_version
+ Tk.tk_call('set', 'shape_version')
+ end
+ alias shape_version package_version
- def self.package_patchlevel
- Tk.tk_call('set', 'shape_patchlevel')
- end
- alias shape_patchlevel package_patchlevel
+ def package_patchlevel
+ Tk.tk_call('set', 'shape_patchLevel')
+ end
+ alias shape_patchlevel package_patchlevel
- def self.version
- tk_call('shape', 'version')
+ def version
+ tk_call('shape', 'version')
+ end
+ alias xshape_version version
end
- alias xshape_version version
############################
diff --git a/ext/tk/lib/tkextlib/tkDND/tkdnd.rb b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb
index a040532eb6..9a9b2dc42c 100644
--- a/ext/tk/lib/tkextlib/tkDND/tkdnd.rb
+++ b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb
@@ -57,6 +57,24 @@ module Tk
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
diff --git a/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb
index 8527f61df1..d893a83cf2 100644
--- a/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb
+++ b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb
@@ -39,7 +39,10 @@ class Tk::HTML_Widget::ClippingWindow
WidgetClassNames[WidgetClassName] = self
HtmlClip_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ HtmlClip_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ HtmlClip_TBL.mutex.synchronize{ HtmlClip_TBL.clear }
+ }
def self.new(parent, keys={})
if parent.kind_of?(Hash)
@@ -54,7 +57,9 @@ class Tk::HTML_Widget::ClippingWindow
else
ppath = ''
end
- return HtmlClip_TBL[ppath] if HtmlClip_TBL[ppath]
+ HtmlClip_TBL.mutex.synchronize{
+ return HtmlClip_TBL[ppath] if HtmlClip_TBL[ppath]
+ }
widgetname = keys.delete('widgetname')
if widgetname =~ /^(.*)\.[^.]+$/
@@ -62,7 +67,9 @@ class Tk::HTML_Widget::ClippingWindow
if ppath2[0] != ?.
ppath2 = ppath + '.' + ppath2
end
- return HtmlClip_TBL[ppath2] if HtmlClip_TBL[ppath2]
+ HtmlClip_TBL.mutex.synchronize{
+ return HtmlClip_TBL[ppath2] if HtmlClip_TBL[ppath2]
+ }
ppath = ppath2
end
@@ -79,7 +86,9 @@ class Tk::HTML_Widget::ClippingWindow
@parent = parent
@ppath = parent.path
@path = @id = @ppath + '.x'
- HtmlClip_TBL[@ppath] = self
+ HtmlClip_TBL.mutex.synchronize{
+ HtmlClip_TBL[@ppath] = self
+ }
end
def method_missing(m, *args, &b)
diff --git a/ext/tk/lib/tkextlib/tktable/tktable.rb b/ext/tk/lib/tkextlib/tktable/tktable.rb
index 4edaabc847..f6cf24b40f 100644
--- a/ext/tk/lib/tkextlib/tktable/tktable.rb
+++ b/ext/tk/lib/tkextlib/tktable/tktable.rb
@@ -77,6 +77,9 @@ module Tk::TkTable::ConfigMethod
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
@@ -90,6 +93,9 @@ module Tk::TkTable::ConfigMethod
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)
@@ -108,8 +114,8 @@ module Tk::TkTable::ConfigMethod
current_itemconfiginfo(['window', tagid(tagOrId)], slot)
end
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
end
#####################################################
@@ -118,23 +124,39 @@ class Tk::TkTable::CellTag
include TkTreatTagFont
CellTagID_TBL = TkCore::INTERP.create_table
- CellTag_ID = ['tktbl:celltag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ CellTagID_TBL.clear }
+ (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
- return id unless CellTagID_TBL[tpath]
- CellTagID_TBL[tpath][id]? CellTagID_TBL[tpath][id] : id
+ 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
- @path = @id = CellTag_ID.join(TkCore::INTERP._ip_id_)
- CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
- CellTagID_TBL[@tpath][@id] = self
- CellTag_ID[1].succ!
+ 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
@@ -144,7 +166,9 @@ class Tk::TkTable::CellTag
def destroy
tk_call(@tpath, 'tag', 'delete', @id)
- CellTagID_TBL[@tpath].delete(@id) if CellTagID_TBL[@tpath]
+ CellTagID_TBL.mutex.synchronize{
+ CellTagID_TBL[@tpath].delete(@id) if CellTagID_TBL[@tpath]
+ }
self
end
alias delete destroy
@@ -176,6 +200,9 @@ class Tk::TkTable::CellTag
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
@@ -189,22 +216,35 @@ end
class Tk::TkTable::NamedCellTag < Tk::TkTable::CellTag
def self.new(parent, name, keys=nil)
- if CellTagID_TBL[parent.path] && CellTagID_TBL[parent.path][name]
- cell = CellTagID_TBL[parent.path][name]
- cell.configure(keys) if keys
- return cell
- else
- super(parent, name, keys)
- end
+ 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
+ @tpath = parent.path
@path = @id = name
- CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
- CellTagID_TBL[@tpath][@id] = self
- configure(keys) if keys
+ CellTagID_TBL.mutex.synchronize{
+ CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
+ CellTagID_TBL[@tpath][@id] = self
+ }
+ configure(keys) if keys && ! keys.empty?
end
end
@@ -220,7 +260,9 @@ class Tk::TkTable
include Tk::ValidateConfigure
def __destroy_hook__
- Tk::TkTable::CelTag::CellTagID_TBL.delete(@path)
+ Tk::TkTable::CelTag::CellTagID_TBL.mutex.synchronize{
+ Tk::TkTable::CelTag::CellTagID_TBL.delete(@path)
+ }
end
def __boolval_optkeys
@@ -258,6 +300,24 @@ class Tk::TkTable
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)
@@ -291,6 +351,24 @@ class Tk::TkTable
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)
@@ -322,6 +400,24 @@ class Tk::TkTable
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)
@@ -356,6 +452,24 @@ class Tk::TkTable
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
@@ -746,15 +860,17 @@ class Tk::TkTable
end
def tagid2obj(tagid)
- if Tk::TkTable::CellTag::CellTagID_TBL.key?(@path)
- if Tk::TkTable::CellTag::CellTagID_TBL[@path].key?(tagid)
- Tk::TkTable::CellTag::CellTagID_TBL[@path][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
- else
- tagid
- end
+ }
end
def tag_cell(tag, *cells)
@@ -775,13 +891,15 @@ class Tk::TkTable
end
def tag_delete(tag)
tk_send('tag', 'delete', tagid(tag))
- 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)
+ 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
- end
+ }
self
end
def tag_exist?(tag)
diff --git a/ext/tk/lib/tkextlib/tktrans/tktrans.rb b/ext/tk/lib/tkextlib/tktrans/tktrans.rb
index 665c57af0c..e051c09211 100644
--- a/ext/tk/lib/tkextlib/tktrans/tktrans.rb
+++ b/ext/tk/lib/tkextlib/tktrans/tktrans.rb
@@ -39,7 +39,7 @@ class TkWindow
end
end
-class TkRoot
+class Tk::Root
undef tktrans_set_image, tktrans_get_image
def tktrans_set_image(img)
@@ -51,7 +51,7 @@ class TkRoot
end
end
-class TkToplevel
+class Tk::Toplevel
undef tktrans_set_image, tktrans_get_image
def tktrans_set_image(img)
diff --git a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
index 12f7cffabf..e10e6e299e 100644
--- a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
+++ b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
@@ -137,6 +137,24 @@ class Tk::TreeCtrl::NotifyEvent
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
@@ -399,6 +417,9 @@ module Tk::TreeCtrl::ConfigMethod
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
@@ -412,6 +433,9 @@ module Tk::TreeCtrl::ConfigMethod
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
@@ -425,6 +449,9 @@ module Tk::TreeCtrl::ConfigMethod
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
@@ -438,6 +465,9 @@ module Tk::TreeCtrl::ConfigMethod
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
@@ -451,6 +481,9 @@ module Tk::TreeCtrl::ConfigMethod
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
@@ -464,6 +497,9 @@ module Tk::TreeCtrl::ConfigMethod
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
@@ -477,6 +513,9 @@ module Tk::TreeCtrl::ConfigMethod
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
@@ -490,6 +529,9 @@ module Tk::TreeCtrl::ConfigMethod
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
@@ -502,7 +544,19 @@ module Tk::TreeCtrl::ConfigMethod
def notify_cget(win, pattern, option)
pattern = "<#{pattern}>"
- itemconfigure(['notify', [win, pattern]], option)
+ # "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}>"
@@ -512,11 +566,17 @@ module Tk::TreeCtrl::ConfigMethod
pattern = "<#{pattern}>"
itemconfiginfo(['notify', [win, pattern]], slot)
end
- alias current_notify_configinfo notify_configinfo
+ 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
@@ -527,8 +587,8 @@ module Tk::TreeCtrl::ConfigMethod
current_itemconfiginfo(['style', tagOrId], slot)
end
- private :itemcget, :itemconfigure
- private :itemconfiginfo, :current_itemconfiginfo
+ private :itemcget, :itemcget_strict
+ private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
end
##############################################
@@ -544,10 +604,18 @@ class Tk::TreeCtrl
#########################
def __destroy_hook__
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.delete(@path)
- Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.delete(@path)
- Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.delete(@path)
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.delete(@path)
+ 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
#########################
@@ -638,9 +706,11 @@ class Tk::TreeCtrl
end
def column_delete(idx)
- if Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[self.path]
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[self.path].delete(idx)
- end
+ 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
@@ -750,11 +820,13 @@ class Tk::TreeCtrl
end
def element_delete(*elems)
- if Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[self.path]
- elems.each{|elem|
- Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[self.path].delete(elem)
- }
- end
+ 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
@@ -885,22 +957,25 @@ class Tk::TreeCtrl
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)
- 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)
- }
+ 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
- end
+ }
tk_send('item', 'delete', first, last)
self
end
@@ -1520,11 +1595,13 @@ class Tk::TreeCtrl
end
def style_delete(*args)
- if Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[self.path]
- args.each{|sty|
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[self.path].delete(sty)
- }
- end
+ 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
@@ -1608,15 +1685,29 @@ end
class Tk::TreeCtrl::Column < TkObject
TreeCtrlColumnID_TBL = TkCore::INTERP.create_table
- TreeCtrlColumnID = ['treectrl_column'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.clear}
+ (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
- return id unless Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath]
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath][id]? \
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath][id] : id
+ 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={})
@@ -1625,17 +1716,19 @@ class Tk::TreeCtrl::Column < TkObject
keys = _symbolkey2str(keys)
- @path = @id =
- keys.delete('tag') ||
- Tk::TreeCtrl::Column::TreeCtrlColumnID.join(TkCore::INTERP._ip_id_)
+ 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
- unless Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath]
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath] = {}
- end
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath][@id] = self
- Tk::TreeCtrl::Column::TreeCtrlColumnID[1].succ!
+ 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
@@ -1651,6 +1744,9 @@ class Tk::TreeCtrl::Column < TkObject
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)
@@ -1692,11 +1788,18 @@ end
class Tk::TreeCtrl::Element < TkObject
TreeCtrlElementID_TBL = TkCore::INTERP.create_table
- TreeCtrlElementID = ['treectrl_element'.freeze, '00000'.taint].freeze
+
+ (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.clear
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.clear
+ }
}
def self.type2class(type)
@@ -1705,22 +1808,30 @@ class Tk::TreeCtrl::Element < TkObject
def self.id2obj(tree, id)
tpath = tree.path
- return id unless Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath]
- Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath][id]? \
+ 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
- @path = @id =
- Tk::TreeCtrl::Element::TreeCtrlElementID.join(TkCore::INTERP._ip_id_)
- unless Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath]
- Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath] = {}
- end
- Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath][@id] = self
- Tk::TreeCtrl::Element::TreeCtrlElementID[1].succ!
+ 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
@@ -1736,6 +1847,9 @@ class Tk::TreeCtrl::Element < TkObject
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)
@@ -1800,13 +1914,22 @@ end
class Tk::TreeCtrl::Item < TkObject
TreeCtrlItemID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.clear}
+ 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
- return id unless Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath]
- Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath][id]? \
- Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath][id] : id
+ 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={})
@@ -1814,10 +1937,10 @@ class Tk::TreeCtrl::Item < TkObject
@tpath = parent.path
@path = @id = @tree.item_create(keys)
- unless Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath]
- Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath] = {}
- end
- Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath][@id] = self
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath] ||= {}
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath][@id] = self
+ }
end
def id
@@ -1858,6 +1981,9 @@ class Tk::TreeCtrl::Item < TkObject
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)
@@ -1891,6 +2017,9 @@ class Tk::TreeCtrl::Item < TkObject
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)
@@ -2088,27 +2217,45 @@ end
class Tk::TreeCtrl::Style < TkObject
TreeCtrlStyleID_TBL = TkCore::INTERP.create_table
- TreeCtrlStyleID = ['treectrl_style'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.clear }
+ (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
- return id unless Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath]
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath][id]? \
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath][id] : id
+ 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
- @path = @id =
- Tk::TreeCtrl::Style::TreeCtrlStyleID.join(TkCore::INTERP._ip_id_)
- unless Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath]
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath] = {}
- end
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath][@id] = self
- Tk::TreeCtrl::Style::TreeCtrlStyleID[1].succ!
+
+ 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
@@ -2124,6 +2271,9 @@ class Tk::TreeCtrl::Style < TkObject
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)
diff --git a/ext/tk/lib/tkextlib/version.rb b/ext/tk/lib/tkextlib/version.rb
index c7816fd4a5..434ed11a2e 100644
--- a/ext/tk/lib/tkextlib/version.rb
+++ b/ext/tk/lib/tkextlib/version.rb
@@ -2,5 +2,5 @@
# release date of tkextlib
#
module Tk
- Tkextlib_RELEASE_DATE = '2007-05-26'.freeze
+ Tkextlib_RELEASE_DATE = '2008-05-23'.freeze
end
diff --git a/ext/tk/lib/tkextlib/vu/pie.rb b/ext/tk/lib/tkextlib/vu/pie.rb
index 78f3fa54da..c1fb6857bf 100644
--- a/ext/tk/lib/tkextlib/vu/pie.rb
+++ b/ext/tk/lib/tkextlib/vu/pie.rb
@@ -116,13 +116,26 @@ end
class Tk::Vu::PieSlice
SliceID_TBL = TkCore::INTERP.create_table
- Pie_Slice_ID = ['vu:pie'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ SliceID_TBL.clear }
+
+ (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
- return id unless SliceID_TBL[pie_path]
- SliceID_TBL[pie_path][id]? SliceID_TBL[pie_path][id]: id
+ 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)
@@ -131,10 +144,14 @@ class Tk::Vu::PieSlice
end
@parent = @pie = parent
@ppath = parent.path
- @path = @id = Pie_Slice_ID.join(TkCore::INTERP._ip_id_)
- SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath]
- SliceID_TBL[@ppath][@id] = self
- Pie_Slice_ID[1].succ!
+ 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
@@ -160,6 +177,10 @@ class Tk::Vu::PieSlice
@pie.itemcget(@id, slot)
end
+ def cget_strict(slot)
+ @pie.itemcget_strict(@id, slot)
+ end
+
def configure(*args)
@pie.itemconfigure(@id, *args)
self
@@ -209,22 +230,48 @@ end
class Tk::Vu::NamedPieSlice
def self.new(parent, name, *args)
- if SliceID_TBL[parent.path] && SliceID_TBL[parent.path][name]
- return SliceID_TBL[parent.path][name]
- else
- super(parent, name, *args)
- end
+ 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[@ppath] = {} unless SliceID_TBL[@ppath]
- SliceID_TBL[@ppath][@id] = self
+ 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
diff --git a/ext/tk/lib/tkextlib/vu/spinbox.rb b/ext/tk/lib/tkextlib/vu/spinbox.rb
index b6499645a3..a7e40ea319 100644
--- a/ext/tk/lib/tkextlib/vu/spinbox.rb
+++ b/ext/tk/lib/tkextlib/vu/spinbox.rb
@@ -17,6 +17,6 @@ end
module Tk
module Vu
- Spinbox = TkSpinbox
+ Spinbox = Tk::Spinbox
end
end
diff --git a/ext/tk/lib/tkextlib/winico/winico.rb b/ext/tk/lib/tkextlib/winico/winico.rb
index c53a3ff48c..00316fd441 100644
--- a/ext/tk/lib/tkextlib/winico/winico.rb
+++ b/ext/tk/lib/tkextlib/winico/winico.rb
@@ -34,10 +34,15 @@ end
class Tk::Winico
WinicoID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ WinicoID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ WinicoID_TBL.mutex.synchronize{ WinicoID_TBL.clear }
+ }
def self.id2obj(id)
- (WinicoID_TBL.key?(id))? WinicoID_TBL[id] : id
+ WinicoID_TBL.mutex.synchronize{
+ (WinicoID_TBL.key?(id))? WinicoID_TBL[id] : id
+ }
end
def self.info
@@ -81,7 +86,9 @@ class Tk::Winico
"must be given proper information from where loading icons"
end
@path = @id
- WinicoID_TBL[@id] = self
+ WinicoID_TBL.mutex.synchronize{
+ WinicoID_TBL[@id] = self
+ }
end
def id
@@ -96,7 +103,9 @@ class Tk::Winico
def delete
tk_call('winico', 'delete', @id)
- WinicoID_TBL.delete(@id)
+ WinicoID_TBL.mutex.synchronize{
+ WinicoID_TBL.delete(@id)
+ }
self
end
alias destroy delete
@@ -126,15 +135,39 @@ class Tk::Winico
[ ?n, TkComm.method(:number) ],
[ ?s, TkComm.method(:string) ],
[ ?x, proc{|id|
- if Tk::Winico::WinicoID_TBL.key?(id)
- Tk::Winico::WinicoID_TBL[id]
- else
- Tk::Winico.new(nil, nil, id)
- end
+ 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)
@@ -154,7 +187,8 @@ class Tk::Winico
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.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])
@@ -170,7 +204,8 @@ class Tk::Winico
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.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])
diff --git a/ext/tk/sample/binstr_usage.rb b/ext/tk/sample/binstr_usage.rb
index 91692856f9..be8399ba51 100644
--- a/ext/tk/sample/binstr_usage.rb
+++ b/ext/tk/sample/binstr_usage.rb
@@ -16,7 +16,7 @@ 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=['images','tcllogo.gif'].join(File::Separator)
+ImgFile=[File.dirname(__FILE__), 'images','tcllogo.gif'].join(File::Separator)
ph1 = TkPhotoImage.new(:file=>ImgFile)
p ph1.configinfo
@@ -28,12 +28,18 @@ ph2 = TkPhotoImage.new(:data=>b_str)
p ph2.configinfo
p ph2.data(:grayscale=>true)
-ph3 = TkPhotoImage.new()
-ph3.put(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/demos-en/anilabel.rb b/ext/tk/sample/demos-en/anilabel.rb
index f063bc53a4..0b9bc7357e 100644
--- a/ext/tk/sample/demos-en/anilabel.rb
+++ b/ext/tk/sample/demos-en/anilabel.rb
@@ -15,8 +15,10 @@ $anilabel_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($anilabel_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($anilabel_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -25,7 +27,7 @@ msg = TkLabel.new($anilabel_demo) {
msg.pack('side'=>'top')
# frame
-TkFrame.new($anilabel_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -43,8 +45,8 @@ TkFrame.new($anilabel_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# create frame for label demo
-f_left = TkLabelFrame.new($anilabel_demo, :text=>'Scrolling Texts')
-f_right = TkLabelFrame.new($anilabel_demo, :text=>'GIF Image')
+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)
diff --git a/ext/tk/sample/demos-en/aniwave.rb b/ext/tk/sample/demos-en/aniwave.rb
index ebe27b875f..63a04a7b98 100644
--- a/ext/tk/sample/demos-en/aniwave.rb
+++ b/ext/tk/sample/demos-en/aniwave.rb
@@ -16,8 +16,10 @@ $aniwave_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($aniwave_demo).pack(:fill=>:both, :expand=>true)
+
# create label
-msg = TkLabel.new($aniwave_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -26,7 +28,7 @@ msg = TkLabel.new($aniwave_demo) {
msg.pack('side'=>'top')
# create frame
-TkFrame.new($aniwave_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -58,6 +60,7 @@ class AnimatedWaveDemo
@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
@@ -112,4 +115,4 @@ class AnimatedWaveDemo
end
# Start the animation processing
-AnimatedWaveDemo.new($aniwave_demo, :left).move
+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 b62e1966eb..055cd2af3c 100644
--- a/ext/tk/sample/demos-en/arrow.rb
+++ b/ext/tk/sample/demos-en/arrow.rb
@@ -77,11 +77,19 @@ def arrowSetup(c)
'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',
+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,7 +134,7 @@ $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,
+$arrow_canvas = TkCanvas.new(base_frame, 'width'=>500, 'height'=>350,
'relief'=>'sunken', 'borderwidth'=>2)
$arrow_canvas.pack('expand'=>'yes', 'fill'=>'both')
diff --git a/ext/tk/sample/demos-en/bind.rb b/ext/tk/sample/demos-en/bind.rb
index aabe7f0849..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}
@@ -94,35 +96,32 @@ TkText.new($bind_demo){|t|
}
d1.bind('1',
proc{
- eval(`cat #{[$demo_dir,'items.rb'].join(File::Separator)}`,
- _null_binding)
+ 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)}`,
- _null_binding)
+ 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)}`,
- _null_binding)
+ 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)}`,
- _null_binding)
+ 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)}`,
- _null_binding)
+ 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)}`,
- _null_binding)
+ 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 7fd551c7a5..133adb0543 100644
--- a/ext/tk/sample/demos-en/bitmap.rb
+++ b/ext/tk/sample/demos-en/bitmap.rb
@@ -21,7 +21,7 @@ def bitmapRow(w,*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')
+ 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',
+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/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 971a8fea73..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,7 +56,7 @@ TkFrame.new($check_demo) {|frame|
TkButton.new(frame) {
text 'See Variables'
command proc{
- showVars($check_demo,
+ 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
index 97d61fba0c..faea748a87 100644
--- a/ext/tk/sample/demos-en/check2.rb
+++ b/ext/tk/sample/demos-en/check2.rb
@@ -15,8 +15,10 @@ $check2_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($check2_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($check2_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -31,7 +33,7 @@ brakes = TkVariable.new(0)
sober = TkVariable.new(0)
# frame
-TkFrame.new($check2_demo) {|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',
@@ -59,15 +61,15 @@ TkFrame.new($check2_demo) {|frame|
# checkbutton
-TkCheckButton.new($check2_demo, :text=>'Safety Check', :variable=>safety,
+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($check2_demo, 'text'=>'Wipers OK', 'variable'=>wipers),
- TkCheckButton.new($check2_demo, 'text'=>'Brakes OK', 'variable'=>brakes),
- TkCheckButton.new($check2_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', 'padx'=>15, 'pady'=>2, 'anchor'=>'w')
diff --git a/ext/tk/sample/demos-en/clrpick.rb b/ext/tk/sample/demos-en/clrpick.rb
index 9486fde314..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',
+#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']})
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')
}
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 0838dfbe08..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',
+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,7 +47,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)
@@ -53,7 +55,7 @@ unless $tk_version =~ /^4\.[01]/
end
# canvas
-$cscroll_canvas = TkCanvas.new($cscroll_demo,
+$cscroll_canvas = TkCanvas.new(base_frame,
'relief'=>'sunken', 'borderwidth'=>2,
'scrollregion'=>['-11c', '-11c', '50c', '20c']
) {|c|
@@ -64,7 +66,7 @@ $cscroll_canvas = TkCanvas.new($cscroll_demo,
'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')
@@ -74,7 +76,7 @@ $cscroll_canvas = TkCanvas.new($cscroll_demo,
end
}
- TkScrollbar.new($cscroll_demo, 'orient'=>'horiz',
+ 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]/
diff --git a/ext/tk/sample/demos-en/ctext.rb b/ext/tk/sample/demos-en/ctext.rb
index dbb5e32638..01374b0321 100644
--- a/ext/tk/sample/demos-en/ctext.rb
+++ b/ext/tk/sample/demos-en/ctext.rb
@@ -19,8 +19,10 @@ $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',
+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.
@@ -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,24 +53,33 @@ $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',
+$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')
+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")
@@ -110,9 +121,14 @@ 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')
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,9 +139,14 @@ 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',
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 415b45f86c..f7df3a5653 100644
--- a/ext/tk/sample/demos-en/entry3.rb
+++ b/ext/tk/sample/demos-en/entry3.rb
@@ -17,7 +17,9 @@ $entry3_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($entry3_demo,
+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 \
@@ -28,13 +30,13 @@ 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{
@@ -60,23 +62,41 @@ TkFrame.new($entry3_demo){|f|
# count - Counter to control the number of times flashed
def focusAndFlash(widget, fg, bg, count=5)
return if count <= 0
- TkTimer.new(200, count,
- 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']
+ 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')
@@ -158,14 +178,14 @@ def validatePhoneChange(widget, vmode, idx, char)
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).
+ # 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=>[
@@ -184,14 +204,14 @@ TkEntry.new(l3, :validate=>:key, :invcmd=>proc{Tk.bell},
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')
-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 36b19de557..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',
+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,7 +60,7 @@ TkFrame.new($filebox_demo) {|frame|
$tk_strictMotif = TkVarAccess.new('tk_strictMotif')
if ($tk_platform['platform'] == 'unix')
- TkCheckButton.new($filebox_demo,
+ TkCheckButton.new(base_frame,
'text'=>'Use Motif Style Dialog',
'variable'=>$tk_strictMotif,
'onvalue'=>1, 'offvalue'=>0 ).pack('anchor'=>'c')
@@ -91,7 +93,10 @@ def fileDialog(w,ent,operation)
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 53adcf96b6..7023f2a72e 100644
--- a/ext/tk/sample/demos-en/floor.rb
+++ b/ext/tk/sample/demos-en/floor.rb
@@ -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',
+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',
+ $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',
+ 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')
diff --git a/ext/tk/sample/demos-en/floor2.rb b/ext/tk/sample/demos-en/floor2.rb
index efaf9e250d..88b07aeee4 100644
--- a/ext/tk/sample/demos-en/floor2.rb
+++ b/ext/tk/sample/demos-en/floor2.rb
@@ -1590,14 +1590,16 @@ $floor2_demo = TkToplevel.new {|w|
minsize(100,100)
}
+base_frame = TkFrame.new($floor2_demo).pack(:fill=>:both, :expand=>true)
+
# label
-TkLabel.new($floor2_demo, 'font'=>$font, 'wraplength'=>'8i', 'justify'=>'left',
+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($floor2_demo) {|frame|
+$floor2_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -1620,17 +1622,17 @@ $floorItems2 = {}
# canvas
if $tk_version =~ /^4\.[01]/
- $floor2_canvas_frame = TkFrame.new($floor2_demo,'bd'=>2,'relief'=>'sunken',
+ $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($floor2_demo, 'orient'=>'horiz',
+ 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($floor2_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]/
$floor2_canvas.pack('expand'=>'yes', 'fill'=>'both')
else
- TkFrame.new($floor2_demo) {|f|
+ TkFrame.new(base_frame) {|f|
pack('side'=>'top', 'fill'=>'both', 'expand'=>'yes')
h = TkScrollbar.new(f, 'highlightthickness'=>0, 'orient'=>'horizontal')
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
index 8d3f6d14f7..c6fa37c09c 100644
--- a/ext/tk/sample/demos-en/goldberg.rb
+++ b/ext/tk/sample/demos-en/goldberg.rb
@@ -54,6 +54,8 @@ $goldberg_demo = TkToplevel.new {|w|
# positionWindow(w)
}
+base_frame = TkFrame.new($goldberg_demo).pack(:fill=>:both, :expand=>true)
+
=begin
# label
msg = TkLabel.new($goldberg_demo) {
@@ -175,7 +177,8 @@ class TkGoldberg_Demo
do_ctrl_frame
do_detail_frame
- msg = TkLabel.new(@parent, :bg=>@C['bg'], :fg=>'white') {
+ # 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'
@@ -185,7 +188,8 @@ class TkGoldberg_Demo
frame = TkFrame.new(@parent, :bg=>@C['bg'])
- TkButton.new(frame, :bg=>@C['bg'], :activebackground=>@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
@@ -194,12 +198,14 @@ class TkGoldberg_Demo
}
}.pack('side'=>'left')
- TkButton.new(frame, :bg=>@C['bg'], :activebackground=>@C['bg']) {
+ # 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 = 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)
@@ -208,10 +214,11 @@ class TkGoldberg_Demo
end
def do_ctrl_frame
- @start = TkButton.new(@parent, :text=>'Start', :bd=>6,
+ @start = Tk::Button.new(@parent, :text=>'Start', :bd=>6,
:command=>proc{do_button(0)})
- @start.font(@start['font'].weight('bold'))
- font = @start['font']
+ 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,
@@ -1996,4 +2003,4 @@ class TkGoldberg_Demo
end
end
-TkGoldberg_Demo.new($goldberg_demo)
+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 58aca2df07..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{
@@ -63,16 +65,18 @@ TkBitmapImage.new('file'=>[$demo_dir,'..',
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){
+ # 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){
+ # TkRadioButton.new(f){
+ Tk::RadioButton.new(f){
bitmap '@' + [$demo_dir,'..',
'images','noletter.xbm'].join(File::Separator)
variable letters
@@ -81,14 +85,16 @@ TkFrame.new($icon_demo, 'borderwidth'=>10){|w|
}.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) {
+ # TkCheckButton.new(w) {
+ Tk::CheckButton.new(w) {
bitmap '@' + [$demo_dir,'..',
'images','letters.xbm'].join(File::Separator)
indicatoron 0
diff --git a/ext/tk/sample/demos-en/image1.rb b/ext/tk/sample/demos-en/image1.rb
index 05c9705c9c..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{
@@ -54,7 +56,10 @@ 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 1aff7173be..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{
@@ -53,21 +55,21 @@ $dirName = TkVariable.new([$demo_dir,'..','images'].join(File::Separator))
$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 e46d3796f2..43afab7ecd 100644
--- a/ext/tk/sample/demos-en/image3.rb
+++ b/ext/tk/sample/demos-en/image3.rb
@@ -19,27 +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)
+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
@@ -49,7 +51,7 @@ end
# label
-msg = TkLabel.new($image3_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -58,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{
@@ -86,11 +88,11 @@ 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:',
+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)
@@ -102,16 +104,17 @@ image3_lbx = TkListbox.new(image3_ff, :width=>20, :height=>10) {
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, '-',
diff --git a/ext/tk/sample/demos-en/items.rb b/ext/tk/sample/demos-en/items.rb
index 8ab7668a07..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
@@ -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'
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 55e07a5ebc..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,8 +49,8 @@ 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')}
@@ -59,7 +61,8 @@ f_right = TkFrame.new($label_demo)
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) {
+# TkLabel.new(f_right) {
+Tk::Label.new(f_right) {
bitmap('@' + [$demo_dir,'..','images','face.xbm'].join(File::Separator))
borderwidth 2
relief 'sunken'
diff --git a/ext/tk/sample/demos-en/labelframe.rb b/ext/tk/sample/demos-en/labelframe.rb
index 842a4f6c04..c912ff4c52 100644
--- a/ext/tk/sample/demos-en/labelframe.rb
+++ b/ext/tk/sample/demos-en/labelframe.rb
@@ -17,8 +17,10 @@ $labelframe_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($labelframe_demo).pack(:fill=>:both, :expand=>true)
+
# Some information
-TkLabel.new($labelframe_demo,
+TkLabel.new(base_frame,
:font=>$font, :wraplength=>'4i', :justify=>:left,
:text=><<EOL).pack(:side=>:top)
Labelframes are used to group related widgets together. \
@@ -29,7 +31,7 @@ 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{
@@ -43,7 +45,7 @@ TkFrame.new($labelframe_demo){|f|
}
# Demo area
-w = TkFrame.new($labelframe_demo).pack(:side=>:bottom, :fill=>:both,
+w = TkFrame.new(base_frame).pack(:side=>:bottom, :fill=>:both,
:expand=>true)
# A group of radiobuttons in a labelframe
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 8370d2f5f0..bf6c22cb9d 100644
--- a/ext/tk/sample/demos-en/menu.rb
+++ b/ext/tk/sample/demos-en/menu.rb
@@ -15,8 +15,10 @@ $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
@@ -26,7 +28,7 @@ rescue
end
# label
-TkLabel.new($menu_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.")
@@ -36,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{
@@ -105,7 +107,7 @@ TkMenubutton.new($menu_frame, 'text'=>'Cascades', 'underline'=>0) {|m|
'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)
oil = TkVariable.new(0)
@@ -127,7 +129,7 @@ TkMenubutton.new($menu_frame, 'text'=>'Cascades', 'underline'=>0) {|m|
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)
pointSize = TkVariable.new
diff --git a/ext/tk/sample/demos-en/menu84.rb b/ext/tk/sample/demos-en/menu84.rb
index cb616d8461..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,7 +35,7 @@ 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,
@@ -43,7 +45,7 @@ TkFrame.new($menu84_demo) {|frame|
# frame
-TkFrame.new($menu84_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
diff --git a/ext/tk/sample/demos-en/menubu.rb b/ext/tk/sample/demos-en/menubu.rb
index e2ddd07bc6..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{
@@ -64,7 +66,7 @@ TkFrame.new($menubu_demo) {|frame|
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 {
diff --git a/ext/tk/sample/demos-en/msgbox.rb b/ext/tk/sample/demos-en/msgbox.rb
index aab1b619cf..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',
+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,8 +47,8 @@ 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')
$msgbox_rightframe.pack('side'=>'left', 'expand'=>'yes', 'fill'=>'y',
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 48ba86de02..26941b84a8 100644
--- a/ext/tk/sample/demos-en/paned1.rb
+++ b/ext/tk/sample/demos-en/paned1.rb
@@ -16,7 +16,9 @@ $paned1_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($paned1_demo,
+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.)
@@ -24,7 +26,7 @@ If your Tk library linked to Ruby doesn't include a 'panedwindow', this demo doe
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{
@@ -37,9 +39,9 @@ TkFrame.new($paned1_demo){|f|
}).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 5911cadab6..0e62013886 100644
--- a/ext/tk/sample/demos-en/paned2.rb
+++ b/ext/tk/sample/demos-en/paned2.rb
@@ -16,7 +16,9 @@ $paned2_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($paned2_demo,
+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.)
@@ -24,7 +26,7 @@ If your Tk library linked to Ruby doesn't include a 'panedwindow', this demo doe
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{
@@ -61,7 +63,7 @@ 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|
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
index 36bb44edec..5f7d361170 100644
--- a/ext/tk/sample/demos-en/pendulum.rb
+++ b/ext/tk/sample/demos-en/pendulum.rb
@@ -18,8 +18,10 @@ $pendulum_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($pendulum_demo).pack(:fill=>:both, :expand=>true)
+
# create label
-msg = TkLabel.new($pendulum_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -28,7 +30,7 @@ msg = TkLabel.new($pendulum_demo) {
msg.pack('side'=>'top')
# create frame
-TkFrame.new($pendulum_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
text 'Dismiss'
command proc{
@@ -49,9 +51,11 @@ TkFrame.new($pendulum_demo) {|frame|
class PendulumAnimationDemo
def initialize(frame)
# Create some structural widgets
- pane = TkPanedWindow.new(frame).pack(:fill=>:both, :expand=>true)
- pane.add(@lf1 = TkLabelFrame.new(pane, :text=>'Pendulum Simulation'))
- pane.add(@lf2 = TkLabelFrame.new(pane, :text=>'Phase Space'))
+ @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.
@@ -99,23 +103,24 @@ class PendulumAnimationDemo
@dTheta = 0.0
@length = 150
- # init display
- showPendulum
-
# 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, y)}, '%x %y')
- btag.bind('B1-Motion', proc{|x, y| showPendulum(x, y)}, '%x %y')
+ 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, y); @timer.start }, '%x %y')
+ proc{|x, y| showPendulum(x.to_i, y.to_i); @timer.start },
+ '%x %y')
- btag.bind('Configure', proc{|w| @plate.coords(0, 25, w, 25)}, '%w')
+ 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)
@@ -124,6 +129,14 @@ class PendulumAnimationDemo
@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
@@ -154,6 +167,10 @@ class PendulumAnimationDemo
# 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]
@@ -220,4 +237,4 @@ class PendulumAnimationDemo
end
# Start the animation processing
-PendulumAnimationDemo.new($pendulum_demo)
+PendulumAnimationDemo.new(base_frame)
diff --git a/ext/tk/sample/demos-en/plot.rb b/ext/tk/sample/demos-en/plot.rb
index 6d01deeef5..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',
+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,7 +49,7 @@ $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
diff --git a/ext/tk/sample/demos-en/puzzle.rb b/ext/tk/sample/demos-en/puzzle.rb
index 0885cf2975..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,6 +98,9 @@ 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)
}
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 2b56ccc9b1..6c02aef0cf 100644
--- a/ext/tk/sample/demos-en/radio2.rb
+++ b/ext/tk/sample/demos-en/radio2.rb
@@ -19,8 +19,10 @@ $radio2_demo = TkToplevel.new {|w|
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{
@@ -53,18 +55,18 @@ TkFrame.new($radio2_demo) {|frame|
TkButton.new(frame) {
text 'See Variables'
command proc{
- showVars($radio2_demo,
+ 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',
+f_left = TkLabelFrame.new(base_frame, 'text'=>'Point Size',
'pady'=>2, 'padx'=>2)
-f_mid = TkLabelFrame.new($radio2_demo, 'text'=>'Color',
+f_mid = TkLabelFrame.new(base_frame, 'text'=>'Color',
'pady'=>2, 'padx'=>2)
-f_right = TkLabelFrame.new($radio2_demo, 'text'=>'Alignment',
+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')
@@ -90,7 +92,8 @@ 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',
+# 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))
diff --git a/ext/tk/sample/demos-en/radio3.rb b/ext/tk/sample/demos-en/radio3.rb
index 70c4abb3b5..9c9d75ef4a 100644
--- a/ext/tk/sample/demos-en/radio3.rb
+++ b/ext/tk/sample/demos-en/radio3.rb
@@ -19,8 +19,10 @@ $radio3_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($radio3_demo).pack(:fill=>:both, :expand=>true)
+
# label
-msg = TkLabel.new($radio3_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '5i'
justify 'left'
@@ -34,14 +36,14 @@ color = TkVariable.new
align = TkVariable.new
# frame
-TkFrame.new($radio3_demo) {|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($radio3_demo, ['size', size],
+ showVars(base_frame, ['size', size],
['color', color], ['compound', align])
}),
TkButton.new(frame, :text=>'See Code',
@@ -61,17 +63,17 @@ TkFrame.new($radio3_demo) {|frame|
}
# frame
-f_left = TkLabelFrame.new($radio3_demo, 'text'=>'Point Size',
+f_left = TkLabelFrame.new(base_frame, 'text'=>'Point Size',
'pady'=>2, 'padx'=>2)
-f_mid = TkLabelFrame.new($radio3_demo, 'text'=>'Color',
+f_mid = TkLabelFrame.new(base_frame, 'text'=>'Color',
'pady'=>2, 'padx'=>2)
-f_right = TkLabelFrame.new($radio3_demo, 'text'=>'Alignment',
+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($radio3_demo, 'text'=>'Tristate',
+TkButton.new(base_frame, 'text'=>'Tristate',
'command'=>proc{size.value = 'multi'; color.value = 'multi'}){
grid('column'=>2, 'row'=>2, 'pady'=>'.5c', 'padx'=>'.5c')
}
@@ -99,7 +101,8 @@ TkButton.new($radio3_demo, 'text'=>'Tristate',
}.pack('side'=>'top', 'pady'=>2, 'fill'=>'x')
}
-label = TkLabel.new(f_right, 'text'=>'Label', 'bitmap'=>'questhead',
+# 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))
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 4299d57b4f..26cd4f3b1c 100644
--- a/ext/tk/sample/demos-en/ruler.rb
+++ b/ext/tk/sample/demos-en/ruler.rb
@@ -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',
+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,7 +59,7 @@ $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')
#
diff --git a/ext/tk/sample/demos-en/sayings.rb b/ext/tk/sample/demos-en/sayings.rb
index cef0f4ecf4..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) {
diff --git a/ext/tk/sample/demos-en/search.rb b/ext/tk/sample/demos-en/search.rb
index 3d3b4aecc8..e1fc565e9d 100644
--- a/ext/tk/sample/demos-en/search.rb
+++ b/ext/tk/sample/demos-en/search.rb
@@ -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,7 +100,7 @@ $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')
$search_fileName = TkVariable.new
@@ -115,7 +117,7 @@ TkFrame.new($search_demo) {|f|
.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')
$search_searchString = TkVariable.new
@@ -133,14 +135,14 @@ TkFrame.new($search_demo) {|f|
}
}.pack('side'=>'top', 'fill'=>'x')
-$search_text = TkText.new($search_demo, 'setgrid'=>true, 'wrap'=>'word') {|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.
@@ -173,8 +175,13 @@ 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 58616b1e02..c2a3a8949b 100644
--- a/ext/tk/sample/demos-en/spin.rb
+++ b/ext/tk/sample/demos-en/spin.rb
@@ -15,7 +15,9 @@ $spin_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($spin_demo,
+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. \
@@ -34,7 +36,7 @@ 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{
@@ -53,11 +55,11 @@ australianCities = [
]
[
- TkSpinbox.new($spin_demo, :from=>1, :to=>10, :width=>10, :validate=>:key,
+ TkSpinbox.new(base_frame, :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,
+ TkSpinbox.new(base_frame, :from=>0, :to=>3, :increment=>0.5,
:format=>'%05.2f', :width=>10),
- TkSpinbox.new($spin_demo, :values=>australianCities, :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 5ed11aa459..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.*/
@@ -109,8 +121,13 @@ TkText.new($style_demo){|t|
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')
style_tag_spacing = TkTextTag.new(t, 'spacing1'=>'10p', 'spacing2'=>'2p',
@@ -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/text.rb b/ext/tk/sample/demos-en/text.rb
index 4bb4b6bc7e..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}
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 24a4bcf706..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,
+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|
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')
@@ -206,7 +208,11 @@ 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)
diff --git a/ext/tk/sample/demos-en/twind2.rb b/ext/tk/sample/demos-en/twind2.rb
index c42e0999d7..43990c1151 100644
--- a/ext/tk/sample/demos-en/twind2.rb
+++ b/ext/tk/sample/demos-en/twind2.rb
@@ -15,8 +15,10 @@ $twind2_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($twind2_demo).pack(:fill=>:both, :expand=>true)
+
# frame
-$twind2_buttons = TkFrame.new($twind2_demo) {|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',
@@ -38,7 +40,7 @@ $twind2_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# frame
$twind2_text = nil
-TkFrame.new($twind2_demo, 'highlightthickness'=>2, 'borderwidth'=>2,
+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',
diff --git a/ext/tk/sample/demos-en/unicodeout.rb b/ext/tk/sample/demos-en/unicodeout.rb
index 07e3bf52b5..9c230a2536 100644
--- a/ext/tk/sample/demos-en/unicodeout.rb
+++ b/ext/tk/sample/demos-en/unicodeout.rb
@@ -16,7 +16,9 @@ $unicodeout_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($unicodeout_demo,
+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 \
@@ -36,7 +38,7 @@ 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{
@@ -49,7 +51,7 @@ TkFrame.new($unicodeout_demo){|f|
}).pack(:side=>:left, :expand=>true)
}
-wait_msg = TkLabel.new($unicodeout_demo,
+wait_msg = TkLabel.new(base_frame,
:text=>"Please wait while loading fonts...",
:font=>"Helvetica 12 italic").pack
@@ -63,8 +65,8 @@ 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
@@ -79,7 +81,7 @@ class Unicodeout_SampleFrame < TkFrame
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
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 3c50582211..9a0605d8b9 100644
--- a/ext/tk/sample/demos-en/widget
+++ b/ext/tk/sample/demos-en/widget
@@ -14,6 +14,8 @@ require 'tk'
### $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
@@ -21,7 +23,8 @@ require 'tk'
#----------------------------------------------------------------
# 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"}
@@ -102,14 +105,22 @@ 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('Meta-q', proc{exit})
+$root.bind('Control-q', proc{exit})
=begin
TkFrame.new($root){|frame|
@@ -164,12 +175,17 @@ 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
@@ -178,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
@@ -247,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) \
@@ -256,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
@@ -289,6 +326,8 @@ txt.insert('end', "13. A simple user interface for viewing images. (if supported
txt.insert('end', " \n ", tag_demospace)
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")
txt.insert('end', "Listboxes\n", tag_title)
@@ -299,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)
@@ -313,7 +356,9 @@ txt.insert('end',
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")
@@ -331,6 +376,8 @@ txt.insert('end', "5. A text widget with embedded windows. (if supported)\n", ta
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")
txt.insert('end', "Canvases\n", tag_title)
@@ -351,31 +398,43 @@ txt.insert('end', "7. A building floor plan. (another way to create canvas items
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")
@@ -383,9 +442,11 @@ 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. Color picker.\n", tag_demo, "demo-clrpick")
+txt.insert('end', "3. File selection dialog.\n", tag_demo, "demo-filebox")
+txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "4. Color picker.\n", tag_demo, "demo-clrpick")
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
@@ -441,11 +502,16 @@ def showVars1(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|
@@ -459,7 +525,7 @@ def showVars1(parent, *args)
.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)
@@ -474,10 +540,12 @@ def showVars2(parent, *args)
rescue
end
end
- $showVarsWin[parent.path] = TkToplevel.new(parent) {|w|
+ $showVarsWin[parent.path] = TkToplevel.new(parent) {|top|
title "Variable values"
- TkLabelFrame.new(w, :text=>"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'),
@@ -489,15 +557,15 @@ def showVars2(parent, *args)
f.grid_columnconfig(1, :weight=>1)
f.grid_rowconfig(100, :weight=>1)
}
- TkButton.new(w, :text=>"OK", :width=>8, :default=>:active,
- :command=>proc{w.destroy}){|b|
- w.bind('Return', proc{b.invoke})
- w.bind('Escape', proc{b.invoke})
+ 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])
}
- w.grid_columnconfig(0, :weight=>1)
- w.grid_rowconfig(0, :weight=>1)
+ base.grid_columnconfig(0, :weight=>1)
+ base.grid_rowconfig(0, :weight=>1)
}
end
@@ -591,8 +659,27 @@ def _null_binding
end
private :_null_binding
-def eval_samplecode(code)
- Thread.new{ _null_binding.pseudo_toplevel_eval{ eval(code) } }.run
+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
@@ -612,7 +699,7 @@ def invoke(txt, idx)
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)
+ 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")
@@ -669,20 +756,32 @@ def showCode1(demo)
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
}
- }.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'), _null_binding)}
- command proc{eval_samplecode($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_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')
@@ -727,10 +826,21 @@ def showCode1(demo)
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')
@@ -741,6 +851,9 @@ def showCode1(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
@@ -761,7 +874,19 @@ def showCode2(demo)
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
@@ -774,12 +899,12 @@ def showCode2(demo)
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'))
+ eval_samplecode($code_text.get('1.0','end'), '<viewer>')
},
:image=>$image['refresh'], :compound=>:left)
- TkGrid('x', b_run, b_prn, b_dis, :padx=>4, :pady=>[6,4])
- bf.grid_columnconfigure(0, :weight=>1)
+ 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')
@@ -792,6 +917,17 @@ def showCode2(demo)
$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
@@ -803,6 +939,9 @@ def showCode2(demo)
$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
@@ -896,12 +1035,13 @@ end
#
def aboutBox
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo',
- 'message'=>"Ruby/Tk widget demonstration Ver.1.6.0-en\n\n" +
+ 'message'=>"Ruby/Tk widget demonstration Ver.1.7.0-en\n\n" +
"based on demos of Tk8.1 -- 8.5 " +
- "( Copyright:: " +
+ "( Copyright of Tcl/Tk demos:: " +
"(c) 1996-1997 Sun Microsystems, Inc. / " +
"(c) 1997-2000 Ajuba Solutions, Inc. / " +
- "(c) 2001-2003 Donal K. Fellows )\n\n" +
+ "(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}")
@@ -923,7 +1063,7 @@ ARGV.each{|cmd|
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)
+ eval_samplecode(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join, cmd + '.rb')
}
if no_launcher
$root.withdraw # hide root window
diff --git a/ext/tk/sample/demos-jp/anilabel.rb b/ext/tk/sample/demos-jp/anilabel.rb
index 97781fbe77..aee57f9f6a 100644
--- a/ext/tk/sample/demos-jp/anilabel.rb
+++ b/ext/tk/sample/demos-jp/anilabel.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# animated label widget demo (called by 'widget')
#
@@ -16,8 +17,10 @@ $anilabel_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($anilabel_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($anilabel_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -26,7 +29,7 @@ msg = TkLabel.new($anilabel_demo) {
msg.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($anilabel_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
#text 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -45,8 +48,8 @@ TkFrame.new($anilabel_demo) {|frame|
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# label demo Íѥե졼¥àÀ¸À®
-f_left = TkLabelFrame.new($anilabel_demo, :text=>'Scrolling Texts')
-f_right = TkLabelFrame.new($anilabel_demo, :text=>'GIF Image')
+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)
diff --git a/ext/tk/sample/demos-jp/aniwave.rb b/ext/tk/sample/demos-jp/aniwave.rb
index 81e2d76b30..8fa14f65fe 100644
--- a/ext/tk/sample/demos-jp/aniwave.rb
+++ b/ext/tk/sample/demos-jp/aniwave.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# animated wave demo (called by 'widget')
#
@@ -16,8 +17,10 @@ $aniwave_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($aniwave_demo).pack(:fill=>:both, :expand=>true)
+
# create label
-msg = TkLabel.new($aniwave_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -26,7 +29,7 @@ msg = TkLabel.new($aniwave_demo) {
msg.pack('side'=>'top')
# create frame
-TkFrame.new($aniwave_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
#text 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -59,6 +62,7 @@ class AnimatedWaveDemo
@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
@@ -113,4 +117,4 @@ class AnimatedWaveDemo
end
# Start the animation processing
-AnimatedWaveDemo.new($aniwave_demo, :left).move
+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 477a0abf6f..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')
#
@@ -73,11 +74,19 @@ def arrowSetup(c)
'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,14 +104,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',
+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 'ÊĤ¸¤ë'
@@ -121,7 +132,7 @@ $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,
+$arrow_canvas = TkCanvas.new(base_frame, 'width'=>500, 'height'=>350,
'relief'=>'sunken', 'borderwidth'=>2)
$arrow_canvas.pack('expand'=>'yes', 'fill'=>'both')
diff --git a/ext/tk/sample/demos-jp/bind.rb b/ext/tk/sample/demos-jp/bind.rb
index e1e23b9893..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,8 +16,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -40,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}
@@ -91,35 +94,32 @@ TkText.new($bind_demo){|t|
}
d1.bind('1',
proc{
- eval(`cat #{[$demo_dir,'items.rb'].join(File::Separator)}`,
- _null_binding)
+ 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)}`,
- _null_binding)
+ 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)}`,
- _null_binding)
+ 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)}`,
- _null_binding)
+ 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)}`,
- _null_binding)
+ 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)}`,
- _null_binding)
+ 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 b71c67d3fd..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')
#
@@ -18,7 +19,7 @@ def bitmapRow(w,*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')
+ Tk::Label.new(base, 'bitmap'=>bitmap).pack('side'=>'bottom')
}
end
}
@@ -37,14 +38,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',
+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 'ÊĤ¸¤ë'
@@ -63,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/button.rb b/ext/tk/sample/demos-jp/button.rb
index 20f8cae299..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,7 +27,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 'λ²ò'
text 'ÊĤ¸¤ë'
diff --git a/ext/tk/sample/demos-jp/check.rb b/ext/tk/sample/demos-jp/check.rb
index be675b9042..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,8 +16,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'
@@ -30,7 +33,7 @@ brakes = TkVariable.new(0)
sober = TkVariable.new(0)
# frame À¸À®
-TkFrame.new($check_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
#text 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -51,7 +54,7 @@ TkFrame.new($check_demo) {|frame|
TkButton.new(frame) {
text 'ÊÑ¿ô»²¾È'
command proc{
- showVars($check_demo,
+ showVars(base_frame,
['wipers', wipers], ['brakes', brakes], ['sober', sober])
}
}.pack('side'=>'left', 'expand'=>'yes')
@@ -60,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
index f681a4d684..7f7cb9e932 100644
--- a/ext/tk/sample/demos-jp/check2.rb
+++ b/ext/tk/sample/demos-jp/check2.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# checkbutton widget demo2 (called by 'widget')
#
@@ -15,8 +16,10 @@ $check2_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($check2_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-msg = TkLabel.new($check2_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -31,7 +34,7 @@ brakes = TkVariable.new(0)
sober = TkVariable.new(0)
# frame À¸À®
-TkFrame.new($check2_demo) {|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',
@@ -59,15 +62,15 @@ TkFrame.new($check2_demo) {|frame|
# checkbutton À¸À®
-TkCheckButton.new($check2_demo, :text=>'°ÂÁ´À­¸¡ºº', :variable=>safety,
+TkCheckButton.new(base_frame, :text=>'°ÂÁ´À­¸¡ºº', :variable=>safety,
:relief=>:flat, :onvalue=>'all', :offvalue=>'none',
:tristatevalue=>'partial'){
pack('side'=>'top', 'pady'=>2, 'anchor'=>'w')
}
-[ TkCheckButton.new($check2_demo, 'text'=>'¥ï¥¤¥Ñ¡¼ OK', 'variable'=>wipers),
- TkCheckButton.new($check2_demo, 'text'=>'¥Ö¥ì¡¼¥­ OK', 'variable'=>brakes),
- TkCheckButton.new($check2_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', 'padx'=>15, 'pady'=>2, 'anchor'=>'w')
diff --git a/ext/tk/sample/demos-jp/clrpick.rb b/ext/tk/sample/demos-jp/clrpick.rb
index de8cd80fcd..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,12 +19,15 @@ $clrpick_demo = TkToplevel.new {|w|
}
# label À¸À®
-TkLabel.new($clrpick_demo,'font'=>$font,'wraplength'=>'4i','justify'=>'left',
+#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) {
+# TkFrame.new($clrpick_demo) {|frame|
+Tk::Frame.new($clrpick_demo) {|frame|
+ # TkButton.new(frame) {
+ Tk::Button.new(frame) {
#text 'λ²ò'
text 'ÊĤ¸¤ë'
command proc{
@@ -31,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']})
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')
}
diff --git a/ext/tk/sample/demos-jp/colors.rb b/ext/tk/sample/demos-jp/colors.rb
index c6128f9c00..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,7 +28,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -45,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
@@ -58,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 0d6db69af6..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,14 +16,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',
+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 'ÊĤ¸¤ë'
@@ -42,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)
@@ -50,7 +53,7 @@ unless $tk_version =~ /^4\.[01]/
end
# canvas ÀßÄê
-$cscroll_canvas = TkCanvas.new($cscroll_demo,
+$cscroll_canvas = TkCanvas.new(base_frame,
'relief'=>'sunken', 'borderwidth'=>2,
'scrollregion'=>['-11c', '-11c', '50c', '20c']
) {|c|
@@ -61,7 +64,7 @@ $cscroll_canvas = TkCanvas.new($cscroll_demo,
'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')
@@ -71,7 +74,7 @@ $cscroll_canvas = TkCanvas.new($cscroll_demo,
end
}
- TkScrollbar.new($cscroll_demo, 'orient'=>'horiz',
+ 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]/
diff --git a/ext/tk/sample/demos-jp/ctext.rb b/ext/tk/sample/demos-jp/ctext.rb
index 66e1fe8107..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,8 +16,10 @@ $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',
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'5i', 'justify'=>'left',
'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¥­¥ã¥ó¥Ð¥¹widget¤Î¥Æ¥­¥¹¥Èµ¡Ç½¤ò¥Ç¥â¤¹¤ë¤¿¤á¤Î¥Æ¥­¥¹¥Èʸ»úÎó¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¥Þ¥¦¥¹¤ò»Í³Ñ¤ÎÃæ¤Ë»ý¤Ã¤Æ¤¤¤­¡¢¥¯¥ê¥Ã¥¯¤¹¤ë¤È°ÌÃÖ¤®¤áÍѤÎÅÀ¤«¤é¤ÎÁêÂаÌÃÖ¤òÊѤ¨¤¿¤ê¡¢¹Ô·¤¨¤òÊѤ¨¤¿¤ê¤¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤Þ¤¿°Ê²¼¤Î¤è¤¦¤ÊÊÔ½¸¤Î¤¿¤á¤Î´Êñ¤Ê¥Ð¥¤¥ó¥Ç¥£¥ó¥°¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Þ¤¹¡£
1. ¥Þ¥¦¥¹¤ò»ý¤Ã¤Æ¤¤¤­¡¢¥¯¥ê¥Ã¥¯¤·¡¢ÆþÎϤǤ­¤Þ¤¹¡£
@@ -28,7 +31,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -47,24 +50,33 @@ $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',
+$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')
+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¤Î¥Æ¥­¥¹¥Èµ¡Ç½¤ò¥Ç¥â¤¹¤ë¤¿¤á¤Îʸ»úÎó¤Ç¤¹¡£\n¾å¤Ç½Ò¤Ù¤¿¤è¤¦¤ÊÊÔ½¸¤ò²Äǽ¤È¤¹¤ë¤¿¤á¤Î¥Ð¥¤¥ó¥Ç¥£¥ó¥°¤ò»Ü¤·¤Æ¤¤¤Þ¤¹¡£",
- '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")
@@ -106,9 +118,14 @@ 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')
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.
@@ -119,9 +136,14 @@ 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',
diff --git a/ext/tk/sample/demos-jp/dialog1.rb b/ext/tk/sample/demos-jp/dialog1.rb
index 0d6181bfc6..07e50306ab 100644
--- a/ext/tk/sample/demos-jp/dialog1.rb
+++ b/ext/tk/sample/demos-jp/dialog1.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# a dialog box with a local grab (called by 'widget')
#
diff --git a/ext/tk/sample/demos-jp/dialog2.rb b/ext/tk/sample/demos-jp/dialog2.rb
index a934378dda..f747f8d6a8 100644
--- a/ext/tk/sample/demos-jp/dialog2.rb
+++ b/ext/tk/sample/demos-jp/dialog2.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# a dialog box with a global grab (called by 'widget')
#
diff --git a/ext/tk/sample/demos-jp/entry1.rb b/ext/tk/sample/demos-jp/entry1.rb
index edf3b5f71d..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,7 +28,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -43,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 7d5740e663..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,7 +28,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -43,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 f57dc13553..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,7 +18,9 @@ $entry3_demo = TkToplevel.new {|w|
positionWindow(w)
}
-TkLabel.new($entry3_demo,
+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,7 +41,7 @@ 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{
@@ -64,23 +67,41 @@ TkFrame.new($entry3_demo){|f|
# count - Counter to control the number of times flashed
def focusAndFlash(widget, fg, bg, count=5)
return if count <= 0
- TkTimer.new(100, 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']
+ 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')
@@ -161,15 +182,15 @@ def validatePhoneChange(widget, vmode, idx, char)
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).
+ # 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=>[
@@ -188,14 +209,14 @@ TkEntry.new(l3, :validate=>:key, :invcmd=>proc{Tk.bell},
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')
-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 f3608ab70f..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,12 +16,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',
+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 'ÊĤ¸¤ë'
@@ -39,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')
@@ -47,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')
}
@@ -57,7 +60,7 @@ TkFrame.new($filebox_demo) {|frame|
$tk_strictMotif = TkVarAccess.new('tk_strictMotif')
if ($tk_platform['platform'] == 'unix')
- TkCheckButton.new($filebox_demo,
+ TkCheckButton.new(base_frame,
'text'=>'Motif¥¹¥¿¥¤¥ë¤Î¥À¥¤¥¢¥í¥°¤òÍѤ¤¤ë',
'variable'=>$tk_strictMotif,
'onvalue'=>1, 'offvalue'=>0 ).pack('anchor'=>'c')
@@ -90,7 +93,10 @@ def fileDialog(w,ent,operation)
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 b029580bd6..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')
#
@@ -1586,14 +1587,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',
+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 'ÊĤ¸¤ë'
@@ -1617,17 +1620,17 @@ $floorItems = {}
# canvas ÀßÄê
if $tk_version =~ /^4\.[01]/
- $floor_canvas_frame = TkFrame.new($floor_demo,'bd'=>2,'relief'=>'sunken',
+ $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',
+ 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')
}
@@ -1636,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')
diff --git a/ext/tk/sample/demos-jp/floor2.rb b/ext/tk/sample/demos-jp/floor2.rb
index a20b31d45c..d4381c5543 100644
--- a/ext/tk/sample/demos-jp/floor2.rb
+++ b/ext/tk/sample/demos-jp/floor2.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# floorDisplay widget demo 2 (called by 'widget')
#
@@ -1586,14 +1587,16 @@ $floor2_demo = TkToplevel.new {|w|
minsize(100,100)
}
+base_frame = TkFrame.new($floor2_demo).pack(:fill=>:both, :expand=>true)
+
# label À¸À®
-TkLabel.new($floor2_demo, 'font'=>$font, 'wraplength'=>'8i', 'justify'=>'left',
+TkLabel.new(base_frame, 'font'=>$font, 'wraplength'=>'8i', 'justify'=>'left',
'text'=>"¤³¤Î¥¦¥£¥ó¥É¥¦¤Ë¤Ï¥Ç¥£¥¸¥¿¥ë¥¨¥¯¥¤¥Ã¥×¥á¥ó¥È¼Ò¤Î¥¦¥§¥¹¥¿¥ó¥ê¥µ¡¼¥Á¥é¥Ü¥é¥È¥ê (DECWRL) ¤Î´Ö¼è¤ê¤¬½ñ¤«¤ì¤¿¥­¥ã¥ó¥Ð¥¹ widget ¤¬Æþ¤Ã¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤Ï 3³¬·ú¤Æ¤Ç¡¢¾ï¤Ë¤½¤Î¤¦¤Á¤Î1³¬Ê¬¤¬ÁªÂò¡¢¤Ä¤Þ¤ê¤½¤Î´Ö¼è¤ê¤¬É½¼¨¤µ¤ì¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£¤¢¤ë³¬¤òÁªÂò¤¹¤ë¤Ë¤Ï¡¢¤½¤Î¾å¤Ç¥Þ¥¦¥¹¤Îº¸¥Ü¥¿¥ó¤ò¥¯¥ê¥Ã¥¯¤·¤Æ¤¯¤À¤µ¤¤¡£¥Þ¥¦¥¹¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤ë³¬¤Î¾å¤òư¤¯¤È¡¢¤½¤Î²¼¤Ë¤¢¤ëÉô²°¤Î¿§¤¬ÊѤï¤ê¡¢Éô²°Èֹ椬¡ÖÉô²°ÈÖ¹æ:¡×¥¨¥ó¥È¥ê¤Ëɽ¼¨¤µ¤ì¤Þ¤¹¡£¤Þ¤¿¡¢¥¨¥ó¥È¥ê¤ËÉô²°ÈÖ¹æ¤ò½ñ¤¯¤È¤½¤ÎÉô²°¤Î¿§¤¬ÊѤï¤ê¤Þ¤¹¡£"){
pack('side'=>'top')
}
# frame À¸À®
-$floor2_buttons = TkFrame.new($floor2_demo) {|frame|
+$floor2_buttons = TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
#text 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -1617,17 +1620,17 @@ $floorItems2 = {}
# canvas ÀßÄê
if $tk_version =~ /^4\.[01]/
- $floor2_canvas_frame = TkFrame.new($floor2_demo,'bd'=>2,'relief'=>'sunken',
+ $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($floor2_demo, 'orient'=>'horiz',
+ 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($floor2_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')
}
@@ -1636,7 +1639,7 @@ if $tk_version =~ /^4\.[01]/
$floor2_canvas.pack('expand'=>'yes', 'fill'=>'both')
else
- TkFrame.new($floor2_demo) {|f|
+ TkFrame.new(base_frame) {|f|
pack('side'=>'top', 'fill'=>'both', 'expand'=>'yes')
h = TkScrollbar.new(f, 'highlightthickness'=>0, 'orient'=>'horizontal')
diff --git a/ext/tk/sample/demos-jp/form.rb b/ext/tk/sample/demos-jp/form.rb
index fe456d3943..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,7 +28,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -45,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
index 592b69f775..a81c7ec70c 100644
--- a/ext/tk/sample/demos-jp/goldberg.rb
+++ b/ext/tk/sample/demos-jp/goldberg.rb
@@ -1,3 +1,4 @@
+# -*- coding: euc-jp -*-
#
# Ruby/Tk Goldverg demo (called by 'widget')
#
@@ -54,6 +55,8 @@ $goldberg_demo = TkToplevel.new {|w|
# positionWindow(w)
}
+base_frame = TkFrame.new($goldberg_demo).pack(:fill=>:both, :expand=>true)
+
=begin
# label
msg = TkLabel.new($goldberg_demo) {
@@ -176,7 +179,8 @@ class TkGoldberg_Demo
do_ctrl_frame
do_detail_frame
- msg = TkLabel.new(@parent, :bg=>@C['bg'], :fg=>'white') {
+ # 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'
@@ -186,7 +190,8 @@ class TkGoldberg_Demo
frame = TkFrame.new(@parent, :bg=>@C['bg'])
- TkButton.new(frame, :bg=>@C['bg'], :activebackground=>@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
@@ -195,12 +200,14 @@ class TkGoldberg_Demo
}
}.pack('side'=>'left')
- TkButton.new(frame, :bg=>@C['bg'], :activebackground=>@C['bg']) {
+ # 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 = 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)
@@ -209,10 +216,11 @@ class TkGoldberg_Demo
end
def do_ctrl_frame
- @start = TkButton.new(@parent, :text=>'Start', :bd=>6,
+ @start = Tk::Button.new(@parent, :text=>'Start', :bd=>6,
:command=>proc{do_button(0)})
- @start.font(@start['font'].weight('bold'))
- font = @start['font']
+ 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,
@@ -2000,4 +2008,4 @@ class TkGoldberg_Demo
end
end
-TkGoldberg_Demo.new($goldberg_demo)
+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 37d215435c..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,7 +24,7 @@ msg = TkLabel.new($hscale_demo) {
}
msg.pack('side'=>'top')
-TkFrame.new($hscale_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
#text 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -39,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
@@ -64,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 e4fef5cae7..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,7 +28,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -60,16 +63,18 @@ TkBitmapImage.new('file'=>[$demo_dir,'..',
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){
+ # 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){
+ # TkRadioButton.new(f){
+ Tk::RadioButton.new(f){
bitmap '@' + [$demo_dir,'..',
'images','noletter.xbm'].join(File::Separator)
variable letters
@@ -78,14 +83,16 @@ TkFrame.new($icon_demo, 'borderwidth'=>10){|w|
}.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) {
+ # TkCheckButton.new(w) {
+ Tk::CheckButton.new(w) {
bitmap '@' + [$demo_dir,'..',
'images','letters.xbm'].join(File::Separator)
indicatoron 0
diff --git a/ext/tk/sample/demos-jp/image1.rb b/ext/tk/sample/demos-jp/image1.rb
index 3d47f844e5..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,7 +28,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -52,7 +55,10 @@ 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 e2e2a2b036..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,7 +28,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -50,21 +53,21 @@ $dirName = TkVariable.new([$demo_dir,'..','images'].join(File::Separator))
$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
@@ -83,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 d9f378c116..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,6 +20,8 @@ $image3_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($image3_demo).pack(:fill=>:both, :expand=>true)
+
#
def loadDir3(w)
w.delete(0,'end')
@@ -49,7 +52,7 @@ end
# label
-msg = TkLabel.new($image3_demo) {
+msg = TkLabel.new(base_frame) {
font $font
wraplength '4i'
justify 'left'
@@ -58,7 +61,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -87,11 +90,11 @@ 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=>'¥Õ¥¡¥¤¥ë:',
+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)
@@ -111,8 +114,9 @@ TkButton.new(image3_df, :pady=>0, :padx=>'2m', :text=>"¥Ç¥£¥ì¥¯¥È¥êÁªÂò",
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, '-',
diff --git a/ext/tk/sample/demos-jp/items.rb b/ext/tk/sample/demos-jp/items.rb
index 38774d10d2..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,7 +27,7 @@ TkLabel.new($items_demo) {
}.pack('side'=>'top')
# frame À¸À®
-TkFrame.new($items_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
#text 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -43,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
@@ -91,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'
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 59626289fc..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,7 +28,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -44,8 +47,8 @@ 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')}
@@ -56,7 +59,8 @@ f_right = TkFrame.new($label_demo)
TkLabel.new(f_left, 'text'=>'3 ÈÖÌÜ¡£ÄÀ¤ó¤Ç¤¤¤Þ¤¹ ', 'relief'=>'sunken')
].each{|w| w.pack('side'=>'top', 'expand'=>'yes', 'pady'=>2, 'anchor'=>'w')}
-TkLabel.new(f_right) {
+# TkLabel.new(f_right) {
+Tk::Label.new(f_right) {
bitmap('@' + [$demo_dir,'..','images','face.xbm'].join(File::Separator))
borderwidth 2
relief 'sunken'
diff --git a/ext/tk/sample/demos-jp/labelframe.rb b/ext/tk/sample/demos-jp/labelframe.rb
index 23c974dcc2..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,8 +19,10 @@ $labelframe_demo = TkToplevel.new {|w|
positionWindow(w)
}
+base_frame = TkFrame.new($labelframe_demo).pack(:fill=>:both, :expand=>true)
+
# Some information
-TkLabel.new($labelframe_demo,
+TkLabel.new(base_frame,
:font=>$font, :wraplength=>'4i', :justify=>:left,
:text=><<EOL).pack(:side=>:top)
TkLabelFrame ¥¦¥£¥¸¥§¥Ã¥È¤Ï´ØÏ¢¤¹¤ë widget
@@ -34,7 +38,7 @@ 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{
@@ -48,7 +52,7 @@ TkFrame.new($labelframe_demo){|f|
}
# Demo area
-w = TkFrame.new($labelframe_demo).pack(:side=>:bottom, :fill=>:both,
+w = TkFrame.new(base_frame).pack(:side=>:bottom, :fill=>:both,
:expand=>true)
# A group of radiobuttons in a labelframe
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 add85f7f7b..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,8 +16,10 @@ $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
@@ -26,7 +29,7 @@ rescue
end
# label À¸À®
-TkLabel.new($menu_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¤¬¥³¥Þ¥ó¥É¥­¡¼µ­¹æ¤Ë³¤¤¤ÆÉ½¼¨¤µ¤ì¤Æ¤¤¤ëʸ»ú¤Ê¤é¤Ð¡¢¥¢¥¯¥»¥é¥ì¡¼¥¿¤ò»È¤Ã¤¿¹àÌܵ¯Æ°¤ò¹Ô¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¥á¥Ë¥å¡¼Í×ÁÇÃæ¡¢ºÇ¸å¤Î¤â¤Î¤Ï¡¢¤½¤Î¥á¥Ë¥å¡¼¤ÎºÇ½é¤Î¹àÌܤòÁªÂò¤¹¤ë¤³¤È¤ÇÆÈΩ¤µ¤»¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£")
@@ -36,7 +39,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 'λ²ò'
text 'ÊĤ¸¤ë'
@@ -107,7 +110,8 @@ TkMenubutton.new($menu_frame, 'text'=>'Cascades', 'underline'=>0) {|m|
'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)
oil = TkVariable.new(0)
@@ -129,7 +133,8 @@ TkMenubutton.new($menu_frame, 'text'=>'Cascades', 'underline'=>0) {|m|
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)
pointSize = TkVariable.new
diff --git a/ext/tk/sample/demos-jp/menu84.rb b/ext/tk/sample/demos-jp/menu84.rb
index 8c2a815d78..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,7 +36,7 @@ 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,
@@ -43,7 +46,7 @@ TkFrame.new($menu84_demo) {|frame|
# frame
-TkFrame.new($menu84_demo) {|frame|
+TkFrame.new(base_frame) {|frame|
TkButton.new(frame) {
#text 'λ²ò'
text 'ÊĤ¸¤ë'
diff --git a/ext/tk/sample/demos-jp/menu8x.rb b/ext/tk/sample/demos-jp/menu8x.rb
index 050f0decb4..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,16 +16,18 @@ $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 'ÊĤ¸¤ë'
@@ -50,7 +53,7 @@ rescue
end
# label À¸À®
-TkLabel.new($menu8x_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¤¬¥³¥Þ¥ó¥É¥­¡¼µ­¹æ¤Ë³¤¤¤ÆÉ½¼¨¤µ¤ì¤Æ¤¤¤ëʸ»ú¤Ê¤é¤Ð¡¢¥¢¥¯¥»¥é¥ì¡¼¥¿¤ò»È¤Ã¤¿¹àÌܵ¯Æ°¤ò¹Ô¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¥á¥Ë¥å¡¼Í×ÁÇÃæ¡¢ºÇ¸å¤Î¤â¤Î¤Ï¡¢¤½¤Î¥á¥Ë¥å¡¼¤ÎºÇ½é¤Î¹àÌܤòÁªÂò¤¹¤ë¤³¤È¤ÇÆÈΩ¤µ¤»¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£")
@@ -61,14 +64,14 @@ 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')\
.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 'ÊĤ¸¤ë'
diff --git a/ext/tk/sample/demos-jp/menubu.rb b/ext/tk/sample/demos-jp/menubu.rb
index aa90a3087f..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,16 +33,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("¼Â¹Ô¤·¤è¤¦¤È¤·¤¿¥¹¥¯¥ê¥×¥È¤Ï 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 'ÊĤ¸¤ë'
@@ -60,7 +63,7 @@ TkFrame.new($menubu_demo) {|frame|
else ; # Tk8.x
-body = TkFrame.new($menubu_demo)
+body = TkFrame.new(base_frame)
body.pack('expand'=>'yes', 'fill'=>'both')
below = TkMenubutton.new(body) {
@@ -155,7 +158,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 'λ²ò'
text 'ÊĤ¸¤ë'
diff --git a/ext/tk/sample/demos-jp/msgbox.rb b/ext/tk/sample/demos-jp/msgbox.rb
index 983e6b6589..88380e08bd 100644
--- a/ext/tk/sample/demos-jp/msgbox.rb
+++ b/