From 7ea2ceddb832b9973694fecac9fe3c30400735ba Mon Sep 17 00:00:00 2001 From: matz Date: Fri, 16 Jan 1998 12:19:22 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r11, which included commits to RCS files with non-trunk default branches. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/cgi-lib.rb | 77 ++++++-- lib/finalize.rb | 36 ++-- lib/mailread.rb | 43 +++-- lib/sync.rb | 90 +++++++-- lib/tk.rb | 573 ++++++++++++++++++++++++++++++++++++++++++++++++-------- lib/tktext.rb | 4 +- 6 files changed, 672 insertions(+), 151 deletions(-) (limited to 'lib') diff --git a/lib/cgi-lib.rb b/lib/cgi-lib.rb index afadbff3b6..5234e046cc 100644 --- a/lib/cgi-lib.rb +++ b/lib/cgi-lib.rb @@ -9,29 +9,59 @@ # foo.keys <== array of fields # foo.inputs <== hash of { => } +# if running on Windows(IIS or PWS) then change cwd. +if ENV['SERVER_SOFTWARE'] =~ /^Microsoft-/ then + Dir.chdir ENV['PATH_TRANSLATED'].sub(/[^\\]+$/, '') +end + +require "shellwords.rb" + class CGI + include Shellwords + attr("inputs") + + # original is CGI.pm + def read_from_cmdline + words = shellwords(if not ARGV.empty? then + ARGV.join(' ') + else + print "(offline mode: enter name=value pairs on standard input)\n" + readlines.join(' ').gsub(/\n/, '') + end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26')) + + if words.find{|x| x =~ /=/} then words.join('&') else words.join('+') end + end + # escape url encode + def escape(str) + str.gsub!(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) } + str + end + + # unescape url encoded + def unescape(str) + str.gsub! /\+/, ' ' + str.gsub!(/%([0-9a-fA-F]{2})/){ [$1.hex].pack("c") } + str + end + module_function :escape, :unescape + def initialize - str = if ENV['REQUEST_METHOD'] == "GET" - ENV['QUERY_STRING'] - elsif ENV['REQUEST_METHOD'] == "POST" - $stdin.read ENV['CONTENT_LENGTH'].to_i - else - "" - end - arr = str.split(/&/) + # exception messages should be printed to stdout. + STDERR.reopen(STDOUT) + @inputs = {} - arr.each do |x| - x.gsub!(/\+/, ' ') - key, val = x.split(/=/, 2) - val = "" unless val - - key.gsub!(/%(..)/) { [$1.hex].pack("c") } - val.gsub!(/%(..)/) { [$1.hex].pack("c") } - - @inputs[key] += "\0" if @inputs[key] - @inputs[key] += val + case ENV['REQUEST_METHOD'] + when "GET" + ENV['QUERY_STRING'] or "" + when "POST" + $stdin.read ENV['CONTENT_LENGTH'].to_i + else + read_from_cmdline + end.split(/&/).each do |x| + key, val = x.split(/=/,2).collect{|x|unescape(x)} + @inputs[key] += ("\0" if @inputs[key]) + (val or "") end end @@ -53,4 +83,15 @@ class CGI TRUE end + def CGI.error + m = $!.dup + m.gsub!(/&/, '&') + m.gsub!(//, '>') + msgs = ["
ERROR: #{m}"]
+    msgs << $@
+    msgs << "
" + CGI.message(msgs.join("\n"), "ERROR") + exit + end end diff --git a/lib/finalize.rb b/lib/finalize.rb index e934753e19..9b2ffefcf5 100644 --- a/lib/finalize.rb +++ b/lib/finalize.rb @@ -1,9 +1,9 @@ # -# finalize.rb - -# $Release Version: $ -# $Revision: 1.2 $ -# $Date: 1997/07/25 02:43:00 $ -# by Keiju ISHITSUKA(SHL Japan Inc.) +# finalizer.rb - +# $Release Version: 0.2$ +# $Revision: 1.3 $ +# $Date: 1998/01/09 08:09:49 $ +# by Keiju ISHITSUKA # # -- # @@ -44,14 +44,14 @@ # module Finalizer - RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/finalize.rb,v 1.2 1997/07/25 02:43:00 keiju Exp keiju $-' + RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/finalize.rb,v 1.3 1998/01/09 08:09:49 keiju Exp keiju $-' # @dependency: {id => [[dependant, method, *opt], ...], ...} # 依存関係 R_method(obj, dependant) の追加 def add_dependency(obj, dependant, method = :finalize, *opt) ObjectSpace.call_finalizer(obj) - method = method.id unless method.kind_of?(Fixnum) + method = method.intern unless method.kind_of?(Integer) assoc = [dependant, method].concat(opt) if dep = @dependency[obj.id] dep.push assoc @@ -63,8 +63,8 @@ module Finalizer # 依存関係 R_method(obj, dependant) の削除 def delete_dependency(id, dependant, method = :finalize) - id = id.id unless id.kind_of?(Fixnum) - method = method.id unless method.kind_of?(Fixnum) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) for assoc in @dependency[id] assoc.delete_if do |d, m, *o| @@ -77,8 +77,8 @@ module Finalizer # 依存関係 R_*(obj, dependant) の削除 def delete_all_dependency(id, dependant) - id = id.id unless id.kind_of?(Fixnum) - method = method.id unless method.kind_of?(Fixnum) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) for assoc in @dependency[id] assoc.delete_if do |d, m, *o| @@ -90,8 +90,8 @@ module Finalizer # 依存関係 R_method(*, dependant) の削除 def delete_by_dependant(dependant, method = :finalize) - method = method.id unless method.kind_of?(Fixnum) - for id in @dependency.keys + method = method.intern unless method.kind_of?(Integer) + for id in Dependency.keys delete(id, dependant, method) end end @@ -106,8 +106,8 @@ module Finalizer # 依存関連 R_method(obj, dependtant) で結ばれるdependantをfinalizeす # る. def finalize_dependency(id, dependant, method = :finalize) - id = id.id unless id.kind_of?(Fixnum) - method = method.id unless method.kind_of?(Fixnum) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) for assocs in @dependency[id] assocs.delete_if do |d, m, *o| @@ -121,8 +121,8 @@ module Finalizer # 依存関連 R_*(obj, dependtant) で結ばれるdependantをfinalizeする. def finalize_all_dependency(id, dependant) - id = id.id unless id.kind_of?(Fixnum) - method = method.id unless method.kind_of?(Fixnum) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) for assoc in @dependency[id] assoc.delete_if do |d, m, *o| @@ -134,7 +134,7 @@ module Finalizer # 依存関連 R_method(*, dependtant) で結ばれるdependantをfinalizeする. def finalize_by_dependant(dependant, method = :finalize) - method = method.id unless method.kind_of?(Fixnum) + method = method.intern unless method.kind_of?(Integer) for id in @dependency.keys finalize(id, dependant, method) end diff --git a/lib/mailread.rb b/lib/mailread.rb index d9feffbb7a..a5d60c84b4 100644 --- a/lib/mailread.rb +++ b/lib/mailread.rb @@ -1,36 +1,35 @@ class Mail - def Mail.new(f) + + def initialize(f) unless f.kind_of?(IO) f = open(f, "r") - me = super(f) - f.close - else - me = super + opened = true end - return me - end - def initialize(f) @header = {} @body = [] - while f.gets() - $_.chop! - next if /^From / # skip From-line - break if /^$/ # end of header + begin + while f.gets() + $_.chop! + next if /^From / # skip From-line + break if /^$/ # end of header - if /^(\S+):\s*(.*)/ - @header[attr = $1.capitalize!] = $2 - elsif attr - sub!(/^\s*/, '') - @header[attr] += "\n" + $_ + if /^(\S+):\s*(.*)/ + @header[attr = $1.capitalize!] = $2 + elsif attr + sub!(/^\s*/, '') + @header[attr] += "\n" + $_ + end end - end - return unless $_ + return unless $_ - while f.gets() - break if /^From / - @body.push($_) + while f.gets() + break if /^From / + @body.push($_) + end + ensure + f.close if opened end end diff --git a/lib/sync.rb b/lib/sync.rb index 3e57ed0e57..b5a3fc32b3 100644 --- a/lib/sync.rb +++ b/lib/sync.rb @@ -1,13 +1,19 @@ # # sync.rb - カウント付2-フェーズロッククラス -# $Release Version: 0.1$ +# $Release Version: 0.2$ # $Revision$ # $Date$ # by Keiju ISHITSUKA # # -- +# Sync_m, Synchronizer_m # Usage: -# Sync_m, Synchronizer_m +# obj.extend(Sync_m) +# or +# class Foo +# Sync_m.include_to self +# : +# end # # Sync_m#sync_mode # Sync_m#sync_locked?, locked? @@ -19,8 +25,9 @@ # # Sync, Synchronicer: # include Sync_m -# +# Usage: # sync = Sync.new +# # Sync#mode # Sync#locked? # Sync#shared? @@ -36,15 +43,17 @@ unless defined? Thread fail "Thread not available for this ruby interpreter" end -require "finalize.rb" +require "finalize" module Sync_m RCS_ID='-$Header$-' + # lock mode UN = :UN SH = :SH EX = :EX + # 例外定義 class Err < Exception def Err.Fail(*opt) fail self, sprintf(self::Message, *opt) @@ -68,21 +77,53 @@ module Sync_m end end - def Sync_m.extend_object(obj) + # include and extend initialize methods. + def Sync_m.extendable_module(obj) if Fixnum === obj or TRUE === obj or FALSE === obj or nil == obj raise TypeError, "Sync_m can't extend to this class(#{obj.type})" else begin - eval "class << obj - @sync_locked - end" - obj.extend(For_primitive_object) + obj.instance_eval "@sync_locked" + For_general_object rescue TypeError - obj.extend(For_general_object) + For_primitive_object end end end + def Sync_m.includable_module(cl) + begin + dummy = cl.new + Sync_m.extendable_module(dummy) + rescue NameError + # newが定義されていない時は, DATAとみなす. + For_primitive_object + end + end + + def Sync_m.extend_class(cl) + return super if cl.instance_of?(Module) + + # モジュールの時は何もしない. クラスの場合, 適切なモジュールの決定 + # とaliasを行う. + real = includable_module(cl) + cl.module_eval %q{ + include real + + alias locked? sync_locked? + alias shared? sync_shared? + alias exclusive? sync_exclusive? + alias lock sync_lock + alias unlock sync_unlock + alias try_lock sync_try_lock + alias synchronize sync_synchronize + } + end + + def Sync_m.extend_object(obj) + obj.extend(Sync_m.extendable_module(obj)) + end + def sync_extended unless (defined? locked? and defined? shared? and @@ -94,7 +135,7 @@ module Sync_m eval "class << self alias locked? sync_locked? alias shared? sync_shared? - alias excluive? sync_exclusive? + alias exclusive? sync_exclusive? alias lock sync_lock alias unlock sync_unlock alias try_lock sync_try_lock @@ -103,6 +144,7 @@ module Sync_m end end + # accessing def sync_locked? sync_mode != UN end @@ -115,6 +157,7 @@ module Sync_m sync_mode == EX end + # locking methods. def sync_try_lock(mode = EX) return unlock if sync_mode == UN @@ -238,7 +281,6 @@ module Sync_m self.sync_ex_locker = Thread.current self.sync_ex_count = 1 ret = TRUE - elsif sync_mode == EX && sync_ex_locker == Thread.current self.sync_ex_count = sync_ex_count + 1 ret = TRUE @@ -262,6 +304,7 @@ module Sync_m end end + # internal class module For_primitive_object include Sync_m @@ -281,12 +324,18 @@ module Sync_m Finalizer.add(obj, For_primitive_object, :sync_finalize) end - def sync_extended + def initialize super Sync_Locked[id] = LockState.new(UN, [], [], Hash.new, nil, 0 ) + self + end + + def sync_extended + super + initialize end - def sync_finalize + def For_primitive_object.sync_finalize(id) wait = Sync_Locked.delete(id) # waiting == [] ときだけ GCされるので, 待ち行列の解放は意味がない. end @@ -343,7 +392,7 @@ module Sync_m obj.sync_extended end - def sync_extended + def initialize super @sync_mode = UN @sync_waiting = [] @@ -351,6 +400,12 @@ module Sync_m @sync_sh_locker = Hash.new @sync_ex_locker = nil @sync_ex_count = 0 + self + end + + def sync_extended + super + initialize end attr :sync_mode, TRUE @@ -366,10 +421,11 @@ end Synchronizer_m = Sync_m class Sync - include Sync_m::For_general_object + Sync_m.extend_class self + #include Sync_m def initialize - sync_extended + super end end diff --git a/lib/tk.rb b/lib/tk.rb index df68874b13..2cbbec02a8 100644 --- a/lib/tk.rb +++ b/lib/tk.rb @@ -1,12 +1,483 @@ # -# tk.rb - Tk interface for ruby +# tk.rb - Tk interface modue using tcltklib # $Date$ -# by Yukihiro Matsumoto +# by Yukihiro Matsumoto -if defined? Thread and $tk_thread_safe - require "tkthcore" -else - require "tkcore" +# use Shigehiro's tcltklib +require "tcltklib" +require "tkutil" + +module TkComm + None = Object.new + def None.to_s + 'None' + end + + Tk_CMDTBL = {} + Tk_WINDOWS = {} + + def error_at + frames = caller(1) + frames.delete_if do |c| + c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+! + end + frames + end + private :error_at + + def tk_tcl2ruby(val) + case val + when /^-?\d+$/ + val.to_i + when /^\./ + Tk_WINDOWS[val] + when /^rb_out (c\d+)/ + Tk_CMDTBL[$1] + when / / + val.split.collect{|elt| + tk_tcl2ruby(elt) + } + when /^-?\d+\.\d*$/ + val.to_f + else + val + end + end + + def tk_split_list(str) + idx = str.index('{') + return tk_tcl2ruby(str) if not idx + + list = tk_tcl2ruby(str[0,idx]) + str = str[idx+1..-1] + i = -1 + brace = 1 + str.each_byte {|c| + i += 1 + brace += 1 if c == ?{ + brace -= 1 if c == ?} + break if brace == 0 + } + 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 + private :tk_tcl2ruby, :tk_split_list + + def hash_kv(keys) + conf = [] + if keys and keys != None + for k, v in keys + conf.push("-#{k}") + v = install_cmd(v) if v.kind_of? Proc + conf.push(v) + end + end + conf + end + private :hash_kv + + def bool(val) + case val + when "1", 1, 'yes', 'true' + TRUE + else + FALSE + end + end + def number(val) + case val + when /^-?\d+$/ + val.to_i + when /^-?\d+\.\d*$/ + val.to_f + else + val + end + end + def string(val) + if val == "{}" + '' + elsif val[0] == ?{ + val[1..-2] + else + val + end + end + def list(val) + tk_split_list(val) + end + def window(val) + Tk_WINDOWS[val] + end + def procedure(val) + if val =~ /^rb_out (c\d+)/ + Tk_CMDTBL[$1] + else + nil + end + end + private :bool, :number, :string, :list, :window, :procedure + + Tk_IDs = [0] # [0]-cmdid, [1]-winid + def _curr_cmd_id + id = format("c%.4d", Tk_IDs[0]) + end + def _next_cmd_id + id = _curr_cmd_id + Tk_IDs[0] += 1 + end + def install_cmd(cmd) + return '' if cmd == '' + id = _next_cmd_id + Tk_CMDTBL[id] = cmd + @cmdtbl = [] if not @cmdtbl + @cmdtbl.push id + return format("rb_out %s", id); + end + def uninstall_cmd(id) + Tk_CMDTBL[id] = nil + end + private :install_cmd, :uninstall_cmd + + def install_win(ppath) + id = format("w%.4d", Tk_IDs[0]) + Tk_IDs[0] += 1 + if !ppath or ppath == "." + @path = format(".%s", id); + else + @path = format("%s.%s", ppath, id) + end + Tk_WINDOWS[@path] = self + end + + def uninstall_win() + Tk_WINDOWS[@path] = nil + end + + class Event + def initialize(seq,b,f,h,k,s,t,w,x,y,aa,ee,kk,nn,ww,tt,xx,yy) + @serial = seq + @num = b + @focus = (f == 1) + @height = h + @keycode = k + @state = s + @time = t + @width = w + @x = x + @y = y + @char = aa + @send_event = (ee == 1) + @keysym = kk + @keysym_num = nn + @type = tt + @widget = ww + @x_root = xx + @y_root = yy + end + attr :serial + attr :num + attr :focus + attr :height + attr :keycode + attr :state + attr :time + attr :width + attr :x + attr :y + attr :char + attr :send_event + attr :keysym + attr :keysym_num + attr :type + attr :widget + attr :x_root + attr :y_root + end + + def install_bind(cmd, args=nil) + if args + id = install_cmd(proc{|arg| + TkUtil.eval_cmd cmd, *arg + }) + id + " " + args + else + id = install_cmd(proc{|arg| + TkUtil.eval_cmd cmd, Event.new(*arg) + }) + id + ' %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X %Y' + end + end + + def _bind(path, context, cmd, args=nil) + begin + id = install_bind(cmd, args) + tk_call 'bind', path, "<#{context}>", id + rescue + uninstall_cmd(id) + fail + end + end + private :install_bind, :_bind + + def bind_all(context, cmd=Proc.new, args=nil) + _bind 'all', context, cmd, args + end + + def pack(*args) + TkPack.configure *args + end + + def after(ms, cmd=Proc.new) + myid = _curr_cmd_id + tk_call 'after', ms, + install_cmd(proc{ + TkUtil.eval_cmd cmd + uninstall_cmd myid + }) + end +end + +module TkCore + include TkComm + extend TkComm + + INTERP = TclTkIp.new + INTERP._eval("proc rb_out {args} { ruby [format \"TkCore.callback %%Q!%s!\" $args] }") + + def TkCore.callback(arg) + arg = Array(tk_split_list(arg)) + TkUtil.eval_cmd Tk_CMDTBL[arg.shift], *arg + end + + def mainloop + TclTkLib.mainloop + end + + def _get_eval_string(*args) + argstr = "" + args.each{|arg| + next if arg == None + if arg.kind_of?(Hash) + str = hash_kv(arg).join(" ") + elsif arg == nil + str = "" + elsif arg == false + str = "0" + elsif arg == true + str = "1" + elsif (arg.respond_to?(:to_eval)) + str = arg.to_eval() + else + str = arg.to_s() + end + argstr += " " if argstr != "" + argstr += '"' + str.gsub(/[][$"]/, '\\\\\&') + '"' + } + return argstr + end + + def tk_call(*args) + argstr = _get_eval_string(*args) + + res = INTERP._eval(argstr) + if INTERP._return_value() != 0 + fail RuntimeError, res, error_at + end + return res + end +end + +module Tk + include TkCore + extend Tk + + def root + TkRoot.new + end + + def bell + tk_call 'bell' + end + + def mainloop + TclTkLib.mainloop + end + + module Scrollable + def xscrollcommand(cmd=Proc.new) + configure_cmd 'xscrollcommand', cmd + end + def yscrollcommand(cmd=Proc.new) + configure_cmd 'yscrollcommand', cmd + end + end + + module Wm + def aspect(*args) + w = window(tk_call('wm', 'grid', path, *args)) + w.split.collect{|s|s.to_i} if args.length == 0 + end + def client(name=None) + tk_call 'wm', 'client', path, name + end + def colormapwindows(*args) + list(tk_call('wm', 'colormapwindows', path, *args)) + end + def wm_command(value=None) + string(tk_call('wm', 'command', path, value)) + end + def deiconify + tk_call 'wm', 'deiconify', path + end + def focusmodel(*args) + tk_call 'wm', 'focusmodel', path, *args + end + def frame + tk_call 'wm', 'frame', path + end + def geometry(*args) + list(tk_call('wm', 'geometry', path, *args)) + end + def grid(*args) + w = tk_call('wm', 'grid', path, *args) + list(w) if args.size == 0 + end + def group(*args) + tk_call 'wm', 'path', path, *args + end + def iconbitmap(*args) + tk_call 'wm', 'bitmap', path, *args + end + def iconify + tk_call 'wm', 'iconify' + end + def iconmask(*args) + tk_call 'wm', 'iconmask', path, *args + end + def iconname(*args) + tk_call 'wm', 'iconname', path, *args + end + def iconposition(*args) + w = tk_call('wm', 'iconposition', path, *args) + list(w) if args.size == 0 + end + def iconwindow(*args) + tk_call 'wm', 'iconwindow', path, *args + end + def maxsize(*args) + w = tk_call('wm', 'maxsize', path, *args) + list(w) if not args.size == 0 + end + def minsize(*args) + w = tk_call('wm', 'minsize', path, *args) + list(w) if args.size == 0 + end + def overrideredirect(bool=None) + if bool == None + bool(tk_call('wm', 'overrideredirect', path)) + else + tk_call 'wm', 'overrideredirect', path, bool + end + end + def positionfrom(*args) + tk_call 'wm', 'positionfrom', path, *args + end + def protocol(name, func=None) + func = install_cmd(func) if not func == None + tk_call 'wm', 'command', path, name, func + end + def resizable(*args) + w = tk_call('wm', 'resizable', path, *args) + if args.length == 0 + list(w).collect{|e| bool(e)} + end + end + def sizefrom(*args) + list(tk_call('wm', 'sizefrom', path, *args)) + end + def state + tk_call 'wm', 'state', path + end + def title(*args) + tk_call 'wm', 'title', path, *args + end + def transient(*args) + tk_call 'wm', 'transient', path, *args + end + def withdraw + tk_call 'wm', 'withdraw', path + end + end +end + +class TkVariable + include Tk + + Tk_VARIABLE_ID = ["v00000"] + def initialize(val="") + @id = Tk_VARIABLE_ID[0] + Tk_VARIABLE_ID[0] = Tk_VARIABLE_ID[0].succ + INTERP._eval(format('global %s; set %s %s', @id, @id, _get_eval_string(val))) + end + + def id + @id + end + + def value + INTERP._eval(format('global %s; set %s', @id, @id)) + end + + def value=(val) + INTERP._eval(format('global %s; set %s %s', @id, @id, _get_eval_string(val))) + end + + def to_i + Integer(number(value)) + end + + def to_f + Float(number(value)) + end + + def to_s + String(string(value)) + end + + def inspect + format "", @id + end + + def ==(other) + case other + when TkVariable + self.equal(self) + when String + self.to_s == other + when Integer + self.to_i == other + when Float + self.to_f == other + when Array + self.to_a == other + else + false + end + end + + def to_a + list(value) + end + + def to_eval + @id + end end module TkSelection @@ -290,7 +761,7 @@ module TkPack end def propagate(master, bool=None) - bool(tk_call('pack', 'propagate', mastaer.epath, bool)) + bool(tk_call('pack', 'propagate', master.epath, bool)) end module_function :configure, :forget, :propagate end @@ -324,6 +795,10 @@ class TkObject", @id - end - - def to_a - list(value) - end -end - class TkWindow