├── .gitignore ├── App.py ├── AutoComplete.py ├── Configure.py ├── GeeKey.py ├── GlobalVim.dmg ├── README.md ├── Tutorial.py ├── Vim.py ├── dat ├── dat_0.dat ├── dat_1.dat ├── dat_10.dat ├── dat_2.dat ├── dat_3.dat ├── dat_4.dat ├── dat_5.dat ├── dat_6.dat ├── dat_7.dat ├── dat_8.dat └── dat_9.dat ├── image_bridge.py ├── image_logo.py ├── image_mountain.py ├── licence.txt ├── localization.py ├── logo.icns ├── requirements.txt ├── res.py └── vim_oper.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.nsi 2 | *.zip 3 | *.exe 4 | *.bat 5 | sign/ 6 | images/ 7 | image2* 8 | config/ 9 | doc/ 10 | dist/ 11 | __pycache__/ 12 | build 13 | *.spec 14 | tmp 15 | *.pyc 16 | sh 17 | setup.py 18 | .DS_Store 19 | Cert* 20 | image_wechat* 21 | -------------------------------------------------------------------------------- /App.py: -------------------------------------------------------------------------------- 1 | 2 | from GeeKey import * 3 | from res import runAsAdmin 4 | import wx 5 | 6 | class LocalApp(wx.App): 7 | def OnInit(self): 8 | #mySplash = LocalSplashScreen() 9 | #mySplash.Show() 10 | ###################### other way without splash 11 | self.name = "SingleApp-%s"% wx.GetUserId() 12 | 13 | self.instance = wx.SingleInstanceChecker(self.name) 14 | 15 | if self.instance.IsAnotherRunning(): 16 | wx.MessageBox(lt("Another GlobalVim instance is running"),lt('Error')) 17 | return False 18 | 19 | INFO['GEEKEY'] = GeeKeyFrame(None,-1) 20 | 21 | self.SetTopWindow(INFO['GEEKEY']) 22 | INFO['GEEKEY'].Show(True) 23 | INFO['GEEKEY'].RaiseShow() 24 | return True 25 | pass 26 | 27 | if __name__ == '__main__': 28 | INFO['PID'] = os.getpid() 29 | INFO['APP'] = LocalApp() 30 | INFO['NSAPP'] = NSApplication.sharedApplication() 31 | INFO['LISTENER'] = Listener() 32 | 33 | # bundle = NSBundle.mainBundle() 34 | # info = bundle.localizedInfoDictionary() or bundle.infoDictionary() 35 | # print(info) 36 | # info['LSUIElement'] = '0' 37 | # print(info) 38 | 39 | #INFO['LOOP'] = CFRunLoopRun() # quit loop triggered by app 40 | INFO['APP'].MainLoop() 41 | 42 | wx.Exit() 43 | -------------------------------------------------------------------------------- /AutoComplete.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from res import * 5 | from sortedcontainers import SortedList 6 | 7 | class AutoComplete(wx.Frame): 8 | def __init__(self,parent, mainFrame, dictfile=None): 9 | self.geekey = mainFrame 10 | wx.Frame.__init__(self,parent,wx.NewId(),"Popup", 11 | style=wx.STAY_ON_TOP| wx.FRAME_NO_TASKBAR|wx.NO_BORDER| 12 | wx.FRAME_TOOL_WINDOW 13 | ) 14 | self.MaxNum = 9 15 | self.ShowBitNum = 3 16 | self.fontsize = 12 17 | ################### 18 | font = wx.Font(self.fontsize, wx.DEFAULT, wx.NORMAL, wx.NORMAL) 19 | self.lists = wx.ListBox(self,) 20 | self.lists.SetFont( font ) 21 | self.lists.Bind( wx.EVT_LISTBOX, self.OnLists ) 22 | ################### 23 | self.min_width = 100 24 | self.max_width = 1666# change to the longest candidates length 25 | self.item_num = self.MaxNum 26 | #self.char_width,self.char_height = (8,16) 27 | self.char_width,self.char_height = self.lists.GetTextExtent('O') 28 | self.switch_force_on = False 29 | self.auto_complete_on = False 30 | #log.log 'char width,height =',self.char_width,self.char_height 31 | ################### read word list in from file 32 | self.word_list = SortedList() 33 | 34 | self.StateReset() 35 | 36 | ################### 37 | #get self hw 38 | #self.ui = GUITHREADINFO(cbSize=sizeof(GUITHREADINFO)) 39 | self.ui = None 40 | self.hw = self.GetTopWindow() 41 | #log.log("current hw is %s"%self.hw) 42 | self.Show(False); 43 | self.Raise() 44 | self.Move((-200,-200) ) 45 | self.popup_hw = self.GetTopWindow() 46 | #win32gui.SetForegroundWindow(self.hw) 47 | #self.ui = None 48 | 49 | #################### 50 | #load dict 51 | self.dictfile = dictfile 52 | if os.path.exists( dictfile ): 53 | f = open( dictfile, 'r' ) 54 | cont = f.read() 55 | f.close() 56 | for row in cont.split('\n'): 57 | items = row.split() 58 | if len(items) == 0: continue 59 | word = items[0] 60 | freq = 1 61 | if len(items) > 1: freq = toFloat( items[1], freq) 62 | self.UpdateWord( word, freq * 0.9 ) 63 | pass 64 | pass 65 | #### 66 | self.height = 0 67 | self.width = 0 68 | self.start_pos = (0,0) 69 | pass 70 | 71 | def FindWord(self,word): 72 | ind = self.word_list.bisect_left( [word.lower(),word,-1] ) 73 | if ind >= len( self.word_list ): return False,ind 74 | if self.word_list[ ind ][1] != word: return False,ind 75 | return True,ind 76 | 77 | def FindSection(self,prefix): 78 | left_ind = self.word_list.bisect_left( [prefix.lower(),prefix.upper(),-1] ) 79 | right_ind = self.word_list.bisect_right( [prefix.lower()+"~",prefix.lower()+"~",-1] ) 80 | return (left_ind,right_ind) 81 | 82 | def UpdateWord(self,word,freq = 1): 83 | if freq <= 0: return 84 | res,ind = self.FindWord(word) 85 | #log.log("update list of len %s with word %s"%(len(self.word_list),self.word) ) 86 | if res: 87 | self.word_list[ind][2]+=freq 88 | else: 89 | #self.word_list.insert([word.lower(),word,freq] ) #sortedcontainers updated 90 | self.word_list.add([word.lower(),word,freq] ) 91 | pass 92 | pass 93 | 94 | def DeleteWord(self,word): 95 | res,ind = self.FindWord(word) 96 | if res: 97 | del self.word_list[ind] 98 | pass 99 | pass 100 | 101 | def PopupActive(self): 102 | return ( self.GetTopWindow() == self.popup_hw ) 103 | 104 | def GetInput(self,evtType,key,geekey,shift,ctrl,alt): 105 | ### 106 | if self.geekey.getConfig('geekeyenabled') == 'False': return True 107 | if not self.auto_complete_on: return True 108 | 109 | #log.log("get into get input") 110 | self.state_on_geekey = geekey 111 | self.state_on_shift = shift 112 | self.state_on_ctrl = ctrl 113 | self.state_on_alt = alt 114 | is_active = ( self.GetTopWindow() == self.popup_hw ) 115 | 116 | # # esc to cancel candinate selection 117 | # if is_active and key == 'esc': 118 | # if is_active: 119 | # log.log('cancel auto complete by esc') 120 | # self.StateReset() 121 | # return False 122 | 123 | if key == 'tab': 124 | #log.log("tab here in tab dealing") 125 | #log.log("prepare to deal with tab without geekey state_is_on = %s"%self.state_is_on) 126 | if self.state_is_on: #candidate is shown on the screen 127 | if evtType == 'key up': return False 128 | #log.log("is active = %s wtop = %s wpop = %s"%(is_active,self.GetTopWindow(),self.popup_hw ) ) 129 | if is_active: #the same as self.state_is_selection 130 | #pop up current selection 131 | #log.log("the popup window is focused.") 132 | select = self.lists.GetSelection() 133 | select_word = self.lists.GetString( select ) 134 | #win32gui.SetForegroundWindow(self.hw) 135 | log.log("update candidate %s with %s"%(select_word,self.word) ) 136 | self.UpdateTabCandidate( select_word, self.word ) 137 | self.StateReset() 138 | elif self.state_is_selection: #on screen current selection 139 | pass 140 | elif self.state_is_tab_selection: #move to next candidate in tab selection mode 141 | #log.log("already in tab selection mode, move to the the next one candidate") 142 | direction = 'down' if not shift else 'up' 143 | word = self.MoveCandidateSelection( direction ) 144 | #log.log("update candidate %s with %s"%(self.word,word ) ) 145 | self.UpdateTabCandidate(word,self.word) 146 | self.word = word 147 | pass 148 | else: #still in input mode, enter the tab selection mode 149 | #log.log("start the tab selection mode") 150 | #choose the first one to be on screen 151 | self.state_is_tab_selection = True 152 | select = self.lists.GetSelection() 153 | reset = True 154 | if select == wx.NOT_FOUND: 155 | self.lists.SetSelection( 0 ) 156 | select = 0 157 | reset = False 158 | pass 159 | new_word = self.lists.GetString(select) 160 | #log.log("update candidate %s on %s"%(new_word,self.word) ) 161 | self.UpdateTabCandidate( new_word, self.word ) 162 | self.word = new_word 163 | if reset or self.item_num == 1: self.StateReset() 164 | pass 165 | #log.log("get out tab when is selection") 166 | return False 167 | else: pass # normal tab, do nothing, and return True to pass the tab by 168 | #log.log("get out normal tab") 169 | return True 170 | 171 | if key == 'Packet': return True 172 | if key == '': return True 173 | 174 | if self.state_is_on and key == 'return': 175 | if evtType == 'key up': return False 176 | select = self.lists.GetSelection() 177 | if select < 0: 178 | self.StateReset() 179 | return True 180 | select_word = self.lists.GetString( select ) 181 | self.UpdateTabCandidate( select_word, self.word ) 182 | self.StateReset() 183 | return False 184 | 185 | if self.state_is_on and key == 'delete': 186 | if evtType == 'key up': return False 187 | select = self.lists.GetSelection() 188 | select_word = self.lists.GetString( select ) 189 | if select_word != '': self.DeleteWord( select_word ) 190 | self.StateReset(); 191 | return False 192 | 193 | if key in ('up','down'): 194 | if self.state_is_on: ##get into selection mode 195 | if evtType == 'key up': return False 196 | #log.log("get in up down") 197 | self.MoveCandidateSelection( key ) 198 | self.state_is_tab_selection = False 199 | #self.StateReset() 200 | #log.log("get out up down") 201 | return False 202 | #else 203 | return True 204 | 205 | if key in ('page up','page down'): 206 | if self.state_is_on: ##get into selection mode 207 | if evtType == 'key up': return False 208 | #log.log("get in page up down") 209 | incr = self.item_num if key == 'page down' else -self.item_num 210 | self.MoveCandidateSelection( incr ) 211 | #self.StateReset() 212 | self.state_is_tab_selection = False 213 | #log.log("get out page up down") 214 | return False 215 | #else 216 | return True 217 | 218 | if is_active: return False 219 | 220 | if evtType == 'key up': 221 | #log.log("get out key up") 222 | return True 223 | 224 | pos = self.GetCaretPosition() 225 | #log.log(pos) 226 | old_pos = self.last_pos 227 | self.last_pos = pos 228 | #log.log('pos = %s old_pos = %s'%(pos,old_pos) ) 229 | if ( old_pos and ( pos[0] - old_pos[0] < -8 or 230 | pos[1] - old_pos[1] > 16 or 231 | pos[1] - old_pos[1] < -16 ) ): 232 | #log.log("position condition not meet. StateReset") 233 | self.StateReset() 234 | return True 235 | 236 | #log.log 'with key = %s'%(key) 237 | 238 | ### combo key with ctrl or alt encoutered, rest 239 | if ctrl or alt or not key in StringKeys: 240 | #log.log("non-string key encountered") 241 | if key == 'backspace': 242 | if len( self.section_list ) >= 1: del self.section_list[-1] 243 | if self.word: self.word = self.word[:-1] 244 | self.ShowSelection() 245 | #log.log("get out up backspace") 246 | return True 247 | else: #record the word to word_list 248 | #log.log("try update %s to word_list %s"%(self.word,self.word_list) ) 249 | #log.log len(self.word), self.ShowBitNum 250 | #remove last SpecKeys 251 | while len(self.word)>1 and self.word[-1] in SpecKeys: self.word = self.word[:-1] 252 | if len(self.word)>=self.ShowBitNum+2 and min(self.word)!=max(self.word): 253 | #log.log("update word %s"%self.word) 254 | #check if word is consist of a single char ignore 255 | self.UpdateWord( self.word ) 256 | #log.log("after word_list = %s"%(self.word_list) ) 257 | pass 258 | else: 259 | #log.log("word content condition not meet to updateword") 260 | #log.log("word = %s min %s max %s"%(self.word,min(self.word),max(self.word))) 261 | pass 262 | self.StateReset() 263 | #log.log("get out up backspace") 264 | return True 265 | pass 266 | 267 | ### normal char dealing 268 | #log.log("normal char dealing key = %s shift = %s"%(key,shift) ) 269 | ### add key to word 270 | if shift: self.word += ( UpperKeys[ key ] if key in UpperKeys else key.upper() ) 271 | else: self.word += key 272 | 273 | #log.log("word expanded to %s"%self.word) 274 | ### 275 | if len(self.word)>2 and self.word[0] == self.word[1]: 276 | self.StateReset() 277 | return True 278 | if not self.auto_complete_on: 279 | return True 280 | #log.log self.word 281 | wordlen = len( self.word ) 282 | 283 | if wordlen == 1: 284 | self.start_pos = pos 285 | return True 286 | 287 | if wordlen < self.ShowBitNum: return True 288 | 289 | if wordlen == self.ShowBitNum: ### show selection window at starting pos 290 | #candidate will be at least MaxNum+2 bits 291 | lind,rind = self.FindSection( self.word ) 292 | self.section_list.append( (lind,rind) ) ## may append (0,0) if not find 293 | self.ShowSelection(True) 294 | return True 295 | 296 | if wordlen > self.ShowBitNum: ### update selection window 297 | lind,rind = self.FindSection( self.word ) 298 | self.section_list.append( (lind,rind) ) 299 | self.ShowSelection() 300 | return True 301 | 302 | ### won't come here 303 | return True 304 | 305 | def ShowSelection(self,initshow=False): 306 | lind,rind = (0,0) 307 | if len( self.section_list ) > 0: lind,rind = self.section_list[-1] 308 | #log.log lind,rind 309 | if lind == rind: 310 | self.state_is_on = False 311 | self.state_no_candidate = True 312 | self.Show(False) 313 | return False 314 | #log.log "section = %s lind = %s rind = %s"%(self.section_list,lind,rind) 315 | #log.log "section list now ",self.word_list[ lind:rind ] 316 | #find out the max width 317 | self.state_is_on = True 318 | self.width = self.min_width 319 | self.width = min(self.max_width, 320 | max( list(map( lambda x:len(x[1])*self.char_width, 321 | self.word_list[ lind:rind ] ) ) ) + 40 ) 322 | self.item_num = min( rind-lind, self.MaxNum ) 323 | #log.log 'show list with item_num = ',self.item_num 324 | self.old_height = self.height 325 | self.height = (self.char_height ) * self.item_num + 6 326 | self.SetSize( (self.width, self.height) ) 327 | self.Move( (self.start_pos[0],self.start_pos[1]-self.height) ) 328 | 329 | word_list = list(map(lambda x:x[1], self.word_list[ lind:rind ])) 330 | self.lists.Set( word_list ) 331 | self.Show( True ) 332 | #win32gui.SetForegroundWindow(self.hw) 333 | pass 334 | 335 | def HideSelection(self): 336 | self.Show( False ) 337 | 338 | 339 | def StateReset(self): 340 | self.Show(False) 341 | self.section_list = [] 342 | self.word = '' 343 | self.start_pos = None 344 | self.state_is_on = False 345 | self.state_is_selection = False 346 | self.state_is_tab_selection = False 347 | self.state_no_candidate = False 348 | self.tab_selection_word = '' 349 | self.last_pos = None 350 | pass 351 | 352 | def UpdateTabCandidate(self,new_word,old_word): 353 | #log.log("get into update cadidate") 354 | for i in range( len(old_word) ): 355 | geeKeyboard.keyPress('backspace') 356 | geeKeyboard.keyRelease('backspace') 357 | pass 358 | for ch in new_word: 359 | upper = False 360 | if ch in LowerKeys: 361 | upper = True 362 | ch = LowerKeys[ ch ] 363 | elif ch.isupper(): 364 | upper = True 365 | ch = ch.lower() 366 | pass 367 | #log.log("deal char %s with upper = %s and shift = %s"%(ch,upper,self.state_on_shift) ) 368 | if self.state_on_shift: 369 | shift_key = 'left shift' if keyboard.is_pressed('left shift') else 'right shift' 370 | if upper: 371 | #log.log"case 1" #shift is on and a upper char 372 | geeKeyboard.keyPress(ch) 373 | geeKeyboard.keyRelease(ch) 374 | else: 375 | #log.log"case 2" #not upper char, but the shift key is on 376 | geeKeyboard.keyRelease(shift_key) 377 | geeKeyboard.keyPress(ch) 378 | geeKeyboard.keyRelease(ch) 379 | geeKeyboard.keyPress(shift_key) 380 | pass 381 | pass 382 | else: # not on shift 383 | if upper: 384 | #log.log"case 3" #not on shift and A upper char 385 | geeKeyboard.keyPress('left shift') 386 | geeKeyboard.keyPress(ch) 387 | geeKeyboard.keyRelease(ch) 388 | geeKeyboard.keyRelease('left shift') 389 | else: 390 | #log.log"case 4" #not shift and not upper 391 | geeKeyboard.keyPress(ch) 392 | geeKeyboard.keyRelease(ch) 393 | pass 394 | pass 395 | pass 396 | #log.log("get out of update cadidate") 397 | pass 398 | 399 | def MoveCandidateSelection(self,direction='down'): 400 | if direction == 'down': incr = 1 401 | elif direction == 'up': incr = -1 402 | else: incr = direction 403 | new_item = self.lists.GetSelection() + incr 404 | if new_item < 0: new_item = 0 405 | elif new_item >= self.lists.GetCount(): new_item = self.lists.GetCount() - 1 406 | else:pass 407 | word = self.lists.GetString( new_item ) 408 | self.lists.SetSelection( new_item ) 409 | self.lists.EnsureVisible( new_item ) 410 | return word 411 | 412 | def GetTopWindow(self): 413 | # fhwnd = win32gui.GetFocus() 414 | # user32.GetGUIThreadInfo(0, byref(self.ui) ) 415 | # return self.ui.hwndFocus 416 | return None 417 | 418 | def GetCaretPosition(self): 419 | # fhwnd = win32gui.GetFocus() 420 | # user32.GetGUIThreadInfo(None, byref(self.ui) ) # None/0 for foreground thread 421 | # if self.ui.hwndFocus != self.popup_hw: self.hw = self.ui.hwndFocus 422 | # return win32gui.ClientToScreen(self.ui.hwndFocus, 423 | # (self.ui.rcCaret.left, self.ui.rcCaret.top ) 424 | # ) 425 | return (0,0) 426 | 427 | def OnLists(self,evt): 428 | #log.log("selection = %s "%(self.lists.GetSelection() ) ) 429 | pass 430 | 431 | def Destroy(self): 432 | ### save lists to dictfile 433 | cont = '' 434 | for item in self.word_list: 435 | if item[2] <= 0: continue 436 | cont += "%s %s\n"%(item[1],item[2]) 437 | pass 438 | f = open( self.dictfile, 'w' ) 439 | f.write( cont ) 440 | f.close() 441 | 442 | super(AutoComplete,self).Destroy() 443 | pass 444 | 445 | def SwitchState(self,state=None): 446 | if not state: 447 | #log.log("geekey+tab to switch the auto complete state") 448 | self.auto_complete_on = not self.auto_complete_on 449 | if not self.auto_complete_on: #turn off 450 | self.StateReset() 451 | self.geekey.taskBarIcon.ShowBalloon( lt('_autocomplete'),lt('_autocomplete_off')) 452 | pass 453 | else: #turn on 454 | self.geekey.taskBarIcon.ShowBalloon( lt('_autocomplete'),lt('_autocomplete_on')) 455 | pass 456 | #log.log("get out geekey + tab") 457 | pass 458 | else: 459 | if state == 'True' or state == 'on': self.auto_complete_on = True 460 | if state == 'False' or state == 'off': self.auto_complete_on = False 461 | pass 462 | pass 463 | 464 | 465 | 466 | 467 | 468 | 469 | pass 470 | -------------------------------------------------------------------------------- /Configure.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from res import * 5 | add_lang('en',{ 6 | '_play_ratio':'Replay Ratio', 7 | '_macro_label':'Alias', 8 | '_operation_sequence':'Operation Sequence', 9 | 10 | }) 11 | add_lang('zh',{ 12 | '_operation_sequence':'操作序列', 13 | '_macro_label':'别名', 14 | '_play_ratio':'重放速率', 15 | }) 16 | 17 | str2bool = lambda v: True if v == 'True' else False 18 | class GeeKeyDialog( wx.Dialog ): 19 | def __init__(self,config,*args,**kwargs): 20 | self.button = {} 21 | self.checkbox = {} 22 | self.combobox = {} 23 | self.textctrl = {} 24 | self.textWidth = 150; self.contWidth = 350; self.height = 500; self.yPos = 10; self.H = 30 25 | self.textPanel = None 26 | self.contPanel = None 27 | self.sizer = None 28 | self.config = config 29 | #log.log('geekeydialog created with config = ',self.config) 30 | ############################ 31 | if 'height' in self.config: self.height = self.config['height'] 32 | wx.Dialog.__init__(self,*args,**kwargs) 33 | 34 | self.sizer = wx.BoxSizer(wx.HORIZONTAL) 35 | self.textPanel = wx.Panel(self,size=(self.textWidth,self.height) ) 36 | self.textPanel.SetBackgroundColour( "#E5E5E5" ) 37 | 38 | self.contPanel = wx.Panel(self,size=(self.contWidth,self.height) ) 39 | self.bottomPanel = wx.Panel( self.contPanel, size=(self.contWidth, self.H), pos = (0.5*self.H, self.height - 2 * self.H ) ) 40 | self.sizer.Add( self.textPanel ) 41 | self.sizer.Add( self.contPanel ) 42 | 43 | ############################################################## 44 | self.SetTitle( lt('_'+self.config['type']+'_to_key', self.config['name'] ) ) 45 | #################### 46 | if self.config['type'] == 'function': 47 | self.addText( lt('_function_path') ); pos = self.contPos(); size = self.contSize() 48 | self.textctrl['value'] = wx.TextCtrl( self.contPanel, 49 | pos = pos, size = size, 50 | value = self.config['value'] ) 51 | self.button['browse']= wx.Button( self.contPanel, 52 | pos = ( pos[0]+size[0],pos[1] ),size = ( 30,size[1] ), 53 | label = '...' ) 54 | self.button['browse'].Bind( wx.EVT_BUTTON,self.function_OnBrowse ) 55 | pass 56 | elif self.config['type'] == 'macro': 57 | 58 | self.addText( lt('_operation_sequence')); pos = self.contPos(); size = self.contSize(y=2*self.H) 59 | self.textctrl['value'] = wx.TextCtrl( self.contPanel, 60 | pos = pos, size = size, 61 | value = self.config['value'], 62 | style = wx.TE_RICH|wx.TE_MULTILINE|wx.TE_BESTWRAP, 63 | ) 64 | 65 | self.addSpacer(2*self.H) 66 | self.addText( lt('_macro_label') ); pos = self.contPos(); size = self.contSize() 67 | self.textctrl['label'] = wx.TextCtrl( self.contPanel, 68 | pos = pos, size = (size[0]/2,size[1]), 69 | value = self.config['label'] 70 | ) 71 | 72 | self.addSpacer() 73 | self.addText( lt('_play_ratio') ); pos = self.contPos(); size = self.contSize() 74 | self.textctrl['ratio'] = wx.TextCtrl( self.contPanel, 75 | pos = pos, size = (size[0]/4,size[1]), 76 | value = str( self.config['ratio'] ), 77 | ) 78 | self.textctrl['label'].SetFocus() 79 | pass 80 | else: raise Exception("type unknown") 81 | 82 | ################## 83 | ### buttons 84 | self.button['ok'] = wx.Button(self.bottomPanel, label=lt("OK"),pos=(self.H,0),size=(80,self.H ) ) 85 | self.button['cancel'] = wx.Button(self.bottomPanel, label=lt("Cancel"),pos=(2*self.H+80,0),size=(80,self.H) ) 86 | self.button['ok'].Bind( wx.EVT_BUTTON,self.OnOk ) 87 | self.button['cancel'].Bind( wx.EVT_BUTTON, self.OnCancel) 88 | ################## 89 | self.SetSizerAndFit( self.sizer ) 90 | self.Bind( wx.EVT_CHAR_HOOK, self.OnKeyUP) 91 | pass 92 | ################################################################################### 93 | def OnKeyUP(self,evt): 94 | if evt.GetKeyCode() == wx.WXK_ESCAPE: 95 | self.OnCancel(evt) 96 | pass 97 | if evt.GetKeyCode() == wx.WXK_RETURN: 98 | self.OnOk(evt) 99 | pass 100 | evt.Skip() 101 | pass 102 | 103 | def contSize(self,x=None,y=None): return (self.contWidth - 3*self.H if not x else x, self.H if not y else y) 104 | def contPos(self): return (1.5*self.H, self.yPos) 105 | def addText(self,label): 106 | self.yPos += self.H 107 | text = wx.StaticText(self.textPanel,label=label, pos=(0,self.yPos), size=(self.textWidth-self.H, self.H ), style= wx.ALIGN_RIGHT ) 108 | return text 109 | 110 | def addSpacer(self,h=None): 111 | self.yPos += self.H if not h else h 112 | pass 113 | 114 | def addCheckBox(self,key,label): 115 | self.checkbox[key] = wx.CheckBox(self.contPanel,label = label,size= self.contSize(), pos = self.contPos() ) 116 | self.checkbox[key].SetValue( str2bool( self.config[key] ) ) 117 | pass 118 | 119 | def function_OnBrowse(self,evt): 120 | fdl = wx.FileDialog(self, lt("_choose_program"), 121 | wildcard="Executables (*.exe)|*.exe|All (*.*)|*.*", 122 | style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST|wx.FD_CHANGE_DIR) 123 | fdl.SetDirectory( self.config['value'] ) 124 | if fdl.ShowModal() == wx.ID_OK: 125 | self.config['value' ] = fdl.GetPath() 126 | self.textctrl['value'].SetLabel( fdl.GetPath() ) 127 | pass 128 | fdl.Destroy() 129 | pass 130 | 131 | def OnCancel(self,evt): 132 | self.EndModal( wx.ID_CANCEL ) 133 | pass 134 | 135 | def OnOk(self,evt): 136 | for key,value in self.checkbox.items(): 137 | self.config[key] = str( value.GetValue() ) 138 | pass 139 | 140 | for key,value in self.textctrl.items(): 141 | self.config[key] = value.GetValue() 142 | pass 143 | 144 | if self.config['type'] == 'function': 145 | self.config['label'] = os.path.basename( self.config['value'] ) 146 | pass 147 | 148 | if self.config['type'] == 'macro': 149 | self.config['ratio'] = str( toFloat( self.config['ratio'],1 ) ) 150 | pass 151 | 152 | self.EndModal( wx.ID_OK ) 153 | pass 154 | 155 | def GetConfig(self): 156 | return self.config 157 | 158 | pass 159 | 160 | class ConfigDialog( wx.Dialog): 161 | 162 | def __init__(self,config,*args,**kwargs): 163 | self.config = None 164 | self.button = {} 165 | self.checkbox = {} 166 | self.combobox = {} 167 | self.textWidth = 150; 168 | self.contWidth = 350; 169 | self.height = 500; 170 | self.yPos = 10; 171 | self.H = 30 172 | self.textPanel = None 173 | self.contPanel = None 174 | self.sizer = None 175 | 176 | self.config = config 177 | wx.Dialog.__init__(self,*args,**kwargs) 178 | self.SetTitle( lt('_configure') ) 179 | self.sizer = wx.BoxSizer(wx.HORIZONTAL) 180 | self.textPanel = wx.Panel(self,size=(self.textWidth,self.height) ) 181 | self.textPanel.SetBackgroundColour( "#E5E5E5" ) 182 | self.contPanel = wx.Panel(self,size=(self.contWidth,self.height) ) 183 | self.bottomPanel = wx.Panel( self.contPanel, size=(self.contWidth, self.H), pos = (0.5*self.H, self.height - 2 * self.H ) ) 184 | self.sizer.Add( self.textPanel ) 185 | self.sizer.Add( self.contPanel ) 186 | 187 | #################### 188 | #################### 189 | ##########enable geekey 190 | self.addText( lt('Geekey Enabled') ) 191 | self.addCheckBox('geekeyenabled',lt('Enable GeeKey HotKey system') ) 192 | self.addSpacer() 193 | 194 | self.addText( lt('GeeKey Mode') ) 195 | self.combobox['geekeymode'] = wx.ComboBox( self.contPanel, 196 | pos = self.contPos(), 197 | choices = [ 198 | lt('block'), 199 | lt('longblock'), 200 | ] ) 201 | self.combobox['geekeymode'].SetValue( lt('block') if self.config['geekeymode'] in ('block','Block','阻塞') else lt('longblock') ) 202 | self.addText( '' ) 203 | 204 | txt = wx.StaticText(self.contPanel, pos=self.contPos(), 205 | label = lt("'block' mode always blocks original key.") ) 206 | self.addText( '' ) 207 | txt = wx.StaticText(self.contPanel, pos=self.contPos(), 208 | label = lt("'longblock' mode only blocks when pressed longer or as GeeKey.") ) 209 | 210 | self.addSpacer() 211 | ##########language 212 | self.addText( lt('_language') ) 213 | self.combobox['language'] = wx.ComboBox( self.contPanel, 214 | pos = self.contPos(), 215 | choices = ['中文','English'] ) 216 | self.combobox['language'].SetValue( 'English' if self.config['language'] in ('en','en_US') else '中文' ) 217 | #self.combobox['language'].Bind( wx.EVT_COMBOBOX, self.OnLanguageSelected ) 218 | self.addSpacer() 219 | ##########default cat 220 | self.addText( lt('_general') ) 221 | # self.addCheckBox('startup',lt('_startup') ) 222 | 223 | # self.addText( lt('') ) 224 | # self.addCheckBox('runasadmin',lt('_runasadmin') ) 225 | 226 | # self.addText( lt('') ) 227 | # self.addCheckBox('startshow',lt('_startshow') ) 228 | 229 | # self.addText( lt('') ) 230 | # self.addCheckBox('startautocomplete',lt('_start_autocomplete') ) 231 | 232 | #self.addText( lt('') ) 233 | self.addCheckBox('startvim',lt('_startvim') ) 234 | 235 | self.addText( lt('') ) 236 | self.addCheckBox('doubleclickfix',lt('_doubleclickfix') ) 237 | 238 | self.addText( lt('') ) 239 | self.addCheckBox('printkeyevent',lt('_print_key_event') ) 240 | 241 | self.addSpacer() 242 | 243 | ##########Acount 244 | #self.addText( lt('_account') ) 245 | 246 | ################## 247 | ### buttons 248 | self.button['ok'] = wx.Button(self.bottomPanel, label=lt("OK"),pos=(self.H,0),size=(80,self.H ) ) 249 | self.button['cancel'] = wx.Button(self.bottomPanel, label=lt("Cancel"),pos=(2*self.H+80,0),size=(80,self.H) ) 250 | self.button['ok'].Bind( wx.EVT_BUTTON,self.OnOk ) 251 | self.button['cancel'].Bind(wx.EVT_BUTTON, self.OnCancel) 252 | ################## 253 | self.SetSizerAndFit( self.sizer ) 254 | self.Bind( wx.EVT_CHAR_HOOK, self.OnKeyUP) 255 | pass 256 | 257 | def contSize(self):return (self.contWidth - 3*self.H, self.H) 258 | def contPos(self): return (1.5*self.H, self.yPos) 259 | 260 | def addConText(self,cont,height): 261 | text = wx.StaticText(self.contPanel,label=cont, pos=self.contPos(), size=self.contSize(y=height*self.H) ) 262 | return text 263 | 264 | def addText(self,label): 265 | self.yPos += self.H 266 | text = wx.StaticText(self.textPanel,label=label, pos=(0,self.yPos), size=(self.textWidth-self.H, self.H ), style= wx.ALIGN_RIGHT ) 267 | return text 268 | 269 | def addSpacer(self,h=None): 270 | self.yPos += self.H if not h else h 271 | 272 | def addCheckBox(self,key,label): 273 | self.checkbox[key] = wx.CheckBox(self.contPanel,label = label,size= self.contSize(), pos = self.contPos() ) 274 | self.checkbox[key].SetValue( str2bool( self.config[key] ) ) 275 | pass 276 | 277 | def OnCancel(self,evt): 278 | self.EndModal( wx.ID_CANCEL ) 279 | pass 280 | 281 | def OnOk(self,evt): 282 | for key,value in self.checkbox.items(): 283 | self.config[key] = str( value.GetValue() ) 284 | pass 285 | 286 | self.config['language'] = 'en' if self.combobox['language'].GetValue() == 'English' else 'zh' 287 | self.config['geekeymode'] = 'block' if self.combobox['geekeymode'].GetValue() in ('block','阻塞') else 'longblock' 288 | self.EndModal(wx.ID_OK) 289 | pass 290 | 291 | def GetConfig(self): 292 | return self.config 293 | 294 | def OnKeyUP(self,evt): 295 | if evt.GetKeyCode() == wx.WXK_ESCAPE: self.OnCancel(evt) 296 | if evt.GetKeyCode() == wx.WXK_RETURN: self.OnOk(evt) 297 | evt.Skip() 298 | pass 299 | 300 | pass 301 | 302 | 303 | 304 | -------------------------------------------------------------------------------- /GlobalVim.dmg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/einsxiao/GlobalVim-Mac/b94816d3fb879d395ef3298a910299489d7265b2/GlobalVim.dmg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GlobalVim 2 | 3 | 二进制dmg包: [GlobolVim.dmg](https://github.com/einsxiao/GlobalVim-Mac/blob/master/GlobalVim.dmg?raw=true) 4 | 5 | 程序键盘监听需要额外权限, 6 | 使用python需要root权限, sudo python3 App.py启动程序 7 | 8 | 二进制安装需要将程序添加到 System Preferences > Security & Privacy > Privacy > Accessibility 列表中. 9 | 10 | GlobalVim能让您在任意环境下使用vim模式编辑。强大易用的GeeKey热键方案能提供丰富灵活的键盘定制和键盘编程能力,让您从从容处理大量的重复输入/操作。 11 | 12 | ## vim模式 —— 把所有编辑器和输入框都变成vim 13 | 14 | GlobalVim的vim模式并不只是简单的vim键位映射,它还支持vim的各种模式以及常用命令: 15 | 16 | #### vim模式在任何编辑器和输入框中均生效。 17 | #### vim模式支持寄存器机制,支持录制包含键盘和鼠标事件的广义宏。 18 | #### vim模式表达式寄存器“= 上可对python表达式求值。 19 | #### vim模式支持完全的的正则表达式替换功能 20 | 21 | 22 | 23 | ### vim常用操作,入门介绍(可参考详细的vim教程) 24 | 25 | 26 | #### normal 常规模式 27 | 在启动vim模式后,vim所在模式即为normal模式。该模式下我们可以通过由字符或字符组合命令实现光标移动或者编辑操作。 28 | normal模式不能直接输入。该模式下按i即可进入插入模式。 29 | 30 | #### insert 插入模式 31 | normal模式下,按下 i/a 键进入插入模式,可以在当前模式插入字符,插入模式下,按esc进入normal模式 32 | 插入模式与常用的无模式编辑的状态一致。 33 | 34 | #### visual 可视模式 35 | 在normal模式下,按 v 即可进入visual模式,然后移动光标选择范围。visual模式下,按 v 或者 esc 退出到 normal 模式。 36 | visual模式下,可对选中的范围执行正则替换命令 37 | 38 | #### command 命令模式 39 | 在normal或者visual模式下,按:进入命令模式,光标在提示窗口处激活,处于输入命令状态。 40 | 按esc取消当前命令。 41 | 按enter执行当前命令。 42 | 43 | GlobalVim支持vim大部分常用命令 44 | 45 | ### 寄存器 46 | GlobalVim支持以下寄存器 47 | 48 | "" 默认寄存器 49 | "= 表达式寄存器 "= 50 | "a-z 命名寄存器 51 | "A-Z 追加寄存器 52 | "0 拷贝寄存器 53 | "1-9 删除寄存器 54 | 55 | 查看寄存器值命令: reg 56 | 搜索(调用当前环境的搜索功能): / 57 | 58 | #### 正则替换 59 | vim模式支持正则替换, 60 | 替换命令支持范围指定,支持偏移量,不支持 c 标志 61 | 替换当前行: 62 | ``` 63 | :s/xx/yy/ 或者 :.s/xx/yy/gi 64 | ``` 65 | 替换当前后前后3行: 66 | ``` 67 | :.-3,.+3s/xx/yy/g 68 | ``` 69 | 替换全文: 70 | ``` 71 | :%s/xx/yy/g 72 | ``` 73 | 74 | #### "=表达式寄存器 75 | 表达式寄存器支持对python表达式求值: 76 | 在当前位置插入0-99的序列 77 | ``` 78 | “=' '.join( map(str, range(100) ) )【回车】p 79 | ``` 80 | 81 | ### vim模式开启/关闭 82 | 83 | 通过在程序面板:单击 v 键 84 | 通过快捷键:GeeKey+v (需要开启geekey热键) 85 | 86 | ### vim模式特殊设定 87 | 88 | 在normal状态下,按下esc键会向系统发送esc,而visual和insert模式下,esc会被拦截,vim状态返回normal状态。 89 | 基于windows下普遍的输入特性,append(a) 命令不在表示在当前字符之后插入 而是和 insert(i) 命令一样都是在当前位置插入。 90 | 为了大部分输入环境的行为一致,GlobalVim不支持r/R操作。 91 | 92 | #### 对中文输入的特别支持 93 | 94 | 命令模式下,按键事件会先被GlobalVim捕获,不会发送给输入法。 95 | 96 | ## GeeKey 热键 97 | 98 | GeeKey方案提供了强大的快捷键方案,让日常重复的输入工作变得更容易。 99 | 100 | 101 | GeeKey热键支持两种模式: 102 | 1. 长按阻塞, 短按状态下,GeeKey行使原按键功能。长按或者组合键则阻塞原按键功能。 103 | 2. 阻塞,始终阻塞GeeKey原按键功能。 104 | 105 | 通过热键,最常用编辑操作(上下左右,Home/End,PageUp/PageDown)都不用移动手掌,只需要GeeKey+相应按键即可完成。 106 | CapsLock 与 Esc, ~ , Tab, Shift, Ctrl, Win Alt 的按键位置可以通过程序面板进行交换(但需要以管理员模式运行程序才能操作,重启生效)。其余与热键连用的映射则可以随时通过相应方式方便地进行修改。 107 | 108 | GeeKey新版本对空格档和录制功能键盘操作序列进行了优化,取消原来以复杂组合按键的形式,代之以类vim的按键序列的形式。 109 | 110 | ### 空档功能 111 | GeeKey+space 【x】& &-可以触发x的空挡绑定 112 | 113 | ### 录制操作序列 114 | GeeKey+q 【x】 开始录制绑定到x的操作宏 115 | GeeKey+q space 【x】 开始录制绑定到x的空挡的操作宏 116 | 117 | ### 前置倍增操作算符 118 | 119 | GeeKey+Space 【N】 【X】& &-操作X重复操作N次 120 | 121 | ## 其它 122 | 123 | ### vim模式命令自定义 124 | 125 | GlobalVim定制自由度很大。软件启动的所有配置信息都在文件 %安装文件夹%/config/default.ini 中。 126 | 当配置出现错误,软件不能启动时,用户需要删除default.ini,并重启软件。 127 | 配置项的内容可以通过宏录制来得到。录制结果的第二个参数为重放速率,0为无限快,1为原样速率。 128 | 129 | ### normal模式 自定义命令 130 | 修改default.ini中的vim_map_【按键序列】:: 131 | 132 | ### 命令模式 自定义命令 133 | 修改default.ini中的vim_cmd_map_【命令名字】:: 134 | 135 | 用户修改配置文件之后,需要重新载入才能生效,否则配置文件的修改会被覆盖。 136 | 137 | ### 修复鼠标硬件错误导致的错误双击 138 | GlobalVim窗口 选项>配置 中可以设置 修复 鼠标双击硬件错误 139 | 当勾选此项时,鼠标左键抬起操作引发的额外左键按下抬起操作会被忽略。 140 | 141 | 142 | 143 | ### 已知问题 144 | 键盘numlock开启,可能会导致vim模式启动后,shift一直按下的情况 145 | 146 | ### 当出现键盘状态错误时 147 | 点击主界面左上方Clear按键,可以重置所有按键的状态。 148 | 149 | ### 升级须知 150 | 当用户升级后,新功能不能使用,或者软件不能启动时,可删除用户家目录下的GlobalVim/default.ini文件,然后重启 151 | 152 | 3.2.1.0& &增加部分vim指令, 修复指示器颜色bug, vim常规模式F1-12功能按键直接放行 153 | 3.1.2.0& &修复vim宏和 GeeKey宏bug 154 | 3.1.1.0& &修复按键事件丢失bug,GeeKey可以选择任意多个按键 155 | 2019.05.17& &取消取色器功能,增加状态重设按钮用于键盘状态错误时,重新设置状态。 156 | 2019.05.16.2& &修复当以Esc为GeeKey时候与vim模式的冲突。 157 | 2019.05.16.1& &增加GeeKey长短按模式。 158 | 2019.05.16& &寄存器鲁棒性加强,visual模式替换bug修复,支持GeeKey热键自定义。移除安装文件权限要求。 159 | 2019.05.14& &修复寄存器bug,增加正则替换功能,增加命令模式中文支持。 160 | 2019.05.11& &添加寄存器机制,支持宏录制, 支持命令reg, register。 161 | 2019.05.07& &GlobalVim模式查找命令修改。 162 | -------------------------------------------------------------------------------- /Tutorial.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from res import * 5 | add_lang('zh',{ 6 | '_manual':'功能手册', 7 | 8 | '_geekey':"GeeKey热键选择", 9 | '_geekey_cont':"可以点击主界面左上角GK按钮来选择任意键作为热键.", 10 | 11 | "_overview":"概诉", 12 | '_overview_cont':"""软件提供全局vim按键绑定和功能, 支持模式编辑/寄存器/宏/正则替换. 13 | 软件提供强大快捷的GeeKey热键方案, 能快速高效完成各种操作. 绑定的内容通过主面板编辑. 14 | 项目主页: """, 15 | 16 | "_esc":'空档状态退出', 17 | "_esc_cont":'Esc -取消空档状态', 18 | 19 | '_oper_record':'快捷宏', 20 | '_oper_record_cont':"""GeeKey+q 【X】 -录制宏到按键X 21 | GeeKey+【X】 -执行X绑定宏 22 | GeeKey+q space 【X】 -录制宏到按键X的空档绑定 23 | GeeKey+space 【X】 -执行X的空档绑定宏 24 | GeeKey+q -结束录制 """, 25 | 26 | '_quick_key':'快捷按键', 27 | '_quick_key_cont':"""GeeKey+【X】 -模拟X的绑定按键 """, 28 | 29 | '_quick_text/app':'快捷文本/应用', 30 | '_quick_text/app_cont':"""GeeKey+【X】 -发送绑定文本到当前编辑区/启动绑定应用 31 | GeeKey+Space 【X】 -触发空档绑定文本/应用""", 32 | 33 | '_quick_repeat':'快速重复', 34 | '_quick_repeat_cont':"""GeeKey+Space 【数字N】 【X】 -操作X被重复N次""", 35 | 36 | '_auto_complete':'自动补全', 37 | '_auto_complete_cont':"""GeeKey+Space Tab -开启/关闭自动补全功能 """, 38 | 39 | '_panel_quickkey':'面板呼出', 40 | '_panel_quickkey_cont':"""GeeKey+Space Space -呼出/隐藏主程序面板 """, 41 | 42 | '_panel_vim':'vim状态切换', 43 | '_panel_vim_cont':"""GeeKey+v -关闭/开启vim模式 """, 44 | }) 45 | add_lang('en',{ 46 | "_esc":'Quit Spacing State', 47 | "_esc_cont":'Esc -quit spacing state.', 48 | 49 | '_geekey':"GeeKey select", 50 | '_geekey_cont':"HotKey can be changed by click GK button on main panel.", 51 | 52 | "_overview":"Overview", 53 | '_overview_cont':"""The application provides Vim keybindings and functions system wide with registers/macro recording/pattern substituting supported.\n 54 | The application also provides the powerfull geekey hotkey solution which can be very quick and efficient. All bindings can be revised by application panel. 55 | More detail instructions please visit project index: """, 56 | 57 | '_manual':'Manual', 58 | 59 | '_oper_record':'Quick Macro', 60 | '_oper_record_cont':"""GeeKey+q 【X】 -record macro of X 61 | GeeKey+【X】 -execute binding macro of X 62 | GeeKey+q space 【X】) -record spacing binding macro of X 63 | GeeKey+space 【X】 -execute spacing binding macro of X 64 | GeeKey+q -stop recording""", 65 | 66 | '_quick_key':'Quick Key', 67 | '_quick_key_cont':"""GeeKey+【X】 -simulate the binding key.""", 68 | 69 | '_quick_text/app':'Quick Text/Application', 70 | '_quick_text/app_cont':"""GeeKey+【X】 -send binding text to editing area/launch binding application 71 | GeeKey+Space K -trigger spacing binding text/application.""", 72 | 73 | '_quick_repeat':'Quick Repeat', 74 | '_quick_repeat_cont':"""GeeKey+Space 【N】 【X】 -operation X will be repeated N Times.""", 75 | 76 | '_auto_complete':'Auto Complete', 77 | '_auto_complete_cont':"""GeeKey+Space Tab -turn on/off the auto-complete mode.""", 78 | 79 | '_panel_quickkey':'Main Panel', 80 | '_panel_quickkey_cont':"""GeeKey+Space Space -show/hide the main panel.""", 81 | 82 | 83 | '_panel_vim':'Vim State Switch', 84 | '_panel_vim_cont':"""GeeKey+v -switch vim on/off""" 85 | 86 | }) 87 | 88 | 89 | class TutorialDialog( wx.Dialog): 90 | 91 | def __init__(self,*args,**kwargs): 92 | self.config = None 93 | self.button = {} 94 | self.checkbox = {} 95 | self.combobox = {} 96 | self.textWidth = 150; self.contWidth = 555; self.height = 755; self.yPos = 10; self.H = 30 97 | self.textPanel = None 98 | self.contPanel = None 99 | self.sizer = None 100 | 101 | wx.Dialog.__init__(self,*args,**kwargs) 102 | self.SetTitle( lt('_manual') ) 103 | self.sizer = wx.BoxSizer(wx.HORIZONTAL) 104 | self.textPanel = wx.Panel(self,size=(self.textWidth,self.height) ) 105 | self.textPanel.SetBackgroundColour( "#E5E5E5" ) 106 | self.contPanel = wx.Panel(self,size=(self.contWidth,self.height) ) 107 | self.bottomPanel = wx.Panel( self.contPanel, size=(self.contWidth, self.H), pos = (0, self.height - 2 * self.H ) ) 108 | self.sizer.Add( self.textPanel ) 109 | self.sizer.Add( self.contPanel ) 110 | 111 | #################### 112 | #################### 113 | 114 | self.addText( lt('_overview') ) 115 | self.addContText( lt('_overview_cont')+INFO['HomePage'], GetMap('color','function_key'), 3.5 ) 116 | 117 | self.addText( lt('_geekey') ) 118 | self.addContText( lt('_geekey_cont'), GetMap('color','geekey'),1.0 ) 119 | 120 | self.addText( lt('_panel_vim') ) 121 | self.addContText( lt('_panel_vim_cont'), GetMap('color','function_button') ) 122 | 123 | self.addText( lt('_quick_repeat') ) 124 | self.addContText( lt('_quick_repeat_cont'),GetMap('color','edit_button'),1.0 ) 125 | 126 | self.addText( lt('_esc') ) 127 | self.addContText( lt('_esc_cont'),GetMap('color','function_button'),1.0 ) 128 | 129 | self.addText( lt('_oper_record') ) 130 | self.addContText( lt('_oper_record_cont'), GetMap('color','macro_key'), 4.0 ) 131 | 132 | self.addText( lt('_quick_key') ) 133 | self.addContText( lt('_quick_key_cont'), GetMap('color','menu_key') ) 134 | 135 | self.addText( lt('_quick_text/app') ) 136 | self.addContText( lt('_quick_text/app_cont'), GetMap('color','text_key'),1.8 ) 137 | 138 | self.addText( lt('_auto_complete') ) 139 | self.addContText( lt('_auto_complete_cont'), GetMap('color','function_key') ) 140 | 141 | self.addText( lt('_panel_quickkey') ) 142 | self.addContText( lt('_panel_quickkey_cont'), GetMap('color','function_button') ) 143 | 144 | # self.addText( lt('_panel_capslock') ) 145 | # self.addContText( lt('_panel_capslock_cont'), GetMap('color','function_button') ) 146 | 147 | ################## 148 | self.SetSizerAndFit( self.sizer ) 149 | pass 150 | 151 | def contSize(self,height=1):return (self.contWidth - 3*self.H, self.H*height) 152 | def contPos(self): return (1.5*self.H, self.yPos) 153 | 154 | def addText(self,label): 155 | self.yPos += self.H 156 | text = wx.StaticText(self.textPanel,label=label, pos=(0,self.yPos), size=(self.textWidth-self.H, self.H ), style= wx.ALIGN_RIGHT ) 157 | return text 158 | 159 | def addSpacer(self,height=1): 160 | self.yPos += self.H *height 161 | pass 162 | 163 | def addContText(self,cont,color='#BFEFFF',height=1): 164 | txt = wx.TextCtrl( self.contPanel, wx.ID_ANY, cont, 165 | size = self.contSize(height), 166 | pos = self.contPos(), 167 | style = wx.TE_RICH|wx.TE_READONLY|wx.TE_WORDWRAP| 168 | wx.TE_AUTO_URL|wx.TE_MULTILINE|wx.NO_BORDER, 169 | ) 170 | txt.SetBackgroundColour(color) 171 | txt.Bind(wx.EVT_TEXT_URL, self.OnUrlClicked) 172 | 173 | self.addSpacer( height - 0.4 ) 174 | pass 175 | 176 | def OnUrlClicked(self,evt): 177 | mevt = evt.GetMouseEvent() 178 | if mevt.LeftDown(): 179 | webbrowser.open( INFO['HomePage'] ) 180 | pass 181 | 182 | pass 183 | 184 | -------------------------------------------------------------------------------- /dat/dat_0.dat: -------------------------------------------------------------------------------- 1 | xxx 2 | xxx 3 | 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 4 | -------------------------------------------------------------------------------- /dat/dat_1.dat: -------------------------------------------------------------------------------- 1 | xxx 2 | xxx 3 | /9j/4AAQSkZJRgABAQEASABIAAD/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCACIA1cDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5Bmi5+U7h6Gm+R/sIPc1Zmg/djaq7h1NII8rkg5/nX9yH8d3fcq+VgY+VvoMUPHuTrtI6VaCHJ2//AKqXYob7vPSgOaxWMHyr+8OajMeJuG5/u+tXHiz90AevtTVgzId2PbjrVKIuZlcWq7KDb7Y1ztx24qdIlC/LgNSrEwb5s/WjlFzIqzxK+zbtz9Kcto5DfdH071KYvmztXb6kUq8DOD+B6UcoSkrkP2dinJqMQ+a23c24VaW1DZ6n601YdpX0/SjlFKT5tdiu1uv+6vc+pp3kNjDfN7bqsNEzIuFVju596aq4bcqq3bb6Uco5WvoV3hUqF27QT1zQYxECNoPvjOassrfeUfdODg9KYY3X8TmqDmKYt9yLtXH4U4wgLz26cVa8tnX5l7dKGh+Tf17EGgOYpiEo3K/e+7Thatu6fnVnZvb+L5f0qQHBNMOfoUPs5X+Ebs9c0DH9xT+tXHUseg+tRtb8/dP4cU9WS5SK67QPlV1b2ppiyq53bsg5NWOg/iH405sPGvrkdulSEZMrlNo+aT6Ad6GiZ16LViaL5z9OuKZFA21cNg561SiHNqVlt3Q4Hy7uvpUi2ZX73lsvqR0qVo1Rs7hnJFM8tVHDO3PTPFHKVGpYhlgZeN3PUAUSW7MisflBHX1qYnAI28elNK4XO1/YHotCTWiDmK7wYT5mzSGBnHynC1ZI+X7tNC7V2jb5nfjtRbuHN0IY4wH6dueKjUbV/i+mKtNCZOVbA74700xeZuPzfKOx60coX7LUrm2LN8u3d6UrQNIcMy/J6VYaH90OGXI/WoREph2/Nvz19aOVg5PqNa1+Xn5fekEOVD9xUzwlG+8elIqjyqnfQrmfUiMSvhvm59DTZNu3GJD7Z4NTGIMnXt6U1U/u80ctiuZELW7Nj7qr3B7U0w+QedzK3pVkw7l54FNSPEzL7UWuHMiEQM3C+XhefejyyBklufepFXYPuj5jS+SHGz5uPejkJ5mQmEEjPQdPmprJgH5Rwf71WETafvfgaaU3fLxzU8ocxDN1XkfnmhYsA/M3rxU3l8YyPl7AU0jnb909KOUuMmNSP/gX1pBJk/LHjHHSnhAoUEZb+I4pwXCR7fXjjpRylXZEYC5OVyR1NKqblz8y7fSpBEx4pzxNt6//AFqHGw+Zldodi8qrZ7iolQ7/APWY+lWRE6/d+b2pskZC/MgwO3rU8t9Q5iIqx6fMnekeFf4cbvWphHuTjCjrikWPYvP4cdKOUrm7FdV5O7bvXkZ7UhgGd3y81M0PHK7snJoeKPcvH04zijlsCk7EDZb+9t6HNKF3SfyGakjj/wBkt7kYprJtf7q0B7QjRSHbvz1p4Vg3/wBelkgCSZDfXFI6Av8AeNBXMxgXBO77uaGG6MbW/wCA4zipEi3DPcfrTTu+95f3OBU8ppzDfIz+HTjpTWO1sbcnvUqZfOQef0oxt64qHHUNbbkW3aM52+3rTCzOPl3fnU5TcVI5b2oZP+AjuPWlyhfoQ9BQkTRrj0p/lgH71MYbPm/r1pOIX6DHTYwyfxpdh9d1P8rkfxZ9DSmILu+U/gaW5p2IWBIxt68UmNmflx+NSrH5QPzdf0oaNUX7u7bzQVqQsN2Bt3cdab5W9iwVo2Xjg9amRdzHaMexpyRHbg/XNTIzKxikg53fKTyT1pZFCxqBu65yamEPmNuOPl5oMWMscMTRE0IW6jCLTlX/AGArU533cDHtQI1Em1u4xSluHNYMbd3+12qOPc/3ePWpAN3PcULHzjp7+tIOa4wx/uWHHX86Qgbh93gdR2p0r7f4aake/v8AQEcGhrS5UrDhhV7f/FVHyTx+7TP8PenkZP8ADnpgUnLA9vm7iszSEkthrbW+78o9KAmwZ/h9KdMuzC8flQVA+U4NTyj5mRh1Zf7oz69abngbOP8AZzUhUZ4Xt97HShU2v13fXtRIW5FmRTlfmIPIHalDlvmk3YXsKcy7Fbpu70MWkRQ386ySvdIuG+p3nhSx8O2vh611TWNAhuLKWQwB5NQZQmACWMcaknJJ7iu00T7L4l0mRtF8H2m60BdZ4dNdSgxwVM8rKV7coeK8u8GeLYPC5kiubKS+spnDvEH2u2Oqq2Dtz3r6A07/AIKIQ+FTZDS/CMlxHDAYri3v78PFMMY/dlFBHOOpya/KPEDJc5xNGUsoTc2tE5afcfpPC+aZdRivrskvldnmmt6t4t8I+JtPh1K80XSVkVmt7X7BG0UKdyxhUYZuMn6V2Hgv9tS++Ht4ttqy2virQoyf9Ha7lVYCO9vv3bMeoAqtqf7X/hvxXJOt98NdHgW4yvnteSzeUTk4EY2gj6k1ieGvHngXxPB9n1Dw/o9ncwszsYrEItxGD8qlnckHHYCv5XzLwY4pxNGVXMqEZ21spL8Nj9Nw/HGVRap4ao7dLo9u8WePvg7+2npFj9s1BvCnjCQbTJd2BmbGMKDcI4dh05cnJ7VyviX/AIJyX+jaHJqFtf2Os6dwsV7pmoLuJ68wSKN3/fwfQ1337PXwy+D3xKa3uILz7HcRcPZro7XMu7HXHC5HqxwMZPFetD4P+EvDWuW9rb6xbtps82LVLqCOz8x8Hh0RyFOMnI9K/NsJxxxTwLSnQwsqipxf8OWqj/heuh7lTh3LM5kq1S3NLqra+p8H6j+zT4gtJrmO3j+0fZxuZgCswHow4Uf8BJrBj8EXWlXKR6hayRNjf8/zjaeRzX6Jap8PNQ8NayY49SjZbhfMWe18uZQmcBMtn8vauU+KPgjwpremra+JtQm8leSFEVuzD/eVc+3Xt0r7HIfpjYlTjSzPDc6/urX7j5bMvCvDxbeHlZ9nsfDlr4VjjuvMgbbjJGDkGtzwz4B1LxJeRrGVZXbH+6K+1vC/7IHwQm8Bw+LvHfiiXwT4cvLlLK0eW6CNdTNkJHCMfOT1J9FJrlfiR4Y+EX7LnxotfCHiCXxB4bj8QKk3hy/1a8V9N1yI90uEX924OMq3Tcp71+3Zb9JbI8bSVRUasXq0uW707eh87Hw7xtPXmio97nA+HPAdv4S06MGNGmgGW46n8jXn3xX8ZahBq26OSO2VsgBAXP8AMY/KvrbxF+wz4l1B/wC0NA1y4urKZRLFpd7CJWbIzhLhOGTGCNwyQepryrxz+wt4t8T3CzaetnqBkyoTd5UiNno2ementXs5T43cJY9qNXEezfaV07mGK4TzChH3YKXpqfMUXgbUPFGharq013qmqadpSg3Uf2sQwhXYBT5Xy78H61g3nh3xBq6+dpqvcLGoT/Tdka7AOMbWzt9O+K9P+I/7O/jH4Q38lnrul6xpPnDzI9lq0iyKP9pcqQfU9MV5v4k8KCSRPtVxdWIwQwnumkY9wTGvtjvX1bllmYx9vg5RqSe0otXt57nFTliKHuVrx7p/octr/h/Vkg8waZ4EhuCd0zpf3MLu3Tkqy/zopJvhV4Ts4Hn/ALH1LWrmRgTcXjmGIZ/u7iBiiub+x6j1ly3+/wDQv6zh/P8AH/M9QMSiQsSGU9KbHFGpIY+30q0bfbJ8u0+vNRmHb2AGeDX9En4PJu5C9v5bZUbselNkh53dKsrC5kb9KRbchdp3E9MEdKA5ivHAu5/m7U1toz86/nVoQsqHoC3GKa1gVj+6OapRHKTsVWtxgdvrTmTaqj8qsC12RLtj59Sc4pzrJ91nVhjkL1FPbYhRuU5Ig8fz9N3+FKYlP3XX8qt/Ztsfyr8vXJ7Vb0zw/NqFxGq7vn9EpSlZXZapt7CeEtDTW9fjtZeA5xnseK76y/ZyurnVFEFrNNb/AHsKapeGvh9NYahHN5nzKwIFfQ3wx8TTWtzFDcxxtHtA3EY/WvDzDGShrA9jB4WEtJnmngL9lm0vdZJ1TT2WBWyAXKsP8a1/i9+y1pem6LcXVjp8+3GYzDyw9OBX0kNKhvrMSW7RyMw4Afk1e07QECeTIke6QfMhYtj1zXzcs6rRnzS2PeWU0XCy3PzS17w3caDdGK5ikVWPysRgn2qh5QdPm3NzgDvivt743/AXTdSsrib7EskyfOmDuzmvkTx34U/4RvXmhjxt6kf3D3H8q+sy3NIYmNup81mGXyoO5zOxX5O5CvGDQiL5P3j+Aq3IuDyo+Y9RTe2MNk+or1uW55cZa2KwEY+6zN7daNoJ5wuP7wxViOAfMrZHfIIxQUCEHaZM8ZNDiProUwpY+zcUMrfdG7K8+xq5LAzkZX2ABwKRoPlPHPbJ6U7WROqKnllh93v3o2MnHl/jVgQKYmXbz6ZoMHlAEqp9COxpA20V8ZPb+dNPyHHOKtCNk/hzu5+lN+y5PzFeOwoCM+5XeMryPm444pFTI/hZu5FWTD8mVyo9+tEcCh8A4RRyfU0w0bKhRvp7g0hiyfvbvUe1WPKzNkrsVe4700x7d6sw+bocUD5kV3Xam1hx707yd8fyfe6kmrPlKsWFw9MNu7lTxx2HSkPmXQrKnmYZPl9cjrSOoCkKrfl0qy0LA5JB/wB3mgRfUfWgOYqG3dyMn6fWmtHnPHzL37VZkj+Zd27r2pZIhJJ5bhkDDIOMZoCRTK+aN2R8tEqZUc7vpVpYPLVlj27e+6l+X+6PyqgjZoqeT+8/iHGaFQrD1LDPpzVgREtujXLe/SmRQna3mcMf4VqSlYikjAbawYLjhvejZ8nCn/ePephBuC5ye4LdqJAy9Mt6kjAFPUOdbEAg3gHbjHqOtMRBlu49TVphhMjbn3FGN/8AdX8aNQKpgwF4zn1p0iYOdp9MYqZwUXA/A44pp2sMMmW+lLUL2ISu37yt8xwO1NkRt3AXHvVry+dyqCDTfLWT727cO1GpXM+hUkDY+ZgtIiArjd+tWmiWXkqy+2P6UojKjp9MEVMg5mVCGx8vPHY09IWP1x0NTujJ/CCc9u1E0ZQhlAb+lTy3NOa+5XWDe+W69gKQwpH97O73FTFBnO1ffB6UrReeOuR6YoDQqsijp80h/u9qj8ravPzMTyPSrX2fYP8AZ7cc0L945Cj0oDm1K0sRx8uMZ4+alMDMu7O31qxGmfuhc98iofLEb553H+8OKCnLUYFw/wB7C0gj+bO7PoKteUXb7q5xzzUePm+by8fXmgfMiHyeP4tuPSmvDkKqkc+3NTCHfyo+VuwNO8nefm/h71mVzdiuIdrfMxx0oeFQ+3d97rUwh3H5j09ab5QUbSelA+YiAwfly3Y8USW/mD5frU5jDlup9sUxIMfw+x+bpS1KjLuVgnmD7uJFPQ8ZpW2udrxtVsIuG4245Ix1qFYd0m3jd1PHak0w5kQ7GO7C8Dp70bQSBtXj36VYEangRkepzQIFX5ei9qh9io2ZBKjKchBg8ZpAqqfm+XbVqSPjao+760zySA3A55pco46EAAkRvl27aGjYQjnvx7VMoweq/SmMMN8vJ6e1Kw+ZEXktjO0Y9c1GoAdhz9DVoxnYfm7dPemxw7EUHnB9KfKV5kahmG77uR0FRxwtkc/nU/lKydF6/nTZrdUG7AP0NSHMQeVkfj1GOKG+Yt8w+Xv3qVosJ/qyO4KmkZMxK3z+Y3BH+NK1w5tSJFPYLnuc08RgsO/9Kd5aghVHy+velMTRzdwMd+9K1h8xE65D/KTz6UMnlbcA9McipEjbsfm96V4sj5tzN7DNSXzK2pEyFj92oyuP4GqUxgkH5uvpSPtQfe/M0AppbEXl74w21vfnpS/x44xjqKdFGqKuc/Nzk9KDGzSFm6YxhazNOa43arKPm5Pamg7pNu36VIE2DDfMO2O1Cbc/d+hPOTQHNYilU7wf4e9DRRsv+6amMPmKx+VfY0MFSLp+dZFRkupA8fzncdvPXHWnhGaTGzAz19aQx717sGOaV15UMzdeQKmXUuLvoixo1/Nomox3VuYmmt2DJ5kQkUn0ZSMVsweN9a1DU76S1lhW4vxtlEUMSDHsDwtc+o3yfKuPcjrT8MME5+o7VzYjCwqrlmrnXh8TOkvcOr8Pa5r9lfCL+0JokclNhuvKGR0yqtuYfhhunOa7b4a/FXxd4V1Mq39jzWMcvKXamO1Y9gZW+ZfqDXkNs4t5Q21ZDnhgxGD2PPp1p/2yaZWWRjM2cspdirfh/Wvg+IuBsNmVN0pWSf8AdX5n1OUcUSws92/vP0N8AfEq4+Ptlp+n6auq+KfHV5G0VtofhaFbLw9pqLjEtxdPsZiTnJLHO04rP+Knw58O+BtGt7jx9418MWurgu1za2l7G1vujch0swx3zbSpBcjG4NzivjvRfH2pp4Gt9H/taO106CUmO2tlSCQkgEvJ5aZkx0UFgetZOveKrOOFprx7m7kt4tiSyQi5ljQDiPy/myv5YHWv5h4k8A8vwuJWJp2jFPXS8n62P1fL+NJV6VmnJ+Zyv7aP7X+g/tD+NIbyGHXNT0XSYTZ6PaXG6GxtYwMCWMEg+YSFJYjPvXafEz/gpZF8X/gnofhnxd4Kvtb0z/hH10u5efSTKLO6iZytxbyuMLuVolZlPIjGegrzXxZrdqt7C1joNzfTbQY7mU+ZBbFhkqN2dgHfYMD1rN8S22o+LNPh2eJbfVFjGx7dLu3s/s5/ubfLaRx7hgRisXwzRXs6dOOkdrRat5/M3p5rOMnKWz7sz/hh/wAFJv2i/hD4e0e18P8AxCvNJsdBjNvYw3Qje1ihJJMRyCWQEnAOQucDFfoJ+yH/AMFn9B+N3geWD4qXmk+G/Hdki7tV0u2f+z9RUD/XOACFk9QAAea/MrWbW38JSst9qVnZyQ/MwtdPe+cA/wAXmXPA/wCArjiuP1S5truQ3eoTeJL6yVzn7RfRWSzeyrtO0+1eHxPwFluYYb2VaKjLvFWkvX1OzB5tV0kldeZ+0tz/AMFY/COny3mgeIr6OG602VY9Ut5IhLDLaygiK/sm53Q7gFkVf7ynbwSN8fsh+Bf2kNCtvEXh14dQ+3KZCNLukjjvxk/vI3JHIGBgkMD/AA4xX4W2t1Y3mtWzxSXVnBEAUW2kMkkCj+BZpC7Dr1Cgc8dK+w/2Pv23tW+Bfh67h0ebw/p2rEeZJo/i13uNF8SQLnbMNjI9tfR8r5qDZIvl7gCpz8bLgbMMoSrcNYidOaXd2/p/P9T1J4rD4l8mKhFr8T3D9r39gi+8EA614Ij1fxNosM3k6lFqaNcanp0xONogxll3cFse9FdDoP8AwVM8C/tN3uk6i+va/wDDfX4bHyJpbeeC61YFfvKySskF5HwVDy7JVGGBYAAle1h/FzjDA01hcVFOcdG3GTv53SaPErcI4KpPnhovU8q4Vl3febqKbJGoOAu7npVryGaRG6fU0pgZhkkFl7V/pzGJ/IkqiZSW23M3G3noKj8pgflX5e+auCAkk7fmz60SRhI/3i/kaqwimbdQ33TuHUGpFAPHy/lVjyPl3EfLjjFIY2X0x6UcoOViBU/e7WYFfSpxaggeWoXJxk+lMlhIjXsvGT3qxbgM25cbenWlyhGRYg0lfJZd+49a2PD58lo41X5umTVPR7dVkbzFWRWHGDyK0DDHYoJV8zK8j2rkqXbsd1FpK51UMa6c8ZJzu5Oe1b9j8RVto44lRpBn+GuW0HVl1O2bz4tyqOo606K7XTjut1jC+h615kqaldNHdTqNao918IfE2PSlt5JG+XbwCMV39j8YLfz4DIqq0o5PpmvlnTvFMl1ufq3QegrorfxzO7LBLt3oPkZR9z615FfKoyZ6lHMJQ3PavHvxRtbHTn3IzbzgcZGK+NPi/qa6l42vHi2+VIc49K9SuviG95HJHcPxGcEnnd9K4j4g+FLG6k+2W7NFJIM89BXp5XhY4d+8efmVaVZXPNza/wB1uV6g05UG3IG1j696tPahZ5FwWYYyR3prWuIfm6KfSvpo7aHzfKyoYcOBtXmkktGLLt2hl9DVzydqhvlYY6U1YhKflUA0tQ94qzBT6nb7dabsUSDhulWpom3HPPHGO1N27WHzEnH51fQXtHsUwrK+O7HOKkkUGH7v8QHSrCwqWO5ju9+1NwHI4+6cfWiw9SuQNnzfTgUzy181ue3U1acKQPvde1IVBkbgn61KRPvFYqoP8XSlKk7dyjp1qw8e+MLgbu+O1Dptb7yn61QalNwueclc8DFDoDtZl71YlhxFnK/hSqiqq/N26HuaCisoDL936U0w5PzfpVvDY4RfWkSDLHPy1KQnfoVfs7KBuy2e1H2fd1jYfjVpY2YFt34dqEgUpnpk80cpauyosKtJjv34phi+fpubOADV/wAhlXd8pX1IqIRsV67cnjjrRylSk9im0XlnKruduoqNY/3js3UdBV4weX8wbJ+tQzRbm/3vUU+UnmIBDs6t97kD0pG5dV+8c4NWDAXYAc+uBTRb+Wx6qfSixPMVyzAMNv3enFHkN5nfpVopmT+ee1NZG29vSlZilJ3uVSh8tfvfXFCptY8L61YMOI1579jTXi2lvp6UWZomRNFlC2OVPT1pPKdDuVcqe2KmUfvOrcdOKf5XfLev1osx9Cu0O75gSvrxTEBDjjP+13qxt8w/d27f1oaHd0X9amxSl0IDEy8Zb5u9RJFsmOT5mauPH936cc03y1jbng9sUuUNSAw4LbfvHhvpSCNV6bgvQVNIm4/e5zg89abIhVsfd+tMqzKrpsf5efUCnD5x83zegFSpEqj+6M014R5a7mbk54FDjdE3ZGyqSSysoFJhWH3uP1qZkVTtyW3dAKa0asp3fLj3o5SuZ9CHywgYg5PUA01UHfGc8YqYosa/L0PfNCphSq/eb17UuUIq+rIXhaPAP8XrSogiB3KN3tT5FwRyXPfHaiUl2yF+U0uUpOxC/KjBAGR+NOdPm+nf1p0Yyu0D5evvUmNw/SjlHZsgYCbn14qNotyhR268VYaHp/Dt5oyFbdz/AI1JXKyFAqnGOnemybVVv4fTAqVky2V4zSgbjt4PalyjjLoQLEXK/O3IzyKdjJzwueN1SIm4spRty9MGpkhAGNu361L0NrXRVFqV+bPSnCPJXpU7IyduPY0sce/+9mplsOJXuIShHufTrUJh+9161oG3Kgbs/jTGt2JP14qOpZUSFiM5WgwEf3cfSrJZh0Xp15pnllm5X8CaGtQjYqoQGoETMzH+Y6VYWAf7K+xoWFsYx8q9vWgpakIhb7w2sPYVGbdd6/eHPSrxjOzzOi+3aozDvO/r/d9aT2FrsU2hxKcZx0HHSm/eO2rjIQdvHPaoZIyD7mlEexXAEfy7dretLF+6J3MWJqfyyT/q8t601oGdl3MP92lLcF3I9u0lsf8A1qj+brkqOuT0NSfZyjsDwDzinMu47fuqvU+9IorqJANuRu64okZ0PK5/CpAjKd2fmzxilZOf3jsT6iokCZFjj+FW7k96jGWl2Y+WpntvN3DdkJ1JoQBZfT5c4zUNDTIZBj5R1/pR9lMa8N+PpUiIsrdyxpZoTGeMtnjFHKacy6kQ++Pmb8utDS7eCGf8Km8vdIT93HT3qPZtbAYepFTy2LjJDRHycfjxTVQg/Ljp3qZY8su0beOp70CNtrcZwe1Q9yla9yHypGb+EY9RTlj3n7yj2FTCIEL8vX1NNkt9rcKN3oKyZStcjS2Vh15HrzTkidCCx6H61IsOf4VbPc9Kc8R8r+H14pG0ZF6xnjlj3STOsi9FC8n168dh3okeP7SjP5ztLlmUqJP1JwPwqjGu1eVG36VPaSqLpVkLCE4BWP7zD2Jr5vN8kp4qPNJ2PoMtzaVG1Pl/EgvJrdYpBdW959mVXcsyiYsAOFC54BOOa4+WddctPO0rQdTvJo2YzG8uVtrEDjGwHOR6/Su/W1tZ74LOtzFZpkA4DSH6dq5rxLpk14GljnktYYydj3ZG0emVXg9TX41mmS0sPi5RcpT8o9Pn/kfdYbHznFezSXm/8jzvxhYXU90l1eR2txqONtpb2Z2WYfsCMYYDjLdua85+KHgV9S1NM6tZXGqOiyTqGWKzs/lztDN95h7V6hr32y4u7mG31PbFCu25uXjG1MjO1FAySfbFU5Phhbfb7E6g9lpq+YqRPew/aJZX9kGQPqxr5eWBli6slhqV10u9/T/gnuU8V7GP76d+uisee6R4t0rwBY2txa6KLi8AMRmuW3xTEfxIMYIH17isu98I6p8TZrnULpQsLsPMMkixRRN1C5cgDII6ZwK9Y+MWqWXw41m2htNM0+O8SM7ri6BuGgTjMqxn5UZuB/wGvI9bkvvHGtfbFkU/b5Mx3FwMTMRhflUDgHbwPauDFYenRkqLfNLqlol8zuwuKdWPPHRee5i6j4MtdFQ+TfXFxcW2N/8AZ8JkaHd2aVsA9e3FFdB4yt9N+GF1FayNefbto+0pJiRicd0+6vt1oqKmHgpWm1f0udyqt6pM/QxovnVipIPbHSgQ7S2FYfWrgVlKthuf0oMYYlvm3e/ev7lP5ElYo+WWbpkeoo8rHp/wIHmrIjxLhjjd07UNEyvIu3dgcUhFYxRt8oLbuuB2pog3dBsYdCRVjy8ncsbZ9fSnPbKw+63NAnKxTaJdvzfeHU4oMBjGOV+lWgrR/Lt3Y4HFEVsAxXPzCgiUr7BYHy5gyyHJ4AxW7d2MlzZj95t4796xIt0Xzbl68YFXU1CWS2+bH0NYTpN6nRSq9Geg/Drw+l5aKsm1UbjJ6Gm+OdCt9JcrBCzHsw6Guf8ACvjH7JAsckmyNiO+MV3Ru7XXdMWNZVk3c9a8qpCcZXPUp1YyjaJyenXtvbQhfL292OO9Ou9ZjeQxp8gPG7ua2L/wOLOD9yrZYZPeubOmTQGSRl8xlzx6VcOWWrIlKSK948MPy4aRpDgc9Kc2ny3Uciu3nKqDA9OtQ6fDNqOqInCRnOWxyK2LK0uNHuWjX94sh6kZrSTjEUU5HAP4cuWD7I+nBJIrOaPGVZdrJx3O6vZE8J7RN50e4zKeCOBmsWH4SC4vFfeyr3Vcc1vTxkEtTnqYF3vE8+tdFvJ2/dQSMrDOStQz2skMvlupjcdsYzX0HofgG3W1VZJsBVwA3FcP8Y/CP9m+VNHbyOzcFlGamnmEXLlCeDcKd0eYSRsnVd2euOtNEBUldqtt6ZPJq21v85UEnk5GO9N8j5egz616kZKx52q3KZt/NA3KOvGO1CRKhbgNj3q0yCPJ3Dd6moSnlOAyqVYdaBcyIVTcn3R17NQ8W1/lVG/GrK2m9cr69c0rRMozuGPpQHMyksY3n5Rn0HNC2zsT8q/jV0EbcNu+oGKjkg2HK7mcdAO9AczKhUAkEbT67TQsRfhmXj2xVs24CbtrLnrk0jQL5W7pt5zQLmKrRbPl+97ZpRbfvC24cDpU/wBmULu3fNSpDGeRlz3J7UDVQpmJpZNxX5eg54p0kO0H+83JG6rUkDLHkj5fYdadtXqFy3pjNBSlrcqeUzR88f8AAqY8OFCkc+uc4q+0fmLkjb7CovL+VmPyKGxzzQO5VksyArBVVR15+9UTxlfvbW/u8itBkJTb8vPSmGJY5FXyxuPt0qeYgovBjovzdfvVFNBvZQu3d3DZrRECqWUfpTGh/hwue2aoooSw/P6H1zTZYeV+bdntVrZJHu3KWx+tIke1923a3pjNAvUpuAc/e+XpS/ZwBuL/AEq0scj5xt60hCxN8u5vwoFzFZYuB8/PpjtRNDhud3sf6VaaNQPl3Z6nHemrHuPzfL2wT1oKT0KZgLD9OuKeECty3ap8c7nUsAfTpTcqVb5cY55oFG99SNkUquD0qOWLleDu/lUzvw3yr2xThHlMt8wHTmlymkpOxVkgBfjqp5FAikZgWXp7ippMBOOGpH+QqNzc+ho5RRk7EAhZu20delDR5jxu/wDHamAG4fM2D70SJ8+1f4vWn0BXKwTy3Xoy+vpTHjDMwbk544q0UWMqMbm781G25lJC7cHHTpUpGnOiAqrBf3e5QMYBpGh8v5sc9KnPydxuPJ+tISGP3hj39aLC9p2Kxh3ncG2le1K+4j7w2jrgVMI2MmMqV9Kc0JDfKNo70hxl3Ksi7dq/d/4D1oaPB2hfl+tTCOQSru6CmiFWbbz1/KkHtGiMcH5o/u8Z3CiNV+8F4PH0qQoIt2ST6UpiHf5WwOnNOyKhPuRGJd/bpmmpb7t2PT16VYjt94+XPqc96Plz8y+wxUSWuhfMmVhGVRP72fXmrAjBdvn+UD+IHrT444zCV2/P/DTpYGCj5frmoauaxvYhRD/e3c+lOaPJ/ut3OOtWBAxXrgY69KaibW/vfWo5WzSJEuAfm+99OtMkTcf7q/TNWGhWJvXce3amybi3y/L65pcoSn0K0nKen4U1UDD5gzfSrTW/G4+vGKRoWcfewPcUwjJlQxgSdG3Z9KVjtm2tzxzx1q1bxs5ZWP3eh6UKchgyjdWZpHUqqm+PaOvvQY9hUbR6ZzUhiLEj7oU5XHenRwgfeb7xz9KClch2fvPugbehphj8xhjJzxVs2/zkq33f1NMNtlV52sp5oG1cplsbspjHB5phh8wfKwVl681c8sb2zJ9ajltkQMT97rnPWpkTZ9yqiYbbjn1JqLyMGTcG57YzVspGFVgGzjk4odFAGH+ZvTtU6j1KO1Q/HH+fSm4xEejc9atGDK5K/iaYsK+UW7bs9aOVdSbyICqhAA33uvB5olIWZdqqeMdP61aYqQw7ds1Ew2x7uCvp60WK1W5EY1+8uFPQjGM0eXuOepHbNSeSrMrbTyOlDoA3+rY/Q1mPchEXl/Njluoz0pGhy3p/SrKpgfdP0JpqRK43NxSlsXGVmQlNgXY3TjmnL++9SMZIHepPs6+Z1+8M0EJHCxUnd1xWXU19rFEBVX/2fTNK4ZT1Xp1qZIcrG3bB49KTYyRHhSemT6VNh819UQIPLj5Vee4NOG3I5O31z0qTcUC7ufpTgSZG+8V7cColE2jLuRj5R8rbvr3qUXG9MiGNWUcH1pDwQvQe4xQyeYwBxt9qylHmVnsaRqOO240STXEXlh2U9QRyFqjLaS31w25VWRQB5wUuw/3VPH51qKVjTA+XFN3fP91f948Y/SvFzDJ6eIg0vmexl+bTofFrcx18IWOmWN1dyXWn2P2faytdRuzOT1EeVwzd8kYycA4Fcv4u1jVNHitX0m0tNGj1h/LgMoWXVb/LYysZB2Z7HAHvXoSxpLcfaLloljhXEUzbfkP+zxxXC6tba5qOpyyafbWen28ybJryQhpZl7gbuSfQj0r8tzjKqmGk6WG0T6Qve3qfa4HFQqJVKvTq9vuOI8R6Zpui3Vx/azQ6pfRSLva6bz1hfrt4IaeYdSvESDOSSQKiXw5rXi6D7dZXUHh+xnba+q3UapJcEcBItpG7AxhYwFHTLEE13uifDO18NRrfak/9q3qt5dtFOABGp5ztGOBjJUYHfrVAxap8T/FUxsb6ay0uzTyptUSMEsR96OFW+UIvquSM9TXh0eHamH1xEdXtFb27ykejHN4z1p7Ldvb5I5DT/h/oeg6wtjZ2+ra1rdwu+QWqRy6rc8ZMmHGy2XHOwgvjgkHIoq7/AGXbPrM2h6JrWqaf4fjYvfanE37+9m6g5ONw3dyTnqMUVm5U4vl5H8lG34nZ7Zy95u/rf9D7QEThNqq3Tim+TsTBDZb9KuMPm+neowAMlgfav6uTZ/NOy1K7WzO8eSvyjg+lJNFtl+6QW4PpirUaMRlYyytzSNC3eP269aozd76FUwZHBPvzSPFlfvD8RWnDAWj/AII89PU1GdLuJ4iscTFc/eAzScktzRwclZFAQLHLubcfXArqdH+HKa/Zh/O+ztjqR1qvYaM1ptdtrZxkMK7DStRENysLDKEcAdK5MRWlFXgdWHoRWkzitT8BXOmS+TLHJIp+7Ig+U/WoLfwdIUbG4uOwWvcdPis7mw8qbY2726VPpPhe1tLr5UjZvvBhXn/2lUjo0d39nwlrc8Av9KNlKI5I/m5ABHSrenXTaWkarIVJOfpXsXxD8GW9xa/ao44SpHzHpivIbvS2N1Ig2nbznNddHEKstTlrU/YPQ6K18QzSlWVpPQktwakgSO5nkdg3mZ5wePyrlrS5YWrQq/7yNuhNamjRzXkwZVZsnGQ1KeH5dio11KyZ3eg6dYx7ZDHHI3fAxW9fDT5I12LHCx7BcmuFNtc6cmS/XoR/Kt/QYnu4kkxlicfMcV5tak73bPQhUi1ZI39OWaV1jWHzg3GWSpPEHgiNbf7RbM0MyjJU1Y0XW7nTZdkkbbS2BwP0rW8W263lurxZ+YZJz7Vw88lOx2cqcdDyu7vZr12jkkeOaI8EHrRq8lzfaXGszZ28Bh6Crt74fuVupJJY22t0YelJDbqYmh5PHc8V6FO10zhqXSaPHfEWmRwazNtkbb19KzDagdN3PIyetdF4xt/M1Bo9vKE9utZAt2xkYOMcYr6KjrG58/WaUinLCdo+Vee9H2Xz8bsNt7VcW1Bb7vB9aaLcIeFUe+K0M7q2pVW2G/G78M4pJIvL+Zug7Zq3JAByMK3r601YgDkKxPUignm7FWQblXHRugFMSLEjBl3MowDnpV9oSCcqv5dKj+z7fvbefSgNyqbdtvGPoaa8LBdny/hVt7dmXb09MCkFvhPn+93OKBIqiPKYHDe4psUSqN2Nqe3rVsWyFuv6UoCnj+6OQRQXdFMR7iVYc5znPanRIGYsu0/h0qxDGM56e5702OEcr39u4oDzIRF5aluPm701ouD827dyBVryFfj72O3pSfZ2A/1YP09KCpS0Kyhm5b5dp4+lNdTg87vTirotfMXnCfWla3C/MV59Km6HHRaFGOzzE3zYOefaoJbcBVz8xxgGtGSErkheO+e9RyrlTxtX3HSqGUZYFMe1Ukxnrmmtb7TkKx479q0IbXIX73ryaYYvnb71AGcLbYp2ocntng0JH8vzD8PWrzxfJ939KjSFQhyeehznNBNmVFh8pWba2c4FRknb8y/N0GauvH5fbcrdD6UkkO4xr/EOpHYUAVI4WxjH1yajeBix9+1XI7dhK38XJwx700pzjgn3FAPXYqG24b5fvVHJbYwNvHbFW5o8fxLt7nBong3suGz34Bqt9x82hVNvsQDbRJDtK/KvGepqwyh9pyC1PeFQmcE+tSESkIunC46ZHaiW0XruBbFWhGsQ246880wQBFOT8386C76lQlljz8uVPXHNAViHHy9c1blg2Ku7IDe9MWBR/ED9F60A1YqhNz/w+2KjCkllXa2D6VcFsrqcL8ynPAppTcCqRsrH2oJZTELRt8y/lTmdvX5TzzViWAjaNrbu/PWnSRFx04/u96ATe5RkjBYc/kKcUwB7+1WjBkfdYf7NEULN+HqKA1KphLDB3flTPKODj5t3UkVbcB5gGJC9KVEyzblP1HcUpGhVVSqKudvce9SsoaPlduOhqTbh/lG76jpQsYR+v1qeUuLK6Px33dSaezZB+U/L1OakMbbW2mPHSlKDLAY56jH8qXKjSMnYj8r5P9nvTfIwG6+1TFCwC7lXnjNP8pQTuUtx1qZFczRWihYJ83BbgUx4W2kH5tvUCrSr5gDdFzxx0pWjWR9zEL+lSyt9Sr5BMq4445FOVcp/jVmSJn5Rl49+tIEbKqGX5Tz61mMqshwV3ZVaURrIR/OrGd8u3dGPXimhMN/e9wOlTylKRWMfzHOWFIYg+3ttOelTrGpZu/PY05ueDwvrik0aKXmV2jCNg/pUclqxDYP61ZaVd34Yxjk1HLHuHDMvc+9Iq5GYVYbSPm71DNbbYPlx1781buJh/D94dTTXPyjcOMUBzIoSK8jY5+o6CgxjcPXPJxVto1lj27tm7r71CAvAbb8nT3oArPDlPvbuetRyrlPlxt71ZkK7e4OcgGo0by1bf8u77uaVrkSIzbqw+ZTTRGqqy/Nt9xUx+W1VdzbvqOaFVlXpub3NTyl8y6lcA7G+ZVUdqaIg6ZVmf6dqslWA3MV29DTdhLfuxlRznpU6FSkrWRB5bInbDdBmlWPDfMPlx92pQu9mUp8qjjJoXt/ePQ4qZagtNyPyWY/KQvpmgwkZ+6wbrx0qVlYJ83PPG0Uu0IeM+/FZWLVmQsNpXsKjYq2A345FWHkWQcqQc46UBF27trN7Yo5e5pHYhihV5O2O1SPDlcfrQyZUny2Ud8CnRgiPcFbHuKzlpsaR13IjBu/2mHrSLZbST+fNTSfvdpYFtvUgdKdv3dDxng4rM15o9CDJVW9O2afJFv2kRt65qQxsI+dvXpT0BPO19qjnFTJGlPRFCXToZpPMkVpGU5G8ZA/ClmWHT1+0TbVyejNt3+w9c+nfpV1BuPyx43dCT0pHtVuyp2LJs5ye30rhqYe2tNanZTr6rnZzeoaPN4ldzdStaaeqkzqDh516hB/dXgEgcnFZPijQr7xqkNrCtva6VaqBFbufLjjTu7jsD/CPrXaXVi2oHa21Y1IcZH3yO+P5msjWtN/trUGtfsbXduRve3LbBI/QFj3RQAQPc18Vm2RuceV7N/Nv/I+mwOYJO60/Jf8ABOFu9M029S2sxpdxqOiquIbSJij6kyjBmkb+GPjKj2Wiuo8WeELrXNF/suzZHvbgh7ydWADsvPYcKMbQo4GBRXxmMwuIo1XTp0rpdkfSYXEU501Ju3zPqMQqw+8QvYkdaaIwm8su5QO461p3WmXNsmZoWjXtuGKqsnyqpHev6UjaSvE/n+UWtGU2gZfpjIwM04RMf7wz6gVYKkAD7xHpQ8flkA9a0MJXIzAsQG4eZ+FWNO1ZrFjsV/oRxURXah+b5j2FL5e1M/1qZRT3LhUcS/Nfyazbsqsitj7vcVDHPNBKq7mL9AR2qC0Q2rK+GbcKsRq32vzMfr0rGUOh0xrXOgstanjtArNz6txWxo3i+S3RQzblUdz1rk5rjdIOmMDrzUxuZDF8vIPauOWHT6HVHEuJ1GseNo5rZovLDh8g81wupRutzuhWNY26c80G7JuW+9x2NQ3EbTscNgDt1rbD4bkdzmrYhz0ZRngJumLKN2MZz1q5pVtcEIseVXOe3Pt1qN4N64Zh05NWLKNYpEKnbsbqa6qlmjCnKzOisLppXWKf5BGc47ZrqrSKGaBWSRhtHRTXK28cUhVjIGbOcetdp4b0f+0YVMborN8tePiNNz1sPK+xnyaptk/fFwqvw+TyKu2+szXZY28wx6Oc1uRfD7zreRJ+doLAj865qDQ1tL5ljZmAPTFcfNCSOy04s3pbTy7SNrxWjaZeHHOPwrBvvLsvl8zK93IwQK7KGZb+ARmNf3aYAJ5BrmdctLeF2W6basnHA6UqT10FUldHl/jDSN90Zrf5lU7T7/Sua8gqzZ/1nTBwMV6D4nsIbSYrGzsrcqVHSuP1Wx2XokVc8YPavo8PLSx89i4e8Zog3D+KkZMfw4q2Y+23mmtDkdj9K6jk53s0UzFt5xx7UiWoL/MT6irflkNzQIzIxz91elA720RVaPAx90Dpmo2hUH39+9XvL83O8cjkf0piW4d93VloFzNMrsuRj5h9RTVjyp+c8eoq6w/2cn2FN8ogsMAZoK+1Yot5nb5vpRJHuRfLbJH3uKuNafu8n8cU1bdfLC/dDUBLcpvD5ke4svXt3qTyCJTjK45zjrU5tIyv3fwpxhLEDblaCkio8Xnncu5VHBGMZpvk7ipXcuD0q4sDCTG3GO2ad5POcAHvQOxU+zE9VZvrTTEztjaRjuavmAkfexUckZPy5689KzHe2xTeFsL39Qe1AtwfvfMpHSrSRZbJ/Whs9sfjVcxRRaLaN2eVOBTUhVhz97vj0q88TIPm2nnI471Gq7T2B78VSAotBufPzEnpTZICzlf1xV4Qs3O7pTXjwWb8PpQD8jPeHL/xHB7jg1GYPNkLDA2+vSrxjO77zdccCo5If9o4oIv0ZRKbgxVCv0NDW2+L7oJ7mrCwYPynr2NE0bI3bkflQTH1KjWzIOFUeijvSAbzzv3Y5Bq00JjX0z/FTWjZl27d/v3p2Y+axUNjtX5QM9xnNIIST823HTrVvyCgxlvypskOE+ULuHrRZhzXKxiYzYjHygcHHeneVJIMsee2BUqowXdubceMelOwxJ5bb6YpBqVJISzKBtDLyc0LEzMfvbhVlE3jd95hxSJkZLcknjFBoUhalnYBsK3J55pzWuR3YYweastCyfNjqPTrTXjIYfeBNAFZLVo920L9SelI0BWNm/M/4VakjOz5TtHv3oBLhsEKCKAKZt9yq+WzjrTfs2BhlUbhwc1cVfMiKkdO5qMwNKm0tuVenNAFXyiY/L39elGzyXwuF7HnpVs2+SrY2t05pWhWFPurljigcSmInkYncrDNNeMI3uOemRVxrXbJxj86a8bsT83X0oKRT8tmXAZvmPSleHy2+ZSOOvepXti5UBtxXHOelKP9HA3Dv09amRcbdSPyo2XA5+vWlS32jrtJ96kdWcY2jn0NOSPavrzU2uNNdCM4A+Vm44I9KGRivzdKkEflybe2OtNG7bilyF81iJoOPvFQfTtSMiH0XjuvJqUJ02/iaS4h8wfMxJ7cVHsx8xHjKj92ob19abIctyGVV4471IqbyvJ+Xv60FHZcbjjOcUezGqjZB9nXH3fm69aYFzIqr8nvU0o3upbG7PWkVCWPIIU9Klx6Bzu+oknOPuleh9T9KgZF8xurewFWf9YmABkGoeQDjJZeoxU8hr7RdCMqsI7t68U1B8u4gke4qQtg43N+VBDFCP1NHsxc5CIlLZPP1GailXa2dqjH6VOoKsevHX3qMQEPg525yaOUOYiZfMGWRWB6VDPGu5TtGR+IqyY8qzDcV7e1N8v93nbg+h70uUXNfchiXPLbSccADpTWX7S2fLyy9CeKmCNvB7AdKVl2k7c5HIwKgrmIA+RtPynPQLRKuxQG+YZ44wasCBpOVbtzimtbGR/m6CplFXsjRPsVpNsU3RcN6DmlaDytzE/TjpUzQr5uB8zHoKdsHmcndt6ipa6FcrZXUMV2q27d/FipJVYx/eanGDBb5fkb7vPSkSNQM7W9zmsy1oMWLHyr9TzTZQybRtye2TVjYqx/LuBPc0CLcA358VMjSJXlR93KlVYc/NninRRbvut937o7/jUgUxPtU5+ppBEBcM3XFZyNFLUZHHgtuLbm/hB60rWrFdowOfWpSuwb1+YNwfWlVQ4/ixioNoyRE8EhCnb04pX8xH27N3HY4FTbGCfL2/lUbL5km75jggCstOrNENTcSB8quvVQtJs8xl4VWz0zVjOwu38XU544FTavpVx4Y0m3v9Ss7y0sboM8U8kDbJQOu04wcV52OzLCYSPPiqsYrzZ1UMLXraUYuT8iu0PKltvX06e341GkKpJIVj2yZB+STn6Dqa5+1+K2n3lvdSabBc6m9mQZltxyw55x6DjJ7Vai+Il9o3hq1upJrfw7cXhZ4L2a2NxDICfu+YOMjA+nNfA5r4mZLhV7kuf8D6nAcJ4+slzLlX4mgzW9pK0lxJDC03A8whS465GME/kKKrT+N/iv4E8HjxFp2k2uuafHMR/amkLBqXysdoDwl1ZeTjgGivgq3i5NyvSpw5el27n1tPgP3FzTZ+gv7Vfw2ufDmnNtjSWBZA25E5C5rwiKJZ4ztxuXpmv0B+ON59j0SSa4toZLVhtbcgwAfb2r47+Mlxp2p6xD9itI4zCrBzGuNxOK/oDhzMp1aXLJH41nmXxpT5os8+khI4/pSunmNxt/xq4sTbvukdOM0xowx4Utz19K+sjJWPmJX2ZWNrkc7aa0HHUGrXlK5z824UBMPtb5W6inzCa0KbxAR/7PTrU1omI/lbtzkdakFsF6559ac0Y5bb07ilIUStE37xsdVpWlaGRTlvr61MbXcqsPlyeSOcU9LfYBuYbM916UaDu76la5QSSbiwHrVeSAA5G75q2hpccsu0YYH+Lp+lV7uyW3bbw23tijmtuNxe6KMKglt38IyadLEpI28nPPtVgW6mNmK/ePGKcLdFl3ZX0xnGKrlBaMIUbK7BllOea6DQ/F82mTbIuuckHsaxY5ZEG1R8vtToA288iP6965alFNam8azi7o9K034gSalahXZlk6fWqv2ptSn3KFjbr9a5/T9RWxt1mkQ5UZBHepX8SNGV3FSuMg7eR+teb9VfN7p6McTdanQLfNBcMqSFZAvzHPWuY8TavcSzt5hDqOnFU9Q8QMpzGzlpO4FY9xfSyMdzMdvv1roo4W25z1sV2Y77atwNrFt3OMmqF7Zea/UDpinyfM67t3zUGQZwu5fY969GNPl2OKVTmKD2uJWB+btmopIeOV74rSdXVefz61A0LOD9fStYmErFDy+eNxpxj+b7vA5PFXPs237qsM+hxTZFO/DKwGPWqMo6MpzR+Y3Apwg+XIXNWFXJ7Y9fWhococ8j16UD6lVhscYDA02RNz/wC01WnQDorZX05pfs/mMrYOW69qCpb3RUaH9w3WmlRiPa3T1FXCBJKB3H60SIzM33sem2gLq2pVFv8A7QIoEK5/r6GrHkbTt5z9Kd9nVQN23DH1oKUiv9lDJuHA7nPNNjVWGctx2NWRGsbEIRu7ZNBiZ23BkD+wrMrmK4iZ1+Xb9KYY98nbPSrE1n5km7JVhz14NO8tfOHPvQStdinDHgnjimlVZsbfcGrXk53fd9sCkCMJMK27+lARvfUgMSs3ys3HqKilg2jdnmrrIwc53fgOtNkhYEbl4b3plSbWxRW1IB3dB3qMRmVWwNvtVyaDev8AEv8AWmtBuXHI9800xRkUpUDcfnxTDaM4wu0Vaxg7W7etMeFZOPlGT6VQpeZU8geZx1Xvnimzpnrye/NWkh2/KFyB+dLJDtPI/Sgzile9ilIgWRfl/PpUcsLN83IGegNXnjV26Efh1qF7L91x/D6c07sciuYsfxHNNYhWxz+VWjGNv3cUiwEJ96ldiUrFLbmU/Nj8KdJFgcSVYEDSHdz9CKdJCw7dPWgfM2UYo+Nu335pskO35c/MT6Vclj3H7v4imPCxI44X2oKjJLdkBg3jBx8vFJJtKHjkelWRDz91vmNCQMG24H4igu6KggVx97gjnI6UxLYLHtz93v61cmhb72OOmBSBFXP8X14xQTK/Qp+RvG/nd+lIYM7fmq4I4yOud3HSh7dioKoNooGldWK3l87V+bI/KmTRBY1X3/I1cS3y3yjy+PTrQsWB8y7sdz1NBZVMS7sADOOeKZ9mEjfNtVfQd6slDvP3vx7U2WLcu0qvrQHMym0W4llH3aNjKzDGc1akgcn5lCLjpnrQI2Vfl9c+tKw+YpImR80YVs0pTD/T071ckjYjcdreiiozCYkztG5uvrSa7F+hBLGxfheG96ZLGFGR8w74qUphc5ZvUelMa38lxt2rvHrS5WLm7kcakQNtHB4wac4Oxvb0qYR7YwufMOajWJicbWHOTjvQOMmyu527f4s9Pam4bZ909egqea2Iyx2r9DUTpkht/wAvvSHz9ERlNjD39qbsYM359KmEfmjG7p+NDJtUgrJsz2FUPVFVFwGUMAc9Ka77JQNufUirSwYHbHuOaiQKpbJ/LipdiY1GyEBW2sSVJ9aQL8+fvHuAf1qYwK0h5LDqM9qP3YUtkBgcZxSkrD5nfQhLc/6uozH833lAbg49KtJHvP8AFt7elR3IjIw2PYjrUWNb6EJ4lXb90dsUSpiTc4BqWOEKo+97DPWlaGMNuVduPWlazDmZVETI33V+tDrtBYsCrcYFSG2wBtVtrdeOlOECv8u3HPB9/Sk49hxkQrCF27fTvQ9syvnbw3apTDj7wK7eMk5ppjaQ/wATY5HHSocTXm00GSWyuwC/K/Y+lRLE0MgGOvU+tWZLbgMsa7u5zyKGc7l4DA8Zx0qJIrW5CIAz55HHOelNEW1eDn0A71ZwAvzfPt49aQLtj+VQp+lY2NPMhEbBcs369KDFleGHtk1N5C+27607y9g+783TpU+hqo6XRV+zsW6ru7ChYmVm42574qd4fm52j36c0/7O20j5V29N7fe/LJ/Ss9Opcb30K6ReWfmYEN0ApZBtTcAw+bb/AJ9vc1dsbSLU9Tjs1uIRdMQBGZF8zB9Ezn8DjI6elfVHwt/4JYXHiH4fL4q8XeP9L8JaG75DxWRka6hHXY0hSUu3O0+SVBI6gZr854s8UeHcgjbMK8eZbRj7z/Db52Prsn4SzLMlejTtH+ZvQ+ULWwkuLqKFQJZpm8sKp+YkkDgdwOpPYCt/4+fC3UP2ZvDum6lrnl6rHqlt9pUaO32tbRCcBbhhxEx64Oe1e1638MZPC7alp+kWTQ/D6RXjbUXC2+uwTKCV+0TplGAwdvknD5wRg188ftd/CzxT8G9A8PeOPhbrutanpNtbPD4luFtw6xoGzGk0CDypVbc43upPXPQZ/n/OPH3FZniFSyq1GnLRN6t/nZn6Rlfh3hcLTcsY1Oa6dP8AgnK2vxrutLb7Lp+l6dctrUKy2zXADLNGPvKHx+7lU5HHGAMit7xl8BvGlrc6dqreNprf+2iD/Z8EjXX2B27yQnP7s9cjbkVD8Cfj18L/ABF9ns/H3hGx8P3V0FXzbaXbZzK3TbvAjSQkn5CNnQAhcY9l8X+DLv4XQw3HhLxDod7oM2PsFjrUws50Y/dtreeZXVbjPAt7gBhjAmYDcfyXOeJsxr4vlqtufRyd4v0e1z7DB5fSpU7QSS8l/TPPbX4b2fhjUja6tdyeEvF5i89J9LO211SPgMY88SdQXUcqMZOK86+JnivXvgjqm6z1PULHS75Sy6no9st5pt/KSQYprZgYt+Ry0e088817Vc/HLwf8evC03hXxu0uh3Vhcxi4uZrYWslhcc7I7pZCXiYgMFmQsp3HbKnKPwfxu+F114NtfL8PrqHj7wpqEqS/2ro08bapok4ADQ3eI2ju4woVkkeMMFYLvGMnnyvEYmriVRrRam+ktn5p9D1KmFhBcyldHyf48+NGtfCyG/Nnptr4W17Upc3kuk3DpCmG6Rw52xq2M4HHPHGKK6j9q34geHfip4gsIJNDtlbRF+wJr9p5sLausS7GaW2csQ28H+L5cY5xmiv0CGBppfvFFPtdfqefLFJOybP6EtZtIfEGgfZ7qFbhZABscZyfSvmv9oj4M7D9o02xW3aPO8DgYr3CX4hW7ALmTcB8jDpn1qnNqP9tWUzXG2VvRuhFf1RltarhZp9PwPwPHUaWJi1LfufFs9q1s+0qVboxqN4irfL8ox0Ne4fFbwzbiGaU6bD5fZ8bcV47PDmZl24we/av0jA4z28eY+AxmFdCT6lApg9OfXtSIuxvmUt71ce3bPPNNjiZj7d8V2LzODUrrAXH3dtNNt8wP8XtVpR5nI3c9vSgxsvsPpTvcqxT2NGrcMNx9elHlb7faWbI71aa33n/E0ptjs/hx7U+hPUgeRw45b5cdKkmkaX5vvL0xUnlYduD0pjowPy/KfUUco3KyKXlswbaCvPO6pMJkA88ZHFWiNxH5H3pghyv3ec9Koy6kRGf936d6agJ64x2wKs+UQv3aRE+n40epqtEPVmkXDN8uMY7U2bvjb0xStGR1prRcZwazjFXL5lbUqyReSh55brUbxsy445HWtFZGUj5AaieNZj9zbzzV9QsnqU/L2L/u9vWmvBhucc81c8jJ6YHc0fZh60zIpeUce3pimLb+Zu+6o55NXJLXeB975uMZprW5x0+UdB6VURctyk1vk/wtTPJ5+6OPSrxt9/Rd2PXimCBQ65X73pTuZ9SsseByvPbNMaMluw9Qauy26g7R+ZojsUk+br2zRdFblBYdzEfrnGaf9nwc+nrzVxrUIPaogg/u0uYOUrfZtj7s01oFJPyt83v0q8LYHpnHpTWj+YfN+lK7KsioIV6fNt9D3pQiQj7p65+tWBD8x4/HpmhosnFFwsiq0OMt/ePp0pPK/wB38qveR8q/LzTJIfzpBoVTGqEYX6Gm+UhPb6Vc8ruc9OKa8S0AvIqeXtPfB96V4P3Z47d6sxw+3HbNIy4P976UAtSmFDR7dtIFx95twHSrbR7UX5ee/tTVh3OufX0oKlLoUnQAjj5mpggZGY4zz+NaDW+R93kHrTGt1DGqRMTOkh+fG73HHSm+WzdW+6Ow61eNv5caqPutyaSaDkY+tUtSmZ/2f8O/NMkgYDqPqauFOSdvGeKbJDtVTj8KCNSkR8udw/KkYqyZ6ccAd6tFGKtlV3L04oaFWYLxu6/Sggo+SwO3b171HLFtb7p+mKvvbfIu5mDeopfKIT+maAu+hn+Vvf7vGB1ppt1Jzt/SrhiYDlsfWnRw/L/WgvlM0rywUBcdRjrSNHsPX/Gr0lvuJyM8/lQbfb/CPxGaCZRRS27VBxxTvI43bd1WvJ3t3Hr6GnLEWX+E0DVOSVygIOMY7/lT2tvNIwuT2Jq0YhwuOvoKUQ7VO7g9cnvQaRjoUzAw67d3sKieNxxgjvxV5oMKCG3N7dab5bMh/r1oKt2KTqcrnhm9qcFCqdoPFWZIcJnJJHrTWi4z830x1oBeZVWDc4+XsaYIlwxA3L3OOlW/JZ23YC/jTfJKsx+77ZoGt9Cj5IB+8349qSSIk/f4xVvG4f0pVQMPurQLcqNbZH3T5nrTDDhunzHg5NXXQdhz61G0SgMPl54pal3KbW5WT5ueO3eofK2/diZvrzV541I2579R3qJ48P8AxDtwaZBAU8pizJ17AUxI1JzgL9RVknbuVeT6ntRJHsP3t3c8dKTRSlYrvCsTD7qt7VG0eT8zN9exqyIs/e/CmH/9dLlYadCu0K8fL+I45qMrj5vmbsBmrUsBkH8Ix7Ukke11+YfTNOxPN0KiwbieO3JNIqhGIZeV6/SpxbeYTnlVORzSKm/DH5cdfeloNSsQCLEWCuymKud3oeh9Ktsvyr0O7se1NZBtbKq3pSeo3Ir4LbV3fdGM00RbuAmGU5zipmiaQbVxz2x0oMDBhjPHXmlZF8+hVwqncyMWzTnQP0jarDW+1eeme5qMR5Hyn8R0pNCVQhih/dMPm/OmiPB2sPl6cnv61ZVVEfBzu96SVMqF4bdznFKSbNCq8ZEm2T94B0welCBnbn8gcVOLY5/h/LrSSWzK4xtx3xWNrGkWyAlEYnHzEcA9qVYhhewXt61aMan+Jc/3SKaCrMF2/lSkjT1IBGQmOm71FLt2BRuX5vWpsfI3qvHNDRgrjbyR6c/WsuXWxotFdFfy2LcYb6CneWWT155GelaGl+GbzWIZJLe33Rwj53eRYkH4t1PsK6Kw+EF5r2gSzaVZ61ql9GMyNDAEtLce79XPsvTFfI8T8WYDI6Xt8ZKy6LufSZDw3i80najHTv0OFuriG3VZGZV7j5d+B3P/ANftVfwxoHiT4peNNN0vT4byy0e+YCS4tIt94V7nzMFVAHJzwAK6L4Z/sx/EH4i/FK5t1s7K4s9PXzZ50k+z6ZYqvzeZNMeXC4yVHUjbg16z4k0ZvCUljpPh5LvxJqOpTqkYYLb6bO56i2skw5X1kfCbcnk4B/kPjfx2x2ZzeFy1qnDvF6v1Z+1ZFwFhcD+8xHvz69j63/Yf/Z5+GP7Pfw71bV/Elv4XvLLwuovdR1v5bqJIyMhGkOQZCeuOAQelSfFT4pzfFFp/Fy7dS0e+TOl38ThrS0t8YSMbeBHjGSPfJ7V5f47vr7wj+zdJ8MZLzT7Txjfxrq10bYZs5JWLLHZqAPmKIjMcDb+8IzXzP8XvD3i/9ivxbp3irwJruoX0esWMGq6j4O8//iXzBo1MrWsJyoiIyWH/ACzbcvO2v58eTV86q1JubdTddb/M/QlXpUIckbJI+ivGF1beFvOu4Fks9Eu7lLe6QQ82BJ3I0gA+VdwHzDAPTvXH6HeXnh/xJ8Q9PN5DcXy2cWpx2s8QNtfWhD7hCGGG4Q5xzkjkd/TvAHiK3+OPwMbxz8O9PtdZ1TS0Cav4cnPmTXdsf9bbBuhYLlkJB5QY5xXQfs//ALOum/G/TxrmhtdS2YtZ00J5k3/2bJtbzrW47psY8E8nd0wBXiYGniadX2GIptapP71r5eTMK04VYqpSd/Lr8j8lPjf+ylY33xXj1TSbiW9+H/i63TXNFljuCbW0WQfvoSB91oZllQjqAg9q674W/tT2nw08ZXPg/wAQW82peAmi2wvBteXSLThVVg2TLFsOTGwbpx6Vu/EnUZPhv8O/EXhu7hgm/snWb28RgCED7isq/wC6xQ8DAIIrw/R/g7c+MrexW8uJheakRfas68s8R5EQHQDaeB7V/X2I4VpVsqo4CMVKdk3K2vlr3R8TRzWUMTOtN2itLHvXx40bwl4nKXdlLY3Wqx2cbeEtUhmLDVlcsBZuc7niyAy+Zko0ZViAyg8jqH7Tfib4KeFNC0PTbGawk0yBotasBlYL+/lkZs7Q2QUBX5VIUEk4ySTP8BvDtx4b0/WtAl0fT49Ju5o2W7uVM00GW6wZOI8AEsQPSuj+IPwY03T/ABxfatpUk2veFtAkCteNHmSe8aCJ24/uqCoBPXk135Lwv9QwCnX15nbVa/JsyxOee3xPLS6HgfxM1KTVvHDanrEcUl9Y26Jc+XGI2luXA80naMs24tknJJySaK9T+E/g7+0NSm1zUbVWvLgGW3LjegEh3FiD3IJ+maK9/B+GuKx1P6zKcY36Pex42K42o4Wo6MtWj9K4vH9xZ2sZhiHHTJzn61taN8Rpjbq1wu1t3PvRRX71UwtNpaH49h8RU7nP/Ezx0NV0i4jZWVW6YFeRyq0ssj/3jz6Yoor2Mtgo6I8fMKkpPUGgYBfugUeUwPbHpRRXqXuedHYRIcvx8v0FNNuMBu5oooGG0HjIx9KX7OoBwCtFFVYfKhypk/3vUU1oMn0ooqSJbjVjZoj7GjyW8votFFVEprQQ2+e9II88Dt196KKBQ1A2/wAncelNMHGORRRR1FIX7PuU8/pSC3/2j+Ioooe4RfQbHDk85+vSkCZAYfkaKKcQkIIt8fVup6VGttgnluvcUUUyRWtsL97b+NMaA9sfKcZ9aKKCZBJExl4IKg4NNS28ofjjiiigSFeHj7v50ww7l+6OBxmiigq2o37O28elK1vlRx+FFFAxkUGAf9ntThFkc/hiiigBhRmPb2xSeRuHsOtFFMq4NHtHy0eTtXlv0oooYRethogzJg0ogw/QGiipKGJDvYn+E+nODQ0LBf0oopmY0W7An7p296b5Izn+lFFMrmZGLdtzfXimm2LHb94AZ5oooiFxr2ZB69ailt8Y+XLCiirIlsQyWrheM9c9Ka0Wef8A9qiigzQqwZH3m/Go5LcZ75oooLiI1uFT6+tIkJ+9z+NFFBTj1BrYqSabJENoYr1oooJi7ix2/HT86QReWtFFBo5aDWiUr7+tNZNqc9hxmiigJEYh2jzF+9nBzQI16/x+lFFA0NMPO75s46UeRvGQMH1oooGQtEwz/XvUZhYgbgB6iiigmw1Yc/MBnPFN+z7EC7STnNFFADpIjld3aoz8rcKpU98UUUAmRNEzfwj8Fphjzt+XJ9xjFFFAo7jXs1D7uT6+9NRD/wB9dc9qKKCxXgKfKBUbIVY/1oooE9xJYN0QbHPXHao5LYDadoH4UUUD6glriBtp5zn7tRtGArBlOG/2aKKCpDPsu192Mt6k0scLeViiipZI3YwT5eucZoeMhvce1FFSEiJrfzW2n7vvSi3ZSqhgF9KKKAGtZrhRgY+vSkktSc7G4z60UUk7m/UQRcYZs84xS/ZNj/Kp9uaKKioOjq2MktcEDbz396Eh8lhgquPXrRRWZcW2OCc5ZevU9qatvJcOIo1aTzeNqc59s+vtxRRSl7qujan7zsz0DwT4W8J2Bjh8ceIobN2OYbG2cXMcK4JzcGI7kcsF2rkcBskDr9E/Djx54Z/Z9+Gl34k8T29xpHhXVVFvF4lv71JZ9YiXIMWn2EIPmOPu5LHBA3MDmiiv5O8XsPDF1/Z19Uj+ieAbUKH7pW0LvwM8X+Iv2ybeG30XwrpvhvwPq8ssvhHwxdX4XWNfj8whtW1N4+ILU8ttGC4wqEZD17rpP7NWjfB6fV/E95fWviHXWjV2lt0EUbEyIq7FwDFErYJXOcDk9aKK/kfPsHRhjvqtOPLC6Wh+pR9+jKct7Hxt8Rf2orXwt+0jqHiq3ksvEl1JqD6PPpzITbxRBISLuJ0+7hjMuDkHYeKk+Jfj3wL8Tb3WvAWg3Im0z7VPqvhXxNdo1qLaeZjO9lLkfLGZ3dFJ4KFTjmiiv7Q4L4ByaWFpV/ZtNQTVnpr8j8TzrP8AGU63sYtWu+hy37HHxtuv2XPjTHeWkdkbW8QWVwl3L9nt7Q5BDM4yo2soHQ7gTwOtfWXgb9o2x/ZZ8eah8QfBMuk+Mvh38RpfN8VaZZP5kng+7XKCRlDfNFKWyDjPymiivoM+4ByOOJhiY0Fzyer76HDkPEuP9nKlzaK9tNT8/f20I9N+I3xa8TNoqx/YvEmqeeXjXMYztL7D2UnJAOeveue8NeG4tHurm6Zd0l1IGOF+6F4Xb/Kiivr8oy3DvENOPwWS8lY8DNMdW9mnf4m2zXhsIzZ+XJEu2NMfum2t1yM/XvUWjT3Wi+G9Ut/MZbfUrj7RNCTne20KD+Cqo/CiivVxmX4erDknHRbHJgcwrxnzJ6si07TltLDYi7V2IQoXaBwKKKK9CnhqUYRSXQ8nFXqVXOT1P//Z 4 | -------------------------------------------------------------------------------- /dat/dat_4.dat: -------------------------------------------------------------------------------- 1 | xxx 2 | xxx 3 | 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 4 | -------------------------------------------------------------------------------- /image_mountain.py: -------------------------------------------------------------------------------- 1 | url='xxx' 2 | md5='xxx' 3 | img=b'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' 4 | -------------------------------------------------------------------------------- /licence.txt: -------------------------------------------------------------------------------- 1 | GlobalVim使用须知 2 | 3 | 1. 本软件著作权和一应解释权归 ovo.ltd 所有, 不得复制本软件用于商业目的. 4 | 2. 如果用户下载, 安装和使用本软件, 那么代表用户信任作者和此软件. ovo.ltd 对任何原因在使用本软件时可能对用户和他人造成的损失不承担责任. 5 | 6 | 7 | I. 本软件不会采集用户的配置记录, 用户的操作记录, 和任何其它任何敏感信息. 8 | 9 | 作者拥有此约定的解释权和修改权 10 | -------------------------------------------------------------------------------- /localization.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | class Language: 5 | lang_dict = {} 6 | lang_dict['zh']={ 7 | "https://ovo.ltd/projects/globalvim-en/":"https://ovo.ltd/projects/globalvim-en/", 8 | "No GeeKey HotKey selected, remain unchanged!":"未选择热键,原热键保持不变!", 9 | "\nShort stoke to perform {0}":"\n短按为{0}", 10 | '--geekey--spacing--':'--geekey--空挡--', 11 | '--geekey--recording--':'--geekey--录制--', 12 | '--geekey--spacing--recording--':'--geekey--空挡--录制--', 13 | 'Keyboard State Cleared':'键盘状态重置', 14 | "Click to Clear Keyboard State":"点击重置键盘状态", 15 | "'block' mode always blocks original key.":"'阻塞‘模式总是阻塞按键原有功能。", 16 | "'longblock' mode only blocks when pressed longer or as GeeKey.":"'长按阻塞'模式仅在长按或者GeeKey组合键时阻塞。", 17 | 'GeeKey Mode':'GeeKey 模式', 18 | 'block':'阻塞', 19 | 'longblock':'长按阻塞', 20 | 'Click to select another GeeKey HotKey':'点击重设 GeeKey 热键', 21 | 'GeeKey HotKey is set to {0}':'{0} 已被设置 GeeKey 热键', 22 | "Click Ok to set new GeeKey to {0}. Otherwize Click Cancel.":'单击确认将 {0} 设为新热键. 否则请点击取消.', 23 | 'GeeKey HotKey':'GeeKey 热键', 24 | 'Press Key as new GeeKey':'请按下新的 GeeKey 热键', 25 | 'GlobalVim/GeeKey':'全局 Vim', 26 | 'Save Layout':'保存布局', 27 | 'enable vim mode':'启用vim模式', 28 | 'exit vim mode':'退出vim模式', 29 | 'substitution failed for: {0}':'替换失败: {0}', 30 | 'substitution done':'替换完成', 31 | '{0} done':'{0} 完成', 32 | "Invalid search scope {0}":"搜索范围 {0} 不合法", 33 | 'Error':'错误', 34 | 'Another GlobalVim/GeeKey instance is running':'GlobalVim/GeeKey 已经启动,并处于运行状态中', 35 | '_title_this': '全局Vim/GeeKey热键', 36 | '_name': "名字", 37 | '_email': '邮箱', 38 | '_about': '关于', 39 | '_apply': '应用', 40 | '_hotkey': '热键', 41 | '_operation': '操作', 42 | '_help': '帮助', 43 | '_quit': '退出', 44 | '_about_message': """谢谢使用GlobalVim/GeeKey! 欢迎提出改进建议!\n有问题请致信einsxiao@hotmail.com.""", 45 | '_startup_with_system':'开机启动', 46 | '_text_to_key':"'{0}' 绑定的文本", 47 | '_function_to_key':"'{0}' 绑定的程序", 48 | '_macro_to_key':"'{0}' 绑定的操作序列", 49 | '_macro_to_key_text':"'Ctrl+GeeKey+{0}' 开始录制操作,Ctrl+GeeKey结束录制", 50 | '_support_tooltip_wechat':'微信扫码点赞, 点击显示log', 51 | '_previous':'上一条', 52 | '_next':'下一条', 53 | '_more':'更多', 54 | '_text_color_info':'绑定文本', 55 | '_edit_color_info':'绑定按键', 56 | '_macro_color_info':'绑定录制', 57 | '_function_color_info':'绑定程序', 58 | '_not_run_as_admin':'须以管理员权限重启程序,才能修改当前按键', 59 | '_tip_for_geekey':'GeeKey+X -执行X的绑定;\nGeeKey+Space X -执行X的空挡绑定{0}', 60 | '_tip_for_space':'GeeKey+Space X -执行 X 绑定的空档绑定\nGeeKey+Space N X -执行N次X\nGeeKey+Space Space -弹出主界面', 61 | '_tip_for_tab':'GeeKey+Space Tab -开启/关闭自动补全功能\n', 62 | '_tip_for_v':'GeeKey+v -进入/退出vim模式\n', 63 | '_tip_for_q':'GeeKey+q X -开始录制X的绑定宏\nGeeKey+q Space X -开始录制X的空档绑定宏\nGeeKey+q -结束当前录制\n', 64 | '_warning':'警告', 65 | '_notice':'注意', 66 | '_restart_to_function':'重启后更改才能生效', 67 | '_reboot_to_function':'重启后更改才能生效', 68 | '_layout':'键位布局{0}', 69 | '_startup':'开机启动', 70 | '_startshow':'程序启动时, 显示界面', 71 | '_doubleclickfix':'修复鼠标双击硬件错误', 72 | '_configure':'配置', 73 | '_language':'语言', 74 | '_general':'一般设置', 75 | '_account':'Eva账户', 76 | '_about':'关于GlobalVim/GeeKey', 77 | '_configure_menu':'配置(&C)\tCtrl+C', 78 | '_exit_menu':"退出(&E)", 79 | '_loadfrom_menu':"从文件导入(&L)\tCtrl+L", 80 | '_saveas_menu':"保存到文件(&S)\tCtrl+S", 81 | '_save_menu':"保存(&S)\tCtrl+Shift+S" , 82 | '_tutorial_menu':"手册(&M)", 83 | '_about_menu':"关于(&A)" , 84 | '_option_menu':"选项(&O)", 85 | '_layout_menu': "布局(&L)", 86 | 'Open Layout':'打开布局', 87 | '_help_menu':"帮助(&H)", 88 | '_index_menu':"主页(&I)", 89 | '_function_path':'路径&&参数', 90 | '_repeat':'重复模式', 91 | '_repeat_enter':'进入重复模式,请输入数字', 92 | '_macro_record':'录制操作序列', 93 | '_macro_record_second':'录制Space操作序列', 94 | '_start_record':'开始录制 {0}, Ctrl+GeeKey结束录制', 95 | '_end_record':"{0} 的录制已经结束", 96 | '_autocomplete':'自动补全', 97 | '_autocomplete_on':'启动自动补全', 98 | '_autocomplete_off':'关闭自动补全', 99 | '_runasadmin':'程序启动时, 以管理员权限运行', 100 | '_key_swap_caution':'异常按键交换', 101 | '_key_swap_caution_content':'存在异常按键交换,程序可能会覆盖原有设置', 102 | "_new_version_available":"有可用新版本", 103 | "_new_version_detail":" 有更新版本的GlobalVim/GeeKey可用,点击更新到应用商店更新. ", 104 | '_check_update':"""更新(&U)""", 105 | '_version_fine':'已经是最新版本', 106 | '_version_fine_detail':'当前版本已经是最新版本.', 107 | 'OK':'确认', 108 | 'Cancel':'取消', 109 | 'Update':'更新', 110 | '_to_index':'查看主页', 111 | '_network_unavailable_detail':'GlobalVim/GeeKey连接服务器失败,您可以尝试点击下面按钮访问主页检查是否有更新.', 112 | '_network_unavailable':'网络不可用', 113 | '_command_not_found':'未知命令 {0}', 114 | 'Unknown command':'未知命令', 115 | '_startvim':'程序启动时, 开启 vim 模式', 116 | 'Geekey Enabled':'启用GeeKey', 117 | 'Enable GeeKey HotKey system':'启用GeeKey热键系统', 118 | '_print_key_event':'打印键盘事件到日志窗口', 119 | '_start_autocomplete':'程序启动时,启用自动补全', 120 | 'visual':'可视', 121 | 'insert':'插入', 122 | 'normal':'常规', 123 | 'vim enabled':'vim 已启用', 124 | 'vim disabled':'vim 已退出', 125 | 'Command failed':'命令错误', 126 | 'Command not processed':'命令未处理', 127 | 'Key {0} set to type {1}':'按键 {0} 被设置为类型 {1}', 128 | """Double click to hide this log window.""": """双击隐藏此日志窗口.""", 129 | 'value for {0} of type {1} set to:\n{2}':"{0} 被设为类型 {1} 且值为:\n{2}", 130 | "Keytype for key {0} not set. Try delete default.ini to fix":"{0} 的按键类型未设置, 请尝试删除 default.ini 来修复问题.", 131 | "Check update failed for: {0}":'更新检查错误: {0}', 132 | "config file {0} does not exists":"配置文件 {0} 不存在", 133 | "Load config error for: {0} \nTry delete default.ini to fix.":"加载配置文件错误: {0}\n请尝试删除default.ini来修复问题.", 134 | "Save config error for: {0}":"保存配置错误: {0}", 135 | 'cmd "{0}" processed by self-defined macro':"命令 {0} 被自定义宏 处理", 136 | 'nothing in register {0}':'寄存器 {0} 中没有内容', 137 | "command {0} not found.":"命令 {0} 未找到", 138 | 'executing {0}':'执行 {0}', 139 | 'executing {0} failed':'{0} 执行失败', 140 | 'evaluation failed for: {0}':'求值失败: {0}', 141 | "recording {0} end":"{0} 录制结束", 142 | 'Registers':'寄存器', 143 | 'save':'保存', 144 | 'save done':'保存完成', 145 | "recording ":"录制 ", 146 | "command {0} not found. You can bind your own operation to vim_cmd_map_{0} item in default.ini":"命令 {0} 未找到. 您可以将操作内容绑定到default.ini中的vim_cmd_map_{0}项", 147 | '':'', 148 | } 149 | lang_dict['en']={ 150 | '_start_autocomplete':'Enable Auto Complete when startup', 151 | '_print_key_event':'Print keyboard event to Log window', 152 | '_startvim':'Start up wiith vim mode enabled.', 153 | '_to_index':'Check on HomePage', 154 | '_network_unavailable_detail':'GlobalVim/GeeKey failed to connect to the server. You can try check whether new version available from homepage by click button below.', 155 | '_network_unavailable':'Network Unavailable', 156 | '_notice':'Notice', 157 | 'OK':'OK', 158 | 'Cancel':'Cancel', 159 | 'Update':'Update', 160 | '_version_fine_detail':'The current application is already the newest version.', 161 | '_version_fine':'Already the newest version', 162 | "_new_version_available":"New Version Available", 163 | '_new_version_detail':" There is a new version of GlobalVim/GeeKey available there. Click 'update' to visit App Store. ", 164 | '_key_swap_caution_content':'There is abnormal key swap which may be overriden', 165 | '_key_swap_caution':'Abnormal Key Swap', 166 | '_autocomplete':'Auto Complete', 167 | '_autocomplete_on':'Auto Complete On', 168 | '_autocomplete_off':'Auto Complete Off', 169 | '_runasadmin':'Run as Administor when startup', 170 | '_macro_record':'Record Operation Sequence', 171 | '_macro_record_second':'Record Spacing Operation Sequence', 172 | '_start_record':'Start Recroding {0}; Ctrl+GeeKey to Stop', 173 | '_end_record':"Recording for {0} Ended", 174 | '_repeat':'Repeat Mode', 175 | '_repeat_enter':'Enter Repeat Mode; Please input a Numberr', 176 | '_function_path':'Path&&Arguments', 177 | '_help_menu': "&Help", 178 | '_index_menu':"&Index", 179 | '_layout_menu': "&Layout" , 180 | '_option_menu':"&Options", 181 | '_about_menu':"&About", 182 | '_tutorial_menu':"&Manual", 183 | '_save_menu':"&Save\tCtrl+Shift+S", 184 | '_saveas_menu':"&Save To File\tCtrl+S", 185 | '_loadfrom_menu':"&Load From\tCtrl+L", 186 | '_exit_menu':"&Exit", 187 | '_configure_menu':'&Configure\tCtrl+C', 188 | '_about':'About GlobalVim/GeeKey', 189 | '_account':'Eva Account', 190 | '_general':'General', 191 | '_language':'Language', 192 | '_configure':'Configure', 193 | '_startup':'Run when PC boots', 194 | '_startshow':'Show main panel when application startup', 195 | '_doubleclickfix':'Fix mouse double click error of hardware', 196 | '_layout':'Keyboard Layout {0}', 197 | '_restart_to_function':'Only after reboot the change can take effect', 198 | '_reboot_to_function':'Only after reboot the change can take effect', 199 | '_title_this':'GlobalVim/GeeKey', 200 | '_name':'Name', 201 | '_email':'Email', 202 | '_apply':'Apply', 203 | '_hotkey':'Hotkey', 204 | '_operation':'Operation', 205 | '_warning':'Warning', 206 | '_help':'Help', 207 | '_quit':'Quit', 208 | '_check_update':'Check &Update', 209 | '_about_message':"""Thank you for using GlobalVim/GeeKey! \nSuggestions are welcomed to improve this tool.\nAny questions please contact einsxiao@hotmail.com""", 210 | '_startup_with_system':'Startup with System', 211 | '_text_to_key':"Text of '{0}'", 212 | '_function_to_key':"Command bound to '{0}'", 213 | '_macro_to_key':"Operation sequence recorded bound to '{0}'", 214 | '_macro_to_key_text':"'Ctrl+GeeKey+{0}' to start recording operation; Ctrl+GeeKey to stop.", 215 | '_support_tooltip_wechat':'Scan QR code with WeChat to support. Click to show the log.', 216 | '_previous':'Prior', 217 | '_next':'Next', 218 | '_more':'More', 219 | '_text_color_info':'Keys to insert text bound.', 220 | '_edit_color_info':'Quick Keys to act like the specific key bound.', 221 | '_macro_color_info':'Macro Keys to replay all keyboard and mouse actions recorded.', 222 | '_function_color_info':'Application Keys will launch the bound application immediately.', 223 | '_not_run_as_admin':'Please restart as Admin to make current key change.', 224 | '_tip_for_geekey':'GeeKey+X -exceute binding of X\nGeeKey+Space X -exceute spacing binding of X{0}', 225 | '_tip_for_space':'GeeKey+Space X -execute spacing binding of X\nGeeKey+Space N X -execute X for N times\nGeeKey+Space Space -raise and active main panel\n', 226 | '_tip_for_tab':'GeeKey+Space Tab -Enable/Disable auto-complete\n', 227 | '_tip_for_v':'GeeKey+v :Enter/Exit vim mode\n', 228 | '_tip_for_q':'GeeKey+q X -start recording binding macro of X\nGeeKey+q Space X -start recording spacing binding macro of X\nGeeKey+q -end current recording\n', 229 | '':'', 230 | } 231 | lang_config = 'zh' ; 232 | def lang(self,term,*args,**kwargs): 233 | try: 234 | text = term 235 | if term in self.lang_dict[ self.lang_config ]: 236 | text = self.lang_dict[ self.lang_config ][ term ]; 237 | elif term in self.lang_dict['en']: 238 | text = self.lang_dict['en'][ term ] 239 | else: text = term 240 | text = text.format( *args, **kwargs ) 241 | except Exception as e: 242 | #print('lang error for:',e) 243 | pass 244 | return text 245 | 246 | def set_language(self,lan): 247 | if lan in ('English','en','en_US'): 248 | self.lang_config = 'en' 249 | else: 250 | self.lang_config = 'zh' 251 | pass 252 | 253 | def add_lang(self,lan,dic): 254 | if lan in self.lang_dict: 255 | self.lang_dict[lan].update(dic) 256 | else: 257 | self.lang_dict['en'].update(dic) 258 | pass 259 | pass 260 | pass 261 | 262 | -------------------------------------------------------------------------------- /logo.icns: -------------------------------------------------------------------------------- 1 | icns -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | altgraph==0.16.1 2 | attrs==19.1.0 3 | Automat==0.7.0 4 | cachetools==3.1.1 5 | carbon==1.1.5 6 | certifi==2019.3.9 7 | chardet==3.0.4 8 | constantly==15.1.0 9 | hyperlink==19.0.0 10 | idna==2.8 11 | import-file==1.11 12 | incremental==17.5.0 13 | keyboard==0.13.3 14 | macholib==1.11 15 | modulegraph==0.17 16 | mouse==0.7.0 17 | numpy==1.16.3 18 | Pillow==6.0.0 19 | py2app==0.19 20 | PyHamcrest==1.9.0 21 | pyobjc==5.2 22 | pyobjc-core==5.2 23 | pyobjc-framework-Accounts==5.2 24 | pyobjc-framework-AddressBook==5.2 25 | pyobjc-framework-AppleScriptKit==5.2 26 | pyobjc-framework-AppleScriptObjC==5.2 27 | pyobjc-framework-ApplicationServices==5.2 28 | pyobjc-framework-Automator==5.2 29 | pyobjc-framework-AVFoundation==5.2 30 | pyobjc-framework-AVKit==5.2 31 | pyobjc-framework-CalendarStore==5.2 32 | pyobjc-framework-CFNetwork==5.2 33 | pyobjc-framework-CloudKit==5.2 34 | pyobjc-framework-Cocoa==5.2 35 | pyobjc-framework-Collaboration==5.2 36 | pyobjc-framework-ColorSync==5.2 37 | pyobjc-framework-Contacts==5.2 38 | pyobjc-framework-ContactsUI==5.2 39 | pyobjc-framework-CoreAudio==5.2 40 | pyobjc-framework-CoreAudioKit==5.2 41 | pyobjc-framework-CoreBluetooth==5.2 42 | pyobjc-framework-CoreData==5.2 43 | pyobjc-framework-CoreLocation==5.2 44 | pyobjc-framework-CoreMedia==5.2 45 | pyobjc-framework-CoreMediaIO==5.2 46 | pyobjc-framework-CoreML==5.2 47 | pyobjc-framework-CoreServices==5.2 48 | pyobjc-framework-CoreSpotlight==5.2 49 | pyobjc-framework-CoreText==5.2 50 | pyobjc-framework-CoreWLAN==5.2 51 | pyobjc-framework-CryptoTokenKit==5.2 52 | pyobjc-framework-DictionaryServices==5.2 53 | pyobjc-framework-DiscRecording==5.2 54 | pyobjc-framework-DiscRecordingUI==5.2 55 | pyobjc-framework-DiskArbitration==5.2 56 | pyobjc-framework-DVDPlayback==5.2 57 | pyobjc-framework-EventKit==5.2 58 | pyobjc-framework-ExceptionHandling==5.2 59 | pyobjc-framework-ExternalAccessory==5.2 60 | pyobjc-framework-FinderSync==5.2 61 | pyobjc-framework-FSEvents==5.2 62 | pyobjc-framework-GameCenter==5.2 63 | pyobjc-framework-GameController==5.2 64 | pyobjc-framework-GameKit==5.2 65 | pyobjc-framework-GameplayKit==5.2 66 | pyobjc-framework-ImageCaptureCore==5.2 67 | pyobjc-framework-IMServicePlugIn==5.2 68 | pyobjc-framework-InputMethodKit==5.2 69 | pyobjc-framework-InstallerPlugins==5.2 70 | pyobjc-framework-InstantMessage==5.2 71 | pyobjc-framework-Intents==5.2 72 | pyobjc-framework-IOSurface==5.2 73 | pyobjc-framework-iTunesLibrary==5.2 74 | pyobjc-framework-LatentSemanticMapping==5.2 75 | pyobjc-framework-LaunchServices==5.2 76 | pyobjc-framework-libdispatch==5.2 77 | pyobjc-framework-LocalAuthentication==5.2 78 | pyobjc-framework-MapKit==5.2 79 | pyobjc-framework-MediaAccessibility==5.2 80 | pyobjc-framework-MediaLibrary==5.2 81 | pyobjc-framework-MediaPlayer==5.2 82 | pyobjc-framework-MediaToolbox==5.2 83 | pyobjc-framework-ModelIO==5.2 84 | pyobjc-framework-MultipeerConnectivity==5.2 85 | pyobjc-framework-NetFS==5.2 86 | pyobjc-framework-NetworkExtension==5.2 87 | pyobjc-framework-NotificationCenter==5.2 88 | pyobjc-framework-OpenDirectory==5.2 89 | pyobjc-framework-OSAKit==5.2 90 | pyobjc-framework-Photos==5.2 91 | pyobjc-framework-PhotosUI==5.2 92 | pyobjc-framework-PreferencePanes==5.2 93 | pyobjc-framework-PubSub==5.2 94 | pyobjc-framework-QTKit==5.2 95 | pyobjc-framework-Quartz==5.2 96 | pyobjc-framework-SafariServices==5.2 97 | pyobjc-framework-SceneKit==5.2 98 | pyobjc-framework-ScreenSaver==5.2 99 | pyobjc-framework-ScriptingBridge==5.2 100 | pyobjc-framework-SearchKit==5.2 101 | pyobjc-framework-Security==5.2 102 | pyobjc-framework-SecurityFoundation==5.2 103 | pyobjc-framework-SecurityInterface==5.2 104 | pyobjc-framework-ServiceManagement==5.2 105 | pyobjc-framework-Social==5.2 106 | pyobjc-framework-SpriteKit==5.2 107 | pyobjc-framework-StoreKit==5.2 108 | pyobjc-framework-SyncServices==5.2 109 | pyobjc-framework-SystemConfiguration==5.2 110 | pyobjc-framework-VideoToolbox==5.2 111 | pyobjc-framework-Vision==5.2 112 | pyobjc-framework-WebKit==5.2 113 | python-swiftclient==3.7.0 114 | requests==2.22.0 115 | richxerox==1.0.1 116 | six==1.12.0 117 | sortedcontainers==2.1.0 118 | Twisted==19.2.0 119 | txAMQP==0.8.2 120 | urllib3==1.25.2 121 | virtualenv==16.6.0 122 | wxPython==4.0.6 123 | zope.interface==4.6.0 124 | -------------------------------------------------------------------------------- /res.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | #from __future__ import unicode_literals 4 | 5 | DEBUG = True 6 | if DEBUG: 7 | import traceback 8 | def DE(): 9 | print( traceback.format_exc() ) 10 | INFO['GEEKEY'].onKeyboardClear() 11 | pass 12 | pass 13 | else: 14 | def DE(): 15 | INFO['GEEKEY'].onKeyboardClear() 16 | pass 17 | 18 | ###################################################################### 19 | INFO= { 20 | 'Email':'einsxiao@hotmail.com', 21 | 'Version':'3.1.3.0', 22 | #'ServerAddr' : "http://192.168.1.77:8573/", 23 | 'ServerAddr' : "https://ovo.ltd/", 24 | 'HomePage':"https://ovo.ltd/projects/globalvim/", 25 | 'ImageChangePeriod': 50, 26 | 'MacroRecordingMax': 9999, 27 | } 28 | 29 | INFO['VersionSrc'] = INFO['ServerAddr']+"image_ads/app_info/" 30 | INFO['ImageSrc'] =INFO['ServerAddr'] + "image_ads/ads_image/" 31 | INFO['LogInitText'] = """Double click to hide this log window.""" 32 | INFO['NetVersion'] = None 33 | ###################################################################### 34 | 35 | import wx 36 | import wx.adv 37 | #import wx.lib.agw.hyperlink as hyperlink 38 | import base64 39 | import os 40 | import sys 41 | import time 42 | #import copy 43 | import re 44 | 45 | from wx.lib.embeddedimage import PyEmbeddedImage 46 | import webbrowser 47 | from functools import reduce 48 | 49 | #from win32 import win32api 50 | #from Foundation import * 51 | #from AppKit import * 52 | #from PyObjCTools import AppHelper 53 | from Quartz import * 54 | 55 | from localization import * 56 | from locale import getdefaultlocale 57 | 58 | from uuid import getnode 59 | client_info = getnode() 60 | 61 | #### coded image used in app 62 | import image_logo 63 | import image_mountain 64 | import image_bridge 65 | 66 | class log: 67 | log_func = None 68 | @classmethod 69 | def log(cls,*args): 70 | cont = ' '.join( str(i) for i in args ) 71 | cls.log_func(cont) 72 | pass 73 | 74 | def toInt(numstr,defaultvalue = 0): 75 | try: 76 | return int(numstr); 77 | except: 78 | return defaultvalue 79 | pass 80 | 81 | def toFloat(numstr,defaultvalue = 0): 82 | try: 83 | return float(numstr); 84 | except: 85 | return defaultvalue 86 | pass 87 | 88 | def toNumber(strnum='',num=0): 89 | try: 90 | num = float(strnum) 91 | except Exception as e: 92 | DE() 93 | pass 94 | return num 95 | 96 | def potentialKeyOfDict(key,dic): 97 | for k in dic: 98 | if k.startswith(key): return True 99 | return False 100 | 101 | INFO['APP'] = None 102 | INFO['LOOP'] = None 103 | 104 | def warning(message,title=''): 105 | style = wx.OK|wx.TE_MULTILINE 106 | dlg = wx.MessageDialog(INFO['APP'],message,title,style = style) 107 | dlg.ShowModal() 108 | dlg.Destroy() 109 | self.payImage.SetFocus() 110 | pass 111 | 112 | import threading 113 | 114 | class callLaterThread( threading.Thread): 115 | def __init__(self, func,*argv): 116 | threading.Thread.__init__(self) 117 | 118 | self.run = lambda argv=argv: func(*argv) 119 | pass 120 | pass 121 | 122 | def ThreadCallLater(delay, func, *args, **kwargs): 123 | try: 124 | delay = max(0.001,toFloat(delay) ) 125 | timer = threading.Timer( delay, func, args, kwargs ) 126 | timer.start() 127 | return timer 128 | except Exception as e: 129 | DE() 130 | log.log('ThreadCallLater Failed for',e) 131 | return None 132 | 133 | def WxCallLater(delay,func,*args,**kwargs): 134 | try: 135 | delay = max(1,toInt(delay*1000) ) 136 | return wx.CallLater(delay, func, *args, **kwargs) 137 | except Exception as e: 138 | DE() 139 | log.log('WxCallLater Failed for',e) 140 | return None 141 | 142 | def WxCallAfter(func,*args,**kwargs): 143 | try: 144 | return wx.CallAfter(func, *args, **kwargs) 145 | except Exception as e: 146 | DE() 147 | log.log('WxCallAfter Failed for',e) 148 | return None 149 | 150 | import locale 151 | lang = Language() 152 | if locale.getlocale()[0] == 'zh_CN': 153 | lang.set_language('zh') 154 | else: 155 | lang.set_language('en') 156 | pass 157 | 158 | set_lang = lang.set_language 159 | is_en = lambda: True if lang.lang_config == 'en' else False 160 | add_lang = lang.add_lang 161 | lt = lang.lang 162 | 163 | def bitmapFromBase64( base64_str ): 164 | try: 165 | return wx.Bitmap( PyEmbeddedImage(base64_str).GetImage() ); 166 | except Exception as e: 167 | log.log("bitmapFromBase64 wrong for:", e , base64_str[:20] ) 168 | return wx.Bitmap( PyEmbeddedImage(image_mountain.img).GetImage() ); 169 | 170 | def boolFromStr( s ): 171 | if ( s == 'True' ): return True 172 | return False 173 | 174 | ########### keyboard basic information 175 | RawKeyMap=[ 176 | ('esc',53,'Esc'), 177 | 178 | ('f1',122), 179 | ('f2',120), 180 | ('f3',99), 181 | ('f4',118), 182 | ('f5',96), 183 | ('f6',97), 184 | ('f7',98), 185 | ('f8',100), 186 | ('f9',101), 187 | ('f10',109), 188 | ('f11',103), 189 | ('f12',111), 190 | ('f13',0x69), 191 | ('f14',0x6b), 192 | ('f15',0x71), 193 | ('f16',0x6a), 194 | ('f18',0x4f), 195 | ('f19',0x50), 196 | ('f20',0x5a), 197 | ('help',0x72), 198 | ('function',0x3f), 199 | 200 | 201 | ('1',18,'1 !'), 202 | ('2',19,'2 @'), 203 | ('3',20,'3 #'), 204 | ('4',21,'4 $'), 205 | ('5',23,'5 %'), 206 | ('6',22,'6 ^'), 207 | ('7',26,'7 &&'), 208 | ('8',28,'8 *'), 209 | ('9',25,'9 ('), 210 | ('0',29,'0 )'), 211 | 212 | ('a',0), 213 | ('b',11), 214 | ('c',8), 215 | ('d',2), 216 | ('e',14), 217 | ('f',3), 218 | ('g',5), 219 | ('h',4), 220 | ('i',34), 221 | ('j',38), 222 | ('k',40), 223 | ('l',37), 224 | ('m',46), 225 | ('n',45), 226 | ('o',31), 227 | ('p',35), 228 | ('q',12,'REC'), 229 | ('r',15), 230 | ('s',1), 231 | ('t',17), 232 | ('u',32), 233 | ('v',9,'VIM'), 234 | ('w',13), 235 | ('x',7), 236 | ('y',16), 237 | ('z',6), 238 | 239 | 240 | ('`',50,'` ~',), 241 | ('-',27,'- _'), 242 | ('=',24,'= +'), 243 | ('backspace',51,'Backspace'), 244 | 245 | ('tab',48,'Tab'), 246 | ('[',33,"[ {"), 247 | (']',30,"] }"), 248 | ('\\',42,"\\ |"), 249 | 250 | ('caps lock',57,'CapsLock',), 251 | ('caps lock_up',255,'CapsLock'), 252 | (';',41,'; :'), 253 | ("'",39,"' \""), 254 | ('return', 36,"Enter"), 255 | ('enter', 76,"Enter"), 256 | 257 | ('left shift',56,"Shift"), 258 | (',',43,', <'), 259 | ('.',47,'. >'), 260 | ('/',44,'/ ?'), 261 | ('right shift',60,"Shift"), 262 | 263 | ('left ctrl',59,'Ctrl'), 264 | ('left cmd',55,'Command'), 265 | ('left alt',58,'Option',), 266 | ('space',49,'Space'), 267 | ('right alt',61,'Option'), 268 | ('right cmd',54,'Command',), 269 | ('menu',110,'Menu'), 270 | ('right ctrl',62,'Ctrl'), 271 | 272 | ('insert',114,'Insert'), 273 | ('delete',117,'Delete'), 274 | ('home',115,'Home'), 275 | ('end',119,'End'), 276 | ('page up',116,'PageUp'), 277 | ('page down',121,'PageDown'), 278 | 279 | ('left',123,'←'), 280 | ('right',124,'→'), 281 | ('up',126,'↑'), 282 | ('down',125,'↓'), 283 | 284 | ('volume up',0x48,'Volume Up'), 285 | ('volume down',0x49,'Volume Down'), 286 | ('volume mute',0x4a,'Volume Mute'), 287 | ('print screen',105,'Print Screen'), 288 | ('unicode',555,'Unicode'), 289 | ('',-1,''), 290 | ] 291 | 292 | Key2Code = {} 293 | Code2Key = {} 294 | Key2Name = {} 295 | Name2Key = {} 296 | 297 | ######## rewrite Key2Code and KeyNameMap 298 | for value in RawKeyMap: 299 | Key2Code[ value[0] ] = value[1] 300 | Code2Key[ value[1] ] = value[0] 301 | Key2Code[ value[0] ] = value[1] 302 | if len(value) > 2 : 303 | Key2Name[ value[0] ] = value[2] 304 | Key2Name[ value[0] ] = value[2] 305 | Name2Key[ value[2] ] = value[0] 306 | else: 307 | Key2Name[ value[0] ] = value[0] 308 | Name2Key[ value[0] ] = value[0] 309 | pass 310 | pass 311 | 312 | def GetKeyText(key): 313 | if key in Key2Name: return Key2Name[key] 314 | return key 315 | 316 | ##### simulate key events with fake scancode 317 | #OUTPUT_SOURCE = CGEventSourceCreate(kCGEventSourceStateHIDSystemState) 318 | Masks = { 319 | 'base' : kCGEventFlagMaskNonCoalesced ,#0x100 ,base mask 320 | 'caps lock' : kCGEventFlagMaskAlphaShift ,#0x10000 321 | 'shift' : kCGEventFlagMaskShift ,#0x20000 322 | 'left shift' : kCGEventFlagMaskShift ,#0x20000 323 | 'right shift' : kCGEventFlagMaskShift ,#0x20000 324 | 'ctrl' : kCGEventFlagMaskControl ,#0x40000 325 | 'left ctrl' : kCGEventFlagMaskControl ,#0x40000 326 | 'right ctrl' : kCGEventFlagMaskControl ,#0x40000 327 | 'alt' : kCGEventFlagMaskAlternate ,#0x80000 328 | 'left alt' : kCGEventFlagMaskAlternate ,#0x80000 329 | 'right alt' : kCGEventFlagMaskAlternate ,#0x80000 330 | 'cmd' : kCGEventFlagMaskCommand ,#0x100000 331 | 'left cmd' : kCGEventFlagMaskCommand ,#0x100000 332 | 'right cmd' : kCGEventFlagMaskCommand ,#0x100000 333 | #'num lock' : kCGEventFlagMaskNumericPad ,#0x200000 334 | 'help' : kCGEventFlagMaskHelp ,#0x400000 335 | 'fn' : kCGEventFlagMaskSecondaryFn ,#0x800000 336 | # f1 f2 f3... #0x800100 337 | 'revised' : 0x1000000, # 338 | 'replay' : 0x2000000, # 339 | 'final' : 0x4000000, # 340 | 'unicode' : 0x8000000, # 341 | } 342 | RevisedMask = Masks['revised'] 343 | ReplayMask = Masks['replay'] 344 | FinalMask = Masks['final'] 345 | UnicodeMask = Masks['unicode'] 346 | 347 | M_B = Masks['base'] 348 | M_R = Masks['revised'] 349 | M_P = Masks['replay'] 350 | M_S = Masks['left shift'] 351 | M_A = Masks['left alt'] 352 | M_C = Masks['left ctrl'] 353 | M_M = Masks['left cmd'] 354 | M_F = Masks['final'] 355 | 356 | INFO['CF'] = Masks['base'] 357 | INFO['RCF'] = Masks['base'] 358 | INFO['EVCF'] = 0x0 359 | 360 | ScanCodeRevised = 222 361 | ScanCodeReplay = 223 362 | ScanCodeFinal = 224 363 | 364 | def type_unicode(character): 365 | # Key down 366 | event = CGEventCreateKeyboardEvent(None, 0, True) 367 | CGEventSetFlags(event, UnicodeMask|M_B ) 368 | CGEventKeyboardSetUnicodeString(event, len(character.encode('utf-16-le')) // 2, character) 369 | CGEventPost(kCGSessionEventTap, event ) 370 | # Key up 371 | event = CGEventCreateKeyboardEvent(None, 0, False) 372 | CGEventSetFlags(event, UnicodeMask|M_B ) 373 | CGEventKeyboardSetUnicodeString(event, len(character.encode('utf-16-le')) // 2, character) 374 | CGEventPost(kCGSessionEventTap, event ) 375 | pass 376 | 377 | INFO['covering'] = False 378 | 379 | class GeeKeyBoard: 380 | def __init__(self): 381 | pass 382 | 383 | def setKeyEventDelay(self,delay): 384 | pass 385 | 386 | def coverKey(self): 387 | for key in ModifierKeys: 388 | if INFO['RCF'] & Masks[key]: 389 | #print('cover',key) 390 | INFO['covering'] = True 391 | INFO['CF']=INFO['CF']&~Masks[key] 392 | pass 393 | 394 | def recoverKey(self): 395 | for key in ModifierKeys: 396 | if INFO['RCF'] & Masks[key]: 397 | #print('recover',key) 398 | INFO['CF']=INFO['CF']|Masks[key] 399 | INFO['covering'] = False 400 | pass 401 | 402 | def keyPress(self, key, flags=RevisedMask ): 403 | code = Key2Code.get(key,key) 404 | evt = CGEventCreateKeyboardEvent(None,code,True) 405 | CGEventSetFlags(evt, flags|INFO['CF']|INFO['EVCF'] ) 406 | CGEventPost(kCGSessionEventTap,evt ) 407 | pass 408 | 409 | def keyRelease(self, key, flags=RevisedMask ): 410 | code = Key2Code.get(key,key) 411 | evt = CGEventCreateKeyboardEvent(None,code,False) 412 | CGEventSetFlags(evt, flags|INFO['CF']|INFO['EVCF'] ) 413 | CGEventPost(kCGSessionEventTap,evt ) 414 | pass 415 | 416 | def keyStroke(self, key, flags=RevisedMask): 417 | code = Key2Code.get(key,key) 418 | self.keyPress(code, flags) 419 | self.keyRelease(code, flags) 420 | pass 421 | 422 | def repeatedNumber(self,num): 423 | if num == '' : return 1 424 | res = 1 425 | try: res = int(num) 426 | except: pass 427 | return res 428 | 429 | def keySend(self,key,keytype = 'key down',repeated = 1, flags= RevisedMask ): 430 | try: 431 | code = Key2Code.get(key,key) 432 | repeated = self.repeatedNumber(repeated ) 433 | if code< 0: return 434 | if keytype in ('key down','d'): 435 | for i in range( repeated -1 ): 436 | self.keyStroke(code, flags) 437 | pass 438 | self.keyPress(key, flags) 439 | else: 440 | self.keyRelease(key, flags) 441 | pass 442 | except Exception as e: 443 | log.log('keySend error for:',e) 444 | de 445 | pass 446 | pass 447 | 448 | def textSend(self,text): 449 | try: 450 | for letter in text: type_unicode(letter) 451 | except Exception as e: 452 | log.log('textSend error for:',e) 453 | DE() 454 | pass 455 | 456 | pass 457 | 458 | ############################################################## 459 | ############################################################## 460 | ### map and choices initialize 461 | FunctionKeys = ['f1','f2','f3','f4','f5','f6','f7','f8','f9','f10','f10','f11','f12'] 462 | 463 | NumberKeys = ['0','1','2','3','4','5','6','7','8','9'] 464 | 465 | CharKeys = ['a','b','c','d','e','f','g', 466 | 'h','i','j','k','l','m','n', 467 | 'o','p','q', 'r','s','t', 468 | 'u','v','w', 'x','y','z'] 469 | SymbolKeys = ['`','-','=','[',']','\\',';','\'',',','.','/',] 470 | 471 | SpecKeys = [',','.','/','\\','-','=','(',')','!','@','#','$','%','^','&','*','=','`',] 472 | 473 | StringKeys = NumberKeys + CharKeys + SymbolKeys 474 | 475 | 476 | ModifierKeys = [ 'left shift','left ctrl', 477 | 'left cmd','left alt','right alt', 478 | 'right cmd','right ctrl','right shift'] 479 | 480 | MenuKeys_1 = [ 'tab','caps lock','menu', ] + ModifierKeys 481 | 482 | MenuKeys = [ 'esc' ] + MenuKeys_1 483 | 484 | MenuKeysText = [ Key2Name[v] for v in MenuKeys ] 485 | 486 | EditKeys = [ '','left','down','up','right','home','end','return', 487 | 'page up','page down','backspace','delete','insert','print screen', 488 | 'volume up','volume down','volume mute', #'num lock', 489 | 'left shift','left ctrl','left alt','left cmd','tab','caps lock', 490 | 'right shift','right ctrl','right alt','right cmd', 491 | ] 492 | EditKeysText = [ Key2Name[v] for v in EditKeys ] 493 | 494 | 495 | GlobalMaps = {} 496 | GlobalMaps['macro'] = { 497 | "t":"", 498 | "y":"copy:0:_right cmd:_c:c:right cmd", 499 | "p":"paste:0:_right cmd:_v:v:right cmd", 500 | "f2":"save:0:_right cmd:_s:s:right cmd", 501 | "":"", 502 | } 503 | GlobalMaps['edit'] = { 504 | '-':'volume down','=':'volume up','backspace':'volume mute', 505 | "h":"left","j":"down","k":"up","l":'right', 506 | "n":"down", 507 | "p":"up", 508 | "b":"left", 509 | "f":"right", 510 | "a":"home", 511 | "e":"end", 512 | '[':'page up', 513 | ']':'page down', 514 | } 515 | GlobalMaps['text'] = { 516 | "":"", 517 | } 518 | GlobalMaps['function'] = { 519 | '':'', 520 | } 521 | 522 | GlobalMaps['keytype'] = { 523 | 'y':'macro', 'p':'macro', 'o':'macro', 'u':'macro', 'i':'macro','w':'macro','b':'macro', 524 | 525 | 'f2':'macro', 526 | 527 | '0':'edit', 528 | '[':'edit', 529 | ']':'edit', 530 | '':'', 531 | } 532 | 533 | GlobalMaps['vim'] = { 534 | ### shift_ should ahead of ctrl_ 535 | 'esc':'esc', 536 | 'space':'right', 537 | 'backspace':'left', 538 | 'return':'return', 539 | 'h':'left', 540 | 'j':'down', 541 | 'k':'up', 542 | 'l':'right', 543 | '0':'home line', 544 | 'shift_\\':'jump bar', 545 | 'shift_6':'home block', 546 | 'shift_4':'end', 547 | 548 | "shift_'":'register', 549 | 'shift_;':'command', 550 | 'q':'record', 551 | 'shift_2':'execute', 552 | 553 | 'i':'insert', 554 | 'shift_i':'insert begin', 555 | 'a':'append', 556 | 'shift_a':'append end', 557 | 'o':'insert next line', 558 | 'shift_o':'insert prev line', 559 | 560 | 's':'change', 561 | 'c__w':'change word', 562 | 'c__e':'change word', 563 | 'c__b':'change word back', 564 | 'shift_s':'change line', 565 | 'c__c':'change line', 566 | 'c__0':'change begin', 567 | 'c__shift_6':'change begin', 568 | 'shift_c':'change end', 569 | 'c__shift_4':'change end', 570 | 571 | #'r':'replace char', ## 572 | #'shift_r':'replace mode', 573 | 574 | 'y':'copy', 575 | 'y__w':'copy word', 576 | 'y__e':'copy word', 577 | 'y__b':'copy word back', 578 | 'y__y':'copy line', 579 | 'shift_y':'copy line', 580 | 'y__shift_6':'copy begin', 581 | 'y__0':'copy begin', 582 | 'y__shift_4':'copy end', 583 | 584 | 'p':'paste', 585 | 'shift_p':'paste prev', # if paste line paste on privous 586 | 587 | 'x':'x cut', 588 | 'shift_x':'x cut previous', 589 | 590 | 'd':'cut', # only function in visual mode 591 | 'd__d':'cut line', 592 | 'd__w':'cut word', 593 | 'd__e':'cut word', 594 | 'd__b':'cut word back', 595 | 'd__0':'cut begin', 596 | 'd__shift_6':'cut begin', 597 | 'shift_d':'cut end', # only function in visual mode 598 | 'd__shift_4':'cut end', 599 | 600 | 'u':'undo', 601 | 'shift_u':'redo', 602 | 'shift_j':'merge line', 603 | 604 | 'v':'visual mode', 605 | 'shift_v':'line visual mode', 606 | 'w':'next word', 607 | 'e':'end word', 608 | 'b':'prev word', 609 | 'shift_[':'prev para', 610 | 'shift_]':'next para', 611 | 612 | 'g__g':'jump head', 613 | 'shift_g':'jump tail', 614 | 615 | 'y__g__g':'copy head', 616 | 'y__shift_g':'copy tail', 617 | 'd__g__g':'cut head', 618 | 'd__shift_g':'cut tail', 619 | 620 | #'f2':'save', 621 | '/':'find', 622 | 'shift_8':'find current', 623 | 624 | 'z__z':'caret center', 625 | # 'z__t':'caret top', 626 | # 'z__b':'caret bottom', 627 | 628 | 'ctrl_r':'redo', 629 | 'ctrl_f':'page down', 630 | 'ctrl_b':'page up', 631 | } 632 | 633 | GlobalMaps['vim_register'] = { 634 | '':'', #(content) 'k':'^xxxx' for pure text or 'k':'^:0:xxxxx' for operation record 635 | } 636 | 637 | vim_move_count ={ 638 | 'left' : -1, 639 | 'right': 1, 640 | 'up' :-40, 641 | 'down' : 40, 642 | 'home' :-20, 643 | 'end' : 20, 644 | 'word' : 6, 645 | 'back' : -6, 646 | } 647 | 648 | GlobalMaps['layout'] = {'':'',} 649 | 650 | ToolTipKeys = {'space','q','v'} 651 | 652 | def GetMap( cat, key): 653 | if not cat in GlobalMaps: return '' 654 | if not key in GlobalMaps[cat]: return '' 655 | return GlobalMaps[cat][key] 656 | 657 | def SetMap( cat, key, value): 658 | if not cat in GlobalMaps: return False 659 | GlobalMaps[ cat ][ key ] = value 660 | return True 661 | 662 | Color_Map ={ 663 | 664 | 'layout_1':'#d2efe8', 665 | 'layout_2':'#d3eee7', 666 | 'layout_3':'#aee0d4', 667 | 'layout_4':'#90d5c4', 668 | 'layout_5':'#76cbb7', 669 | 'layout_6':'#59c0a7', #deepskyblue 670 | 'layout_selected':'#87cefa', 671 | 672 | 'geekey' : '#c0f616', 673 | 'rec': '#cb5bff', 674 | 'space' : '#cfefa1', 675 | 676 | 'menu_key' : '#66cdef', 677 | 678 | 'macro_key':'#D8BFD8', 679 | 'macro_button':'#CD96CD', 680 | 681 | 'text_key':'#D8BFff', 682 | 'text_button':'#CD96ff', 683 | 684 | 'edit_key':'#BFEFFF', 685 | 'edit_button':'#87cefa', 686 | 687 | 'function_key':'#9Fb6cd', 688 | 'function_button':'#9bcd9b', 689 | 690 | 'plain_key' : '#9Fb6cd', 691 | 692 | 'candidate_texts':'#9Fb6cd', 693 | 'candidate_selected':'#c0ff3e', 694 | 695 | 'vim disable':'#ff6f5d', 696 | 'vim normal':'#ebffb3', 697 | 'vim insert':'#b3baff', 698 | 'vim visual':'#eab3ff', 699 | 'vim text':'#555555', 700 | 'keyboard_panel':'#4a708b', 701 | 'bottom_panel':'#698b69', 702 | '':'', 703 | } 704 | GlobalMaps['color'] = Color_Map 705 | def GetColorMap(key,default='plain_key'): return GlobalMaps['color'].get(key,GlobalMaps['color'][default] ) 706 | 707 | 708 | def regesterGeeKey(action=True): 709 | if action: # add regedit 710 | pass 711 | else: 712 | pass 713 | win32api.RegCloseKey(key) 714 | pass 715 | 716 | class GeeMouse: 717 | 718 | #def buttonEvent(self, pos=None, buttonStr='left' ): 719 | def buttonEvent(self, evttype, pos=None, wheel=0 ): 720 | if evttype in (kCGEventLeftMouseDown, 721 | kCGEventLeftMouseUp): 722 | evt = CGEventCreateMouseEvent(None,evttype,pos,kCGMouseButtonLeft) 723 | CGEventPost(kCGSessionEventTap,evt ) 724 | pass 725 | elif evttype in (kCGEventRightMouseDown, 726 | kCGEventRightMouseUp): 727 | evt = CGEventCreateMouseEvent(None,evttype,pos,kCGMouseButtonRight) 728 | CGEventPost(kCGSessionEventTap,evt ) 729 | elif evttype == kCGEventScrollWheel: 730 | evt = CGEventCreateScrollWheelEvent(None,kCGScrollEventUnitLine,1,wheel) 731 | CGEventPost(kCGSessionEventTap,evt ) 732 | pass 733 | 734 | pass 735 | 736 | geeKeyboard = GeeKeyBoard() 737 | geeMouse = GeeMouse() 738 | 739 | KeyStroke = lambda Key,flags=0x0,eflags=RevisedMask: geeKeyboard.keyStroke(Key,flags|eflags) 740 | KeyPress = lambda Key,flags=0x0,eflags=RevisedMask: geeKeyboard.keyPress(Key,flags|eflags) 741 | KeyRelease = lambda Key,flags=0x0,eflags=RevisedMask: geeKeyboard.keyRelease(Key,flags|eflags) 742 | 743 | DelayKeyStroke = lambda t,Key,flags=0x0,eflags=RevisedMask: WxCallLater(t,geeKeyboard.keyStroke,Key,flags|eflags) 744 | DelayKeyPress = lambda t,Key,flags=0x0,eflags=RevisedMask: WxCallLater(t,geeKeyboard.keyPress,Key,flags|eflags) 745 | DelayKeyRelease = lambda t,Key,flags=0x0,eflags=RevisedMask: WxCallLater(t,geeKeyboard.keyRelease,Key,flags|eflags) 746 | 747 | KeySend = lambda key,keytype='key down',repeated=1, flags=RevisedMask: geeKeyboard.keySend(key,keytype,repeated,flags) 748 | SetKeyDelay = lambda delay: geeKeyboard.setKeyEventDelay(delay) 749 | TextSend = lambda txt: geeKeyboard.textSend( txt ) 750 | 751 | GlobalMaps['menu'] = {} 752 | 753 | mouseEventTypeMap = { 754 | kCGEventLeftMouseDown:'ld', 755 | kCGEventLeftMouseUp:'lu', 756 | kCGEventRightMouseDown:'rd', 757 | kCGEventRightMouseUp:'ru', 758 | kCGEventScrollWheel:'w', 759 | } 760 | 761 | rmouseEventTypeMap = dict( map( lambda ele:(ele[1],ele[0]), mouseEventTypeMap.items() ) ) 762 | 763 | def runAsAdmin(argv=None, debug=False): 764 | return False 765 | 766 | class UpdateDialog( wx.Dialog): 767 | 768 | def __init__(self,cont,*args,**kwargs): 769 | self.textPanel = None 770 | self.contPanel = None 771 | self.sizer = None 772 | self.button = {} 773 | self.H = 30; 774 | self.W = 450; self.tH = 60; self.bH = 50; 775 | self.yP = 20; self.xP = 20; 776 | 777 | wx.Dialog.__init__(self,*args,**kwargs) 778 | self.SetTitle( _('_new_version_available') ) 779 | self.sizer = wx.BoxSizer(wx.VERTICAL) 780 | 781 | self.textPanel = wx.Panel(self,size=(self.W, self.tH) ) 782 | self.bottomPanel = wx.Panel( self, size=(self.W, self.bH) ) 783 | self.bottomPanel.SetBackgroundColour( "#E5E5E5" ) 784 | 785 | self.sizer.Add( self.textPanel ) 786 | self.sizer.Add( self.bottomPanel ) 787 | 788 | text = wx.StaticText( self.textPanel, label='test', pos=(self.yP, self.xP), size=(self.W-20, self.tH-20 ), style= wx.ALIGN_CENTER) 789 | 790 | self.button['update'] = wx.Button(self.bottomPanel, label= _("Update"),pos=(self.W/2-60,self.H/3),size=(80,self.H ) ) 791 | self.button['cancel'] = wx.Button(self.bottomPanel, label= _("Cancel"),pos=(self.W/2+40,self.H/3),size=(80,self.H) ) 792 | 793 | self.SetSizerAndFit( self.sizer ) 794 | pass 795 | pass 796 | 797 | def rgbToHex(r,g,b): 798 | return "{0:02x}{1:02x}{2:02x}".format(r,g,b) 799 | 800 | def hexToRgb(h): 801 | if h[0] != '#': raise Exception('hexToRgb failed for hex string not start with #') 802 | if len(h)<4: raise Exception('hexToRgb failed for hex string shorter than 4bits') 803 | if len(h)<7: h += h[1:4] 804 | return tuple( int(h[i:i+2],16) for i in(1,3,5) ) 805 | 806 | def hexReverse(h): 807 | rgb = hexToRgb( h ) 808 | return rgbToHex( 255-rgb[0],255-rgb[1], 255-rgb[2] ) 809 | 810 | def getCbText(): 811 | #print('try get cb') 812 | txt = wx.TextDataObject() 813 | while True: 814 | time.sleep(0.01) 815 | try: 816 | if not wx.TheClipboard.IsOpened(): 817 | if wx.TheClipboard.Open(): 818 | wx.TheClipboard.GetData( txt ) 819 | wx.TheClipboard.Close() 820 | break 821 | pass 822 | #print('no data get wait and try again') 823 | except Exception as e: 824 | DE() 825 | pass 826 | time.sleep(0.01) 827 | pass 828 | return txt.GetText() 829 | 830 | def setCbText(txt): 831 | while True: 832 | time.sleep(0.01) 833 | try: 834 | if not wx.TheClipboard.IsOpened(): 835 | if wx.TheClipboard.Open(): 836 | #print('set cb>>>',[txt,] ) 837 | wx.TheClipboard.Clear() 838 | success = wx.TheClipboard.SetData( wx.TextDataObject(txt) ) 839 | wx.TheClipboard.Close() 840 | #print('set result =',success) 841 | break 842 | #print('no data set wait and try again') 843 | except Exception as e: 844 | DE() 845 | pass 846 | time.sleep(0.01) 847 | return 848 | 849 | def SetRegister(register, txt): 850 | if not txt: return None 851 | #print('set register {0}:{1}'.format(register,txt) ) 852 | 853 | if register[:6] == 'shift_': 854 | if register[7:] in CharKeys: 855 | # ignore the first ^ or < 856 | txt = GetMap('vim_register',register) + txt[1:] 857 | pass 858 | pass 859 | 860 | return SetMap('vim_register',register,txt ) 861 | 862 | def GetRegister(register): 863 | if not register: return None#do nothing 864 | res = GetMap('vim_register',register ) 865 | if not res: return None 866 | #print(type(res),res ) 867 | return res 868 | 869 | 870 | mapping = {'\a': r'\a', '\b': r'\b', '\f': r'\f', '\n': r'\n', 871 | '\r': r'\r', '\t': r'\t', '\v': r'\v'} 872 | 873 | def escape(astr): 874 | for char, escaped in mapping.items(): 875 | astr = astr.replace(char, escaped) 876 | return astr 877 | 878 | UpperKeys = { #Key uppper chr, ie. 1 -> ! 879 | '`':'~', 880 | '1':'!','2':'@','3':'#','4':'$','5':'%','6':'^','7':'&','8':'*','9':'(','0':')', 881 | '-':'_','=':'+', 882 | '[':'{',']':'}','\\':'|', 883 | ';':':','\'':'"', 884 | ',':'<','.':'>', 885 | } 886 | 887 | LowerKeys = { v:k for k,v in UpperKeys.items() } 888 | 889 | def upper(ch): 890 | return UpperKeys.get(ch) or ch.upper() 891 | 892 | def lower(ch): 893 | return LowerKeys.get(ch) or ch.lower() 894 | 895 | KeyDisplays = { 'space':' ', } 896 | def display(ch): 897 | if ch in KeyDisplays: return KeyDisplays.get(ch) 898 | return ch 899 | 900 | def vim_search_scope(astr): 901 | num = '' 902 | while astr and astr[-1] in NumberKeys: 903 | num = astr[-1]+num 904 | astr = astr[:-1] 905 | pass 906 | if astr and astr[-1] in ('-','+'): 907 | d = astr[-1] 908 | astr = astr[:-1] 909 | else: 910 | d = '' 911 | pass 912 | if not d and num and astr: return False 913 | if not d and num: return [int(num),0] 914 | if num == '': num = 0 915 | else: num = int(d+num) 916 | 917 | return [astr,num] 918 | 919 | import ctypes, objc 920 | _objc = ctypes.PyDLL(objc._objc.__file__) 921 | 922 | # PyObject *PyObjCObject_New(id objc_object, int flags, int retain) 923 | _objc.PyObjCObject_New.restype = ctypes.py_object 924 | _objc.PyObjCObject_New.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] 925 | 926 | def objc_object(id): 927 | return _objc.PyObjCObject_New(id, 0, 1) 928 | 929 | def SetFullScreenCapable(frame): 930 | frameobj = objc_object(frame.GetHandle()) 931 | 932 | NSWindowCollectionBehaviorFullScreenPrimary = 1<<7 933 | window = frameobj.window() 934 | newBehavior = window.collectionBehavior() | NSWindowCollectionBehaviorFullScreenPrimary 935 | window.setCollectionBehavior_(newBehavior) 936 | 937 | class windowManagement: 938 | def getActiveScreenSize(self): 939 | s = NSScreen.mainScreen().frame().size 940 | return (0,0,s.width, s.height) 941 | 942 | def getActiveAppPID(self): 943 | workspace = NSWorkspace.sharedWorkspace() 944 | app = workspace.frontmostApplication() 945 | pid = app.processIdentifier() 946 | return pid 947 | 948 | def getActiveWindow(self): 949 | workspace = NSWorkspace.sharedWorkspace() 950 | app = workspace.frontmostApplication() 951 | pid = app.processIdentifier() 952 | options = kCGWindowListOptionOnScreenOnly 953 | windowList = CGWindowListCopyWindowInfo(options, kCGNullWindowID) 954 | rect = None 955 | for window in windowList: 956 | if window['kCGWindowOwnerPID'] == pid : 957 | r = window['kCGWindowBounds'] 958 | rect = (r['X'],r['Y'],r['Width'],r['Height'] ) 959 | break 960 | pass 961 | return (rect,app) 962 | 963 | pass 964 | 965 | geeWindow = windowManagement() 966 | 967 | def keyboardCallBack(proxy, evttype, evt, refcon): 968 | try: 969 | KeyCode = CGEventGetIntegerValueField(evt,kCGKeyboardEventKeycode) 970 | Key = Code2Key.get(KeyCode, KeyCode ) 971 | if Key == 'caps lock_up': Key = 'caps lock' 972 | AutoKey = CGEventGetIntegerValueField(evt,kCGKeyboardEventAutorepeat) 973 | Flags = CGEventGetFlags(evt) 974 | EvtScanCode = 0 975 | if Flags&RevisedMask: EvtScanCode = ScanCodeRevised# 976 | elif Flags&ReplayMask : EvtScanCode = ScanCodeReplay# 977 | elif Flags&FinalMask : EvtScanCode = ScanCodeFinal# 978 | elif Flags&UnicodeMask: return evt 979 | EvtType = 'key down' if evttype == 10 else 'key up' 980 | mask = Masks.get(Key,0x0) 981 | if mask: 982 | if mask&Flags: 983 | EvtType = 'key down' 984 | INFO['CF'] = INFO['CF']|mask 985 | if EvtScanCode == 0: INFO['RCF'] = INFO['RCF']|mask 986 | else: 987 | INFO['CF'] = INFO['CF']&~mask 988 | if EvtScanCode == 0: INFO['RCF'] = INFO['RCF']&~mask 989 | pass 990 | pass 991 | 992 | if EvtScanCode == ScanCodeFinal: return evt 993 | 994 | #print(EvtType,Key,'Flags:',hex(Flags),'CF:',hex(INFO['CF']),'RawCF:',hex(INFO['RCF']),EvtScanCode) 995 | #print(EvtType,Key,'Flags:',hex(Flags&M_S),EvtScanCode ) 996 | 997 | if INFO['GEEKEY'].getConfig('printkeyevent') == 'True': 998 | log.log('{1} {0} ScanCode: {2}'.format(EvtType,Key,EvtScanCode), ) 999 | pass 1000 | 1001 | covering = INFO['covering'] 1002 | if not INFO['GEEKEY'].vim.vim_on: covering = True 1003 | if INFO["GEEKEY"].vim.vim_on and INFO['GEEKEY'].vim.insert_mode: 1004 | covering = True 1005 | 1006 | if not covering: geeKeyboard.coverKey() 1007 | res = INFO['GEEKEY'].OnKeyboardEvent(Key,EvtType,EvtScanCode) 1008 | if not covering: geeKeyboard.recoverKey() 1009 | 1010 | if res: return evt 1011 | return None 1012 | except Exception as e: 1013 | DE() 1014 | pass 1015 | return evt 1016 | 1017 | 1018 | 1019 | def mouseCallBack( proxy, evttype, evt, refcon): 1020 | try: 1021 | EvtType = CGEventGetType(evt) 1022 | EvtPosition = CGEventGetLocation(evt) 1023 | EvtPosition = ("%.2f"%EvtPosition.x,"%.2f"%EvtPosition.y) 1024 | EvtWheel = CGEventGetIntegerValueField(evt,kCGScrollWheelEventDeltaAxis1) 1025 | 1026 | res = INFO['GEEKEY'].OnMouseEvent(EvtType,EvtPosition,EvtWheel) 1027 | if res: return evt 1028 | return None 1029 | 1030 | except Exception as e: 1031 | DE() 1032 | pass 1033 | 1034 | return evt 1035 | 1036 | class Listener: 1037 | def __init__(self): 1038 | self.pool = NSAutoreleasePool.alloc().init() 1039 | KeyEventsMask= CGEventMaskBit(kCGEventKeyDown)| CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged ) 1040 | 1041 | KeyEventsMask= CGEventMaskBit(kCGEventKeyDown)| CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged ) 1042 | MouseEventsMask = CGEventMaskBit(kCGEventLeftMouseUp)| CGEventMaskBit(kCGEventLeftMouseDown)| CGEventMaskBit(kCGEventRightMouseUp)|CGEventMaskBit(kCGEventRightMouseDown)| CGEventMaskBit(kCGEventScrollWheel) 1043 | 1044 | self.keyboardTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, KeyEventsMask, keyboardCallBack, None ) 1045 | self.mouseTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, MouseEventsMask, mouseCallBack, None ) 1046 | 1047 | if self.keyboardTap: 1048 | self.keyboardSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, self.keyboardTap,0) 1049 | CFRunLoopAddSource( CFRunLoopGetCurrent(), self.keyboardSource, kCFRunLoopCommonModes); 1050 | else: 1051 | log.log('Can not make keyboard hook to system') 1052 | raise Exception('Can not make keyboard hook to system') 1053 | if self.mouseTap: 1054 | self.mouseSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, self.mouseTap,0) 1055 | CFRunLoopAddSource( CFRunLoopGetCurrent(), self.mouseSource, kCFRunLoopCommonModes); 1056 | else: 1057 | log.log('Can not make mouse hook to system') 1058 | raise Exception('Can not make mouse hook to system') 1059 | 1060 | self.timer = None 1061 | self.hook() 1062 | pass 1063 | 1064 | def hook(self): 1065 | if self.keyboardTap: 1066 | CGEventTapEnable(self.keyboardTap,True) 1067 | if self.mouseTap: 1068 | CGEventTapEnable(self.mouseTap,True) 1069 | if self.timer: self.timer.Stop() 1070 | self.timer = WxCallLater( 5, self.hook ) 1071 | 1072 | def exit(self): 1073 | if self.keyboardTap: 1074 | CFRelease(self.keyboardTap) 1075 | CFRelease(self.keyboardSource) 1076 | if self.mouseTap: 1077 | CFRelease(self.mouseTap) 1078 | CFRelease(self.mouseSource) 1079 | pass 1080 | #self.pool.release() 1081 | pass 1082 | 1083 | pass 1084 | 1085 | -------------------------------------------------------------------------------- /vim_oper.py: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------