?? editor.cxx
字號(hào):
topLine = 0;
posTopLine = 0;
lengthForEncode = -1;
needUpdateUI = true;
braces[0] = invalidPosition;
braces[1] = invalidPosition;
bracesMatchStyle = STYLE_BRACEBAD;
highlightGuideColumn = 0;
theEdge = 0;
paintState = notPainting;
modEventMask = SC_MODEVENTMASKALL;
pdoc = new Document();
pdoc->AddRef();
pdoc->AddWatcher(this, 0);
recordingMacro = false;
foldFlags = 0;
wrapState = eWrapNone;
wrapWidth = LineLayout::wrapWidthInfinite;
wrapStart = wrapLineLarge;
wrapEnd = wrapLineLarge;
wrapVisualFlags = 0;
wrapVisualFlagsLocation = 0;
wrapVisualStartIndent = 0;
actualWrapVisualStartIndent = 0;
convertPastes = true;
hsStart = -1;
hsEnd = -1;
llc.SetLevel(LineLayoutCache::llcCaret);
}
Editor::~Editor() {
pdoc->RemoveWatcher(this, 0);
pdoc->Release();
pdoc = 0;
DropGraphics();
delete pixmapLine;
delete pixmapSelMargin;
delete pixmapSelPattern;
delete pixmapIndentGuide;
delete pixmapIndentGuideHighlight;
}
void Editor::Finalise() {
SetIdle(false);
CancelModes();
}
void Editor::DropGraphics() {
pixmapLine->Release();
pixmapSelMargin->Release();
pixmapSelPattern->Release();
pixmapIndentGuide->Release();
pixmapIndentGuideHighlight->Release();
}
void Editor::InvalidateStyleData() {
stylesValid = false;
palette.Release();
DropGraphics();
llc.Invalidate(LineLayout::llInvalid);
if (selType == selRectangle) {
xStartSelect = XFromPosition(anchor);
xEndSelect = XFromPosition(currentPos);
}
}
void Editor::InvalidateStyleRedraw() {
NeedWrapping();
InvalidateStyleData();
Redraw();
}
void Editor::RefreshColourPalette(Palette &pal, bool want) {
vs.RefreshColourPalette(pal, want);
}
void Editor::RefreshStyleData() {
if (!stylesValid) {
stylesValid = true;
AutoSurface surface(this);
if (surface) {
vs.Refresh(*surface);
RefreshColourPalette(palette, true);
palette.Allocate(wMain);
RefreshColourPalette(palette, false);
}
SetScrollBars();
}
}
PRectangle Editor::GetClientRectangle() {
return wMain.GetClientPosition();
}
PRectangle Editor::GetTextRectangle() {
PRectangle rc = GetClientRectangle();
rc.left += vs.fixedColumnWidth;
rc.right -= vs.rightMarginWidth;
return rc;
}
int Editor::LinesOnScreen() {
PRectangle rcClient = GetClientRectangle();
int htClient = rcClient.bottom - rcClient.top;
//Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
return htClient / vs.lineHeight;
}
int Editor::LinesToScroll() {
int retVal = LinesOnScreen() - 1;
if (retVal < 1)
return 1;
else
return retVal;
}
int Editor::MaxScrollPos() {
//Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
//LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
int retVal = cs.LinesDisplayed();
if (endAtLastLine) {
retVal -= LinesOnScreen();
} else {
retVal--;
}
if (retVal < 0) {
return 0;
} else {
return retVal;
}
}
static inline bool IsControlCharacter(int ch) {
// iscntrl returns true for lots of chars > 127 which are displayable
return ch >= 0 && ch < ' ';
}
const char *ControlCharacterString(unsigned char ch) {
const char *reps[] = {
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
"BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
"CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
};
if (ch < (sizeof(reps) / sizeof(reps[0]))) {
return reps[ch];
} else {
return "BAD";
}
}
/**
* Convenience class to ensure LineLayout objects are always disposed.
*/
class AutoLineLayout {
LineLayoutCache &llc;
LineLayout *ll;
AutoLineLayout &operator=(const AutoLineLayout &) { return * this; }
public:
AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) : llc(llc_), ll(ll_) {}
~AutoLineLayout() {
llc.Dispose(ll);
ll = 0;
}
LineLayout *operator->() const {
return ll;
}
operator LineLayout *() const {
return ll;
}
void Set(LineLayout *ll_) {
llc.Dispose(ll);
ll = ll_;
}
};
/**
* Allows to iterate through the lines of a selection.
* Althought it can be called for a stream selection, in most cases
* it is inefficient and it should be used only for
* a rectangular or a line selection.
*/
class SelectionLineIterator {
private:
Editor *ed;
int line; ///< Current line within the iteration.
bool forward; ///< True if iterating by increasing line number, false otherwise.
int selStart, selEnd; ///< Positions of the start and end of the selection relative to the start of the document.
int minX, maxX; ///< Left and right of selection rectangle.
public:
int lineStart, lineEnd; ///< Line numbers, first and last lines of the selection.
int startPos, endPos; ///< Positions of the beginning and end of the selection on the current line.
void Reset() {
if (forward) {
line = lineStart;
} else {
line = lineEnd;
}
}
SelectionLineIterator(Editor *ed_, bool forward_ = true) : line(0), startPos(0), endPos(0) {
ed = ed_;
forward = forward_;
selStart = ed->SelectionStart();
selEnd = ed->SelectionEnd();
lineStart = ed->pdoc->LineFromPosition(selStart);
lineEnd = ed->pdoc->LineFromPosition(selEnd);
// Left of rectangle
minX = Platform::Minimum(ed->xStartSelect, ed->xEndSelect);
// Right of rectangle
maxX = Platform::Maximum(ed->xStartSelect, ed->xEndSelect);
Reset();
}
~SelectionLineIterator() {}
void SetAt(int line) {
if (line < lineStart || line > lineEnd) {
startPos = endPos = INVALID_POSITION;
} else {
if (ed->selType == ed->selRectangle) {
// Measure line and return character closest to minX
startPos = ed->PositionFromLineX(line, minX);
// Measure line and return character closest to maxX
endPos = ed->PositionFromLineX(line, maxX);
} else if (ed->selType == ed->selLines) {
startPos = ed->pdoc->LineStart(line);
endPos = ed->pdoc->LineStart(line + 1);
} else { // Stream selection, here only for completion
if (line == lineStart) {
startPos = selStart;
} else {
startPos = ed->pdoc->LineStart(line);
}
if (line == lineEnd) {
endPos = selEnd;
} else {
endPos = ed->pdoc->LineStart(line + 1);
}
}
}
}
bool Iterate() {
SetAt(line);
if (forward) {
line++;
} else {
line--;
}
return startPos != INVALID_POSITION;
}
};
Point Editor::LocationFromPosition(int pos) {
Point pt;
RefreshStyleData();
if (pos == INVALID_POSITION)
return pt;
int line = pdoc->LineFromPosition(pos);
int lineVisible = cs.DisplayFromDoc(line);
//Platform::DebugPrintf("line=%d\n", line);
AutoSurface surface(this);
AutoLineLayout ll(llc, RetrieveLineLayout(line));
if (surface && ll) {
// -1 because of adding in for visible lines in following loop.
pt.y = (lineVisible - topLine - 1) * vs.lineHeight;
pt.x = 0;
unsigned int posLineStart = pdoc->LineStart(line);
LayoutLine(line, surface, vs, ll, wrapWidth);
int posInLine = pos - posLineStart;
// In case of very long line put x at arbitrary large position
if (posInLine > ll->maxLineLength) {
pt.x = ll->positions[ll->maxLineLength] - ll->positions[ll->LineStart(ll->lines)];
}
for (int subLine = 0; subLine < ll->lines; subLine++) {
if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {
pt.x = ll->positions[posInLine] - ll->positions[ll->LineStart(subLine)];
if (actualWrapVisualStartIndent != 0) {
int lineStart = ll->LineStart(subLine);
if (lineStart != 0) // Wrapped
pt.x += actualWrapVisualStartIndent * vs.aveCharWidth;
}
}
if (posInLine >= ll->LineStart(subLine)) {
pt.y += vs.lineHeight;
}
}
pt.x += vs.fixedColumnWidth - xOffset;
}
return pt;
}
int Editor::XFromPosition(int pos) {
Point pt = LocationFromPosition(pos);
return pt.x - vs.fixedColumnWidth + xOffset;
}
int Editor::LineFromLocation(Point pt) {
return cs.DocFromDisplay(pt.y / vs.lineHeight + topLine);
}
void Editor::SetTopLine(int topLineNew) {
topLine = topLineNew;
posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine));
}
static inline bool IsEOLChar(char ch) {
return (ch == '\r') || (ch == '\n');
}
int Editor::PositionFromLocation(Point pt) {
RefreshStyleData();
pt.x = pt.x - vs.fixedColumnWidth + xOffset;
int visibleLine = pt.y / vs.lineHeight + topLine;
if (pt.y < 0) { // Division rounds towards 0
visibleLine = (pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine;
}
if (visibleLine < 0)
visibleLine = 0;
int lineDoc = cs.DocFromDisplay(visibleLine);
if (lineDoc >= pdoc->LinesTotal())
return pdoc->Length();
unsigned int posLineStart = pdoc->LineStart(lineDoc);
int retVal = posLineStart;
AutoSurface surface(this);
AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
if (surface && ll) {
LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
int lineStartSet = cs.DisplayFromDoc(lineDoc);
int subLine = visibleLine - lineStartSet;
if (subLine < ll->lines) {
int lineStart = ll->LineStart(subLine);
int lineEnd = ll->LineStart(subLine + 1);
int subLineStart = ll->positions[lineStart];
if (actualWrapVisualStartIndent != 0) {
if (lineStart != 0) // Wrapped
pt.x -= actualWrapVisualStartIndent * vs.aveCharWidth;
}
for (int i = lineStart; i < lineEnd; i++) {
if (pt.x < (((ll->positions[i] + ll->positions[i + 1]) / 2) - subLineStart) ||
IsEOLChar(ll->chars[i])) {
return pdoc->MovePositionOutsideChar(i + posLineStart, 1);
}
}
return lineEnd + posLineStart;
}
retVal = ll->numCharsInLine + posLineStart;
}
return retVal;
}
// Like PositionFromLocation but INVALID_POSITION returned when not near any text.
int Editor::PositionFromLocationClose(Point pt) {
RefreshStyleData();
PRectangle rcClient = GetTextRectangle();
if (!rcClient.Contains(pt))
return INVALID_POSITION;
if (pt.x < vs.fixedColumnWidth)
return INVALID_POSITION;
if (pt.y < 0)
return INVALID_POSITION;
pt.x = pt.x - vs.fixedColumnWidth + xOffset;
int visibleLine = pt.y / vs.lineHeight + topLine;
if (pt.y < 0) { // Division rounds towards 0
visibleLine = (pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine;
}
int lineDoc = cs.DocFromDisplay(visibleLine);
if (lineDoc < 0)
return INVALID_POSITION;
if (lineDoc >= pdoc->LinesTotal())
return INVALID_POSITION;
AutoSurface surface(this);
AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
if (surface && ll) {
LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
unsigned int posLineStart = pdoc->LineStart(lineDoc);
int lineStartSet = cs.DisplayFromDoc(lineDoc);
int subLine = visibleLine - lineStartSet;
if (subLine < ll->lines) {
int lineStart = ll->LineStart(subLine);
int lineEnd = ll->LineStart(subLine + 1);
int subLineStart = ll->positions[lineStart];
if (actualWrapVisualStartIndent != 0) {
if (lineStart != 0) // Wrapped
pt.x -= actualWrapVisualStartIndent * vs.aveCharWidth;
}
for (int i = lineStart; i < lineEnd; i++) {
if (pt.x < (((ll->positions[i] + ll->positions[i + 1]) / 2) - subLineStart) ||
IsEOLChar(ll->chars[i])) {
return pdoc->MovePositionOutsideChar(i + posLineStart, 1);
}
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -