origami 1.2.7 → 2.0.0

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.
Files changed (162) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -0
  3. data/README.md +112 -0
  4. data/bin/config/pdfcop.conf.yml +232 -233
  5. data/bin/gui/about.rb +27 -37
  6. data/bin/gui/config.rb +108 -117
  7. data/bin/gui/file.rb +416 -365
  8. data/bin/gui/gtkhex.rb +1138 -1153
  9. data/bin/gui/hexview.rb +55 -57
  10. data/bin/gui/imgview.rb +48 -51
  11. data/bin/gui/menu.rb +388 -386
  12. data/bin/gui/properties.rb +114 -130
  13. data/bin/gui/signing.rb +571 -617
  14. data/bin/gui/textview.rb +77 -95
  15. data/bin/gui/treeview.rb +382 -387
  16. data/bin/gui/walker.rb +227 -232
  17. data/bin/gui/xrefs.rb +56 -60
  18. data/bin/pdf2pdfa +53 -57
  19. data/bin/pdf2ruby +212 -228
  20. data/bin/pdfcop +338 -348
  21. data/bin/pdfdecompress +58 -65
  22. data/bin/pdfdecrypt +56 -60
  23. data/bin/pdfencrypt +75 -80
  24. data/bin/pdfexplode +185 -182
  25. data/bin/pdfextract +201 -218
  26. data/bin/pdfmetadata +83 -82
  27. data/bin/pdfsh +4 -5
  28. data/bin/pdfwalker +1 -2
  29. data/bin/shell/.irbrc +45 -82
  30. data/bin/shell/console.rb +105 -130
  31. data/bin/shell/hexdump.rb +40 -64
  32. data/examples/README.md +34 -0
  33. data/examples/attachments/attachment.rb +38 -0
  34. data/examples/attachments/nested_document.rb +51 -0
  35. data/examples/encryption/encryption.rb +28 -0
  36. data/{samples/actions/triggerevents/trigger.rb → examples/events/events.rb} +13 -16
  37. data/examples/flash/flash.rb +37 -0
  38. data/{samples → examples}/flash/helloworld.swf +0 -0
  39. data/examples/forms/javascript.rb +54 -0
  40. data/examples/forms/xfa.rb +115 -0
  41. data/examples/javascript/hello_world.rb +22 -0
  42. data/examples/javascript/js_emulation.rb +54 -0
  43. data/examples/loop/goto.rb +32 -0
  44. data/examples/loop/named.rb +33 -0
  45. data/examples/signature/signature.rb +65 -0
  46. data/examples/uri/javascript.rb +56 -0
  47. data/examples/uri/open-uri.rb +21 -0
  48. data/examples/uri/submitform.rb +47 -0
  49. data/lib/origami.rb +29 -42
  50. data/lib/origami/3d.rb +350 -225
  51. data/lib/origami/acroform.rb +262 -288
  52. data/lib/origami/actions.rb +268 -288
  53. data/lib/origami/annotations.rb +697 -722
  54. data/lib/origami/array.rb +258 -184
  55. data/lib/origami/boolean.rb +74 -84
  56. data/lib/origami/catalog.rb +397 -434
  57. data/lib/origami/collections.rb +144 -0
  58. data/lib/origami/destinations.rb +233 -194
  59. data/lib/origami/dictionary.rb +253 -232
  60. data/lib/origami/encryption.rb +1274 -1243
  61. data/lib/origami/export.rb +232 -268
  62. data/lib/origami/extensions/fdf.rb +307 -220
  63. data/lib/origami/extensions/ppklite.rb +368 -435
  64. data/lib/origami/filespec.rb +197 -0
  65. data/lib/origami/filters.rb +301 -295
  66. data/lib/origami/filters/ascii.rb +177 -180
  67. data/lib/origami/filters/ccitt.rb +528 -535
  68. data/lib/origami/filters/crypt.rb +26 -35
  69. data/lib/origami/filters/dct.rb +46 -52
  70. data/lib/origami/filters/flate.rb +95 -94
  71. data/lib/origami/filters/jbig2.rb +49 -55
  72. data/lib/origami/filters/jpx.rb +38 -44
  73. data/lib/origami/filters/lzw.rb +189 -183
  74. data/lib/origami/filters/predictors.rb +221 -235
  75. data/lib/origami/filters/runlength.rb +103 -104
  76. data/lib/origami/font.rb +173 -186
  77. data/lib/origami/functions.rb +67 -81
  78. data/lib/origami/graphics.rb +25 -21
  79. data/lib/origami/graphics/colors.rb +178 -187
  80. data/lib/origami/graphics/instruction.rb +79 -85
  81. data/lib/origami/graphics/path.rb +142 -148
  82. data/lib/origami/graphics/patterns.rb +160 -167
  83. data/lib/origami/graphics/render.rb +43 -50
  84. data/lib/origami/graphics/state.rb +138 -153
  85. data/lib/origami/graphics/text.rb +188 -205
  86. data/lib/origami/graphics/xobject.rb +819 -815
  87. data/lib/origami/header.rb +63 -78
  88. data/lib/origami/javascript.rb +596 -597
  89. data/lib/origami/linearization.rb +285 -290
  90. data/lib/origami/metadata.rb +139 -148
  91. data/lib/origami/name.rb +112 -148
  92. data/lib/origami/null.rb +53 -62
  93. data/lib/origami/numeric.rb +162 -175
  94. data/lib/origami/obfuscation.rb +186 -174
  95. data/lib/origami/object.rb +593 -573
  96. data/lib/origami/outline.rb +42 -47
  97. data/lib/origami/outputintents.rb +73 -82
  98. data/lib/origami/page.rb +703 -592
  99. data/lib/origami/parser.rb +238 -290
  100. data/lib/origami/parsers/fdf.rb +41 -33
  101. data/lib/origami/parsers/pdf.rb +75 -95
  102. data/lib/origami/parsers/pdf/lazy.rb +137 -0
  103. data/lib/origami/parsers/pdf/linear.rb +64 -66
  104. data/lib/origami/parsers/ppklite.rb +34 -70
  105. data/lib/origami/pdf.rb +1030 -1005
  106. data/lib/origami/reference.rb +102 -102
  107. data/lib/origami/signature.rb +591 -609
  108. data/lib/origami/stream.rb +668 -551
  109. data/lib/origami/string.rb +397 -373
  110. data/lib/origami/template/patterns.rb +56 -0
  111. data/lib/origami/template/widgets.rb +151 -0
  112. data/lib/origami/trailer.rb +144 -158
  113. data/lib/origami/tree.rb +62 -0
  114. data/lib/origami/version.rb +23 -0
  115. data/lib/origami/webcapture.rb +88 -79
  116. data/lib/origami/xfa.rb +2863 -2882
  117. data/lib/origami/xreftable.rb +472 -384
  118. data/test/dataset/calc.pdf +85 -0
  119. data/test/dataset/crypto.pdf +82 -0
  120. data/test/dataset/empty.pdf +49 -0
  121. data/test/test_actions.rb +27 -0
  122. data/test/test_annotations.rb +90 -0
  123. data/test/test_pages.rb +31 -0
  124. data/test/test_pdf.rb +16 -0
  125. data/test/test_pdf_attachment.rb +34 -0
  126. data/test/test_pdf_create.rb +24 -0
  127. data/test/test_pdf_encrypt.rb +95 -0
  128. data/test/test_pdf_parse.rb +96 -0
  129. data/test/test_pdf_sign.rb +58 -0
  130. data/test/test_streams.rb +182 -0
  131. data/test/test_xrefs.rb +67 -0
  132. metadata +88 -58
  133. data/README +0 -67
  134. data/bin/pdf2graph +0 -121
  135. data/bin/pdfcocoon +0 -104
  136. data/lib/origami/file.rb +0 -233
  137. data/samples/README.txt +0 -45
  138. data/samples/actions/launch/calc.rb +0 -87
  139. data/samples/actions/launch/winparams.rb +0 -22
  140. data/samples/actions/loop/loopgoto.rb +0 -24
  141. data/samples/actions/loop/loopnamed.rb +0 -21
  142. data/samples/actions/named/named.rb +0 -31
  143. data/samples/actions/samba/smbrelay.rb +0 -26
  144. data/samples/actions/webbug/submitform.js +0 -26
  145. data/samples/actions/webbug/webbug-browser.rb +0 -68
  146. data/samples/actions/webbug/webbug-js.rb +0 -67
  147. data/samples/actions/webbug/webbug-reader.rb +0 -90
  148. data/samples/attachments/attach.rb +0 -40
  149. data/samples/attachments/attached.txt +0 -1
  150. data/samples/crypto/crypto.rb +0 -28
  151. data/samples/digsig/signed.rb +0 -46
  152. data/samples/exploits/cve-2008-2992-utilprintf.rb +0 -87
  153. data/samples/exploits/cve-2009-0927-geticon.rb +0 -65
  154. data/samples/exploits/exploit_customdictopen.rb +0 -55
  155. data/samples/exploits/getannots.rb +0 -69
  156. data/samples/flash/flash.rb +0 -31
  157. data/samples/javascript/attached.txt +0 -1
  158. data/samples/javascript/js.rb +0 -52
  159. data/templates/patterns.rb +0 -66
  160. data/templates/widgets.rb +0 -173
  161. data/templates/xdp.rb +0 -92
  162. data/test/ts_pdf.rb +0 -50
@@ -1,1328 +1,1313 @@
1
1
  =begin
2
2
 
3
- = File
4
- gtkhex.rb
5
-
6
- = Info
7
- This file is part of PDF Walker, a graphical PDF file browser
8
- Copyright (C) 2010 Guillaume Delugré <guillaume AT security-labs DOT org>
9
- All right reserved.
10
-
11
- PDF Walker is free software: you can redistribute it and/or modify
12
- it under the terms of the GNU General Public License as published by
13
- the Free Software Foundation, either version 3 of the License, or
14
- (at your option) any later version.
15
-
16
- PDF Walker is distributed in the hope that it will be useful,
17
- but WITHOUT ANY WARRANTY; without even the implied warranty of
18
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
- GNU General Public License for more details.
20
-
21
- You should have received a copy of the GNU General Public License
22
- along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
23
-
24
- This work has been derived from the GHex project. Thanks to them.
25
- Original implementation: Jaka Mocnik <jaka@gnu.org>
3
+ This file is part of PDF Walker, a graphical PDF file browser
4
+ Copyright (C) 2016 Guillaume Delugré.
5
+
6
+ PDF Walker is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ PDF Walker is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ This work has been derived from the GHex project. Thanks to them.
20
+ Original implementation: Jaka Mocnik <jaka@gnu.org>
26
21
  =end
27
22
 
28
23
  require 'gtk2'
29
24
 
30
25
  module Gtk
31
-
32
- class HexEditor < Fixed
33
- module View
34
- HEX = 1
35
- ASCII = 2
36
- end
37
26
 
38
- module Group
39
- BYTE = 1
40
- WORD = 2
41
- LONG = 4
42
- end
27
+ class HexEditor < Fixed
28
+ module View
29
+ HEX = 1
30
+ ASCII = 2
31
+ end
43
32
 
44
- class Highlight
45
- attr_accessor :start, :end
46
- attr_accessor :start_line, :end_line
47
- attr_accessor :style
48
- attr_accessor :min_select
49
- attr_accessor :valid
50
- end
33
+ module Group
34
+ BYTE = 1
35
+ WORD = 2
36
+ LONG = 4
37
+ end
51
38
 
52
- class AutoHighlight
53
- attr_accessor :search_view
54
- attr_accessor :search_string
55
- attr_accessor :search_len
39
+ class Highlight
40
+ attr_accessor :start, :end
41
+ attr_accessor :start_line, :end_line
42
+ attr_accessor :style
43
+ attr_accessor :min_select
44
+ attr_accessor :valid
45
+ end
56
46
 
57
- attr_accessor :color
47
+ class AutoHighlight
48
+ attr_accessor :search_view
49
+ attr_accessor :search_string
50
+ attr_accessor :search_len
58
51
 
59
- attr_accessor :view_min
60
- attr_accessor :view_max
52
+ attr_accessor :color
61
53
 
62
- attr_accessor :highlights
63
- end
54
+ attr_accessor :view_min
55
+ attr_accessor :view_max
64
56
 
65
- DEFAULT_FONT = "Monospace 12"
66
- DEFAULT_CPL = 32
67
- DEFAULT_LINES = 16
68
- DISPLAY_BORDER = 4
69
- SCROLL_TIMEOUT = 100
70
-
71
- type_register
72
-
73
- @@primary = Clipboard.get(Gdk::Selection::PRIMARY)
74
- @@clipboard = Clipboard.get(Gdk::Selection::CLIPBOARD)
75
-
76
- def initialize(data = '')
77
- super()
78
-
79
- @data = data
80
- if RUBY_VERSION >= '1.9'
81
- @data.force_encoding('binary')
82
- end
83
-
84
- @scroll_timeout = -1
85
- @disp_buffer = ""
86
- @starting_offset = 0
87
-
88
- @xdisp_width = @adisp_width = 200
89
- @xdisp_gc = @adisp_gc = nil
90
- @active_view = View::HEX
91
- @group_type = Group::BYTE
92
- @lines = @vis_lines = @top_line = @cpl = 0
93
- @cursor_pos = 0
94
- @lower_nibble = false
95
- @cursor_shown = false
96
- @button = 0
97
- @insert = false
98
- @selecting = false
99
-
100
- @selection = Highlight.new
101
- @selection.start = @selection.end = 0
102
- @selection.style = nil
103
- @selection.min_select = 1
104
- @selection.valid = false
105
-
106
- @highlights = [ @selection ]
107
-
108
- @auto_highlight = nil
109
-
110
- @disp_font_metrics = load_font DEFAULT_FONT
111
- @font_desc = Pango::FontDescription.new DEFAULT_FONT
112
-
113
- @char_width = get_max_char_width(@disp_font_metrics)
114
- @char_height = Pango.pixels(@disp_font_metrics.ascent) + Pango.pixels(@disp_font_metrics.descent) + 2
115
-
116
- self.can_focus = true
117
- self.events = Gdk::Event::KEY_PRESS_MASK
118
- self.border_width = DISPLAY_BORDER
119
-
120
- mouse_handler = lambda do |widget, event|
121
- if event.event_type == Gdk::Event::BUTTON_RELEASE and event.button == 1
122
- if @scroll_timeout
123
- GLib::Source.remove @scroll_timeout
124
- @scroll_timeout = nil
125
- @scroll_dir = 0
126
- end
127
-
128
- @selecting = false
129
- Gtk.grab_remove(widget)
130
- @button = 0
131
- elsif event.event_type == Gdk::Event::BUTTON_PRESS and event.button == 1
132
- self.grab_focus unless self.has_focus?
133
-
134
- Gtk.grab_add(widget)
135
- @button = event.button
136
-
137
- focus_view = (widget == @xdisp) ? View::HEX : View::ASCII
138
-
139
- if @active_view == focus_view
140
- if @active_view == View::HEX
141
- hex_to_pointer(event.x, event.y)
142
- else
143
- ascii_to_pointer(event.x, event.y)
57
+ attr_accessor :highlights
58
+ end
59
+
60
+ DEFAULT_FONT = "Monospace 12"
61
+ DEFAULT_CPL = 32
62
+ DEFAULT_LINES = 16
63
+ DISPLAY_BORDER = 4
64
+ SCROLL_TIMEOUT = 100
65
+
66
+ type_register
67
+
68
+ @@primary = Clipboard.get(Gdk::Selection::PRIMARY)
69
+ @@clipboard = Clipboard.get(Gdk::Selection::CLIPBOARD)
70
+
71
+ def initialize(data = '')
72
+ super()
73
+
74
+ @data = data.force_encoding('binary')
75
+
76
+ @scroll_timeout = -1
77
+ @disp_buffer = ""
78
+ @starting_offset = 0
79
+
80
+ @xdisp_width = @adisp_width = 200
81
+ @xdisp_gc = @adisp_gc = nil
82
+ @active_view = View::HEX
83
+ @group_type = Group::BYTE
84
+ @lines = @vis_lines = @top_line = @cpl = 0
85
+ @cursor_pos = 0
86
+ @lower_nibble = false
87
+ @cursor_shown = false
88
+ @button = 0
89
+ @insert = false
90
+ @selecting = false
91
+
92
+ @selection = Highlight.new
93
+ @selection.start = @selection.end = 0
94
+ @selection.style = nil
95
+ @selection.min_select = 1
96
+ @selection.valid = false
97
+
98
+ @highlights = [ @selection ]
99
+
100
+ @auto_highlight = nil
101
+
102
+ @disp_font_metrics = load_font DEFAULT_FONT
103
+ @font_desc = Pango::FontDescription.new DEFAULT_FONT
104
+
105
+ @char_width = get_max_char_width(@disp_font_metrics)
106
+ @char_height = Pango.pixels(@disp_font_metrics.ascent) + Pango.pixels(@disp_font_metrics.descent) + 2
107
+
108
+ @show_offsets = false
109
+ @offsets_gc = nil
110
+
111
+ self.can_focus = true
112
+ self.events = Gdk::Event::KEY_PRESS_MASK
113
+ self.border_width = DISPLAY_BORDER
114
+
115
+ mouse_handler = lambda do |widget, event|
116
+ if event.event_type == Gdk::Event::BUTTON_RELEASE and event.button == 1
117
+ if @scroll_timeout
118
+ GLib::Source.remove @scroll_timeout
119
+ @scroll_timeout = nil
120
+ @scroll_dir = 0
121
+ end
122
+
123
+ @selecting = false
124
+ Gtk.grab_remove(widget)
125
+ @button = 0
126
+ elsif event.event_type == Gdk::Event::BUTTON_PRESS and event.button == 1
127
+ self.grab_focus unless self.has_focus?
128
+
129
+ Gtk.grab_add(widget)
130
+ @button = event.button
131
+
132
+ focus_view = (widget == @xdisp) ? View::HEX : View::ASCII
133
+
134
+ if @active_view == focus_view
135
+ if @active_view == View::HEX
136
+ hex_to_pointer(event.x, event.y)
137
+ else
138
+ ascii_to_pointer(event.x, event.y)
139
+ end
140
+
141
+ unless @selecting
142
+ @selecting = true
143
+ set_selection(@cursor_pos, @cursor_pos)
144
+ end
145
+ else
146
+ hide_cursor
147
+ @active_view = focus_view
148
+ show_cursor
149
+ end
150
+ elsif event.event_type == Gdk::Event::BUTTON_PRESS and event.button == 2
151
+ # TODO
152
+ else
153
+ @button = 0
154
+ end
144
155
  end
145
156
 
146
- unless @selecting
147
- @selecting = true
148
- set_selection(@cursor_pos, @cursor_pos)
157
+ @xdisp = DrawingArea.new
158
+ @xdisp.modify_font @font_desc
159
+ @xlayout = @xdisp.create_pango_layout('')
160
+ @xdisp.events =
161
+ Gdk::Event::EXPOSURE_MASK |
162
+ Gdk::Event::BUTTON_PRESS_MASK |
163
+ Gdk::Event::BUTTON_RELEASE_MASK |
164
+ Gdk::Event::BUTTON_MOTION_MASK |
165
+ Gdk::Event::SCROLL_MASK
166
+
167
+ @xdisp.signal_connect 'realize' do
168
+ @xdisp_gc = Gdk::GC.new(@xdisp.window)
169
+ @xdisp_gc.set_exposures(true)
149
170
  end
150
- else
151
- hide_cursor
152
- @active_view = focus_view
153
- show_cursor
154
- end
155
- elsif event.event_type == Gdk::Event::BUTTON_PRESS and event.button == 2
156
- # TODO
157
- else
158
- @button = 0
171
+
172
+ @xdisp.signal_connect 'expose_event' do |xdisp, event|
173
+ imin = (event.area.y / @char_height).to_i
174
+ imax = ((event.area.y + event.area.height) / @char_height).to_i
175
+ imax += 1 if (event.area.y + event.area.height).to_i % @char_height != 0
176
+
177
+ imax = [ imax, @vis_lines ].min
178
+
179
+ render_hex_lines(imin, imax)
180
+ end
181
+
182
+ @xdisp.signal_connect 'scroll_event' do |xdisp, event|
183
+ @scrollbar.event(event)
184
+ end
185
+
186
+ @xdisp.signal_connect 'button_press_event' do |xdisp, event|
187
+ mouse_handler[xdisp, event]
188
+ end
189
+
190
+ @xdisp.signal_connect 'button_release_event' do |xdisp, event|
191
+ mouse_handler[xdisp, event]
192
+ end
193
+
194
+ @xdisp.signal_connect 'motion_notify_event' do |xdisp, event|
195
+ _w, x, y, _m = xdisp.window.pointer
196
+
197
+ if y < 0
198
+ @scroll_dir = -1
199
+ elsif y >= xdisp.allocation.height
200
+ @scroll_dir = 1
201
+ else
202
+ @scroll_dir = 0
203
+ end
204
+
205
+ if @scroll_dir != 0
206
+ if @scroll_timeout == nil
207
+ @scroll_timeout = GLib::Timeout.add(SCROLL_TIMEOUT) {
208
+ if @scroll_dir < 0
209
+ set_cursor([ 0, @cursor_pos - @cpl ].max)
210
+ elsif @scroll_dir > 0
211
+ set_cursor([ @data.size - 1, @cursor_pos + @cpl ].min)
212
+ end
213
+
214
+ true
215
+ }
216
+ next
217
+ end
218
+ else
219
+ if @scroll_timeout != nil
220
+ GLib::Source.remove @scroll_timeout
221
+ @scroll_timeout = nil
222
+ end
223
+ end
224
+
225
+ next if event.window != xdisp.window
226
+
227
+ hex_to_pointer(x,y) if @active_view == View::HEX and @button == 1
228
+ end
229
+
230
+ put @xdisp, 0, 0
231
+ @xdisp.show
232
+
233
+ @adisp = DrawingArea.new
234
+ @adisp.modify_font @font_desc
235
+ @alayout = @adisp.create_pango_layout('')
236
+ @adisp.events =
237
+ Gdk::Event::EXPOSURE_MASK |
238
+ Gdk::Event::BUTTON_PRESS_MASK |
239
+ Gdk::Event::BUTTON_RELEASE_MASK |
240
+ Gdk::Event::BUTTON_MOTION_MASK |
241
+ Gdk::Event::SCROLL_MASK
242
+
243
+ @adisp.signal_connect 'realize' do
244
+ @adisp_gc = Gdk::GC.new(@adisp.window)
245
+ @adisp_gc.set_exposures(true)
246
+ end
247
+
248
+ @adisp.signal_connect 'expose_event' do |adisp, event|
249
+ imin = (event.area.y / @char_height).to_i
250
+ imax = ((event.area.y + event.area.height) / @char_height).to_i
251
+ imax += 1 if (event.area.y + event.area.height).to_i % @char_height != 0
252
+
253
+ imax = [ imax, @vis_lines ].min
254
+ render_ascii_lines(imin, imax)
255
+ end
256
+
257
+ @adisp.signal_connect 'scroll_event' do |adisp, event|
258
+ @scrollbar.event(event)
259
+ end
260
+
261
+ @adisp.signal_connect 'button_press_event' do |adisp, event|
262
+ mouse_handler[adisp, event]
263
+ end
264
+
265
+ @adisp.signal_connect 'button_release_event' do |adisp, event|
266
+ mouse_handler[adisp, event]
267
+ end
268
+
269
+ @adisp.signal_connect 'motion_notify_event' do |adisp, event|
270
+ _w, x, y, _m = adisp.window.pointer
271
+
272
+ if y < 0
273
+ @scroll_dir = -1
274
+ elsif y >= adisp.allocation.height
275
+ @scroll_dir = 1
276
+ else
277
+ @scroll_dir = 0
278
+ end
279
+
280
+ if @scroll_dir != 0
281
+ if @scroll_timeout == nil
282
+ @scroll_timeout = GLib::Timeout.add(SCROLL_TIMEOUT) {
283
+ if @scroll_dir < 0
284
+ set_cursor([ 0, @cursor_pos - @cpl ].max)
285
+ elsif @scroll_dir > 0
286
+ set_cursor([ @data.size - 1, @cursor_pos + @cpl ].min)
287
+ end
288
+
289
+ true
290
+ }
291
+ next
292
+ end
293
+ else
294
+ if @scroll_timeout != nil
295
+ GLib::Source.remove @scroll_timeout
296
+ @scroll_timeout = nil
297
+ end
298
+ end
299
+
300
+ next if event.window != adisp.window
301
+
302
+ ascii_to_pointer(x,y) if @active_view == View::ASCII and @button == 1
303
+ end
304
+
305
+ put @adisp, 0, 0
306
+ @adisp.show
307
+
308
+ @adj = Gtk::Adjustment.new(0, 0, 0, 0, 0, 0)
309
+ @scrollbar = Gtk::VScrollbar.new(@adj)
310
+ @adj.signal_connect 'value_changed' do |adj|
311
+ unless @xdisp_gc.nil? or @adisp_gc.nil? or not @xdisp.drawable? or not @adisp.drawable?
312
+ source_min = (adj.value.to_i - @top_line) * @char_height
313
+ source_max = source_min + @xdisp.allocation.height
314
+ dest_min = 0
315
+ dest_max = @xdisp.allocation.height
316
+
317
+ rect = Gdk::Rectangle.new(0, 0, 0, 0)
318
+ @top_line = adj.value.to_i
319
+ if source_min < 0
320
+ rect.y = 0
321
+ rect.height = -source_min
322
+ rect_height = [ rect.height, @xdisp.allocation.height ].min
323
+ source_min = 0
324
+ dest_min = rect.height
325
+ else
326
+ rect.y = 2 * @xdisp.allocation.height - source_max
327
+ rect.y = 0 if rect.y < 0
328
+ rect.height = @xdisp.allocation.height - rect.y
329
+ source_max = @xdisp.allocation.height
330
+ dest_max = rect.y
331
+ end
332
+
333
+ if source_min != source_max
334
+ @xdisp.window.draw_drawable(
335
+ @xdisp_gc,
336
+ @xdisp.window,
337
+ 0, source_min,
338
+ 0, dest_min,
339
+ @xdisp.allocation.width,
340
+ source_max - source_min
341
+ )
342
+ @adisp.window.draw_drawable(
343
+ @adisp_gc,
344
+ @adisp.window,
345
+ 0, source_min,
346
+ 0, dest_min,
347
+ @adisp.allocation.width,
348
+ source_max - source_min
349
+ )
350
+
351
+ if @offsets
352
+ if @offsets_gc.nil?
353
+ @offsets_gc = Gdk::GC.new(@offsets.window)
354
+ @offsets_gc.set_exposures(true)
355
+ end
356
+
357
+ @offsets.window.draw_drawable(
358
+ @offsets_gc,
359
+ @offsets.window,
360
+ 0, source_min,
361
+ 0, dest_min,
362
+ @offsets.allocation.width,
363
+ source_max - source_min
364
+ )
365
+ end
366
+
367
+ # TODO update_all_auto_highlights(true, true)
368
+ invalidate_all_highlights
369
+
370
+ rect.width = @xdisp.allocation.width
371
+ @xdisp.window.invalidate(rect, false)
372
+ rect.width = @adisp.allocation.width
373
+ @adisp.window.invalidate(rect, false)
374
+
375
+ if @offsets
376
+ rect.width = @offsets.allocation.width
377
+ @offsets.window.invalidate(rect, false)
378
+ end
379
+ end
380
+ end
381
+ end
382
+
383
+ put @scrollbar, 0, 0
384
+ @scrollbar.show
159
385
  end
160
- end
161
-
162
- @xdisp = DrawingArea.new
163
- @xdisp.modify_font @font_desc
164
- @xlayout = @xdisp.create_pango_layout('')
165
- @xdisp.events =
166
- Gdk::Event::EXPOSURE_MASK |
167
- Gdk::Event::BUTTON_PRESS_MASK |
168
- Gdk::Event::BUTTON_RELEASE_MASK |
169
- Gdk::Event::BUTTON_MOTION_MASK |
170
- Gdk::Event::SCROLL_MASK
171
-
172
- @xdisp.signal_connect 'realize' do
173
- @xdisp_gc = Gdk::GC.new(@xdisp.window)
174
- @xdisp_gc.set_exposures(true)
175
- end
176
-
177
- @xdisp.signal_connect 'expose_event' do |xdisp, event|
178
- imin = (event.area.y / @char_height).to_i
179
- imax = ((event.area.y + event.area.height) / @char_height).to_i
180
- imax += 1 if (event.area.y + event.area.height).to_i % @char_height != 0
181
-
182
- imax = [ imax, @vis_lines ].min
183
-
184
- render_hex_lines(imin, imax)
185
- end
186
-
187
- @xdisp.signal_connect 'scroll_event' do |xdisp, event|
188
- @scrollbar.event(event)
189
- end
190
-
191
- @xdisp.signal_connect 'button_press_event' do |xdisp, event|
192
- mouse_handler[xdisp, event]
193
- end
194
-
195
- @xdisp.signal_connect 'button_release_event' do |xdisp, event|
196
- mouse_handler[xdisp, event]
197
- end
198
-
199
- @xdisp.signal_connect 'motion_notify_event' do |xdisp, event|
200
- w, x, y, m = xdisp.window.pointer
201
-
202
- if y < 0
203
- @scroll_dir = -1
204
- elsif y >= xdisp.allocation.height
205
- @scroll_dir = 1
206
- else
207
- @scroll_dir = 0
386
+
387
+ def set_selection(s, e)
388
+ e = [ e, @data.size ].min
389
+
390
+ @@primary.clear if @selection.start != @selection.end
391
+
392
+ os, oe = [ @selection.start, @selection.end ].sort
393
+
394
+ @selection.start = [ 0, s ].max
395
+ @selection.start = [ @selection.start, @data.size ].min
396
+ @selection.end = [ e, @data.size ].min
397
+
398
+ invalidate_highlight(@selection)
399
+
400
+ ns, ne = [ @selection.start, @selection.end ].sort
401
+
402
+ if ns != os and ne != oe
403
+ bytes_changed([ns, os].min, [ne, oe].max)
404
+ elsif ne != oe
405
+ bytes_changed(*[ne, oe].sort)
406
+ elsif ns != os
407
+ bytes_changed(*[ns, os].sort)
408
+ end
409
+
410
+ if @selection.start != @selection.end
411
+ if @active_view == View::HEX
412
+ brk_len = 2 * @cpl + @cpl / @group_type
413
+ format_xblock(s,e)
414
+ (@disp_buffer.size / brk_len + 1).times do |i| @disp_buffer.insert(i * (brk_len + 1), $/) end
415
+ else
416
+ brk_len = @cpl
417
+ format_ablock(s,e)
418
+ end
419
+
420
+ @@primary.set_text(@disp_buffer)
421
+ end
208
422
  end
209
423
 
210
- if @scroll_dir != 0
211
- if @scroll_timeout == nil
212
- @scroll_timeout = GLib::Timeout.add(SCROLL_TIMEOUT) {
213
- if @scroll_dir < 0
214
- set_cursor([ 0, @cursor_pos - @cpl ].max)
215
- elsif @scroll_dir > 0
216
- set_cursor([ @data.size - 1, @cursor_pos + @cpl ].min)
217
- end
218
-
219
- true
220
- }
221
- next
222
- end
223
- else
224
- if @scroll_timeout != nil
225
- GLib::Source.remove @scroll_timeout
226
- @scroll_timeout = nil
227
- end
424
+ def get_selection
425
+ [ @selection.start, @selection.end ].sort
228
426
  end
229
427
 
230
- next if event.window != xdisp.window
231
-
232
- hex_to_pointer(x,y) if @active_view == View::HEX and @button == 1
233
- end
234
-
235
- put @xdisp, 0, 0
236
- @xdisp.show
237
-
238
- @adisp = DrawingArea.new
239
- @adisp.modify_font @font_desc
240
- @alayout = @adisp.create_pango_layout('')
241
- @adisp.events =
242
- Gdk::Event::EXPOSURE_MASK |
243
- Gdk::Event::BUTTON_PRESS_MASK |
244
- Gdk::Event::BUTTON_RELEASE_MASK |
245
- Gdk::Event::BUTTON_MOTION_MASK |
246
- Gdk::Event::SCROLL_MASK
247
-
248
-
249
- @adisp.signal_connect 'realize' do
250
- @adisp_gc = Gdk::GC.new(@adisp.window)
251
- @adisp_gc.set_exposures(true)
252
- end
253
-
254
- @adisp.signal_connect 'expose_event' do |adisp, event|
255
- imin = (event.area.y / @char_height).to_i
256
- imax = ((event.area.y + event.area.height) / @char_height).to_i
257
- imax += 1 if (event.area.y + event.area.height).to_i % @char_height != 0
258
-
259
- imax = [ imax, @vis_lines ].min
260
- render_ascii_lines(imin, imax)
261
- end
262
-
263
- @adisp.signal_connect 'scroll_event' do |adisp, event|
264
- @scrollbar.event(event)
265
- end
266
-
267
- @adisp.signal_connect 'button_press_event' do |adisp, event|
268
- mouse_handler[adisp, event]
269
- end
270
-
271
- @adisp.signal_connect 'button_release_event' do |adisp, event|
272
- mouse_handler[adisp, event]
273
- end
274
-
275
- @adisp.signal_connect 'motion_notify_event' do |adisp, event|
276
- w, x, y, m = adisp.window.pointer
277
-
278
- if y < 0
279
- @scroll_dir = -1
280
- elsif y >= adisp.allocation.height
281
- @scroll_dir = 1
282
- else
283
- @scroll_dir = 0
428
+ def clear_selection
429
+ set_selection(0, 0)
284
430
  end
285
431
 
286
- if @scroll_dir != 0
287
- if @scroll_timeout == nil
288
- @scroll_timeout = GLib::Timeout.add(SCROLL_TIMEOUT) {
289
- if @scroll_dir < 0
290
- set_cursor([ 0, @cursor_pos - @cpl ].max)
291
- elsif @scroll_dir > 0
292
- set_cursor([ @data.size - 1, @cursor_pos + @cpl ].min)
293
- end
294
-
295
- true
296
- }
297
- next
298
- end
299
- else
300
- if @scroll_timeout != nil
301
- GLib::Source.remove @scroll_timeout
302
- @scroll_timeout = nil
303
- end
432
+ def cursor
433
+ @cursor_pos
304
434
  end
305
435
 
306
- next if event.window != adisp.window
307
-
308
- ascii_to_pointer(x,y) if @active_view == View::ASCII and @button == 1
309
- end
310
-
311
- put @adisp, 0, 0
312
- @adisp.show
313
-
314
- @adj = Gtk::Adjustment.new(0, 0, 0, 0, 0, 0)
315
- @scrollbar = Gtk::VScrollbar.new(@adj)
316
- @adj.signal_connect 'value_changed' do |adj|
317
- unless @xdisp_gc.nil? or @adisp_gc.nil? or not @xdisp.drawable? or not @adisp.drawable?
318
-
319
- source_min = (adj.value.to_i - @top_line) * @char_height
320
- source_max = source_min + @xdisp.allocation.height
321
- dest_min = 0
322
- dest_max = @xdisp.allocation.height
323
-
324
- rect = Gdk::Rectangle.new(0, 0, 0, 0)
325
- @top_line = adj.value.to_i
326
- if source_min < 0
327
- rect.y = 0
328
- rect.height = -source_min
329
- rect_height = [ rect.height, @xdisp.allocation.height ].min
330
- source_min = 0
331
- dest_min = rect.height
332
- else
333
- rect.y = 2 * @xdisp.allocation.height - source_max
334
- rect.y = 0 if rect.y < 0
335
- rect.height = @xdisp.allocation.height - rect.y
336
- source_max = @xdisp.allocation.height
337
- dest_max = rect.y
338
- end
339
-
340
- if source_min != source_max
341
- @xdisp.window.draw_drawable(
342
- @xdisp_gc,
343
- @xdisp.window,
344
- 0, source_min,
345
- 0, dest_min,
346
- @xdisp.allocation.width,
347
- source_max - source_min
348
- )
349
- @adisp.window.draw_drawable(
350
- @adisp_gc,
351
- @adisp.window,
352
- 0, source_min,
353
- 0, dest_min,
354
- @adisp.allocation.width,
355
- source_max - source_min
356
- )
436
+ def set_cursor(index)
437
+ return if index < 0 or index > @data.size
357
438
 
358
- if @offsets
359
- if @offsets_gc.nil?
360
- @offsets_gc = Gdk::GC.new(@offsets.window)
361
- @offsets_gc.set_exposures(true)
362
- end
439
+ old_pos = @cursor_pos
440
+ index -= 1 if @insert and index == @data.size
441
+ index = [ 0, index ].max
363
442
 
364
- @offsets.window.draw_drawable(
365
- @offsets_gc,
366
- @offsets.window,
367
- 0, source_min,
368
- 0, dest_min,
369
- @offsets.allocation.width,
370
- source_max - source_min
371
- )
443
+ hide_cursor
444
+
445
+ @cursor_pos = index
446
+ return if @cpl == 0
447
+
448
+ y = index / @cpl
449
+ if y >= @top_line + @vis_lines
450
+ @adj.value = [ y - @vis_lines + 1, @lines - @vis_lines ].min
451
+ @adj.value = [ 0, @adj.value ].max
452
+ @adj.signal_emit 'value_changed'
453
+ elsif y < @top_line
454
+ @adj.value = y
455
+ @adj.signal_emit 'value_changed'
372
456
  end
373
457
 
374
- # TODO update_all_auto_highlights(true, true)
375
- invalidate_all_highlights
376
-
377
- rect.width = @xdisp.allocation.width
378
- @xdisp.window.invalidate(rect, false)
379
- rect.width = @adisp.allocation.width
380
- @adisp.window.invalidate(rect, false)
458
+ @lower_nibble = false if index == @data.size
381
459
 
382
- if @offsets
383
- rect.width = @offsets.allocation.width
384
- @offsets.window.invalidate(rect, false)
460
+ if @selecting
461
+ set_selection(@selection.start, @cursor_pos)
462
+ bytes_changed(*[@cursor_pos, old_pos].sort)
463
+ else# @selection.start != @selection.end
464
+ s, e = [@selection.start, @selection.end].sort
465
+ @selection.end = @selection.start = @cursor_pos
466
+ bytes_changed(s, e)
385
467
  end
386
- end
468
+
469
+ self.signal_emit 'cursor_moved'
470
+
471
+ bytes_changed(old_pos, old_pos)
472
+ show_cursor
387
473
  end
388
- end
389
474
 
390
- put @scrollbar, 0, 0
391
- @scrollbar.show
392
- end
475
+ def set_cursor_xy(x, y)
476
+ pos = y.to_i * @cpl + x.to_i
477
+ return if y < 0 or y >= @lines or x < 0 or x >= @cpl or pos > @data.size
393
478
 
394
- def set_selection(s, e)
395
- e = [ e, @data.size ].min
479
+ set_cursor(pos)
480
+ end
396
481
 
397
- @@primary.clear if @selection.start != @selection.end
482
+ def set_cursor_on_lower_nibble(bool)
483
+ if @selecting
484
+ bytes_changed(@cursor_pos, @cursor_pos)
485
+ @lower_nibble = bool
486
+ elsif @selection.start != @selection.end
487
+ s, e = [ @selection.start, @selection.end ].sort
488
+
489
+ @selection.start = @selection.end = 0
490
+ bytes_changed(s, e)
491
+ @lower_nibble = bool
492
+ else
493
+ hide_cursor
494
+ @lower_nibble = bool
495
+ show_cursor
496
+ end
497
+ end
398
498
 
399
- os, oe = [ @selection.start, @selection.end ].sort
499
+ def set_group_type(type)
500
+ hide_cursor
501
+ @group_type = type
502
+ recalc_displays(self.allocation.width, self.allocation.height)
503
+ self.queue_resize
504
+ show_cursor
505
+ end
506
+
507
+ def show_offsets(bool)
508
+ return unless @show_offsets ^ bool
400
509
 
401
- @selection.start = [ 0, s ].max
402
- @selection.start = [ @selection.start, @data.size ].min
403
- @selection.end = [ e, @data.size ].min
510
+ @show_offsets = bool
511
+ if bool
512
+ show_offsets_widget
513
+ else
514
+ hide_offsets_widget
515
+ end
516
+ end
404
517
 
405
- invalidate_highlight(@selection)
518
+ def set_font(fontname)
519
+ @font_desc = Pango::FontDescription.new(fontname)
520
+ @disp_font_metrics = load_font(fontname)
406
521
 
407
- ns, ne = [ @selection.start, @selection.end ].sort
522
+ @xdisp.modify_font(@font_desc) if @xdisp
523
+ @adisp.modify_font(@font_desc) if @adisp
524
+ @offsets.modify_font(@font_desc) if @offsets
408
525
 
409
- if ns != os and ne != oe
410
- bytes_changed([ns, os].min, [ne, oe].max)
411
- elsif ne != oe
412
- bytes_changed(*[ne, oe].sort)
413
- elsif ns != os
414
- bytes_changed(*[ns, os].sort)
415
- end
526
+ @char_width = get_max_char_width(@disp_font_metrics)
527
+ @char_height = Pango.pixels(@disp_font_metrics.ascent) + Pango.pixels(@disp_font_metrics.descent) + 2
528
+ recalc_displays(self.allocation.width, self.allocation.height)
416
529
 
417
- if @selection.start != @selection.end
418
- if @active_view == View::HEX
419
- brk_len = 2 * @cpl + @cpl / @group_type
420
- format_xblock(s,e)
421
- (@disp_buffer.size / brk_len + 1).times do |i| @disp_buffer.insert(i * (brk_len + 1), $/) end
422
- else
423
- brk_len = @cpl
424
- format_ablock(s,e)
530
+ redraw_widget
425
531
  end
426
532
 
427
- @@primary.set_text(@disp_buffer)
428
- end
429
- end
533
+ def set_data(data)
534
+ prev_data_size = @data.size
535
+ @data = data.dup
430
536
 
431
- def get_selection
432
- [ @selection.start, @selection.end ].sort
433
- end
537
+ recalc_displays(self.allocation.width, self.allocation.height)
434
538
 
435
- def clear_selection
436
- set_selection(0, 0)
437
- end
539
+ set_cursor 0
540
+ bytes_changed(0, [ prev_data_size, @data.size ].max)
541
+ redraw_widget
542
+ end
438
543
 
439
- def cursor
440
- @cursor_pos
441
- end
544
+ def validate_highlight(hl)
545
+ unless hl.valid
546
+ hl.start_line = [ hl.start, hl.end ].min / @cpl - @top_line
547
+ hl.end_line = [ hl.start, hl.end ].max / @cpl - @top_line
548
+ hl.valid = true
549
+ end
550
+ end
442
551
 
443
- def set_cursor(index)
444
- return if index < 0 or index > @data.size
445
-
446
- old_pos = @cursor_pos
447
- index -= 1 if @insert and index == @data.size
448
- index = [ 0, index ].max
449
-
450
- hide_cursor
451
-
452
- @cursor_pos = index
453
- return if @cpl == 0
454
-
455
- y = index / @cpl
456
- if y >= @top_line + @vis_lines
457
- @adj.value = [ y - @vis_lines + 1, @lines - @vis_lines ].min
458
- @adj.value = [ 0, @adj.value ].max
459
- @adj.signal_emit 'value_changed'
460
- elsif y < @top_line
461
- @adj.value = y
462
- @adj.signal_emit 'value_changed'
463
- end
464
-
465
- @lower_nibble = false if index == @data.size
466
-
467
- if @selecting
468
- set_selection(@selection.start, @cursor_pos)
469
- bytes_changed(*[@cursor_pos, old_pos].sort)
470
- else# @selection.start != @selection.end
471
- s, e = [@selection.start, @selection.end].sort
472
- @selection.end = @selection.start = @cursor_pos
473
- bytes_changed(s, e)
474
- end
475
-
476
- self.signal_emit 'cursor_moved'
477
-
478
- bytes_changed(old_pos, old_pos)
479
- show_cursor
480
- end
552
+ def invalidate_highlight(hl)
553
+ hl.valid = false
554
+ end
481
555
 
482
- def set_cursor_xy(x, y)
483
- pos = y.to_i * @cpl + x.to_i
484
- return if y < 0 or y >= @lines or x < 0 or x >= @cpl or pos > @data.size
556
+ def invalidate_all_highlights
557
+ @highlights.each do |hl| invalidate_highlight(hl) end
558
+ end
485
559
 
486
- set_cursor(pos)
487
- end
560
+ private
488
561
 
489
- def set_cursor_on_lower_nibble(bool)
490
- if @selecting
491
- bytes_changed(@cursor_pos, @cursor_pos)
492
- @lower_nibble = bool
493
- elsif @selection.start != @selection.end
494
- s, e = [ @selection.start, @selection.end ].sort
495
-
496
- @selection.start = @selection.end = 0
497
- bytes_changed(s, e)
498
- @lower_nibble = bool
499
- else
500
- hide_cursor
501
- @lower_nibble = bool
502
- show_cursor
503
- end
504
- end
562
+ signal_new(
563
+ 'data_changed',
564
+ GLib::Signal::RUN_FIRST,
565
+ nil,
566
+ nil,
567
+ String
568
+ )
505
569
 
506
- def set_group_type(type)
507
- hide_cursor
508
- @group_type = type
509
- recalc_displays(self.allocation.width, self.allocation.height)
510
- self.queue_resize
511
- show_cursor
512
- end
570
+ signal_new(
571
+ 'cursor_moved',
572
+ GLib::Signal::RUN_FIRST,
573
+ nil,
574
+ nil
575
+ )
513
576
 
514
- def show_offsets(bool)
515
- return unless @show_offsets ^ bool
577
+ def signal_do_cursor_moved
578
+ end
516
579
 
517
- @show_offsets = bool
518
- if bool
519
- show_offsets_widget
520
- else
521
- hide_offsets_widget
522
- end
523
- end
580
+ def signal_do_data_changed(data)
581
+ # TODO
582
+ end
524
583
 
525
- def set_font(fontname)
526
- @font_desc = Pango::FontDescription.new(fontname)
527
- @disp_font_metrics = load_font(fontname)
584
+ def signal_do_realize
585
+ super
528
586
 
529
- @xdisp.modify_font(@font_desc) if @xdisp
530
- @adisp.modify_font(@font_desc) if @adisp
531
- @offsets.modify_font(@font_desc) if @offsets
587
+ self.window.set_back_pixmap(nil, true)
588
+ end
532
589
 
533
- @char_width = get_max_char_width(@disp_font_metrics)
534
- @char_height = Pango.pixels(@disp_font_metrics.ascent) + Pango.pixels(@disp_font_metrics.descent) + 2
535
- recalc_displays(self.allocation.width, self.allocation.height)
590
+ def signal_do_size_allocate(alloc)
591
+ hide_cursor
536
592
 
537
- redraw_widget
538
- end
593
+ recalc_displays(alloc.width, alloc.height)
594
+
595
+ self.set_allocation(alloc.x, alloc.y, alloc.width, alloc.height)
596
+ self.window.move_resize(
597
+ alloc.x, alloc.y,
598
+ alloc.width, alloc.height
599
+ ) if self.realized?
600
+
601
+ bw = self.border_width
602
+ xt = widget_get_xt
603
+ yt = widget_get_yt
604
+
605
+ my_alloc = Gtk::Allocation.new(0, 0, 0, 0)
606
+ my_alloc.x = bw + xt
607
+ my_alloc.y = bw + yt
608
+ my_alloc.height = [ alloc.height - 2*bw - 2*yt, 1 ].max
609
+ if @show_offsets
610
+ my_alloc.width = 8 * @char_width
611
+ @offsets.size_allocate(my_alloc)
612
+ @offsets.queue_draw
613
+ my_alloc.x += 2*xt + my_alloc.width
614
+ end
539
615
 
540
- def set_data(data)
541
- prev_data_size = @data.size
542
- @data = data.dup
616
+ my_alloc.width = @xdisp_width
617
+ @xdisp.size_allocate(my_alloc)
543
618
 
544
- recalc_displays(self.allocation.width, self.allocation.height)
545
-
546
- set_cursor 0
547
- bytes_changed(0, [ prev_data_size, @data.size ].max)
548
- redraw_widget
549
- end
619
+ my_alloc.x = alloc.width - bw - @scrollbar.requisition[0]
620
+ my_alloc.y = bw
621
+ my_alloc.width = @scrollbar.requisition[0]
622
+ my_alloc.height = [ alloc.height - 2*bw, 1 ].max
623
+ @scrollbar.size_allocate(my_alloc)
550
624
 
551
- def validate_highlight(hl)
552
- unless hl.valid
553
- hl.start_line = [ hl.start, hl.end ].min / @cpl - @top_line
554
- hl.end_line = [ hl.start, hl.end ].max / @cpl - @top_line
555
- hl.valid = true
556
- end
557
- end
625
+ my_alloc.x -= @adisp_width + xt
626
+ my_alloc.y = bw + yt
627
+ my_alloc.width = @adisp_width
628
+ my_alloc.height = [ alloc.height - 2*bw - 2*yt, 1 ].max
629
+ @adisp.size_allocate(my_alloc)
558
630
 
559
- def invalidate_highlight(hl)
560
- hl.valid = false
561
- end
631
+ show_cursor
632
+ end
562
633
 
563
- def invalidate_all_highlights
564
- @highlights.each do |hl| invalidate_highlight(hl) end
565
- end
634
+ def signal_do_size_request(req)
635
+ sb_width, _sb_height = @scrollbar.size_request
636
+ bw = self.border_width
637
+ xt, yt = widget_get_xt, widget_get_yt
566
638
 
567
- private
639
+ width = 4*xt + 2*bw + sb_width +
640
+ @char_width*(DEFAULT_CPL + (DEFAULT_CPL-1)/@group_type)
568
641
 
569
- signal_new(
570
- 'data_changed',
571
- GLib::Signal::RUN_FIRST,
572
- nil,
573
- nil,
574
- String
575
- )
642
+ width += 2*xt + 8*@char_width if @show_offsets
576
643
 
577
- signal_new(
578
- 'cursor_moved',
579
- GLib::Signal::RUN_FIRST,
580
- nil,
581
- nil
582
- )
644
+ height = DEFAULT_LINES * @char_height + 2*yt + 2*bw
583
645
 
584
- def signal_do_cursor_moved
585
- end
646
+ req[0] = width
647
+ req[1] = height
648
+ end
586
649
 
587
- def signal_do_data_changed(data)
588
- # TODO
589
- end
650
+ def signal_do_expose_event(event)
651
+ draw_shadow(event.area)
652
+ super(event)
590
653
 
591
- def signal_do_realize
592
- super
654
+ true
655
+ end
593
656
 
594
- self.window.set_back_pixmap(nil, true)
595
- end
657
+ def signal_do_key_press_event(event)
596
658
 
597
- def signal_do_size_allocate(alloc)
598
- hide_cursor
599
-
600
- recalc_displays(alloc.width, alloc.height)
601
-
602
- self.set_allocation(alloc.x, alloc.y, alloc.width, alloc.height)
603
- self.window.move_resize(
604
- alloc.x, alloc.y,
605
- alloc.width, alloc.height
606
- ) if self.realized?
607
-
608
- bw = self.border_width
609
- xt = widget_get_xt
610
- yt = widget_get_yt
611
-
612
- my_alloc = Gtk::Allocation.new(0, 0, 0, 0)
613
- my_alloc.x = bw + xt
614
- my_alloc.y = bw + yt
615
- my_alloc.height = [ alloc.height - 2*bw - 2*yt, 1 ].max
616
- if @show_offsets
617
- my_alloc.width = 8 * @char_width
618
- @offsets.size_allocate(my_alloc)
619
- @offsets.queue_draw
620
- my_alloc.x += 2*xt + my_alloc.width
621
- end
622
-
623
- my_alloc.width = @xdisp_width
624
- @xdisp.size_allocate(my_alloc)
625
-
626
- my_alloc.x = alloc.width - bw - @scrollbar.requisition[0]
627
- my_alloc.y = bw
628
- my_alloc.width = @scrollbar.requisition[0]
629
- my_alloc.height = [ alloc.height - 2*bw, 1 ].max
630
- @scrollbar.size_allocate(my_alloc)
631
-
632
- my_alloc.x -= @adisp_width + xt
633
- my_alloc.y = bw + yt
634
- my_alloc.width = @adisp_width
635
- my_alloc.height = [ alloc.height - 2*bw - 2*yt, 1 ].max
636
- @adisp.size_allocate(my_alloc)
637
-
638
- show_cursor
639
- end
659
+ hide_cursor
660
+ @selecting = (event.state & Gdk::Window::SHIFT_MASK) != 0
661
+ ret = true
662
+
663
+ case event.keyval
664
+ when Gdk::Keyval::GDK_KP_Tab, Gdk::Keyval::GDK_Tab
665
+ @active_view = (@active_view == View::HEX) ? View::ASCII : View::HEX
666
+
667
+ when Gdk::Keyval::GDK_Up
668
+ set_cursor(@cursor_pos - @cpl)
669
+
670
+ when Gdk::Keyval::GDK_Down
671
+ set_cursor(@cursor_pos + @cpl)
672
+
673
+ when Gdk::Keyval::GDK_Page_Up
674
+ set_cursor([0, @cursor_pos - @vis_lines * @cpl].max)
675
+
676
+ when Gdk::Keyval::GDK_Page_Down
677
+ set_cursor([@cursor_pos + @vis_lines * @cpl, @data.size].min)
678
+
679
+ when Gdk::Keyval::GDK_Left
680
+ if @active_view == View::HEX
681
+ if @selecting
682
+ set_cursor(@cursor_pos - 1)
683
+ else
684
+ @lower_nibble ^= 1
685
+ set_cursor(@cursor_pos - 1) if @lower_nibble
686
+ end
687
+ else
688
+ set_cursor(@cursor_pos - 1)
689
+ end
690
+
691
+ when Gdk::Keyval::GDK_Right
692
+ if @active_view == View::HEX
693
+ if @selecting
694
+ set_cursor(@cursor_pos + 1)
695
+ else
696
+ @lower_nibble ^= 1
697
+ set_cursor(@cursor_pos + 1) unless @lower_nibble
698
+ end
699
+ else
700
+ set_cursor(@cursor_pos + 1)
701
+ end
702
+
703
+ when Gdk::Keyval::GDK_c, Gdk::Keyval::GDK_C
704
+ if event.state & Gdk::Window::CONTROL_MASK != 0
705
+ s,e = @selection.start, @selection.end + 1
706
+ if @active_view == View::HEX
707
+ brk_len = 2 * @cpl + @cpl / @group_type
708
+ format_xblock(s,e)
709
+ (@disp_buffer.size / brk_len + 1).times do |i| @disp_buffer.insert(i * (brk_len + 1), $/) end
710
+ else
711
+ brk_len = @cpl
712
+ format_ablock(s,e)
713
+ end
714
+
715
+ @@clipboard.set_text(@disp_buffer)
716
+ end
717
+ else
718
+ ret = false
719
+ end
640
720
 
641
- def signal_do_size_request(req)
642
- sb_width, sb_height = @scrollbar.size_request
643
- bw = self.border_width
644
- xt, yt = widget_get_xt, widget_get_yt
721
+ show_cursor
645
722
 
646
- width = 4*xt + 2*bw + sb_width +
647
- @char_width*(DEFAULT_CPL + (DEFAULT_CPL-1)/@group_type)
723
+ ret
724
+ end
648
725
 
649
- width += 2*xt + 8*@char_width if @show_offsets
726
+ def hex_to_pointer(mx, my)
727
+ cy = @top_line + my.to_i / @char_height
650
728
 
651
- height = DEFAULT_LINES * @char_height + 2*yt + 2*bw
652
-
653
- req[0] = width
654
- req[1] = height
655
- end
729
+ cx = x = 0
730
+ while cx < 2 * @cpl
731
+ x += @char_width
656
732
 
657
- def signal_do_expose_event(event)
658
- draw_shadow(event.area)
659
- super(event)
733
+ if x > mx
734
+ set_cursor_xy(cx / 2, cy)
735
+ set_cursor_on_lower_nibble(cx % 2 != 0)
660
736
 
661
- true
662
- end
737
+ cx = 2 * @cpl
738
+ end
663
739
 
664
- def signal_do_key_press_event(event)
665
- old_cp = @cursor_pos
740
+ cx += 1
741
+ x += @char_width if ( cx % (2 * @group_type) == 0 )
742
+ end
743
+ end
666
744
 
667
- hide_cursor
668
- @selecting = (event.state & Gdk::Window::SHIFT_MASK) != 0
669
- ret = true
745
+ def ascii_to_pointer(mx, my)
746
+ cx = mx / @char_width
747
+ cy = @top_line + my / @char_height
670
748
 
671
- case event.keyval
672
- when Gdk::Keyval::GDK_KP_Tab, Gdk::Keyval::GDK_Tab
673
- @active_view = (@active_view == View::HEX) ? View::ASCII : View::HEX
674
-
675
- when Gdk::Keyval::GDK_Up
676
- set_cursor(@cursor_pos - @cpl)
749
+ set_cursor_xy(cx, cy)
750
+ end
677
751
 
678
- when Gdk::Keyval::GDK_Down
679
- set_cursor(@cursor_pos + @cpl)
752
+ def load_font(fontname)
753
+ desc = Pango::FontDescription.new(fontname)
754
+ context = Gdk::Pango.context
755
+ context.set_language(Gtk.default_language)
680
756
 
681
- when Gdk::Keyval::GDK_Page_Up
682
- set_cursor([0, @cursor_pos - @vis_lines * @cpl].max)
757
+ font = context.load_font(desc)
683
758
 
684
- when Gdk::Keyval::GDK_Page_Down
685
- set_cursor([@cursor_pos + @vis_lines * @cpl, @data.size].min)
759
+ font.metrics(context.language)
760
+ end
686
761
 
687
- when Gdk::Keyval::GDK_Left
688
- if @active_view == View::HEX
689
- if @selecting
690
- set_cursor(@cursor_pos - 1)
691
- else
692
- @lower_nibble ^= 1
693
- set_cursor(@cursor_pos - 1) if @lower_nibble
762
+ def draw_shadow(area)
763
+ bw = self.border_width
764
+ x = bw
765
+ xt = widget_get_xt
766
+
767
+ if @show_offsets
768
+ self.style.paint_shadow(
769
+ self.window,
770
+ Gtk::STATE_NORMAL, Gtk::SHADOW_IN,
771
+ nil, self, nil,
772
+ bw, bw,
773
+ 8*@char_width + 2*xt, self.allocation.height - 2*bw
774
+ )
775
+
776
+ x += 8*@char_width + 2*xt
694
777
  end
695
- else
696
- set_cursor(@cursor_pos - 1)
697
- end
698
778
 
699
- when Gdk::Keyval::GDK_Right
700
- if @active_view == View::HEX
701
- if @selecting
702
- set_cursor(@cursor_pos + 1)
703
- else
704
- @lower_nibble ^= 1
705
- set_cursor(@cursor_pos + 1) unless @lower_nibble
706
- end
707
- else
708
- set_cursor(@cursor_pos + 1)
709
- end
710
-
711
- when Gdk::Keyval::GDK_c, Gdk::Keyval::GDK_C
712
- if event.state & Gdk::Window::CONTROL_MASK != 0
713
- s,e = @selection.start, @selection.end + 1
714
- if @active_view == View::HEX
715
- brk_len = 2 * @cpl + @cpl / @group_type
716
- format_xblock(s,e)
717
- (@disp_buffer.size / brk_len + 1).times do |i| @disp_buffer.insert(i * (brk_len + 1), $/) end
718
- else
719
- brk_len = @cpl
720
- format_ablock(s,e)
721
- end
779
+ self.style.paint_shadow(
780
+ self.window,
781
+ Gtk::STATE_NORMAL, Gtk::SHADOW_IN,
782
+ nil, self, nil,
783
+ x, bw,
784
+ @xdisp_width + 2*xt, self.allocation.height - 2*bw
785
+ )
722
786
 
723
- @@clipboard.set_text(@disp_buffer)
724
- end
725
- else
726
- ret = false
727
- end
787
+ self.style.paint_shadow(
788
+ self.window,
789
+ Gtk::STATE_NORMAL, Gtk::SHADOW_IN,
790
+ nil, self, nil,
791
+ self.allocation.width - bw - @adisp_width - @scrollbar.requisition[0] - 2*xt, bw,
792
+ @adisp_width + 2*xt, self.allocation.height - 2*bw
793
+ )
794
+ end
728
795
 
729
- show_cursor
730
-
731
- ret
732
- end
796
+ def redraw_widget
797
+ return unless self.realized?
733
798
 
734
- def hex_to_pointer(mx, my)
735
- cy = @top_line + my.to_i / @char_height
736
-
737
- cx = x = 0
738
- while cx < 2 * @cpl
739
- x += @char_width
799
+ self.window.invalidate(nil, false)
800
+ end
740
801
 
741
- if x > mx
742
- set_cursor_xy(cx / 2, cy)
743
- set_cursor_on_lower_nibble(cx % 2 != 0)
802
+ def widget_get_xt
803
+ self.style.xthickness
804
+ end
744
805
 
745
- cx = 2 * @cpl
806
+ def widget_get_yt
807
+ self.style.ythickness
746
808
  end
747
809
 
748
- cx += 1
749
- x += @char_width if ( cx % (2 * @group_type) == 0 )
750
- end
751
- end
810
+ def recalc_displays(width, height)
811
+ old_cpl = @cpl
752
812
 
753
- def ascii_to_pointer(mx, my)
754
- cx = mx / @char_width
755
- cy = @top_line + my / @char_height
813
+ w, _h = @scrollbar.size_request
814
+ @xdisp_width = 1
815
+ @adisp_width = 1
756
816
 
757
- set_cursor_xy(cx, cy)
758
- end
817
+ total_width = width - 2 * self.border_width - 4 * widget_get_xt - w
818
+ total_width -= 2 * widget_get_xt + 8 * @char_width if @show_offsets
759
819
 
760
- def load_font(fontname)
761
- desc = Pango::FontDescription.new(fontname)
762
- context = Gdk::Pango.context
763
- context.set_language(Gtk.default_language)
764
-
765
- font = context.load_font(desc)
766
-
767
- font.metrics(context.language)
768
- end
820
+ total_cpl = total_width / @char_width
821
+ if total_cpl == 0 or total_width < 0
822
+ @cpl = @lines = @vis_lines = 0
823
+ return
824
+ end
769
825
 
770
- def draw_shadow(area)
771
- bw = self.border_width
772
- x = bw
773
- xt = widget_get_xt
774
-
775
- if @show_offsets
776
- self.style.paint_shadow(
777
- self.window,
778
- Gtk::STATE_NORMAL, Gtk::SHADOW_IN,
779
- nil, self, nil,
780
- bw, bw,
781
- 8*@char_width + 2*xt, self.allocation.height - 2*bw
782
- )
826
+ @cpl = 0
827
+ begin
828
+ break if @cpl % @group_type == 0 and total_cpl < @group_type * 3
783
829
 
784
- x += 8*@char_width + 2*xt
785
- end
786
-
787
- self.style.paint_shadow(
788
- self.window,
789
- Gtk::STATE_NORMAL, Gtk::SHADOW_IN,
790
- nil, self, nil,
791
- x, bw,
792
- @xdisp_width + 2*xt, self.allocation.height - 2*bw
793
- )
794
-
795
- self.style.paint_shadow(
796
- self.window,
797
- Gtk::STATE_NORMAL, Gtk::SHADOW_IN,
798
- nil, self, nil,
799
- self.allocation.width - bw - @adisp_width - @scrollbar.requisition[0] - 2*xt, bw,
800
- @adisp_width + 2*xt, self.allocation.height - 2*bw
801
- )
802
- end
830
+ @cpl += 1
831
+ total_cpl -= 3
803
832
 
804
- def redraw_widget
805
- return unless self.realized?
833
+ total_cpl -= 1 if @cpl % @group_type == 0
834
+ end while total_cpl > 0
806
835
 
807
- self.window.invalidate(nil, false)
808
- end
836
+ return if @cpl == 0
809
837
 
810
- def widget_get_xt
811
- self.style.xthickness
812
- end
838
+ if @data.empty?
839
+ @lines = 1
840
+ else
841
+ @lines = @data.size / @cpl
842
+ @lines += 1 if @data.size % @cpl != 0
843
+ end
813
844
 
814
- def widget_get_yt
815
- self.style.ythickness
816
- end
845
+ @vis_lines = (height - 2*self.border_width - 2*widget_get_yt).to_i / @char_height.to_i
846
+ @adisp_width = @cpl * @char_width + 1
847
+ xcpl = @cpl * 2 + (@cpl - 1) / @group_type
848
+ @xdisp_width = xcpl * @char_width + 1
817
849
 
818
- def recalc_displays(width, height)
819
- old_cpl = @cpl
820
-
821
- w, h = @scrollbar.size_request
822
- @xdisp_width = 1
823
- @adisp_width = 1
824
-
825
- total_width = width - 2 * self.border_width - 4 * widget_get_xt - w
826
- total_width -= 2 * widget_get_xt + 8 * @char_width if @show_offsets
827
-
828
- total_cpl = total_width / @char_width
829
- if total_cpl == 0 or total_width < 0
830
- @cpl = @lines = @vis_lines = 0
831
- return
832
- end
833
-
834
- @cpl = 0
835
- begin
836
- break if @cpl % @group_type == 0 and total_cpl < @group_type * 3
837
-
838
- @cpl += 1
839
- total_cpl -= 3
840
-
841
- total_cpl -= 1 if @cpl % @group_type == 0
842
- end while total_cpl > 0
843
-
844
- return if @cpl == 0
845
-
846
- if @data.empty?
847
- @lines = 1
848
- else
849
- @lines = @data.size / @cpl
850
- @lines += 1 if @data.size % @cpl != 0
851
- end
852
-
853
- @vis_lines = (height - 2*self.border_width - 2*widget_get_yt).to_i / @char_height.to_i
854
- @adisp_width = @cpl * @char_width + 1
855
- xcpl = @cpl * 2 + (@cpl - 1) / @group_type
856
- @xdisp_width = xcpl * @char_width + 1
857
-
858
- @disp_buffer = ''
859
-
860
- @adj.value = [@top_line * old_cpl / @cpl, @lines - @vis_lines].min
861
- @adj.value = [ 0, @adj.value ].max
862
- if @cursor_pos / @cpl < @adj.value or @cursor_pos / @cpl > @adj.value + @vis_lines - 1
863
- @adj.value = [ @cursor_pos / @cpl, @lines - @vis_lines ].min
864
- @adj.value = [ 0, @adj.value ].max
865
- end
866
-
867
- @adj.lower = 0
868
- @adj.upper = @lines
869
- @adj.step_increment = 1
870
- @adj.page_increment = @vis_lines - 1
871
- @adj.page_size = @vis_lines
872
-
873
- @adj.signal_emit 'changed'
874
- @adj.signal_emit 'value_changed'
875
- end
850
+ @disp_buffer = ''
876
851
 
877
- def get_max_char_width(metrics)
852
+ @adj.value = [@top_line * old_cpl / @cpl, @lines - @vis_lines].min
853
+ @adj.value = [ 0, @adj.value ].max
854
+ if @cursor_pos / @cpl < @adj.value or @cursor_pos / @cpl > @adj.value + @vis_lines - 1
855
+ @adj.value = [ @cursor_pos / @cpl, @lines - @vis_lines ].min
856
+ @adj.value = [ 0, @adj.value ].max
857
+ end
878
858
 
879
- layout = self.create_pango_layout('')
880
- layout.set_font_description(@font_desc)
881
- char_widths = [ 0 ]
859
+ @adj.lower = 0
860
+ @adj.upper = @lines
861
+ @adj.step_increment = 1
862
+ @adj.page_increment = @vis_lines - 1
863
+ @adj.page_size = @vis_lines
882
864
 
883
- (1..100).each do |i|
884
- logical_rect = Pango::Rectangle.new(0, 0, 0, 0)
885
- if is_displayable(i.chr)
886
- layout.set_text(i.chr)
887
- logical_rect = layout.pixel_extents[1]
865
+ @adj.signal_emit 'changed'
866
+ @adj.signal_emit 'value_changed'
888
867
  end
889
- char_widths << logical_rect.width
890
- end
891
868
 
892
- char_widths[48..122].max
893
- end
869
+ def get_max_char_width(metrics)
870
+ layout = self.create_pango_layout('')
871
+ layout.set_font_description(@font_desc)
872
+ char_widths = [ 0 ]
873
+
874
+ (1..100).each do |i|
875
+ logical_rect = Pango::Rectangle.new(0, 0, 0, 0)
876
+ if is_displayable(i.chr)
877
+ layout.set_text(i.chr)
878
+ logical_rect = layout.pixel_extents[1]
879
+ end
880
+ char_widths << logical_rect.width
881
+ end
894
882
 
895
- def show_cursor
896
- unless @cursor_shown
897
- if @xdisp_gc and @adisp_gc and @xdisp.realized? and @adisp.realized?
898
- render_xc
899
- render_ac
883
+ char_widths[48..122].max
900
884
  end
901
885
 
902
- @cursor_shown = true
903
- end
904
- end
886
+ def show_cursor
887
+ unless @cursor_shown
888
+ if @xdisp_gc and @adisp_gc and @xdisp.realized? and @adisp.realized?
889
+ render_xc
890
+ render_ac
891
+ end
905
892
 
906
- def hide_cursor
907
- if @cursor_shown
908
- if @xdisp_gc and @adisp_gc and @xdisp.realized? and @adisp.realized?
909
- render_byte(@cursor_pos)
893
+ @cursor_shown = true
894
+ end
910
895
  end
911
896
 
912
- @cursor_shown = false
913
- end
914
- end
897
+ def hide_cursor
898
+ if @cursor_shown
899
+ if @xdisp_gc and @adisp_gc and @xdisp.realized? and @adisp.realized?
900
+ render_byte(@cursor_pos)
901
+ end
915
902
 
916
- def show_offsets_widget
917
- @offsets = DrawingArea.new
918
- @offsets.modify_font @font_desc
919
- @olayout = @offsets.create_pango_layout('')
903
+ @cursor_shown = false
904
+ end
905
+ end
920
906
 
921
- @offsets.events = Gdk::Event::EXPOSURE_MASK
922
- @offsets.signal_connect 'expose_event' do |offsets, event|
923
- imin = (event.area.y / @char_height).to_i
924
- imax = ((event.area.y + event.area.height) / @char_height).to_i
925
- imax += 1 if (event.area.y + event.area.height).to_i % @char_height != 0
907
+ def show_offsets_widget
908
+ @offsets = DrawingArea.new
909
+ @offsets.modify_font @font_desc
910
+ @olayout = @offsets.create_pango_layout('')
926
911
 
927
- imax = [ imax, @vis_lines ].min
912
+ @offsets.events = Gdk::Event::EXPOSURE_MASK
913
+ @offsets.signal_connect 'expose_event' do |offsets, event|
914
+ imin = (event.area.y / @char_height).to_i
915
+ imax = ((event.area.y + event.area.height) / @char_height).to_i
916
+ imax += 1 if (event.area.y + event.area.height).to_i % @char_height != 0
928
917
 
929
- render_offsets(imin, imax)
930
- end
918
+ imax = [ imax, @vis_lines ].min
931
919
 
932
- put @offsets, 0, 0
933
- @offsets.show
934
- end
920
+ render_offsets(imin, imax)
921
+ end
935
922
 
936
- def hide_offsets_widget
937
- if @offsets
938
- self.remove(@offsets)
939
- @offsets = @offsets_gc = nil
940
- end
941
- end
923
+ put @offsets, 0, 0
924
+ @offsets.show
925
+ end
942
926
 
943
- def is_displayable(c)
944
- if RUBY_VERSION < '1.9'
945
- c = c[0]
946
- else
947
- c = c.ord
948
- end
927
+ def hide_offsets_widget
928
+ if @offsets
929
+ self.remove(@offsets)
930
+ @offsets = @offsets_gc = nil
931
+ end
932
+ end
949
933
 
950
- c >= 0x20 and c < 0x7f
951
- end
934
+ def is_displayable(c)
935
+ c = c.ord
936
+ c >= 0x20 and c < 0x7f
937
+ end
952
938
 
953
- def bytes_changed(s, e)
954
- start_line = s / @cpl - @top_line
955
- end_line = e / @cpl - @top_line
939
+ def bytes_changed(s, e)
940
+ start_line = s / @cpl - @top_line
941
+ end_line = e / @cpl - @top_line
956
942
 
957
- return if end_line < 0 or start_line > @vis_lines
943
+ return if end_line < 0 or start_line > @vis_lines
958
944
 
959
- start_line = [ 0, start_line ].max
945
+ start_line = [ 0, start_line ].max
960
946
 
961
- render_hex_lines(start_line, end_line)
962
- render_ascii_lines(start_line, end_line)
963
- render_offsets(start_line, end_line) if @show_offsets
964
- end
947
+ render_hex_lines(start_line, end_line)
948
+ render_ascii_lines(start_line, end_line)
949
+ render_offsets(start_line, end_line) if @show_offsets
950
+ end
965
951
 
966
- def render_hex_highlights(cursor_line)
967
- xcpl = @cpl * 2 + @cpl / @group_type
968
-
969
- @highlights.each do |hl|
970
- next if (hl.start - hl.end).abs < hl.min_select
971
-
972
- validate_highlight(hl)
973
-
974
- s, e = [ hl.start, hl.end ].sort
975
- sl, el = hl.start_line, hl.end_line
976
-
977
- hl.style.attach(@xdisp.window) if hl.style
978
- state = (@active_view == View::HEX) ? Gtk::STATE_SELECTED : Gtk::STATE_INSENSITIVE
979
-
980
- if cursor_line == sl
981
- cursor_off = 2 * (s % @cpl) + (s % @cpl) / @group_type
982
- if cursor_line == el
983
- len = 2 * (e % @cpl + 1) + (e % @cpl) / @group_type
984
- else
985
- len = xcpl
986
- end
987
-
988
- len -= cursor_off
989
- (hl.style || self.style).paint_flat_box(
990
- @xdisp.window,
991
- state, Gtk::SHADOW_NONE,
992
- nil, @xdisp, '',
993
- cursor_off * @char_width, cursor_line * @char_height,
994
- len * @char_width, @char_height
995
- ) if len > 0
996
-
997
- elsif cursor_line == el
998
- cursor_off = 2 * (e % @cpl + 1) + (e % @cpl) / @group_type
999
- (hl.style || self.style).paint_flat_box(
1000
- @xdisp.window,
1001
- state, Gtk::SHADOW_NONE,
1002
- nil, @xdisp, '',
1003
- 0, cursor_line * @char_height,
1004
- cursor_off * @char_width, @char_height
1005
- ) if cursor_off > 0
1006
-
1007
- elsif cursor_line > sl and cursor_line < el
1008
- (hl.style || self.style).paint_flat_box(
1009
- @xdisp.window,
1010
- state, Gtk::SHADOW_NONE,
1011
- nil, @xdisp, '',
1012
- 0, cursor_line * @char_height,
1013
- xcpl * @char_width, @char_height
1014
- )
952
+ def render_hex_highlights(cursor_line)
953
+ xcpl = @cpl * 2 + @cpl / @group_type
954
+
955
+ @highlights.each do |hl|
956
+ next if (hl.start - hl.end).abs < hl.min_select
957
+
958
+ validate_highlight(hl)
959
+
960
+ s, e = [ hl.start, hl.end ].sort
961
+ sl, el = hl.start_line, hl.end_line
962
+
963
+ hl.style.attach(@xdisp.window) if hl.style
964
+ state = (@active_view == View::HEX) ? Gtk::STATE_SELECTED : Gtk::STATE_INSENSITIVE
965
+
966
+ if cursor_line == sl
967
+ cursor_off = 2 * (s % @cpl) + (s % @cpl) / @group_type
968
+ if cursor_line == el
969
+ len = 2 * (e % @cpl + 1) + (e % @cpl) / @group_type
970
+ else
971
+ len = xcpl
972
+ end
973
+
974
+ len -= cursor_off
975
+ (hl.style || self.style).paint_flat_box(
976
+ @xdisp.window,
977
+ state, Gtk::SHADOW_NONE,
978
+ nil, @xdisp, '',
979
+ cursor_off * @char_width, cursor_line * @char_height,
980
+ len * @char_width, @char_height
981
+ ) if len > 0
982
+
983
+ elsif cursor_line == el
984
+ cursor_off = 2 * (e % @cpl + 1) + (e % @cpl) / @group_type
985
+ (hl.style || self.style).paint_flat_box(
986
+ @xdisp.window,
987
+ state, Gtk::SHADOW_NONE,
988
+ nil, @xdisp, '',
989
+ 0, cursor_line * @char_height,
990
+ cursor_off * @char_width, @char_height
991
+ ) if cursor_off > 0
992
+
993
+ elsif cursor_line > sl and cursor_line < el
994
+ (hl.style || self.style).paint_flat_box(
995
+ @xdisp.window,
996
+ state, Gtk::SHADOW_NONE,
997
+ nil, @xdisp, '',
998
+ 0, cursor_line * @char_height,
999
+ xcpl * @char_width, @char_height
1000
+ )
1001
+ end
1002
+
1003
+ hl.style.attach(@adisp.window) if hl.style
1004
+ end
1015
1005
  end
1016
-
1017
- hl.style.attach(@adisp.window) if hl.style
1018
- end
1019
- end
1020
1006
 
1021
- def render_hex_lines(imin, imax)
1022
- return unless self.realized? and @cpl != 0
1007
+ def render_hex_lines(imin, imax)
1008
+ return unless self.realized? and @cpl != 0
1009
+
1010
+ cursor_line = @cursor_pos / @cpl - @top_line
1023
1011
 
1024
- cursor_line = @cursor_pos / @cpl - @top_line
1012
+ @xdisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL))
1013
+ @xdisp.window.draw_rectangle(
1014
+ @xdisp_gc,
1015
+ true,
1016
+ 0,
1017
+ imin * @char_height,
1018
+ @xdisp.allocation.width,
1019
+ (imax - imin + 1) * @char_height
1020
+ )
1025
1021
 
1026
- @xdisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL))
1027
- @xdisp.window.draw_rectangle(
1028
- @xdisp_gc,
1029
- true,
1030
- 0,
1031
- imin * @char_height,
1032
- @xdisp.allocation.width,
1033
- (imax - imin + 1) * @char_height
1034
- )
1022
+ imax = [ imax, @vis_lines, @lines ].min
1035
1023
 
1036
- imax = [ imax, @vis_lines, @lines ].min
1024
+ @xdisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL))
1037
1025
 
1038
- @xdisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL))
1026
+ frm_len = format_xblock((@top_line+imin) * @cpl, [(@top_line+imax+1) * @cpl, @data.size].min)
1039
1027
 
1040
- frm_len = format_xblock((@top_line+imin) * @cpl, [(@top_line+imax+1) * @cpl, @data.size].min)
1028
+ tmp = nil
1029
+ xcpl = @cpl*2 + @cpl/@group_type
1030
+ (imin..imax).each do |i|
1031
+ return unless (tmp = frm_len - ((i - imin) * xcpl)) > 0
1041
1032
 
1042
- tmp = nil
1043
- xcpl = @cpl*2 + @cpl/@group_type
1044
- (imin..imax).each do |i|
1045
- return unless (tmp = frm_len - ((i - imin) * xcpl)) > 0
1046
-
1047
- render_hex_highlights(i)
1048
- text = @disp_buffer[(i-imin) * xcpl, [xcpl, tmp].min]
1049
- @xlayout.set_text(text)
1050
- @xdisp.window.draw_layout(@xdisp_gc, 0, i * @char_height, @xlayout)
1051
- end
1033
+ render_hex_highlights(i)
1034
+ text = @disp_buffer[(i-imin) * xcpl, [xcpl, tmp].min]
1035
+ @xlayout.set_text(text)
1036
+ @xdisp.window.draw_layout(@xdisp_gc, 0, i * @char_height, @xlayout)
1037
+ end
1052
1038
 
1053
- render_xc if cursor_line >= imin and cursor_line <= imax and @cursor_shown
1054
- end
1039
+ render_xc if cursor_line >= imin and cursor_line <= imax and @cursor_shown
1040
+ end
1055
1041
 
1056
- def render_ascii_highlights(cursor_line)
1057
- @highlights.each do |hl|
1058
- next if (hl.start - hl.end).abs < hl.min_select
1042
+ def render_ascii_highlights(cursor_line)
1043
+ @highlights.each do |hl|
1044
+ next if (hl.start - hl.end).abs < hl.min_select
1045
+
1046
+ validate_highlight(hl)
1047
+
1048
+ s, e = [ hl.start, hl.end ].sort
1049
+ sl, el = hl.start_line, hl.end_line
1050
+
1051
+ hl.style.attach(@adisp.window) if hl.style
1052
+ state = (@active_view == View::ASCII) ? Gtk::STATE_SELECTED : Gtk::STATE_INSENSITIVE
1053
+
1054
+ if cursor_line == sl
1055
+ cursor_off = s % @cpl
1056
+ len =
1057
+ if cursor_line == el
1058
+ e - s + 1
1059
+ else
1060
+ @cpl - cursor_off
1061
+ end
1062
+
1063
+ (hl.style || self.style).paint_flat_box(
1064
+ @adisp.window,
1065
+ state, Gtk::SHADOW_NONE,
1066
+ nil, @adisp, '',
1067
+ cursor_off * @char_width, cursor_line * @char_height,
1068
+ len * @char_width, @char_height
1069
+ ) if len > 0
1070
+
1071
+ elsif cursor_line == el
1072
+ cursor_off = e % @cpl + 1
1073
+ (hl.style || self.style).paint_flat_box(
1074
+ @adisp.window,
1075
+ state, Gtk::SHADOW_NONE,
1076
+ nil, @adisp, '',
1077
+ 0, cursor_line * @char_height,
1078
+ cursor_off * @char_width, @char_height
1079
+ ) if cursor_off > 0
1080
+
1081
+ elsif cursor_line > sl and cursor_line < el
1082
+ (hl.style || self.style).paint_flat_box(
1083
+ @adisp.window,
1084
+ state, Gtk::SHADOW_NONE,
1085
+ nil, @adisp, '',
1086
+ 0, cursor_line * @char_height,
1087
+ @cpl * @char_width, @char_height
1088
+ )
1089
+ end
1090
+
1091
+ hl.style.attach(@adisp.window) if hl.style
1092
+ end
1093
+ end
1059
1094
 
1060
- validate_highlight(hl)
1095
+ def render_ascii_lines(imin, imax)
1096
+ return unless self.realized? and @cpl != 0
1061
1097
 
1062
- s, e = [ hl.start, hl.end ].sort
1063
- sl, el = hl.start_line, hl.end_line
1098
+ cursor_line = @cursor_pos / @cpl - @top_line
1064
1099
 
1065
- hl.style.attach(@adisp.window) if hl.style
1066
- state = (@active_view == View::ASCII) ? Gtk::STATE_SELECTED : Gtk::STATE_INSENSITIVE
1100
+ @adisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL))
1101
+ @adisp.window.draw_rectangle(
1102
+ @adisp_gc,
1103
+ true,
1104
+ 0,
1105
+ imin * @char_height,
1106
+ @adisp.allocation.width,
1107
+ (imax - imin + 1) * @char_height
1108
+ )
1067
1109
 
1068
- if cursor_line == sl
1069
- cursor_off = s % @cpl
1070
- len =
1071
- if cursor_line == el
1072
- e - s + 1
1073
- else
1074
- @cpl - cursor_off
1110
+ imax = [ imax, @vis_lines, @lines ].min
1111
+
1112
+ @adisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL))
1113
+
1114
+ frm_len = format_ablock((@top_line+imin) * @cpl, [(@top_line+imax+1) * @cpl, @data.size].min)
1115
+
1116
+ tmp = nil
1117
+ (imin..imax).each do |i|
1118
+ return unless (tmp = frm_len - ((i - imin) * @cpl)) > 0
1119
+
1120
+ render_ascii_highlights(i)
1121
+ text = @disp_buffer[(i-imin) * @cpl, [@cpl, tmp].min]
1122
+ @alayout.set_text(text)
1123
+ @adisp.window.draw_layout(@adisp_gc, 0, i * @char_height, @alayout)
1075
1124
  end
1076
1125
 
1077
- (hl.style || self.style).paint_flat_box(
1078
- @adisp.window,
1079
- state, Gtk::SHADOW_NONE,
1080
- nil, @adisp, '',
1081
- cursor_off * @char_width, cursor_line * @char_height,
1082
- len * @char_width, @char_height
1083
- ) if len > 0
1084
-
1085
- elsif cursor_line == el
1086
- cursor_off = e % @cpl + 1
1087
- (hl.style || self.style).paint_flat_box(
1088
- @adisp.window,
1089
- state, Gtk::SHADOW_NONE,
1090
- nil, @adisp, '',
1091
- 0, cursor_line * @char_height,
1092
- cursor_off * @char_width, @char_height
1093
- ) if cursor_off > 0
1094
-
1095
- elsif cursor_line > sl and cursor_line < el
1096
- (hl.style || self.style).paint_flat_box(
1097
- @adisp.window,
1098
- state, Gtk::SHADOW_NONE,
1099
- nil, @adisp, '',
1100
- 0, cursor_line * @char_height,
1101
- @cpl * @char_width, @char_height
1102
- )
1126
+ render_ac if cursor_line >= imin and cursor_line <= imax and @cursor_shown
1103
1127
  end
1104
1128
 
1105
- hl.style.attach(@adisp.window) if hl.style
1106
- end
1107
- end
1129
+ def render_offsets(imin, imax)
1130
+ return unless self.realized?
1108
1131
 
1109
- def render_ascii_lines(imin, imax)
1110
- return unless self.realized? and @cpl != 0
1111
-
1112
- cursor_line = @cursor_pos / @cpl - @top_line
1113
-
1114
- @adisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL))
1115
- @adisp.window.draw_rectangle(
1116
- @adisp_gc,
1117
- true,
1118
- 0,
1119
- imin * @char_height,
1120
- @adisp.allocation.width,
1121
- (imax - imin + 1) * @char_height
1122
- )
1123
-
1124
- imax = [ imax, @vis_lines, @lines ].min
1125
-
1126
- @adisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL))
1127
-
1128
- frm_len = format_ablock((@top_line+imin) * @cpl, [(@top_line+imax+1) * @cpl, @data.size].min)
1129
-
1130
- tmp = nil
1131
- (imin..imax).each do |i|
1132
- return unless (tmp = frm_len - ((i - imin) * @cpl)) > 0
1133
-
1134
- render_ascii_highlights(i)
1135
- text = @disp_buffer[(i-imin) * @cpl, [@cpl, tmp].min]
1136
- @alayout.set_text(text)
1137
- @adisp.window.draw_layout(@adisp_gc, 0, i * @char_height, @alayout)
1138
- end
1139
-
1140
- render_ac if cursor_line >= imin and cursor_line <= imax and @cursor_shown
1141
- end
1132
+ unless @offsets_gc
1133
+ @offsets_gc = Gdk::GC.new(@offsets.window)
1134
+ @offsets_gc.set_exposures(true)
1135
+ end
1142
1136
 
1143
- def render_offsets(imin, imax)
1144
- return unless self.realized?
1145
-
1146
- unless @offsets_gc
1147
- @offsets_gc = Gdk::GC.new(@offsets.window)
1148
- @offsets_gc.set_exposures(true)
1149
- end
1150
-
1151
- @offsets_gc.set_foreground(self.style.base(Gtk::STATE_INSENSITIVE))
1152
- @offsets.window.draw_rectangle(
1153
- @offsets_gc,
1154
- true,
1155
- 0, imin * @char_height,
1156
- @offsets.allocation.width, (imax - imin + 1) * @char_height
1157
- )
1158
-
1159
- imax = [ imax, @vis_lines, @lines - @top_line - 1 ].min
1160
- @offsets_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL))
1161
-
1162
- (imin..imax).each do |i|
1163
- text = "%08x" % ((@top_line + i) * @cpl + @starting_offset)
1164
- @olayout.set_text(text)
1165
- @offsets.window.draw_layout(@offsets_gc, 0, i * @char_height, @olayout)
1166
- end
1167
- end
1137
+ @offsets_gc.set_foreground(self.style.base(Gtk::STATE_INSENSITIVE))
1138
+ @offsets.window.draw_rectangle(
1139
+ @offsets_gc,
1140
+ true,
1141
+ 0, imin * @char_height,
1142
+ @offsets.allocation.width, (imax - imin + 1) * @char_height
1143
+ )
1168
1144
 
1169
- def render_byte(pos)
1170
- return unless @xdisp_gc and @adisp_gc and @xdisp.realized? and @adisp.realized?
1171
-
1172
- return unless (coords = get_xcoords(pos))
1173
- cx, cy = coords
1174
- c = format_xbyte(pos)
1175
-
1176
- @xdisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL))
1177
- @xdisp.window.draw_rectangle(
1178
- @xdisp_gc,
1179
- true,
1180
- cx, cy,
1181
- 2 * @char_width, @char_height
1182
- )
1183
-
1184
- if pos < @data.size
1185
- @xdisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL))
1186
- @xlayout.set_text(c)
1187
- @xdisp.window.draw_layout(@xdisp_gc, cx, cy, @xlayout)
1188
- end
1189
-
1190
- return unless (coords = get_acoords(pos))
1191
- cx, cy = coords
1192
-
1193
- @adisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL))
1194
- @adisp.window.draw_rectangle(
1195
- @adisp_gc,
1196
- true,
1197
- cx, cy,
1198
- @char_width, @char_height
1199
- )
1200
-
1201
- if pos < @data.size
1202
- @adisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL))
1203
- c = get_byte(pos)
1204
- c = '.' unless is_displayable(c)
1205
-
1206
- @alayout.set_text(c)
1207
- @adisp.window.draw_layout(@adisp_gc, cx, cy, @alayout)
1208
- end
1209
- end
1145
+ imax = [ imax, @vis_lines, @lines - @top_line - 1 ].min
1146
+ @offsets_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL))
1147
+
1148
+ (imin..imax).each do |i|
1149
+ text = "%08x" % ((@top_line + i) * @cpl + @starting_offset)
1150
+ @olayout.set_text(text)
1151
+ @offsets.window.draw_layout(@offsets_gc, 0, i * @char_height, @olayout)
1152
+ end
1153
+ end
1154
+
1155
+ def render_byte(pos)
1156
+ return unless @xdisp_gc and @adisp_gc and @xdisp.realized? and @adisp.realized?
1157
+
1158
+ return unless (coords = get_xcoords(pos))
1159
+ cx, cy = coords
1160
+ c = format_xbyte(pos)
1210
1161
 
1211
- def render_xc
1212
- return unless @xdisp.realized?
1162
+ @xdisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL))
1163
+ @xdisp.window.draw_rectangle(
1164
+ @xdisp_gc,
1165
+ true,
1166
+ cx, cy,
1167
+ 2 * @char_width, @char_height
1168
+ )
1169
+
1170
+ if pos < @data.size
1171
+ @xdisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL))
1172
+ @xlayout.set_text(c)
1173
+ @xdisp.window.draw_layout(@xdisp_gc, cx, cy, @xlayout)
1174
+ end
1213
1175
 
1214
- if coords = get_xcoords(@cursor_pos)
1215
- cx, cy = coords
1176
+ return unless (coords = get_acoords(pos))
1177
+ cx, cy = coords
1216
1178
 
1217
- c = format_xbyte(@cursor_pos)
1218
- if @lower_nibble
1219
- cx += @char_width
1220
- c = c[1,1]
1221
- else
1222
- c = c[0,1]
1179
+ @adisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL))
1180
+ @adisp.window.draw_rectangle(
1181
+ @adisp_gc,
1182
+ true,
1183
+ cx, cy,
1184
+ @char_width, @char_height
1185
+ )
1186
+
1187
+ if pos < @data.size
1188
+ @adisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL))
1189
+ c = get_byte(pos)
1190
+ c = '.' unless is_displayable(c)
1191
+
1192
+ @alayout.set_text(c)
1193
+ @adisp.window.draw_layout(@adisp_gc, cx, cy, @alayout)
1194
+ end
1223
1195
  end
1224
1196
 
1225
- @xdisp_gc.set_foreground(self.style.base(Gtk::STATE_ACTIVE))
1226
- @xdisp.window.draw_rectangle(
1227
- @xdisp_gc,
1228
- (@active_view == View::HEX),
1229
- cx, cy,
1230
- @char_width,
1231
- @char_height - 1
1232
- )
1233
- @xdisp_gc.set_foreground(self.style.text(Gtk::STATE_ACTIVE))
1234
- @xlayout.set_text(c)
1235
- @xdisp.window.draw_layout(@xdisp_gc, cx, cy, @xlayout)
1236
- end
1237
- end
1197
+ def render_xc
1198
+ return unless @xdisp.realized?
1199
+
1200
+ if coords = get_xcoords(@cursor_pos)
1201
+ cx, cy = coords
1202
+
1203
+ c = format_xbyte(@cursor_pos)
1204
+ if @lower_nibble
1205
+ cx += @char_width
1206
+ c = c[1,1]
1207
+ else
1208
+ c = c[0,1]
1209
+ end
1210
+
1211
+ @xdisp_gc.set_foreground(self.style.base(Gtk::STATE_ACTIVE))
1212
+ @xdisp.window.draw_rectangle(
1213
+ @xdisp_gc,
1214
+ (@active_view == View::HEX),
1215
+ cx, cy,
1216
+ @char_width,
1217
+ @char_height - 1
1218
+ )
1219
+ @xdisp_gc.set_foreground(self.style.text(Gtk::STATE_ACTIVE))
1220
+ @xlayout.set_text(c)
1221
+ @xdisp.window.draw_layout(@xdisp_gc, cx, cy, @xlayout)
1222
+ end
1223
+ end
1238
1224
 
1239
- def render_ac
1240
- return unless @adisp.realized?
1241
-
1242
- if coords = get_acoords(@cursor_pos)
1243
- cx, cy = coords
1244
-
1245
- c = get_byte(@cursor_pos)
1246
- c = '.' unless is_displayable(c)
1247
-
1248
- @adisp_gc.set_foreground(self.style.base(Gtk::STATE_ACTIVE))
1249
- @adisp.window.draw_rectangle(
1250
- @adisp_gc,
1251
- (@active_view == View::ASCII),
1252
- cx, cy,
1253
- @char_width,
1254
- @char_height - 1
1255
- )
1256
- @adisp_gc.set_foreground(self.style.text(Gtk::STATE_ACTIVE))
1257
- @alayout.set_text(c)
1258
- @adisp.window.draw_layout(@adisp_gc, cx, cy, @alayout)
1259
- end
1260
- end
1225
+ def render_ac
1226
+ return unless @adisp.realized?
1227
+
1228
+ if coords = get_acoords(@cursor_pos)
1229
+ cx, cy = coords
1230
+
1231
+ c = get_byte(@cursor_pos)
1232
+ c = '.' unless is_displayable(c)
1233
+
1234
+ @adisp_gc.set_foreground(self.style.base(Gtk::STATE_ACTIVE))
1235
+ @adisp.window.draw_rectangle(
1236
+ @adisp_gc,
1237
+ (@active_view == View::ASCII),
1238
+ cx, cy,
1239
+ @char_width,
1240
+ @char_height - 1
1241
+ )
1242
+ @adisp_gc.set_foreground(self.style.text(Gtk::STATE_ACTIVE))
1243
+ @alayout.set_text(c)
1244
+ @adisp.window.draw_layout(@adisp_gc, cx, cy, @alayout)
1245
+ end
1246
+ end
1261
1247
 
1262
- def get_xcoords(pos)
1263
- return nil if @cpl == 0
1248
+ def get_xcoords(pos)
1249
+ return nil if @cpl == 0
1264
1250
 
1265
- cy = pos / @cpl - @top_line
1266
- return nil if cy < 0
1251
+ cy = pos / @cpl - @top_line
1252
+ return nil if cy < 0
1267
1253
 
1268
- cx = 2 * (pos % @cpl)
1269
- spaces = (pos % @cpl) / @group_type
1254
+ cx = 2 * (pos % @cpl)
1255
+ spaces = (pos % @cpl) / @group_type
1270
1256
 
1271
- cx *= @char_width
1272
- cy *= @char_height
1273
- spaces *= @char_width
1257
+ cx *= @char_width
1258
+ cy *= @char_height
1259
+ spaces *= @char_width
1274
1260
 
1275
- [cx + spaces, cy]
1276
- end
1261
+ [cx + spaces, cy]
1262
+ end
1277
1263
 
1278
- def get_acoords(pos)
1279
- return nil if @cpl == 0
1264
+ def get_acoords(pos)
1265
+ return nil if @cpl == 0
1280
1266
 
1281
- cy = pos / @cpl - @top_line
1282
- return nil if cy < 0
1267
+ cy = pos / @cpl - @top_line
1268
+ return nil if cy < 0
1283
1269
 
1284
- cy *= @char_height
1285
- cx = @char_width * (pos % @cpl)
1270
+ cy *= @char_height
1271
+ cx = @char_width * (pos % @cpl)
1286
1272
 
1287
- [cx, cy]
1288
- end
1273
+ [cx, cy]
1274
+ end
1289
1275
 
1290
- def format_xblock(s, e)
1291
- @disp_buffer = ''
1276
+ def format_xblock(s, e)
1277
+ @disp_buffer = ''
1292
1278
 
1293
- (s+1..e).each do |i|
1294
- @disp_buffer << get_byte(i - 1).unpack('H2')[0]
1295
- @disp_buffer << ' ' if i % @group_type == 0
1296
- end
1279
+ (s+1..e).each do |i|
1280
+ @disp_buffer << get_byte(i - 1).unpack('H2')[0]
1281
+ @disp_buffer << ' ' if i % @group_type == 0
1282
+ end
1297
1283
 
1298
- @disp_buffer.size
1299
- end
1284
+ @disp_buffer.size
1285
+ end
1300
1286
 
1301
- def format_ablock(s, e)
1302
- @disp_buffer = ''
1287
+ def format_ablock(s, e)
1288
+ @disp_buffer = ''
1303
1289
 
1304
- (s..e-1).each do |i|
1305
- c = get_byte(i)
1306
- c = '.' unless is_displayable(c)
1307
- @disp_buffer << c
1308
- end
1290
+ (s..e-1).each do |i|
1291
+ c = get_byte(i)
1292
+ c = '.' unless is_displayable(c)
1293
+ @disp_buffer << c
1294
+ end
1309
1295
 
1310
- @disp_buffer.size
1311
- end
1296
+ @disp_buffer.size
1297
+ end
1312
1298
 
1313
- def get_byte(offset)
1314
- if offset >= 0 and offset < @data.size
1315
- @data[offset, 1]
1316
- else
1317
- 0.chr
1318
- end
1319
- end
1299
+ def get_byte(offset)
1300
+ if offset >= 0 and offset < @data.size
1301
+ @data[offset, 1]
1302
+ else
1303
+ 0.chr
1304
+ end
1305
+ end
1320
1306
 
1321
- def format_xbyte(pos)
1322
- get_byte(pos).unpack('H2')[0]
1307
+ def format_xbyte(pos)
1308
+ get_byte(pos).unpack('H2')[0]
1309
+ end
1323
1310
  end
1324
- end
1325
-
1326
1311
  end
1327
1312
 
1328
1313
  __END__