cpython/Mac/Tools/IDE/Wtext.py

980 lines
27 KiB
Python
Raw Blame History

import Qd
import TE
import Fm
import waste
import WASTEconst
import Res
import Evt
import Events
import Scrap
import string
import Win
import Wbase
import Wkeys
import Wcontrols
import PyFontify
from types import *
import Fonts
import TextEdit
class TextBox(Wbase.Widget):
"""A static text widget"""
def __init__(self, possize, text = "", align = TextEdit.teJustLeft,
fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)),
backgroundcolor = (0xffff, 0xffff, 0xffff)
):
Wbase.Widget.__init__(self, possize)
self.fontsettings = fontsettings
self.text = text
self.align = align
self._backgroundcolor = backgroundcolor
def draw(self, visRgn = None):
if self._visible:
(font, style, size, color) = self.fontsettings
fontid = GetFNum(font)
savestate = Qd.GetPenState()
Qd.TextFont(fontid)
Qd.TextFace(style)
Qd.TextSize(size)
Qd.RGBForeColor(color)
Qd.RGBBackColor(self._backgroundcolor)
TE.TETextBox(self.text, self._bounds, self.align)
Qd.RGBBackColor((0xffff, 0xffff, 0xffff))
Qd.SetPenState(savestate)
def get(self):
return self.text
def set(self, text):
self.text = text
if self._parentwindow and self._parentwindow.wid:
self.SetPort()
self.draw()
class _ScrollWidget:
# to be overridden
def getscrollbarvalues(self):
return None, None
# internal method
def updatescrollbars(self):
vx, vy = self.getscrollbarvalues()
if self._parent._barx:
if vx <> None:
self._parent._barx.enable(1)
self._parent._barx.set(vx)
else:
self._parent._barx.enable(0)
if self._parent._bary:
if vy <> None:
self._parent._bary.enable(1)
self._parent._bary.set(vy)
else:
self._parent._bary.enable(0)
UNDOLABELS = [ # Indexed by WEGetUndoInfo() value
None, "", "typing", "Cut", "Paste", "Clear", "Drag", "Style"]
class EditText(Wbase.SelectableWidget, _ScrollWidget):
"""A text edit widget, mainly for simple entry fields."""
def __init__(self, possize, text = "",
callback = None, inset = (3, 3),
fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)),
tabsettings = (32, 0),
readonly = 0):
Wbase.SelectableWidget.__init__(self, possize)
self.temptext = text
self.ted = None
self.selection = None
self._callback = callback
self.changed = 0
self.selchanged = 0
self._selected = 0
self._enabled = 1
self.wrap = 1
self.readonly = readonly
self.fontsettings = fontsettings
self.tabsettings = tabsettings
if type(inset) <> TupleType:
self.inset = (inset, inset)
else:
self.inset = inset
def open(self):
if not hasattr(self._parent, "_barx"):
self._parent._barx = None
if not hasattr(self._parent, "_bary"):
self._parent._bary = None
self._calcbounds()
self.SetPort()
viewrect, destrect = self._calctextbounds()
flags = self._getflags()
self.ted = waste.WENew(destrect, viewrect, flags)
self.ted.WEInstallTabHooks()
self.ted.WESetAlignment(WASTEconst.weFlushLeft)
self.setfontsettings(self.fontsettings)
self.settabsettings(self.tabsettings)
self.ted.WEUseText(Res.Resource(self.temptext))
self.ted.WECalText()
if self.selection:
self.setselection(self.selection[0], self.selection[1])
self.selection = None
else:
self.selview()
self.temptext = None
self.updatescrollbars()
self.bind("pageup", self.scrollpageup)
self.bind("pagedown", self.scrollpagedown)
self.bind("top", self.scrolltop)
self.bind("bottom", self.scrollbottom)
self.selchanged = 0
def close(self):
self._parent._barx = None
self._parent._bary = None
self.ted = None
self.temptext = None
Wbase.SelectableWidget.close(self)
def gettabsettings(self):
return self.tabsettings
def settabsettings(self, (tabsize, tabmode)):
self.tabsettings = (tabsize, tabmode)
if hasattr(self.ted, "WESetTabSize"):
port = self._parentwindow.wid.GetWindowPort()
if tabmode:
(font, style, size, color) = self.getfontsettings()
savesettings = GetPortFontSettings(port)
SetPortFontSettings(port, (font, style, size))
tabsize = Qd.StringWidth(' ' * tabsize)
SetPortFontSettings(port, savesettings)
tabsize = max(tabsize, 1)
self.ted.WESetTabSize(tabsize)
self.SetPort()
Qd.EraseRect(self.ted.WEGetViewRect())
self.ted.WEUpdate(port.visRgn)
def getfontsettings(self):
import Res
(font, style, size, color) = self.ted.WEGetRunInfo(0)[4]
font = Fm.GetFontName(font)
return (font, style, size, color)
def setfontsettings(self, (font, style, size, color)):
self.SetPort()
if type(font) <> StringType:
font = Fm.GetFontName(font)
self.fontsettings = (font, style, size, color)
fontid = GetFNum(font)
readonly = self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, -1)
if readonly:
self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0)
try:
self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 1)
selstart, selend = self.ted.WEGetSelection()
self.ted.WESetSelection(0, self.ted.WEGetTextLength())
self.ted.WESetStyle(WASTEconst.weDoFace, (0, 0, 0, (0, 0, 0)))
self.ted.WESetStyle(WASTEconst.weDoFace |
WASTEconst.weDoColor |
WASTEconst.weDoFont |
WASTEconst.weDoSize,
(fontid, style, size, color))
self.ted.WEFeatureFlag(WASTEconst.weFInhibitRecal, 0)
self.ted.WECalText()
self.ted.WESetSelection(selstart, selend)
finally:
if readonly:
self.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1)
viewrect = self.ted.WEGetViewRect()
Qd.EraseRect(viewrect)
self.ted.WEUpdate(self._parentwindow.wid.GetWindowPort().visRgn)
self.selchanged = 1
self.updatescrollbars()
def adjust(self, oldbounds):
self.SetPort()
if self._selected and self._parentwindow._hasselframes:
Win.InvalRect(Qd.InsetRect(oldbounds, -3, -3))
Win.InvalRect(Qd.InsetRect(self._bounds, -3, -3))
else:
Win.InvalRect(oldbounds)
Win.InvalRect(self._bounds)
viewrect, destrect = self._calctextbounds()
self.ted.WESetViewRect(viewrect)
self.ted.WESetDestRect(destrect)
if self.wrap:
self.ted.WECalText()
if self.ted.WEGetDestRect()[3] < viewrect[1]:
self.selview()
self.updatescrollbars()
# interface -----------------------
# selection stuff
def selview(self):
self.ted.WESelView()
def selectall(self):
self.ted.WESetSelection(0, self.ted.WEGetTextLength())
self.selchanged = 1
self.updatescrollbars()
def selectline(self, lineno, charoffset = 0):
newselstart, newselend = self.ted.WEGetLineRange(lineno)
# Autoscroll makes the *end* of the selection visible, which,
# in the case of a whole line, is the beginning of the *next* line.
# So sometimes it leaves our line just above the view rect.
# Let's fool Waste by initially selecting one char less:
self.ted.WESetSelection(newselstart + charoffset, newselend-1)
self.ted.WESetSelection(newselstart + charoffset, newselend)
self.selchanged = 1
self.updatescrollbars()
def getselection(self):
if self.ted:
return self.ted.WEGetSelection()
else:
return self.selection
def setselection(self, selstart, selend):
self.selchanged = 1
if self.ted:
self.ted.WESetSelection(selstart, selend)
self.ted.WESelView()
self.updatescrollbars()
else:
self.selection = selstart, selend
def offsettoline(self, offset):
return self.ted.WEOffsetToLine(offset)
def countlines(self):
return self.ted.WECountLines()
def getselectedtext(self):
selstart, selend = self.ted.WEGetSelection()
return self.ted.WEGetText().data[selstart:selend]
def expandselection(self):
oldselstart, oldselend = self.ted.WEGetSelection()
selstart, selend = min(oldselstart, oldselend), max(oldselstart, oldselend)
if selstart <> selend and chr(self.ted.WEGetChar(selend-1)) == '\r':
selend = selend - 1
newselstart, dummy = self.ted.WEFindLine(selstart, 0)
dummy, newselend = self.ted.WEFindLine(selend, 0)
if oldselstart <> newselstart or oldselend <> newselend:
self.ted.WESetSelection(newselstart, newselend)
self.updatescrollbars()
self.selchanged = 1
def insert(self, text):
self.ted.WEInsert(text, None, None)
self.changed = 1
self.selchanged = 1
# text
def set(self, text):
if not self.ted:
self.temptext = text
else:
self.ted.WEUseText(Res.Resource(text))
self.ted.WECalText()
self.SetPort()
viewrect, destrect = self._calctextbounds()
self.ted.WESetViewRect(viewrect)
self.ted.WESetDestRect(destrect)
rgn = Qd.NewRgn()
Qd.RectRgn(rgn, viewrect)
Qd.EraseRect(viewrect)
self.draw(rgn)
#Win.InvalRect(self.ted.WEGetViewRect())
self.updatescrollbars()
def get(self):
if not self._parent:
return self.temptext
else:
return self.ted.WEGetText().data
# events
def key(self, char, event):
(what, message, when, where, modifiers) = event
if self._enabled and not modifiers & Events.cmdKey or char in Wkeys.arrowkeys:
self.ted.WEKey(ord(char), modifiers)
if char not in Wkeys.navigationkeys:
self.changed = 1
if char not in Wkeys.scrollkeys:
self.selchanged = 1
self.updatescrollbars()
if self._callback:
Wbase.CallbackCall(self._callback, 0, char, modifiers)
def click(self, point, modifiers):
if not self._enabled:
return
self.ted.WEClick(point, modifiers, Evt.TickCount())
self.selchanged = 1
self.updatescrollbars()
return 1
def idle(self):
self.SetPort()
self.ted.WEIdle()
def rollover(self, point, onoff):
if onoff:
Wbase.SetCursor("iBeam")
def activate(self, onoff):
self._activated = onoff
if self._selected and self._visible:
if onoff:
self.ted.WEActivate()
else:
self.ted.WEDeactivate()
if self._selected:
self.drawselframe(onoff)
def select(self, onoff, isclick = 0):
if Wbase.SelectableWidget.select(self, onoff):
return
self.SetPort()
if onoff:
self.ted.WEActivate()
if self._parentwindow._tabbable and not isclick:
self.selectall()
else:
self.ted.WEDeactivate()
self.drawselframe(onoff)
def draw(self, visRgn = None):
if self._visible:
if not visRgn:
visRgn = self._parentwindow.wid.GetWindowPort().visRgn
self.ted.WEUpdate(visRgn)
if self._selected and self._activated:
self.drawselframe(1)
Qd.FrameRect(self._bounds)
# scrolling
def scrollpageup(self):
if self._parent._bary and self._parent._bary._enabled:
self.vscroll("++")
def scrollpagedown(self):
if self._parent._bary and self._parent._bary._enabled:
self.vscroll("--")
def scrolltop(self):
if self._parent._bary and self._parent._bary._enabled:
self.vscroll(0)
if self._parent._barx and self._parent._barx._enabled:
self.hscroll(0)
def scrollbottom(self):
if self._parent._bary and self._parent._bary._enabled:
self.vscroll(32767)
# menu handlers
def domenu_copy(self, *args):
selbegin, selend = self.ted.WEGetSelection()
if selbegin == selend:
return
Scrap.ZeroScrap()
self.ted.WECopy()
self.updatescrollbars()
def domenu_cut(self, *args):
selbegin, selend = self.ted.WEGetSelection()
if selbegin == selend:
return
Scrap.ZeroScrap()
self.ted.WECut()
self.updatescrollbars()
self.selview()
self.changed = 1
self.selchanged = 1
if self._callback:
Wbase.CallbackCall(self._callback, 0, "", None)
def domenu_paste(self, *args):
if not self.ted.WECanPaste():
return
self.selview()
self.ted.WEPaste()
self.updatescrollbars()
self.changed = 1
self.selchanged = 1
if self._callback:
Wbase.CallbackCall(self._callback, 0, "", None)
def domenu_clear(self, *args):
self.ted.WEDelete()
self.selview()
self.updatescrollbars()
self.changed = 1
self.selchanged = 1
if self._callback:
Wbase.CallbackCall(self._callback, 0, "", None)
def domenu_undo(self, *args):
which, redo = self.ted.WEGetUndoInfo()
if not which:
return
self.ted.WEUndo()
self.updatescrollbars()
self.changed = 1
self.selchanged = 1
if self._callback:
Wbase.CallbackCall(self._callback, 0, "", None)
def can_undo(self, menuitem):
#doundo = self.ted.WEFeatureFlag(WASTEconst.weFUndo, -1)
#print doundo
#if not doundo:
# return 0
which, redo = self.ted.WEGetUndoInfo()
which = UNDOLABELS[which]
if which == None:
return None
if redo:
which = "Redo "+which
else:
which = "Undo "+which
menuitem.settext(which)
return 1
def domenu_selectall(self, *args):
self.selectall()
# private
def getscrollbarvalues(self):
dr = self.ted.WEGetDestRect()
vr = self.ted.WEGetViewRect()
vx = Wcontrols._scalebarvalue(dr[0], dr[2], vr[0], vr[2])
vy = Wcontrols._scalebarvalue(dr[1], dr[3], vr[1], vr[3])
return vx, vy
def vscroll(self, value):
lineheight = self.ted.WEGetHeight(0, 1)
dr = self.ted.WEGetDestRect()
vr = self.ted.WEGetViewRect()
destheight = dr[3] - dr[1]
viewheight = vr[3] - vr[1]
viewoffset = maxdelta = vr[1] - dr[1]
mindelta = vr[3] - dr[3]
if value == "+":
delta = lineheight
elif value == "-":
delta = - lineheight
elif value == "++":
delta = viewheight - lineheight
elif value == "--":
delta = lineheight - viewheight
else: # in thumb
cur = (32767L * viewoffset) / (destheight - viewheight)
delta = (cur-value)*(destheight - viewheight)/32767
if abs(delta - viewoffset) <=2:
# compensate for irritating rounding error
delta = viewoffset
delta = min(maxdelta, delta)
delta = max(mindelta, delta)
self.ted.WEScroll(0, delta)
self.updatescrollbars()
def hscroll(self, value):
dr = self.ted.WEGetDestRect()
vr = self.ted.WEGetViewRect()
destwidth = dr[2] - dr[0]
viewwidth = vr[2] - vr[0]
viewoffset = maxdelta = vr[0] - dr[0]
mindelta = vr[2] - dr[2]
if value == "+":
delta = 32
elif value == "-":
delta = - 32
elif value == "++":
delta = 0.5 * (vr[2] - vr[0])
elif value == "--":
delta = 0.5 * (vr[0] - vr[2])
else: # in thumb
cur = (32767 * viewoffset) / (destwidth - viewwidth)
delta = (cur-value)*(destwidth - viewwidth)/32767
if abs(delta - viewoffset) <=2:
# compensate for irritating rounding error
delta = viewoffset
delta = min(maxdelta, delta)
delta = max(mindelta, delta)
self.ted.WEScroll(delta, 0)
self.updatescrollbars()
# some internals
def _getflags(self):
flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoMonoStyled
if self.readonly:
flags = flags | WASTEconst.weDoReadOnly
else:
flags = flags | WASTEconst.weDoUndo
return flags
def _getviewrect(self):
return Qd.InsetRect(self._bounds, self.inset[0], self.inset[1])
def _calctextbounds(self):
viewrect = l, t, r, b = self._getviewrect()
if self.ted:
dl, dt, dr, db = self.ted.WEGetDestRect()
vl, vt, vr, vb = self.ted.WEGetViewRect()
yshift = t - vt
if (db - dt) < (b - t):
destrect = viewrect
else:
destrect = l, dt + yshift, r, db + yshift
else:
destrect = viewrect
return viewrect, destrect
class TextEditor(EditText):
"""A text edit widget."""
def __init__(self, possize, text = "", callback = None, wrap = 1, inset = (4, 4),
fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)),
tabsettings = (32, 0),
readonly = 0):
EditText.__init__(self, possize, text, callback, inset, fontsettings, tabsettings, readonly)
self.wrap = wrap
def _getflags(self):
flags = WASTEconst.weDoAutoScroll | WASTEconst.weDoMonoStyled | \
WASTEconst.weDoOutlineHilite
if self.readonly:
flags = flags | WASTEconst.weDoReadOnly
else:
flags = flags | WASTEconst.weDoUndo
return flags
def _getviewrect(self):
l, t, r, b = self._bounds
return (l + 5, t + 2, r, b - 2)
def _calctextbounds(self):
if self.wrap:
return EditText._calctextbounds(self)
else:
viewrect = l, t, r, b = self._getviewrect()
if self.ted:
dl, dt, dr, db = self.ted.WEGetDestRect()
vl, vt, vr, vb = self.ted.WEGetViewRect()
xshift = l - vl
yshift = t - vt
if (db - dt) < (b - t):
yshift = t - dt
destrect = (dl + xshift, dt + yshift, dr + xshift, db + yshift)
else:
destrect = (l, t, r + 5000, b)
return viewrect, destrect
def draw(self, visRgn = None):
if self._visible:
if not visRgn:
visRgn = self._parentwindow.wid.GetWindowPort().visRgn
self.ted.WEUpdate(visRgn)
if self._selected and self._activated:
self.drawselframe(1)
import regex
commentPat = regex.compile("[ \t]*\(#\)")
indentPat = regex.compile("\t*")
class PyEditor(TextEditor):
"""A specialized Python source edit widget"""
def __init__(self, possize, text = "", callback = None, inset = (4, 4),
fontsettings = ("Python-Sans", 0, 9, (0, 0, 0)),
tabsettings = (32, 0),
readonly = 0,
debugger = None,
file = ''):
TextEditor.__init__(self, possize, text, callback, 0, inset, fontsettings, tabsettings, readonly)
self.bind("cmd[", self.domenu_shiftleft)
self.bind("cmd]", self.domenu_shiftright)
self.bind("cmdshift[", self.domenu_uncomment)
self.bind("cmdshift]", self.domenu_comment)
self.file = file # only for debugger reference
self._debugger = debugger
if debugger:
debugger.register_editor(self, self.file)
def domenu_shiftleft(self):
self.expandselection()
selstart, selend = self.ted.WEGetSelection()
selstart, selend = min(selstart, selend), max(selstart, selend)
snippet = self.getselectedtext()
lines = string.split(snippet, '\r')
for i in range(len(lines)):
if lines[i][:1] == '\t':
lines[i] = lines[i][1:]
snippet = string.join(lines, '\r')
self.insert(snippet)
self.ted.WESetSelection(selstart, selstart + len(snippet))
def domenu_shiftright(self):
self.expandselection()
selstart, selend = self.ted.WEGetSelection()
selstart, selend = min(selstart, selend), max(selstart, selend)
snippet = self.getselectedtext()
lines = string.split(snippet, '\r')
for i in range(len(lines) - (not lines[-1])):
lines[i] = '\t' + lines[i]
snippet = string.join(lines, '\r')
self.insert(snippet)
self.ted.WESetSelection(selstart, selstart + len(snippet))
def domenu_uncomment(self):
self.expandselection()
selstart, selend = self.ted.WEGetSelection()
selstart, selend = min(selstart, selend), max(selstart, selend)
snippet = self.getselectedtext()
lines = string.split(snippet, '\r')
for i in range(len(lines)):
res = commentPat.match(lines[i]) >= 0
if res > 0:
pos = commentPat.regs[1][0]
lines[i] = lines[i][:pos] + lines[i][pos+1:]
snippet = string.join(lines, '\r')
self.insert(snippet)
self.ted.WESetSelection(selstart, selstart + len(snippet))
def domenu_comment(self):
self.expandselection()
selstart, selend = self.ted.WEGetSelection()
selstart, selend = min(selstart, selend), max(selstart, selend)
snippet = self.getselectedtext()
lines = string.split(snippet, '\r')
indent = 3000 # arbitrary large number...
for line in lines:
if string.strip(line):
if indentPat.match(line):
indent = min(indent, indentPat.regs[0][1])
else:
indent = 0
break
for i in range(len(lines) - (not lines[-1])):
lines[i] = lines[i][:indent] + "#" + lines[i][indent:]
snippet = string.join(lines, '\r')
self.insert(snippet)
self.ted.WESetSelection(selstart, selstart + len(snippet))
def setfile(self, file):
self.file = file
def set(self, text, file = ''):
oldfile = self.file
self.file = file
if self._debugger:
self._debugger.unregister_editor(self, oldfile)
self._debugger.register_editor(self, file)
TextEditor.set(self, text)
def close(self):
if self._debugger:
self._debugger.unregister_editor(self, self.file)
self._debugger = None
TextEditor.close(self)
def click(self, point, modifiers):
if not self._enabled:
return
if self._debugger and self.pt_in_breaks(point):
self.breakhit(point, modifiers)
elif self._debugger:
bl, bt, br, bb = self._getbreakrect()
Qd.EraseRect((bl, bt, br-1, bb))
TextEditor.click(self, point, modifiers)
self.drawbreakpoints()
else:
TextEditor.click(self, point, modifiers)
if self.ted.WEGetClickCount() >= 3:
# select block with our indent
lines = string.split(self.get(), '\r')
selstart, selend = self.ted.WEGetSelection()
lineno = self.ted.WEOffsetToLine(selstart)
tabs = 0
line = lines[lineno]
while line[tabs:] and line[tabs] == '\t':
tabs = tabs + 1
tabstag = '\t' * tabs
fromline = 0
toline = len(lines)
if tabs:
for i in range(lineno - 1, -1, -1):
line = lines[i]
if line[:tabs] <> tabstag:
fromline = i + 1
break
for i in range(lineno + 1, toline):
line = lines[i]
if line[:tabs] <> tabstag:
toline = i - 1
break
selstart, dummy = self.ted.WEGetLineRange(fromline)
dummy, selend = self.ted.WEGetLineRange(toline)
self.ted.WESetSelection(selstart, selend)
def breakhit(self, point, modifiers):
if not self.file:
return
destrect = self.ted.WEGetDestRect()
offset, edge = self.ted.WEGetOffset(point)
lineno = self.ted.WEOffsetToLine(offset) + 1
if point[1] <= destrect[3]:
self._debugger.clear_breaks_above(self.file, self.countlines())
self._debugger.toggle_break(self.file, lineno)
else:
self._debugger.clear_breaks_above(self.file, lineno)
def key(self, char, event):
(what, message, when, where, modifiers) = event
if modifiers & Events.cmdKey and not char in Wkeys.arrowkeys:
return
if char == '\r':
selstart, selend = self.ted.WEGetSelection()
selstart, selend = min(selstart, selend), max(selstart, selend)
lastchar = chr(self.ted.WEGetChar(selstart-1))
if lastchar <> '\r' and selstart:
pos, dummy = self.ted.WEFindLine(selstart, 0)
lineres = Res.Resource('')
self.ted.WECopyRange(pos, selstart, lineres, None, None)
line = lineres.data + '\n'
tabcount = self.extratabs(line)
self.ted.WEKey(ord('\r'), 0)
for i in range(tabcount):
self.ted.WEKey(ord('\t'), 0)
else:
self.ted.WEKey(ord('\r'), 0)
elif char in ')]}':
self.ted.WEKey(ord(char), modifiers)
self.balanceparens(char)
else:
self.ted.WEKey(ord(char), modifiers)
if char not in Wkeys.navigationkeys:
self.changed = 1
self.selchanged = 1
self.updatescrollbars()
def balanceparens(self, char):
if char == ')':
target = '('
elif char == ']':
target = '['
elif char == '}':
target = '{'
recursionlevel = 1
selstart, selend = self.ted.WEGetSelection()
count = min(selstart, selend) - 2
mincount = max(0, count - 2048)
lastquote = None
while count > mincount:
testchar = chr(self.ted.WEGetChar(count))
if testchar in "\"'" and chr(self.ted.WEGetChar(count - 1)) <> '\\':
if lastquote == testchar:
recursionlevel = recursionlevel - 1
lastquote = None
elif not lastquote:
recursionlevel = recursionlevel + 1
lastquote = testchar
elif not lastquote and testchar == char:
recursionlevel = recursionlevel + 1
elif not lastquote and testchar == target:
recursionlevel = recursionlevel - 1
if recursionlevel == 0:
import time
autoscroll = self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, -1)
if autoscroll:
self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 0)
self.ted.WESetSelection(count, count + 1)
time.sleep(0.2)
self.ted.WESetSelection(selstart, selend)
if autoscroll:
self.ted.WEFeatureFlag(WASTEconst.weFAutoScroll, 1)
break
count = count - 1
def extratabs(self, line):
tabcount = 0
for c in line:
if c <> '\t':
break
tabcount = tabcount + 1
last = 0
cleanline = ''
tags = PyFontify.fontify(line)
# strip comments and strings
for tag, start, end, sublist in tags:
if tag in ('string', 'comment'):
cleanline = cleanline + line[last:start]
last = end
cleanline = cleanline + line[last:]
cleanline = string.strip(cleanline)
if cleanline and cleanline[-1] == ':':
tabcount = tabcount + 1
else:
# extra indent after unbalanced (, [ or {
for open, close in (('(', ')'), ('[', ']'), ('{', '}')):
count = string.count(cleanline, open)
if count and count > string.count(cleanline, close):
tabcount = tabcount + 2
break
return tabcount
def rollover(self, point, onoff):
if onoff:
if self._debugger and self.pt_in_breaks(point):
Wbase.SetCursor("arrow")
else:
Wbase.SetCursor("iBeam")
def draw(self, visRgn = None):
TextEditor.draw(self, visRgn)
if self._debugger:
self.drawbreakpoints()
def showbreakpoints(self, onoff):
if (not not self._debugger) <> onoff:
if onoff:
if not __debug__:
import W
raise W.AlertError, "Can<EFBFBD>t debug in <20>Optimize bytecode<64> mode.\r(see <20>Default startup options<6E> in EditPythonPreferences)"
import PyDebugger
self._debugger = PyDebugger.getdebugger()
self._debugger.register_editor(self, self.file)
elif self._debugger:
self._debugger.unregister_editor(self, self.file)
self._debugger = None
self.adjust(self._bounds)
def togglebreakpoints(self):
self.showbreakpoints(not self._debugger)
def clearbreakpoints(self):
if self.file:
self._debugger.clear_all_file_breaks(self.file)
def editbreakpoints(self):
if self._debugger:
self._debugger.edit_breaks()
self._debugger.breaksviewer.selectfile(self.file)
def drawbreakpoints(self, eraseall = 0):
breakrect = bl, bt, br, bb = self._getbreakrect()
br = br - 1
self.SetPort()
Qd.PenPat(Qd.qd.gray)
Qd.PaintRect((br, bt, br + 1, bb))
Qd.PenNormal()
self._parentwindow.tempcliprect(breakrect)
Qd.RGBForeColor((0xffff, 0, 0))
try:
lasttop = bt
self_ted = self.ted
Qd_PaintOval = Qd.PaintOval
Qd_EraseRect = Qd.EraseRect
for lineno in self._debugger.get_file_breaks(self.file):
start, end = self_ted.WEGetLineRange(lineno - 1)
if lineno <> self_ted.WEOffsetToLine(start) + 1:
# breakpoints beyond our text: erase rest, and back out
Qd_EraseRect((bl, lasttop, br, bb))
break
(x, y), h = self_ted.WEGetPoint(start, 0)
bottom = y + h
#print y, (lasttop, bottom)
if bottom > lasttop:
Qd_EraseRect((bl, lasttop, br, y + h * eraseall))
lasttop = bottom
redbullet = bl + 2, y + 3, bl + 8, y + 9
Qd_PaintOval(redbullet)
else:
Qd_EraseRect((bl, lasttop, br, bb))
Qd.RGBForeColor((0, 0, 0))
finally:
self._parentwindow.restoreclip()
def updatescrollbars(self):
if self._debugger:
self.drawbreakpoints(1)
TextEditor.updatescrollbars(self)
def pt_in_breaks(self, point):
return Qd.PtInRect(point, self._getbreakrect())
def _getbreakrect(self):
if self._debugger:
l, t, r, b = self._bounds
return (l+1, t+1, l + 12, b-1)
else:
return (0, 0, 0, 0)
def _getviewrect(self):
l, t, r, b = self._bounds
if self._debugger:
return (l + 17, t + 2, r, b - 2)
else:
return (l + 5, t + 2, r, b - 2)
def _calctextbounds(self):
viewrect = l, t, r, b = self._getviewrect()
if self.ted:
dl, dt, dr, db = self.ted.WEGetDestRect()
vl, vt, vr, vb = self.ted.WEGetViewRect()
xshift = l - vl
yshift = t - vt
if (db - dt) < (b - t):
yshift = t - dt
destrect = (dl + xshift, dt + yshift, dr + xshift, db + yshift)
else:
destrect = (l, t, r + 5000, b)
return viewrect, destrect
def GetFNum(fontname):
"""Same as Fm.GetFNum(), but maps a missing font to Monaco instead of the system font."""
if fontname <> Fm.GetFontName(0):
fontid = Fm.GetFNum(fontname)
if fontid == 0:
fontid = Fonts.monaco
else:
fontid = 0
return fontid
# b/w compat. Anyone using this?
GetFName = Fm.GetFontName
def GetPortFontSettings(port):
return Fm.GetFontName(port.txFont), port.txFace, port.txSize
def SetPortFontSettings(port, (font, face, size)):
saveport = Qd.GetPort()
Qd.SetPort(port)
Qd.TextFont(GetFNum(font))
Qd.TextFace(face)
Qd.TextSize(size)
Qd.SetPort(saveport)