origami 1.2.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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__