metasm 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.hgtags +3 -0
  4. data/Gemfile +1 -0
  5. data/INSTALL +61 -0
  6. data/LICENCE +458 -0
  7. data/README +29 -21
  8. data/Rakefile +10 -0
  9. data/TODO +10 -12
  10. data/doc/code_organisation.txt +2 -0
  11. data/doc/core/DynLdr.txt +247 -0
  12. data/doc/core/ExeFormat.txt +43 -0
  13. data/doc/core/Expression.txt +220 -0
  14. data/doc/core/GNUExports.txt +27 -0
  15. data/doc/core/Ia32.txt +236 -0
  16. data/doc/core/SerialStruct.txt +108 -0
  17. data/doc/core/VirtualString.txt +145 -0
  18. data/doc/core/WindowsExports.txt +61 -0
  19. data/doc/core/index.txt +1 -0
  20. data/doc/style.css +6 -3
  21. data/doc/usage/debugger.txt +327 -0
  22. data/doc/usage/index.txt +1 -0
  23. data/doc/use_cases.txt +2 -2
  24. data/metasm.gemspec +22 -0
  25. data/{lib/metasm.rb → metasm.rb} +11 -3
  26. data/{lib/metasm → metasm}/compile_c.rb +13 -7
  27. data/metasm/cpu/arc.rb +8 -0
  28. data/metasm/cpu/arc/decode.rb +425 -0
  29. data/metasm/cpu/arc/main.rb +191 -0
  30. data/metasm/cpu/arc/opcodes.rb +588 -0
  31. data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
  32. data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
  33. data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
  34. data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
  35. data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
  36. data/metasm/cpu/arm/opcodes.rb +324 -0
  37. data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
  38. data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
  39. data/metasm/cpu/arm64.rb +15 -0
  40. data/metasm/cpu/arm64/debug.rb +38 -0
  41. data/metasm/cpu/arm64/decode.rb +289 -0
  42. data/metasm/cpu/arm64/encode.rb +41 -0
  43. data/metasm/cpu/arm64/main.rb +105 -0
  44. data/metasm/cpu/arm64/opcodes.rb +232 -0
  45. data/metasm/cpu/arm64/parse.rb +20 -0
  46. data/metasm/cpu/arm64/render.rb +95 -0
  47. data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
  48. data/metasm/cpu/bpf/decode.rb +142 -0
  49. data/metasm/cpu/bpf/main.rb +60 -0
  50. data/metasm/cpu/bpf/opcodes.rb +81 -0
  51. data/metasm/cpu/bpf/render.rb +41 -0
  52. data/metasm/cpu/cy16.rb +9 -0
  53. data/metasm/cpu/cy16/decode.rb +253 -0
  54. data/metasm/cpu/cy16/main.rb +63 -0
  55. data/metasm/cpu/cy16/opcodes.rb +78 -0
  56. data/metasm/cpu/cy16/render.rb +41 -0
  57. data/metasm/cpu/dalvik.rb +11 -0
  58. data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
  59. data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
  60. data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
  61. data/metasm/cpu/ia32.rb +17 -0
  62. data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
  63. data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
  64. data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
  65. data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
  66. data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
  67. data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
  68. data/metasm/cpu/ia32/opcodes.rb +1424 -0
  69. data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
  70. data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
  71. data/metasm/cpu/mips.rb +14 -0
  72. data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
  73. data/metasm/cpu/mips/debug.rb +42 -0
  74. data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
  75. data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
  76. data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
  77. data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
  78. data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
  79. data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
  80. data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
  81. data/metasm/cpu/msp430/decode.rb +247 -0
  82. data/metasm/cpu/msp430/main.rb +62 -0
  83. data/metasm/cpu/msp430/opcodes.rb +101 -0
  84. data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
  85. data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
  86. data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
  87. data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
  88. data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
  89. data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
  90. data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
  91. data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
  92. data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
  93. data/metasm/cpu/ppc/parse.rb +55 -0
  94. data/metasm/cpu/python.rb +8 -0
  95. data/metasm/cpu/python/decode.rb +136 -0
  96. data/metasm/cpu/python/main.rb +36 -0
  97. data/metasm/cpu/python/opcodes.rb +180 -0
  98. data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
  99. data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
  100. data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
  101. data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
  102. data/metasm/cpu/x86_64.rb +15 -0
  103. data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
  104. data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
  105. data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
  106. data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
  107. data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
  108. data/metasm/cpu/x86_64/opcodes.rb +136 -0
  109. data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
  110. data/metasm/cpu/x86_64/render.rb +35 -0
  111. data/metasm/cpu/z80.rb +9 -0
  112. data/metasm/cpu/z80/decode.rb +313 -0
  113. data/metasm/cpu/z80/main.rb +67 -0
  114. data/metasm/cpu/z80/opcodes.rb +224 -0
  115. data/metasm/cpu/z80/render.rb +59 -0
  116. data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
  117. data/{lib/metasm → metasm}/decode.rb +35 -4
  118. data/{lib/metasm → metasm}/decompile.rb +15 -16
  119. data/{lib/metasm → metasm}/disassemble.rb +201 -45
  120. data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
  121. data/{lib/metasm → metasm}/dynldr.rb +220 -133
  122. data/{lib/metasm → metasm}/encode.rb +10 -1
  123. data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
  124. data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
  125. data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
  126. data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
  127. data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
  128. data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
  129. data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
  130. data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
  131. data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
  132. data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
  133. data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
  134. data/metasm/exe_format/gb.rb +65 -0
  135. data/metasm/exe_format/javaclass.rb +424 -0
  136. data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
  137. data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
  138. data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
  139. data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
  140. data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
  141. data/metasm/exe_format/pyc.rb +167 -0
  142. data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
  143. data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
  144. data/metasm/exe_format/shellcode_rwx.rb +114 -0
  145. data/metasm/exe_format/swf.rb +205 -0
  146. data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
  147. data/metasm/exe_format/zip.rb +335 -0
  148. data/metasm/gui.rb +13 -0
  149. data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
  150. data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
  151. data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
  152. data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
  153. data/metasm/gui/dasm_graph.rb +1695 -0
  154. data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
  155. data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
  156. data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
  157. data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
  158. data/{lib/metasm → metasm}/gui/debug.rb +93 -27
  159. data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
  160. data/{lib/metasm → metasm}/gui/qt.rb +12 -2
  161. data/{lib/metasm → metasm}/gui/win32.rb +179 -42
  162. data/{lib/metasm → metasm}/gui/x11.rb +59 -59
  163. data/{lib/metasm → metasm}/main.rb +389 -264
  164. data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
  165. data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
  166. data/{lib/metasm → metasm}/os/linux.rb +628 -151
  167. data/metasm/os/main.rb +330 -0
  168. data/{lib/metasm → metasm}/os/windows.rb +132 -42
  169. data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
  170. data/{lib/metasm → metasm}/parse.rb +26 -24
  171. data/{lib/metasm → metasm}/parse_c.rb +221 -116
  172. data/{lib/metasm → metasm}/preprocessor.rb +55 -40
  173. data/{lib/metasm → metasm}/render.rb +14 -38
  174. data/misc/hexdump.rb +2 -1
  175. data/misc/lint.rb +58 -0
  176. data/misc/txt2html.rb +9 -7
  177. data/samples/bindiff.rb +3 -4
  178. data/samples/dasm-plugins/bindiff.rb +15 -0
  179. data/samples/dasm-plugins/bookmark.rb +133 -0
  180. data/samples/dasm-plugins/c_constants.rb +57 -0
  181. data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
  182. data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
  183. data/samples/dasm-plugins/dasm_all.rb +70 -0
  184. data/samples/dasm-plugins/demangle_cpp.rb +31 -0
  185. data/samples/dasm-plugins/deobfuscate.rb +251 -0
  186. data/samples/dasm-plugins/dump_text.rb +35 -0
  187. data/samples/dasm-plugins/export_graph_svg.rb +86 -0
  188. data/samples/dasm-plugins/findgadget.rb +75 -0
  189. data/samples/dasm-plugins/hl_opcode.rb +32 -0
  190. data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
  191. data/samples/dasm-plugins/imm2off.rb +34 -0
  192. data/samples/dasm-plugins/match_libsigs.rb +93 -0
  193. data/samples/dasm-plugins/patch_file.rb +95 -0
  194. data/samples/dasm-plugins/scanfuncstart.rb +36 -0
  195. data/samples/dasm-plugins/scanxrefs.rb +26 -0
  196. data/samples/dasm-plugins/selfmodify.rb +197 -0
  197. data/samples/dasm-plugins/stringsxrefs.rb +28 -0
  198. data/samples/dasmnavig.rb +1 -1
  199. data/samples/dbg-apihook.rb +24 -9
  200. data/samples/dbg-plugins/heapscan.rb +283 -0
  201. data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
  202. data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
  203. data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
  204. data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
  205. data/samples/dbg-plugins/heapscan/winheap.h +174 -0
  206. data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
  207. data/samples/dbg-plugins/trace_func.rb +214 -0
  208. data/samples/disassemble-gui.rb +35 -5
  209. data/samples/disassemble.rb +31 -6
  210. data/samples/dump_upx.rb +24 -12
  211. data/samples/dynamic_ruby.rb +12 -3
  212. data/samples/exeencode.rb +6 -5
  213. data/samples/factorize-headers-peimports.rb +1 -1
  214. data/samples/lindebug.rb +175 -381
  215. data/samples/metasm-shell.rb +1 -2
  216. data/samples/peldr.rb +2 -2
  217. data/tests/all.rb +1 -1
  218. data/tests/arc.rb +26 -0
  219. data/tests/dynldr.rb +22 -4
  220. data/tests/expression.rb +55 -0
  221. data/tests/graph_layout.rb +285 -0
  222. data/tests/ia32.rb +79 -26
  223. data/tests/mips.rb +9 -2
  224. data/tests/x86_64.rb +66 -18
  225. metadata +330 -218
  226. data/lib/metasm/arm/opcodes.rb +0 -177
  227. data/lib/metasm/gui.rb +0 -23
  228. data/lib/metasm/gui/dasm_graph.rb +0 -1354
  229. data/lib/metasm/ia32.rb +0 -14
  230. data/lib/metasm/ia32/opcodes.rb +0 -873
  231. data/lib/metasm/ppc/parse.rb +0 -52
  232. data/lib/metasm/x86_64.rb +0 -12
  233. data/lib/metasm/x86_64/opcodes.rb +0 -118
  234. data/samples/gdbclient.rb +0 -583
  235. data/samples/rubstop.rb +0 -399
@@ -323,11 +323,21 @@ Execute Printer Play Sleep Zoom Cancel
323
323
  end
324
324
 
325
325
  # update @hl_word from a line & offset, return nil if unchanged
326
- def update_hl_word(line, offset)
326
+ def update_hl_word(line, offset, mode=:asm)
327
327
  return if not line
328
328
  word = line[0...offset].to_s[/\w*$/] << line[offset..-1].to_s[/^\w*/]
329
329
  word = nil if word == ''
330
- @hl_word = word if @hl_word != word
330
+ if @hl_word != word
331
+ if word
332
+ if mode == :asm and defined?(@dasm) and @dasm
333
+ re = @dasm.gui_hilight_word_regexp(word)
334
+ else
335
+ re = Regexp.escape word
336
+ end
337
+ @hl_word_re = /^(.*?)(\b(?:#{re})\b)/
338
+ end
339
+ @hl_word = word
340
+ end
331
341
  end
332
342
 
333
343
  # invalidate the whole widget area
@@ -685,7 +685,7 @@ TrackMouseEvent(
685
685
  #define QS_ALLEVENTS (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY)
686
686
  #define QS_ALLINPUT (QS_ALLEVENTS | QS_SENDMESSAGE)
687
687
 
688
- #define WAIT_TIMEOUT 258L
688
+ #define WAIT_TIMEOUT 258L
689
689
 
690
690
  #define CF_TEXT 1
691
691
  #define CF_BITMAP 2
@@ -960,6 +960,33 @@ GetTextExtentPoint32A(
960
960
  __in_ecount(c) LPCSTR lpString,
961
961
  __in int c,
962
962
  __out LPPOINT lpsz);
963
+
964
+ typedef struct tagRECT {
965
+ LONG left;
966
+ LONG top;
967
+ LONG right;
968
+ LONG bottom;
969
+ } RECT, *LPRECT;
970
+
971
+ #define TPM_LEFTBUTTON 0x0000L
972
+ #define TPM_RIGHTBUTTON 0x0002L
973
+ #define TPM_LEFTALIGN 0x0000L
974
+ #define TPM_CENTERALIGN 0x0004L
975
+ #define TPM_RIGHTALIGN 0x0008L
976
+ #define TPM_TOPALIGN 0x0000L
977
+ #define TPM_VCENTERALIGN 0x0010L
978
+ #define TPM_BOTTOMALIGN 0x0020L
979
+ #define TPM_HORIZONTAL 0x0000L
980
+ #define TPM_VERTICAL 0x0040L
981
+ #define TPM_NONOTIFY 0x0080L
982
+ #define TPM_RETURNCMD 0x0100L
983
+ #define TPM_RECURSE 0x0001L
984
+ #define TPM_HORPOSANIMATION 0x0400L
985
+ #define TPM_HORNEGANIMATION 0x0800L
986
+ #define TPM_VERPOSANIMATION 0x1000L
987
+ #define TPM_VERNEGANIMATION 0x2000L
988
+ #define TPM_NOANIMATION 0x4000L
989
+ #define TPM_LAYOUTRTL 0x8000L
963
990
  WINUSERAPI
964
991
  BOOL
965
992
  WINAPI
@@ -980,6 +1007,17 @@ WINAPI
980
1007
  DestroyMenu(
981
1008
  __in HMENU hMenu);
982
1009
  WINUSERAPI
1010
+ BOOL
1011
+ WINAPI
1012
+ TrackPopupMenu(
1013
+ __in HMENU hMenu,
1014
+ __in UINT uFlags,
1015
+ __in int x,
1016
+ __in int y,
1017
+ __in int nReserved,
1018
+ __in HWND hWnd,
1019
+ __in_opt CONST RECT *prcRect);
1020
+ WINUSERAPI
983
1021
  DWORD
984
1022
  WINAPI
985
1023
  CheckMenuItem(
@@ -999,13 +1037,6 @@ AppendMenuA(
999
1037
  #define OPAQUE 2
1000
1038
  int WINAPI SetBkMode(__in HDC hdc, __in int mode);
1001
1039
 
1002
- typedef struct tagRECT {
1003
- LONG left;
1004
- LONG top;
1005
- LONG right;
1006
- LONG bottom;
1007
- } RECT, *LPRECT;
1008
-
1009
1040
  WINUSERAPI
1010
1041
  int
1011
1042
  WINAPI
@@ -1086,6 +1117,18 @@ UpdateWindow(
1086
1117
  WINUSERAPI
1087
1118
  BOOL
1088
1119
  WINAPI
1120
+ ClientToScreen(
1121
+ __in HWND hWnd,
1122
+ __inout LPPOINT pt);
1123
+ WINUSERAPI
1124
+ BOOL
1125
+ WINAPI
1126
+ ScreenToClient(
1127
+ __in HWND hWnd,
1128
+ __inout LPPOINT pt);
1129
+ WINUSERAPI
1130
+ BOOL
1131
+ WINAPI
1089
1132
  GetClientRect(
1090
1133
  __in HWND hWnd,
1091
1134
  __out LPRECT lpRect);
@@ -1390,11 +1433,11 @@ class WinWidget
1390
1433
  return if not @parent
1391
1434
  @parent.set_focus(self) if @parent.respond_to? :set_focus
1392
1435
  end
1393
-
1436
+
1394
1437
  def focus?
1395
1438
  return true if not @parent
1396
1439
  (@parent.respond_to?(:focus?) ? @parent.focus? : true) and
1397
- (@parent.respond_to?(:has_focus?) ? @parent.has_focus?(self) : true)
1440
+ (@parent.respond_to?(:has_focus?) ? @parent.has_focus?(self) : true)
1398
1441
  end
1399
1442
 
1400
1443
  def redraw
@@ -1484,6 +1527,7 @@ class ContainerChoiceWidget < WinWidget
1484
1527
 
1485
1528
  def set_focus(c)
1486
1529
  @curview = c
1530
+ grab_focus
1487
1531
  redraw
1488
1532
  end
1489
1533
  end
@@ -1519,7 +1563,7 @@ class ContainerVBoxWidget < WinWidget
1519
1563
  cy = 0
1520
1564
  pv = []
1521
1565
  @views.each_with_index { |v, i|
1522
- if y >= cy and y < cy + v.height
1566
+ if y >= cy+1 and y < cy + v.height - 1
1523
1567
  if @focus_idx != i
1524
1568
  @focus_idx = i
1525
1569
  redraw
@@ -1528,8 +1572,7 @@ class ContainerVBoxWidget < WinWidget
1528
1572
  return
1529
1573
  end
1530
1574
  cy += v.height
1531
- if y >= cy and y < cy+@spacing
1532
- vsz = v
1575
+ if y >= cy-1 and y < cy+@spacing+1
1533
1576
  @resizing = v
1534
1577
  @wantheight[@resizing] ||= v.height
1535
1578
  @tmpwantheight = []
@@ -1665,12 +1708,13 @@ class ContainerVBoxWidget < WinWidget
1665
1708
 
1666
1709
  def set_focus(c)
1667
1710
  @focus_idx = @views.index(c)
1711
+ grab_focus
1668
1712
  redraw
1669
1713
  end
1670
1714
  end
1671
1715
 
1672
1716
  module TextWidget
1673
- attr_accessor :caret_x, :caret_y, :hl_word, :font_width, :font_height
1717
+ attr_accessor :caret_x, :caret_y, :hl_word, :hl_word_re, :font_width, :font_height
1674
1718
 
1675
1719
  def initialize_text
1676
1720
  @caret_x = @caret_y = 0 # text cursor position
@@ -1679,11 +1723,21 @@ module TextWidget
1679
1723
  @hl_word = nil
1680
1724
  end
1681
1725
 
1682
- def update_hl_word(line, offset)
1726
+ def update_hl_word(line, offset, mode=:asm)
1683
1727
  return if not line
1684
1728
  word = line[0...offset].to_s[/\w*$/] << line[offset..-1].to_s[/^\w*/]
1685
1729
  word = nil if word == ''
1686
- @hl_word = word if @hl_word != word
1730
+ if @hl_word != word
1731
+ if word
1732
+ if mode == :asm and defined?(@dasm) and @dasm
1733
+ re = @dasm.gui_hilight_word_regexp(word)
1734
+ else
1735
+ re = Regexp.escape(word)
1736
+ end
1737
+ @hl_word_re = /^(.*?)(\b(?:#{re})\b)/
1738
+ end
1739
+ @hl_word = word
1740
+ end
1687
1741
  end
1688
1742
 
1689
1743
  def set_caret_from_click(x, y)
@@ -1737,7 +1791,15 @@ end
1737
1791
  class DrawableWidget < WinWidget
1738
1792
  include TextWidget
1739
1793
 
1740
- attr_accessor :buttons
1794
+ BasicColor = { :white => 'fff', :palegrey => 'ddd', :black => '000', :grey => '444',
1795
+ :red => 'f44', :darkred => '800', :palered => 'faa',
1796
+ :green => '4f4', :darkgreen => '080', :palegreen => 'afa',
1797
+ :blue => '44f', :darkblue => '008', :paleblue => 'aaf',
1798
+ :yellow => 'ff4', :darkyellow => '440', :paleyellow => 'ffa',
1799
+ :orange => 'fc8',
1800
+ }
1801
+ attr_accessor :buttons, :parent_widget
1802
+ attr_accessor :default_color_association
1741
1803
 
1742
1804
  def initialize(*a, &b)
1743
1805
  @color = {}
@@ -1754,12 +1816,7 @@ class DrawableWidget < WinWidget
1754
1816
  end
1755
1817
 
1756
1818
  def initialize_visible_
1757
- { :white => 'fff', :palegrey => 'ddd', :black => '000', :grey => '444',
1758
- :red => 'f00', :darkred => '800', :palered => 'fcc',
1759
- :green => '0f0', :darkgreen => '080', :palegreen => 'cfc',
1760
- :blue => '00f', :darkblue => '008', :paleblue => 'ccf',
1761
- :yellow => 'ff0', :darkyellow => '440', :paleyellow => 'ffc',
1762
- }.each { |tag, val|
1819
+ BasicColor.each { |tag, val|
1763
1820
  @color[tag] = color(val)
1764
1821
  }
1765
1822
  @color[:winbg] = Win32Gui.getsyscolor(Win32Gui::COLOR_BTNFACE)
@@ -1768,11 +1825,24 @@ class DrawableWidget < WinWidget
1768
1825
  initialize_visible if respond_to? :initialize_visible
1769
1826
  end
1770
1827
 
1771
- def set_color_association(h)
1772
- h.each { |k, v| @color[k] = color(v) }
1828
+ def set_color_association(hash)
1829
+ hord = Hash.new { |h, k| h[k] = (hash[k] ? h[hash[k]] + 1 : 0) }
1830
+ hash.sort_by { |k, v| hord[k] }.each { |k, v| @color[k] = color(v) }
1773
1831
  gui_update
1774
1832
  end
1775
1833
 
1834
+ def new_menu
1835
+ toplevel.new_menu
1836
+ end
1837
+
1838
+ def addsubmenu(*a, &b)
1839
+ toplevel.addsubmenu(*a, &b)
1840
+ end
1841
+
1842
+ def popupmenu(m, x, y)
1843
+ toplevel.popupmenu(m, (x+@x).to_i, (y+@y).to_i)
1844
+ end
1845
+
1776
1846
  def paint_(realhdc)
1777
1847
  @hdc = Win32Gui.createcompatibledc(realhdc)
1778
1848
  bmp = Win32Gui.createcompatiblebitmap(realhdc, @width, @height)
@@ -1813,7 +1883,7 @@ class DrawableWidget < WinWidget
1813
1883
  end
1814
1884
 
1815
1885
  def color(col)
1816
- @color[col] ||= col.sub(/^(\w)(\w)(\w)$/, '\\3\\3\\2\\2\\1\\1').to_i(16)
1886
+ @color[col] ||= col.sub(/^(\w\w)(\w\w)(\w\w)$/, '\\3\\2\\1').sub(/^(\w)(\w)(\w)$/, '\\3\\3\\2\\2\\1\\1').to_i(16)
1817
1887
  end
1818
1888
 
1819
1889
  def draw_color(col)
@@ -1853,6 +1923,23 @@ class DrawableWidget < WinWidget
1853
1923
  draw_string(x, y, text)
1854
1924
  end
1855
1925
 
1926
+ # same as draw_string_color + hilight @hl_word_re
1927
+ def draw_string_hl(col, x, y, str)
1928
+ if @hl_word
1929
+ while str =~ @hl_word_re
1930
+ s1, s2 = $1, $2
1931
+ draw_string_color(col, x, y, s1)
1932
+ x += s1.length*@font_width
1933
+ hl_w = s2.length*@font_width
1934
+ draw_rectangle_color(:hl_word_bg, x, y, hl_w, @font_height)
1935
+ draw_string_color(:hl_word, x, y, s2)
1936
+ x += hl_w
1937
+ str = str[s1.length+s2.length..-1]
1938
+ end
1939
+ end
1940
+ draw_string_color(col, x, y, str)
1941
+ end
1942
+
1856
1943
  def keyboard_state(query=nil)
1857
1944
  case query
1858
1945
  when :control, :ctrl
@@ -1952,10 +2039,10 @@ class Window
1952
2039
  :style => Win32Gui::CS_DBLCLKS,
1953
2040
  :hcursor => Win32Gui.loadcursora(0, Win32Gui::IDC_ARROW),
1954
2041
  :lpszclassname => cname,
1955
- :lpfnwndproc => Win32Gui.callback_alloc_c('__stdcall int wndproc(int, int, int, int)') { |hwnd, msg, wp, lp| windowproc(hwnd, msg, wp, lp) }
2042
+ :lpfnwndproc => Win32Gui.callback_alloc_c('__stdcall int wndproc(int, int, int, int)') { |hwnd, msg, wp, lp| windowproc(hwnd, msg, wp, lp) }
1956
2043
 
1957
2044
  Win32Gui.registerclassexa(cls)
1958
-
2045
+
1959
2046
  @hwnd = Win32Gui.createwindowexa(win32styleex, cname, 'win32gui window', win32style, Win32Gui::CW_USEDEFAULT, Win32Gui::SW_HIDE, Win32Gui::CW_USEDEFAULT, 0, 0, 0, 0, 0)
1960
2047
 
1961
2048
  initialize_window(*a, &b)
@@ -1997,7 +2084,8 @@ class Window
1997
2084
  h.update v => {
1998
2085
  :prior => :pgup, :next => :pgdown,
1999
2086
  :escape => :esc, :return => :enter,
2000
- :back => :backspace,
2087
+ :back => :backspace, :apps => :popupmenu,
2088
+ :add => ?+, :subtract => ?-, :multiply => ?*, :divide => ?/,
2001
2089
  }.fetch(key, key)
2002
2090
  }
2003
2091
 
@@ -2053,7 +2141,9 @@ class Window
2053
2141
  when Win32Gui::WM_KEYDOWN, Win32Gui::WM_SYSKEYDOWN
2054
2142
  # SYSKEYDOWN for f10 (default = activate the menu bar)
2055
2143
  if key = Keyboard_trad[wparam]
2056
- if keyboard_state(:control)
2144
+ if [?+, ?-, ?/, ?*].include?(key)
2145
+ # keypad keys generate wm_keydown + wm_char, ignore this one
2146
+ elsif keyboard_state(:control)
2057
2147
  @widget.keypress_ctrl_(key) if @widget
2058
2148
  else
2059
2149
  @widget.keypress_(key) if @widget
@@ -2064,15 +2154,15 @@ class Window
2064
2154
  if keyboard_state(:control) and not keyboard_state(:alt) # altgr+[ returns CTRL on..
2065
2155
  if ?a.kind_of?(String)
2066
2156
  wparam += (keyboard_state(:shift) ? ?A.ord : ?a.ord) - 1 if wparam < 0x1a
2067
- k = wparam.chr
2157
+ key = wparam.chr
2068
2158
  else
2069
2159
  wparam += (keyboard_state(:shift) ? ?A : ?a) - 1 if wparam < 0x1a
2070
- k = wparam
2160
+ key = wparam
2071
2161
  end
2072
- @widget.keypress_ctrl_(k) if @widget
2162
+ @widget.keypress_ctrl_(key) if @widget
2073
2163
  else
2074
- k = (?a.kind_of?(String) ? wparam.chr : wparam)
2075
- @widget.keypress_(k) if @widget
2164
+ key = (?a.kind_of?(String) ? wparam.chr : wparam)
2165
+ @widget.keypress_(key) if @widget
2076
2166
  end
2077
2167
  when Win32Gui::WM_DESTROY
2078
2168
  destroy_window
@@ -2214,12 +2304,39 @@ class Window
2214
2304
 
2215
2305
  # make the window's MenuBar reflect the content of @menu
2216
2306
  def update_menu
2307
+ unuse_menu(@menu)
2217
2308
  Win32Gui.destroymenu(@menuhwnd) if @menuhwnd != 0
2218
2309
  @menuhwnd = Win32Gui.createmenu()
2219
2310
  @menu.each { |e| create_menu_item(@menuhwnd, e) }
2220
2311
  Win32Gui.setmenu(@hwnd, @menuhwnd)
2221
2312
  end
2222
2313
 
2314
+ def popupmenu(m, x, y)
2315
+ hm = Win32Gui.createpopupmenu()
2316
+ m.each { |e| create_menu_item(hm, e) }
2317
+ pt = Win32Gui.alloc_c_struct('POINT', :x => x, :y => y)
2318
+ Win32Gui.clienttoscreen(@hwnd, pt)
2319
+ id = Win32Gui.trackpopupmenu(hm, Win32Gui::TPM_NONOTIFY | Win32Gui::TPM_RETURNCMD, pt.x, pt.y, 0, @hwnd, 0)
2320
+ if p = @control_action[id]
2321
+ # TrackPopup returns before WM_COMMAND is delivered, so if we
2322
+ # want to cleanup @control_action we must call it now & clenup
2323
+ p.call
2324
+ end
2325
+ unuse_menu(m)
2326
+ Win32Gui.destroymenu(hm)
2327
+ end
2328
+
2329
+ def unuse_menu(m)
2330
+ m.flatten.grep(Proc).reverse_each { |c|
2331
+ if @control_action[@controlid-1] == c
2332
+ @controlid -= 1 # recycle IDs
2333
+ @control_action.delete @controlid
2334
+ elsif i = @control_action.index(c)
2335
+ @control_action.delete i
2336
+ end
2337
+ }
2338
+ end
2339
+
2223
2340
  def create_menu_item(menu, entry)
2224
2341
  args = entry.dup
2225
2342
 
@@ -2270,6 +2387,7 @@ class Window
2270
2387
  checked = action.call(!checked)
2271
2388
  Win32Gui.checkmenuitem(menu, id, (checked ? Win32Gui::MF_CHECKED : Win32Gui::MF_UNCHECKED))
2272
2389
  }
2390
+ entry << @control_action[id] # allow deletion in unuse_menu
2273
2391
  end
2274
2392
  @controlid += 1
2275
2393
  end
@@ -2329,7 +2447,7 @@ class OpenFile
2329
2447
  buf = [0].pack('C')*512
2330
2448
  ofn = Win32Gui.alloc_c_struct 'OPENFILENAMEA',
2331
2449
  :lstructsize => :size,
2332
- #:hwndowner => win.hwnd, # 0 for nonmodal
2450
+ #:hwndowner => win.hwnd, # 0 for nonmodal
2333
2451
  :lpstrfilter => "All Files\0*.*\0\0",
2334
2452
  :lpstrfile => buf,
2335
2453
  :lpstrtitle => title,
@@ -2369,6 +2487,10 @@ class IBoxWidget < DrawableWidget
2369
2487
  @oldsel_x = @caret_x_select = 0
2370
2488
  @caret_x = @curline.length
2371
2489
  @caret_x_start = 0
2490
+ @@history ||= {}
2491
+ histkey = opts[:history] || label[0, 10]
2492
+ @history = (@@history[histkey] ||= [])
2493
+ @history_off = @history.length
2372
2494
 
2373
2495
  add_button('Ok', :btnc1, :btnc2) { keypress(:enter) }
2374
2496
  add_button('Cancel', :btnc1, :btnc2) { keypress(:esc) }
@@ -2505,7 +2627,19 @@ class IBoxWidget < DrawableWidget
2505
2627
  end
2506
2628
  @caret_x = @curline.length
2507
2629
  update_caret
2630
+ when :up, :down
2631
+ if @history_off < @history.length or @curline.strip != @history.last
2632
+ @history[@history_off] = @curline.strip
2633
+ end
2634
+ @history_off += (key == :up ? -1 : 1)
2635
+ @history_off %= @history.length
2636
+ @curline = @history[@history_off].to_s
2637
+ @caret_x = @curline.length if @caret_x > @curline.length
2638
+ redraw
2508
2639
  when :enter
2640
+ @history << @curline.strip
2641
+ @history.pop if @history.last == ''
2642
+ @history.pop if @history.last == @history[-2]
2509
2643
  destroy
2510
2644
  Gui.main_iter
2511
2645
  protect { @action.call(@curline.strip) }
@@ -2588,7 +2722,7 @@ class IBoxWidget < DrawableWidget
2588
2722
  elsif mouserelease_buttons(x, y)
2589
2723
  end
2590
2724
  end
2591
-
2725
+
2592
2726
  def update_caret
2593
2727
  return if @oldcaret_x == @caret_x and @oldsel_x == @caret_x_select
2594
2728
  redraw
@@ -2664,7 +2798,7 @@ class LBoxWidget < DrawableWidget
2664
2798
  def initial_size
2665
2799
  @colw = @colwmax.map { |w| (w+1) * @font_width }
2666
2800
  allw = @colw.inject(0) { |a, i| a+i }
2667
- [[allw, 80*@font_width].min, [@list.length+1, 30].min * @font_height+2]
2801
+ [[allw+@font_width, 80*@font_width].min, [@list.length+2, 30].min * @font_height+2]
2668
2802
  end
2669
2803
 
2670
2804
  def resized(w, h)
@@ -2699,7 +2833,11 @@ class LBoxWidget < DrawableWidget
2699
2833
  def paint
2700
2834
  @btnx = []
2701
2835
  @btny = 0
2702
- @btnheight = @font_height * 4/3
2836
+ if @btnheight != @font_height * 4/3
2837
+ # fix vscrollbar height on w7
2838
+ @btnheight = @font_height * 4/3
2839
+ resized(width, height)
2840
+ end
2703
2841
  x = 0
2704
2842
  @colw.each { |w|
2705
2843
  @btnx << x
@@ -2817,7 +2955,6 @@ class LBoxWidget < DrawableWidget
2817
2955
  vscroll((@linehead-off)*@font_height)
2818
2956
  redraw
2819
2957
  when :down
2820
- n = @lineshown-1
2821
2958
  off = [@lineshown, [@lineshown/2, 5].max].min
2822
2959
  vscroll((@linehead+off)*@font_height)
2823
2960
  redraw
@@ -2907,7 +3044,7 @@ class LBoxWidget < DrawableWidget
2907
3044
  redraw
2908
3045
  end
2909
3046
  end
2910
-
3047
+
2911
3048
  def destroy
2912
3049
  @parent.destroy
2913
3050
  end
@@ -2943,7 +3080,7 @@ end
2943
3080
  Win32Gui.getscrollinfo(@hwnd, Win32Gui::SB_VERT, sif)
2944
3081
  case wparam & 0xffff
2945
3082
  when Win32Gui::SB_THUMBPOSITION; val = sif.ntrackpos
2946
- when Win32Gui::SB_THUMBTRACK; val = sif.ntrackpos; nopos = true
3083
+ when Win32Gui::SB_THUMBTRACK; val = sif.ntrackpos #; nopos = true
2947
3084
  when Win32Gui::SB_LINEDOWN; val = sif.npos + 1
2948
3085
  when Win32Gui::SB_LINEUP; val = sif.npos - 1
2949
3086
  when Win32Gui::SB_PAGEDOWN; val = sif.npos + sif.npage