⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 document.cxx

📁 porting scintilla to qt
💻 CXX
📖 第 1 页 / 共 3 页
字号:
// Scintilla source code edit control/** @file Document.cxx ** Text document that handles notifications, DBCS, styling, words and end of line. **/// Copyright 1998-2003 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"#include "Scintilla.h"#include "SplitVector.h"#include "Partitioning.h"#include "RunStyles.h"#include "CellBuffer.h"#include "CharClassify.h"#include "Decoration.h"#include "Document.h"#include "RESearch.h"#ifdef SCI_NAMESPACEusing namespace Scintilla;#endif// This is ASCII specific but is safe with chars >= 0x80static inline bool isspacechar(unsigned char ch) {	return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));}static inline bool IsPunctuation(char ch) {	return isascii(ch) && ispunct(ch);}static inline bool IsADigit(char ch) {	return isascii(ch) && isdigit(ch);}static inline bool IsLowerCase(char ch) {	return isascii(ch) && islower(ch);}static inline bool IsUpperCase(char ch) {	return isascii(ch) && isupper(ch);}Document::Document() {	refCount = 0;#ifdef unix	eolMode = SC_EOL_LF;#else	eolMode = SC_EOL_CRLF;#endif	dbcsCodePage = 0;	stylingBits = 5;	stylingBitsMask = 0x1F;	stylingMask = 0;	endStyled = 0;	styleClock = 0;	enteredModification = 0;	enteredStyling = 0;	enteredReadOnlyCount = 0;	tabInChars = 8;	indentInChars = 0;	actualIndentInChars = 8;	useTabs = true;	tabIndents = true;	backspaceUnindents = false;	watchers = 0;	lenWatchers = 0;	matchesValid = false;	pre = 0;	substituted = 0;}Document::~Document() {	for (int i = 0; i < lenWatchers; i++) {		watchers[i].watcher->NotifyDeleted(this, watchers[i].userData);	}	delete []watchers;	watchers = 0;	lenWatchers = 0;	delete pre;	pre = 0;	delete []substituted;	substituted = 0;}// Increase reference count and return its previous value.int Document::AddRef() {	return refCount++;}// Decrease reference count and return its previous value.// Delete the document if reference count reaches zero.int Document::Release() {	int curRefCount = --refCount;	if (curRefCount == 0)		delete this;	return curRefCount;}void Document::SetSavePoint() {	cb.SetSavePoint();	NotifySavePoint(true);}int Document::AddMark(int line, int markerNum) {	int prev = cb.AddMark(line, markerNum);	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);	NotifyModified(mh);	return prev;}void Document::AddMarkSet(int line, int valueSet) {	unsigned int m = valueSet;	for (int i = 0; m; i++, m >>= 1)		if (m & 1)			cb.AddMark(line, i);	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);	NotifyModified(mh);}void Document::DeleteMark(int line, int markerNum) {	cb.DeleteMark(line, markerNum);	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);	NotifyModified(mh);}void Document::DeleteMarkFromHandle(int markerHandle) {	cb.DeleteMarkFromHandle(markerHandle);	DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);	mh.line = -1;	NotifyModified(mh);}void Document::DeleteAllMarks(int markerNum) {	cb.DeleteAllMarks(markerNum);	DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);	mh.line = -1;	NotifyModified(mh);}int Document::LineStart(int line) const {	return cb.LineStart(line);}int Document::LineEnd(int line) const {	if (line == LinesTotal() - 1) {		return LineStart(line + 1);	} else {		int position = LineStart(line + 1) - 1;		// When line terminator is CR+LF, may need to go back one more		if ((position > LineStart(line)) && (cb.CharAt(position - 1) == '\r')) {			position--;		}		return position;	}}int Document::LineFromPosition(int pos) {	return cb.LineFromPosition(pos);}int Document::LineEndPosition(int position) {	return LineEnd(LineFromPosition(position));}int Document::VCHomePosition(int position) {	int line = LineFromPosition(position);	int startPosition = LineStart(line);	int endLine = LineStart(line + 1) - 1;	int startText = startPosition;	while (startText < endLine && (cb.CharAt(startText) == ' ' || cb.CharAt(startText) == '\t' ) )		startText++;	if (position == startText)		return startPosition;	else		return startText;}int Document::SetLevel(int line, int level) {	int prev = cb.SetLevel(line, level);	if (prev != level) {		DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER,		                   LineStart(line), 0, 0, 0, line);		mh.foldLevelNow = level;		mh.foldLevelPrev = prev;		NotifyModified(mh);	}	return prev;}static bool IsSubordinate(int levelStart, int levelTry) {	if (levelTry & SC_FOLDLEVELWHITEFLAG)		return true;	else		return (levelStart & SC_FOLDLEVELNUMBERMASK) < (levelTry & SC_FOLDLEVELNUMBERMASK);}int Document::GetLastChild(int lineParent, int level) {	if (level == -1)		level = GetLevel(lineParent) & SC_FOLDLEVELNUMBERMASK;	int maxLine = LinesTotal();	int lineMaxSubord = lineParent;	while (lineMaxSubord < maxLine - 1) {		EnsureStyledTo(LineStart(lineMaxSubord + 2));		if (!IsSubordinate(level, GetLevel(lineMaxSubord + 1)))			break;		lineMaxSubord++;	}	if (lineMaxSubord > lineParent) {		if (level > (GetLevel(lineMaxSubord + 1) & SC_FOLDLEVELNUMBERMASK)) {			// Have chewed up some whitespace that belongs to a parent so seek back			if (GetLevel(lineMaxSubord) & SC_FOLDLEVELWHITEFLAG) {				lineMaxSubord--;			}		}	}	return lineMaxSubord;}int Document::GetFoldParent(int line) {	int level = GetLevel(line) & SC_FOLDLEVELNUMBERMASK;	int lineLook = line - 1;	while ((lineLook > 0) && (	            (!(GetLevel(lineLook) & SC_FOLDLEVELHEADERFLAG)) ||	            ((GetLevel(lineLook) & SC_FOLDLEVELNUMBERMASK) >= level))	      ) {		lineLook--;	}	if ((GetLevel(lineLook) & SC_FOLDLEVELHEADERFLAG) &&	        ((GetLevel(lineLook) & SC_FOLDLEVELNUMBERMASK) < level)) {		return lineLook;	} else {		return -1;	}}int Document::ClampPositionIntoDocument(int pos) {	return Platform::Clamp(pos, 0, Length());}bool Document::IsCrLf(int pos) {	if (pos < 0)		return false;	if (pos >= (Length() - 1))		return false;	return (cb.CharAt(pos) == '\r') && (cb.CharAt(pos + 1) == '\n');}static const int maxBytesInDBCSCharacter=5;int Document::LenChar(int pos) {	if (pos < 0) {		return 1;	} else if (IsCrLf(pos)) {		return 2;	} else if (SC_CP_UTF8 == dbcsCodePage) {		unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));		if (ch < 0x80)			return 1;		int len = 2;		if (ch >= (0x80 + 0x40 + 0x20 + 0x10))			len = 4;		else if (ch >= (0x80 + 0x40 + 0x20))			len = 3;		int lengthDoc = Length();		if ((pos + len) > lengthDoc)			return lengthDoc -pos;		else			return len;	} else if (dbcsCodePage) {		char mbstr[maxBytesInDBCSCharacter+1];		int i;		for (i=0; i<Platform::DBCSCharMaxLength(); i++) {			mbstr[i] = cb.CharAt(pos+i);		}		mbstr[i] = '\0';		return Platform::DBCSCharLength(dbcsCodePage, mbstr);	} else {		return 1;	}}static bool IsTrailByte(int ch) {	return (ch >= 0x80) && (ch < (0x80 + 0x40));}static int BytesFromLead(int leadByte) {	if (leadByte > 0xF4) {		// Characters longer than 4 bytes not possible in current UTF-8		return 0;	} else if (leadByte >= 0xF0) {		return 4;	} else if (leadByte >= 0xE0) {		return 3;	} else if (leadByte >= 0xC2) {		return 2;	}	return 0;}bool Document::InGoodUTF8(int pos, int &start, int &end) {	int lead = pos;	while ((lead>0) && (pos-lead < 4) && IsTrailByte(static_cast<unsigned char>(cb.CharAt(lead-1))))		lead--;	start = 0;	if (lead > 0) {		start = lead-1;	}	int leadByte = static_cast<unsigned char>(cb.CharAt(start));	int bytes = BytesFromLead(leadByte);	if (bytes == 0) {		return false;	} else {		int trailBytes = bytes - 1;		int len = pos - lead + 1;		if (len > trailBytes)			// pos too far from lead			return false;		// Check that there are enough trails for this lead		int trail = pos + 1;		while ((trail-lead<trailBytes) && (trail < Length())) {			if (!IsTrailByte(static_cast<unsigned char>(cb.CharAt(trail)))) {				return false;			}			trail++;		}		end = start + bytes;		return true;	}}// Normalise a position so that it is not halfway through a two byte character.// This can occur in two situations -// When lines are terminated with \r\n pairs which should be treated as one character.// When displaying DBCS text such as Japanese.// If moving, move the position in the indicated direction.int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) {	//Platform::DebugPrintf("NoCRLF %d %d\n", pos, moveDir);	// If out of range, just return minimum/maximum value.	if (pos <= 0)		return 0;	if (pos >= Length())		return Length();	// PLATFORM_ASSERT(pos > 0 && pos < Length());	if (checkLineEnd && IsCrLf(pos - 1)) {		if (moveDir > 0)			return pos + 1;		else			return pos - 1;	}	// Not between CR and LF	if (dbcsCodePage) {		if (SC_CP_UTF8 == dbcsCodePage) {			unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));			int startUTF = pos;			int endUTF = pos;			if (IsTrailByte(ch) && InGoodUTF8(pos, startUTF, endUTF)) {				// ch is a trail byte within a UTF-8 character				if (moveDir > 0)					pos = endUTF;				else					pos = startUTF;			}		} else {			// Anchor DBCS calculations at start of line because start of line can			// not be a DBCS trail byte.			int posCheck = LineStart(LineFromPosition(pos));			while (posCheck < pos) {				char mbstr[maxBytesInDBCSCharacter+1];				int i;				for(i=0;i<Platform::DBCSCharMaxLength();i++) {					mbstr[i] = cb.CharAt(posCheck+i);				}				mbstr[i] = '\0';				int mbsize = Platform::DBCSCharLength(dbcsCodePage, mbstr);				if (posCheck + mbsize == pos) {					return pos;				} else if (posCheck + mbsize > pos) {					if (moveDir > 0) {						return posCheck + mbsize;					} else {						return posCheck;					}				}				posCheck += mbsize;			}		}	}	return pos;}void Document::ModifiedAt(int pos) {	if (endStyled > pos)		endStyled = pos;}void Document::CheckReadOnly() {	if (cb.IsReadOnly() && enteredReadOnlyCount == 0) {		enteredReadOnlyCount++;		NotifyModifyAttempt();		enteredReadOnlyCount--;	}}// Document only modified by gateways DeleteChars, InsertString, Undo, Redo, and SetStyleAt.// SetStyleAt does not change the persistent state of a documentbool Document::DeleteChars(int pos, int len) {	if (len == 0)		return false;	if ((pos + len) > Length())		return false;	CheckReadOnly();	if (enteredModification != 0) {		return false;	} else {		enteredModification++;		if (!cb.IsReadOnly()) {			NotifyModified(			    DocModification(			        SC_MOD_BEFOREDELETE | SC_PERFORMED_USER,			        pos, len,			        0, 0));			int prevLinesTotal = LinesTotal();			bool startSavePoint = cb.IsSavePoint();			bool startSequence = false;			const char *text = cb.DeleteChars(pos, len, startSequence);			if (startSavePoint && cb.IsCollectingUndo())				NotifySavePoint(!startSavePoint);			if ((pos < Length()) || (pos == 0))				ModifiedAt(pos);			else				ModifiedAt(pos-1);			NotifyModified(			    DocModification(			        SC_MOD_DELETETEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0),			        pos, len,			        LinesTotal() - prevLinesTotal, text));		}		enteredModification--;	}	return !cb.IsReadOnly();}/** * Insert a string with a length. */bool Document::InsertString(int position, const char *s, int insertLength) {	if (insertLength <= 0) {		return false;	}	CheckReadOnly();	if (enteredModification != 0) {		return false;	} else {		enteredModification++;		if (!cb.IsReadOnly()) {			NotifyModified(			    DocModification(			        SC_MOD_BEFOREINSERT | SC_PERFORMED_USER,			        position, insertLength,			        0, s));			int prevLinesTotal = LinesTotal();			bool startSavePoint = cb.IsSavePoint();			bool startSequence = false;			const char *text = cb.InsertString(position, s, insertLength, startSequence);			if (startSavePoint && cb.IsCollectingUndo())				NotifySavePoint(!startSavePoint);			ModifiedAt(position);			NotifyModified(			    DocModification(			        SC_MOD_INSERTTEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0),			        position, insertLength,			        LinesTotal() - prevLinesTotal, text));		}		enteredModification--;	}	return !cb.IsReadOnly();}int Document::Undo() {	int newPos = -1;	CheckReadOnly();	if (enteredModification == 0) {		enteredModification++;		if (!cb.IsReadOnly()) {			bool startSavePoint = cb.IsSavePoint();			bool multiLine = false;			int steps = cb.StartUndo();			//Platform::DebugPrintf("Steps=%d\n", steps);			for (int step = 0; step < steps; step++) {				const int prevLinesTotal = LinesTotal();				const Action &action = cb.GetUndoStep();				if (action.at == removeAction) {					NotifyModified(DocModification(									SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action));				} else {					NotifyModified(DocModification(									SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action));				}				cb.PerformUndoStep();				int cellPosition = action.position;				ModifiedAt(cellPosition);				newPos = cellPosition;				int modFlags = SC_PERFORMED_UNDO;				// With undo, an insertion action becomes a deletion notification				if (action.at == removeAction) {					newPos += action.lenData;					modFlags |= SC_MOD_INSERTTEXT;				} else {					modFlags |= SC_MOD_DELETETEXT;				}				if (steps > 1)					modFlags |= SC_MULTISTEPUNDOREDO;				const int linesAdded = LinesTotal() - prevLinesTotal;				if (linesAdded != 0)					multiLine = true;				if (step == steps - 1) {					modFlags |= SC_LASTSTEPINUNDOREDO;					if (multiLine)						modFlags |= SC_MULTILINEUNDOREDO;				}				NotifyModified(DocModification(modFlags, cellPosition, action.lenData,											   linesAdded, action.data));			}			bool endSavePoint = cb.IsSavePoint();			if (startSavePoint != endSavePoint)				NotifySavePoint(endSavePoint);		}		enteredModification--;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -