📄 editor.cxx
字号:
// Scintilla source code edit control/** @file Editor.cxx ** Main code for the edit control. **/// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>// The License.txt file describes the conditions under which this software may be distributed.#include <stdlib.h>#include <string.h>#include <stdio.h>#include <ctype.h>#include "Platform.h"#ifndef PLAT_QT#define INCLUDE_DEPRECATED_FEATURES#endif#include "Scintilla.h"#include "ContractionState.h"#include "SVector.h"#include "CellBuffer.h"#include "KeyMap.h"#include "Indicator.h"#include "XPM.h"#include "LineMarker.h"#include "Style.h"#include "ViewStyle.h"#include "CharClassify.h"#include "Document.h"#include "Editor.h"/* return whether this modification represents an operation that may reasonably be deferred (not done now OR [possibly] at all)*/static bool CanDeferToLastStep(const DocModification& mh) { if (mh.modificationType & (SC_MOD_BEFOREINSERT|SC_MOD_BEFOREDELETE)) return true; // CAN skip if (!(mh.modificationType & (SC_PERFORMED_UNDO|SC_PERFORMED_REDO))) return false; // MUST do if (mh.modificationType & SC_MULTISTEPUNDOREDO) return true; // CAN skip return false; // PRESUMABLY must do}static bool CanEliminate(const DocModification& mh) { return (mh.modificationType & (SC_MOD_BEFOREINSERT|SC_MOD_BEFOREDELETE)) != 0;}/* return whether this modification represents the FINAL step in a [possibly lengthy] multi-step Undo/Redo sequence*/static bool IsLastStep(const DocModification& mh) { return (mh.modificationType & (SC_PERFORMED_UNDO|SC_PERFORMED_REDO)) != 0 && (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0 && (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0 && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;}Caret::Caret() :active(false), on(false), period(500) {}Timer::Timer() :ticking(false), ticksToWait(0), tickerID(0) {}Idler::Idler() :state(false), idlerID(0) {}LineLayout::LineLayout(int maxLineLength_) : lineStarts(0), lenLineStarts(0), lineNumber(-1), inCache(false), maxLineLength(-1), numCharsInLine(0), validity(llInvalid), xHighlightGuide(0), highlightColumn(0), selStart(0), selEnd(0), containsCaret(false), edgeColumn(0), chars(0), styles(0), styleBitsSet(0), indicators(0), positions(0), hsStart(0), hsEnd(0), widthLine(wrapWidthInfinite), lines(1) { Resize(maxLineLength_);}LineLayout::~LineLayout() { Free();}void LineLayout::Resize(int maxLineLength_) { if (maxLineLength_ > maxLineLength) { Free(); chars = new char[maxLineLength_ + 1]; styles = new unsigned char[maxLineLength_ + 1]; indicators = new char[maxLineLength_ + 1]; // Extra position allocated as sometimes the Windows // GetTextExtentExPoint API writes an extra element. positions = new int[maxLineLength_ + 1 + 1]; maxLineLength = maxLineLength_; }}void LineLayout::Free() { delete []chars; chars = 0; delete []styles; styles = 0; delete []indicators; indicators = 0; delete []positions; positions = 0; delete []lineStarts; lineStarts = 0;}void LineLayout::Invalidate(validLevel validity_) { if (validity > validity_) validity = validity_;}void LineLayout::SetLineStart(int line, int start) { if ((line >= lenLineStarts) && (line != 0)) { int newMaxLines = line + 20; int *newLineStarts = new int[newMaxLines]; if (!newLineStarts) return; for (int i = 0; i < newMaxLines; i++) { if (i < lenLineStarts) newLineStarts[i] = lineStarts[i]; else newLineStarts[i] = 0; } delete []lineStarts; lineStarts = newLineStarts; lenLineStarts = newMaxLines; } lineStarts[line] = start;}void LineLayout::SetBracesHighlight(Range rangeLine, Position braces[], char bracesMatchStyle, int xHighlight) { if (rangeLine.ContainsCharacter(braces[0])) { int braceOffset = braces[0] - rangeLine.start; if (braceOffset < numCharsInLine) { bracePreviousStyles[0] = styles[braceOffset]; styles[braceOffset] = bracesMatchStyle; } } if (rangeLine.ContainsCharacter(braces[1])) { int braceOffset = braces[1] - rangeLine.start; if (braceOffset < numCharsInLine) { bracePreviousStyles[1] = styles[braceOffset]; styles[braceOffset] = bracesMatchStyle; } } if ((braces[0] >= rangeLine.start && braces[1] <= rangeLine.end) || (braces[1] >= rangeLine.start && braces[0] <= rangeLine.end)) { xHighlightGuide = xHighlight; }}void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[]) { if (rangeLine.ContainsCharacter(braces[0])) { int braceOffset = braces[0] - rangeLine.start; if (braceOffset < numCharsInLine) { styles[braceOffset] = bracePreviousStyles[0]; } } if (rangeLine.ContainsCharacter(braces[1])) { int braceOffset = braces[1] - rangeLine.start; if (braceOffset < numCharsInLine) { styles[braceOffset] = bracePreviousStyles[1]; } } xHighlightGuide = 0;}LineLayoutCache::LineLayoutCache() : level(0), length(0), size(0), cache(0), allInvalidated(false), styleClock(-1), useCount(0) { Allocate(0);}LineLayoutCache::~LineLayoutCache() { Deallocate();}void LineLayoutCache::Allocate(int length_) { PLATFORM_ASSERT(cache == NULL); allInvalidated = false; length = length_; size = length; if (size > 1) { size = (size / 16 + 1) * 16; } if (size > 0) { cache = new LineLayout * [size]; } for (int i = 0; i < size; i++) cache[i] = 0;}void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) { PLATFORM_ASSERT(useCount == 0); int lengthForLevel = 0; if (level == llcCaret) { lengthForLevel = 1; } else if (level == llcPage) { lengthForLevel = linesOnScreen + 1; } else if (level == llcDocument) { lengthForLevel = linesInDoc; } if (lengthForLevel > size) { Deallocate(); Allocate(lengthForLevel); } else { if (lengthForLevel < length) { for (int i = lengthForLevel; i < length; i++) { delete cache[i]; cache[i] = 0; } } length = lengthForLevel; } PLATFORM_ASSERT(length == lengthForLevel); PLATFORM_ASSERT(cache != NULL || length == 0);}void LineLayoutCache::Deallocate() { PLATFORM_ASSERT(useCount == 0); for (int i = 0; i < length; i++) delete cache[i]; delete []cache; cache = 0; length = 0; size = 0;}void LineLayoutCache::Invalidate(LineLayout::validLevel validity_) { if (cache && !allInvalidated) { for (int i = 0; i < length; i++) { if (cache[i]) { cache[i]->Invalidate(validity_); } } if (validity_ == LineLayout::llInvalid) { allInvalidated = true; } }}void LineLayoutCache::SetLevel(int level_) { allInvalidated = false; if ((level_ != -1) && (level != level_)) { level = level_; Deallocate(); }}LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_, int linesOnScreen, int linesInDoc) { AllocateForLevel(linesOnScreen, linesInDoc); if (styleClock != styleClock_) { Invalidate(LineLayout::llCheckTextAndStyle); styleClock = styleClock_; } allInvalidated = false; int pos = -1; LineLayout *ret = 0; if (level == llcCaret) { pos = 0; } else if (level == llcPage) { if (lineNumber == lineCaret) { pos = 0; } else if (length > 1) { pos = 1 + (lineNumber % (length - 1)); } } else if (level == llcDocument) { pos = lineNumber; } if (pos >= 0) { PLATFORM_ASSERT(useCount == 0); if (cache && (pos < length)) { if (cache[pos]) { if ((cache[pos]->lineNumber != lineNumber) || (cache[pos]->maxLineLength < maxChars)) { delete cache[pos]; cache[pos] = 0; } } if (!cache[pos]) { cache[pos] = new LineLayout(maxChars); } if (cache[pos]) { cache[pos]->lineNumber = lineNumber; cache[pos]->inCache = true; ret = cache[pos]; useCount++; } } } if (!ret) { ret = new LineLayout(maxChars); ret->lineNumber = lineNumber; } return ret;}void LineLayoutCache::Dispose(LineLayout *ll) { allInvalidated = false; if (ll) { if (!ll->inCache) { delete ll; } else { useCount--; } }}Editor::Editor() { ctrlID = 0; stylesValid = false; printMagnification = 0; printColourMode = SC_PRINT_NORMAL; printWrapState = eWrapWord; cursorMode = SC_CURSORNORMAL; controlCharSymbol = 0; /* Draw the control characters */ hasFocus = false; hideSelection = false; inOverstrike = false; errorStatus = 0; mouseDownCaptures = true; bufferedDraw = true; twoPhaseDraw = true; lastClickTime = 0; dwellDelay = SC_TIME_FOREVER; ticksToDwell = SC_TIME_FOREVER; dwelling = false; ptMouseLast.x = 0; ptMouseLast.y = 0; inDragDrop = false; dropWentOutside = false; posDrag = invalidPosition; posDrop = invalidPosition; selectionType = selChar; lastXChosen = 0; lineAnchor = 0; originalAnchorPos = 0; selType = selStream; moveExtendsSelection = false; xStartSelect = 0; xEndSelect = 0; primarySelection = true; caretXPolicy = CARET_SLOP | CARET_EVEN; caretXSlop = 50; caretYPolicy = CARET_EVEN; caretYSlop = 0; searchAnchor = 0; xOffset = 0; xCaretMargin = 50; horizontalScrollBarVisible = true; scrollWidth = 2000; verticalScrollBarVisible = true; endAtLastLine = true; caretSticky = false; pixmapLine = Surface::Allocate(); pixmapSelMargin = Surface::Allocate(); pixmapSelPattern = Surface::Allocate(); pixmapIndentGuide = Surface::Allocate(); pixmapIndentGuideHighlight = Surface::Allocate(); currentPos = 0; anchor = 0; targetStart = 0; targetEnd = 0; searchFlags = 0; topLine = 0; posTopLine = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -