diff -ur rubywebdialogs-none.tar.gz/rubywebdialogs/init.rb rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/init.rb
--- rubywebdialogs-none.tar.gz/rubywebdialogs/init.rb	2004-06-23 00:36:57.000000000 +0200
+++ rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/init.rb	2004-04-21 23:29:38.000000000 +0200
@@ -0,0 +1,40 @@
+require "rbconfig"
+
+Reversed	= (ARGV.include?("-r"))
+
+FromDirs	= ENV["PATH"].split(/:/) + [".", "./lib", "./rubylib/lib"]
+ToDir		= Config::CONFIG["sitelibdir"] + "/ev"
+
+Dir.mkdir(ToDir)	if not File.directory?(ToDir)
+
+FromDirs.each do |fromdir|
+  fromdir	= Dir.pwd	if fromdir == "."
+  if File.directory?(fromdir)
+    Dir.new(fromdir).each do |file|
+      if not file.scan(/\.lib\.rb$/).empty?
+        fromfile	= fromdir + "/" + file
+        tofile		= ToDir + "/" + file.sub(/\.lib\.rb/, ".rb")
+
+        if not (File.directory?("c:/"))
+          printf "%s -> %s\n", fromfile, tofile
+
+          File.unlink(tofile)	if File.symlink?(tofile)
+          File.symlink(fromfile, tofile)
+        else
+          if Reversed
+            tofile, fromfile = fromfile, tofile
+          end
+
+          if FileTest.file?(fromfile)
+            printf "%s -> %s\n", fromfile, tofile
+
+            File.delete(tofile)	if File.writable?(tofile)
+            File.open(tofile, "w") {|f| f.puts File.new(fromfile).readlines}
+          else
+            printf "%s -> %s (Skipped!)\n", fromfile, tofile
+          end
+        end
+      end
+    end
+  end
+end
diff -ur rubywebdialogs-none.tar.gz/rubywebdialogs/install.rb rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/install.rb
--- rubywebdialogs-none.tar.gz/rubywebdialogs/install.rb	2004-06-23 00:36:57.000000000 +0200
+++ rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/install.rb	2004-04-18 14:20:31.000000000 +0200
@@ -0,0 +1,40 @@
+require "rbconfig"
+
+Reversed	= (ARGV.include?("-r"))
+
+FromDirs	= ENV["PATH"].split(/:/) + [".", "./lib", "./rubylib/lib"]
+ToDir		= Config::CONFIG["sitelibdir"] + "/ev"
+
+Dir.mkdir(ToDir)	if not File.directory?(ToDir)
+
+FromDirs.each do |fromdir|
+  fromdir	= Dir.pwd	if fromdir == "."
+  if File.directory?(fromdir)
+    Dir.new(fromdir).each do |file|
+      if not file.scan(/\.lib\.rb$/).empty?
+        fromfile	= fromdir + "/" + file
+        tofile		= ToDir + "/" + file.sub(/\.lib\.rb/, ".rb")
+
+        if not (File.directory?("c:/"))
+          printf "%s -> %s\n", fromfile, tofile
+
+          File.unlink(tofile)	if File.symlink?(tofile)
+          File.symlink(fromfile, tofile)
+        else
+          if Reversed
+            tofile, fromfile = fromfile, tofile
+          end
+
+          if FileTest.file?(fromfile)
+            printf "%s -> %s\n", fromfile, tofile
+
+            File.delete(tofile)	if File.writable?(tofile)
+            File.open(tofile, "w") {|f| f.puts File.new(fromfile).readlines}
+          else
+            printf "%s -> %s (Skipped!)\n", fromfile, tofile
+          end
+        end
+      end
+    end
+  end
+end
diff -ur rubywebdialogs-none.tar.gz/rubywebdialogs/lib/net.lib.rb rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/net.lib.rb
--- rubywebdialogs-none.tar.gz/rubywebdialogs/lib/net.lib.rb	2004-06-23 00:36:57.000000000 +0200
+++ rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/net.lib.rb	2004-04-18 14:20:31.000000000 +0200
@@ -0,0 +1,541 @@
+require "ev/ruby"
+#alias old_timeout :timeout
+require "net/http"
+#alias timeout :old_timeout
+require "socket"
+require "uri"
+require "cgi"
+require "md5"
+require "thread"
+
+file	= "#{home}/.evnet"
+if File.file?(file)
+  Hash.file(file).each do |k, v|
+    eval "$#{k} = ´#{v}´"	unless k=~ /^\#/
+    #$proxy_auth	= [$proxy_auth].pack("m").chomp	if k == "proxy_auth"
+  end
+end
+
+def uri2txt(s)
+  i	= s.index(/%[[:digit:]]{2}/)
+  while not i.nil?
+    s	= s[0..(i-1)] + s[(i+1)..(i+2)].unpack(´H2´).shift.to_i.chr + s[(i+3)..-1]
+    i	= s.index(/%[[:digit:]]{2}/)
+  end
+  s
+end
+
+class EVURI
+  attr_reader :protocol
+  attr_writer :protocol
+  attr_reader :userpass
+  attr_writer :userpass
+  attr_reader :host
+  attr_writer :host
+  attr_reader :port
+  attr_writer :port
+  attr_reader :path
+  attr_writer :path
+  attr_reader :vars
+  attr_writer :vars
+  attr_reader :anchor
+  attr_writer :anchor
+
+  def initialize(url)
+    begin
+      @protocol, @userpass, @host, @port, d1, @path, d2, @vars, @anchor	= URI.split(url.to_s)
+    rescue
+    end
+
+    @protocol		= ""		if @protocol.nil?
+    @userpass		= ""		if @userpass.nil?
+    @host		= ""		if @host.nil?
+    @port		= 0		if @port.nil?
+    @path		= ""		if @path.nil?
+    @vars		= ""		if @vars.nil?
+    @anchor		= ""		if @anchor.nil?
+
+    res			= {}
+    @varsvolgorde	= []
+    @vars.split(/&/).each{|var| k, v = var.split(/=/) ; res[k] = v ; @varsvolgorde << k}
+    @vars		= res
+
+    @port		= @port.to_i
+  end
+
+  def + (url2)
+    url1	= self.to_s
+    url2	= url2.to_s	if url2.kind_of?(self.class)
+
+    return EVURI.new((URI::Generic.new(*URI.split(url1)) + URI::Generic.new(*URI.split(url2))).to_s)	rescue nil
+  end
+
+  def to_s
+    protocol	= @protocol
+    userpass	= @userpass
+    host	= @host
+    port	= @port.to_s
+    path	= @path
+    vars	= varstring
+    anchor	= @anchor
+
+    protocol	= nil	if @protocol.empty?
+    userpass	= nil	if @userpass.empty?
+    host	= nil	if @host.empty?
+    port	= nil	if @port.zero?
+    path	= nil	if @path.empty?
+    vars	= nil	if @vars.empty?
+    anchor	= nil	if @anchor.empty?
+
+    res	= URI::HTTP.new(@protocol, @userpass, @host, port, nil, @path, nil, vars, @anchor).to_s
+
+    res.gsub!(/@/, "")	if (@userpass.nil? or @userpass.empty?)
+
+    res.gsub!(/\#$/, "")
+
+    return res
+  end
+
+  def varstring
+    res		= []
+    vars	= @vars.dup
+
+    @varsvolgorde.each do |k|
+      if vars.include?(k)
+        v	= vars[k]
+        vars.delete(k)
+
+        res << (v.nil? ? k : "#{k}=#{v}")
+      end
+    end
+
+    res.concat(vars.collect{|k, v| v.nil? ? k : "#{k}=#{v}"})
+
+    return res.join("&")
+  end
+end
+
+class HTTPClient
+  @@versie	= 1
+  @@mutex	= Mutex.new
+  @@hosts	= {}
+
+  class Header
+    attr_reader :header
+    attr_reader :protocol
+    attr_reader :code
+    attr_reader :text
+
+    def initialize(header)
+      @header	= {}
+
+      if not header.nil?
+        firstline, rest	= header.split(/\r*\n/, 2)
+
+        @protocol, @code, @text	= firstline.split(/  */, 3)
+
+        if not rest.nil?
+          rest.split(/\r*\n/).each do |line|
+            key, value	= line.split(/ /, 2)
+            @header[key.sub(/:$/, "").downcase]	= value
+          end
+        end
+      end
+    end
+
+    def to_s
+      res	= ""
+
+      res << "%s %s %s\n" % [@protocol, @code, @text]
+
+      @header.each do |k, v|
+        res << "%s=%s\n" % [k, v]
+      end
+
+      return res
+    end
+  end
+
+  class Chunk
+    def initialize(data)
+      @data	= ""
+      line, data	= data.split(/\r*\n/, 2)
+      size, ext		= line.split(/;/, 2)
+      size		= size.hex
+      while not size.zero? and not data.nil?
+        @data		+= data[0..(size-1)]
+        data		= data[size..-1]
+        if not data.nil?
+          data.gsub!(/^\r*\n/, "")
+          line, data	= data.split(/\r*\n/, 2)
+          size, ext	= line.split(/;/, 2)
+          size		= size.hex
+        end
+      end
+    end
+
+    def to_s
+      @data
+    end
+  end
+
+  def self.head(uri, form={}, recursive=true)
+    header	= Header.new(nil)
+
+    begin
+      while not uri.nil?
+        if $proxy.nil? or $proxy.empty?
+          uri		= EVURI.new(uri) if uri.kind_of? String
+          host		= uri.host
+          port		= uri.port
+          io		= nil
+
+          @@mutex.synchronize do
+            @@hosts[host]	= IPSocket.getaddress(host)	if not @@hosts.include?(host)
+            io			= TCPSocket.new(@@hosts[host], port.zero? ? 80 : port)
+          end
+
+          io.write("HEAD #{uri.path or ´/´}#{uri.varstring.empty? ? ´´ : ´?´ + uri.varstring} HTTP/1.0\r\nHost: #{host}\r\n\r\n")
+        else
+          proxy		= EVURI.new($proxy)
+          host		= proxy.host
+          port		= proxy.port
+
+          io		= TCPSocket.new(host, port.zero? ? 8080 : port)
+
+          io.write("HEAD #{uri} HTTP/1.0\r\n#{"Proxy-Authorization: Basic "+$proxy_auth+"\r\n" if not $proxy_auth.nil?}\r\n\r\n")
+        end
+
+        io.close_write
+
+        res		= io.read
+        header, data	= nil, nil
+        header, data	= res.split(/\r*\n\r*\n/, 2)	if not res.nil?
+        header	= Header.new(header)
+
+        if recursive and header.header["location"] != uri.to_s
+          uri	= EVURI.new(uri) + header.header["location"]
+        else
+          uri	= nil
+        end
+      end
+    rescue
+      header	= Header.new(nil)
+    end
+
+    return header
+  end
+
+  def self.get(uri, form={})
+    res	= Array.new
+    form.each_pair do |var, value|
+      res << "#{var.to_html}=#{value.to_html}"
+    end
+    post	= res.join("?")
+
+    data	= nil
+
+    begin
+      while not uri.nil?
+        if $proxy.nil? or $proxy.empty?
+          uri	= EVURI.new(uri) if uri.kind_of? String
+          host	= uri.host
+          port	= uri.port
+          io	= nil
+
+          @@mutex.synchronize do
+            @@hosts[host]	= IPSocket.getaddress(host)	if not @@hosts.include?(host)
+            io			= TCPSocket.new(@@hosts[host], port.zero? ? 80 : port)
+          end
+
+          if post.empty?
+            io.write("GET #{uri.path or ´/´}#{uri.varstring.empty? ? ´´ : ´?´ + uri.varstring} HTTP/1.0\r\nHost: #{host}\r\n\r\n")
+          else
+            io.write("POST #{uri.path or ´/´}#{uri.varstring.empty? ? ´´ : ´?´ + uri.varstring} HTTP/1.0\r\nHost: #{host}\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: #{post.length}\r\n\r\n")
+            io.write(post)
+          end
+        else
+          proxy	= EVURI.new($proxy)
+          host	= proxy.host
+          port	= proxy.port
+          io	= nil
+
+          io	= TCPSocket.new(host, port.zero? ? 8080 : port)
+
+          if post.empty?
+            io.write("GET #{uri} HTTP/1.0\r\n#{"Proxy-Authorization: Basic "+$proxy_auth+"\r\n" if not $proxy_auth.nil?}\r\n\r\n")
+          else
+            io.write("POST #{uri} HTTP/1.0\r\n#{"Proxy-Authorization: Basic "+$proxy_auth+"\r\n" if not $proxy_auth.nil?}Content-Type: application/x-www-form-urlencoded\r\nContent-Length: #{post.length}\r\n\r\n")
+            io.write(post)
+          end
+        end
+
+        io.close_write
+
+        res		= io.read
+        header, data	= nil, nil
+        header, data	= res.split(/\r*\n\r*\n/, 2)	if not res.nil?
+
+        header	= Header.new(header)
+
+        if header.header["location"] != uri.to_s
+          uri	= EVURI.new(uri) + header.header["location"]
+        else
+          uri	= nil
+        end
+
+        if header.header["transfer-encoding"] == "chunked"
+          data	= Chunk.new(data).to_s	if not data.nil?
+        end
+      end
+    rescue
+      data	= nil
+    end
+
+    return data
+  end
+
+  def self.head_from_cache(uri, form={})
+    from_cache("head", uri, form)
+  end
+
+  def self.get_from_cache(uri, form={})
+    from_cache("get", uri, form)
+  end
+
+  def self.from_cache(action, uri, form)
+    loc		= uri.to_s + form.sort.inspect
+    hash	= MD5.new("#{@@versie} #{loc}")
+
+    dir		= "#{temp}/evcache.#{user}/httpclient.#{action}"
+    file	= "#{dir}/#{hash}"
+    data	= nil
+
+    Dir.mkdirrec(dir)
+
+    expire	= 356*24*60*60
+
+    if FileTest.file?(file) and (Time.new.to_f - File.stat(file).mtime.to_f < expire)
+      @@mutex.synchronize do
+        File.open(file, "rb")	{|f| data = f.read}
+      end
+    else
+      data	= method(action).call(uri, form)
+
+      if not data.nil?
+        @@mutex.synchronize do
+          File.open(file, "wb")	{|f| f.write data}
+        end
+      end
+    end
+
+    return data
+  end
+end
+
+class RequestGet < Hash
+  def initialize(data)
+    CGI.parse(data).each do |k, v|
+      self[k]	= v.join(" ")
+    end
+  end
+end
+
+class RequestPost < Hash
+  def initialize(data)
+    CGI.parse(data).each do |k, v|
+      self[k]	= v.join(" ")
+    end
+  end
+end
+
+class RequestRequest
+  attr_reader :method
+  attr_reader :uri
+  attr_reader :path
+  attr_reader :data
+  attr_reader :protocol
+
+  def initialize(firstline)
+    @method, @uri, @protocol	= firstline.split(/ /)
+    @path, @data		= @uri.split(/\?/)
+    @data			= ""			if @data.nil?	# TODO
+
+#    i	= @path.index(/%[[:digit:]]{2}/)
+#    while not i.nil?
+#      @path	= @path[0..(i-1)] + @path[(i+1)..(i+2)].unpack(´H2´).shift.to_i.chr + @path[(i+3)..-1]
+#      i	= @path.index(/%[[:digit:]]{2}/)
+#    end
+  end
+
+  def to_s
+    "#{@method} #{@uri} #{@protocol}\r\n"
+  end
+end
+
+class Request < Hash
+  attr_reader :peeraddr
+  attr_reader :request
+  attr_reader :cookies
+  attr_reader :vars
+
+  def initialize(io)
+    @io		= io
+
+    firstline	= @io.gets
+
+    return	if firstline.nil?
+
+    @request	= RequestRequest.new(firstline.strip)
+
+    line	= @io.gets.strip
+    while not line.empty? do
+      key, value	= line.split(" ", 2)
+      self[key.sub(/:$/, "").downcase]	= value
+
+      line	= @io.gets.strip
+    end
+
+    cookie	= self["cookie"]
+    cookie	= ""	if cookie.nil?
+    @cookies	= {}
+    cookie.split(/;/).each do |s|
+      k, v		= s.strip.split(/=/, 2)
+      @cookies[k]	= v
+    end
+
+    if not @request.method.nil?
+      case @request.method
+      when "HEAD"
+      when "GET"
+        @vars	= RequestGet.new(@request.data.nil? ? "" : @request.data)
+      when "POST"
+        data	= @io.read(self["content-length"].to_i)
+        @vars	= RequestPost.new((self["content-type"] == "application/x-www-form-urlencoded") ? data : "")
+      else
+        puts "Unknown request (´#{firstline}´)."
+      end
+    end
+
+    @peeraddr	= @io.peeraddr
+
+    @io.close_read
+  end
+
+  def to_s
+    res = @request.to_s
+    self.each do |k, v|
+      res << "#{k}: #{v}\r\n"
+    end
+    res
+  end
+end
+
+class Response < Hash
+  attr_writer :response
+
+  def initialize(io)
+    @io		= io
+    @response	= "HTTP/1.0 200 OK"
+    @data	= ""
+  end
+
+  def flush
+    @io.write("#{to_s}\r\n#{@data}")
+    @io.close
+  end
+
+  def to_s
+    res = "#{@response}\r\n"
+    self.each do |k, v|
+      res << "#{k}: #{v}\r\n"
+    end
+    res
+  end
+
+  def << (s)
+    @data << s
+  end
+end
+
+class HTTPServer
+  @@times	= {}
+
+  def self.serve(port=80, remote=false, auth=nil, realm="ev/net")
+    begin
+      server	= TCPServer.new(remote ? "0.0.0.0" : "localhost", port)
+      puts "Just point your browser to http://localhost:#{port}/ ..."
+    rescue
+      server	= nil
+      puts "Port #{port} is in use."
+    end
+
+    if not server.nil?
+      loop do
+        io	= nil
+
+        begin
+          io	= server.accept
+
+          req	= Request.new(io)
+          resp	= Response.new(io)
+        rescue
+          puts "Getting request from browser failed."
+          io	= nil
+        end
+
+        if not io.nil? and not req.peeraddr.nil?
+          #Thread.new(req, resp) do |req, resp|
+	    com	= req.request.to_s.strip + req.peeraddr[3]
+
+	    @@times[com]=Time.new.to_f	if not @@times.include?(com)
+
+	    if (not remote) or (remote and (auth.nil? or authenticate(auth, realm, req, resp)))
+	      #puts "#{Time.new.strftime("%H:%M:%S")}: #{req.peeraddr[3]}: #{((Time.new.to_f - @@times[com]).to_s + "0"*4)[0..4]}: > #{req.request}"
+
+	      yield(req, resp)
+
+	      puts "#{Time.new.strftime("%H:%M:%S")}: #{req.peeraddr[3]}: #{((Time.new.to_f - @@times[com]).to_s + "0"*4)[0..4]}: < #{req.request}"
+
+	      @@times.delete(com)
+	    end
+
+	    begin
+	      resp.flush
+	    rescue
+	    end
+          #end
+	end
+      end
+    end
+  end
+
+  def self.authenticate(auth, realm, req, resp)
+    if auth.kind_of? String
+      file	= "#{home}/#{auth}"
+      auths	= {}
+      auths	= Hash.file(file)	if FileTest.file?(file)
+    else
+      auths	= auth
+    end
+
+    authuserpassword	= req["authorization"]
+    if not authuserpassword.nil?
+      authtype, userpassword	= authuserpassword.split(/ /)
+      if authtype == "Basic" and not userpassword.nil?
+        u, p	= userpassword.unpack("m").shift.split(/:/)
+      end
+    end
+
+    ok	= (auths.include?(u) and auths[u] == p)
+
+    if ok
+
+    else
+      resp["WWW-Authenticate"]	= "Basic realm=\"#{realm}\""
+      resp.response		= "HTTP/1.0 401 Unauthorized"
+    end
+
+    return ok
+  end
+end
diff -ur rubywebdialogs-none.tar.gz/rubywebdialogs/lib/ruby.lib.rb rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/ruby.lib.rb
--- rubywebdialogs-none.tar.gz/rubywebdialogs/lib/ruby.lib.rb	2004-06-23 00:36:57.000000000 +0200
+++ rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/ruby.lib.rb	2004-04-18 14:20:31.000000000 +0200
@@ -0,0 +1,648 @@
+require "cgi"
+require "rbconfig"
+
+Thread.abort_on_exception	= true
+
+module Enumerable
+  def deep_dup
+    Marshal::load(Marshal::dump(dup))
+  end
+
+  def deep_clone
+    Marshal::load(Marshal::dump(clone))
+  end
+end
+
+class Object
+  alias deep_dup :dup
+  alias deep_clone :clone
+
+  def to_fs
+    to_s
+  end
+end
+
+class Numeric
+  def to_fs
+    to_f
+  end
+end
+
+class String
+  def chomp!(dummy=nil)
+    self.gsub!(/[\r\n]*\z/, "")
+  end
+
+  def chomp(dummy=nil)
+    self.gsub(/[\r\n]*\z/, "")
+  end
+
+  def crlf
+    self.gsub(/\r*\n/, "\r\n").gsub(/\r\n\z/, "") + "\r\n"
+  end
+
+  def strip
+    self.stripbefore.stripafter
+  end
+
+  def stripbefore
+    self.gsub(/\A[[:blank:]\r\n]*/, "")
+  end
+
+  def stripafter
+    self.gsub(/[[:blank:]\r\n]*\z/, "")
+  end
+
+  def compress
+    self.gsub(/[[:blank:]\r\n]+/, " ").strip
+  end
+
+  def compressspaces
+    self.gsub(/[[:blank:]]+/, " ")
+  end
+
+  def numeric?
+    d, a, n	= [self].to_par
+
+    not n.empty?
+  end
+
+  def exec(input=nil, output=true)
+    res	= []
+
+    IO.popen(self, "w+") do |f|
+      f.puts input	if not input.nil?
+      f.close_write
+
+      res	= f.readlines if output
+    end
+
+    res.join("")
+  end
+
+  def eval
+    Kernel::eval(self)
+  end
+
+  def speak
+    require "drb"
+
+    DRb.start_service
+    DRbObject.new(nil, "druby://localhost:3100").speak(self)
+  end
+
+  def splitblocks(begindelimiters, enddelimiter)
+    bd	= begindelimiters.collect {|s| Regexp.escape(s)}
+    ed	= enddelimiter.collect {|s| Regexp.escape(s)}
+
+    be	= bd.join("|")
+    ee	= ed.join("|")
+
+    res		= []
+    type	= 0
+    tmp		= ""
+    es		= ""
+    self.split(/(#{be}|#{ee})/).each do |s|
+      if type == 0
+        if begindelimiters.include?(s)
+          type	= begindelimiters.index(s)+1
+          tmp	= s
+          es	= enddelimiter[begindelimiters.index(s)]
+        else
+          #res << [0, s]	if not s.compress.empty?
+          res << [0, s]	if not s.empty?
+        end
+      else
+        if s == es
+          res << [type, tmp + s]
+          type	= 0
+          tmp	= ""
+          es	= ""
+        else
+          tmp 	= tmp + s
+        end
+      end
+    end
+    res
+  end
+
+  def splitwords(tokens=[], begindelimiters=["´", ´"´], enddelimiter=["´", ´"´])
+    tokens	= [tokens]	if not tokens.kind_of?(Array)
+    res		= []
+    self.splitblocks(begindelimiters, enddelimiter).each do |type, s|
+      case type
+      when 0
+        tokens.each do |token|
+          token2	= token
+          token2	= Regexp.escape(token2)	if token2.kind_of?(String)
+          s.gsub!(/#{token2}/, " #{token} ")
+        end
+        s.split().each do |w|
+          res << w
+        end
+      when 1, 2
+        res << s[1..-2]
+      end
+    end
+    res
+  end
+
+  def uncomment
+    res	= []
+    self.splitblocks(	["´" , ´"´ , "/*" , "<!--" , "#" , ";" ],
+			["´" , ´"´ , "*/" , "-->"  , "\n", "\n"]).each do |type, s|
+      case type
+      when 0, 1, 2	then	res << s
+      when 3, 4, 5
+      end
+    end
+    res.join("")
+  end
+
+  def noquotes
+    self.sub(/\A[´"]/, "").sub(/[´"]\z/, "")
+  end
+
+  def to_html(eolconversion=true)
+    s	= CGI.escapeHTML(self)
+
+    s.gsub!(/\"/, "\&#34;")
+    s.gsub!(/\´/, "\&#180;")
+
+    if eolconversion
+      s.gsub!(/\n/ , "<br>")
+    end
+
+    s
+  end
+
+  def from_html(eolconversion=true)
+    s	= self
+
+    s.gsub!(/&#34;/ , "\"")
+    s.gsub!(/&#180;/, "\´")
+
+    s	= CGI.unescapeHTML(self)
+
+    if eolconversion
+      s.gsub!(/<br>/, "\n")
+    end
+
+    s
+  end
+
+  def to_fs
+    if numeric?
+      to_f
+    else
+      to_s
+    end
+  end
+end
+
+class Array
+  def chomp!
+    self.collect!{|s| s.chomp}
+  end
+
+  def chomp
+    self.collect{|s| s.chomp}
+  end
+
+  def compress
+    self.collect{|s| s.compress}
+  end
+
+  def uncomment
+    self.join("\0").uncomment.split("\0")
+  end
+
+  def strip
+    self.collect{|s| s.strip}
+  end
+
+  def sum
+    res	= 0
+    self.each do |n|
+      res += n
+    end
+    res
+  end
+
+  def product
+    res	= 1
+    self.each do |n|
+      res *= n
+    end
+    res
+  end
+
+  def joinwords(sep=" ", quote=´"´)
+    self.collect do |s|
+      s	= quote + s + quote	if s =~ /[[:blank:]]/
+      s
+    end.join(sep)
+  end
+
+  def domino(tabellen, kolom=nil, onlymatchinglines=false)
+    links	= self
+    res		= []
+    res		= self.dup	unless onlymatchinglines
+
+    tabellen.each do |rechts|
+      tmp	= []
+
+      links.each do |l|
+        if kolom.nil? or l.length == kolom
+          rechts.each do |r|
+            tmp << l + r[1..-1]	if l[-1] == r[0]
+          end
+        end
+      end
+
+      links	= tmp
+      res.concat(tmp)
+    end
+
+    res	= res.sort.uniq
+  end
+
+  def dominoloop(tabellen)
+    lres	= []
+    res		= self.dup
+    kolom	= 2
+
+    while lres.length != res.length do
+      lres	= res.dup
+      res	= res.domino(tabellen, kolom)
+
+      res.each do |line|
+        line << "*"	if (line.length != line.uniq.length and line[-1] != "*")
+      end
+
+      $stderr.print "#{100*(res.length)/(lres.length)}% "
+
+      kolom += 1
+    end
+
+    $stderr.puts ""
+
+    return res
+  end
+
+  def buildtree
+    self.dominoloop([self])
+  end
+
+  def subset(fields, values, results, exact=true, emptyline=nil, joinwith=nil)
+    fields	= [fields]	if not fields.kind_of? Array
+    values	= [values]	if not values.kind_of? Array
+    results	= [results]	if not results.kind_of? Array
+    res		= []
+
+    self.each do |l|
+      ok	= true
+
+      case l.class.to_s
+      when "String"
+        c		= l.splitwords
+        correction	= 1
+        joinwith	= " "	if joinwith.nil?
+      when "Array"
+        c		= l
+        correction	= 0
+      end
+
+      0.upto(c.length-1) do |n|
+        if fields.include?(n+correction)
+          v	= values[fields.index(n+correction)]
+          if not emptyline.nil? and not v.downcase == emptyline.downcase
+            if exact
+              ok	= false	unless (v.nil? or c[n].downcase == v.downcase)
+            else
+              ok	= false	unless (v.nil? or c[n].downcase.include?(v.downcase))
+            end
+          end
+        end
+      end
+
+      if ok
+        res2	= []
+        results.each do |n|
+          res2 << c[n-1]
+        end
+        res2	= res2.join(joinwith)	if not joinwith.nil?
+        res << res2
+      end
+    end
+
+    return res
+  end
+
+  def format(format)
+    res		= []
+
+    [format.length, self.length].min.times do |n|
+      case format[n].chr
+      when "i"	then res << self[n].to_i
+      when "s"	then res << self[n].to_s
+      when "x"	then res << self[n]
+      end
+    end
+
+    res
+  end
+
+  def to_i
+    collect{|c| c.to_i}
+  end
+
+  def to_par
+    dash	= self.dup
+    alpha	= self.dup
+    numeric	= self.dup
+
+    dash.delete_if do |s|
+      not (s =~ /\A-/) or
+      (s =~ /\A-?[[:digit:]\.]+\z/) or
+      (s =~ /^-+$/)
+    end
+
+    alpha.delete_if do |s|
+      ((s =~ /\A-/) or
+       (s =~ /\A-?[[:digit:]\.]+\z/)) and
+      not ((s =~ /^\.+$/) or (s =~ /^-+$/))
+    end
+
+    numeric.delete_if do |s|
+      not (s =~ /\A-?[[:digit:]\.]+\z/) or
+      (s =~ /^\.+$/)
+    end
+
+    raise "Oops!"	if dash.length + alpha.length + numeric.length != length
+
+    return dash, alpha, numeric
+  end
+
+  def self.file(file)
+    res	= []
+
+    File.new(file).readlines.uncomment.chomp.each do |line|
+      res << line
+    end
+
+    res
+  end
+
+  def numsort
+    sort do |a, b|
+      a2	= a.to_fs
+      b2	= b.to_fs
+
+      if a2.class != b2.class
+        a2	= a
+        b2	= b
+      end
+
+      a2 <=> b2
+    end
+  end
+
+  def to_fs
+    collect{|s| s.to_fs}
+  end
+
+  def chaos
+    res	= self.dup
+
+    (length^2).times do
+      a	= rand(length)
+      b	= rand(length)
+
+      res[a], res[b]	= res[b], res[a]
+    end
+
+    res
+  end
+
+  def minmax
+    min, value, max	= self
+    [min, [value, max].min].max
+  end
+end
+
+class Hash
+  def save(file, append=false)
+    org	= {}
+    org	= Hash.file(file)	if (append and File.file?(file))
+
+    self.sort.each do |k, v|
+     org[k]	= v
+    end
+
+    File.open(file, "w") do |f|
+      org.sort.each do |k, v|
+        #f.puts "´%s´=´%s´" % [k, v]
+        f.puts "%s = %s" % [k, v]
+      end
+    end
+  end
+
+  def subset(fields, values, results=nil, exact=true, emptyline=nil, joinwith=nil)
+    fields	= [fields]	if not fields.kind_of? Array
+    values	= [values]	if not values.kind_of? Array
+    results	= [results]	if not results.kind_of? Array
+    res		= self.dup
+    res.delete_if {true}
+
+    self.each do |k, l|
+      ok	= true
+
+      case l.class.to_s
+      when "String"
+        c		= l.splitwords
+        correction	= 1
+        joinwith	= " "	if joinwith.nil?
+      when "Array"
+        c		= l
+        correction	= 0
+      end
+
+      0.upto(c.length-1) do |n|
+        if fields.include?(n+correction)
+          v	= values[fields.index(n+correction)]
+          if emptyline.nil? or (not emptyline.nil? and not v.downcase == emptyline.downcase)
+            if exact
+              ok	= false	unless (v.nil? or c[n].downcase == v.downcase)
+            else
+              ok	= false	unless (v.nil? or c[n].downcase.include?(v.downcase))
+            end
+          end
+        end
+      end
+
+      if ok
+        res2	= []
+        if results == [nil]
+          res2	= c
+        else
+          results.each do |n|
+            res2 << c[n-correction]
+          end
+        end
+        res2	= res2.join(joinwith)	if not joinwith.nil?
+        res[k]	= res2
+      end
+    end
+
+    return res
+  end
+
+  def to_i
+    collect{|k, v| v.to_i}
+  end
+
+  def self.file(file)
+    res	= {}
+
+    File.new(file).readlines.chomp.each do |line|
+      if not line.compress.empty?
+        k, v	= line.split(/\s*=\s*/, 2)
+        res[k]	= v
+      end
+    end
+#    File.new(file).readlines.uncomment.chomp.each do |line|
+#      if not line.compress.empty?
+#        a	= line.splitwords("=")
+#
+#        if a.size == 3 and  a[1] == "="
+#	  res[a[0]]	= a[2]
+#        else
+#	  puts "Error in #{file} (not ´var=\"value\"´)."
+#        end
+#      end
+#    end
+
+    res
+  end
+end
+
+class Dir
+  def Dir.mkdirrec(dir)
+    pdir	= File.dirname(dir)
+
+    if not pdir.empty? and not FileTest.directory?(pdir)
+      mkdirrec (pdir)
+    end
+
+    Dir.mkdir(dir)	rescue nil
+  end
+end
+
+def id2ref(id)
+  ObjectSpace._id2ref(id)
+end
+
+def after(seconds)
+  if not seconds.nil? and not seconds.zero?
+    Thread.new do
+      sleep seconds
+      yield
+    end
+  end
+end
+
+def every(seconds)
+  if not seconds.nil? and not seconds.zero?
+    Thread.new do
+      loop do
+        sleep seconds
+        yield
+      end
+    end
+  end
+end
+
+def evtimeout(seconds)
+  if not seconds.nil? and not seconds.zero?
+    t		= Thread.current
+    threads	= []
+    res		= nil
+
+    threads[1] = Thread.new do
+      sleep seconds
+      begin
+        threads[2].kill
+      rescue NameError
+      end
+      res	= false
+      t.wakeup
+    end
+
+    threads[2] = Thread.new do
+      yield
+      begin
+        threads[1].kill
+      rescue NameError
+      end
+      res	= true
+      t.wakeup
+    end
+
+    threads[1].join
+    threads[2].join
+
+    return res
+  else
+    yield
+  end
+end
+
+def evtimeoutretry(seconds)
+  ok	= false
+
+  while not ok
+    evtimeout(seconds) do
+      yield
+      ok	= true
+    end
+  end
+end
+
+def trap(signal)
+  Kernel::trap(signal) do
+    yield
+  end
+
+	# Seems pointless, but it´s for catching ^C under Windows...
+
+  every(1)	{}
+end
+
+def linux?
+  not windows? and not cygwin?
+end
+
+def windows?
+  not (target_os.downcase =~ /32/).nil?
+end
+
+def cygwin?
+  not (target_os.downcase =~ /cyg/).nil?
+end
+
+def target_os
+  Config::CONFIG["target_os"] or ""
+end
+
+def user
+  ENV["USER"] or ENV["USERNAME"]
+end
+
+def home
+  (ENV["HOME"] or ENV["USERPROFILE"] or (File.directory?("h:/") ? "h:" : "c:")).gsub(/\\/, "/")
+end
+
+def temp
+  (ENV["TEMP"] or "/tmp").gsub(/\\/, "/")
+end
diff -ur rubywebdialogs-none.tar.gz/rubywebdialogs/lib/rwd.lib.rb rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/rwd.lib.rb
--- rubywebdialogs-none.tar.gz/rubywebdialogs/lib/rwd.lib.rb	2004-06-23 00:36:57.000000000 +0200
+++ rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/rwd.lib.rb	2004-04-18 14:20:31.000000000 +0200
@@ -0,0 +1,1320 @@
+require "ev/xml"
+require "ev/net"
+require "md5"
+require "rbconfig"
+require "pstore"
+
+begin
+  require "win32ole"
+  require "win32/registry"
+rescue LoadError
+  $".push "win32ole.rb"
+  $".push "win32/registry.rb"
+end
+
+exit	if ARGV.include?("--rwd-exit")
+
+Debug		= false
+Border		= 0
+RWDEmptyline	= "..."
+
+rcfile	= nil
+s	= ENV["HOME"]		; s = s + "/.rwdrc"	if not s.nil?	; rcfile = s	if (not s.nil? and rcfile.nil? and FileTest.file?(s))
+s	= ENV["USERPROFILE"]	; s = s + "/rwd.cfg"	if not s.nil?	; rcfile = s	if (not s.nil? and rcfile.nil? and FileTest.file?(s))
+s	= ENV["windir"]		; s = s + "/rwd.cfg"	if not s.nil?	; rcfile = s	if (not s.nil? and rcfile.nil? and FileTest.file?(s))
+
+AL	= "align=´left´"
+AC	= "align=´center´"
+AR	= "align=´right´"
+VA	= "valign=´middle´"
+
+Format	= "\n<!-- %-10s %-10s -->\t"
+
+if not rcfile.nil?
+  puts "Reading #{rcfile} ..."
+
+  Hash.file(rcfile).each do |k, v|
+    ENV[k]	= v
+  end
+else
+  begin
+    puts "Looking for default browser..."
+    ENV["RWDBROWSER"]	= Win32::Registry::HKEY_CLASSES_ROOT.open(´htmlfile\shell\open\command´)[0]
+  rescue
+    puts "Not found."
+  end
+
+  if not ENV.include?("RWDBROWSER") and false # ???
+    s	= ENV["HOME"]		; s = s + "/.rwdrc"	if not s.nil?	; rcfile = s	if (not s.nil? and rcfile.nil?)
+    s	= ENV["USERPROFILE"]	; s = s + "/rwd.cfg"	if not s.nil?	; rcfile = s	if (not s.nil? and rcfile.nil?)
+    s	= ENV["windir"]		; s = s + "/rwd.cfg"	if not s.nil?	; rcfile = s	if (not s.nil? and rcfile.nil?)
+
+    if not rcfile.nil?
+      puts "Creating #{rcfile} ..."
+      puts ""
+      puts "# This is the first time you start a RubyWebDialog application."
+      puts "# I have to know your favorite browser."
+      puts "# "
+      puts "# Put the full path to your favorite browser between the quotes"
+      puts "# (\"...\") after RWDBROWSER= and remove the hash (#) at the"
+      puts "# beginning of the line."
+      puts "# "
+      puts "# Restart your application."
+      puts ""
+
+      File.open(rcfile, "a") do |f|
+        f.puts "# This is the first time you start a RubyWebDialog application."
+        f.puts "# I have to know your favorite browser."
+        f.puts "# "
+        f.puts "# Put the full path to your favorite browser between the quotes"
+        f.puts "# (\"...\") after RWDBROWSER= and remove the hash (#) at the"
+        f.puts "# beginning of the line."
+        f.puts "# "
+        f.puts "# Restart your application."
+        f.puts ""
+        f.puts "#RWDBROWSER=\"...\""
+      end
+    end
+
+    if windows?
+      system("notepad #{rcfile}")
+
+      sleep 1
+    else
+      puts "Please edit #{rcfile}."
+    end
+
+    exit
+  end
+end
+
+trap("INT")	{puts "Terminating..." ; exit}
+
+$SAFE	= 2
+
+class IE
+  def initialize(url)
+    @ie = WIN32OLE.new("InternetExplorer.Application")
+    @ev	= WIN32OLE_EVENT.new(@ie, "DWebBrowserEvents2")
+
+    @ie.navigate(url)
+
+    @ie.menubar		= false
+    @ie.toolbar		= false
+    @ie.addressbar	= false
+    @ie.statusbar	= false
+
+    @ie.visible		= true
+
+    at_exit do
+      @ie.visible	= false
+    end
+
+    @ev.on_event("OnQuit") do
+      Thread.main.exit
+    end
+
+    Thread.new do
+      loop do
+	WIN32OLE_EVENT.message_loop
+      end
+    end
+  end
+end
+
+class Array
+  def rwd_options(emptyline=nil)
+    if emptyline.nil?
+      a	= self
+    else
+      a	= [emptyline].concat self
+    end
+
+    a.numsort.collect{|s| "<option>#{s.to_html}</option>" }.join("\n")
+  end
+
+  def rwd_method(method)
+    res	= ""
+
+    self.each do |s|
+      s		= s.join("/")	if s.kind_of?(Array)
+      s2	= s.dup
+      s2[0..0]	= s2[0..0].upcase
+      res	= res + "<p align=´left´><a action=´#{method}/#{s.to_html}´>#{s2.to_html}</a></p>"
+    end
+
+    return res
+  end
+
+  def rwd_row(key=nil, value=nil)
+    res	= ""
+
+    res	= res + "<row valign=´top´>"
+    res	= res + "<radio name=´#{key.to_html}´ value=´#{value.to_html}´/>"	if not key.nil?
+    res	= res + self.collect{|s| "<p align=´left´>#{s.to_html}</p>"}.join("")
+    res	= res + "</row>"
+
+    return res
+  end
+
+  def rwd_headers(emptyfield=false)
+    res	= ""
+
+    res	= res + "<row>"
+    res	= res + "<p/>"	if emptyfield
+    res	= res + self.collect{|s| "<p align=´left´><b>#{s.to_html}</b></p>" }.join("")
+    res	= res + "</row>"
+
+    return res
+  end
+
+  def rwd_form(prefix, values, twoparts=0, options={})
+    res	= []
+
+    res << "<table>"
+    self.each_index do |n|
+      name	= "#{prefix.to_html}#{self[n].downcase.to_html}"
+
+      res << "<row>"
+      res << "<p align=´right´>"
+      res << "#{self[n].to_html}:"
+      res << "</p>"
+
+      if options.keys.include?(self[n])
+        res << "<select name=´#{name}´>"
+        res << options[self[n]].rwd_options(RWDEmptyline)
+        res << "</select>"
+      else
+        s	= ""
+
+	s << "<text name=´#{name}´"
+	s << " value=´#{values[n].to_html}´"	if n < values.length
+	s << "/>"
+
+	res << s
+      end
+
+      res << "</row>"
+
+      if twoparts > 0 and n == twoparts-1
+        res << "<row><empty/></row>"
+      end
+    end
+    res << "</table>"
+
+    return res.join("\n")
+  end
+end
+
+class Hash
+  def rwd_table(field, joinwith=@sep, headers=nil)
+    res	= []
+
+    res << "<table>"
+    res << headers.rwd_headers(true)	if not headers.nil?
+    self.keys.numsort.each do |key|
+      key2	= key
+      value2	= self[key]
+
+      key2	= key2.join(joinwith)	if key2.kind_of?(Array)
+      value2	= [value2]		if value2.kind_of?(String)
+
+      res << value2.rwd_row(field, key2)
+    end
+    res << "</table>"
+
+    res.join("\n")
+  end
+end
+
+class EVTable
+  def rwd_table(key, joinwith)
+    super(key, joinwith, @headers)
+  end
+
+  def rwd_form(prefix="", key=nil, twoparts=false)
+    values	= self[key]	if not key.nil?
+    values	= []		if values.nil?
+    options	= {}
+
+    if File.file?(oldlocation("constraints.csv"))
+      table	= File.basename(@file).gsub(/\.csv$/, "")
+
+      CSVFile.new(oldlocation("constraints.csv")).subset(["Table", "Constraint"], [table, "key"], ["Column", "Value"]).values.each do |column, table2|
+        options[column]	= CSVFile.new(oldlocation("#{table2}.csv")).keys.collect{|a| a.join("\t")}
+      end
+    end
+
+    @headers.rwd_form(prefix, values, twoparts ? @key : 0, options)
+  end
+
+  def rwd_metadata
+    res	= []
+
+    res << "<table>"
+    res << "<row>"
+    res << "  <empty/>"
+    res << "  <text name=´header_new´ value=´´/>"
+    res << "</row>"
+    @headers.each_index do |n|
+      res << "<row>"
+      res << "  <text name=´header_#{n}_old´ value=´#{@headers[n]}´/>"
+      res << "  <text name=´header_#{n}_new´ value=´´/>"
+      res << "</row>"
+    end
+    res << "</table>"
+
+    return res.join("\n")
+  end
+end
+
+class OpenTag
+  def prechildren(res, before, after, vars, switches, help, firstaction, tabs, tab)
+    bef	= before[-1]
+    res.concat Format % ["Before", @subtype]		if (Debug and not bef.nil?)
+    res.concat bef	if not bef.nil?
+
+    res.concat Format % ["Pre", @subtype]	if Debug
+
+    align	= AC
+    align	= "align=´#{@args["align"]}´"	if @args.include?("align")
+
+    valign	= VA
+    valign	= "valign=´#{@args["valign"]}´"	if @args.include?("valign")
+
+    value	= ""
+    value	= vars[@args["name"]]		if vars.include?(@args["name"])
+    value	= @args["value"]		if @args.include?("value")
+
+    case @subtype
+    when "application"
+    when "window", "helpwindow"
+      args	= @args.deep_dup
+
+      args["nohelpbutton"]	= (not help)
+
+      res.concat(template(RWD_HTML1, args))
+    when "p"		then res.concat "<p #{align}>"
+    when "pre"		then res.concat "<pre>"
+    when "big"		then res.concat "<p #{align}><big>"
+    when "small"	then res.concat "<p #{align}><small>"
+    when "list"		then res.concat "<ul #{align}>"
+    when "item"		then res.concat "<li #{align}>"
+    when "empty"	then res.concat "<p><br>"
+    when "image"	then res.concat "<img src=´#{@args["src"]}´>"
+    when "br"		then res.concat "<br>"
+    when "hr"		then res.concat "<hr>"
+    when "b"		then res.concat "<b>"
+    when "i"		then res.concat "<i>"
+    when "a"
+      if @args.include?("href")
+        res.concat "<a href=´#{@args["href"]}´ target=´#{@args["target"] or "new"}´>"
+      else
+        res.concat "<a href=´javascript:document.bodyform.rwd_action.value=\"#{@args["action"]}\";document.bodyform.submit();´>"
+      end
+    when "vertical"	then res.concat "<table #{AC} border=´#{Border}´ cellspacing=´3´ cellpadding=´0´>"
+    when "horizontal"	then res.concat "<table #{AC} border=´#{Border}´ cellspacing=´3´ cellpadding=´0´><tr #{align} #{valign}>"
+    when "table"	then res.concat "<table #{AC} border=´#{Border}´ cellspacing=´3´ cellpadding=´0´>"
+    when "row"		then res.concat "<tr #{align} #{valign}>"
+    when "hidden"	then res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value}´ type=´hidden´>"
+    when "text"		then res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value}´ type=´text´>"
+    when "textarea"	then res.concat "<p #{align}><textarea name=´#{@args["name"]}´>#{value}</textarea>"
+    when "password"	then res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value}´ type=´password´>"
+    when "checkbox"
+      if vars[@args["name"]] == "on"
+        switches[@args["name"]]	= true
+        res.concat "<p #{align}><input name=´#{@args["name"]}´ checked=´on´ type=´checkbox´>"
+      else
+        switches[@args["name"]]	= false
+        res.concat "<p #{align}><input name=´#{@args["name"]}´ type=´checkbox´>"
+      end
+    when "radio"
+      if vars[@args["name"]] == value
+        res.concat "<p #{align}><input name=´#{@args["name"]}´ checked=´on´ value=´#{value}´ type=´radio´>"
+      else
+        res.concat "<p #{align}><input name=´#{@args["name"]}´ value=´#{value}´ type=´radio´>"
+      end
+    when "select"
+      res.concat "<select #{align} name=´#{@args["name"]}´ width=´#{@args["width"]}´>"
+      name	= @args["name"]
+      $select	= vars[name]
+    when "option"
+      if $select == @children[0].text
+        res.concat "<option selected=´true´>"
+      else
+        res.concat "<option>"
+      end
+    when "button"
+      res.concat "<input type=´submit´ value=´#{@args["caption"]}´ onclick=´document.bodyform.rwd_action.value=\"#{@args["action"]}\";´>"
+      firstaction	<< @args["action"]	if (firstaction.empty? and @args.include?("action"))
+    when "back"
+      res.concat "<input type=´submit´ value=´Back´ onclick=´document.bodyform.rwd_action.value=\"rwd_back\";´>"
+      firstaction	<< "rwd_back"	if firstaction.empty?
+    when "help"
+      res.concat "<input type=´submit´ value=´Help´ onclick=´document.bodyform.rwd_action.value=\"rwd_help\";´>"
+      firstaction	<< "rwd_help"	if firstaction.empty?
+    when "quit"
+      res.concat "<input type=´submit´ value=´Quit´ onclick=´document.bodyform.rwd_action.value=\"rwd_quit\";´>"
+      firstaction	<< "rwd_quit"	if firstaction.empty?
+    when "close"
+      res.concat "<input type=´submit´ value=´Close´ onclick=´window.close();´>"
+      firstaction	<< "rwd_quit"	if firstaction.empty?
+    when "reset"
+      res.concat "<input type=´reset´  value=´Reset´>"
+      firstaction	<< "rwd_quit"	if firstaction.empty?
+    when "closewindow"
+      #res.concat "<script type=´text/javascript´>\n"
+      #res.concat "<!--\n"
+      #res.concat "  window.close();\n"
+      #res.concat "//-->\n"
+      #res.concat "</script>"
+    when "tabs"
+      res.concat "<table #{AC} border=´#{Border}´ cellspacing=´3´ cellpadding=´0´>"
+      res.concat "  <tr #{AC}>"
+      res.concat "    <td #{AC}>"
+      res.concat "      <table #{AC} border=´#{Border}´ cellspacing=´3´ cellpadding=´0´>"
+      res.concat "        <tr #{AC}>"
+      tabs.each do |obj|
+        caption	= obj.args["caption"]
+        if caption == tab
+          res.concat "<td #{AC}><div class=´box´><tt><b>&nbsp;#{caption}&nbsp;</b></tt></div></td>"
+        else
+          res.concat "<td #{AC}><div class=´box´><a href=´javascript:document.bodyform.rwd_action.value=\"rwd_tab_#{caption}\";document.bodyform.submit();´><tt>&nbsp;#{caption}&nbsp;</tt></a></div></td>"
+        end
+      end
+      res.concat "        </tr>"
+      res.concat "      </table>"
+      res.concat "    </td>"
+      res.concat "  </tr>"
+    when "tab"
+      res.concat "<tr #{align} #{valign}><td #{align}><div class=´box2´>"
+    else
+      puts "<#{@subtype}>"
+      res.concat "&lt;#{@subtype}&gt;"
+    end
+
+    bef	= nil
+    aft	= nil
+
+    case @subtype
+    when "vertical", "window", "helpwindow"
+      res.concat Format % ["AftPre", @subtype]	if Debug
+      if @args.include?("spacing")
+        s	= "<tr><td>&nbsp;</td></tr>" * (@args["spacing"].to_i)
+      else
+        s	= ""
+      end
+      bef	= "#{s}<tr #{align} #{valign}><td #{align}>"
+      aft	= "</td></tr>"
+    when "horizontal", "row"
+      res.concat Format % ["AftPre", @subtype]	if Debug
+      bef	= "<td #{align}>"
+      aft	= "</td>"
+    end
+
+    before.push(bef)
+    after.push(aft)
+  end
+
+  def postchildren(res, before, after, vars, switches, help, firstaction, tabs, tab)
+    case @subtype
+    when "vertical", "window", "helpwindow"
+      res.concat Format % ["BefPost", @subtype]	if Debug
+      if @args.include?("spacing")
+        res.concat "<tr><td>&nbsp;</td></tr>" * (@args["spacing"].to_i)
+      end
+    when "horizontal", "row"
+      res.concat Format % ["BefPost", @subtype]	if Debug
+    end
+
+    res.concat Format % ["Post", @subtype]		if Debug
+
+    case @subtype
+    when "application"
+    when "window", "helpwindow"
+      args	= @args.deep_dup
+
+      args["nohelpbutton"]	= (not help)
+
+      res.concat(template(RWD_HTML2, args))
+    when "p"		then res.concat "</p>"
+    when "pre"		then res.concat "</pre>"
+    when "big"		then res.concat "</big></p>"
+    when "small"	then res.concat "</small></p>"
+    when "list"		then res.concat "</ul>"
+    when "item"		then res.concat "</li>"
+    when "empty"	then res.concat "</p>"
+    when "image"	then res.concat ""
+    when "br"		then res.concat ""
+    when "hr"		then res.concat ""
+    when "b"		then res.concat "</b>"
+    when "i"		then res.concat "</i>"
+    when "a"		then res.concat "</a>"
+    when "vertical"	then res.concat "</table>"
+    when "horizontal"	then res.concat "</tr></table>"
+    when "table"	then res.concat "</table>"
+    when "row"		then res.concat "</tr>"
+    when "hidden"	then res.concat "</p>"
+    when "text"		then res.concat "</p>"
+    when "textarea"	then res.concat "</p>"
+    when "password"	then res.concat "</p>"
+    when "checkbox"	then res.concat "</p>"
+    when "radio"	then res.concat "</p>"
+    when "select"
+      res.concat "</select>"
+      $select	= nil
+    when "option"	then res.concat "</option>"
+    when "button"	then res.concat ""
+    when "back"		then res.concat ""
+    when "help"		then res.concat ""
+    when "quit"		then res.concat ""
+    when "close"	then res.concat ""
+    when "reset"	then res.concat ""
+    when "closewindow"	then res.concat ""
+    when "tabs"		then res.concat "</table>"
+    when "tab"		then res.concat "</div></td></tr>"
+    else
+      puts "</#{@subtype}>"
+      res.concat "&lt;/#{@subtype}&gt;"
+    end
+
+    before.pop
+    after.pop
+
+    aft	= after[-1]
+    res.concat Format % ["After", @subtype]		if (Debug and not aft.nil?)
+    res.concat aft	if not aft.nil?
+  end
+
+  def template(html, vars)
+    res	= []
+
+    a	= {}
+
+    vars.each do |k, v|
+      a[k.upcase]	= v
+    end
+
+    a["LOGO"]		= ""	unless ((not vars["logo"].nil?) and FileTest.file?(vars["logo"]))
+
+    a["HELPBUTTON"]	= (not (vars["nohelpbutton"]))
+    a["BACKBUTTONS"]	= (not (vars["nobackbuttons"]))
+    a["BACKBUTTONS"]	= (not (vars["nobackbuttons"]))
+    a["CLOSEBUTTON"]	= (not (vars["noclosebutton"]))
+
+    html.split(/\r*\n/).each do |line|
+      if line =~ /%[A-Z]+%/
+        a.each do |k, v|
+          v	= false	if (v.kind_of?(String) and v.empty?)
+
+          if line.include?("%#{k}%")
+            line.gsub!("%#{k}%", "#{v}")	if v
+          end
+        end
+
+        line	= "<!-- #{line.scan(/%[A-Z]+%/).join(" ")} -->"	if line =~ /%[A-Z]+%/
+      end
+
+      res << line
+    end
+
+    res.join("\n")
+  end
+end
+
+class Text
+  def prechildren(res, before, after, vars, switches, help, firstaction, tabs, tab)
+    if not @text.scan(/[^ \t\r\n]/).empty?
+      res.concat Format % ["Text", ""]	if Debug
+      res.concat "#{@text}"
+    end
+  end
+end
+
+class RWDTree < XML
+end
+
+class RWDWindow
+  @@windows	= {}	# Kind of caching.
+  @@helpwindows	= {}	# Kind of caching.
+
+  def initialize(rwd, window=nil)
+    rwd	= rwd.join("\n")	if rwd.kind_of?(Array)
+
+    if @@windows[rwd].nil?
+      @@windows[rwd]		= {}
+      @@helpwindows[rwd]	= {}
+
+      tree	= XML.new(rwd)
+
+      tree.parse(OpenTag, "window") do |type, obj|
+        @@windows[rwd][obj.args["name"]]	= obj.to_h
+      end
+
+      tree.parse(OpenTag, "helpwindow") do |type, obj|
+        @@helpwindows[rwd][obj.args["name"]]	= obj.to_h
+      end
+    end
+
+    @rwd	= (@@windows[rwd][window] or "").dup
+    @helprwd	= (@@helpwindows[rwd][window] or "").dup
+  end
+
+  def render(vars=Hash.new, switches=Hash.new, help=false, tab="")
+    vars2	= Hash.new
+    firstaction	= ""
+    html	= ""
+
+    vars.each do |key, value|
+      if not key.empty?
+        if value.respond_to? "to_s"
+          @rwd.gsub!(/%%#{key}%%/, value.to_s)
+          @rwd.gsub!(/%#{key}%/, value.to_s.to_html)
+
+          @helprwd.gsub!(/%%#{key}%%/, value.to_s)
+          @helprwd.gsub!(/%#{key}%/, value.to_s.to_html)
+
+          vars2[key]	= value.to_s.to_html
+        end
+      end
+    end
+
+    windowobject	= RWDTree.new(@rwd).children.dup.delete_if{|obj| obj.subtype != "window"}[0]
+    helpobject		= RWDTree.new(@helprwd).children.dup.delete_if{|obj| obj.subtype != "helpwindow"}[0]
+
+    tabsobj	= windowobject.children.dup.delete_if{|obj| obj.subtype != "tabs"}[0]
+
+    if not tabsobj.nil?
+      tabs	= tabsobj.children.dup.delete_if{|obj| (not obj.kind_of?(OpenTag)) or (obj.subtype != "tab")}
+
+      if tab.empty?
+        tab			= tabs[0].args["caption"]
+      end
+
+      tabsobj.children.delete_if{|obj| (obj.kind_of?(OpenTag)) and (obj.subtype == "tab") and obj.args["caption"] != tab}
+    end
+
+    if help
+      helpobject.parsetree("prechildren", "postchildren", html, [""], [""], vars2, switches, false, firstaction, tabs, tab)
+    else
+      windowobject.parsetree("prechildren", "postchildren", html, [""], [""], vars2, switches, (not @helprwd.empty?), firstaction, tabs, tab)
+    end
+
+    html.gsub!(/%%*[[:alnum:]_\-]+%%*/, "")	if not Debug
+    html.gsub!(/%%/, "%")
+    html.gsub!(/\n\n*/, "\n")
+
+    if firstaction.empty?
+      focus	= ""
+    else
+      focus	= "document.bodyform.elements[0].focus();"
+    end
+
+    html.gsub!(/\$RWD_FIRSTACTION\$/	, firstaction)
+    html.gsub!(/\$RWD_FOCUS\$/		, focus)
+
+    html
+  end
+end
+
+class RWDMessage < RWDWindow
+  def initialize(msg)
+    super("<window title=´RWD Message´ nobackbuttons><vertical><p><b>Message:</b> #{msg}</p><back/></vertical></window>")
+  end
+end
+
+class RWDError < RWDWindow
+  def initialize(msg)
+    super("<window title=´RWD Error´ nobackbuttons><vertical><p><b>Error:</b> #{msg}</p><back/></vertical></window>")
+  end
+end
+
+class RWDDone < RWDWindow
+  def initialize(exitbrowser)
+    super("<window title=´RWD Message´ nobackbuttons noclosebutton><p>Done.</p><horizontal><close/>#{exitbrowser ? "" : "<button caption=´Login´/>"}</horizontal>#{exitbrowser ? "<closewindow/>" : ""}</window>")
+  end
+end
+
+class RWDialog
+  def initialize(xml)
+    @rwd_xml		= xml
+    @rwd_exitbrowser	= false
+    @rwd_history	= []
+    @rwd_clone_vars	= ["@rwd_history"]
+    @rwd_ignore_vars	= ["@rwd_server"]
+  end
+
+  def self.file(rwdfile, *args)
+    new(File.new(rwdfile).readlines, *args)
+  end
+
+  def serve(port=1234, auth=nil, realm=self.class.to_s)
+    raise "RWD is not initialized."	if @rwd_xml.nil?
+
+    @rwd_server	= RWDServer.new(self, port, auth, realm)
+  end
+
+  def render(res, path, post, sessionid)
+
+		# Initialize some vars.
+
+    vars		= Hash.new	if vars.nil?
+    @rwd_switches	= Hash.new	if @rwd_switches.nil?
+
+    done	= false
+    help	= false
+    back	= false
+    tab		= ""
+    @rwd_msg	= nil
+
+		# Switches are used for checkboxes.
+
+    @rwd_switches.each do |key, value|
+      vars[key]	= "off"
+    end
+
+    @rwd_switches	= Hash.new
+
+		# Copy the vars from the window to vars. vars wil later on be copied to instance variables.
+
+    post.sort.each do |key, value|
+      puts "Post: #{key} -> #{value.from_html.inspect}"	if Debug
+
+      vars[key]	= value.from_html
+    end
+
+		# Stack handling for rwd_action and rwd_window.
+
+    @rwd_action			= vars["rwd_action"]
+    @rwd_action, @rwd_args	= @rwd_action.split(/\//, 2)	unless @rwd_action.nil?
+
+    if @rwd_action =~ /^rwd_tab_/
+      tab		= @rwd_action.sub(/^rwd_tab_/, "")
+    else
+      case @rwd_action
+      when "rwd_back"
+        @rwd_history.pop
+        @rwd_action			= (@rwd_history[-1] or [nil, nil])[0]
+        @rwd_window			= (@rwd_history[-1] or [nil, nil])[1]
+        back				= true
+      when "rwd_help"
+        help				= true
+      when "rwd_main"
+        @rwd_window			= "main"
+        @rwd_action			= "main"
+        @rwd_history			= []
+      when "rwd_quit"
+        done				= true
+      end
+
+		# History stuff
+
+      @rwd_history	= @rwd_history[-100..-1]	if @rwd_history.length >= 100
+      @rwd_action	= "main"			if @rwd_action.nil?
+      @rwd_action	= "main"			if @rwd_action.empty?
+      @rwd_args		= []				if @rwd_args.nil?
+      @rwd_window	= "main"			if @rwd_window.nil?
+
+      vars["rwd_action"]	= @rwd_action
+      vars["rwd_window"]	= @rwd_window
+
+		# Copy vars from window to instance.
+
+      vars.each do |k, v|
+        instance_eval "@#{k}	= vars[´#{k}´]"		if ((not k.empty?) and k.scan(/^rwd_/).empty? and not @rwd_ignore_vars.include?("@#{k}"))
+      end
+
+		# Callback.
+
+      if not back
+        begin
+          puts "Method: #{@rwd_action}(#{@rwdargs.join(", ")})"	if Debug
+          method(@rwd_action).call(*@rwd_args)
+        rescue NameError
+        end
+
+		# History stuff
+
+        @rwd_history	= [["main", "main"]]		if @rwd_action == "main"
+        @rwd_history	= [["main", "main"]]		if @rwd_history.empty?
+        @rwd_history.push [@rwd_action, @rwd_window]	if (@rwd_history[-1] != [@rwd_action, @rwd_window] or not @rwd_msg.nil?)
+      end
+    end
+
+		# Copy vars from instance to window.
+
+    instance_variables.each do |k|
+      k.sub!(/^@/, "")
+      instance_eval "vars[´#{k}´] = @#{k}.to_s"	if (k.scan(/^rwd_/).empty? and not @rwd_ignore_vars.include?("@#{k}"))
+    end
+
+		# just ignore.
+
+    vars.sort.each do |key, value|
+      puts "Pre: #{key} -> #{value.inspect}"	if Debug
+    end
+
+		# Answer to browser.
+
+    if done
+      res << RWDDone.new(@rwd_exitbrowser).render
+    else
+      if not @rwd_msg.nil?
+        res << RWDMessage.new(@rwd_msg).render		if @rwd_msgtype == "message"
+        res << RWDError.new(@rwd_msg).render		if @rwd_msgtype == "error"
+      else
+        puts "Window: #{@rwd_window}"			if Debug
+        res << RWDWindow.new(@rwd_xml, @rwd_window).render(vars, @rwd_switches, help, tab)
+      end
+    end
+
+    return done
+  end
+
+  def samewindow?
+    @rwd_history[-1][1] == @rwd_window
+  end
+
+  def message(msg)
+    @rwd_msg		= msg
+    @rwd_msgtype	= "message"
+  end
+
+  def error(msg)
+    @rwd_msg		= msg
+    @rwd_msgtype	= "error"
+  end
+
+  def clone
+    @rwd_history	= []
+
+    @rwd_clone_vars.each do |var|
+      instance_eval "#{var}	= #{var}.clone"
+    end
+
+    super
+  end
+
+  def exitbrowser
+    @rwd_exitbrowser	= true
+  end
+end
+
+class RWDLogin < RWDialog
+  def initialize(realm)
+    super("<window name=´main´ title=´RWD Login for #{realm}´ nobackbuttons noclosebutton><table><row><p align=´right´>Username:</p><text name=´rwd_a´/></row><row><p align=´right´>Password:</p><password name=´rwd_b´/></row></table><button caption=´Login´/></window>")
+  end
+end
+
+class RWDTimeOut < RWDialog
+  def initialize
+    super("<window name=´main´ title=´RWD Error´ nobackbuttons noclosebutton><p><b>Error:</b> Session has expired.</p><button caption=´New session´/></window>")
+  end
+end
+
+class SessionCleanup
+  def initialize(sessions, interval, timeout)
+    every(interval) do
+      sessions.delete_if do |id, session|
+        time	= Time.now.to_i - session.lastaccess.to_i
+
+        puts "Session %s deleted" % id	if time > timeout
+
+        time > timeout
+      end
+    end
+  end
+end
+
+class Sessions
+  def initialize(rack, cleanup)
+    @rack	= rack.to_s
+    @cleanup	= SessionCleanup.new(self, 3600, 24*3600)	if cleanup
+    @sessions	= {}
+    #@store	= PStore.new("#{temp}/store.#{@rack}.#{user}")
+
+    #@store.transaction do
+      #@store[@rack]	= {}	if not @store.root?(@rack)
+      #@sessions		= @store[@rack]
+    #end
+
+    #at_exit do
+      #@store.transaction do
+        #@store[@rack]	= @sessions
+      #end
+    #end
+  end
+
+  def [](sessionid)
+    @sessions[sessionid]
+  end
+
+  def []=(sessionid, value)
+    @sessions[sessionid]	= value
+  end
+
+  def delete(sessionid)
+    @sessions.delete(sessionid)
+  end
+
+  def delete_if(&block)
+    @sessions.delete_if{|k, v| block.call(k, v)}
+  end
+end
+
+class Session < Hash
+  attr_reader :sessionid
+  attr_reader :lastaccess
+  attr_reader :authenticated
+  attr_writer :authenticated
+
+  def initialize(sessionid=nil)
+    @sessionid		= sessionid
+    @lastaccess		= Time.now
+    @authenticated	= false
+  end
+
+  def touch
+    @lastaccess	= Time.now
+  end
+end
+
+class RWDSession < Session
+  def render(res, path, post)
+    done	= self["object"].render(res, path, post, @sessionid)
+
+    if done
+      res.gsub!(/\$RWD_SESSION\$/, "")
+    else
+      res.gsub!(/\$RWD_SESSION\$/, "#{@sessionid}")
+    end
+
+    done
+  end
+end
+
+class RWDServer
+  def initialize(obj, port, auth, realm)
+    @object		= obj
+    @localbrowsing	= false
+    @browserstarted	= false
+    @sessions		= Sessions.new(obj.class, (not auth.nil?))
+
+    if auth.nil?
+      @localbrowsing	= true
+
+      if ENV.include?("RWDBROWSER")
+        @browserstarted	= true
+        @object.exitbrowser
+
+	# Start browser.
+
+        @browserthread	= Thread.new do
+          puts "Starting the browser..."
+
+          #if ENV["RWDBROWSER"].downcase =~ /iexplore/
+            #@ie	= IE.new("http://localhost:#{port}/")
+          #else
+            if windows?
+              system("#{ENV["RWDBROWSER"]} \"http://localhost:#{port}/\"")
+            elsif cygwin?
+              system("#{ENV["RWDBROWSER"].gsub(/\\/, "/").gsub(/ /, "\ ")} \"http://localhost:#{port}/\"")
+            else
+              system("#{ENV["RWDBROWSER"]} \"http://localhost:#{port}/\"")
+            end
+          #end
+
+          puts "The browser has terminated."
+        end
+      end
+    end
+
+	# Start server.
+
+    catch :exit do
+      HTTPServer.serve(port, (not auth.nil?)) do |req, resp|
+        vars	= req.vars.dup
+
+        if auth.kind_of? String
+          file	= "#{home}/#{auth}"
+          auths	= {}
+          auths	= Hash.file(file)	if FileTest.file?(file)
+        else
+          auths	= auth
+        end
+  
+        oldsessionid	= vars["rwd_session"]
+  
+		  # Retrieve session.
+  
+        session	= @sessions[oldsessionid]
+  
+		  # Eventually create new session.
+  
+        if session.nil?
+          if auth.nil?
+            session		= RWDSession.new(MD5.new(req.peeraddr[3].to_s + @object.inspect.to_s).to_s)
+            session["object"]	= @object
+          else
+            session		= RWDSession.new(MD5.new(Time.new.to_s + req.peeraddr[3].to_s + @object.inspect.to_s).to_s)
+            session["object"]	= @object.clone
+          end
+  
+          if oldsessionid.nil? or oldsessionid.empty?
+            if not auth.nil? and not session.authenticated
+  
+		  # Check authentication
+  
+              us	= vars["rwd_a"]
+              pa	= vars["rwd_b"]
+  
+              if us.nil? or pa.nil? or auths[us] != pa
+                session		= RWDSession.new
+                session["object"]	= RWDLogin.new(realm)
+              else
+                session.authenticated		= true
+                @sessions[session.sessionid]	= session
+              end
+            else
+              @sessions[session.sessionid]	= session
+            end
+          else
+            session		= RWDSession.new
+            session["object"]	= RWDTimeOut.new
+          end
+  
+          vars	= {}
+        end
+  
+		  # Avoid timeout.
+  
+        session.touch
+  
+        if req.request.path == "/"
+  
+		  # Serve methods/callbacks.
+  
+		  # Build new page.
+  
+          res	= ""
+  
+          done	= session.render(res, req.request.path, vars)
+  
+          begin
+            resp["Content-Type"]	= "text/html"
+  
+            resp << res
+          rescue
+            puts "Sending response to browser failed."
+  
+            @sessions.delete(session.sessionid)
+          end
+  
+		  # Eventually delete this session.
+  
+          if done
+            @sessions.delete(session.sessionid)
+  
+            if @localbrowsing
+              resp.flush
+  
+              if @browserstarted and @browserthread.alive?
+                puts "Waiting for the browser to terminate..."
+  
+                @browserthread.join
+              end
+  
+              throw :exit
+            end
+          end
+  
+        else
+  
+		  # Serve files.
+  
+          if req.request.path == "/pixel.gif"
+            resp << RWD_Pixel
+          else
+            if (FileTest.file?(req.request.path.sub(/^\/*/, "")))
+              resp << File.new(req.request.path.sub(/^\/*/, ""), "rb").read	rescue nil
+            else
+              resp.response	= "HTTP/1.0 404 NOT FOUND"
+            end
+          end
+  
+        end
+      end
+    end
+  end
+end
+
+RWD_HTML	= "
+<!-- Generated by RubyWebDialog.                                               -->
+<!-- For more information, please contact Erik Veenstra <rwd@erikveen.dds.nl>. -->
+<html>
+  <head>
+    <title>%TITLE%</title>
+
+    <meta http-equiv=´Content-Type´ content=´text/html; charset=ISO-8859-15´>
+    <meta http-equiv=´Content-Style-Type´ content=´text/css´>
+
+    <link rel=´shortcut icon´ href=´%LOGO%´>
+
+    <style type=´text/css´>
+    <!--
+      a           { text-decoration : none               }
+      div.box     { border          : thin solid #AAAAAA }
+      div.box2    { border-top      : thin solid #AAAAAA }
+    //-->
+    </style>
+
+    <script type=´text/javascript´>
+    <!--
+      function BodyGo() {
+        $RWD_FOCUS$
+      }
+    //-->
+    </script>
+  </head>
+
+  <body onload=´BodyGo()´ link=´#000000´ vlink=´#000000´ alink=´#000000´>
+    <table align=´center´ border=´0´ cellspacing=´0´ cellpadding=´0´ width=´100%´ height=´100%´>
+      <tr align=´center´ valign=´middle´>
+        <td align=´center´>
+
+          <table align=´center´ border=´0´ cellspacing=´0´ cellpadding=´0´>
+
+            <tr align=´center´>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+            </tr>
+
+            <tr align=´center´>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+            </tr>
+
+            <tr align=´center´>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+            </tr>
+
+            <tr align=´center´>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+            </tr>
+
+            <tr align=´center´>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+            </tr>
+
+            <tr align=´center´>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+
+              <td align=´center´>
+
+                <table align=´center´ border=´0´ cellspacing=´0´ cellpadding=´0´>
+                  <tr align=´center´>
+                    <td align=´center´ bgcolor=´#444488´>
+
+                      <table align=´left´ border=´0´ cellspacing=´1´ cellpadding=´0´>
+                        <tr align=´center´>
+                          <td align=´border´><img src=´%LOGO%´ width=´14´ height=´14´></td>
+                          <td align=´center´><b><small><font color=´#FFFFFF´>&nbsp;%TITLE%&nbsp;</font></small></b></td>
+                        </tr>
+                      </table>
+
+                      <table align=´right´ border=´0´ cellspacing=´1´ cellpadding=´0´>
+                        <tr align=´center´>
+                          <!-- %HELPBUTTON%  --><td align=´center´ bgcolor=´#EEEEEE´><b><small><a href=´javascript:document.bodyform.rwd_action.value=\"rwd_help\";document.bodyform.submit();´>&nbsp;?&nbsp;</a></small></b></td>
+                          <!-- %BACKBUTTONS% --><td align=´center´ bgcolor=´#EEEEEE´><b><small><a href=´javascript:document.bodyform.rwd_action.value=\"rwd_main\";document.bodyform.submit();´>&nbsp;&lt;&lt;&nbsp;</a></small></b></td>
+                          <!-- %BACKBUTTONS% --><td align=´center´ bgcolor=´#EEEEEE´><b><small><a href=´javascript:document.bodyform.rwd_action.value=\"rwd_back\";document.bodyform.submit();´>&nbsp;&lt;&nbsp;</a></small></b></td>
+                          <!-- %CLOSEBUTTON% --><td align=´center´ bgcolor=´#EEEEEE´><b><small><a href=´javascript:document.bodyform.rwd_action.value=\"rwd_quit\";document.bodyform.submit();´>&nbsp;X&nbsp;</a></small></b></td>
+                        </tr>
+                      </table>
+
+                    </td>
+                  </tr>
+
+                  <tr align=´center´>
+                    <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+                  </tr>
+
+                  <tr align=´center´>
+                    <td align=´center´ bgcolor=´#CCCCCC´>
+                      <form name=´bodyform´ action=´/´ method=´post´>
+
+                        <table align=´center´ border=´0´ cellspacing=´3´ cellpadding=´0´>
+
+                          %BODY%
+
+                        </table>
+
+                        <input name=´rwd_action´ value=´$RWD_FIRSTACTION$´ type=´hidden´>
+                        <input name=´rwd_session´ value=´$RWD_SESSION$´ type=´hidden´>
+                      </form>
+                    </td>
+                  </tr>
+                </table>
+
+              </td>
+
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+            </tr>
+
+            <tr align=´center´>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+            </tr>
+
+            <tr align=´center´>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+            </tr>
+
+            <tr align=´center´>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´#EEEEEE´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+            </tr>
+
+            <tr align=´center´>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+            </tr>
+
+            <tr align=´center´>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´black´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+              <td align=´center´ bgcolor=´white´><img src=´pixel.gif´ height=´1´ width=´1´></td>
+            </tr>
+
+          </table>
+
+        </td>
+      </tr>
+    </table>
+  </body>
+</html>
+"
+
+RWD_Pixel	= "
+R0lGODlhAQABAOcAAAAAAAEBAQICAgMDAwQEBAUFBQYGBgcHBwgICAkJCQoK
+CgsLCwwMDA0NDQ4ODg8PDxAQEBERERISEhMTExQUFBUVFRYWFhcXFxgYGBkZ
+GRoaGhsbGxwcHB0dHR4eHh8fHyAgICEhISIiIiMjIyQkJCUlJSYmJicnJygo
+KCkpKSoqKisrKywsLC0tLS4uLi8vLzAwMDExMTIyMjMzMzQ0NDU1NTY2Njc3
+Nzg4ODk5OTo6Ojs7Ozw8PD09PT4+Pj8/P0BAQEFBQUJCQkNDQ0REREVFRUZG
+RkdHR0hISElJSUpKSktLS0xMTE1NTU5OTk9PT1BQUFFRUVJSUlNTU1RUVFVV
+VVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2Rk
+ZGVlZWZmZmdnZ2hoaGlpaWpqamtra2xsbG1tbW5ubm9vb3BwcHFxcXJycnNz
+c3R0dHV1dXZ2dnd3d3h4eHl5eXp6ent7e3x8fH19fX5+fn9/f4CAgIGBgYKC
+goODg4SEhIWFhYaGhoeHh4iIiImJiYqKiouLi4yMjI2NjY6Ojo+Pj5CQkJGR
+kZKSkpOTk5SUlJWVlZaWlpeXl5iYmJmZmZqampubm5ycnJ2dnZ6enp+fn6Cg
+oKGhoaKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq6ysrK2tra6urq+v
+r7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6+
+vr+/v8DAwMHBwcLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy8zMzM3N
+zc7Ozs/Pz9DQ0NHR0dLS0tPT09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb29zc
+3N3d3d7e3t/f3+Dg4OHh4eLi4uPj4+Tk5OXl5ebm5ufn5+jo6Onp6erq6uvr
+6+zs7O3t7e7u7u/v7/Dw8PHx8fLy8vPz8/T09PX19fb29vf39/j4+Pn5+fr6
++vv7+/z8/P39/f7+/v///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQB
+CgD/ACwAAAAAAQABAAAIBAD/BQQAOw==
+".unpack("m").shift
+
+RWD_HTML1, RWD_HTML2	= RWD_HTML.split(/^\s*%BODY%\s*\r*$/)
diff -ur rubywebdialogs-none.tar.gz/rubywebdialogs/lib/sgml.lib.rb rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/sgml.lib.rb
--- rubywebdialogs-none.tar.gz/rubywebdialogs/lib/sgml.lib.rb	2004-06-23 00:36:57.000000000 +0200
+++ rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/sgml.lib.rb	2004-04-18 14:20:31.000000000 +0200
@@ -0,0 +1,234 @@
+require "ev/tree"
+
+class SGMLObject < TreeObject
+  def to_s
+    res	= ""
+
+    parsetree("prechildren_to_s", "postchildren_to_s", res)
+
+    res
+  end
+
+  def to_h
+    res	= ""
+
+    parsetree("prechildren_to_sgml", "postchildren_to_sgml", res)
+
+    res
+  end
+end
+
+class Text < SGMLObject
+  def initialize(text)
+    super()
+    @text = text
+  end
+
+  def prechildren_to_s(res)
+    res << "#{@text}"
+  end
+
+  def prechildren_to_sgml(res)
+    res << "#{@text}"
+  end
+end
+
+class Comment < SGMLObject
+  def initialize(text)
+    super()
+    @text = text
+  end
+
+  def prechildren_to_sgml(res)
+    res << "#{@text}"
+  end
+end
+
+class Special < SGMLObject
+  def initialize(text)
+    super()
+    @text = text
+  end
+
+  def prechildren_to_sgml(res)
+    res << "#{@text}"
+  end
+end
+
+class Instruction < SGMLObject
+  def initialize(text)
+    super()
+    @text = text
+  end
+
+  def prechildren_to_sgml(res)
+    res << "#{@text}"
+  end
+end
+
+class Tag < SGMLObject
+  attr_reader :args
+  attr_writer :args
+
+  def initialize(subtype, args={})
+    super(subtype)
+    @args = args
+  end
+end
+
+class OpenTag < Tag
+  def initialize(*args)
+    super
+    @upordown = Down
+  end
+
+  def prechildren_to_sgml(res)
+    a	= [@subtype]
+
+    @args.each do |k, v|
+      if not v.include?("´")
+        a << "#{k}=´#{v}´"
+      else
+        if not v.include?(´"´)
+          a << "#{k}=\"#{v}\""
+        else
+          a << "#{k}=´#{v.gsub(/\´/, ´"´)}´"
+        end
+      end
+    end
+
+    res << "<#{a.join(" ")}>"
+  end
+
+  def postchildren_to_sgml(res)
+    res << "</#{@subtype}>"	if @closed
+  end
+end
+
+class CloseTag < Tag
+  def initialize(*args)
+    super
+    @upordown = Dummy
+  end
+end
+
+class SGML < Tree
+  def initialize(*args)
+    @tagcache	= {}
+
+    super
+  end
+
+  def buildobjects(string)
+    @objects = []
+
+    string.splitblocks(["<!--", "<!", "<?", "<"], ["-->", ">", "?>", ">"]).each do |type, s|
+      case type
+      when 0	then @objects << Text.new(s)
+      when 1	then @objects << Comment.new(s)
+      when 2	then @objects << Special.new(s)
+      when 3	then @objects << Instruction.new(s)
+      when 4
+
+        tag, args, open, close	= verwerktag1(s)
+
+        @objects << OpenTag.new(tag.dup, args.dup)	if open
+        @objects << CloseTag.new(tag.dup, args.dup)	if close
+      end
+    end
+  end
+
+  def verwerktag1(string)
+    res	= nil
+
+    if @tagcache.include? string
+      res	= @tagcache[string]
+
+    else
+      res	= verwerktag2(string)
+
+      @tagcache[string] = res
+    end
+
+    return res
+  end
+
+  def verwerktag2(string)
+    a	= []
+
+    string.splitblocks(["´", ´"´], ["´", ´"´]).collect do |type, s|
+      case type
+      when 0
+        if self.class.to_s == "HTML"
+          s.splitwords(["<", ">"]).each do |w|
+            d	= w.split("=", 2)
+
+            if d.length == 1
+              a << d[0]
+            else
+              a << d[0]	if not d[0].nil? and not d[0].empty?
+              a << "="
+              a << d[1]	if not d[1].nil? and not d[1].empty?
+            end
+          end
+        else
+          a.concat s.splitwords(["<", "/", "=", ">"])
+        end
+      when 1, 2	then a << s
+      end
+    end
+
+    a	= a[1..-2]
+    open	= false
+    close	= false
+
+    if not a.nil?
+      a = a[0].splitwords("/") + a[1..-1]
+
+      if a[0] == "/"
+        close	= true
+        a.shift
+      else
+        open	= true
+      end
+
+      if a[-1] == "/"
+        close	= true
+        a.pop
+      end
+
+      tag	= a.shift.downcase
+      args	= {}
+
+      while not a.length.zero?
+        if a.length >= 3 and a[1] == "="
+          key	= a.shift.downcase
+          dummy	= a.shift
+          value	= a.shift.noquotes
+          args[key]	= value
+        else
+          key	= a.shift.downcase
+          args[key]	= ""
+        end
+      end
+    end
+
+    return [tag, args, open, close]
+  end
+
+  def to_s
+    res	= ""
+
+    parsetree("prechildren_to_s", "postchildren_to_s", res)
+
+    res
+  end
+
+  def to_h
+    res	= ""
+
+    parsetree("prechildren_to_sgml", "postchildren_to_sgml", res)
+
+    res
+  end
+end
diff -ur rubywebdialogs-none.tar.gz/rubywebdialogs/lib/tree.lib.rb rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/tree.lib.rb
--- rubywebdialogs-none.tar.gz/rubywebdialogs/lib/tree.lib.rb	2004-06-23 00:36:57.000000000 +0200
+++ rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/tree.lib.rb	2004-04-18 14:20:31.000000000 +0200
@@ -0,0 +1,316 @@
+require "ev/ruby"
+require "ev/net"
+require "md5"
+require "thread"
+
+Same	= 0
+Down	= 1
+Up	= 2
+Dummy	= 3
+
+module TextArray
+  def textarray
+    @children.collect do |obj|
+      [obj.text] << obj.textarray
+    end.flatten.compact
+  end
+end
+
+
+module ParseTree
+  def parsetree(premethod="prechildren", postmethod="postchildren", *args)
+    if @visible
+      method(premethod).call(*args)	if respond_to?(premethod)
+
+      @children.each do |obj|
+        obj.parsetree(premethod, postmethod, *args)
+      end
+
+      method(postmethod).call(*args)	if respond_to?(postmethod)
+    end
+  end
+
+  #def parsetree(premethod="prechildren", postmethod="postchildren", *args)
+  #  stack	= [self]
+  #  done	= []
+  #
+  #  while not stack.empty?
+  #    obj	= stack.pop
+  #
+  #    if not done.include?(obj)
+  #      obj.method(premethod).call(*args)	if obj.respond_to?(premethod)
+  #
+  #      stack.push(obj)
+  #      done.push(obj)
+  #
+  #      stack.concat obj.children.reverse
+  #      #obj.children.reverse.each do |cobj|
+  #        #stack.push(cobj)
+  #      #end
+  #    else
+  #      obj.method(postmethod).call(*args)	if obj.respond_to?(postmethod)
+  #    end
+  #  end
+  #end
+end
+
+class TreeObject
+  attr_reader :subtype
+  attr_writer :subtype
+  attr_reader :upordown
+  attr_writer :upordown
+  attr_reader :level
+  attr_writer :level
+  attr_reader :parent
+  attr_writer :parent
+  attr_reader :children
+  attr_writer :children
+  attr_writer :closed
+  attr_writer :closed
+  attr_reader :text
+  attr_writer :text
+  attr_reader :visible
+  attr_writer :visible
+
+  include TextArray
+  include ParseTree
+
+  def initialize(subtype=nil)
+    @subtype	= subtype
+    @upordown	= Same
+    @level	= nil
+    @parent	= nil
+    @children	= []
+    @closed	= nil
+    @visible	= true
+  end
+
+  def inspect
+    parent, children	= @parent, @children
+
+    @parent, @children	= parent.id, children.collect{|obj| obj.id}
+
+    res = "  " * (level-1) + "#{self.class}(#{@subtype}) #{super}"
+
+    @parent, @children	= parent, children
+
+    res
+  end
+end
+
+class Tree
+  @@versie	= 1
+  @@mutex	= Mutex.new
+
+  attr_reader :data
+  attr_writer :data
+  attr_reader :parent
+  attr_writer :parent
+  attr_reader :children
+  attr_writer :children
+  attr_reader :visible
+  attr_writer :visible
+
+  include TextArray
+  include ParseTree
+
+  def initialize(string)
+    string = string.join("") if string.kind_of?(Array)
+
+    @data		= string
+    @parent		= nil
+    @children		= []
+    @objects		= []
+    @visible		= true
+    @checkvisibility	= false
+
+    buildobjects(string)
+    buildparents
+    buildchildren
+    markclosed
+    deletedummies
+
+    @checkvisibility	= true
+  end
+
+  def self.file(file)
+    new(File.new(file).readlines)
+  end
+
+  def self.location(url, form=Hash.new)
+    s	= HTTPClient.get(url, form)
+    s	= ""	if s.nil?
+    new(s)
+  end
+
+  def self.new_from_cache2(data)
+    new(data)
+  end
+
+  def self.new_from_cache(data)
+    hash	= MD5.new("#{@@versie} #{data}")
+
+    dir		= "#{temp}/evcache.#{user}/tree.new"
+    file	= "#{dir}/#{hash}"
+
+    tree	= nil
+
+    Dir.mkdirrec(dir)
+
+    if FileTest.file?(file)
+      @@mutex.synchronize do
+        tree	= Marshal.restore(File.new(file, "rb"))
+      end
+    else
+      tree	= new(data)
+
+      if not tree.nil?
+        @@mutex.synchronize do
+          File.open(file, "wb") {|f| Marshal.dump(tree, f)}
+        end
+      end
+    end
+
+    return tree
+  end
+
+  def inspect
+    @objects.collect do |obj|
+      obj.inspect
+    end.join("\n")
+  end
+
+  def buildobjects(string)
+    raise "Has to be defined in the subclass."
+  end
+
+  def buildparents
+    level	= 1
+    levels	= Hash.new
+    levels[0]	= nil
+    parse do |type, obj|
+      case obj.upordown
+      when Down
+        obj.level	= level
+        obj.parent	= levels[level-1]
+        levels[level]	= obj
+        level += 1
+      when Up, Dummy
+        pl = level
+        1.upto(level-1) do |l|
+          po = levels[l]
+          pl = l if po.subtype == obj.subtype
+        end
+        level = pl
+        obj.level	= level
+        obj.parent	= levels[level-1]
+      when Same
+        obj.level	= level
+        obj.parent	= levels[level-1]
+      end
+    end
+  end
+
+  def buildchildren
+    @objects.each do |obj|
+      obj.children = []
+    end
+
+    parse do |type, obj|
+      if not obj.parent.nil?
+        po = obj.parent
+        po.children << obj
+      else
+        @children << obj
+      end
+    end
+  end
+
+  def markclosed
+    ([self].concat @objects).each do |obj|
+      obj.children.each_index do |i|
+        co1		= obj.children[i]
+        co2		= obj.children[i+1]
+
+        co1.closed	= (not co2.nil? and co1.upordown == Down and (co2.upordown == Up or co2.upordown == Dummy) and co1.subtype == co2.subtype)
+      end
+    end
+  end
+
+  def deletedummies
+    ([self].concat @objects).each do |obj|
+      obj.children.delete_if do |obj2|
+        obj2.upordown == Dummy
+      end
+    end
+
+    @objects.delete_if do |obj|
+      obj.upordown == Dummy
+    end
+  end
+
+  def parse(types=[], subtypes=[])
+    types	= [types]	if types.class == Class
+    subtypes	= [subtypes]	if subtypes.class == String
+    hidelevel	= nil
+
+    @objects.each do |obj|
+      hidelevel	= obj.level		if (@checkvisibility and hidelevel.nil? and (not obj.visible))
+      hidelevel	= nil			if (@checkvisibility and (not hidelevel.nil?) and obj.visible and obj.level <= hidelevel)
+
+      if hidelevel.nil?
+        ok = false
+        if types.empty?
+          if subtypes.empty?
+            ok = true
+          else
+            subtypes.each do |st|
+              ok = true if obj.subtype == st
+            end
+          end
+        else
+          if subtypes.empty?
+            types.each do |t|
+              ok = true if obj.kind_of?(t)
+            end
+          else
+            types.each do |t|
+              subtypes.each do |st|
+                ok = true if obj.kind_of?(t) if obj.subtype == st
+              end
+            end
+          end
+        end
+
+        yield(obj.class.to_s, obj) if ok
+      end
+    end
+  end
+
+  def path(pad)
+    p	= self
+
+    pad.split(/\//).each do |deel|
+      tag, voorkomen	= deel.split(/:/)
+
+      if (not tag.nil?) and (not p.nil?)
+        voorkomen	= 1	if voorkomen.nil?
+        voorkomen	= voorkomen.to_i
+
+        teller	= 0
+        p2	= nil
+        p.children.each_index do |i|
+          if p.children[i].upordown == Down
+            if p.children[i].subtype.noquotes == tag.noquotes
+              teller	+= 1
+              p2		= p.children[i]	if teller == voorkomen
+            end
+          end
+        end
+        p	= p2
+      end
+    end
+
+    p
+  end
+end
diff -ur rubywebdialogs-none.tar.gz/rubywebdialogs/lib/xml.lib.rb rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/xml.lib.rb
--- rubywebdialogs-none.tar.gz/rubywebdialogs/lib/xml.lib.rb	2004-06-23 00:36:57.000000000 +0200
+++ rubywebdialogs-0.0.1.tar.gz/rubywebdialogs/lib/xml.lib.rb	2004-04-18 14:20:31.000000000 +0200
@@ -0,0 +1,4 @@
+require "ev/sgml"
+
+class XML < SGML
+end