cheri 0.0.2
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/MIT-LICENSE +20 -0
- data/README +98 -0
- data/Rakefile +121 -0
- data/examples/hello_world_1.rb +28 -0
- data/examples/table_1.rb +44 -0
- data/lib/cheri/awt.rb +41 -0
- data/lib/cheri/builder.rb +31 -0
- data/lib/cheri/builder/awt/connecter.rb +63 -0
- data/lib/cheri/builder/awt/constants.rb +1003 -0
- data/lib/cheri/builder/awt/main.rb +191 -0
- data/lib/cheri/builder/awt/types.rb +220 -0
- data/lib/cheri/builder/base.rb +533 -0
- data/lib/cheri/builder/config.rb +187 -0
- data/lib/cheri/builder/connecter.rb +386 -0
- data/lib/cheri/builder/context.rb +655 -0
- data/lib/cheri/builder/generator.rb +425 -0
- data/lib/cheri/builder/html/charsets.rb +154 -0
- data/lib/cheri/builder/html/common.rb +32 -0
- data/lib/cheri/builder/html/connecter.rb +57 -0
- data/lib/cheri/builder/html/element.rb +156 -0
- data/lib/cheri/builder/html/main.rb +116 -0
- data/lib/cheri/builder/html/types.rb +123 -0
- data/lib/cheri/builder/main.rb +483 -0
- data/lib/cheri/builder/swing/connecter.rb +141 -0
- data/lib/cheri/builder/swing/constants.rb +420 -0
- data/lib/cheri/builder/swing/main.rb +446 -0
- data/lib/cheri/builder/swing/types.rb +270 -0
- data/lib/cheri/builder/xml/charsets.rb +154 -0
- data/lib/cheri/builder/xml/common.rb +32 -0
- data/lib/cheri/builder/xml/connecter.rb +42 -0
- data/lib/cheri/builder/xml/element.rb +189 -0
- data/lib/cheri/builder/xml/main.rb +130 -0
- data/lib/cheri/builder/xml/types.rb +36 -0
- data/lib/cheri/cheri.rb +70 -0
- data/lib/cheri/cjx.rb +3 -0
- data/lib/cheri/explorer.rb +32 -0
- data/lib/cheri/explorer/explorer.rb +560 -0
- data/lib/cheri/html.rb +31 -0
- data/lib/cheri/image/Delete24.gif +0 -0
- data/lib/cheri/image/Find24.gif +0 -0
- data/lib/cheri/image/FindAgain24.gif +0 -0
- data/lib/cheri/image/Refresh24.gif +0 -0
- data/lib/cheri/image/Search24.gif +0 -0
- data/lib/cheri/image/Thumbs.db +0 -0
- data/lib/cheri/image/cheri_icon_16x16.png +0 -0
- data/lib/cheri/image/cheri_icon_24x24.png +0 -0
- data/lib/cheri/image/cheri_logo_medium.png +0 -0
- data/lib/cheri/image/close_10x10.png +0 -0
- data/lib/cheri/image/close_10x10s.png +0 -0
- data/lib/cheri/image/close_12x12.png +0 -0
- data/lib/cheri/image/close_14x14.png +0 -0
- data/lib/cheri/image/close_24x24.png +0 -0
- data/lib/cheri/image/close_dim2_12x12.png +0 -0
- data/lib/cheri/image/close_dim_12x12.png +0 -0
- data/lib/cheri/image/cls_tree.png +0 -0
- data/lib/cheri/image/con_tree.png +0 -0
- data/lib/cheri/image/jruby_14x16.png +0 -0
- data/lib/cheri/image/jruby_logo.png +0 -0
- data/lib/cheri/image/mod_tree.png +0 -0
- data/lib/cheri/image/obj_tree.png +0 -0
- data/lib/cheri/image/ruby_16x16.png +0 -0
- data/lib/cheri/image/vars_tree.png +0 -0
- data/lib/cheri/java.rb +26 -0
- data/lib/cheri/java/builder.rb +28 -0
- data/lib/cheri/java/builder/main.rb +407 -0
- data/lib/cheri/java/builder/util.rb +480 -0
- data/lib/cheri/java/java.rb +56 -0
- data/lib/cheri/jruby.rb +32 -0
- data/lib/cheri/jruby/explorer.rb +43 -0
- data/lib/cheri/jruby/explorer/common.rb +38 -0
- data/lib/cheri/jruby/explorer/dialogs.rb +383 -0
- data/lib/cheri/jruby/explorer/explorer.rb +904 -0
- data/lib/cheri/jruby/explorer/splash.rb +80 -0
- data/lib/cheri/jruby/explorer/viewer.rb +619 -0
- data/lib/cheri/jruby/explorer/viewers.rb +1057 -0
- data/lib/cheri/jruby/jruby.rb +59 -0
- data/lib/cheri/swing.rb +41 -0
- data/lib/cheri/xml.rb +31 -0
- metadata +135 -0
@@ -0,0 +1,425 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2007 William N Dortch <bill.dortch@gmail.com>
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
#
|
24
|
+
|
25
|
+
module Cheri
|
26
|
+
module Builder
|
27
|
+
|
28
|
+
class Generator
|
29
|
+
module Template
|
30
|
+
class << self
|
31
|
+
def append_features(clazz)
|
32
|
+
Cheri::Builder.module_included(@ext,clazz) if @ext
|
33
|
+
Cheri::Builder.module_included(self,clazz)
|
34
|
+
super
|
35
|
+
end
|
36
|
+
private :append_features
|
37
|
+
|
38
|
+
def factory
|
39
|
+
@fct
|
40
|
+
end
|
41
|
+
|
42
|
+
def connecter
|
43
|
+
@ctr
|
44
|
+
end
|
45
|
+
|
46
|
+
def consumer
|
47
|
+
@cns
|
48
|
+
end
|
49
|
+
end #self
|
50
|
+
end #Template
|
51
|
+
|
52
|
+
class TypeBuilder < Cheri::Builder::AbstractBuilder
|
53
|
+
def initialize(mod,clazz,*r,&k)
|
54
|
+
super(*r,&k)
|
55
|
+
@mod = mod
|
56
|
+
@clazz = clazz
|
57
|
+
end
|
58
|
+
# returns the module to which this builder belongs
|
59
|
+
def mod
|
60
|
+
@mod
|
61
|
+
end
|
62
|
+
def run
|
63
|
+
@obj = @clazz.new(*@args)
|
64
|
+
@ctx.call(self,&@blk) if @blk
|
65
|
+
@obj
|
66
|
+
end
|
67
|
+
end #TypeBuilder
|
68
|
+
|
69
|
+
class CherifyBuilder < Cheri::Builder::AbstractBuilder
|
70
|
+
def initialize(mod,ctx,sym,*args,&k)
|
71
|
+
raise Cheri.argument_error(args.length,1) unless args.length == 1
|
72
|
+
super(ctx,sym,*args,&k)
|
73
|
+
@mod = mod
|
74
|
+
@obj = args.first
|
75
|
+
end
|
76
|
+
def mod
|
77
|
+
@mod
|
78
|
+
end
|
79
|
+
def run
|
80
|
+
@ctx.call(self,&@blk) if @blk
|
81
|
+
@obj
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class CheriYieldBuilder < CherifyBuilder
|
86
|
+
def child?
|
87
|
+
false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class TypeFactory
|
92
|
+
def initialize(mod,types)
|
93
|
+
raise Cheri.type_error(types,Hash) unless Hash === types
|
94
|
+
@mod = mod
|
95
|
+
@types = types
|
96
|
+
@inv = types.invert
|
97
|
+
end
|
98
|
+
def builder(ctx,sym,*r,&k)
|
99
|
+
if (clazz = @types[sym])
|
100
|
+
TypeBuilder.new(@mod,clazz,ctx,sym,*r,&k)
|
101
|
+
elsif @inv[r.first.class]
|
102
|
+
if sym == :cherify
|
103
|
+
CherifyBuilder.new(@mod,ctx,sym,*r,&k)
|
104
|
+
elsif sym == :cheri_yield
|
105
|
+
CheriYieldBuilder.new(@mod,ctx,sym,*r,&k)
|
106
|
+
else
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
else
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end #TypeFactory
|
114
|
+
|
115
|
+
class AutoFactory
|
116
|
+
def initialize(mod,types)
|
117
|
+
raise Cheri.type_error(types,Hash) unless Hash === types
|
118
|
+
@mod = mod
|
119
|
+
@types = types
|
120
|
+
@inv = types.invert
|
121
|
+
end
|
122
|
+
def builder(ctx,sym,*r,&k)
|
123
|
+
if (clazz = @types[sym])
|
124
|
+
bld = clazz.new(ctx,sym,*r,&k)
|
125
|
+
elsif @inv[r.first.class]
|
126
|
+
if sym == :cherify
|
127
|
+
CherifyBuilder.new(@mod,ctx,sym,*r,&k)
|
128
|
+
elsif sym == :cheri_yield
|
129
|
+
CheriYieldBuilder.new(@mod,ctx,sym,*r,&k)
|
130
|
+
else
|
131
|
+
nil
|
132
|
+
end
|
133
|
+
else
|
134
|
+
nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end #AutoFactory
|
138
|
+
|
139
|
+
CamelCase = /([a-z])([A-Z])/ #:nodoc:
|
140
|
+
RubyCase = '\1_\2' #:nodoc:
|
141
|
+
Sep = '::' #:nodoc:
|
142
|
+
def initialize(*r,&k)
|
143
|
+
raise ArgumentError,"no args or block supplied" unless k || !r.empty?
|
144
|
+
raise ArgumentError,"no arguments permitted when block supplied" if k && !r.empty?
|
145
|
+
@args = r
|
146
|
+
@blk = k if k
|
147
|
+
end
|
148
|
+
|
149
|
+
def run
|
150
|
+
if @blk
|
151
|
+
eb = EvalBuilder.new(&@blk)
|
152
|
+
create_mod(eb)
|
153
|
+
else
|
154
|
+
# _really_ simple builder
|
155
|
+
@types = {}
|
156
|
+
@ctr = TypeConnecter.new
|
157
|
+
if Hash === @args.last
|
158
|
+
@args.pop.each_pair do |clazz,adder|
|
159
|
+
add_type(clazz,nil,adder)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
@args.each do |clazz|
|
163
|
+
add_type(clazz)
|
164
|
+
end
|
165
|
+
create_simple_mod
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def add_type(clazz,sym=nil,adder=:add)
|
170
|
+
raise Cheri.type_error(clazz,Class) unless Class === clazz
|
171
|
+
raise Cheri.type_error(sym,Symbol,String) if sym && !(Symbol === sym || String === sym)
|
172
|
+
raise Cheri.type_error(adder,Symbol,String) unless Symbol === adder || String === adder
|
173
|
+
sym ||= make_sym(clazz)
|
174
|
+
adder = adder.to_sym
|
175
|
+
warn "warning: redefining type #{sym} => #{clazz}" if @types[sym]
|
176
|
+
@types[sym] = clazz
|
177
|
+
@ctr.add_type(clazz).connect(Object,adder)
|
178
|
+
end
|
179
|
+
private :add_type
|
180
|
+
|
181
|
+
def make_sym(clazz)
|
182
|
+
if (s = (name = clazz.name).rindex(Sep))
|
183
|
+
name = name[s+2,name.length-s-2]
|
184
|
+
end
|
185
|
+
name.gsub(CamelCase,RubyCase).downcase!.to_sym
|
186
|
+
end
|
187
|
+
private :make_sym
|
188
|
+
|
189
|
+
def create_simple_mod
|
190
|
+
mod = Template.dup
|
191
|
+
mod.instance_variable_set(:@fct, fct = TypeFactory.new(mod,@types))
|
192
|
+
mod.const_set('Factory',fct)
|
193
|
+
mod.instance_variable_set(:@ctr,@ctr)
|
194
|
+
mod.const_set('Connecter',@ctr)
|
195
|
+
mod.instance_variable_set(:@cns,Cheri::Builder::DefaultConsumer)
|
196
|
+
mod.const_set('Consumer',Cheri::Builder::DefaultConsumer)
|
197
|
+
mod.send(:include,Cheri::Builder)
|
198
|
+
mod
|
199
|
+
end
|
200
|
+
private :create_simple_mod
|
201
|
+
|
202
|
+
def create_mod(eb)
|
203
|
+
mapped = eb.__mapped
|
204
|
+
unmapped = eb.__unmapped
|
205
|
+
ext = eb.__ext
|
206
|
+
pkg = eb.__pkg
|
207
|
+
tc = eb.__tc
|
208
|
+
# sc = eb.__sc
|
209
|
+
# this may be valid if the user is just adding connecters to an existing builder
|
210
|
+
if mapped.empty? && unmapped.empty? && !pkg && !(ext && tc)
|
211
|
+
raise BuilderException,"no build classes specified!"
|
212
|
+
end
|
213
|
+
# map any unmapped class names to symbols
|
214
|
+
unless unmapped.empty?
|
215
|
+
iv = mapped.invert
|
216
|
+
unmapped.each do |unm|
|
217
|
+
unless iv[unm]
|
218
|
+
sym = make_sym(unm)
|
219
|
+
if (dupl = mapped[sym])
|
220
|
+
warn "warning: derived symbol #{sym} (#{unm}) conflicts with symbol for #{dupl} -- ignoring"
|
221
|
+
else
|
222
|
+
mapped[sym] = unm
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# separate the Java classes (if any)
|
229
|
+
jmapped = nil
|
230
|
+
if !mapped.empty? && defined?Cheri::Java::Builder
|
231
|
+
jmapped = {}
|
232
|
+
mapped.each_pair do |sym,clazz|
|
233
|
+
jmapped[sym] = clazz if clazz.respond_to?(:java_class)
|
234
|
+
end
|
235
|
+
if jmapped.empty?
|
236
|
+
jmapped = nil
|
237
|
+
else
|
238
|
+
jmapped.each_key do |sym|
|
239
|
+
mapped.delete(sym)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# separate the auto classes (self-building, e.g. Cheri::Xml::Elem), if any
|
245
|
+
# doesn't (currently) apply to Java classes (and likely never will)
|
246
|
+
amapped = nil
|
247
|
+
unless mapped.empty?
|
248
|
+
amapped = {}
|
249
|
+
mapped.each_pair do |sym,clazz|
|
250
|
+
if clazz < Cheri::Builder::Frame
|
251
|
+
amapped[sym] = clazz
|
252
|
+
end
|
253
|
+
end
|
254
|
+
if amapped.empty?
|
255
|
+
amapped = nil
|
256
|
+
else
|
257
|
+
amapped.each_key do |sym|
|
258
|
+
mapped.delete(sym)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
mapped = nil if mapped.empty?
|
264
|
+
|
265
|
+
# create the module
|
266
|
+
mod = Template.dup
|
267
|
+
mod.send(:include,Cheri::Builder)
|
268
|
+
# determine if we need a SuperFactory
|
269
|
+
fcount = 0
|
270
|
+
fcount += 1 if mapped
|
271
|
+
fcount += 1 if jmapped
|
272
|
+
fcount += 1 if amapped
|
273
|
+
fcount += pkg.length if pkg
|
274
|
+
|
275
|
+
# setup the factory(s)
|
276
|
+
if fcount > 1
|
277
|
+
fct = SuperFactory.new do |f|
|
278
|
+
f << TypeFactory.new(mod,mapped) if mapped
|
279
|
+
f << AutoFactory.new(mod,amapped) if amapped
|
280
|
+
f << Cheri::Java::Builder::GenericBuilderFactory.new(mod,jmapped) if jmapped
|
281
|
+
pkg.each do |p|
|
282
|
+
f << Cheri::Java::Builder::PackageFactory.new(p,mod)
|
283
|
+
end if pkg
|
284
|
+
end
|
285
|
+
elsif mapped
|
286
|
+
fct = TypeFactory.new(mod,mapped)
|
287
|
+
elsif amapped
|
288
|
+
fct = AutoFactory.new(mod,amapped)
|
289
|
+
elsif jmapped
|
290
|
+
fct = Cheri::Java::Builder::GenericBuilderFactory.new(mod,jmapped)
|
291
|
+
elsif pkg
|
292
|
+
fct = Cheri::Java::Builder::PackageFactory.new(pkg.first,mod)
|
293
|
+
else
|
294
|
+
fct = nil
|
295
|
+
end
|
296
|
+
if fct
|
297
|
+
mod.instance_variable_set(:@fct,fct)
|
298
|
+
mod.const_set('Factory',fct)
|
299
|
+
end
|
300
|
+
|
301
|
+
# setup connecter
|
302
|
+
if tc
|
303
|
+
mod.instance_variable_set(:@ctr,tc)
|
304
|
+
mod.const_set('Connecter',tc)
|
305
|
+
end
|
306
|
+
|
307
|
+
# setup consumers - TODO: pkg builders?
|
308
|
+
if mapped || amapped || jmapped
|
309
|
+
if (amapped || mapped) && jmapped
|
310
|
+
cns = SuperConsumer[Cheri::Java::Builder::DefaultConsumer,Cheri::Builder::DefaultConsumer]
|
311
|
+
elsif amapped || mapped
|
312
|
+
cns = Cheri::Builder::DefaultConsumer
|
313
|
+
else
|
314
|
+
cns = Cheri::Java::Builder::DefaultConsumer
|
315
|
+
end
|
316
|
+
mod.instance_variable_set(:@cns,cns)
|
317
|
+
mod.const_set('Consumer',cns)
|
318
|
+
end
|
319
|
+
|
320
|
+
# setup extend builder, if any
|
321
|
+
ext ||= Cheri::Java::Builder if jmapped || pkg
|
322
|
+
if ext
|
323
|
+
mod.instance_variable_set(:@ext,ext)
|
324
|
+
mod.module_eval do
|
325
|
+
def self.extends
|
326
|
+
@ext
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
mod
|
331
|
+
end
|
332
|
+
private :create_mod
|
333
|
+
|
334
|
+
class EvalBuilder
|
335
|
+
keep = /^(__|=|<|>|class|to_s|eql\?|equal\?|inspect|instance_|respond_to\?)/
|
336
|
+
instance_methods.each do |m|
|
337
|
+
undef_method m unless m =~ keep
|
338
|
+
end
|
339
|
+
|
340
|
+
def initialize(*r,&k)
|
341
|
+
@__mapped = {}
|
342
|
+
@__unmapped = []
|
343
|
+
instance_eval(&k)
|
344
|
+
end
|
345
|
+
|
346
|
+
def __mapped
|
347
|
+
@__mapped
|
348
|
+
end
|
349
|
+
|
350
|
+
def __unmapped
|
351
|
+
@__unmapped
|
352
|
+
end
|
353
|
+
|
354
|
+
def __ext
|
355
|
+
@__ext
|
356
|
+
end
|
357
|
+
|
358
|
+
def __pkg
|
359
|
+
@__pkg
|
360
|
+
end
|
361
|
+
|
362
|
+
def __tc
|
363
|
+
@__tc
|
364
|
+
end
|
365
|
+
|
366
|
+
def extend_builder(bld)
|
367
|
+
return unless bld
|
368
|
+
raise BuilderException,"only one extend_builder may be specified" if @__ext
|
369
|
+
unless bld.respond_to?(:factory) || bld.respond_to?(:connecter) ||
|
370
|
+
bld.respond_to?(:consumer) || bld.respond_to?(:resolver)
|
371
|
+
raise ArgumentError,"not a valid builder: #{bld}"
|
372
|
+
end
|
373
|
+
@__ext = bld
|
374
|
+
end
|
375
|
+
|
376
|
+
def build(type,sym=nil)
|
377
|
+
raise Cheri.type_error(type,Class) unless Class === type
|
378
|
+
if sym
|
379
|
+
if Symbol === sym
|
380
|
+
add_mapped(type,sym)
|
381
|
+
elsif Array === sym
|
382
|
+
sym.each do |s|
|
383
|
+
raise Cheri.type_error(s,Symbol) unless Symbol === s
|
384
|
+
add_mapped(type,s)
|
385
|
+
end
|
386
|
+
else
|
387
|
+
raise Cheri.type_error(sym,Symbol,Array)
|
388
|
+
end
|
389
|
+
else
|
390
|
+
@__unmapped << type unless @__unmapped.include?(type)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
def add_mapped(type,sym)
|
395
|
+
warn "warning: redefining :#{sym} from #{@__mapped[sym]} to #{type}" if @__mapped[sym]
|
396
|
+
@__mapped[sym] = type
|
397
|
+
end
|
398
|
+
private :add_mapped
|
399
|
+
|
400
|
+
def build_package(str)
|
401
|
+
raise Cheri.type_error(str,String) unless String === str
|
402
|
+
raise BuilderException,"packages supported only for Java (JRuby)" unless defined?JRUBY_VERSION
|
403
|
+
require 'cheri/java/builder'
|
404
|
+
if @__pkg
|
405
|
+
@__pkg << str unless @__pkg.include?(str)
|
406
|
+
else
|
407
|
+
@__pkg = [str]
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
def type(mod,&k)
|
412
|
+
@__tc ||= TypeConnecter.new
|
413
|
+
@__tc.type(mod,&k)
|
414
|
+
end
|
415
|
+
alias_method :types, :type
|
416
|
+
alias_method :symbol, :type
|
417
|
+
alias_method :symbols, :type
|
418
|
+
|
419
|
+
|
420
|
+
end #EvalBuilder
|
421
|
+
|
422
|
+
end #Generator
|
423
|
+
|
424
|
+
end #Builder
|
425
|
+
end #Cheri
|
@@ -0,0 +1,154 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2007 William N Dortch <bill.dortch@gmail.com>
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
#
|
24
|
+
|
25
|
+
module Cheri
|
26
|
+
module Html
|
27
|
+
module Charsets
|
28
|
+
SPECIAL = /[\000-\010\013\014\016-\037\046\074\076\200-\377]/
|
29
|
+
HIBYTES = /[\200-\377]/
|
30
|
+
class << self
|
31
|
+
def special?(str)
|
32
|
+
str =~ SPECIAL
|
33
|
+
end
|
34
|
+
# Returns a Charset if +str+ requires translation, else +nil+
|
35
|
+
def charset(str)
|
36
|
+
return nil unless str =~ SPECIAL
|
37
|
+
if str =~ HIBYTES
|
38
|
+
Utf8.detect?(str) ? Utf8 : Win1252
|
39
|
+
else
|
40
|
+
Iso8859
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end #self
|
44
|
+
module Charset
|
45
|
+
def xlat(i,o)
|
46
|
+
m = @map
|
47
|
+
i.each_byte do |b| o << m[b]; end
|
48
|
+
end
|
49
|
+
def map
|
50
|
+
@map
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
module Win1252
|
55
|
+
extend Charset
|
56
|
+
@map = Array.new(256)
|
57
|
+
map = @map
|
58
|
+
0.upto(31) do |i| map[i] = 32; end
|
59
|
+
map[9] = ?\t
|
60
|
+
map[10] = ?\n
|
61
|
+
map[13] = ?\r
|
62
|
+
32.upto(127) do |i| map[i] = i; end
|
63
|
+
map[38] = '&'
|
64
|
+
map[60] = '<'
|
65
|
+
map[62] = '>'
|
66
|
+
# windows-1252 mappings
|
67
|
+
map[128] = '€'
|
68
|
+
map[129] = '?' #undefined
|
69
|
+
map[130] = '‚'
|
70
|
+
map[131] = 'ƒ'
|
71
|
+
map[132] = '„'
|
72
|
+
map[133] = '…'
|
73
|
+
map[134] = '†'
|
74
|
+
map[135] = '‡'
|
75
|
+
map[136] = 'ˆ'
|
76
|
+
map[137] = '‰'
|
77
|
+
map[138] = 'Š'
|
78
|
+
map[139] = '‹'
|
79
|
+
map[140] = 'Œ'
|
80
|
+
map[141] = '?' #undefined
|
81
|
+
map[142] = 'Ž'
|
82
|
+
map[143] = '?' #undefined
|
83
|
+
map[144] = '?' #undefined
|
84
|
+
map[145] = '‘'
|
85
|
+
map[146] = '’'
|
86
|
+
map[147] = '“'
|
87
|
+
map[148] = '”'
|
88
|
+
map[149] = '•'
|
89
|
+
map[150] = '–'
|
90
|
+
map[151] = '—'
|
91
|
+
map[152] = '˜'
|
92
|
+
map[153] = '™'
|
93
|
+
map[154] = 'š'
|
94
|
+
map[155] = '›'
|
95
|
+
map[156] = 'œ'
|
96
|
+
map[157] = '?' #undefined
|
97
|
+
map[158] = 'ž'
|
98
|
+
map[159] = 'Ÿ'
|
99
|
+
# 160-255 same for windows-1252 & ISO 8859-1 (Latin-1)
|
100
|
+
160.upto(255) do |i| map[i] = "&##{i};"; end
|
101
|
+
end
|
102
|
+
|
103
|
+
module Iso8859
|
104
|
+
extend Charset
|
105
|
+
# using same map for windows-1252 & ISO 8859-1, since the
|
106
|
+
# only detectable difference is use of 0x80-0x9f
|
107
|
+
@map = Win1252.map
|
108
|
+
end
|
109
|
+
|
110
|
+
module Utf8
|
111
|
+
extend Charset
|
112
|
+
|
113
|
+
# TODO: not quite correct for EO, F0, F4 ?
|
114
|
+
def self.detect?(str)
|
115
|
+
d = @detect
|
116
|
+
ct = 0
|
117
|
+
begin
|
118
|
+
str.each_byte do |b|
|
119
|
+
if b < 128
|
120
|
+
return false if ct > 0
|
121
|
+
elsif b < 192
|
122
|
+
return false if (ct -= 1) < 0
|
123
|
+
else
|
124
|
+
return false unless ct == 0
|
125
|
+
ct += d[b]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
ct == 0
|
129
|
+
rescue
|
130
|
+
false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
@map = Array.new(256)
|
135
|
+
map = @map
|
136
|
+
0.upto(31) do |i| map[i] = 32; end
|
137
|
+
map[9] = ?\t
|
138
|
+
map[10] = ?\n
|
139
|
+
map[13] = ?\r
|
140
|
+
32.upto(255) do |i| map[i] = i; end
|
141
|
+
map[38] = '&'
|
142
|
+
map[60] = '<'
|
143
|
+
map[62] = '>'
|
144
|
+
|
145
|
+
@detect = Array.new(256)
|
146
|
+
det = @detect
|
147
|
+
0x80.upto(0xBF) do |i| det[i] = -1; end
|
148
|
+
0xC2.upto(0xDF) do |i| det[i] = 1; end
|
149
|
+
0xE0.upto(0xEF) do |i| det[i] = 2; end
|
150
|
+
0xF0.upto(0xF4) do |i| det[i] = 3; end
|
151
|
+
end
|
152
|
+
end #Charsets
|
153
|
+
end #Html
|
154
|
+
end #Cheri
|