watobo 0.9.19 → 0.9.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (266) hide show
  1. data/CHANGELOG.md +104 -0
  2. data/bin/nfq_server.rb +8 -20
  3. data/bin/watobo_gui.rb +8 -20
  4. data/config/forwarding_proxy.yml +2 -2
  5. data/lib/watobo.rb +12 -22
  6. data/lib/watobo/adapters.rb +12 -24
  7. data/lib/watobo/adapters/data_store.rb +76 -66
  8. data/lib/watobo/adapters/file/file_store.rb +295 -307
  9. data/lib/watobo/adapters/session_store.rb +13 -25
  10. data/lib/watobo/ca.rb +9 -21
  11. data/lib/watobo/config.rb +205 -217
  12. data/lib/watobo/constants.rb +8 -20
  13. data/lib/watobo/core.rb +11 -23
  14. data/lib/watobo/core/active_check.rb +11 -21
  15. data/lib/watobo/core/active_checks.rb +57 -69
  16. data/lib/watobo/core/ca.rb +388 -398
  17. data/lib/watobo/core/cert_store.rb +42 -54
  18. data/lib/watobo/core/chat.rb +100 -112
  19. data/lib/watobo/core/chats.rb +271 -275
  20. data/lib/watobo/core/client_cert_store.rb +33 -45
  21. data/lib/watobo/core/conversation.rb +56 -68
  22. data/lib/watobo/core/cookie.rb +31 -43
  23. data/lib/watobo/core/finding.rb +74 -86
  24. data/lib/watobo/core/findings.rb +113 -125
  25. data/lib/watobo/core/forwarding_proxy.rb +44 -35
  26. data/lib/watobo/core/fuzz_gen.rb +8 -20
  27. data/lib/watobo/core/intercept_carver.rb +176 -188
  28. data/lib/watobo/core/intercept_filter.rb +243 -255
  29. data/lib/watobo/core/interceptor.rb +106 -118
  30. data/lib/watobo/core/min_class.rb +12 -24
  31. data/lib/watobo/core/netfilter_queue.rb +178 -190
  32. data/lib/watobo/core/ott_cache.rb +152 -148
  33. data/lib/watobo/core/parameter.rb +53 -58
  34. data/lib/watobo/core/passive_check.rb +8 -20
  35. data/lib/watobo/core/passive_checks.rb +56 -68
  36. data/lib/watobo/core/passive_scanner.rb +54 -66
  37. data/lib/watobo/core/plugin.rb +19 -31
  38. data/lib/watobo/core/project.rb +8 -20
  39. data/lib/watobo/core/proxy.rb +51 -63
  40. data/lib/watobo/core/request.rb +128 -120
  41. data/lib/watobo/core/response.rb +59 -61
  42. data/lib/watobo/core/scanner.rb +8 -20
  43. data/lib/watobo/core/scanner3.rb +413 -425
  44. data/lib/watobo/core/scope.rb +91 -103
  45. data/lib/watobo/core/session.rb +109 -87
  46. data/lib/watobo/core/sid_cache.rb +106 -118
  47. data/lib/watobo/core/subscriber.rb +33 -45
  48. data/lib/watobo/defaults.rb +29 -41
  49. data/lib/watobo/external/diff/lcs.rb +8 -20
  50. data/lib/watobo/external/diff/lcs/array.rb +8 -20
  51. data/lib/watobo/external/diff/lcs/block.rb +8 -20
  52. data/lib/watobo/external/diff/lcs/callbacks.rb +8 -20
  53. data/lib/watobo/external/diff/lcs/change.rb +8 -20
  54. data/lib/watobo/external/diff/lcs/hunk.rb +8 -20
  55. data/lib/watobo/external/diff/lcs/ldiff.rb +8 -20
  56. data/lib/watobo/external/diff/lcs/string.rb +8 -20
  57. data/lib/watobo/externals.rb +14 -26
  58. data/lib/watobo/framework.rb +12 -24
  59. data/lib/watobo/framework/create_project.rb +68 -80
  60. data/lib/watobo/framework/init.rb +8 -20
  61. data/lib/watobo/framework/init_modules.rb +8 -20
  62. data/lib/watobo/framework/license_text.rb +36 -48
  63. data/lib/watobo/framework/load_chat.rb +21 -33
  64. data/lib/watobo/gui.rb +121 -133
  65. data/lib/watobo/gui/about_watobo.rb +8 -20
  66. data/lib/watobo/gui/browser_preview.rb +8 -20
  67. data/lib/watobo/gui/certificate_dialog.rb +8 -20
  68. data/lib/watobo/gui/chat_diff.rb +11 -21
  69. data/lib/watobo/gui/chatviewer_frame.rb +10 -22
  70. data/lib/watobo/gui/checkboxtree.rb +8 -20
  71. data/lib/watobo/gui/checks_policy_frame.rb +8 -20
  72. data/lib/watobo/gui/client_cert_dialog.rb +10 -21
  73. data/lib/watobo/gui/confirm_scan_dialog.rb +8 -20
  74. data/lib/watobo/gui/conversation_table.rb +54 -44
  75. data/lib/watobo/gui/conversation_table_ctrl.rb +215 -227
  76. data/lib/watobo/gui/conversation_table_ctrl2.rb +385 -393
  77. data/lib/watobo/gui/csrf_token_dialog.rb +11 -25
  78. data/lib/watobo/gui/custom_viewer.rb +357 -369
  79. data/lib/watobo/gui/dashboard.rb +8 -20
  80. data/lib/watobo/gui/define_scope_frame.rb +8 -20
  81. data/lib/watobo/gui/differ_frame.rb +223 -235
  82. data/lib/watobo/gui/edit_comment.rb +8 -20
  83. data/lib/watobo/gui/edit_scope_dialog.rb +8 -20
  84. data/lib/watobo/gui/export_dialog.rb +114 -0
  85. data/lib/watobo/gui/finding_info.rb +9 -21
  86. data/lib/watobo/gui/findings_tree.rb +8 -20
  87. data/lib/watobo/gui/full_scan_dialog.rb +8 -20
  88. data/lib/watobo/gui/fuzzer_gui.rb +8 -20
  89. data/lib/watobo/gui/goto_url_dialog.rb +78 -90
  90. data/lib/watobo/gui/hex_viewer.rb +25 -27
  91. data/lib/watobo/gui/html_viewer.rb +295 -307
  92. data/lib/watobo/gui/intercept_filter_dialog.rb +196 -208
  93. data/lib/watobo/gui/interceptor_gui.rb +1046 -1041
  94. data/lib/watobo/gui/interceptor_settings_dialog.rb +8 -20
  95. data/lib/watobo/gui/list_box.rb +109 -121
  96. data/lib/watobo/gui/log_file_viewer.rb +40 -52
  97. data/lib/watobo/gui/log_viewer.rb +87 -99
  98. data/lib/watobo/gui/login_wizzard.rb +8 -20
  99. data/lib/watobo/gui/main_window.rb +34 -33
  100. data/lib/watobo/gui/manual_request_editor.rb +25 -35
  101. data/lib/watobo/gui/master_pw_dialog.rb +8 -20
  102. data/lib/watobo/gui/mixins/gui_settings.rb +37 -49
  103. data/lib/watobo/gui/page_tree.rb +225 -237
  104. data/lib/watobo/gui/password_policy_dialog.rb +8 -20
  105. data/lib/watobo/gui/plugin_board.rb +8 -20
  106. data/lib/watobo/gui/preferences_dialog.rb +8 -20
  107. data/lib/watobo/gui/progress_window.rb +8 -20
  108. data/lib/watobo/gui/project_wizzard.rb +8 -20
  109. data/lib/watobo/gui/proxy_dialog.rb +117 -85
  110. data/lib/watobo/gui/quick_scan_dialog.rb +8 -20
  111. data/lib/watobo/gui/request_builder_frame.rb +125 -122
  112. data/lib/watobo/gui/request_editor.rb +53 -28
  113. data/lib/watobo/gui/rewrite_filters_dialog.rb +402 -414
  114. data/lib/watobo/gui/rewrite_rules_dialog.rb +380 -392
  115. data/lib/watobo/gui/save_chat_dialog.rb +148 -160
  116. data/lib/watobo/gui/scanner_settings_dialog.rb +8 -20
  117. data/lib/watobo/gui/select_chat_dialog.rb +8 -20
  118. data/lib/watobo/gui/session_management_dialog.rb +8 -20
  119. data/lib/watobo/gui/sites_tree.rb +118 -22
  120. data/lib/watobo/gui/status_bar.rb +8 -20
  121. data/lib/watobo/gui/table_editor.rb +76 -53
  122. data/lib/watobo/gui/tagless_viewer.rb +10 -21
  123. data/lib/watobo/gui/templates/plugin.rb +8 -20
  124. data/lib/watobo/gui/templates/plugin2.rb +99 -111
  125. data/lib/watobo/gui/templates/plugin_base.rb +152 -164
  126. data/lib/watobo/gui/text_viewer.rb +8 -20
  127. data/lib/watobo/gui/transcoder_window.rb +15 -22
  128. data/lib/watobo/gui/utils/gui_utils.rb +8 -20
  129. data/lib/watobo/gui/utils/init_icons.rb +94 -106
  130. data/lib/watobo/gui/utils/load_icons.rb +41 -53
  131. data/lib/watobo/gui/utils/load_plugins.rb +118 -130
  132. data/lib/watobo/gui/utils/master_password.rb +76 -88
  133. data/lib/watobo/gui/utils/save_default_settings.rb +121 -133
  134. data/lib/watobo/gui/utils/save_project_settings.rb +8 -20
  135. data/lib/watobo/gui/utils/save_proxy_settings.rb +53 -21
  136. data/lib/watobo/gui/utils/save_scanner_settings.rb +26 -38
  137. data/lib/watobo/gui/utils/session_history.rb +120 -132
  138. data/lib/watobo/gui/workspace_dialog.rb +8 -20
  139. data/lib/watobo/gui/www_auth_dialog.rb +8 -20
  140. data/lib/watobo/gui/xml_viewer_frame.rb +8 -20
  141. data/lib/watobo/http.rb +12 -23
  142. data/lib/watobo/http/cookies/cookies.rb +63 -70
  143. data/lib/watobo/http/data/data.rb +56 -64
  144. data/lib/watobo/http/data/json.rb +51 -0
  145. data/lib/watobo/http/url/url.rb +46 -58
  146. data/lib/watobo/http/xml/xml.rb +129 -141
  147. data/lib/watobo/interceptor.rb +11 -23
  148. data/lib/watobo/interceptor/proxy.rb +624 -625
  149. data/lib/watobo/interceptor/transparent.rb +22 -34
  150. data/lib/watobo/mixins.rb +18 -30
  151. data/lib/watobo/mixins/check_info.rb +35 -47
  152. data/lib/watobo/mixins/httpparser.rb +42 -35
  153. data/lib/watobo/mixins/request_parser.rb +8 -20
  154. data/lib/watobo/mixins/shapers.rb +484 -477
  155. data/lib/watobo/mixins/transcoders.rb +8 -20
  156. data/lib/watobo/parser.rb +9 -21
  157. data/lib/watobo/parser/html.rb +91 -103
  158. data/lib/watobo/sockets.rb +11 -23
  159. data/lib/watobo/sockets/agent.rb +836 -848
  160. data/lib/watobo/sockets/client_socket.rb +283 -277
  161. data/lib/watobo/sockets/connection.rb +409 -421
  162. data/lib/watobo/sockets/http_socket.rb +16 -23
  163. data/lib/watobo/sockets/ntlm_auth.rb +137 -149
  164. data/lib/watobo/utils.rb +18 -30
  165. data/lib/watobo/utils/check_regex.rb +8 -20
  166. data/lib/watobo/utils/copy_object.rb +8 -20
  167. data/lib/watobo/utils/crypto.rb +8 -20
  168. data/lib/watobo/utils/expand_range.rb +31 -43
  169. data/lib/watobo/utils/export_xml.rb +108 -0
  170. data/lib/watobo/utils/file_management.rb +8 -20
  171. data/lib/watobo/utils/hexprint.rb +17 -29
  172. data/lib/watobo/utils/load_chat.rb +8 -20
  173. data/lib/watobo/utils/load_icon.rb +8 -20
  174. data/lib/watobo/{external/ntlm → utils}/ntlm.rb +874 -796
  175. data/lib/watobo/utils/print_debug.rb +20 -32
  176. data/lib/watobo/utils/response_builder.rb +98 -110
  177. data/lib/watobo/utils/response_hash.rb +9 -20
  178. data/lib/watobo/utils/secure_eval.rb +10 -22
  179. data/lib/watobo/utils/strings.rb +18 -30
  180. data/lib/watobo/utils/text2request.rb +12 -20
  181. data/lib/watobo/utils/url.rb +31 -43
  182. data/lib/watobo/utils/utf16.rb +22 -0
  183. data/modules/active/Apache/mod_status.rb +9 -0
  184. data/modules/active/Apache/multiview.rb +161 -0
  185. data/modules/active/Flash/crossdomain.rb +9 -0
  186. data/modules/active/directories/dirwalker.rb +8 -20
  187. data/modules/active/discovery/fileextensions.rb +10 -22
  188. data/modules/active/discovery/http_methods.rb +8 -20
  189. data/modules/active/domino/domino_db.rb +8 -20
  190. data/modules/active/dotNET/custom_errors.rb +110 -122
  191. data/modules/active/dotNET/dotnet_files.rb +98 -110
  192. data/modules/active/fileinclusion/lfi_simple.rb +8 -20
  193. data/modules/active/jboss/jboss_basic.rb +8 -20
  194. data/modules/active/sap/business_objects.rb +63 -0
  195. data/modules/active/sap/its_commands.rb +8 -20
  196. data/modules/active/sap/its_service_parameter.rb +8 -20
  197. data/modules/active/sap/its_services.rb +8 -20
  198. data/modules/active/sap/its_xss.rb +8 -20
  199. data/modules/active/shell_shock/shell_shock.rb +149 -0
  200. data/modules/active/siebel/siebel_apps.rb +168 -180
  201. data/modules/active/sqlinjection/sql_boolean.rb +9 -21
  202. data/modules/active/sqlinjection/sqli_error.rb +10 -22
  203. data/modules/active/sqlinjection/sqli_timing.rb +228 -240
  204. data/modules/active/struts2/default_handler_ognl.rb +114 -126
  205. data/modules/active/struts2/include_params_ognl.rb +113 -125
  206. data/modules/active/xml/xml_xxe.rb +122 -127
  207. data/modules/active/xss/xss_ng.rb +223 -234
  208. data/modules/active/xss/xss_simple.rb +8 -20
  209. data/modules/passive/ajax.rb +76 -84
  210. data/modules/passive/autocomplete.rb +64 -76
  211. data/modules/passive/cookie_options.rb +8 -20
  212. data/modules/passive/cookie_xss.rb +9 -21
  213. data/modules/passive/detect_code.rb +9 -21
  214. data/modules/passive/detect_fileupload.rb +11 -22
  215. data/modules/passive/detect_infrastructure.rb +23 -35
  216. data/modules/passive/detect_one_time_tokens.rb +8 -20
  217. data/modules/passive/dirindexing.rb +9 -21
  218. data/modules/passive/disclosure_domino.rb +66 -79
  219. data/modules/passive/disclosure_emails.rb +9 -21
  220. data/modules/passive/disclosure_ipaddr.rb +15 -23
  221. data/modules/passive/filename_as_parameter.rb +8 -20
  222. data/modules/passive/form_spotter.rb +15 -21
  223. data/modules/passive/hidden_fields.rb +64 -70
  224. data/modules/passive/hotspots.rb +13 -22
  225. data/modules/passive/in_script_parameter.rb +15 -24
  226. data/modules/passive/multiple_server_headers.rb +8 -20
  227. data/modules/passive/possible_login.rb +12 -23
  228. data/modules/passive/redirect_url.rb +10 -22
  229. data/modules/passive/redirectionz.rb +9 -21
  230. data/modules/passive/sap-headers.rb +64 -76
  231. data/modules/passive/xss_dom.rb +10 -21
  232. data/plugins/catalog/catalog.rb +17 -23
  233. data/plugins/crawler/crawler.rb +12 -24
  234. data/plugins/crawler/gui.rb +13 -25
  235. data/plugins/crawler/gui/auth_frame.rb +278 -290
  236. data/plugins/crawler/gui/crawler_gui.rb +302 -320
  237. data/plugins/crawler/gui/general_settings_frame.rb +104 -116
  238. data/plugins/crawler/gui/hooks_frame.rb +88 -100
  239. data/plugins/crawler/gui/scope_frame.rb +58 -70
  240. data/plugins/crawler/gui/settings_tabbook.rb +46 -58
  241. data/plugins/crawler/gui/status_frame.rb +67 -78
  242. data/plugins/crawler/lib/bags.rb +26 -38
  243. data/plugins/crawler/lib/constants.rb +19 -31
  244. data/plugins/crawler/lib/engine.rb +505 -508
  245. data/plugins/crawler/lib/grabber.rb +77 -87
  246. data/plugins/crawler/lib/status.rb +82 -0
  247. data/plugins/crawler/lib/uri_mp.rb +20 -32
  248. data/plugins/filefinder/dbs/siebel_paths.txt +1118 -0
  249. data/plugins/filefinder/dbs/subs-big.lst +31986 -0
  250. data/plugins/filefinder/filefinder.rb +13 -23
  251. data/plugins/sqlmap/bin/test.rb +86 -98
  252. data/plugins/sqlmap/gui.rb +12 -24
  253. data/plugins/sqlmap/gui/main.rb +226 -238
  254. data/plugins/sqlmap/gui/options_frame.rb +105 -117
  255. data/plugins/sqlmap/lib/sqlmap_ctrl.rb +103 -115
  256. data/plugins/sqlmap/sqlmap.rb +10 -22
  257. data/plugins/sslchecker/cli/sslchecker_cli.rb +8 -20
  258. data/plugins/sslchecker/gui/cipher_table.rb +252 -264
  259. data/plugins/sslchecker/gui/gui.rb +267 -276
  260. data/plugins/sslchecker/gui/sslchecker.rb +12 -24
  261. data/plugins/sslchecker/lib/check.rb +172 -80
  262. data/plugins/wshell/gui/main.rb +115 -127
  263. data/plugins/wshell/lib/core.rb +85 -97
  264. data/plugins/wshell/wshell.rb +19 -31
  265. metadata +14 -6
  266. data/.yardopts +0 -24
@@ -1,24 +1,12 @@
1
- # .
1
+ #.
2
2
  # hex_viewer.rb
3
- #
4
- # Copyright 2013 by siberas, http://www.siberas.de
5
- #
6
- # This file is part of WATOBO (Web Application Tool Box)
7
- # http://watobo.sourceforge.com
8
- #
9
- # WATOBO is free software; you can redistribute it and/or modify
10
- # it under the terms of the GNU General Public License as published by
11
- # the Free Software Foundation version 2 of the License.
12
- #
13
- # WATOBO is distributed in the hope that it will be useful,
14
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # GNU General Public License for more details.
17
- #
18
- # You should have received a copy of the GNU General Public License
19
- # along with WATOBO; if not, write to the Free Software
20
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- # .
3
+ #.
4
+ # Copyright 2014 by siberas, http://www.siberas.de
5
+ # This file is part of WATOBO (Web Application Tool Box) http://watobo.sourceforge.com
6
+ # WATOBO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License.
7
+ # WATOBO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8
+ # You should have received a copy of the GNU General Public License along with WATOBO; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9
+
22
10
  # @private
23
11
  module Watobo#:nodoc: all
24
12
  module Gui
@@ -43,10 +31,10 @@ module Watobo#:nodoc: all
43
31
 
44
32
  if tobject.respond_to? :has_body?
45
33
  raw_text = ""
46
- raw_text << tobject.body.to_s unless tobject.body.nil?
34
+ #raw_text << tobject.body.to_s unless tobject.body.nil?
35
+ raw_text << tobject.to_s
47
36
  end
48
-
49
-
37
+
50
38
 
51
39
  initTable()
52
40
 
@@ -69,8 +57,10 @@ module Watobo#:nodoc: all
69
57
  if pos % 16 == 0 then
70
58
  chunk = raw_text[row*16..pos-1]
71
59
 
72
- # puts chunk
73
- @hexTable.setItemText(row, 16, chunk.gsub(/[^[:print:]]/,'.')) if !chunk.nil?
60
+
61
+ # Filter bad utf-8 chars
62
+ printable = chunk.unpack("C*").pack("C*").gsub(/[^[:print:]]/,'.')
63
+ @hexTable.setItemText(row, 16, printable) if !chunk.nil?
74
64
  @hexTable.getItem(row, 16).justify = FXTableItem::LEFT
75
65
 
76
66
  row = @hexTable.getNumRows
@@ -78,7 +68,7 @@ module Watobo#:nodoc: all
78
68
 
79
69
  # puts "=#{pos}/#{row}"
80
70
  @hexTable.rowHeader.setItemJustify(row, FXTableItem::LEFT)
81
- @hexTable.setRowText(row, "%0.4X" % row.to_s)
71
+ @hexTable.setRowText(row, "%0.4X" % (row*16).to_s)
82
72
 
83
73
  col = -1
84
74
  end
@@ -90,12 +80,20 @@ module Watobo#:nodoc: all
90
80
  @hexTable.getItem(row, 16).justify = FXTableItem::LEFT
91
81
 
92
82
  end
83
+
84
+ 0.upto(16) do |i|
85
+ @hexTable.fitColumnsToContents(i)
86
+ end
93
87
  end
94
88
 
95
89
  def initialize(owner)
96
90
  super(owner, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
97
91
  sunken = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
98
92
  @hexTable = FXTable.new(sunken, :opts => FRAME_SUNKEN|TABLE_COL_SIZABLE|TABLE_ROW_SIZABLE|LAYOUT_FILL_X|LAYOUT_FILL_Y|TABLE_READONLY|LAYOUT_SIDE_TOP, :padding => 2)
93
+ f = FXFont.new(getApp(), "courier", 8, FONTSLANT_REGULAR, FONTENCODING_DEFAULT)
94
+ @hexTable.font = f
95
+ @hexTable.columnHeaderFont = f
96
+ @hexTable.rowHeaderFont = f
99
97
 
100
98
 
101
99
  end
@@ -108,7 +106,7 @@ module Watobo#:nodoc: all
108
106
  0.upto(15) do |i|
109
107
  htext = "%X" % i
110
108
  @hexTable.setColumnText( i, htext)
111
- @hexTable.setColumnWidth(i, 35)
109
+ # @hexTable.setColumnWidth(i, 33)
112
110
  end
113
111
  @hexTable.setColumnWidth(16, 115)
114
112
  end
@@ -1,309 +1,297 @@
1
- # .
1
+ #.
2
2
  # html_viewer.rb
3
- #
4
- # Copyright 2013 by siberas, http://www.siberas.de
5
- #
6
- # This file is part of WATOBO (Web Application Tool Box)
7
- # http://watobo.sourceforge.com
8
- #
9
- # WATOBO is free software; you can redistribute it and/or modify
10
- # it under the terms of the GNU General Public License as published by
11
- # the Free Software Foundation version 2 of the License.
12
- #
13
- # WATOBO is distributed in the hope that it will be useful,
14
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # GNU General Public License for more details.
17
- #
18
- # You should have received a copy of the GNU General Public License
19
- # along with WATOBO; if not, write to the Free Software
20
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
- # .
22
- require 'fox16/scintilla'
23
-
3
+ #.
4
+ # Copyright 2014 by siberas, http://www.siberas.de
5
+ # This file is part of WATOBO (Web Application Tool Box) http://watobo.sourceforge.com
6
+ # WATOBO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License.
7
+ # WATOBO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8
+ # You should have received a copy of the GNU General Public License along with WATOBO; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9
+
10
+ require 'fox16/scintilla'
11
+
24
12
  # @private
25
- module Watobo#:nodoc: all
26
- module Gui
27
- class HTMLViewer < FXScintilla
28
- attr_accessor :max_len
29
-
30
- def search_text(text, &block)
31
- matches = []
32
- setTargetStart 0
33
- setTargetEnd getLength
34
- while searchInTarget(text.length, text) >= 0
35
- pos = getTargetStart
36
- setTargetStart pos+1
37
- setTargetEnd getLength
38
- yield pos if block_given?
39
- matches << pos
40
- end
41
-
42
- matches
43
- end
44
-
45
-
46
- def initialize(owner, opts)
47
- super(owner, nil, 0, opts)
48
- self.setLexer FXScintilla::SCLEX_HTML
49
- self.setCodePage(FXScintilla::SC_CP_UTF8)
50
- self.styleSetFont(FXScintilla::STYLE_DEFAULT, "fixed")
51
- self.styleSetSize(FXScintilla::STYLE_DEFAULT, 9)
52
- self.styleClearAll
53
- self.styleSetFore(FXScintilla::SCE_P_DEFAULT, FXRGB(0x80, 0x80, 0x80) & 0xffffff)
54
- self.styleSetFore(FXScintilla::SCE_P_COMMENTLINE, FXRGB(0x00, 0x7f, 0x00) & 0xffffff)
55
- self.styleSetFore(FXScintilla::SCE_P_NUMBER, FXRGB(0x00, 0x7f, 0x7f) & 0xffffff)
56
- self.styleSetFore(FXScintilla::SCE_P_STRING, FXRGB(0x7f, 0x00, 0x7f) & 0xffffff)
57
- self.styleSetFore(FXScintilla::SCE_P_CHARACTER, FXRGB(0x7f, 0x00, 0x7f) & 0xffffff)
58
- self.styleSetFore(FXScintilla::SCE_P_WORD, FXRGB(0x00, 0x00, 0x7f) & 0xffffff)
59
- self.styleSetBold(FXScintilla::SCE_P_WORD, true)
60
- self.styleSetFore(FXScintilla::SCE_P_TRIPLE, FXRGB(0x7f, 0x00, 0x00) & 0xffffff)
61
- self.styleSetFore(FXScintilla::SCE_P_TRIPLEDOUBLE, FXRGB(0x7f, 0x00, 0x00) & 0xffffff)
62
- self.styleSetFore(FXScintilla::SCE_P_CLASSNAME, FXRGB(0x00, 0x00, 0xff) & 0xffffff)
63
- self.styleSetBold(FXScintilla::SCE_P_CLASSNAME, true)
64
- self.styleSetFore(FXScintilla::SCE_P_DEFNAME, FXRGB(0x00, 0x7f, 0x7f) & 0xffffff)
65
- self.styleSetBold(FXScintilla::SCE_P_DEFNAME, true)
66
- self.styleSetBold(FXScintilla::SCE_P_OPERATOR, true)
67
- self.styleSetFore(FXScintilla::SCE_P_IDENTIFIER, FXRGB(0x7f, 0x7f, 0x7f) & 0xffffff)
68
- self.styleSetFore(FXScintilla::SCE_P_COMMENTBLOCK, FXRGB(0x7f, 0x7f, 0x7f) & 0xffffff)
69
- self.styleSetFore(FXScintilla::SCE_P_STRINGEOL, FXRGB(0x00, 0x00, 0x00) & 0xffffff)
70
- self.styleSetBack(FXScintilla::SCE_P_STRINGEOL, FXRGB(0xe0, 0xc0, 0xe0) & 0xffffff)
71
- self.styleSetEOLFilled(FXScintilla::SCE_P_STRINGEOL, true)
72
- self.styleSetFore(34, FXRGB(0x00, 0x00, 0xff) & 0xffffff)
73
- self.styleSetBold(34, true)
74
- self.styleSetFore(35, FXRGB(0xff, 0x00, 0x00) & 0xffffff)
75
- self.styleSetBold(35, true)
76
- @max_len = 0
77
- end
78
- end
79
-
80
- class HTMLViewerFrame < FXVerticalFrame
81
-
82
- attr_accessor :max_len
83
-
84
- def setText(text, prefs={})
85
-
86
- normalized_text = "- empty -"
87
- if text.is_a? String
88
- normalized_text = text.gsub(/[^[:print:]]/,".")
89
- elsif text.respond_to? :has_body?
90
- unless text.body.nil? or text.body.empty?
91
- body = text.body.strip
92
- if text.content_type =~ /(html|xml)/
93
- doc = Nokogiri::XML(body, &:noblanks)
94
- fbody = doc.to_xhtml( indent:3, indent_text:" ")
95
- normalized_text = fbody.to_s
96
- else
97
- normalized_text = body
98
- end
99
- end
100
- elsif text.is_a? Array
101
- normalized_text = text.join
102
- end
103
-
104
- @text = normalized_text
105
-
106
- # puts normalized_text
107
- @html_viewer.setText(@text)
108
- #@html_viewer.encodedFromUTF8(normalized_text)
109
-
110
- @match_pos_label.text = "0/0"
111
- @match_pos_label.textColor = 'grey'
112
-
113
- @html_viewer.setTargetStart 0
114
- @html_viewer.setTargetEnd @html_viewer.getLength
115
-
116
- applyFilter() if @auto_apply_cbtn.checked?
117
- end
118
-
119
- def highlight(pattern)
120
- highlightPattern(pattern)
121
- end
122
-
123
- def getText
124
- @html_viewer.to_s
125
- end
126
-
127
- def initialize(owner, opts)
128
- super(owner, opts)
129
-
130
- @text_matches = []
131
-
132
- @style = 2 # default style
133
- @text = ''
134
- @max_len = 5000
135
- @filter_mode = SEL_TYPE_HIGHLIGHT
136
- @match_pos = 0
137
-
138
- text_view_header = FXHorizontalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_BOTTOM|LAYOUT_FIX_HEIGHT,:height => 24, :padding => 0)
139
-
140
- #@auto_apply_cbtn.connect(SEL_COMMAND, method(:onInterceptChanged))
141
-
142
- pmatch_btn = FXButton.new(text_view_header, "<", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y)
143
- @match_pos_label = FXLabel.new(text_view_header, "0/0", :opts => LAYOUT_FILL_Y)
144
- @match_pos_label.textColor = 'grey'
145
- pmatch_btn.connect(SEL_COMMAND) { gotoPrevMatch() }
146
- nmatch_btn = FXButton.new(text_view_header, ">", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y)
147
- nmatch_btn.connect(SEL_COMMAND) { gotoNextMatch() }
148
-
149
- # @filter_text = FXTextField.new(text_view_header, 10,
150
- # :target => @filter_dt, :selector => FXDataTarget::ID_VALUE,
151
- # :opts => FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y)
152
-
153
- @filter_text = FXComboBox.new(text_view_header, 20, nil, 0, FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
154
- @filter_text.connect(SEL_COMMAND){
155
- applyFilter()
156
- addFilterHistory()
157
- }
158
-
159
- @filter_text.connect(SEL_CHANGED) {
160
- applyFilter()
161
- }
162
-
163
- @auto_apply_cbtn = FXCheckButton.new(text_view_header, "auto-apply", nil, 0, ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP|LAYOUT_RIGHT|LAYOUT_FILL_Y)
164
-
165
-
166
- text_box_frame = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
167
-
168
- @html_viewer = HTMLViewer.new(text_box_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
169
- #searchflags = FXScintilla::SCFIND_WHOLEWORD|FXScintilla::SCFIND_MATCHCASE|FXScintilla::SCFIND_REGEXP|FXScintilla::SCFIND_WORDSTART
170
- @searchflags = FXScintilla::SCFIND_REGEXP
171
- @html_viewer.setSearchFlags @searchflags
172
-
173
- addHotkeyHandler(@html_viewer)
174
- addHotkeyHandler(@filter_text)
175
-
176
- # @filter_dt.connect(SEL_COMMAND) { applyFilter() }
177
-
178
- end
179
-
180
- def applyFilter
181
- pattern = @filter_text.text
182
- return if pattern.empty?
183
-
184
- @match_pos_label.text = "0/0"
185
- @match_pos_label.textColor = 'grey'
186
-
187
- @text_matches = @html_viewer.search_text(pattern)
188
-
189
-
190
- if @text_matches.length > 0
191
- @match_pos_label.textColor = 'black'
192
- @match_pos_label.text = "1/#{@text_matches.length}"
193
-
194
- show_match_pos(0)
195
- end
196
-
197
- end
198
-
199
- private
200
-
201
- def show_match_pos(match_pos=nil)
202
-
203
- pos = match_pos.nil? ? 0 : match_pos
204
- return false if @text_matches.empty?
205
- return false if pos > @text_matches.length-1
206
- @match_pos = pos
207
- pattern = @filter_text.text
208
- text_pos = @text_matches[pos]
209
- @html_viewer.gotoPos text_pos
210
- @html_viewer.setSel text_pos, text_pos+pattern.length
211
- end
212
-
213
- def show_next
214
- if @match_pos < @text_matches.length-1
215
- @match_pos += 1
216
- show_match_pos @match_pos
217
- return true
218
- end
219
- return false
220
- end
221
-
222
- def show_prev
223
- if @match_pos > 0
224
- @match_pos -= 1
225
- show_match_pos @match_pos
226
- return true
227
- end
228
- return false
229
- end
230
-
231
-
232
- def addFilterHistory()
233
- text = @filter_text.text
234
- return true if text == ''
235
- has_item = false
236
- @filter_text.each do |item, data|
237
- has_item = true if data == text
238
- end
239
- @filter_text.appendItem(text, text) unless has_item == true
240
- @filter_text.numVisible = @filter_text.numItems
241
- end
242
-
243
- def resetFilter
244
- @match_pos_label.text = "0/0"
245
- @match_pos_label.textColor = 'grey'
246
- @filter_text.text = ''
247
- end
248
-
249
- def addHotkeyHandler(widget)
250
- @ctrl_pressed = false
251
-
252
- widget.connect(SEL_KEYPRESS) { |sender, sel, event|
253
- state = false
254
- @ctrl_pressed = true if event.code == KEY_Control_L or event.code == KEY_Control_R
255
- # @shift_pressed = true if @ctrl_pressed and ( event.code == KEY_Shift_L or event.code == KEY_Shift_R )
256
- if event.code == KEY_Return
257
- highlight(@filter_text.text)
258
- state = true # special handling of KEY_Return, because we don't want a linebreak in textbox.
259
- end
260
-
261
- if event.code == KEY_F1
262
-
263
- unless event.moved?
264
- FXMenuPane.new(self) do |menu_pane|
265
- FXMenuCaption.new(menu_pane, "Hotkeys:")
266
- FXMenuSeparator.new(menu_pane)
267
- [ "<ctrl-r> - Reset Filter",
268
- "<ctrl-n> - Goto Next",
269
- "<ctrl-shift-n> - Goto Prev"
270
- ].each do |hk|
271
- FXMenuCaption.new(menu_pane, hk).backColor = 'yellow'
272
- end
273
-
274
- menu_pane.create
275
- menu_pane.popup(nil, event.root_x, event.root_y)
276
- app.runModalWhileShown(menu_pane)
277
- end
278
-
279
- end
280
- end
281
-
282
- if @ctrl_pressed
283
- case event.code
284
- when KEY_n
285
- if show_next
286
- @match_pos_label.text = "#{@match_pos+1}/#{@text_matches.length}"
287
- end
288
- when KEY_N
289
- if show_prev
290
- @match_pos_label.text = "#{@match_pos+1}/#{@text_matches.length}"
291
- end
292
- when KEY_r
293
- resetFilter()
294
-
295
- end
296
- end
297
- state
298
- }
299
-
300
- widget.connect(SEL_KEYRELEASE) { |sender, sel, event|
301
- @ctrl_pressed = false if event.code == KEY_Control_L or event.code == KEY_Control_R
302
- false
303
- }
304
- end
305
-
306
- end
307
- end
308
- end
309
-
13
+ module Watobo#:nodoc: all
14
+ module Gui
15
+ class HTMLViewer < FXScintilla
16
+ attr_accessor :max_len
17
+
18
+ def search_text(text, &block)
19
+ matches = []
20
+ setTargetStart 0
21
+ setTargetEnd getLength
22
+ while searchInTarget(text.length, text) >= 0
23
+ pos = getTargetStart
24
+ setTargetStart pos+1
25
+ setTargetEnd getLength
26
+ yield pos if block_given?
27
+ matches << pos
28
+ end
29
+
30
+ matches
31
+ end
32
+
33
+
34
+ def initialize(owner, opts)
35
+ super(owner, nil, 0, opts)
36
+ self.setLexer FXScintilla::SCLEX_HTML
37
+ self.setCodePage(FXScintilla::SC_CP_UTF8)
38
+ self.styleSetFont(FXScintilla::STYLE_DEFAULT, "fixed")
39
+ self.styleSetSize(FXScintilla::STYLE_DEFAULT, 9)
40
+ self.styleClearAll
41
+ self.styleSetFore(FXScintilla::SCE_P_DEFAULT, FXRGB(0x80, 0x80, 0x80) & 0xffffff)
42
+ self.styleSetFore(FXScintilla::SCE_P_COMMENTLINE, FXRGB(0x00, 0x7f, 0x00) & 0xffffff)
43
+ self.styleSetFore(FXScintilla::SCE_P_NUMBER, FXRGB(0x00, 0x7f, 0x7f) & 0xffffff)
44
+ self.styleSetFore(FXScintilla::SCE_P_STRING, FXRGB(0x7f, 0x00, 0x7f) & 0xffffff)
45
+ self.styleSetFore(FXScintilla::SCE_P_CHARACTER, FXRGB(0x7f, 0x00, 0x7f) & 0xffffff)
46
+ self.styleSetFore(FXScintilla::SCE_P_WORD, FXRGB(0x00, 0x00, 0x7f) & 0xffffff)
47
+ self.styleSetBold(FXScintilla::SCE_P_WORD, true)
48
+ self.styleSetFore(FXScintilla::SCE_P_TRIPLE, FXRGB(0x7f, 0x00, 0x00) & 0xffffff)
49
+ self.styleSetFore(FXScintilla::SCE_P_TRIPLEDOUBLE, FXRGB(0x7f, 0x00, 0x00) & 0xffffff)
50
+ self.styleSetFore(FXScintilla::SCE_P_CLASSNAME, FXRGB(0x00, 0x00, 0xff) & 0xffffff)
51
+ self.styleSetBold(FXScintilla::SCE_P_CLASSNAME, true)
52
+ self.styleSetFore(FXScintilla::SCE_P_DEFNAME, FXRGB(0x00, 0x7f, 0x7f) & 0xffffff)
53
+ self.styleSetBold(FXScintilla::SCE_P_DEFNAME, true)
54
+ self.styleSetBold(FXScintilla::SCE_P_OPERATOR, true)
55
+ self.styleSetFore(FXScintilla::SCE_P_IDENTIFIER, FXRGB(0x7f, 0x7f, 0x7f) & 0xffffff)
56
+ self.styleSetFore(FXScintilla::SCE_P_COMMENTBLOCK, FXRGB(0x7f, 0x7f, 0x7f) & 0xffffff)
57
+ self.styleSetFore(FXScintilla::SCE_P_STRINGEOL, FXRGB(0x00, 0x00, 0x00) & 0xffffff)
58
+ self.styleSetBack(FXScintilla::SCE_P_STRINGEOL, FXRGB(0xe0, 0xc0, 0xe0) & 0xffffff)
59
+ self.styleSetEOLFilled(FXScintilla::SCE_P_STRINGEOL, true)
60
+ self.styleSetFore(34, FXRGB(0x00, 0x00, 0xff) & 0xffffff)
61
+ self.styleSetBold(34, true)
62
+ self.styleSetFore(35, FXRGB(0xff, 0x00, 0x00) & 0xffffff)
63
+ self.styleSetBold(35, true)
64
+ @max_len = 0
65
+ end
66
+ end
67
+
68
+ class HTMLViewerFrame < FXVerticalFrame
69
+
70
+ attr_accessor :max_len
71
+
72
+ def setText(text, prefs={})
73
+
74
+ normalized_text = "- empty -"
75
+ if text.is_a? String
76
+ normalized_text = text.gsub(/[^[:print:]]/,".")
77
+ elsif text.respond_to? :has_body?
78
+ unless text.body.nil? or text.body.empty?
79
+ body = text.body.strip
80
+ if text.content_type =~ /(html|xml)/
81
+ doc = Nokogiri::XML(body, &:noblanks)
82
+ fbody = doc.to_xhtml( indent:3, indent_text:" ")
83
+ normalized_text = fbody.to_s
84
+ else
85
+ normalized_text = body
86
+ end
87
+ end
88
+ elsif text.is_a? Array
89
+ normalized_text = text.join
90
+ end
91
+
92
+ @text = normalized_text
93
+
94
+ # puts normalized_text
95
+ @html_viewer.setText(@text)
96
+ #@html_viewer.encodedFromUTF8(normalized_text)
97
+
98
+ @match_pos_label.text = "0/0"
99
+ @match_pos_label.textColor = 'grey'
100
+
101
+ @html_viewer.setTargetStart 0
102
+ @html_viewer.setTargetEnd @html_viewer.getLength
103
+
104
+ applyFilter() if @auto_apply_cbtn.checked?
105
+ end
106
+
107
+ def highlight(pattern)
108
+ highlightPattern(pattern)
109
+ end
110
+
111
+ def getText
112
+ @html_viewer.to_s
113
+ end
114
+
115
+ def initialize(owner, opts)
116
+ super(owner, opts)
117
+
118
+ @text_matches = []
119
+
120
+ @style = 2 # default style
121
+ @text = ''
122
+ @max_len = 5000
123
+ @filter_mode = SEL_TYPE_HIGHLIGHT
124
+ @match_pos = 0
125
+
126
+ text_view_header = FXHorizontalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_BOTTOM|LAYOUT_FIX_HEIGHT,:height => 24, :padding => 0)
127
+
128
+ #@auto_apply_cbtn.connect(SEL_COMMAND, method(:onInterceptChanged))
129
+
130
+ pmatch_btn = FXButton.new(text_view_header, "<", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y)
131
+ @match_pos_label = FXLabel.new(text_view_header, "0/0", :opts => LAYOUT_FILL_Y)
132
+ @match_pos_label.textColor = 'grey'
133
+ pmatch_btn.connect(SEL_COMMAND) { gotoPrevMatch() }
134
+ nmatch_btn = FXButton.new(text_view_header, ">", nil, nil, 0, FRAME_RAISED|LAYOUT_FILL_Y)
135
+ nmatch_btn.connect(SEL_COMMAND) { gotoNextMatch() }
136
+
137
+ # @filter_text = FXTextField.new(text_view_header, 10,
138
+ # :target => @filter_dt, :selector => FXDataTarget::ID_VALUE,
139
+ # :opts => FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y)
140
+
141
+ @filter_text = FXComboBox.new(text_view_header, 20, nil, 0, FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
142
+ @filter_text.connect(SEL_COMMAND){
143
+ applyFilter()
144
+ addFilterHistory()
145
+ }
146
+
147
+ @filter_text.connect(SEL_CHANGED) {
148
+ applyFilter()
149
+ }
150
+
151
+ @auto_apply_cbtn = FXCheckButton.new(text_view_header, "auto-apply", nil, 0, ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP|LAYOUT_RIGHT|LAYOUT_FILL_Y)
152
+
153
+
154
+ text_box_frame = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
155
+
156
+ @html_viewer = HTMLViewer.new(text_box_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
157
+ #searchflags = FXScintilla::SCFIND_WHOLEWORD|FXScintilla::SCFIND_MATCHCASE|FXScintilla::SCFIND_REGEXP|FXScintilla::SCFIND_WORDSTART
158
+ @searchflags = FXScintilla::SCFIND_REGEXP
159
+ @html_viewer.setSearchFlags @searchflags
160
+
161
+ addHotkeyHandler(@html_viewer)
162
+ addHotkeyHandler(@filter_text)
163
+
164
+ # @filter_dt.connect(SEL_COMMAND) { applyFilter() }
165
+
166
+ end
167
+
168
+ def applyFilter
169
+ pattern = @filter_text.text
170
+ return if pattern.empty?
171
+
172
+ @match_pos_label.text = "0/0"
173
+ @match_pos_label.textColor = 'grey'
174
+
175
+ @text_matches = @html_viewer.search_text(pattern)
176
+
177
+
178
+ if @text_matches.length > 0
179
+ @match_pos_label.textColor = 'black'
180
+ @match_pos_label.text = "1/#{@text_matches.length}"
181
+
182
+ show_match_pos(0)
183
+ end
184
+
185
+ end
186
+
187
+ private
188
+
189
+ def show_match_pos(match_pos=nil)
190
+
191
+ pos = match_pos.nil? ? 0 : match_pos
192
+ return false if @text_matches.empty?
193
+ return false if pos > @text_matches.length-1
194
+ @match_pos = pos
195
+ pattern = @filter_text.text
196
+ text_pos = @text_matches[pos]
197
+ @html_viewer.gotoPos text_pos
198
+ @html_viewer.setSel text_pos, text_pos+pattern.length
199
+ end
200
+
201
+ def show_next
202
+ if @match_pos < @text_matches.length-1
203
+ @match_pos += 1
204
+ show_match_pos @match_pos
205
+ return true
206
+ end
207
+ return false
208
+ end
209
+
210
+ def show_prev
211
+ if @match_pos > 0
212
+ @match_pos -= 1
213
+ show_match_pos @match_pos
214
+ return true
215
+ end
216
+ return false
217
+ end
218
+
219
+
220
+ def addFilterHistory()
221
+ text = @filter_text.text
222
+ return true if text == ''
223
+ has_item = false
224
+ @filter_text.each do |item, data|
225
+ has_item = true if data == text
226
+ end
227
+ @filter_text.appendItem(text, text) unless has_item == true
228
+ @filter_text.numVisible = @filter_text.numItems
229
+ end
230
+
231
+ def resetFilter
232
+ @match_pos_label.text = "0/0"
233
+ @match_pos_label.textColor = 'grey'
234
+ @filter_text.text = ''
235
+ end
236
+
237
+ def addHotkeyHandler(widget)
238
+ @ctrl_pressed = false
239
+
240
+ widget.connect(SEL_KEYPRESS) { |sender, sel, event|
241
+ state = false
242
+ @ctrl_pressed = true if event.code == KEY_Control_L or event.code == KEY_Control_R
243
+ # @shift_pressed = true if @ctrl_pressed and ( event.code == KEY_Shift_L or event.code == KEY_Shift_R )
244
+ if event.code == KEY_Return
245
+ highlight(@filter_text.text)
246
+ state = true # special handling of KEY_Return, because we don't want a linebreak in textbox.
247
+ end
248
+
249
+ if event.code == KEY_F1
250
+
251
+ unless event.moved?
252
+ FXMenuPane.new(self) do |menu_pane|
253
+ FXMenuCaption.new(menu_pane, "Hotkeys:")
254
+ FXMenuSeparator.new(menu_pane)
255
+ [ "<ctrl-r> - Reset Filter",
256
+ "<ctrl-n> - Goto Next",
257
+ "<ctrl-shift-n> - Goto Prev"
258
+ ].each do |hk|
259
+ FXMenuCaption.new(menu_pane, hk).backColor = 'yellow'
260
+ end
261
+
262
+ menu_pane.create
263
+ menu_pane.popup(nil, event.root_x, event.root_y)
264
+ app.runModalWhileShown(menu_pane)
265
+ end
266
+
267
+ end
268
+ end
269
+
270
+ if @ctrl_pressed
271
+ case event.code
272
+ when KEY_n
273
+ if show_next
274
+ @match_pos_label.text = "#{@match_pos+1}/#{@text_matches.length}"
275
+ end
276
+ when KEY_N
277
+ if show_prev
278
+ @match_pos_label.text = "#{@match_pos+1}/#{@text_matches.length}"
279
+ end
280
+ when KEY_r
281
+ resetFilter()
282
+
283
+ end
284
+ end
285
+ state
286
+ }
287
+
288
+ widget.connect(SEL_KEYRELEASE) { |sender, sel, event|
289
+ @ctrl_pressed = false if event.code == KEY_Control_L or event.code == KEY_Control_R
290
+ false
291
+ }
292
+ end
293
+
294
+ end
295
+ end
296
+ end
297
+