fxri 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,63 +1,63 @@
1
- # Copyright (c) 2004, 2005 Martin Ankerl
2
- # Shows a grey text in an FXTextField if the user did not enter any input. This is a nice way to
3
- # give the user more information about what to enter into a text field, without the need of additional
4
- # space in the GUI.
5
- class Empty_Text_Field_Handler
6
-
7
- # Create a new handler for the specified textfield, with the given text. From now on you have to use the
8
- # created object to get and set text, not the textfield or this handler would come out of sync
9
- def initialize(textField, myText)
10
- @textField = textField
11
- @myText = myText
12
- @isEmpty = true
13
- onTextFieldFocusOut
14
- # create connections
15
- @textField.connect(SEL_FOCUSIN, method(:onTextFieldFocusIn))
16
- @textField.connect(SEL_FOCUSOUT, method(:onTextFieldFocusOut))
17
- end
18
-
19
- # Check if textfield is empty (no user input).
20
- def empty?
21
- @isEmpty
22
- end
23
-
24
- # Set new text for the textfield
25
- def text=(newText)
26
- onTextFieldFocusIn
27
- @textField.text = newText.to_s
28
- onTextFieldFocusOut
29
- end
30
-
31
- # Get the textfield's text, if the user has entered something.
32
- def text
33
- if empty? && !@inside
34
- ""
35
- else
36
- @textField.text
37
- end
38
- end
39
-
40
- # Set focus to the textfield.
41
- def setFocus
42
- @textField.setFocus
43
- end
44
-
45
- private
46
-
47
- def onTextFieldFocusIn(*args)
48
- @inside = true
49
- return if !@isEmpty
50
- @textField.textColor = FXColor::Black
51
- @textField.text = ""
52
- end
53
-
54
- def onTextFieldFocusOut(*args)
55
- @inside = false
56
- @textField.killSelection
57
- @isEmpty = @textField.text == ""
58
- return if !@isEmpty
59
- @textField.textColor = FXColor::DarkGrey
60
- @textField.text = @myText
61
- @isEmpty = true
62
- end
63
- end
1
+ # Copyright (c) 2004, 2005 Martin Ankerl
2
+ # Shows a grey text in an FXTextField if the user did not enter any input. This is a nice way to
3
+ # give the user more information about what to enter into a text field, without the need of additional
4
+ # space in the GUI.
5
+ class Empty_Text_Field_Handler
6
+
7
+ # Create a new handler for the specified textfield, with the given text. From now on you have to use the
8
+ # created object to get and set text, not the textfield or this handler would come out of sync
9
+ def initialize(textField, myText)
10
+ @textField = textField
11
+ @myText = myText
12
+ @isEmpty = true
13
+ onTextFieldFocusOut
14
+ # create connections
15
+ @textField.connect(SEL_FOCUSIN, method(:onTextFieldFocusIn))
16
+ @textField.connect(SEL_FOCUSOUT, method(:onTextFieldFocusOut))
17
+ end
18
+
19
+ # Check if textfield is empty (no user input).
20
+ def empty?
21
+ @isEmpty
22
+ end
23
+
24
+ # Set new text for the textfield
25
+ def text=(newText)
26
+ onTextFieldFocusIn
27
+ @textField.text = newText.to_s
28
+ onTextFieldFocusOut
29
+ end
30
+
31
+ # Get the textfield's text, if the user has entered something.
32
+ def text
33
+ if empty? && !@inside
34
+ ""
35
+ else
36
+ @textField.text
37
+ end
38
+ end
39
+
40
+ # Set focus to the textfield.
41
+ def setFocus
42
+ @textField.setFocus
43
+ end
44
+
45
+ private
46
+
47
+ def onTextFieldFocusIn(*args)
48
+ @inside = true
49
+ return if !@isEmpty
50
+ @textField.textColor = FXColor::Black
51
+ @textField.text = ""
52
+ end
53
+
54
+ def onTextFieldFocusOut(*args)
55
+ @inside = false
56
+ @textField.killSelection
57
+ @isEmpty = @textField.text == ""
58
+ return if !@isEmpty
59
+ @textField.textColor = FXColor::DarkGrey
60
+ @textField.text = @myText
61
+ @isEmpty = true
62
+ end
63
+ end
@@ -1,148 +1,148 @@
1
- class FoxDisplayer
2
- attr_accessor :reader
3
-
4
- def initialize(text_field)
5
- @text_field = text_field
6
- @formatter = FoxTextFormatter.new(70, "") do |arg, style|
7
- startpos = @str.size
8
- @str << arg
9
- @formats.push [startpos, arg.size, style]
10
- end
11
- @reader = nil
12
- end
13
-
14
- def width=(newWidth)
15
- @formatter.width = newWidth
16
- end
17
-
18
- def no_info_available
19
- @text_field.text="nothing here, move on!"
20
- end
21
-
22
- def init_text
23
- @str = ""
24
- @formats = Array.new
25
- end
26
-
27
- # Sets a new text, and all styles
28
- def set_text
29
- @text_field.text = @str
30
- @formats.each do |start, n, style|
31
- case style
32
- when FoxTextFormatter::STYLE_BOLD
33
- @text_field.changeStyle(start, n, 2)
34
- when FoxTextFormatter::STYLE_H1
35
- @text_field.changeStyle(start, n, 3)
36
- when FoxTextFormatter::STYLE_H2
37
- @text_field.changeStyle(start, n, 4)
38
- when FoxTextFormatter::STYLE_H3
39
- @text_field.changeStyle(start, n, 5)
40
- when FoxTextFormatter::STYLE_TELETYPE
41
- @text_field.changeStyle(start, n, 6)
42
- when FoxTextFormatter::STYLE_CODE
43
- @text_field.changeStyle(start, n, 7)
44
- when FoxTextFormatter::STYLE_EMPHASIS
45
- @text_field.changeStyle(start, n, 8)
46
- when FoxTextFormatter::STYLE_CLASS
47
- @text_field.changeStyle(start, n, 9)
48
- else
49
- @text_field.changeStyle(start, n, 1)
50
- end
51
-
52
- end
53
- end
54
-
55
- # Display method information
56
- def display_method_info(method)
57
- init_text
58
- @formatter.draw_line(method.full_name)
59
- @formatter.display_params(method)
60
- @formatter.draw_line
61
- display_flow(method.comment)
62
-
63
- if method.aliases && !method.aliases.empty?
64
- @formatter.blankline
65
- aka = "(also known as "
66
- aka << method.aliases.map {|a| a.name }.join(", ")
67
- aka << ")"
68
- @formatter.wrap(aka)
69
- end
70
- set_text
71
- end
72
-
73
- def display_information(message)
74
- init_text
75
- display_flow(message)
76
- set_text
77
- end
78
-
79
- def display_class_info(klass)
80
- init_text
81
- superclass = klass.superclass_string
82
- if superclass
83
- superclass = " < " + superclass
84
- else
85
- superclass = ""
86
- end
87
- @formatter.draw_line(klass.display_name + ": " + klass.full_name + superclass)
88
- display_flow(klass.comment)
89
- @formatter.draw_line
90
-
91
- unless klass.includes.empty?
92
- @formatter.blankline
93
- @formatter.display_heading("Includes:", 2, "")
94
- incs = []
95
- klass.includes.each do |inc|
96
- inc_desc = @reader.find_class_by_name(inc.name)
97
- if inc_desc
98
- str = inc.name + "("
99
- str << inc_desc.instance_methods.map{|m| m.name}.join(", ")
100
- str << ")"
101
- incs << str
102
- else
103
- incs << inc.name
104
- end
105
- end
106
- @formatter.wrap(incs.sort.join(', '))
107
- end
108
-
109
- unless klass.constants.empty?
110
- @formatter.blankline
111
- @formatter.display_heading("Constants:", 2, "")
112
- len = 0
113
- klass.constants.each { |c| len = c.name.length if c.name.length > len }
114
- len += 2
115
- klass.constants.each do |c|
116
- @formatter.wrap(c.value, @formatter.indent+((c.name+":").ljust(len)))
117
- end
118
- end
119
-
120
- unless klass.class_methods.empty?
121
- @formatter.blankline
122
- @formatter.display_heading("Class methods:", 2, "")
123
- @formatter.wrap(klass.class_methods.map{|m| m.name}.sort.join(', '))
124
- end
125
-
126
- unless klass.instance_methods.empty?
127
- @formatter.blankline
128
- @formatter.display_heading("Instance methods:", 2, "")
129
- @formatter.wrap(klass.instance_methods.map{|m| m.name}.sort.join(', '))
130
- end
131
-
132
- unless klass.attributes.empty?
133
- @formatter.blankline
134
- @formatter.wrap("Attributes:", "")
135
- @formatter.wrap(klass.attributes.map{|a| a.name}.sort.join(', '))
136
- end
137
-
138
- set_text
139
- end
140
-
141
- def display_flow(flow)
142
- if !flow || flow.empty?
143
- @formatter.wrap("(no description...)\n")
144
- else
145
- @formatter.display_flow(flow)
146
- end
147
- end
148
- end
1
+ class FoxDisplayer
2
+ attr_accessor :reader
3
+
4
+ def initialize(text_field)
5
+ @text_field = text_field
6
+ @formatter = FoxTextFormatter.new(70, "") do |arg, style|
7
+ startpos = @str.size
8
+ @str << arg
9
+ @formats.push [startpos, arg.size, style]
10
+ end
11
+ @reader = nil
12
+ end
13
+
14
+ def width=(newWidth)
15
+ @formatter.width = newWidth
16
+ end
17
+
18
+ def no_info_available
19
+ @text_field.text="nothing here, move on!"
20
+ end
21
+
22
+ def init_text
23
+ @str = ""
24
+ @formats = Array.new
25
+ end
26
+
27
+ # Sets a new text, and all styles
28
+ def set_text
29
+ @text_field.text = @str
30
+ @formats.each do |start, n, style|
31
+ case style
32
+ when FoxTextFormatter::STYLE_BOLD
33
+ @text_field.changeStyle(start, n, 2)
34
+ when FoxTextFormatter::STYLE_H1
35
+ @text_field.changeStyle(start, n, 3)
36
+ when FoxTextFormatter::STYLE_H2
37
+ @text_field.changeStyle(start, n, 4)
38
+ when FoxTextFormatter::STYLE_H3
39
+ @text_field.changeStyle(start, n, 5)
40
+ when FoxTextFormatter::STYLE_TELETYPE
41
+ @text_field.changeStyle(start, n, 6)
42
+ when FoxTextFormatter::STYLE_CODE
43
+ @text_field.changeStyle(start, n, 7)
44
+ when FoxTextFormatter::STYLE_EMPHASIS
45
+ @text_field.changeStyle(start, n, 8)
46
+ when FoxTextFormatter::STYLE_CLASS
47
+ @text_field.changeStyle(start, n, 9)
48
+ else
49
+ @text_field.changeStyle(start, n, 1)
50
+ end
51
+
52
+ end
53
+ end
54
+
55
+ # Display method information
56
+ def display_method_info(method)
57
+ init_text
58
+ @formatter.draw_line(method.full_name)
59
+ @formatter.display_params(method)
60
+ @formatter.draw_line
61
+ display_flow(method.comment)
62
+
63
+ if method.aliases && !method.aliases.empty?
64
+ @formatter.blankline
65
+ aka = "(also known as "
66
+ aka << method.aliases.map {|a| a.name }.join(", ")
67
+ aka << ")"
68
+ @formatter.wrap(aka)
69
+ end
70
+ set_text
71
+ end
72
+
73
+ def display_information(message)
74
+ init_text
75
+ display_flow(message)
76
+ set_text
77
+ end
78
+
79
+ def display_class_info(klass)
80
+ init_text
81
+ superclass = klass.superclass_string
82
+ if superclass
83
+ superclass = " < " + superclass
84
+ else
85
+ superclass = ""
86
+ end
87
+ @formatter.draw_line(klass.display_name + ": " + klass.full_name + superclass)
88
+ display_flow(klass.comment)
89
+ @formatter.draw_line
90
+
91
+ unless klass.includes.empty?
92
+ @formatter.blankline
93
+ @formatter.display_heading("Includes:", 2, "")
94
+ incs = []
95
+ klass.includes.each do |inc|
96
+ inc_desc = @reader.find_class_by_name(inc.name)
97
+ if inc_desc
98
+ str = inc.name + "("
99
+ str << inc_desc.instance_methods.map{|m| m.name}.join(", ")
100
+ str << ")"
101
+ incs << str
102
+ else
103
+ incs << inc.name
104
+ end
105
+ end
106
+ @formatter.wrap(incs.sort.join(', '))
107
+ end
108
+
109
+ unless klass.constants.empty?
110
+ @formatter.blankline
111
+ @formatter.display_heading("Constants:", 2, "")
112
+ len = 0
113
+ klass.constants.each { |c| len = c.name.length if c.name.length > len }
114
+ len += 2
115
+ klass.constants.each do |c|
116
+ @formatter.wrap(c.value, @formatter.indent+((c.name+":").ljust(len)))
117
+ end
118
+ end
119
+
120
+ unless klass.class_methods.empty?
121
+ @formatter.blankline
122
+ @formatter.display_heading("Class methods:", 2, "")
123
+ @formatter.wrap(klass.class_methods.map{|m| m.name}.sort.join(', '))
124
+ end
125
+
126
+ unless klass.instance_methods.empty?
127
+ @formatter.blankline
128
+ @formatter.display_heading("Instance methods:", 2, "")
129
+ @formatter.wrap(klass.instance_methods.map{|m| m.name}.sort.join(', '))
130
+ end
131
+
132
+ unless klass.attributes.empty?
133
+ @formatter.blankline
134
+ @formatter.wrap("Attributes:", "")
135
+ @formatter.wrap(klass.attributes.map{|a| a.name}.sort.join(', '))
136
+ end
137
+
138
+ set_text
139
+ end
140
+
141
+ def display_flow(flow)
142
+ if !flow || flow.empty?
143
+ @formatter.wrap("(no description...)\n")
144
+ else
145
+ @formatter.display_flow(flow)
146
+ end
147
+ end
148
+ end
@@ -1,275 +1,275 @@
1
- # This class is mostly copy & paste from ri_formatter.rb.
2
- # except that it always returns a string and does not print anything.
3
- class FoxTextFormatter
4
- # define all possible styles
5
- STYLE_NORMAL = :STYLE_NORMAL
6
- STYLE_BOLD = :STYLE_BOLD
7
- STYLE_CLASS = :STYLE_CLASS
8
- STYLE_H1 = :STYLE_H1
9
- STYLE_H2 = :STYLE_H2
10
- STYLE_H3 = :STYLE_H3
11
- STYLE_TELETYPE = :STYLE_TELETYPE
12
- STYLE_CODE = :STYLE_CODE
13
- STYLE_EMPHASIS = :STYLE_EMPHASIS
14
-
15
- attr_reader :indent
16
- attr_accessor :width
17
-
18
- # whenever text should be printed/added/shown, proc is called with the text as the argument.
19
- def initialize(width, indent, &proc)
20
- @width = width
21
- @indent = indent
22
- @proc = proc
23
- end
24
-
25
- ######################################################################
26
-
27
- def draw_line(label=nil)
28
- len = @width
29
- len -= (label.size+1) if label
30
- len = [0, len].max
31
- @proc.call("-"*len)
32
- if label
33
- @proc.call(" ")
34
- @proc.call(label, STYLE_CLASS)
35
- end
36
- @proc.call("\n")
37
- end
38
-
39
- def display_params(method)
40
- params = method.params
41
-
42
- if params[0] == ?(
43
- if method.is_singleton
44
- params = method.full_name + params
45
- else
46
- params = method.name + params
47
- end
48
- end
49
- params.split(/\n/).each do |param|
50
- @proc.call(param+"\n", STYLE_BOLD)
51
- end
52
- end
53
-
54
- def wrap(txt, prefix=@indent, linelen=@width)
55
- return if !txt || txt.empty?
56
- @proc.call(prefix, STYLE_EMPHASIS)
57
- conv_markup(txt, prefix, linelen)
58
- =begin
59
- textLen = linelen - prefix.length
60
- patt = Regexp.new("^(.{0,#{textLen}})[ \n]")
61
- next_prefix = prefix.tr("^ ", " ")
62
-
63
- res = []
64
-
65
- while work.length > textLen
66
- if work =~ patt
67
- res << $1
68
- work.slice!(0, $&.length)
69
- else
70
- res << work.slice!(0, textLen)
71
- end
72
- end
73
- res << work if work.length.nonzero?
74
- @proc.call(prefix + res.join("\n" + next_prefix) + "\n")
75
- =end
76
- end
77
-
78
- ######################################################################
79
-
80
- def blankline
81
- @proc.call("\n")
82
- end
83
-
84
- ######################################################################
85
-
86
- # called when we want to ensure a nbew 'wrap' starts on a newline
87
- # Only needed for HtmlFormatter, because the rest do their
88
- # own line breaking
89
-
90
- def break_to_newline
91
- end
92
-
93
- ######################################################################
94
-
95
- def bold_print(txt)
96
- @proc.call(txt, STYLE_BOLD)
97
- end
98
-
99
- ######################################################################
100
-
101
- def raw_print_line(txt)
102
- @proc.call(txt)
103
- end
104
-
105
- ######################################################################
106
-
107
- # convert HTML entities back to ASCII
108
- def conv_html(txt)
109
- case txt
110
- when Array
111
- txt.join.
112
- gsub(/&gt;/, '>').
113
- gsub(/&lt;/, '<').
114
- gsub(/&quot;/, '"').
115
- gsub(/&amp;/, '&')
116
- else # it's a String
117
- txt.
118
- gsub(/&gt;/, '>').
119
- gsub(/&lt;/, '<').
120
- gsub(/&quot;/, '"').
121
- gsub(/&amp;/, '&')
122
- end
123
- end
124
-
125
- # convert markup into display form
126
- def conv_markup(txt, prefix, linelen)
127
-
128
- # this code assumes that tags are not used inside tags
129
- pos = 0
130
- old_pos = 0
131
- style = STYLE_NORMAL
132
- current_indent = prefix.size
133
- while pos = txt.index(%r{(<tt>|<code>|<b>|<em>|</tt>|</code>|</b>|</em>)}, old_pos)
134
- new_part = txt[old_pos...pos]
135
- @proc.call(new_part, style)
136
-
137
- # get tag name
138
- old_pos = txt.index(">", pos) + 1
139
- style = case txt[(pos+1)...(old_pos-1)]
140
- when "tt"
141
- STYLE_TELETYPE
142
- when "code"
143
- STYLE_CODE
144
- when "b"
145
- STYLE_BOLD
146
- when "em"
147
- STYLE_EMPHASIS
148
- else
149
- # closing or unknown tags
150
- STYLE_NORMAL
151
- end
152
- end
153
- @proc.call(txt[old_pos...txt.size], style)
154
- @proc.call("\n")
155
- end
156
-
157
- ######################################################################
158
-
159
- def display_list(list)
160
- case list.type
161
- when SM::ListBase::BULLET
162
- prefixer = proc { |ignored| @indent + "* " }
163
-
164
- when SM::ListBase::NUMBER,
165
- SM::ListBase::UPPERALPHA,
166
- SM::ListBase::LOWERALPHA
167
-
168
- start = case list.type
169
- when SM::ListBase::NUMBER then 1
170
- when SM::ListBase::UPPERALPHA then 'A'
171
- when SM::ListBase::LOWERALPHA then 'a'
172
- end
173
- prefixer = proc do |ignored|
174
- res = @indent + "#{start}.".ljust(4)
175
- start = start.succ
176
- res
177
- end
178
-
179
- when SM::ListBase::LABELED
180
- prefixer = proc do |li|
181
- li.label
182
- end
183
-
184
- when SM::ListBase::NOTE
185
- longest = 0
186
- list.contents.each do |item|
187
- if item.kind_of?(SM::Flow::LI) && item.label.length > longest
188
- longest = item.label.length
189
- end
190
- end
191
-
192
- prefixer = proc do |li|
193
- @indent + li.label.ljust(longest+1)
194
- end
195
-
196
- else
197
- fail "unknown list type"
198
- end
199
-
200
- list.contents.each do |item|
201
- if item.kind_of? SM::Flow::LI
202
- prefix = prefixer.call(item)
203
- display_flow_item(item, prefix)
204
- else
205
- display_flow_item(item)
206
- end
207
- end
208
- end
209
-
210
- ######################################################################
211
-
212
- def display_flow_item(item, prefix=@indent)
213
-
214
- case item
215
- when SM::Flow::P, SM::Flow::LI
216
- wrap(conv_html(item.body), prefix)
217
- blankline
218
-
219
- when SM::Flow::LIST
220
- display_list(item)
221
-
222
- when SM::Flow::VERB
223
- display_verbatim_flow_item(item, @indent)
224
-
225
- when SM::Flow::H
226
- display_heading(conv_html(item.text), item.level, @indent)
227
-
228
- when SM::Flow::RULE
229
- draw_line
230
-
231
- when String
232
- wrap(conv_html(item), prefix)
233
-
234
- else
235
- fail "Unknown flow element: #{item.class}"
236
- end
237
- end
238
-
239
- ######################################################################
240
-
241
- def display_verbatim_flow_item(item, prefix=@indent)
242
- item.body.split(/\n/).each do |line|
243
- @proc.call(@indent)
244
- @proc.call(conv_html(line))
245
- @proc.call("\n")
246
- end
247
- blankline
248
- end
249
-
250
- ######################################################################
251
-
252
- def display_heading(text, level, indent)
253
- case level
254
- when 1
255
- @proc.call(text, STYLE_H1)
256
- @proc.call("\n")
257
-
258
- when 2
259
- @proc.call(text, STYLE_H2)
260
- @proc.call("\n")
261
-
262
- else
263
- @proc.call(indent)
264
- @proc.call(text, STYLE_H3)
265
- @proc.call("\n")
266
- end
267
- end
268
-
269
-
270
- def display_flow(flow)
271
- flow.each do |f|
272
- display_flow_item(f)
273
- end
274
- end
1
+ # This class is mostly copy & paste from ri_formatter.rb.
2
+ # except that it always returns a string and does not print anything.
3
+ class FoxTextFormatter
4
+ # define all possible styles
5
+ STYLE_NORMAL = :STYLE_NORMAL
6
+ STYLE_BOLD = :STYLE_BOLD
7
+ STYLE_CLASS = :STYLE_CLASS
8
+ STYLE_H1 = :STYLE_H1
9
+ STYLE_H2 = :STYLE_H2
10
+ STYLE_H3 = :STYLE_H3
11
+ STYLE_TELETYPE = :STYLE_TELETYPE
12
+ STYLE_CODE = :STYLE_CODE
13
+ STYLE_EMPHASIS = :STYLE_EMPHASIS
14
+
15
+ attr_reader :indent
16
+ attr_accessor :width
17
+
18
+ # whenever text should be printed/added/shown, proc is called with the text as the argument.
19
+ def initialize(width, indent, &proc)
20
+ @width = width
21
+ @indent = indent
22
+ @proc = proc
23
+ end
24
+
25
+ ######################################################################
26
+
27
+ def draw_line(label=nil)
28
+ len = @width
29
+ len -= (label.size+1) if label
30
+ len = [0, len].max
31
+ @proc.call("-"*len)
32
+ if label
33
+ @proc.call(" ")
34
+ @proc.call(label, STYLE_CLASS)
35
+ end
36
+ @proc.call("\n")
37
+ end
38
+
39
+ def display_params(method)
40
+ params = method.params
41
+
42
+ if params[0] == ?(
43
+ if method.is_singleton
44
+ params = method.full_name + params
45
+ else
46
+ params = method.name + params
47
+ end
48
+ end
49
+ params.split(/\n/).each do |param|
50
+ @proc.call(param+"\n", STYLE_BOLD)
51
+ end
52
+ end
53
+
54
+ def wrap(txt, prefix=@indent, linelen=@width)
55
+ return if !txt || txt.empty?
56
+ @proc.call(prefix, STYLE_EMPHASIS)
57
+ conv_markup(txt, prefix, linelen)
58
+ =begin
59
+ textLen = linelen - prefix.length
60
+ patt = Regexp.new("^(.{0,#{textLen}})[ \n]")
61
+ next_prefix = prefix.tr("^ ", " ")
62
+
63
+ res = []
64
+
65
+ while work.length > textLen
66
+ if work =~ patt
67
+ res << $1
68
+ work.slice!(0, $&.length)
69
+ else
70
+ res << work.slice!(0, textLen)
71
+ end
72
+ end
73
+ res << work if work.length.nonzero?
74
+ @proc.call(prefix + res.join("\n" + next_prefix) + "\n")
75
+ =end
76
+ end
77
+
78
+ ######################################################################
79
+
80
+ def blankline
81
+ @proc.call("\n")
82
+ end
83
+
84
+ ######################################################################
85
+
86
+ # called when we want to ensure a nbew 'wrap' starts on a newline
87
+ # Only needed for HtmlFormatter, because the rest do their
88
+ # own line breaking
89
+
90
+ def break_to_newline
91
+ end
92
+
93
+ ######################################################################
94
+
95
+ def bold_print(txt)
96
+ @proc.call(txt, STYLE_BOLD)
97
+ end
98
+
99
+ ######################################################################
100
+
101
+ def raw_print_line(txt)
102
+ @proc.call(txt)
103
+ end
104
+
105
+ ######################################################################
106
+
107
+ # convert HTML entities back to ASCII
108
+ def conv_html(txt)
109
+ case txt
110
+ when Array
111
+ txt.join.
112
+ gsub(/&gt;/, '>').
113
+ gsub(/&lt;/, '<').
114
+ gsub(/&quot;/, '"').
115
+ gsub(/&amp;/, '&')
116
+ else # it's a String
117
+ txt.
118
+ gsub(/&gt;/, '>').
119
+ gsub(/&lt;/, '<').
120
+ gsub(/&quot;/, '"').
121
+ gsub(/&amp;/, '&')
122
+ end
123
+ end
124
+
125
+ # convert markup into display form
126
+ def conv_markup(txt, prefix, linelen)
127
+
128
+ # this code assumes that tags are not used inside tags
129
+ pos = 0
130
+ old_pos = 0
131
+ style = STYLE_NORMAL
132
+ current_indent = prefix.size
133
+ while pos = txt.index(%r{(<tt>|<code>|<b>|<em>|</tt>|</code>|</b>|</em>)}, old_pos)
134
+ new_part = txt[old_pos...pos]
135
+ @proc.call(new_part, style)
136
+
137
+ # get tag name
138
+ old_pos = txt.index(">", pos) + 1
139
+ style = case txt[(pos+1)...(old_pos-1)]
140
+ when "tt"
141
+ STYLE_TELETYPE
142
+ when "code"
143
+ STYLE_CODE
144
+ when "b"
145
+ STYLE_BOLD
146
+ when "em"
147
+ STYLE_EMPHASIS
148
+ else
149
+ # closing or unknown tags
150
+ STYLE_NORMAL
151
+ end
152
+ end
153
+ @proc.call(txt[old_pos...txt.size], style)
154
+ @proc.call("\n")
155
+ end
156
+
157
+ ######################################################################
158
+
159
+ def display_list(list)
160
+ case list.type
161
+ when SM::ListBase::BULLET
162
+ prefixer = proc { |ignored| @indent + "* " }
163
+
164
+ when SM::ListBase::NUMBER,
165
+ SM::ListBase::UPPERALPHA,
166
+ SM::ListBase::LOWERALPHA
167
+
168
+ start = case list.type
169
+ when SM::ListBase::NUMBER then 1
170
+ when SM::ListBase::UPPERALPHA then 'A'
171
+ when SM::ListBase::LOWERALPHA then 'a'
172
+ end
173
+ prefixer = proc do |ignored|
174
+ res = @indent + "#{start}.".ljust(4)
175
+ start = start.succ
176
+ res
177
+ end
178
+
179
+ when SM::ListBase::LABELED
180
+ prefixer = proc do |li|
181
+ li.label
182
+ end
183
+
184
+ when SM::ListBase::NOTE
185
+ longest = 0
186
+ list.contents.each do |item|
187
+ if item.kind_of?(SM::Flow::LI) && item.label.length > longest
188
+ longest = item.label.length
189
+ end
190
+ end
191
+
192
+ prefixer = proc do |li|
193
+ @indent + li.label.ljust(longest+1)
194
+ end
195
+
196
+ else
197
+ fail "unknown list type"
198
+ end
199
+
200
+ list.contents.each do |item|
201
+ if item.kind_of? SM::Flow::LI
202
+ prefix = prefixer.call(item)
203
+ display_flow_item(item, prefix)
204
+ else
205
+ display_flow_item(item)
206
+ end
207
+ end
208
+ end
209
+
210
+ ######################################################################
211
+
212
+ def display_flow_item(item, prefix=@indent)
213
+
214
+ case item
215
+ when SM::Flow::P, SM::Flow::LI
216
+ wrap(conv_html(item.body), prefix)
217
+ blankline
218
+
219
+ when SM::Flow::LIST
220
+ display_list(item)
221
+
222
+ when SM::Flow::VERB
223
+ display_verbatim_flow_item(item, @indent)
224
+
225
+ when SM::Flow::H
226
+ display_heading(conv_html(item.text), item.level, @indent)
227
+
228
+ when SM::Flow::RULE
229
+ draw_line
230
+
231
+ when String
232
+ wrap(conv_html(item), prefix)
233
+
234
+ else
235
+ fail "Unknown flow element: #{item.class}"
236
+ end
237
+ end
238
+
239
+ ######################################################################
240
+
241
+ def display_verbatim_flow_item(item, prefix=@indent)
242
+ item.body.split(/\n/).each do |line|
243
+ @proc.call(@indent)
244
+ @proc.call(conv_html(line))
245
+ @proc.call("\n")
246
+ end
247
+ blankline
248
+ end
249
+
250
+ ######################################################################
251
+
252
+ def display_heading(text, level, indent)
253
+ case level
254
+ when 1
255
+ @proc.call(text, STYLE_H1)
256
+ @proc.call("\n")
257
+
258
+ when 2
259
+ @proc.call(text, STYLE_H2)
260
+ @proc.call("\n")
261
+
262
+ else
263
+ @proc.call(indent)
264
+ @proc.call(text, STYLE_H3)
265
+ @proc.call("\n")
266
+ end
267
+ end
268
+
269
+
270
+ def display_flow(flow)
271
+ flow.each do |f|
272
+ display_flow_item(f)
273
+ end
274
+ end
275
275
  end