XDCC-Fetch 1.386
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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>
|