570 lines
20 KiB
Python
570 lines
20 KiB
Python
|
# An Python interface to the Scintilla control.
|
||
|
#
|
||
|
# Exposes Python classes that allow you to use Scintilla as
|
||
|
# a "standard" MFC edit control (eg, control.GetTextLength(), control.GetSel()
|
||
|
# plus many Scintilla specific features (eg control.SCIAddStyledText())
|
||
|
|
||
|
import array
|
||
|
import os
|
||
|
import struct
|
||
|
|
||
|
import win32api
|
||
|
import win32con
|
||
|
import win32ui
|
||
|
from pywin import default_scintilla_encoding
|
||
|
from pywin.mfc import window
|
||
|
|
||
|
from . import scintillacon
|
||
|
|
||
|
# Load Scintilla.dll to get access to the control.
|
||
|
# We expect to find this in the same directory as win32ui.pyd
|
||
|
dllid = None
|
||
|
if win32ui.debug: # If running _d version of Pythonwin...
|
||
|
try:
|
||
|
dllid = win32api.LoadLibrary(
|
||
|
os.path.join(os.path.split(win32ui.__file__)[0], "Scintilla_d.DLL")
|
||
|
)
|
||
|
except (
|
||
|
win32api.error
|
||
|
): # Not there - we dont _need_ a debug ver, so ignore this error.
|
||
|
pass
|
||
|
if dllid is None:
|
||
|
try:
|
||
|
dllid = win32api.LoadLibrary(
|
||
|
os.path.join(os.path.split(win32ui.__file__)[0], "Scintilla.DLL")
|
||
|
)
|
||
|
except win32api.error:
|
||
|
pass
|
||
|
if dllid is None:
|
||
|
# Still not there - lets see if Windows can find it by searching?
|
||
|
dllid = win32api.LoadLibrary("Scintilla.DLL")
|
||
|
|
||
|
# null_byte is str in py2k, bytes on py3k
|
||
|
null_byte = "\0".encode("ascii")
|
||
|
|
||
|
## These are from Richedit.h - need to add to win32con or commctrl
|
||
|
EM_GETTEXTRANGE = 1099
|
||
|
EM_EXLINEFROMCHAR = 1078
|
||
|
EM_FINDTEXTEX = 1103
|
||
|
EM_GETSELTEXT = 1086
|
||
|
EM_EXSETSEL = win32con.WM_USER + 55
|
||
|
|
||
|
|
||
|
class ScintillaNotification:
|
||
|
def __init__(self, **args):
|
||
|
self.__dict__.update(args)
|
||
|
|
||
|
|
||
|
class ScintillaControlInterface:
|
||
|
def SCIUnpackNotifyMessage(self, msg):
|
||
|
format = "iiiiPiiiPPiiii"
|
||
|
bytes = win32ui.GetBytes(msg, struct.calcsize(format))
|
||
|
(
|
||
|
position,
|
||
|
ch,
|
||
|
modifiers,
|
||
|
modificationType,
|
||
|
text_ptr,
|
||
|
length,
|
||
|
linesAdded,
|
||
|
msg,
|
||
|
wParam,
|
||
|
lParam,
|
||
|
line,
|
||
|
foldLevelNow,
|
||
|
foldLevelPrev,
|
||
|
margin,
|
||
|
) = struct.unpack(format, bytes)
|
||
|
return ScintillaNotification(
|
||
|
position=position,
|
||
|
ch=ch,
|
||
|
modifiers=modifiers,
|
||
|
modificationType=modificationType,
|
||
|
text_ptr=text_ptr,
|
||
|
length=length,
|
||
|
linesAdded=linesAdded,
|
||
|
msg=msg,
|
||
|
wParam=wParam,
|
||
|
lParam=lParam,
|
||
|
line=line,
|
||
|
foldLevelNow=foldLevelNow,
|
||
|
foldLevelPrev=foldLevelPrev,
|
||
|
margin=margin,
|
||
|
)
|
||
|
|
||
|
def SCIAddText(self, text):
|
||
|
self.SendMessage(
|
||
|
scintillacon.SCI_ADDTEXT, text.encode(default_scintilla_encoding)
|
||
|
)
|
||
|
|
||
|
def SCIAddStyledText(self, text, style=None):
|
||
|
# If style is None, text is assumed to be a "native" Scintilla buffer.
|
||
|
# If style is specified, text is a normal string, and the style is
|
||
|
# assumed to apply to the entire string.
|
||
|
if style is not None:
|
||
|
text = list(map(lambda char, style=style: char + chr(style), text))
|
||
|
text = "".join(text)
|
||
|
self.SendMessage(
|
||
|
scintillacon.SCI_ADDSTYLEDTEXT, text.encode(default_scintilla_encoding)
|
||
|
)
|
||
|
|
||
|
def SCIInsertText(self, text, pos=-1):
|
||
|
# SCIInsertText allows unicode or bytes - but if they are bytes,
|
||
|
# the caller must ensure it is encoded correctly.
|
||
|
if isinstance(text, str):
|
||
|
text = text.encode(default_scintilla_encoding)
|
||
|
self.SendScintilla(scintillacon.SCI_INSERTTEXT, pos, text + null_byte)
|
||
|
|
||
|
def SCISetSavePoint(self):
|
||
|
self.SendScintilla(scintillacon.SCI_SETSAVEPOINT)
|
||
|
|
||
|
def SCISetUndoCollection(self, collectFlag):
|
||
|
self.SendScintilla(scintillacon.SCI_SETUNDOCOLLECTION, collectFlag)
|
||
|
|
||
|
def SCIBeginUndoAction(self):
|
||
|
self.SendScintilla(scintillacon.SCI_BEGINUNDOACTION)
|
||
|
|
||
|
def SCIEndUndoAction(self):
|
||
|
self.SendScintilla(scintillacon.SCI_ENDUNDOACTION)
|
||
|
|
||
|
def SCIGetCurrentPos(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETCURRENTPOS)
|
||
|
|
||
|
def SCIGetCharAt(self, pos):
|
||
|
# Must ensure char is unsigned!
|
||
|
return chr(self.SendScintilla(scintillacon.SCI_GETCHARAT, pos) & 0xFF)
|
||
|
|
||
|
def SCIGotoLine(self, line):
|
||
|
self.SendScintilla(scintillacon.SCI_GOTOLINE, line)
|
||
|
|
||
|
def SCIBraceMatch(self, pos, maxReStyle):
|
||
|
return self.SendScintilla(scintillacon.SCI_BRACEMATCH, pos, maxReStyle)
|
||
|
|
||
|
def SCIBraceHighlight(self, pos, posOpposite):
|
||
|
return self.SendScintilla(scintillacon.SCI_BRACEHIGHLIGHT, pos, posOpposite)
|
||
|
|
||
|
def SCIBraceBadHighlight(self, pos):
|
||
|
return self.SendScintilla(scintillacon.SCI_BRACEBADLIGHT, pos)
|
||
|
|
||
|
####################################
|
||
|
# Styling
|
||
|
# def SCIColourise(self, start=0, end=-1):
|
||
|
# NOTE - dependent on of we use builtin lexer, so handled below.
|
||
|
def SCIGetEndStyled(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETENDSTYLED)
|
||
|
|
||
|
def SCIStyleSetFore(self, num, v):
|
||
|
return self.SendScintilla(scintillacon.SCI_STYLESETFORE, num, v)
|
||
|
|
||
|
def SCIStyleSetBack(self, num, v):
|
||
|
return self.SendScintilla(scintillacon.SCI_STYLESETBACK, num, v)
|
||
|
|
||
|
def SCIStyleSetEOLFilled(self, num, v):
|
||
|
return self.SendScintilla(scintillacon.SCI_STYLESETEOLFILLED, num, v)
|
||
|
|
||
|
def SCIStyleSetFont(self, num, name, characterset=0):
|
||
|
buff = (name + "\0").encode(default_scintilla_encoding)
|
||
|
self.SendScintilla(scintillacon.SCI_STYLESETFONT, num, buff)
|
||
|
self.SendScintilla(scintillacon.SCI_STYLESETCHARACTERSET, num, characterset)
|
||
|
|
||
|
def SCIStyleSetBold(self, num, bBold):
|
||
|
self.SendScintilla(scintillacon.SCI_STYLESETBOLD, num, bBold)
|
||
|
|
||
|
def SCIStyleSetItalic(self, num, bItalic):
|
||
|
self.SendScintilla(scintillacon.SCI_STYLESETITALIC, num, bItalic)
|
||
|
|
||
|
def SCIStyleSetSize(self, num, size):
|
||
|
self.SendScintilla(scintillacon.SCI_STYLESETSIZE, num, size)
|
||
|
|
||
|
def SCIGetViewWS(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETVIEWWS)
|
||
|
|
||
|
def SCISetViewWS(self, val):
|
||
|
self.SendScintilla(scintillacon.SCI_SETVIEWWS, not (val == 0))
|
||
|
self.InvalidateRect()
|
||
|
|
||
|
def SCISetIndentationGuides(self, val):
|
||
|
self.SendScintilla(scintillacon.SCI_SETINDENTATIONGUIDES, val)
|
||
|
|
||
|
def SCIGetIndentationGuides(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETINDENTATIONGUIDES)
|
||
|
|
||
|
def SCISetIndent(self, val):
|
||
|
self.SendScintilla(scintillacon.SCI_SETINDENT, val)
|
||
|
|
||
|
def SCIGetIndent(self, val):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETINDENT)
|
||
|
|
||
|
def SCIGetViewEOL(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETVIEWEOL)
|
||
|
|
||
|
def SCISetViewEOL(self, val):
|
||
|
self.SendScintilla(scintillacon.SCI_SETVIEWEOL, not (val == 0))
|
||
|
self.InvalidateRect()
|
||
|
|
||
|
def SCISetTabWidth(self, width):
|
||
|
self.SendScintilla(scintillacon.SCI_SETTABWIDTH, width, 0)
|
||
|
|
||
|
def SCIStartStyling(self, pos, mask):
|
||
|
self.SendScintilla(scintillacon.SCI_STARTSTYLING, pos, mask)
|
||
|
|
||
|
def SCISetStyling(self, pos, attr):
|
||
|
self.SendScintilla(scintillacon.SCI_SETSTYLING, pos, attr)
|
||
|
|
||
|
def SCISetStylingEx(self, ray): # ray is an array.
|
||
|
address, length = ray.buffer_info()
|
||
|
self.SendScintilla(scintillacon.SCI_SETSTYLINGEX, length, address)
|
||
|
|
||
|
def SCIGetStyleAt(self, pos):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETSTYLEAT, pos)
|
||
|
|
||
|
def SCISetMarginWidth(self, width):
|
||
|
self.SendScintilla(scintillacon.SCI_SETMARGINWIDTHN, 1, width)
|
||
|
|
||
|
def SCISetMarginWidthN(self, n, width):
|
||
|
self.SendScintilla(scintillacon.SCI_SETMARGINWIDTHN, n, width)
|
||
|
|
||
|
def SCISetFoldFlags(self, flags):
|
||
|
self.SendScintilla(scintillacon.SCI_SETFOLDFLAGS, flags)
|
||
|
|
||
|
# Markers
|
||
|
def SCIMarkerDefineAll(self, markerNum, markerType, fore, back):
|
||
|
self.SCIMarkerDefine(markerNum, markerType)
|
||
|
self.SCIMarkerSetFore(markerNum, fore)
|
||
|
self.SCIMarkerSetBack(markerNum, back)
|
||
|
|
||
|
def SCIMarkerDefine(self, markerNum, markerType):
|
||
|
self.SendScintilla(scintillacon.SCI_MARKERDEFINE, markerNum, markerType)
|
||
|
|
||
|
def SCIMarkerSetFore(self, markerNum, fore):
|
||
|
self.SendScintilla(scintillacon.SCI_MARKERSETFORE, markerNum, fore)
|
||
|
|
||
|
def SCIMarkerSetBack(self, markerNum, back):
|
||
|
self.SendScintilla(scintillacon.SCI_MARKERSETBACK, markerNum, back)
|
||
|
|
||
|
def SCIMarkerAdd(self, lineNo, markerNum):
|
||
|
self.SendScintilla(scintillacon.SCI_MARKERADD, lineNo, markerNum)
|
||
|
|
||
|
def SCIMarkerDelete(self, lineNo, markerNum):
|
||
|
self.SendScintilla(scintillacon.SCI_MARKERDELETE, lineNo, markerNum)
|
||
|
|
||
|
def SCIMarkerDeleteAll(self, markerNum=-1):
|
||
|
self.SendScintilla(scintillacon.SCI_MARKERDELETEALL, markerNum)
|
||
|
|
||
|
def SCIMarkerGet(self, lineNo):
|
||
|
return self.SendScintilla(scintillacon.SCI_MARKERGET, lineNo)
|
||
|
|
||
|
def SCIMarkerNext(self, lineNo, markerNum):
|
||
|
return self.SendScintilla(scintillacon.SCI_MARKERNEXT, lineNo, markerNum)
|
||
|
|
||
|
def SCICancel(self):
|
||
|
self.SendScintilla(scintillacon.SCI_CANCEL)
|
||
|
|
||
|
# AutoComplete
|
||
|
def SCIAutoCShow(self, text):
|
||
|
if type(text) in [type([]), type(())]:
|
||
|
text = " ".join(text)
|
||
|
buff = (text + "\0").encode(default_scintilla_encoding)
|
||
|
return self.SendScintilla(scintillacon.SCI_AUTOCSHOW, 0, buff)
|
||
|
|
||
|
def SCIAutoCCancel(self):
|
||
|
self.SendScintilla(scintillacon.SCI_AUTOCCANCEL)
|
||
|
|
||
|
def SCIAutoCActive(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_AUTOCACTIVE)
|
||
|
|
||
|
def SCIAutoCComplete(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_AUTOCCOMPLETE)
|
||
|
|
||
|
def SCIAutoCStops(self, stops):
|
||
|
buff = (stops + "\0").encode(default_scintilla_encoding)
|
||
|
self.SendScintilla(scintillacon.SCI_AUTOCSTOPS, 0, buff)
|
||
|
|
||
|
def SCIAutoCSetAutoHide(self, hide):
|
||
|
self.SendScintilla(scintillacon.SCI_AUTOCSETAUTOHIDE, hide)
|
||
|
|
||
|
def SCIAutoCSetFillups(self, fillups):
|
||
|
self.SendScintilla(scintillacon.SCI_AUTOCSETFILLUPS, fillups)
|
||
|
|
||
|
# Call tips
|
||
|
def SCICallTipShow(self, text, pos=-1):
|
||
|
if pos == -1:
|
||
|
pos = self.GetSel()[0]
|
||
|
buff = (text + "\0").encode(default_scintilla_encoding)
|
||
|
self.SendScintilla(scintillacon.SCI_CALLTIPSHOW, pos, buff)
|
||
|
|
||
|
def SCICallTipCancel(self):
|
||
|
self.SendScintilla(scintillacon.SCI_CALLTIPCANCEL)
|
||
|
|
||
|
def SCICallTipActive(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_CALLTIPACTIVE)
|
||
|
|
||
|
def SCICallTipPosStart(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_CALLTIPPOSSTART)
|
||
|
|
||
|
def SCINewline(self):
|
||
|
self.SendScintilla(scintillacon.SCI_NEWLINE)
|
||
|
|
||
|
# Lexer etc
|
||
|
def SCISetKeywords(self, keywords, kw_list_no=0):
|
||
|
buff = (keywords + "\0").encode(default_scintilla_encoding)
|
||
|
self.SendScintilla(scintillacon.SCI_SETKEYWORDS, kw_list_no, buff)
|
||
|
|
||
|
def SCISetProperty(self, name, value):
|
||
|
name_buff = array.array("b", (name + "\0").encode(default_scintilla_encoding))
|
||
|
val_buff = array.array(
|
||
|
"b", (str(value) + "\0").encode(default_scintilla_encoding)
|
||
|
)
|
||
|
address_name_buffer = name_buff.buffer_info()[0]
|
||
|
address_val_buffer = val_buff.buffer_info()[0]
|
||
|
self.SendScintilla(
|
||
|
scintillacon.SCI_SETPROPERTY, address_name_buffer, address_val_buffer
|
||
|
)
|
||
|
|
||
|
def SCISetStyleBits(self, nbits):
|
||
|
self.SendScintilla(scintillacon.SCI_SETSTYLEBITS, nbits)
|
||
|
|
||
|
# Folding
|
||
|
def SCIGetFoldLevel(self, lineno):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETFOLDLEVEL, lineno)
|
||
|
|
||
|
def SCIToggleFold(self, lineno):
|
||
|
return self.SendScintilla(scintillacon.SCI_TOGGLEFOLD, lineno)
|
||
|
|
||
|
def SCIEnsureVisible(self, lineno):
|
||
|
self.SendScintilla(scintillacon.SCI_ENSUREVISIBLE, lineno)
|
||
|
|
||
|
def SCIGetFoldExpanded(self, lineno):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETFOLDEXPANDED, lineno)
|
||
|
|
||
|
# right edge
|
||
|
def SCISetEdgeColumn(self, edge):
|
||
|
self.SendScintilla(scintillacon.SCI_SETEDGECOLUMN, edge)
|
||
|
|
||
|
def SCIGetEdgeColumn(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETEDGECOLUMN)
|
||
|
|
||
|
def SCISetEdgeMode(self, mode):
|
||
|
self.SendScintilla(scintillacon.SCI_SETEDGEMODE, mode)
|
||
|
|
||
|
def SCIGetEdgeMode(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETEDGEMODE)
|
||
|
|
||
|
def SCISetEdgeColor(self, color):
|
||
|
self.SendScintilla(scintillacon.SCI_SETEDGECOLOUR, color)
|
||
|
|
||
|
def SCIGetEdgeColor(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETEDGECOLOR)
|
||
|
|
||
|
# Multi-doc
|
||
|
def SCIGetDocPointer(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETDOCPOINTER)
|
||
|
|
||
|
def SCISetDocPointer(self, p):
|
||
|
return self.SendScintilla(scintillacon.SCI_SETDOCPOINTER, 0, p)
|
||
|
|
||
|
def SCISetWrapMode(self, mode):
|
||
|
return self.SendScintilla(scintillacon.SCI_SETWRAPMODE, mode)
|
||
|
|
||
|
def SCIGetWrapMode(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETWRAPMODE)
|
||
|
|
||
|
|
||
|
class CScintillaEditInterface(ScintillaControlInterface):
|
||
|
def close(self):
|
||
|
self.colorizer = None
|
||
|
|
||
|
def Clear(self):
|
||
|
self.SendScintilla(win32con.WM_CLEAR)
|
||
|
|
||
|
def FindText(self, flags, range, findText):
|
||
|
"""LPARAM for EM_FINDTEXTEX:
|
||
|
typedef struct _findtextex {
|
||
|
CHARRANGE chrg;
|
||
|
LPCTSTR lpstrText;
|
||
|
CHARRANGE chrgText;} FINDTEXTEX;
|
||
|
typedef struct _charrange {
|
||
|
LONG cpMin;
|
||
|
LONG cpMax;} CHARRANGE;
|
||
|
"""
|
||
|
findtextex_fmt = "llPll"
|
||
|
## Scintilla does not handle unicode in EM_FINDTEXT msg (FINDTEXTEX struct)
|
||
|
txt_buff = (findText + "\0").encode(default_scintilla_encoding)
|
||
|
txt_array = array.array("b", txt_buff)
|
||
|
ft_buff = struct.pack(
|
||
|
findtextex_fmt, range[0], range[1], txt_array.buffer_info()[0], 0, 0
|
||
|
)
|
||
|
ft_array = array.array("b", ft_buff)
|
||
|
rc = self.SendScintilla(EM_FINDTEXTEX, flags, ft_array.buffer_info()[0])
|
||
|
ftUnpacked = struct.unpack(findtextex_fmt, ft_array)
|
||
|
return rc, (ftUnpacked[3], ftUnpacked[4])
|
||
|
|
||
|
def GetSel(self):
|
||
|
currentPos = self.SendScintilla(scintillacon.SCI_GETCURRENTPOS)
|
||
|
anchorPos = self.SendScintilla(scintillacon.SCI_GETANCHOR)
|
||
|
if currentPos < anchorPos:
|
||
|
return (currentPos, anchorPos)
|
||
|
else:
|
||
|
return (anchorPos, currentPos)
|
||
|
return currentPos
|
||
|
|
||
|
def GetSelText(self):
|
||
|
start, end = self.GetSel()
|
||
|
txtBuf = array.array("b", null_byte * (end - start + 1))
|
||
|
addressTxtBuf = txtBuf.buffer_info()[0]
|
||
|
# EM_GETSELTEXT is documented as returning the number of chars
|
||
|
# not including the NULL, but scintilla includes the NULL. A
|
||
|
# quick glance at the scintilla impl doesn't make this
|
||
|
# obvious - the NULL is included in the 'selection' object
|
||
|
# and reflected in the length of that 'selection' object.
|
||
|
# I expect that is a bug in scintilla and may be fixed by now,
|
||
|
# but we just blindly assume that the last char is \0 and
|
||
|
# strip it.
|
||
|
self.SendScintilla(EM_GETSELTEXT, 0, addressTxtBuf)
|
||
|
return txtBuf.tobytes()[:-1].decode(default_scintilla_encoding)
|
||
|
|
||
|
def SetSel(self, start=0, end=None):
|
||
|
if type(start) == type(()):
|
||
|
assert (
|
||
|
end is None
|
||
|
), "If you pass a point in the first param, the second must be None"
|
||
|
start, end = start
|
||
|
elif end is None:
|
||
|
end = start
|
||
|
if start < 0:
|
||
|
start = self.GetTextLength()
|
||
|
if end < 0:
|
||
|
end = self.GetTextLength()
|
||
|
assert start <= self.GetTextLength(), "The start postion is invalid (%d/%d)" % (
|
||
|
start,
|
||
|
self.GetTextLength(),
|
||
|
)
|
||
|
assert end <= self.GetTextLength(), "The end postion is invalid (%d/%d)" % (
|
||
|
end,
|
||
|
self.GetTextLength(),
|
||
|
)
|
||
|
cr = struct.pack("ll", start, end)
|
||
|
crBuff = array.array("b", cr)
|
||
|
addressCrBuff = crBuff.buffer_info()[0]
|
||
|
rc = self.SendScintilla(EM_EXSETSEL, 0, addressCrBuff)
|
||
|
|
||
|
def GetLineCount(self):
|
||
|
return self.SendScintilla(win32con.EM_GETLINECOUNT)
|
||
|
|
||
|
def LineFromChar(self, charPos=-1):
|
||
|
if charPos == -1:
|
||
|
charPos = self.GetSel()[0]
|
||
|
assert (
|
||
|
charPos >= 0 and charPos <= self.GetTextLength()
|
||
|
), "The charPos postion (%s) is invalid (max=%s)" % (
|
||
|
charPos,
|
||
|
self.GetTextLength(),
|
||
|
)
|
||
|
# return self.SendScintilla(EM_EXLINEFROMCHAR, charPos)
|
||
|
# EM_EXLINEFROMCHAR puts charPos in lParam, not wParam
|
||
|
return self.SendScintilla(EM_EXLINEFROMCHAR, 0, charPos)
|
||
|
|
||
|
def LineIndex(self, line):
|
||
|
return self.SendScintilla(win32con.EM_LINEINDEX, line)
|
||
|
|
||
|
def ScrollCaret(self):
|
||
|
return self.SendScintilla(win32con.EM_SCROLLCARET)
|
||
|
|
||
|
def GetCurLineNumber(self):
|
||
|
return self.LineFromChar(self.SCIGetCurrentPos())
|
||
|
|
||
|
def GetTextLength(self):
|
||
|
return self.SendScintilla(scintillacon.SCI_GETTEXTLENGTH)
|
||
|
|
||
|
def GetTextRange(self, start=0, end=-1, decode=True):
|
||
|
if end == -1:
|
||
|
end = self.SendScintilla(scintillacon.SCI_GETTEXTLENGTH)
|
||
|
assert end >= start, "Negative index requested (%d/%d)" % (start, end)
|
||
|
assert (
|
||
|
start >= 0 and start <= self.GetTextLength()
|
||
|
), "The start postion is invalid"
|
||
|
assert end >= 0 and end <= self.GetTextLength(), "The end postion is invalid"
|
||
|
initer = null_byte * (end - start + 1)
|
||
|
buff = array.array("b", initer)
|
||
|
addressBuffer = buff.buffer_info()[0]
|
||
|
tr = struct.pack("llP", start, end, addressBuffer)
|
||
|
trBuff = array.array("b", tr)
|
||
|
addressTrBuff = trBuff.buffer_info()[0]
|
||
|
num_bytes = self.SendScintilla(EM_GETTEXTRANGE, 0, addressTrBuff)
|
||
|
ret = buff.tobytes()[:num_bytes]
|
||
|
if decode:
|
||
|
ret = ret.decode(default_scintilla_encoding)
|
||
|
return ret
|
||
|
|
||
|
def ReplaceSel(self, str):
|
||
|
buff = (str + "\0").encode(default_scintilla_encoding)
|
||
|
self.SendScintilla(scintillacon.SCI_REPLACESEL, 0, buff)
|
||
|
|
||
|
def GetLine(self, line=-1):
|
||
|
if line == -1:
|
||
|
line = self.GetCurLineNumber()
|
||
|
start = self.LineIndex(line)
|
||
|
end = self.LineIndex(line + 1)
|
||
|
return self.GetTextRange(start, end)
|
||
|
|
||
|
def SetReadOnly(self, flag=1):
|
||
|
return self.SendScintilla(win32con.EM_SETREADONLY, flag)
|
||
|
|
||
|
def LineScroll(self, lines, cols=0):
|
||
|
return self.SendScintilla(win32con.EM_LINESCROLL, cols, lines)
|
||
|
|
||
|
def GetFirstVisibleLine(self):
|
||
|
return self.SendScintilla(win32con.EM_GETFIRSTVISIBLELINE)
|
||
|
|
||
|
def SetWordWrap(self, mode):
|
||
|
if mode != win32ui.CRichEditView_WrapNone:
|
||
|
raise ValueError("We dont support word-wrap (I dont think :-)")
|
||
|
|
||
|
|
||
|
class CScintillaColorEditInterface(CScintillaEditInterface):
|
||
|
################################
|
||
|
# Plug-in colorizer support
|
||
|
def _GetColorizer(self):
|
||
|
if not hasattr(self, "colorizer"):
|
||
|
self.colorizer = self._MakeColorizer()
|
||
|
return self.colorizer
|
||
|
|
||
|
def _MakeColorizer(self):
|
||
|
# Give parent a chance to hook.
|
||
|
parent_func = getattr(self.GetParentFrame(), "_MakeColorizer", None)
|
||
|
if parent_func is not None:
|
||
|
return parent_func()
|
||
|
from . import formatter
|
||
|
|
||
|
## return formatter.PythonSourceFormatter(self)
|
||
|
return formatter.BuiltinPythonSourceFormatter(self)
|
||
|
|
||
|
def Colorize(self, start=0, end=-1):
|
||
|
c = self._GetColorizer()
|
||
|
if c is not None:
|
||
|
c.Colorize(start, end)
|
||
|
|
||
|
def ApplyFormattingStyles(self, bReload=1):
|
||
|
c = self._GetColorizer()
|
||
|
if c is not None:
|
||
|
c.ApplyFormattingStyles(bReload)
|
||
|
|
||
|
# The Parent window will normally hook
|
||
|
def HookFormatter(self, parent=None):
|
||
|
c = self._GetColorizer()
|
||
|
if c is not None: # No need if we have no color!
|
||
|
c.HookFormatter(parent)
|
||
|
|
||
|
|
||
|
class CScintillaEdit(window.Wnd, CScintillaColorEditInterface):
|
||
|
def __init__(self, wnd=None):
|
||
|
if wnd is None:
|
||
|
wnd = win32ui.CreateWnd()
|
||
|
window.Wnd.__init__(self, wnd)
|
||
|
|
||
|
def SendScintilla(self, msg, w=0, l=0):
|
||
|
return self.SendMessage(msg, w, l)
|
||
|
|
||
|
def CreateWindow(self, style, rect, parent, id):
|
||
|
self._obj_.CreateWindow("Scintilla", "Scintilla", style, rect, parent, id, None)
|