XDCC-Fetch 1.386
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +23 -0
- data/XDCC-Fetch.rbw +54 -0
- data/doc/ark.png +0 -0
- data/doc/connect_established.png +0 -0
- data/doc/index.html +300 -0
- data/doc/mega_ark.png +0 -0
- data/doc/package.png +0 -0
- data/doc/package_unknown.png +0 -0
- data/doc/shot1.png +0 -0
- data/doc/shot1_mini.png +0 -0
- data/doc/shot2.png +0 -0
- data/doc/shot2_mini.png +0 -0
- data/doc/xdccfetch.css +155 -0
- data/icons/ark.png +0 -0
- data/icons/ark_big.png +0 -0
- data/icons/camera_test.png +0 -0
- data/icons/cancel.png +0 -0
- data/icons/connect_creating.png +0 -0
- data/icons/connect_established.png +0 -0
- data/icons/connect_failed.png +0 -0
- data/icons/connect_no.png +0 -0
- data/icons/edit_add.png +0 -0
- data/icons/edit_remove.png +0 -0
- data/icons/exit.png +0 -0
- data/icons/fileclose.png +0 -0
- data/icons/folder_inbox.png +0 -0
- data/icons/idea.png +0 -0
- data/icons/mega_ark.png +0 -0
- data/icons/messagebox_critical.png +0 -0
- data/icons/messagebox_info.png +0 -0
- data/icons/messagebox_warning.png +0 -0
- data/icons/messagebox_warning_small.png +0 -0
- data/icons/package.png +0 -0
- data/icons/package_favourite.png +0 -0
- data/icons/package_unknown.png +0 -0
- data/src/Console/Console_Parser.rb +71 -0
- data/src/Console/XDCC_Pack_Match_Template.rb +29 -0
- data/src/Console/xdcc-fetch.rb +123 -0
- data/src/GUI/About_Dialog.rb +50 -0
- data/src/GUI/Application_Builder.rb +280 -0
- data/src/GUI/Context_Menu.rb +81 -0
- data/src/GUI/Custom_Tabs.rb +60 -0
- data/src/GUI/Dialog_Box.rb +116 -0
- data/src/GUI/Download_Finished_Box.rb +41 -0
- data/src/GUI/Empty_Text_Field_Handler.rb +86 -0
- data/src/GUI/Gui_Logic.rb +629 -0
- data/src/GUI/Icon_Loader.rb +58 -0
- data/src/GUI/Main_Window.rb +227 -0
- data/src/GUI/Packet_Item.rb +171 -0
- data/src/GUI/Packet_List.rb +145 -0
- data/src/GUI/Speed_Widget.rb +101 -0
- data/src/GUI/Talk_Back.rb +118 -0
- data/src/GUI/Toggle_Button.rb +56 -0
- data/src/Network/CTCP_Handler.rb +61 -0
- data/src/Network/DCC_File.rb +323 -0
- data/src/Network/DCC_Parser.rb +71 -0
- data/src/Network/IPAddr_Ext.rb +76 -0
- data/src/Network/IRC_Message.rb +161 -0
- data/src/Network/IRC_Server.rb +273 -0
- data/src/Network/IRC_Server_Respond_Map.rb +223 -0
- data/src/Network/IRC_User.rb +58 -0
- data/src/Network/TCP_Connection.rb +168 -0
- data/src/Network/XDCC_Announcement.rb +120 -0
- data/src/Network/XDCC_Announcement_Storage.rb +167 -0
- data/src/Network/XDCC_Download_Handler.rb +412 -0
- data/src/Network/XDCC_Pack.rb +58 -0
- data/src/Network/XDCC_Parser.rb +253 -0
- data/src/Translations/README +61 -0
- data/src/Translations/check_translations +83 -0
- data/src/Translations/de.rb +140 -0
- data/src/Translations/en.rb +145 -0
- data/src/Utilities/Configuration.rb +91 -0
- data/src/Utilities/Events.rb +87 -0
- data/src/Utilities/Globals.rb +138 -0
- data/src/Utilities/PrettyException.rb +1091 -0
- data/src/Utilities/Recursive_Open_Struct.rb +159 -0
- data/src/Utilities/Timer.rb +71 -0
- metadata +135 -0
@@ -0,0 +1,1091 @@
|
|
1
|
+
###################################################
|
2
|
+
# # # # # # # # # # # # # # # # # # # # # # # # # #
|
3
|
+
#
|
4
|
+
# = lib/PrettyException.rb
|
5
|
+
#
|
6
|
+
# PrettyPrint for Exceptions
|
7
|
+
#
|
8
|
+
# Author:: Dmitry V. Sabanin <sdmitry@lrn.ru>
|
9
|
+
# Revision:: $Date: 2004/12/20 05:11:50 $ $Revision: 1.16 $
|
10
|
+
# License:: LGPL
|
11
|
+
#
|
12
|
+
# Modified to use rdoc's templating by Michael Neumann (mneumann@ntecs.de).
|
13
|
+
#
|
14
|
+
# # # # # # # # # # # # # # # # # # # # # # # # # #
|
15
|
+
###################################################
|
16
|
+
|
17
|
+
require 'rdoc/template'
|
18
|
+
require 'rbconfig'
|
19
|
+
require 'cgi'
|
20
|
+
|
21
|
+
###################################################
|
22
|
+
# Web PrettyPrint for Exceptions
|
23
|
+
#
|
24
|
+
class PrettyException
|
25
|
+
|
26
|
+
attr_writer :message
|
27
|
+
|
28
|
+
###################################################
|
29
|
+
def initialize(exception, tplpath = nil)
|
30
|
+
@tplpath = tplpath
|
31
|
+
@exception = exception
|
32
|
+
@message = nil
|
33
|
+
end
|
34
|
+
###################################################
|
35
|
+
|
36
|
+
###################################################
|
37
|
+
def build_template
|
38
|
+
tmpl =
|
39
|
+
if @tplpath and File.exists?(@tplpath)
|
40
|
+
File.read(@tplpath)
|
41
|
+
else
|
42
|
+
tplfile = File.readlines(__FILE__)
|
43
|
+
start = nil
|
44
|
+
tplfile.each_with_index do |line,idx|
|
45
|
+
if line =~ /^__END__\s*$/
|
46
|
+
start = idx + 1
|
47
|
+
break
|
48
|
+
end
|
49
|
+
end
|
50
|
+
tplfile[start..-1].join('')
|
51
|
+
end
|
52
|
+
|
53
|
+
return TemplatePage.new(tmpl)
|
54
|
+
end
|
55
|
+
###################################################
|
56
|
+
|
57
|
+
###################################################
|
58
|
+
def gen_source(file, line, mark_line = true)
|
59
|
+
source = File.readlines(file)
|
60
|
+
source = hilite_source(source)
|
61
|
+
line = line.to_i
|
62
|
+
if mark_line
|
63
|
+
show = 3
|
64
|
+
begin_from = line - show
|
65
|
+
end_at = line + show
|
66
|
+
begin_from = begin_from > 0 ? begin_from : 0
|
67
|
+
work_with = source[begin_from..end_at]
|
68
|
+
else
|
69
|
+
work_with = [ source[line-1] ]
|
70
|
+
end
|
71
|
+
work_with ||= []
|
72
|
+
res = []
|
73
|
+
work_with.each do |i, l|
|
74
|
+
l = ('<span class="hl_lineno">%.3d:</span>%s' % [i," "]) + l
|
75
|
+
if i == line and mark_line
|
76
|
+
buf = '<div class="current_line">' + l + '</div>'
|
77
|
+
else
|
78
|
+
buf = l + "\n"
|
79
|
+
end
|
80
|
+
res << buf
|
81
|
+
end
|
82
|
+
res.join
|
83
|
+
end
|
84
|
+
###################################################
|
85
|
+
|
86
|
+
###################################################
|
87
|
+
def hilite_source(src)
|
88
|
+
lx = LexerRuby::LexerOld.new
|
89
|
+
src.each do |sline|
|
90
|
+
lx.lex_line(sline)
|
91
|
+
end
|
92
|
+
res = []
|
93
|
+
lineno = 0
|
94
|
+
this_line = []
|
95
|
+
hc = false
|
96
|
+
heredoc_buf = nil
|
97
|
+
lx.result.each do |text, token|
|
98
|
+
if hc
|
99
|
+
lineno += 1
|
100
|
+
res << [lineno, this_line.join]
|
101
|
+
this_line = []
|
102
|
+
hc = false
|
103
|
+
end
|
104
|
+
if token != :heredoc and heredoc_buf and token != :any
|
105
|
+
heredoc = heredoc_buf.split(/\n/)
|
106
|
+
heredoc.each do |hd_line|
|
107
|
+
res << [lineno, ('<span class="hl_heredoc">%s</span>' % [hd_line.to_s])]
|
108
|
+
lineno += 1
|
109
|
+
end
|
110
|
+
this_line = []
|
111
|
+
heredoc_buf = nil
|
112
|
+
end
|
113
|
+
case token
|
114
|
+
when :keyword, :ident, :punct,
|
115
|
+
:comment, :ivar, :dot,
|
116
|
+
:string, :command, :number,
|
117
|
+
:gvar, :literal, :symbol
|
118
|
+
if token == :comment
|
119
|
+
hc = true
|
120
|
+
end
|
121
|
+
text = CGI.escapeHTML(text)
|
122
|
+
this_line << ('<span class="hl_%s">%s</span>' % [token.to_s, text.rstrip])
|
123
|
+
when :heredoc
|
124
|
+
text = CGI.escapeHTML(text)
|
125
|
+
heredoc_buf ||= ''
|
126
|
+
heredoc_buf << text
|
127
|
+
when :any
|
128
|
+
if text =~ /^\s*\n$/
|
129
|
+
lineno += 1
|
130
|
+
res << [lineno, this_line.join]
|
131
|
+
this_line = []
|
132
|
+
else
|
133
|
+
this_line << text
|
134
|
+
end
|
135
|
+
else
|
136
|
+
this_line << CGI.escapeHTML(text)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
res << [lineno+1, this_line.join] if this_line.length > 0
|
140
|
+
res
|
141
|
+
end
|
142
|
+
###################################################
|
143
|
+
|
144
|
+
###################################################
|
145
|
+
def print
|
146
|
+
tpl = build_template
|
147
|
+
contents = {}
|
148
|
+
contents['message'] = CGI::escapeHTML(@exception.message).to_s
|
149
|
+
contents['exception'] = @exception.class.to_s
|
150
|
+
contents['time'] = Time.now.to_s
|
151
|
+
bt = []
|
152
|
+
@exception.backtrace.each_with_index do |str,idx|
|
153
|
+
file,text = str.scan(/^(.+):(.+)(?::(.+))?$/).flatten;
|
154
|
+
file,line = file.split(/:/)
|
155
|
+
unless line
|
156
|
+
line = text
|
157
|
+
text = nil
|
158
|
+
end
|
159
|
+
is_stdlib = false
|
160
|
+
paths = [Config::CONFIG['rubylibdir'], Config::CONFIG['sitedir']]
|
161
|
+
paths.each do |dir|
|
162
|
+
is_stdlib = true if (file =~ /#{Regexp::escape(dir)}/)
|
163
|
+
end
|
164
|
+
data = { 'file' => file, 'line' => line, 'text' => text, 'from_stdlib' => is_stdlib }
|
165
|
+
if idx == 0
|
166
|
+
data['source'] = gen_source(file, line)
|
167
|
+
else
|
168
|
+
data['source'] = gen_source(file, line)
|
169
|
+
end
|
170
|
+
data['iteration_id'] = idx.to_s
|
171
|
+
bt << data
|
172
|
+
end
|
173
|
+
contents['backtrace'] = bt
|
174
|
+
tpl.write_html_on(output='', contents)
|
175
|
+
output
|
176
|
+
end
|
177
|
+
###################################################
|
178
|
+
|
179
|
+
alias_method :to_s, :print
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
class LexerBase
|
184
|
+
def initialize
|
185
|
+
@states = []
|
186
|
+
@result = []
|
187
|
+
@result_endofline = nil
|
188
|
+
end
|
189
|
+
attr_reader :states, :result, :result_endofline
|
190
|
+
|
191
|
+
def set_states(states)
|
192
|
+
@states = states
|
193
|
+
end
|
194
|
+
def set_result(result)
|
195
|
+
@result = result
|
196
|
+
end
|
197
|
+
def format(text, state_output)
|
198
|
+
@result << [text, state_output]
|
199
|
+
end
|
200
|
+
def format_end(state_output)
|
201
|
+
@result_endofline = state_output
|
202
|
+
end
|
203
|
+
def match(regexp, output)
|
204
|
+
m = regexp.match(@text)
|
205
|
+
return false unless m
|
206
|
+
txt = @text.slice!(0, m.end(0))
|
207
|
+
format(txt, output)
|
208
|
+
true
|
209
|
+
end
|
210
|
+
def lex_line(text)
|
211
|
+
raise "derived class #{self.class} must overload #lex_line."
|
212
|
+
end
|
213
|
+
def self.profile
|
214
|
+
lines = IO.readlines(__FILE__)
|
215
|
+
lexer = self.new
|
216
|
+
puts "profiling the #{self.inspect} lexer (this may take some time)"
|
217
|
+
require 'profiler'
|
218
|
+
Profiler__.start_profile
|
219
|
+
lines.each do |line|
|
220
|
+
lexer.set_states([])
|
221
|
+
lexer.set_result([])
|
222
|
+
lexer.lex_line(line)
|
223
|
+
end
|
224
|
+
Profiler__.print_profile(STDOUT)
|
225
|
+
end
|
226
|
+
def self.benchmark
|
227
|
+
n = 10000
|
228
|
+
puts "benchmarking the lexers (computing #{n} lines " +
|
229
|
+
"with GC disabled)"
|
230
|
+
require 'benchmark'
|
231
|
+
Benchmark.bm(20) do |b|
|
232
|
+
lexer = LexerRuby::LexerOld.new
|
233
|
+
#=begin
|
234
|
+
lines = IO.readlines(__FILE__)
|
235
|
+
GC.disable
|
236
|
+
b.report("#{lexer.class}") do
|
237
|
+
n.times do |i|
|
238
|
+
lexer.set_states([])
|
239
|
+
lexer.set_result([])
|
240
|
+
lexer.lex_line(lines[i%lines.size].clone)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
#=begin
|
244
|
+
GC.enable
|
245
|
+
GC.start
|
246
|
+
lines = IO.readlines(__FILE__)
|
247
|
+
lexer = LexerRuby::LexerNew.new
|
248
|
+
GC.disable
|
249
|
+
b.report("#{lexer.class}") do
|
250
|
+
n.times do |i|
|
251
|
+
lexer.set_states([])
|
252
|
+
lexer.set_result([])
|
253
|
+
lexer.lex_line(lines[i%lines.size])
|
254
|
+
end
|
255
|
+
end
|
256
|
+
=begin
|
257
|
+
=end
|
258
|
+
GC.enable
|
259
|
+
GC.start
|
260
|
+
lines = IO.readlines(__FILE__)
|
261
|
+
lexer = LexerRuby::Lexer3.new
|
262
|
+
GC.disable
|
263
|
+
b.report("#{lexer.class}") do
|
264
|
+
n.times do |i|
|
265
|
+
lexer.set_states([])
|
266
|
+
lexer.set_result([])
|
267
|
+
lexer.lex_line(lines[i%lines.size])
|
268
|
+
end
|
269
|
+
end
|
270
|
+
GC.enable
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
module LexerText
|
276
|
+
|
277
|
+
class Lexer < LexerBase
|
278
|
+
RE_TAB = /\A\t+/
|
279
|
+
RE_NOTTAB = /\A[^\t]+/
|
280
|
+
def lex_line(text)
|
281
|
+
@text = text
|
282
|
+
until @text.empty?
|
283
|
+
if match(RE_TAB, :tab)
|
284
|
+
else
|
285
|
+
match(RE_NOTTAB, :text)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end # class Lexer
|
290
|
+
|
291
|
+
end # module LexerText
|
292
|
+
|
293
|
+
module LexerRuby
|
294
|
+
|
295
|
+
module State
|
296
|
+
|
297
|
+
class Base
|
298
|
+
end
|
299
|
+
|
300
|
+
class Heredoc < Base
|
301
|
+
def initialize(begin_tag, ignore_leading_spaces, interpolate=true)
|
302
|
+
@begin_tag = begin_tag
|
303
|
+
@ignore_leading_spaces = ignore_leading_spaces
|
304
|
+
@interpolate = interpolate
|
305
|
+
end
|
306
|
+
attr_reader :begin_tag, :ignore_leading_spaces, :interpolate
|
307
|
+
def ==(other)
|
308
|
+
(self.class == other.class) and
|
309
|
+
(@begin_tag == other.begin_tag) and
|
310
|
+
(@ignore_leading_spaces == other.ignore_leading_spaces) and
|
311
|
+
(@interpolate == other.interpolate)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
class Comment < Base
|
316
|
+
def ==(other)
|
317
|
+
(self.class == other.class)
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
class Endoffile < Base
|
322
|
+
def ==(other)
|
323
|
+
(self.class == other.class)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
end # module State
|
328
|
+
|
329
|
+
class NewerRubyLexer
|
330
|
+
RE_TOKENIZE = Regexp.new([
|
331
|
+
# TODO: @ivar
|
332
|
+
# TODO: @@cvar
|
333
|
+
# TODO: $gvar
|
334
|
+
# TODO: %literals %w(a b c) %Q|'"|
|
335
|
+
# TODO: :symbol
|
336
|
+
# TODO: ?x chars
|
337
|
+
# TODO: 0b01001 binary data
|
338
|
+
# TODO: 0x234af hex data
|
339
|
+
# TODO: keywords =begin defined?
|
340
|
+
# TODO: ruby puncturation .. ... && ||
|
341
|
+
# TODO: /regexp/
|
342
|
+
# TODO: __END__ tag
|
343
|
+
# TODO: illegal ruby heredoc which has space after end-tag
|
344
|
+
# TODO: illegal ruby puncturation &&& |||
|
345
|
+
# TODO: illegal ruby numbers 0x23Yab
|
346
|
+
'#.*', # # blah ## !?! comment
|
347
|
+
'<<-?[[:alpha:]]+', # <<HTML <<-XML heredoc
|
348
|
+
'<<-?\'[[:alpha:]]+\'', # <<'eof' <<-'X' heredoc single quoted
|
349
|
+
'<<-?"[[:alpha:]]+"', # <<"eof" <<-"X" heredoc double quoted
|
350
|
+
'\.[[:alpha:]][[:alnum:]_]*', # .method .dup2 method call
|
351
|
+
'[[:alpha:]][[:alnum:]_]*', # value pix2_3 identifier
|
352
|
+
'\'(?:[^\\\\]|\\\\.)*?\'', # '\'x\\' '' string single quoted
|
353
|
+
'"(?:[^\\\\]|\\\\.)*?"', # "ab" "" string double quoted
|
354
|
+
'\d+\.\d+', # 0.123 32.10 number as float
|
355
|
+
'\d+', # 42 999 number as integer
|
356
|
+
'.' # * + fallthrough
|
357
|
+
].join('|'))
|
358
|
+
def initialize
|
359
|
+
@char_to_symbol_hash = {
|
360
|
+
" " => :space,
|
361
|
+
"\t" => :tab
|
362
|
+
}
|
363
|
+
@char_to_symbol_hash.default = :should_not_happen
|
364
|
+
end
|
365
|
+
def tokenize(string)
|
366
|
+
string.scan(RE_TOKENIZE)
|
367
|
+
end
|
368
|
+
def lex(string)
|
369
|
+
tokens = tokenize(string)
|
370
|
+
states = tokens.map do |token|
|
371
|
+
# TODO: by inserting 2 parentesises in the TOKENIZER
|
372
|
+
# then I can destinguish between good/bad tokens.
|
373
|
+
# 'ab'.scan(/(a)(b)/) do |(good, bad)|
|
374
|
+
case token
|
375
|
+
when /\A(?:"|')./
|
376
|
+
:string
|
377
|
+
when /\A<<-?(?:"|'|)[[:alpha:]]/
|
378
|
+
:heredoc
|
379
|
+
when /\A\.[[:alpha:]]/
|
380
|
+
:method
|
381
|
+
when /\A[[:alpha:]]/
|
382
|
+
:ident
|
383
|
+
when /\A#/
|
384
|
+
:comment
|
385
|
+
when /\A[[:punct:]]/
|
386
|
+
:punct
|
387
|
+
when /\A[[:digit:]]/
|
388
|
+
:number
|
389
|
+
else
|
390
|
+
@char_to_symbol_hash[token]
|
391
|
+
end
|
392
|
+
end
|
393
|
+
[tokens, states]
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
class Lexer3 < LexerBase
|
398
|
+
def initialize
|
399
|
+
@rl = NewerRubyLexer.new
|
400
|
+
super
|
401
|
+
end
|
402
|
+
def what_to_output(hash)
|
403
|
+
@rl.what_to_output(hash)
|
404
|
+
end
|
405
|
+
def lex_line(text)
|
406
|
+
tokens, states = @rl.lex(text)
|
407
|
+
tokens.each_with_index do |token, index|
|
408
|
+
format(token, states[index])
|
409
|
+
end
|
410
|
+
true
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
|
415
|
+
class RubyLexer
|
416
|
+
def initialize
|
417
|
+
@result = []
|
418
|
+
end
|
419
|
+
attr_reader :result
|
420
|
+
PUNCT = ['(', ')'] +
|
421
|
+
%w(=== == =~ => = != !~ !) +
|
422
|
+
%w(<< <=> <= < >= >) +
|
423
|
+
%w({ } [ ]) +
|
424
|
+
%w(:: : ... ..) +
|
425
|
+
%w(+= + -= - ** * / %) +
|
426
|
+
%w(|| | && &) +
|
427
|
+
%w(, ;)
|
428
|
+
RE_NUMBER = /\d[\d\.]*/
|
429
|
+
RE_PUNCT = Regexp.new('(?:' +
|
430
|
+
PUNCT.map{|i| Regexp.escape(i)}.join('|') + ')')
|
431
|
+
RE_IDENT = /[[:alpha:]][\w\!]*/
|
432
|
+
RE_STRING = /".*?"|'.*?'/
|
433
|
+
RE_COMMENT = /#.*/
|
434
|
+
RE_COMMAND = /\.[[:alnum:]_]*[[:alnum:]_\?\!]/
|
435
|
+
RE_SPACE = /\x20+/
|
436
|
+
RE_NEWLINE = /\n+/
|
437
|
+
RE_TABS = /\t+/
|
438
|
+
def scan_index(string, regexp, prio, symbol)
|
439
|
+
string.scan(regexp) do
|
440
|
+
@result << [$~.begin(0), prio, $~.end(0), symbol]
|
441
|
+
end
|
442
|
+
end
|
443
|
+
def lex(string)
|
444
|
+
scan_index(string, RE_COMMENT, 0, :comment)
|
445
|
+
scan_index(string, RE_STRING, 1, :string)
|
446
|
+
scan_index(string, RE_COMMAND, 2, :command)
|
447
|
+
scan_index(string, RE_IDENT, 3, :ident)
|
448
|
+
scan_index(string, RE_NUMBER, 4, :number)
|
449
|
+
scan_index(string, RE_PUNCT, 5, :punct)
|
450
|
+
scan_index(string, RE_SPACE, 6, :space)
|
451
|
+
scan_index(string, RE_NEWLINE, 7, :newline)
|
452
|
+
scan_index(string, RE_TABS, 8, :tabs)
|
453
|
+
end
|
454
|
+
def result
|
455
|
+
# primary key = string begin position
|
456
|
+
# secondary key = priority
|
457
|
+
@result.sort!
|
458
|
+
# collect the highest precedens data
|
459
|
+
ary = [0]
|
460
|
+
@result.each do |i1, prio, i2, symbol|
|
461
|
+
next if ary.last > i1 # discard low precedens data
|
462
|
+
if ary.last < i1
|
463
|
+
ary << :any
|
464
|
+
ary << i1
|
465
|
+
end
|
466
|
+
ary << symbol
|
467
|
+
ary << i2
|
468
|
+
end
|
469
|
+
#p ary
|
470
|
+
ary
|
471
|
+
end
|
472
|
+
def self.mk(*symbols)
|
473
|
+
symbols.each do |symbol|
|
474
|
+
class_eval %{
|
475
|
+
def #{symbol.to_s}
|
476
|
+
res = []
|
477
|
+
@result.each do |i1, prio, i2, sym|
|
478
|
+
if sym == :#{symbol.to_s}
|
479
|
+
res << [i1, i2]
|
480
|
+
end
|
481
|
+
end
|
482
|
+
res
|
483
|
+
end
|
484
|
+
}
|
485
|
+
end
|
486
|
+
end
|
487
|
+
mk :number, :ident, :string, :punct
|
488
|
+
mk :comment, :command, :space, :newline, :tabs
|
489
|
+
end
|
490
|
+
|
491
|
+
class LexerNew < LexerBase
|
492
|
+
def lex_line(text)
|
493
|
+
#puts("-"*40)
|
494
|
+
#puts "text=#{text.inspect}"
|
495
|
+
rl = RubyLexer.new
|
496
|
+
rl.lex(text)
|
497
|
+
res = rl.result
|
498
|
+
#puts "res=#{res.inspect}"
|
499
|
+
i1 = res.shift
|
500
|
+
while res.size > 1
|
501
|
+
symbol = res.shift
|
502
|
+
i2 = res.shift
|
503
|
+
format(text[i1, (i2-i1)], symbol)
|
504
|
+
i1 = i2
|
505
|
+
end
|
506
|
+
#puts "result=#{@result.inspect}"
|
507
|
+
true
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
class LexerOld < LexerBase
|
512
|
+
RE_COMMENT = /^#.*/m
|
513
|
+
|
514
|
+
RE_TAB = /^\t+/
|
515
|
+
|
516
|
+
RE_SPACE = /^\x20+/
|
517
|
+
|
518
|
+
KEYWORDS = %w(alias and begin BEGIN break case class) +
|
519
|
+
%w(defined? def do else elsif end END ensure for if loop) +
|
520
|
+
%w(module next nil not or raise redo require rescue) +
|
521
|
+
%w(retry return self super then true false undef) +
|
522
|
+
%w(unless until yield when while)
|
523
|
+
RE_KEYWORD = Regexp.new(
|
524
|
+
'\A(?:' +
|
525
|
+
KEYWORDS.map{|txt|Regexp.escape(txt)}.join('|') +
|
526
|
+
')(?!\w)'
|
527
|
+
)
|
528
|
+
|
529
|
+
RE_SYMBOL = /\A:[[:alpha:]_][[:alnum:]_]*/
|
530
|
+
|
531
|
+
RE_STRING = /^("|\')(?:[^\\]|\\.)*?\1/
|
532
|
+
RE_STRING_INTERPOL = /\A ((?:[^\\]|\\.)*?) (\#\{ .*? \}) /x
|
533
|
+
# TODO: interpolated code can nest (hint: recursion is necessary)
|
534
|
+
def match_string
|
535
|
+
m = RE_STRING.match(@text)
|
536
|
+
return false unless m
|
537
|
+
txt = @text.slice!(0, m.end(0))
|
538
|
+
if m[1] == '\''
|
539
|
+
format(txt, :string)
|
540
|
+
return true
|
541
|
+
end
|
542
|
+
# double quoted strings may contain interpolated code
|
543
|
+
until txt.empty?
|
544
|
+
m = RE_STRING_INTERPOL.match(txt)
|
545
|
+
unless m
|
546
|
+
format(txt, :string)
|
547
|
+
break
|
548
|
+
end
|
549
|
+
format(m[1], :string) unless m[1].empty?
|
550
|
+
format(m[2], :string1)
|
551
|
+
txt.slice!(0, m.end(0))
|
552
|
+
end
|
553
|
+
true
|
554
|
+
end
|
555
|
+
|
556
|
+
RE_REGEXP = /\A\/(.*?[^\\])?\//
|
557
|
+
|
558
|
+
RE_IVAR = /\A@[[:alnum:]_]+/
|
559
|
+
|
560
|
+
RE_DOT = /\A\.[[:alnum:]_]*[[:alnum:]_\?\!]/
|
561
|
+
|
562
|
+
RE_IDENTIFIER = /\A(?:[[:alnum:]_]+|\S+)/
|
563
|
+
|
564
|
+
RE_NUMBER = Regexp.new(
|
565
|
+
'\A(?:' + [
|
566
|
+
'0x[_a-fA-F0-9]+',
|
567
|
+
'0b[_01]+',
|
568
|
+
'\d[0-9_]*(?:\.[0-9_]*)?',
|
569
|
+
'\?.'
|
570
|
+
].join('|') +
|
571
|
+
')'
|
572
|
+
)
|
573
|
+
|
574
|
+
PUNCT = ['(', ')'] +
|
575
|
+
%w(=== == =~ => = != !~ !) +
|
576
|
+
%w(<< <=> <= < >= >) +
|
577
|
+
%w({ } [ ]) +
|
578
|
+
%w(:: : ... ..) +
|
579
|
+
%w(+= + -= - ** * / %) +
|
580
|
+
%w(|| | && &) +
|
581
|
+
%w(, ;)
|
582
|
+
RE_PUNCT = Regexp.new(
|
583
|
+
'\A(?:' +
|
584
|
+
PUNCT.map{|txt|Regexp.escape(txt)}.join('|') +
|
585
|
+
')'
|
586
|
+
)
|
587
|
+
|
588
|
+
VAR_GLOBALS = %q(_~*$!@/\\;,.=:<>"-&`'+1234567890).split(//)
|
589
|
+
RE_GVAR = Regexp.new(
|
590
|
+
'\A\$(?:' +
|
591
|
+
VAR_GLOBALS.map{|txt|Regexp.escape(txt)}.join('|') +
|
592
|
+
'|[[:alnum:]_]+' +
|
593
|
+
')'
|
594
|
+
)
|
595
|
+
|
596
|
+
# TODO: deal with multiline literals
|
597
|
+
RE_LITERAL = Regexp.new(
|
598
|
+
'\A%[Qqwrx]?(?:' + [
|
599
|
+
'\(.*?\)', # TODO: must count pairs
|
600
|
+
'\{.*?\}', # TODO: must count pairs
|
601
|
+
'\<.*?\>', # TODO: must count pairs
|
602
|
+
'\[.*?\]', # TODO: must count pairs
|
603
|
+
'([^\(\{\<\[]).*?\1'
|
604
|
+
].join('|') + ')'
|
605
|
+
)
|
606
|
+
|
607
|
+
RE_BEGIN = /\A=begin$\n?\x20*\z/ # eat tailing space
|
608
|
+
def match_comment_begin
|
609
|
+
m = RE_BEGIN.match(@text)
|
610
|
+
return false unless m
|
611
|
+
#puts "comments"
|
612
|
+
@states << State::Comment.new
|
613
|
+
txt = @text.slice!(0, m.end(0))
|
614
|
+
format(txt, :mcomment)
|
615
|
+
format_end(:mcomment_end)
|
616
|
+
true
|
617
|
+
end
|
618
|
+
RE_HEREDOC = /\A<<(-)?('|"|)(\w+)\2/
|
619
|
+
def match_heredoc_begin
|
620
|
+
m = RE_HEREDOC.match(@text)
|
621
|
+
return false unless m
|
622
|
+
ignore_leading_space = (m[1] != nil)
|
623
|
+
interpolate = (m[2] != "'")
|
624
|
+
begin_pattern = m[3]
|
625
|
+
@states << State::Heredoc.new(
|
626
|
+
begin_pattern,
|
627
|
+
ignore_leading_space,
|
628
|
+
interpolate
|
629
|
+
)
|
630
|
+
txt = @text.slice!(0, m.end(0))
|
631
|
+
format(txt, :heredoc)
|
632
|
+
true
|
633
|
+
end
|
634
|
+
RE_END = /\A__END__$\n?\x20*\z/ # eat tailing space
|
635
|
+
def match_endoffile
|
636
|
+
m = RE_END.match(@text)
|
637
|
+
return false unless m
|
638
|
+
#puts "propagate __END__"
|
639
|
+
@states << State::Endoffile.new
|
640
|
+
txt = @text.slice!(0, m.end(0))
|
641
|
+
format(txt, :endoffile)
|
642
|
+
format_end(:endoffile_end)
|
643
|
+
true
|
644
|
+
end
|
645
|
+
def lex_line_normal(text)
|
646
|
+
@text = text
|
647
|
+
return if match_comment_begin
|
648
|
+
return if match_endoffile
|
649
|
+
until @text.empty?
|
650
|
+
if match(RE_COMMENT, :comment)
|
651
|
+
format_end(:comment_end)
|
652
|
+
elsif match(RE_REGEXP, :regexp)
|
653
|
+
elsif match_heredoc_begin
|
654
|
+
elsif match(RE_LITERAL, :literal)
|
655
|
+
elsif match(RE_KEYWORD, :keyword)
|
656
|
+
elsif match(RE_SYMBOL, :symbol)
|
657
|
+
elsif match(RE_PUNCT, :punct)
|
658
|
+
elsif match(RE_GVAR, :gvar)
|
659
|
+
elsif match_string
|
660
|
+
elsif match(RE_NUMBER, :number)
|
661
|
+
elsif match(RE_IVAR, :ivar)
|
662
|
+
elsif match(RE_DOT, :dot)
|
663
|
+
elsif match(RE_IDENTIFIER, :ident)
|
664
|
+
elsif match(RE_TAB, :tab)
|
665
|
+
elsif match(RE_SPACE, :space)
|
666
|
+
else
|
667
|
+
#@text.slice!(0, 1)
|
668
|
+
txt = @text.slice!(0, 1)
|
669
|
+
format(txt, :any)
|
670
|
+
end
|
671
|
+
end
|
672
|
+
end
|
673
|
+
def match_heredoc_end(regexp)
|
674
|
+
m = regexp.match(@text)
|
675
|
+
return false unless m
|
676
|
+
#puts "end of heredoc"
|
677
|
+
@states.shift
|
678
|
+
txt = @text.slice!(0, m.end(0))
|
679
|
+
format(txt, :heredoc)
|
680
|
+
format_end(:heredoc_end2)
|
681
|
+
true
|
682
|
+
end
|
683
|
+
def lex_line_heredoc(text)
|
684
|
+
# TODO: color interpolated code #{code}
|
685
|
+
@text = text
|
686
|
+
format_end(:heredoc_end)
|
687
|
+
hd_end = nil
|
688
|
+
state = @states[0]
|
689
|
+
hd_end = /\A#{state.begin_tag}$\n?\x20*\z/
|
690
|
+
return if match_heredoc_end(hd_end)
|
691
|
+
# continue lexing
|
692
|
+
ign_lead_spc = state.ignore_leading_spaces
|
693
|
+
until @text.empty?
|
694
|
+
if match(RE_TAB, :heredoc_tab)
|
695
|
+
elsif ign_lead_spc and match_heredoc_end(hd_end)
|
696
|
+
else
|
697
|
+
txt = @text.slice!(0, 1)
|
698
|
+
format(txt, :heredoc)
|
699
|
+
end
|
700
|
+
end
|
701
|
+
end
|
702
|
+
def match_comment_end
|
703
|
+
m = /\A\=end\b.*?$\n?\x20*\z/.match(@text)
|
704
|
+
return false unless m
|
705
|
+
#puts "comment end"
|
706
|
+
@states.shift
|
707
|
+
txt = @text.slice!(0, m.end(0))
|
708
|
+
format(txt, :mcomment)
|
709
|
+
true
|
710
|
+
end
|
711
|
+
def lex_line_comment(text)
|
712
|
+
@text = text
|
713
|
+
format_end(:mcomment_end)
|
714
|
+
return if match_comment_end
|
715
|
+
until @text.empty?
|
716
|
+
if match(RE_TAB, :mcomment_tab)
|
717
|
+
else
|
718
|
+
txt = @text.slice!(0, 1)
|
719
|
+
format(txt, :mcomment)
|
720
|
+
end
|
721
|
+
end
|
722
|
+
end
|
723
|
+
def lex_line_endoffile(text)
|
724
|
+
@text = text
|
725
|
+
format_end(:endoffile_end)
|
726
|
+
until @text.empty?
|
727
|
+
if match(RE_TAB, :endoffile_tab)
|
728
|
+
else
|
729
|
+
txt = @text.slice!(0, 1)
|
730
|
+
format(txt, :endoffile)
|
731
|
+
end
|
732
|
+
end
|
733
|
+
end
|
734
|
+
def lex_line(text)
|
735
|
+
if @states.empty?
|
736
|
+
return lex_line_normal(text)
|
737
|
+
end
|
738
|
+
state = @states[0]
|
739
|
+
case state
|
740
|
+
when State::Heredoc: lex_line_heredoc(text)
|
741
|
+
when State::Comment: lex_line_comment(text)
|
742
|
+
when State::Endoffile: lex_line_endoffile(text)
|
743
|
+
else
|
744
|
+
raise "unknown state #{state.class}"
|
745
|
+
end
|
746
|
+
end
|
747
|
+
end
|
748
|
+
|
749
|
+
# TODO: make the new lexer work!
|
750
|
+
Lexer = LexerOld # slow
|
751
|
+
#Lexer = LexerNew # slow
|
752
|
+
#Lexer = Lexer3 # fastest
|
753
|
+
|
754
|
+
end # module LexerRuby
|
755
|
+
|
756
|
+
__END__
|
757
|
+
<html>
|
758
|
+
<head>
|
759
|
+
<title>Oops!</title>
|
760
|
+
<style>
|
761
|
+
.data {
|
762
|
+
border-style: dotted;
|
763
|
+
padding: 4px; }
|
764
|
+
.trace_header {
|
765
|
+
border-style: dotted;
|
766
|
+
border-width: thin;
|
767
|
+
background-color: #CCCCCC;
|
768
|
+
text-align: center; }
|
769
|
+
.normal_trace_entry {
|
770
|
+
border-style: dotted;
|
771
|
+
border-width: thin;
|
772
|
+
text-align: center;
|
773
|
+
padding: 6px; }
|
774
|
+
.stdlib_trace_entry {
|
775
|
+
border-style: dotted;
|
776
|
+
border-width: thin;
|
777
|
+
text-align: right;
|
778
|
+
padding: 6px; }
|
779
|
+
.source {
|
780
|
+
width: 100%;
|
781
|
+
background-color: #F4F4F4;
|
782
|
+
display: none;
|
783
|
+
}
|
784
|
+
span.hl_lineno {
|
785
|
+
font-weight: bold;
|
786
|
+
}
|
787
|
+
pre {
|
788
|
+
width: 80%;
|
789
|
+
padding: 0px;
|
790
|
+
margin: 0px;
|
791
|
+
}
|
792
|
+
div.current_line {
|
793
|
+
color: red;
|
794
|
+
background-color: #F4DADA;
|
795
|
+
}
|
796
|
+
span.hl_keyword {
|
797
|
+
font-weight: bold;
|
798
|
+
}
|
799
|
+
span.hl_punct {
|
800
|
+
font-weight: bold;
|
801
|
+
color: darkblue;
|
802
|
+
}
|
803
|
+
span.hl_ident {
|
804
|
+
}
|
805
|
+
span.hl_command {
|
806
|
+
font-weight: bold;
|
807
|
+
}
|
808
|
+
span.hl_number {
|
809
|
+
color: darkgreen;
|
810
|
+
}
|
811
|
+
span.hl_string {
|
812
|
+
color: darkgreen;
|
813
|
+
}
|
814
|
+
span.hl_comment {
|
815
|
+
color: grey;
|
816
|
+
}
|
817
|
+
span.hl_ivar {
|
818
|
+
font-weight: bold;
|
819
|
+
color: darkred;
|
820
|
+
}
|
821
|
+
span.hl_dot {
|
822
|
+
font-weight: bold;
|
823
|
+
}
|
824
|
+
span.hl_literal {
|
825
|
+
color: green;
|
826
|
+
}
|
827
|
+
span.hl_gvar {
|
828
|
+
font-weight: bold;
|
829
|
+
}
|
830
|
+
span.hl_symbol {
|
831
|
+
color: blue;
|
832
|
+
}
|
833
|
+
span.hl_regexp {
|
834
|
+
color: green;
|
835
|
+
}
|
836
|
+
tr {
|
837
|
+
background-color: white;
|
838
|
+
}
|
839
|
+
</style>
|
840
|
+
<script type="text/javascript" language="javascript">
|
841
|
+
function toggleCode( id ) {
|
842
|
+
if ( document.getElementById )
|
843
|
+
elem = document.getElementById( id );
|
844
|
+
else if ( document.all )
|
845
|
+
elem = eval( "document.all." + id );
|
846
|
+
else
|
847
|
+
return false;
|
848
|
+
|
849
|
+
elemStyle = elem.style;
|
850
|
+
|
851
|
+
if ( elemStyle.display != "block" ) {
|
852
|
+
elemStyle.display = "block"
|
853
|
+
} else {
|
854
|
+
elemStyle.display = "none"
|
855
|
+
}
|
856
|
+
|
857
|
+
return true;
|
858
|
+
}
|
859
|
+
|
860
|
+
var isDOM = (typeof(document.getElementsByTagName) != 'undefined'
|
861
|
+
&& typeof(document.createElement) != 'undefined')
|
862
|
+
? 1 : 0;
|
863
|
+
var isIE4 = (typeof(document.all) != 'undefined'
|
864
|
+
&& parseInt(navigator.appVersion) >= 4)
|
865
|
+
? 1 : 0;
|
866
|
+
var isNS4 = (typeof(document.layers) != 'undefined')
|
867
|
+
? 1 : 0;
|
868
|
+
var capable = (isDOM || isIE4 || isNS4)
|
869
|
+
? 1 : 0;
|
870
|
+
// Uggly fix for Opera and Konqueror 2.2 that are half DOM compliant
|
871
|
+
if (capable) {
|
872
|
+
if (typeof(window.opera) != 'undefined') {
|
873
|
+
var browserName = ' ' + navigator.userAgent.toLowerCase();
|
874
|
+
if ((browserName.indexOf('konqueror 7') == 0)) {
|
875
|
+
capable = 0;
|
876
|
+
}
|
877
|
+
} else if (typeof(navigator.userAgent) != 'undefined') {
|
878
|
+
var browserName = ' ' + navigator.userAgent.toLowerCase();
|
879
|
+
if ((browserName.indexOf('konqueror') > 0) && (browserName.indexOf('konqueror/3') == 0)) {
|
880
|
+
capable = 0;
|
881
|
+
}
|
882
|
+
} // end if... else if...
|
883
|
+
} // end if
|
884
|
+
|
885
|
+
/**
|
886
|
+
* This array is used to remember mark status of rows in browse mode
|
887
|
+
*/
|
888
|
+
var marked_row = new Array;
|
889
|
+
|
890
|
+
|
891
|
+
/**
|
892
|
+
* Sets/unsets the pointer and marker in browse mode
|
893
|
+
*
|
894
|
+
* @param object the table row
|
895
|
+
* @param integer the row number
|
896
|
+
* @param string the action calling this script (over, out or click)
|
897
|
+
* @param string the default background color
|
898
|
+
* @param string the color to use for mouseover
|
899
|
+
* @param string the color to use for marking a row
|
900
|
+
*
|
901
|
+
* @return boolean whether pointer is set or not
|
902
|
+
*/
|
903
|
+
function setPointer(theRow, theRowNum, theAction, theDefaultColor, thePointerColor, theMarkColor)
|
904
|
+
{
|
905
|
+
var theCells = null;
|
906
|
+
|
907
|
+
// 1. Pointer and mark feature are disabled or the browser can't get the
|
908
|
+
// row -> exits
|
909
|
+
if ((thePointerColor == '' && theMarkColor == '')
|
910
|
+
|| typeof(theRow.style) == 'undefined') {
|
911
|
+
return false;
|
912
|
+
}
|
913
|
+
|
914
|
+
// 2. Gets the current row and exits if the browser can't get it
|
915
|
+
if (typeof(document.getElementsByTagName) != 'undefined') {
|
916
|
+
theCells = theRow.getElementsByTagName('td');
|
917
|
+
}
|
918
|
+
else if (typeof(theRow.cells) != 'undefined') {
|
919
|
+
theCells = theRow.cells;
|
920
|
+
}
|
921
|
+
else {
|
922
|
+
return false;
|
923
|
+
}
|
924
|
+
|
925
|
+
// 3. Gets the current color...
|
926
|
+
var rowCellsCnt = theCells.length;
|
927
|
+
var domDetect = null;
|
928
|
+
var currentColor = null;
|
929
|
+
var newColor = null;
|
930
|
+
// 3.1 ... with DOM compatible browsers except Opera that does not return
|
931
|
+
// valid values with "getAttribute"
|
932
|
+
if (typeof(window.opera) == 'undefined'
|
933
|
+
&& typeof(theCells[0].getAttribute) != 'undefined') {
|
934
|
+
currentColor = theCells[0].getAttribute('bgcolor');
|
935
|
+
domDetect = true;
|
936
|
+
}
|
937
|
+
// 3.2 ... with other browsers
|
938
|
+
else {
|
939
|
+
currentColor = theCells[0].style.backgroundColor;
|
940
|
+
domDetect = false;
|
941
|
+
} // end 3
|
942
|
+
|
943
|
+
// 3.3 ... Opera changes colors set via HTML to rgb(r,g,b) format so fix it
|
944
|
+
if (currentColor.indexOf("rgb") >= 0)
|
945
|
+
{
|
946
|
+
var rgbStr = currentColor.slice(currentColor.indexOf('(') + 1,
|
947
|
+
currentColor.indexOf(')'));
|
948
|
+
var rgbValues = rgbStr.split(",");
|
949
|
+
currentColor = "#";
|
950
|
+
var hexChars = "0123456789ABCDEF";
|
951
|
+
for (var i = 0; i < 3; i++)
|
952
|
+
{
|
953
|
+
var v = rgbValues[i].valueOf();
|
954
|
+
currentColor += hexChars.charAt(v/16) + hexChars.charAt(v%16);
|
955
|
+
}
|
956
|
+
}
|
957
|
+
|
958
|
+
// 4. Defines the new color
|
959
|
+
// 4.1 Current color is the default one
|
960
|
+
if (currentColor == ''
|
961
|
+
|| currentColor.toLowerCase() == theDefaultColor.toLowerCase()) {
|
962
|
+
if (theAction == 'over' && thePointerColor != '') {
|
963
|
+
newColor = thePointerColor;
|
964
|
+
}
|
965
|
+
else if (theAction == 'click' && theMarkColor != '') {
|
966
|
+
newColor = theMarkColor;
|
967
|
+
marked_row[theRowNum] = true;
|
968
|
+
// Garvin: deactivated onclick marking of the checkbox because it's also executed
|
969
|
+
// when an action (like edit/delete) on a single item is performed. Then the checkbox
|
970
|
+
// would get deactived, even though we need it activated. Maybe there is a way
|
971
|
+
// to detect if the row was clicked, and not an item therein...
|
972
|
+
// document.getElementById('id_rows_to_delete' + theRowNum).checked = true;
|
973
|
+
}
|
974
|
+
}
|
975
|
+
// 4.1.2 Current color is the pointer one
|
976
|
+
else if (currentColor.toLowerCase() == thePointerColor.toLowerCase()
|
977
|
+
&& (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum])) {
|
978
|
+
if (theAction == 'out') {
|
979
|
+
newColor = theDefaultColor;
|
980
|
+
}
|
981
|
+
else if (theAction == 'click' && theMarkColor != '') {
|
982
|
+
newColor = theMarkColor;
|
983
|
+
marked_row[theRowNum] = true;
|
984
|
+
// document.getElementById('id_rows_to_delete' + theRowNum).checked = true;
|
985
|
+
}
|
986
|
+
}
|
987
|
+
// 4.1.3 Current color is the marker one
|
988
|
+
else if (currentColor.toLowerCase() == theMarkColor.toLowerCase()) {
|
989
|
+
if (theAction == 'click') {
|
990
|
+
newColor = (thePointerColor != '')
|
991
|
+
? thePointerColor
|
992
|
+
: theDefaultColor;
|
993
|
+
marked_row[theRowNum] = (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum])
|
994
|
+
? true
|
995
|
+
: null;
|
996
|
+
// document.getElementById('id_rows_to_delete' + theRowNum).checked = false;
|
997
|
+
}
|
998
|
+
} // end 4
|
999
|
+
|
1000
|
+
// 5. Sets the new color...
|
1001
|
+
if (newColor) {
|
1002
|
+
var c = null;
|
1003
|
+
// 5.1 ... with DOM compatible browsers except Opera
|
1004
|
+
if (domDetect) {
|
1005
|
+
for (c = 0; c < rowCellsCnt; c++) {
|
1006
|
+
theCells[c].setAttribute('bgcolor', newColor, 0);
|
1007
|
+
} // end for
|
1008
|
+
}
|
1009
|
+
// 5.2 ... with other browsers
|
1010
|
+
else {
|
1011
|
+
for (c = 0; c < rowCellsCnt; c++) {
|
1012
|
+
theCells[c].style.backgroundColor = newColor;
|
1013
|
+
}
|
1014
|
+
}
|
1015
|
+
} // end 5
|
1016
|
+
|
1017
|
+
return true;
|
1018
|
+
} // end of the 'setPointer()' function
|
1019
|
+
|
1020
|
+
|
1021
|
+
/**
|
1022
|
+
* getElement
|
1023
|
+
*/
|
1024
|
+
function getElement(e,f){
|
1025
|
+
if(document.layers){
|
1026
|
+
f=(f)?f:self;
|
1027
|
+
if(f.document.layers[e]) {
|
1028
|
+
return f.document.layers[e];
|
1029
|
+
}
|
1030
|
+
for(W=0;i<f.document.layers.length;W++) {
|
1031
|
+
return(getElement(e,fdocument.layers[W]));
|
1032
|
+
}
|
1033
|
+
}
|
1034
|
+
if(document.all) {
|
1035
|
+
return document.all[e];
|
1036
|
+
}
|
1037
|
+
return document.getElementById(e);
|
1038
|
+
}
|
1039
|
+
</script>
|
1040
|
+
</head>
|
1041
|
+
<body bgcolor="white">
|
1042
|
+
<table cellspacing="4" width ="80%" align="center">
|
1043
|
+
<tr>
|
1044
|
+
<td colspan="3" align="left" class="normal_trace_entry">
|
1045
|
+
<p class="data" style="font-size: large; margin: 0px; border-color: red;"><b>Exception raised!</b><br />
|
1046
|
+
<b>%exception%</b>: <b>%message%</b><br />
|
1047
|
+
Time: <b>%time%</b>
|
1048
|
+
</p>
|
1049
|
+
</td>
|
1050
|
+
</tr>
|
1051
|
+
<tr>
|
1052
|
+
<td class="trace_header"><b>File</b></td>
|
1053
|
+
<td class="trace_header"><b>Line</b></td>
|
1054
|
+
<td class="trace_header"><b>Info</b></td>
|
1055
|
+
</tr>
|
1056
|
+
START:backtrace
|
1057
|
+
IFNOT:from_stdlib
|
1058
|
+
<tr bgcolor="white" onmouseover="setPointer(this, %iteration_id%, 'over', 'white', '#CCFFCC', '#FFB2B2');" onmouseout="setPointer(this, %iteration_id%, 'out', 'white', '#CCFFCC', '#FFB2B2');" onmousedown="toggleCode('src%iteration_id%'); setPointer(this, %iteration_id%, 'click', 'white', '#CCFFCC', '#FFB2B2');">
|
1059
|
+
IF:text
|
1060
|
+
<td bgcolor="white" class="normal_trace_entry">%file%</td>
|
1061
|
+
<td bgcolor="white" class="normal_trace_entry">%line%</td>
|
1062
|
+
<td bgcolor="white" class="normal_trace_entry">%text%</td>
|
1063
|
+
ENDIF:text
|
1064
|
+
IFNOT:text
|
1065
|
+
<td bgcolor="white" class="normal_trace_entry">%file%</td>
|
1066
|
+
<td bgcolor="white" class="normal_trace_entry" colspan="2">%line%</td>
|
1067
|
+
ENDIF:text
|
1068
|
+
IF:source
|
1069
|
+
</tr>
|
1070
|
+
<tr>
|
1071
|
+
<td colspan="3"><div id="src%iteration_id%" class="source"><tt><pre>%source%</pre></tt></div></td>
|
1072
|
+
ENDIF:source
|
1073
|
+
ENDIF:from_stdlib
|
1074
|
+
IF:from_stdlib
|
1075
|
+
<tr bgcolor="white" onmouseover="setPointer(this, %iteration_id%, 'over', 'white', '#CCFFCC', '#FFB2B2');" onmouseout="setPointer(this, %iteration_id%, 'out', 'white', '#CCFFCC', '#FFB2B2');" onmousedown="setPointer(this, %iteration_id%, 'click', 'white', '#CCFFCC', '#FFB2B2');">
|
1076
|
+
IF:text
|
1077
|
+
<td bgcolor="white" class="stdlib_trace_entry">%file%</td>
|
1078
|
+
<td bgcolor="white" class="stdlib_trace_entry">%line%</td>
|
1079
|
+
<td bgcolor="white" class="stdlib_trace_entry">%text%</td>
|
1080
|
+
ENDIF:text
|
1081
|
+
IFNOT:text
|
1082
|
+
<td bgcolor="white" class="stdlib_trace_entry">%file%</td>
|
1083
|
+
<td bgcolor="white" class="stdlib_trace_entry" colspan="2">%line%</td>
|
1084
|
+
ENDIF:text
|
1085
|
+
ENDIF:from_stdlib
|
1086
|
+
</tr>
|
1087
|
+
|
1088
|
+
END:backtrace
|
1089
|
+
</table>
|
1090
|
+
</body>
|
1091
|
+
</html>
|