codekingpro/portable-devtools
114k
1# A general purpose MFC CCtrlView view that uses Scintilla.2 3import array4import os5import re6import string7import struct8import sys9 10import __main__ # for attribute lookup11import afxres12import win32con13import win32ui14from pywin.mfc import dialog, docview15 16from . import IDLEenvironment # IDLE emulation.17from . import bindings, control, keycodes, scintillacon18 19PRINTDLGORD = 153820IDC_PRINT_MAG_EDIT = 101021EM_FORMATRANGE = win32con.WM_USER + 5722 23wordbreaks = "._" + string.ascii_uppercase + string.ascii_lowercase + string.digits24 25patImport = re.compile("import (?P<name>.*)")26 27_event_commands = [28 # File menu29 "win32ui.ID_FILE_LOCATE",30 "win32ui.ID_FILE_CHECK",31 "afxres.ID_FILE_CLOSE",32 "afxres.ID_FILE_NEW",33 "afxres.ID_FILE_OPEN",34 "afxres.ID_FILE_SAVE",35 "afxres.ID_FILE_SAVE_AS",36 "win32ui.ID_FILE_SAVE_ALL",37 # Edit menu38 "afxres.ID_EDIT_UNDO",39 "afxres.ID_EDIT_REDO",40 "afxres.ID_EDIT_CUT",41 "afxres.ID_EDIT_COPY",42 "afxres.ID_EDIT_PASTE",43 "afxres.ID_EDIT_SELECT_ALL",44 "afxres.ID_EDIT_FIND",45 "afxres.ID_EDIT_REPEAT",46 "afxres.ID_EDIT_REPLACE",47 # View menu48 "win32ui.ID_VIEW_WHITESPACE",49 "win32ui.ID_VIEW_FIXED_FONT",50 "win32ui.ID_VIEW_BROWSE",51 "win32ui.ID_VIEW_INTERACTIVE",52 # Window menu53 "afxres.ID_WINDOW_ARRANGE",54 "afxres.ID_WINDOW_CASCADE",55 "afxres.ID_WINDOW_NEW",56 "afxres.ID_WINDOW_SPLIT",57 "afxres.ID_WINDOW_TILE_HORZ",58 "afxres.ID_WINDOW_TILE_VERT",59 # Others60 "afxres.ID_APP_EXIT",61 "afxres.ID_APP_ABOUT",62]63 64_extra_event_commands = [65 ("EditDelete", afxres.ID_EDIT_CLEAR),66 ("LocateModule", win32ui.ID_FILE_LOCATE),67 ("GotoLine", win32ui.ID_EDIT_GOTO_LINE),68 ("DbgBreakpointToggle", win32ui.IDC_DBG_ADD),69 ("DbgGo", win32ui.IDC_DBG_GO),70 ("DbgStepOver", win32ui.IDC_DBG_STEPOVER),71 ("DbgStep", win32ui.IDC_DBG_STEP),72 ("DbgStepOut", win32ui.IDC_DBG_STEPOUT),73 ("DbgBreakpointClearAll", win32ui.IDC_DBG_CLEAR),74 ("DbgClose", win32ui.IDC_DBG_CLOSE),75]76 77event_commands = []78 79 80def _CreateEvents():81 for name in _event_commands:82 val = eval(name)83 name_parts = name.split("_")[1:]84 name_parts = [p.capitalize() for p in name_parts]85 event = "".join(name_parts)86 event_commands.append((event, val))87 for name, id in _extra_event_commands:88 event_commands.append((name, id))89 90 91_CreateEvents()92del _event_commands93del _extra_event_commands94 95command_reflectors = [96 (win32ui.ID_EDIT_UNDO, win32con.WM_UNDO),97 (win32ui.ID_EDIT_REDO, scintillacon.SCI_REDO),98 (win32ui.ID_EDIT_CUT, win32con.WM_CUT),99 (win32ui.ID_EDIT_COPY, win32con.WM_COPY),100 (win32ui.ID_EDIT_PASTE, win32con.WM_PASTE),101 (win32ui.ID_EDIT_CLEAR, win32con.WM_CLEAR),102 (win32ui.ID_EDIT_SELECT_ALL, scintillacon.SCI_SELECTALL),103]104 105 106def DoBraceMatch(control):107 curPos = control.SCIGetCurrentPos()108 charBefore = " "109 if curPos:110 charBefore = control.SCIGetCharAt(curPos - 1)111 charAt = control.SCIGetCharAt(curPos)112 braceAtPos = braceOpposite = -1113 if charBefore in "[](){}":114 braceAtPos = curPos - 1115 if braceAtPos == -1:116 if charAt in "[](){}":117 braceAtPos = curPos118 if braceAtPos != -1:119 braceOpposite = control.SCIBraceMatch(braceAtPos, 0)120 if braceAtPos != -1 and braceOpposite == -1:121 control.SCIBraceBadHighlight(braceAtPos)122 else:123 # either clear them both or set them both.124 control.SCIBraceHighlight(braceAtPos, braceOpposite)125 126 127def _get_class_attributes(ob):128 # Recurse into base classes looking for attributes129 items = []130 try:131 items = items + dir(ob)132 for i in ob.__bases__:133 for item in _get_class_attributes(i):134 if item not in items:135 items.append(item)136 except AttributeError:137 pass138 return items139 140 141# Supposed to look like an MFC CEditView, but142# also supports IDLE extensions and other source code generic features.143class CScintillaView(docview.CtrlView, control.CScintillaColorEditInterface):144 def __init__(self, doc):145 docview.CtrlView.__init__(146 self,147 doc,148 "Scintilla",149 win32con.WS_CHILD150 | win32con.WS_VSCROLL151 | win32con.WS_HSCROLL152 | win32con.WS_CLIPCHILDREN153 | win32con.WS_VISIBLE,154 )155 self._tabWidth = (156 8 # Mirror of what we send to Scintilla - never change this directly157 )158 self.bAutoCompleteAttributes = 1159 self.bShowCallTips = 1160 self.bMatchBraces = 0 # Editor option will default this to true later!161 self.bindings = bindings.BindingsManager(self)162 163 self.idle = IDLEenvironment.IDLEEditorWindow(self)164 self.idle.IDLEExtension("AutoExpand")165 # SendScintilla is called so frequently it is worth optimizing.166 self.SendScintilla = self._obj_.SendMessage167 168 def _MakeColorizer(self):169 ext = os.path.splitext(self.GetDocument().GetPathName())[1]170 from . import formatter171 172 return formatter.BuiltinPythonSourceFormatter(self, ext)173 174 # def SendScintilla(self, msg, w=0, l=0):175 # return self._obj_.SendMessage(msg, w, l)176 177 def SCISetTabWidth(self, width):178 # I need to remember the tab-width for the AutoIndent extension. This may go.179 self._tabWidth = width180 control.CScintillaEditInterface.SCISetTabWidth(self, width)181 182 def GetTabWidth(self):183 return self._tabWidth184 185 def HookHandlers(self):186 # Create events for all the menu names.187 for name, val in event_commands:188 # handler = lambda id, code, tosend=val, parent=parent: parent.OnCommand(tosend, 0) and 0189 self.bindings.bind(name, None, cid=val)190 191 # Hook commands that do nothing other than send Scintilla messages.192 for command, reflection in command_reflectors:193 handler = (194 lambda id, code, ss=self.SendScintilla, tosend=reflection: ss(tosend)195 and 0196 )197 self.HookCommand(handler, command)198 199 self.HookCommand(self.OnCmdViewWS, win32ui.ID_VIEW_WHITESPACE)200 self.HookCommandUpdate(self.OnUpdateViewWS, win32ui.ID_VIEW_WHITESPACE)201 self.HookCommand(202 self.OnCmdViewIndentationGuides, win32ui.ID_VIEW_INDENTATIONGUIDES203 )204 self.HookCommandUpdate(205 self.OnUpdateViewIndentationGuides, win32ui.ID_VIEW_INDENTATIONGUIDES206 )207 self.HookCommand(self.OnCmdViewRightEdge, win32ui.ID_VIEW_RIGHT_EDGE)208 self.HookCommandUpdate(self.OnUpdateViewRightEdge, win32ui.ID_VIEW_RIGHT_EDGE)209 self.HookCommand(self.OnCmdViewEOL, win32ui.ID_VIEW_EOL)210 self.HookCommandUpdate(self.OnUpdateViewEOL, win32ui.ID_VIEW_EOL)211 self.HookCommand(self.OnCmdViewFixedFont, win32ui.ID_VIEW_FIXED_FONT)212 self.HookCommandUpdate(self.OnUpdateViewFixedFont, win32ui.ID_VIEW_FIXED_FONT)213 self.HookCommand(self.OnCmdFileLocate, win32ui.ID_FILE_LOCATE)214 self.HookCommand(self.OnCmdEditFind, win32ui.ID_EDIT_FIND)215 self.HookCommand(self.OnCmdEditRepeat, win32ui.ID_EDIT_REPEAT)216 self.HookCommand(self.OnCmdEditReplace, win32ui.ID_EDIT_REPLACE)217 self.HookCommand(self.OnCmdGotoLine, win32ui.ID_EDIT_GOTO_LINE)218 self.HookCommand(self.OnFilePrint, afxres.ID_FILE_PRINT)219 self.HookCommand(self.OnFilePrint, afxres.ID_FILE_PRINT_DIRECT)220 self.HookCommand(self.OnFilePrintPreview, win32ui.ID_FILE_PRINT_PREVIEW)221 # Key bindings.222 self.HookMessage(self.OnKeyDown, win32con.WM_KEYDOWN)223 self.HookMessage(self.OnKeyDown, win32con.WM_SYSKEYDOWN)224 # Hook wheeley mouse events225 # self.HookMessage(self.OnMouseWheel, win32con.WM_MOUSEWHEEL)226 self.HookFormatter()227 228 def OnInitialUpdate(self):229 doc = self.GetDocument()230 231 # Enable Unicode232 self.SendScintilla(scintillacon.SCI_SETCODEPAGE, scintillacon.SC_CP_UTF8, 0)233 self.SendScintilla(scintillacon.SCI_SETKEYSUNICODE, 1, 0)234 235 # Create margins236 self.SendScintilla(237 scintillacon.SCI_SETMARGINTYPEN, 1, scintillacon.SC_MARGIN_SYMBOL238 )239 self.SendScintilla(scintillacon.SCI_SETMARGINMASKN, 1, 0xF)240 self.SendScintilla(241 scintillacon.SCI_SETMARGINTYPEN, 2, scintillacon.SC_MARGIN_SYMBOL242 )243 self.SendScintilla(244 scintillacon.SCI_SETMARGINMASKN, 2, scintillacon.SC_MASK_FOLDERS245 )246 self.SendScintilla(scintillacon.SCI_SETMARGINSENSITIVEN, 2, 1)247 248 self.GetDocument().HookViewNotifications(249 self250 ) # is there an MFC way to grab this?251 self.HookHandlers()252 253 # Load the configuration information.254 self.OnWinIniChange(None)255 256 self.SetSel()257 258 self.GetDocument().FinalizeViewCreation(259 self260 ) # is there an MFC way to grab this?261 262 def _GetSubConfigNames(self):263 return None # By default we use only sections without sub-sections.264 265 def OnWinIniChange(self, section=None):266 self.bindings.prepare_configure()267 try:268 self.DoConfigChange()269 finally:270 self.bindings.complete_configure()271 272 def DoConfigChange(self):273 # Bit of a hack I dont kow what to do about - these should be "editor options"274 from pywin.framework.editor import GetEditorOption275 276 self.bAutoCompleteAttributes = GetEditorOption("Autocomplete Attributes", 1)277 self.bShowCallTips = GetEditorOption("Show Call Tips", 1)278 # Update the key map and extension data.279 configManager.configure(self, self._GetSubConfigNames())280 if configManager.last_error:281 win32ui.MessageBox(configManager.last_error, "Configuration Error")282 self.bMatchBraces = GetEditorOption("Match Braces", 1)283 self.ApplyFormattingStyles(1)284 285 def OnDestroy(self, msg):286 self.bindings.close()287 self.bindings = None288 self.idle.close()289 self.idle = None290 control.CScintillaColorEditInterface.close(self)291 return docview.CtrlView.OnDestroy(self, msg)292 293 def OnMouseWheel(self, msg):294 zDelta = msg[2] >> 16295 vpos = self.GetScrollPos(win32con.SB_VERT)296 vpos = vpos - zDelta / 40 # 3 lines per notch297 self.SetScrollPos(win32con.SB_VERT, vpos)298 self.SendScintilla(299 win32con.WM_VSCROLL, (vpos << 16) | win32con.SB_THUMBPOSITION, 0300 )301 302 def OnBraceMatch(self, std, extra):303 if not self.bMatchBraces:304 return305 DoBraceMatch(self)306 307 def OnNeedShown(self, std, extra):308 notify = self.SCIUnpackNotifyMessage(extra)309 # OnNeedShown is called before an edit operation when310 # text is folded (as it is possible the text insertion will happen311 # in a folded region.) As this happens _before_ the insert,312 # we ignore the length (if we are at EOF, pos + length may313 # actually be beyond the end of buffer)314 self.EnsureCharsVisible(notify.position)315 316 def EnsureCharsVisible(self, start, end=None):317 if end is None:318 end = start319 lineStart = self.LineFromChar(min(start, end))320 lineEnd = self.LineFromChar(max(start, end))321 while lineStart <= lineEnd:322 self.SCIEnsureVisible(lineStart)323 lineStart = lineStart + 1324 325 # Helper to add an event to a menu.326 def AppendMenu(self, menu, text="", event=None, flags=None, checked=0):327 if event is None:328 assert flags is not None, "No event or custom flags!"329 cmdid = 0330 else:331 cmdid = self.bindings.get_command_id(event)332 if cmdid is None:333 # No event of that name - no point displaying it.334 print(335 'View.AppendMenu(): Unknown event "%s" specified for menu text "%s" - ignored'336 % (event, text)337 )338 return339 keyname = configManager.get_key_binding(event, self._GetSubConfigNames())340 if keyname is not None:341 text = text + "\t" + keyname342 if flags is None:343 flags = win32con.MF_STRING | win32con.MF_ENABLED344 if checked:345 flags = flags | win32con.MF_CHECKED346 menu.AppendMenu(flags, cmdid, text)347 348 def OnKeyDown(self, msg):349 return self.bindings.fire_key_event(msg)350 351 def GotoEndOfFileEvent(self, event):352 self.SetSel(-1)353 354 def KeyDotEvent(self, event):355 ## Don't trigger autocomplete if any text is selected356 s, e = self.GetSel()357 if s != e:358 return 1359 self.SCIAddText(".")360 if self.bAutoCompleteAttributes:361 self._AutoComplete()362 363 # View Whitespace/EOL/Indentation UI.364 365 def OnCmdViewWS(self, cmd, code): # Handle the menu command366 viewWS = self.SCIGetViewWS()367 self.SCISetViewWS(not viewWS)368 369 def OnUpdateViewWS(self, cmdui): # Update the tick on the UI.370 cmdui.SetCheck(self.SCIGetViewWS())371 cmdui.Enable()372 373 def OnCmdViewIndentationGuides(self, cmd, code): # Handle the menu command374 viewIG = self.SCIGetIndentationGuides()375 self.SCISetIndentationGuides(not viewIG)376 377 def OnUpdateViewIndentationGuides(self, cmdui): # Update the tick on the UI.378 cmdui.SetCheck(self.SCIGetIndentationGuides())379 cmdui.Enable()380 381 def OnCmdViewRightEdge(self, cmd, code): # Handle the menu command382 if self.SCIGetEdgeMode() == scintillacon.EDGE_NONE:383 mode = scintillacon.EDGE_BACKGROUND384 else:385 mode = scintillacon.EDGE_NONE386 self.SCISetEdgeMode(mode)387 388 def OnUpdateViewRightEdge(self, cmdui): # Update the tick on the UI.389 cmdui.SetCheck(self.SCIGetEdgeMode() != scintillacon.EDGE_NONE)390 cmdui.Enable()391 392 def OnCmdViewEOL(self, cmd, code): # Handle the menu command393 viewEOL = self.SCIGetViewEOL()394 self.SCISetViewEOL(not viewEOL)395 396 def OnUpdateViewEOL(self, cmdui): # Update the tick on the UI.397 cmdui.SetCheck(self.SCIGetViewEOL())398 cmdui.Enable()399 400 def OnCmdViewFixedFont(self, cmd, code): # Handle the menu command401 self._GetColorizer().bUseFixed = not self._GetColorizer().bUseFixed402 self.ApplyFormattingStyles(0)403 # Ensure the selection is visible!404 self.ScrollCaret()405 406 def OnUpdateViewFixedFont(self, cmdui): # Update the tick on the UI.407 c = self._GetColorizer()408 if c is not None:409 cmdui.SetCheck(c.bUseFixed)410 cmdui.Enable(c is not None)411 412 def OnCmdEditFind(self, cmd, code):413 from . import find414 415 find.ShowFindDialog()416 417 def OnCmdEditRepeat(self, cmd, code):418 from . import find419 420 find.FindNext()421 422 def OnCmdEditReplace(self, cmd, code):423 from . import find424 425 find.ShowReplaceDialog()426 427 def OnCmdFileLocate(self, cmd, id):428 line = self.GetLine().strip()429 import pywin.framework.scriptutils430 431 m = patImport.match(line)432 if m:433 # Module name on this line - locate that!434 modName = m.group("name")435 fileName = pywin.framework.scriptutils.LocatePythonFile(modName)436 if fileName is None:437 win32ui.SetStatusText("Can't locate module %s" % modName)438 return 1 # Let the default get it.439 else:440 win32ui.GetApp().OpenDocumentFile(fileName)441 else:442 # Just to a "normal" locate - let the default handler get it.443 return 1444 return 0445 446 def OnCmdGotoLine(self, cmd, id):447 try:448 lineNo = int(input("Enter Line Number")) - 1449 except (ValueError, KeyboardInterrupt):450 return 0451 self.SCIEnsureVisible(lineNo)452 self.SCIGotoLine(lineNo)453 return 0454 455 def SaveTextFile(self, filename, encoding=None):456 doc = self.GetDocument()457 doc._SaveTextToFile(self, filename, encoding=encoding)458 doc.SetModifiedFlag(0)459 return 1460 461 def _AutoComplete(self):462 def list2dict(l):463 ret = {}464 for i in l:465 ret[i] = None466 return ret467 468 self.SCIAutoCCancel() # Cancel old auto-complete lists.469 # First try and get an object without evaluating calls470 ob = self._GetObjectAtPos(bAllowCalls=0)471 # If that failed, try and process call or indexing to get the object.472 if ob is None:473 ob = self._GetObjectAtPos(bAllowCalls=1)474 items_dict = {}475 if ob is not None:476 try: # Catch unexpected errors when fetching attribute names from the object477 # extra attributes of win32ui objects478 if hasattr(ob, "_obj_"):479 try:480 items_dict.update(list2dict(dir(ob._obj_)))481 except AttributeError:482 pass # object has no __dict__483 484 # normal attributes485 try:486 items_dict.update(list2dict(dir(ob)))487 except AttributeError:488 pass # object has no __dict__489 if hasattr(ob, "__class__"):490 items_dict.update(list2dict(_get_class_attributes(ob.__class__)))491 # The object may be a COM object with typelib support - lets see if we can get its props.492 # (contributed by Stefan Migowsky)493 try:494 # Get the automation attributes495 items_dict.update(ob.__class__._prop_map_get_)496 # See if there is an write only property497 # could be optimized498 items_dict.update(ob.__class__._prop_map_put_)499 # append to the already evaluated list500 except AttributeError:501 pass502 # The object might be a pure COM dynamic dispatch with typelib support - lets see if we can get its props.503 if hasattr(ob, "_oleobj_"):504 try:505 for iTI in range(0, ob._oleobj_.GetTypeInfoCount()):506 typeInfo = ob._oleobj_.GetTypeInfo(iTI)507 self._UpdateWithITypeInfo(items_dict, typeInfo)508 except:509 pass510 except:511 win32ui.SetStatusText(512 "Error attempting to get object attributes - %s"513 % (repr(sys.exc_info()[0]),)514 )515 516 # ensure all keys are strings.517 items = [str(k) for k in items_dict.keys()]518 # All names that start with "_" go!519 items = [k for k in items if not k.startswith("_")]520 521 if not items:522 # Heuristics a-la AutoExpand523 # The idea is to find other usages of the current binding524 # and assume, that it refers to the same object (or at least,525 # to an object of the same type)526 # Contributed by Vadim Chugunov [vadimch@yahoo.com]527 left, right = self._GetWordSplit()528 if left == "": # Ignore standalone dots529 return None530 # We limit our search to the current class, if that531 # information is available532 minline, maxline, curclass = self._GetClassInfoFromBrowser()533 endpos = self.LineIndex(maxline)534 text = self.GetTextRange(self.LineIndex(minline), endpos)535 try:536 l = re.findall(r"\b" + left + "\.\w+", text)537 except re.error:538 # parens etc may make an invalid RE, but this code wouldnt539 # benefit even if the RE did work :-)540 l = []541 prefix = len(left) + 1542 unique = {}543 for li in l:544 unique[li[prefix:]] = 1545 # Assuming traditional usage of self...546 if curclass and left == "self":547 self._UpdateWithClassMethods(unique, curclass)548 549 items = [550 word for word in unique.keys() if word[:2] != "__" or word[-2:] != "__"551 ]552 # Ignore the word currently to the right of the dot - probably a red-herring.553 try:554 items.remove(right[1:])555 except ValueError:556 pass557 if items:558 items.sort()559 self.SCIAutoCSetAutoHide(0)560 self.SCIAutoCShow(items)561 562 def _UpdateWithITypeInfo(self, items_dict, typeInfo):563 import pythoncom564 565 typeInfos = [typeInfo]566 # suppress IDispatch and IUnknown methods567 inspectedIIDs = {pythoncom.IID_IDispatch: None}568 569 while len(typeInfos) > 0:570 typeInfo = typeInfos.pop()571 typeAttr = typeInfo.GetTypeAttr()572 573 if typeAttr.iid not in inspectedIIDs:574 inspectedIIDs[typeAttr.iid] = None575 for iFun in range(0, typeAttr.cFuncs):576 funDesc = typeInfo.GetFuncDesc(iFun)577 funName = typeInfo.GetNames(funDesc.memid)[0]578 if funName not in items_dict:579 items_dict[funName] = None580 581 # Inspect the type info of all implemented types582 # E.g. IShellDispatch5 implements IShellDispatch4 which implements IShellDispatch3 ...583 for iImplType in range(0, typeAttr.cImplTypes):584 iRefType = typeInfo.GetRefTypeOfImplType(iImplType)585 refTypeInfo = typeInfo.GetRefTypeInfo(iRefType)586 typeInfos.append(refTypeInfo)587 588 # TODO: This is kinda slow. Probably need some kind of cache589 # here that is flushed upon file save590 # Or maybe we don't need the superclass methods at all ?591 def _UpdateWithClassMethods(self, dict, classinfo):592 if not hasattr(classinfo, "methods"):593 # No 'methods' - probably not what we think it is.594 return595 dict.update(classinfo.methods)596 for super in classinfo.super:597 if hasattr(super, "methods"):598 self._UpdateWithClassMethods(dict, super)599 600 # Find which class definition caret is currently in and return601 # indexes of the the first and the last lines of that class definition602 # Data is obtained from module browser (if enabled)603 def _GetClassInfoFromBrowser(self, pos=-1):604 minline = 0605 maxline = self.GetLineCount() - 1606 doc = self.GetParentFrame().GetActiveDocument()607 browser = None608 try:609 if doc is not None:610 browser = doc.GetAllViews()[1]611 except IndexError:612 pass613 if browser is None:614 return (minline, maxline, None) # Current window has no browser615 if not browser.list:616 return (minline, maxline, None) # Not initialized617 path = self.GetDocument().GetPathName()618 if not path:619 return (minline, maxline, None) # No current path620 621 import pywin.framework.scriptutils622 623 curmodule, path = pywin.framework.scriptutils.GetPackageModuleName(path)624 try:625 clbrdata = browser.list.root.clbrdata626 except AttributeError:627 return (minline, maxline, None) # No class data for this module.628 curline = self.LineFromChar(pos)629 curclass = None630 # Find out which class we are in631 for item in clbrdata.values():632 if item.module == curmodule:633 item_lineno = (634 item.lineno - 1635 ) # Scintilla counts lines from 0, whereas pyclbr - from 1636 if minline < item_lineno <= curline:637 minline = item_lineno638 curclass = item639 if curline < item_lineno < maxline:640 maxline = item_lineno641 return (minline, maxline, curclass)642 643 def _GetObjectAtPos(self, pos=-1, bAllowCalls=0):644 left, right = self._GetWordSplit(pos, bAllowCalls)645 if left: # It is an attribute lookup646 # How is this for a hack!647 namespace = sys.modules.copy()648 namespace.update(__main__.__dict__)649 # Get the debugger's context.650 try:651 from pywin.framework import interact652 653 if interact.edit is not None and interact.edit.currentView is not None:654 globs, locs = interact.edit.currentView.GetContext()[:2]655 if globs:656 namespace.update(globs)657 if locs:658 namespace.update(locs)659 except ImportError:660 pass661 try:662 return eval(left, namespace)663 except:664 pass665 return None666 667 def _GetWordSplit(self, pos=-1, bAllowCalls=0):668 if pos == -1:669 pos = self.GetSel()[0] - 1 # Character before current one670 limit = self.GetTextLength()671 before = []672 after = []673 index = pos - 1674 wordbreaks_use = wordbreaks675 if bAllowCalls:676 wordbreaks_use = wordbreaks_use + "()[]"677 while index >= 0:678 char = self.SCIGetCharAt(index)679 if char not in wordbreaks_use:680 break681 before.insert(0, char)682 index = index - 1683 index = pos684 while index <= limit:685 char = self.SCIGetCharAt(index)686 if char not in wordbreaks_use:687 break688 after.append(char)689 index = index + 1690 return "".join(before), "".join(after)691 692 def OnPrepareDC(self, dc, pInfo):693 # print "OnPrepareDC for page", pInfo.GetCurPage(), "of", pInfo.GetFromPage(), "to", pInfo.GetToPage(), ", starts=", self.starts694 if dc.IsPrinting():695 # Check if we are beyond the end.696 # (only do this when actually printing, else messes up print preview!)697 if not pInfo.GetPreview() and self.starts is not None:698 prevPage = pInfo.GetCurPage() - 1699 if prevPage > 0 and self.starts[prevPage] >= self.GetTextLength():700 # All finished.701 pInfo.SetContinuePrinting(0)702 return703 dc.SetMapMode(win32con.MM_TEXT)704 705 def OnPreparePrinting(self, pInfo):706 flags = (707 win32ui.PD_USEDEVMODECOPIES | win32ui.PD_ALLPAGES | win32ui.PD_NOSELECTION708 ) # Dont support printing just a selection.709 # NOTE: Custom print dialogs are stopping the user's values from coming back :-(710 # self.prtDlg = PrintDialog(pInfo, PRINTDLGORD, flags)711 # pInfo.SetPrintDialog(self.prtDlg)712 pInfo.SetMinPage(1)713 # max page remains undefined for now.714 pInfo.SetFromPage(1)715 pInfo.SetToPage(1)716 ret = self.DoPreparePrinting(pInfo)717 return ret718 719 def OnBeginPrinting(self, dc, pInfo):720 self.starts = None721 return self._obj_.OnBeginPrinting(dc, pInfo)722 723 def CalculatePageRanges(self, dc, pInfo):724 # Calculate page ranges and max page725 self.starts = {0: 0}726 metrics = dc.GetTextMetrics()727 left, top, right, bottom = pInfo.GetDraw()728 # Leave space at the top for the header.729 rc = (left, top + int((9 * metrics["tmHeight"]) / 2), right, bottom)730 pageStart = 0731 maxPage = 0732 textLen = self.GetTextLength()733 while pageStart < textLen:734 pageStart = self.FormatRange(dc, pageStart, textLen, rc, 0)735 maxPage = maxPage + 1736 self.starts[maxPage] = pageStart737 # And a sentinal for one page past the end738 self.starts[maxPage + 1] = textLen739 # When actually printing, maxPage doesnt have any effect at this late state.740 # but is needed to make the Print Preview work correctly.741 pInfo.SetMaxPage(maxPage)742 743 def OnFilePrintPreview(self, *arg):744 self._obj_.OnFilePrintPreview()745 746 def OnFilePrint(self, *arg):747 self._obj_.OnFilePrint()748 749 def FormatRange(self, dc, pageStart, lengthDoc, rc, draw):750 """751 typedef struct _formatrange {752 HDC hdc;753 HDC hdcTarget;754 RECT rc;755 RECT rcPage;756 CHARRANGE chrg;} FORMATRANGE;757 """758 fmt = "PPIIIIIIIIll"759 hdcRender = dc.GetHandleOutput()760 hdcFormat = dc.GetHandleAttrib()761 fr = struct.pack(762 fmt,763 hdcRender,764 hdcFormat,765 rc[0],766 rc[1],767 rc[2],768 rc[3],769 rc[0],770 rc[1],771 rc[2],772 rc[3],773 pageStart,774 lengthDoc,775 )776 nextPageStart = self.SendScintilla(EM_FORMATRANGE, draw, fr)777 return nextPageStart778 779 def OnPrint(self, dc, pInfo):780 metrics = dc.GetTextMetrics()781 # print "dev", w, h, l, metrics['tmAscent'], metrics['tmDescent']782 if self.starts is None:783 self.CalculatePageRanges(dc, pInfo)784 pageNum = pInfo.GetCurPage() - 1785 # Setup the header of the page - docname on left, pagenum on right.786 doc = self.GetDocument()787 cxChar = metrics["tmAveCharWidth"]788 cyChar = metrics["tmHeight"]789 left, top, right, bottom = pInfo.GetDraw()790 dc.TextOut(0, 2 * cyChar, doc.GetTitle())791 pagenum_str = win32ui.LoadString(afxres.AFX_IDS_PRINTPAGENUM) % (pageNum + 1,)792 dc.SetTextAlign(win32con.TA_RIGHT)793 dc.TextOut(right, 2 * cyChar, pagenum_str)794 dc.SetTextAlign(win32con.TA_LEFT)795 top = top + int((7 * cyChar) / 2)796 dc.MoveTo(left, top)797 dc.LineTo(right, top)798 top = top + cyChar799 rc = (left, top, right, bottom)800 nextPageStart = self.FormatRange(801 dc, self.starts[pageNum], self.starts[pageNum + 1], rc, 1802 )803 804 805def LoadConfiguration():806 global configManager807 # Bit of a hack I dont kow what to do about?808 from .config import ConfigManager809 810 configName = rc = win32ui.GetProfileVal("Editor", "Keyboard Config", "default")811 configManager = ConfigManager(configName)812 if configManager.last_error:813 bTryDefault = 0814 msg = "Error loading configuration '%s'\n\n%s" % (815 configName,816 configManager.last_error,817 )818 if configName != "default":819 msg = msg + "\n\nThe default configuration will be loaded."820 bTryDefault = 1821 win32ui.MessageBox(msg)822 if bTryDefault:823 configManager = ConfigManager("default")824 if configManager.last_error:825 win32ui.MessageBox(826 "Error loading configuration 'default'\n\n%s"827 % (configManager.last_error)828 )829 830 831configManager = None832LoadConfiguration()833 