99from typing import Optional , Callable , List
1010import math
1111import typing as t
12+ import re
1213
1314from construct_editor .helper import CallbackList
1415
@@ -918,17 +919,8 @@ def _paste(self, overwrite: bool = False, insert: bool = False) -> bool:
918919 clipboard = wx .TextDataObject ()
919920 wx .TheClipboard .GetData (clipboard )
920921 wx .TheClipboard .Close ()
921- byts_str : str = clipboard .GetText ()
922-
923- # convert string to bytes
924- try :
925- byts_str = byts_str .replace (" " , "" )
926- byts = bytes .fromhex (byts_str )
927- except Exception as e :
928- wx .MessageBox (
929- f"Can't convert data from clipboard to bytes.\n \n { str (e )} \n \n Clipboard Data:\n { byts_str } " ,
930- "Warning" ,
931- )
922+ byts = self .string_to_byts (clipboard .GetText ())
923+ if not byts :
932924 return False
933925
934926 # copy new data to the binary data
@@ -940,6 +932,35 @@ def _paste(self, overwrite: bool = False, insert: bool = False) -> bool:
940932 self .select_range (sel [0 ], sel [0 ] + len (byts ) - 1 )
941933 return True
942934
935+ def string_to_byts (self , byts_str : str ):
936+ """
937+ Normalize pasted string converting it to bytes (can be overridden).
938+ Return a "bytes" variable, or None in case or error.
939+ """
940+ byts_str = (re .sub (r".*[\"'](.*)[\"'].*" , r"\1" , byts_str ))
941+ try :
942+ byts = bytes .fromhex (byts_str )
943+ return byts
944+ except Exception :
945+ pass
946+ try :
947+ byts_str_conv = re .findall (r'[0-9A-Fa-fXx]+' , byts_str )
948+ byts = bytes (map (lambda x : int (x , 16 ), byts_str_conv ))
949+ return byts
950+ except Exception :
951+ pass
952+ try :
953+ byts = bytes (byts_str .encode ('utf8' , 'backslashreplace' )
954+ .decode ('unicode_escape' ), encoding = "raw_unicode_escape" )
955+ return byts
956+ except Exception as e :
957+ wx .MessageBox (
958+ f"Can't convert data from clipboard to bytes.\n \n { str (e )} "
959+ f"\n \n Processed clipboard data:\n { byts_str } " ,
960+ "Warning" ,
961+ )
962+ return None
963+
943964 def _undo (self ):
944965 self ._binary_data .command_processor .Undo ()
945966
@@ -1025,53 +1046,70 @@ def _on_cell_right_click(self, event: Grid.GridEvent):
10251046 if select_cell :
10261047 self .SetGridCursor (event .GetRow (), event .GetCol ())
10271048
1028- menus = [
1049+ popup_menu = wx .Menu ()
1050+ for menu in self .build_context_menu ():
1051+ if menu is None :
1052+ popup_menu .AppendSeparator ()
1053+ continue
1054+ if menu [3 ] != None : # checkbox boolean state
1055+ item : wx .MenuItem = popup_menu .AppendCheckItem (menu [0 ], menu [1 ])
1056+ item .Check (menu [3 ])
1057+ else :
1058+ item : wx .MenuItem = popup_menu .Append (menu [0 ], menu [1 ])
1059+ self .Bind (wx .EVT_MENU , menu [2 ], id = item .Id )
1060+ item .Enable (menu [4 ])
1061+
1062+ self .PopupMenu (popup_menu , event .GetPosition ())
1063+ popup_menu .Destroy ()
1064+
1065+ def build_context_menu (self ):
1066+ """Build the context menu. Can be overridden."""
1067+ return [
10291068 (
10301069 wx .ID_CUT ,
10311070 "Cut\t Ctrl+X" ,
10321071 lambda event : self ._cut_selection (),
1072+ None ,
10331073 not self .read_only ,
10341074 ),
1035- (wx .ID_COPY , "Copy\t Ctrl+C" , lambda event : self ._copy_selection (), True ),
1075+ (
1076+ wx .ID_COPY ,
1077+ "Copy\t Ctrl+C" ,
1078+ lambda event : self ._copy_selection (),
1079+ None ,
1080+ True
1081+ ),
10361082 (
10371083 wx .ID_PASTE ,
10381084 "Paste (overwrite)\t Ctrl+V" ,
10391085 lambda event : self ._paste (overwrite = True ),
1086+ None ,
10401087 not self .read_only ,
10411088 ),
10421089 (
10431090 wx .ID_PASTE ,
10441091 "Paste (insert)\t Ctrl+Shift+V" ,
10451092 lambda event : self ._paste (insert = True ),
1093+ None ,
10461094 not self .read_only ,
10471095 ),
10481096 None ,
10491097 (
10501098 wx .ID_UNDO ,
10511099 "Undo\t Ctrl+Z" ,
10521100 lambda event : self ._undo (),
1101+ None ,
10531102 self ._binary_data .command_processor .CanUndo (),
10541103 ),
10551104 (
10561105 wx .ID_REDO ,
10571106 "Redo\t Ctrl+Y" ,
10581107 lambda event : self ._redo (),
1108+ None ,
10591109 self ._binary_data .command_processor .CanRedo (),
10601110 ),
10611111 ]
10621112
1063- popup_menu = wx .Menu ()
1064- for menu in menus :
1065- if menu is None :
1066- popup_menu .AppendSeparator ()
1067- continue
1068- item : wx .MenuItem = popup_menu .Append (menu [0 ], menu [1 ])
1069- self .Bind (wx .EVT_MENU , menu [2 ], id = item .Id )
1070- item .Enable (menu [3 ])
1071-
1072- self .PopupMenu (popup_menu , event .GetPosition ())
1073- popup_menu .Destroy ()
1074-
10751113
10761114# #####################################################################################################################
10771115# ############################################## HexEditor ############################################################
0 commit comments