diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Editor.cxx | 21 | ||||
| -rw-r--r-- | src/Editor.h | 1 | ||||
| -rw-r--r-- | src/KeyMap.cxx | 1 | ||||
| -rw-r--r-- | src/KeyWords.cxx | 1 | ||||
| -rw-r--r-- | src/LexCSS.cxx | 234 | ||||
| -rw-r--r-- | src/LexHTML.cxx | 42 | 
6 files changed, 284 insertions, 16 deletions
| diff --git a/src/Editor.cxx b/src/Editor.cxx index 76ba18565..2af278b19 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -3134,6 +3134,7 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, unsigned long wParam, long  	case SCI_LINECUT:  	case SCI_LINEDELETE:  	case SCI_LINETRANSPOSE: +	case SCI_LINEDUPLICATE:  	case SCI_LOWERCASE:  	case SCI_UPPERCASE:  	case SCI_LINESCROLLDOWN: @@ -3234,6 +3235,22 @@ void Editor::LineTranspose() {  	}  } +void Editor::LineDuplicate() { +	int line = pdoc->LineFromPosition(currentPos); +	int start = pdoc->LineStart(line); +	int end = pdoc->LineEnd(line); +	char *thisLine = CopyRange(start, end); +	const char *eol = "\n"; +	if (pdoc->eolMode == SC_EOL_CRLF) { +		eol = "\r\n"; +	} else if (pdoc->eolMode == SC_EOL_CR) { +		eol = "\r"; +	} +	pdoc->InsertString(end, eol); +	pdoc->InsertString(end + strlen(eol), thisLine, end - start); +	delete []thisLine; +} +  void Editor::CancelModes() {}  void Editor::NewLine() { @@ -3518,6 +3535,9 @@ int Editor::KeyCommand(unsigned int iMessage) {  	case SCI_LINETRANSPOSE:  		LineTranspose();  		break; +	case SCI_LINEDUPLICATE: +		LineDuplicate(); +		break;  	case SCI_LOWERCASE:  		ChangeCaseOfSelection(false);  		break; @@ -5665,6 +5685,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  	case SCI_LINECUT:  	case SCI_LINEDELETE:  	case SCI_LINETRANSPOSE: +	case SCI_LINEDUPLICATE:  	case SCI_LOWERCASE:  	case SCI_UPPERCASE:  	case SCI_LINESCROLLDOWN: diff --git a/src/Editor.h b/src/Editor.h index 3d99676ae..d4cbe50ff 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -404,6 +404,7 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	void PageMove(int direction, bool extend=false);  	void ChangeCaseOfSelection(bool makeUpperCase);  	void LineTranspose(); +	void LineDuplicate();  	virtual void CancelModes();  	void NewLine();  	void CursorUpOrDown(int direction, bool extend=false); diff --git a/src/KeyMap.cxx b/src/KeyMap.cxx index c91e6c6cc..4e580e8e6 100644 --- a/src/KeyMap.cxx +++ b/src/KeyMap.cxx @@ -127,6 +127,7 @@ const KeyToCommand KeyMap::MapDefault[] = {      {'L', 			SCI_CTRL,	SCI_LINECUT},      {'L', 			SCI_CSHIFT,	SCI_LINEDELETE},      {'T', 			SCI_CTRL,	SCI_LINETRANSPOSE}, +    {'D', 			SCI_CTRL,	SCI_LINEDUPLICATE},      {'U', 			SCI_CTRL,	SCI_LOWERCASE},      {'U', 			SCI_CSHIFT,	SCI_UPPERCASE},      {0,0,0}, diff --git a/src/KeyWords.cxx b/src/KeyWords.cxx index d9682b606..6183916c6 100644 --- a/src/KeyWords.cxx +++ b/src/KeyWords.cxx @@ -151,6 +151,7 @@ int Scintilla_LinkLexers() {  	LINK_LEXER(lmCPPNoCase);  	LINK_LEXER(lmTCL);  	LINK_LEXER(lmNncrontab); +	LINK_LEXER(lmCss);  	LINK_LEXER(lmEiffel);  	LINK_LEXER(lmEiffelkw);  	LINK_LEXER(lmFortran); diff --git a/src/LexCSS.cxx b/src/LexCSS.cxx new file mode 100644 index 000000000..fcf39a5c1 --- /dev/null +++ b/src/LexCSS.cxx @@ -0,0 +1,234 @@ +// Scintilla source code edit control +/** @file LexCSS.cxx + ** Lexer for Cascade Style Sheets + ** Written by Jakub Vrána + **/ +// Copyright 1998-2002 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 <ctype.h> +#include <stdio.h> +#include <stdarg.h> + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + + + +static inline bool IsAWordChar(const unsigned int ch) { +	return (isalnum(ch) || ch == '-' || ch >= 161); +} + +inline bool IsCssOperator(const char ch) { +	if (!isalnum(ch) && (ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' || ch == '.' || ch == '#' || ch == '!' || ch == '@')) +		return true; +	return false; +} + +static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { +	WordList &keywords = *keywordlists[0]; +	WordList &pseudoClasses = *keywordlists[1]; + +	StyleContext sc(startPos, length, initStyle, styler); + +	int lastState = -1; // before operator +	int lastStateC = -1; // before comment +	int op = ' '; // last operator + +	for (; sc.More(); sc.Forward()) { +		if (sc.state == SCE_CSS_COMMENT && sc.Match('*', '/')) { +			if (lastStateC == -1) { +				// backtrack to get last state +				unsigned int i = startPos; +				for (; i > 0; i--) { +					if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) { +						if (lastStateC == SCE_CSS_OPERATOR) { +							op = styler.SafeGetCharAt(i-1); +							while (--i) { +								lastState = styler.StyleAt(i-1); +								if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) +									break; +							} +							if (i == 0) +								lastState = SCE_CSS_DEFAULT; +						} +						break; +					} +				} +				if (i == 0) +					lastStateC = SCE_CSS_DEFAULT; +			} +			sc.Forward(); +			sc.ForwardSetState(lastStateC); +		} +		 +		if (sc.state == SCE_CSS_COMMENT) +			continue; +		 +		if (sc.state == SCE_CSS_OPERATOR) { +			if (op == ' ') { +				unsigned int i = startPos; +				op = styler.SafeGetCharAt(i-1); +				while (--i) { +					lastState = styler.StyleAt(i-1); +					if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT) +						break; +				} +			} +			switch (op) { +			case '@': +				if (lastState == SCE_CSS_DEFAULT) +					sc.SetState(SCE_CSS_DIRECTIVE); +				break; +			case '{': +				if (lastState == SCE_CSS_DIRECTIVE) +					sc.SetState(SCE_CSS_DEFAULT); +				else if (lastState == SCE_CSS_TAG) +					sc.SetState(SCE_CSS_IDENTIFIER); +				break; +			case '}': +				if (lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT || lastState == SCE_CSS_IDENTIFIER) +					sc.SetState(SCE_CSS_DEFAULT); +				break; +			case ':': +				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID) +					sc.SetState(SCE_CSS_PSEUDOCLASS); +				else if (lastState == SCE_CSS_IDENTIFIER || SCE_CSS_UNKNOWN_IDENTIFIER) +					sc.SetState(SCE_CSS_VALUE); +				break; +			case '.': +				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT) +					sc.SetState(SCE_CSS_CLASS); +				break; +			case '#': +				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT) +					sc.SetState(SCE_CSS_ID); +				break; +			case ',': +				if (lastState == SCE_CSS_TAG) +					sc.SetState(SCE_CSS_DEFAULT); +				break; +			case ';': +				if (lastState == SCE_CSS_DIRECTIVE) +					sc.SetState(SCE_CSS_DEFAULT); +				else if (lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT) +					sc.SetState(SCE_CSS_IDENTIFIER); +				break; +			case '!': +				if (lastState == SCE_CSS_VALUE) +					sc.SetState(SCE_CSS_IMPORTANT); +				break; +			} +		} +		 +		if (IsAWordChar(sc.ch)) { +			if (sc.state == SCE_CSS_DEFAULT) +				sc.SetState(SCE_CSS_TAG); +			continue; +		} +		 +		if (IsAWordChar(sc.chPrev) && (sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_IMPORTANT)) { +			char s[100]; +			sc.GetCurrentLowered(s, sizeof(s)); +			char *s2 = s; +			while (*s2 && !IsAWordChar(*s2)) +				s2++; +			switch (sc.state) { +			case SCE_CSS_IDENTIFIER: +				if (!keywords.InList(s2)) +					sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER); +				break; +			case SCE_CSS_PSEUDOCLASS: +				if (!pseudoClasses.InList(s2)) +					sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS); +				break; +			case SCE_CSS_IMPORTANT: +				if (strcmp(s2, "important") != 0) +					sc.ChangeState(SCE_CSS_VALUE); +				break; +			} +		} +		 +		if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && (sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || sc.state == SCE_CSS_ID)) +			sc.SetState(SCE_CSS_TAG); +		 +		if (sc.Match('/', '*')) { +			lastStateC = sc.state; +			sc.SetState(SCE_CSS_COMMENT); +			sc.Forward(); +			continue; +		} +		 +		if (IsCssOperator(sc.ch) +		&& (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!') +		&& (sc.state != SCE_CSS_DIRECTIVE || sc.ch == ';' || sc.ch == '{') +		) { +			if (sc.state != SCE_CSS_OPERATOR) +				lastState = sc.state; +			sc.SetState(SCE_CSS_OPERATOR); +			op = sc.ch; +		} +	} +	 +	sc.Complete(); +} + +static void FoldCSSDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { +	bool foldComment = styler.GetPropertyInt("fold.comment") != 0; +	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; +	unsigned int endPos = startPos + length; +	int visibleChars = 0; +	int lineCurrent = styler.GetLine(startPos); +	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; +	int levelCurrent = levelPrev; +	char chNext = styler[startPos]; +	bool inComment = (styler.StyleAt(startPos-1) == SCE_CSS_COMMENT); +	for (unsigned int i = startPos; i < endPos; i++) { +		char ch = chNext; +		chNext = styler.SafeGetCharAt(i + 1); +		int style = styler.StyleAt(i); +		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); +		if (foldComment) { +			if (!inComment && (style == SCE_CSS_COMMENT)) +				levelCurrent++; +			else if (inComment && (style != SCE_CSS_COMMENT)) +				levelCurrent--; +			inComment = (style == SCE_CSS_COMMENT); +		} +		if (style == SCE_CSS_OPERATOR) { +			if (ch == '{') { +				levelCurrent++; +			} else if (ch == '}') { +				levelCurrent--; +			} +		} +		if (atEOL) { +			int lev = levelPrev; +			if (visibleChars == 0 && foldCompact) +				lev |= SC_FOLDLEVELWHITEFLAG; +			if ((levelCurrent > levelPrev) && (visibleChars > 0)) +				lev |= SC_FOLDLEVELHEADERFLAG; +			if (lev != styler.LevelAt(lineCurrent)) { +				styler.SetLevel(lineCurrent, lev); +			} +			lineCurrent++; +			levelPrev = levelCurrent; +			visibleChars = 0; +		} +		if (!isspacechar(ch)) +			visibleChars++; +	} +	// Fill in the real level of the next line, keeping the current flags as they will be filled in later +	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; +	styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc); diff --git a/src/LexHTML.cxx b/src/LexHTML.cxx index 545bbfd55..687e2c533 100644 --- a/src/LexHTML.cxx +++ b/src/LexHTML.cxx @@ -368,6 +368,14 @@ static inline bool issgmlwordchar(char ch) {  	return isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '[';  } +static inline bool IsPhpWordStart(const unsigned char ch) { +	return isalpha(ch) || (ch == '_') || (ch >= 0x7f); +} + +static inline bool IsPhpWordChar(char ch) { +	return isdigit(ch) || IsPhpWordStart(ch); +} +  static bool InTagState(int state) {  	return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN ||  	       state == SCE_H_SCRIPT || @@ -481,7 +489,9 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty  			case eScriptPHP:  				//not currently supported				case eScriptVBS: -				if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC)) { +				/* if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC)) { */ +				//Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle); +				if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) {  					if ((ch == '{') || (ch == '}')) {  						levelCurrent += (ch == '{') ? 1 : -1;  					} @@ -1044,10 +1054,10 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty  			break;  		case SCE_H_VALUE:  			if (!ishtmlwordchar(ch)) { -				if (ch == '\"') { +				if (ch == '\"' && chPrev == '=') {  					// Should really test for being first character  					state = SCE_H_DOUBLESTRING; -				} else if (ch == '\'') { +				} else if (ch == '\'' && chPrev == '=') {  					state = SCE_H_SINGLESTRING;  				} else {  					if (IsNumber(styler.GetStartSegment(), styler)) { @@ -1397,7 +1407,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty  			break;  			///////////// start - PHP state handling  		case SCE_HPHP_WORD: -			if (!iswordstart(ch)) { +			if (!iswordchar(ch)) {  				classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler);  				if (ch == '/' && chNext == '*') {  					i++; @@ -1411,7 +1421,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty  					state = SCE_HPHP_HSTRING;  				} else if (ch == '\'') {  					state = SCE_HPHP_SIMPLESTRING; -				} else if (ch == '$') { +				} else if (ch == '$' && IsPhpWordStart(chNext)) {  					state = SCE_HPHP_VARIABLE;  				} else if (isoperator(ch)) {  					state = SCE_HPHP_OPERATOR; @@ -1430,7 +1440,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty  			}  			break;  		case SCE_HPHP_VARIABLE: -			if (!iswordstart(ch)) { +			if (!IsPhpWordChar(ch)) {  				styler.ColourTo(i - 1, SCE_HPHP_VARIABLE);  				if (isoperator(ch))  					state = SCE_HPHP_OPERATOR; @@ -1454,7 +1464,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty  			if (ch == '\\') {  				// skip the next char  				i++; -			} else if (ch == '$') { +			} else if (ch == '$' && IsPhpWordStart(chNext)) {  				styler.ColourTo(i - 1, StateToPrint);  				state = SCE_HPHP_HSTRING_VARIABLE;  			} else if (ch == '\"') { @@ -1472,7 +1482,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty  			}  			break;  		case SCE_HPHP_HSTRING_VARIABLE: -			if (!iswordstart(ch)) { +			if (!IsPhpWordChar(ch)) {  				styler.ColourTo(i - 1, StateToPrint);  				i--; // strange but it works  				state = SCE_HPHP_HSTRING; @@ -1497,7 +1507,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty  				state = SCE_HPHP_HSTRING;  			} else if (ch == '\'') {  				state = SCE_HPHP_SIMPLESTRING; -			} else if (ch == '$') { +			} else if (ch == '$' && IsPhpWordStart(chNext)) {  				state = SCE_HPHP_VARIABLE;  			} else if (isoperator(ch)) {  				state = SCE_HPHP_OPERATOR; @@ -1553,7 +1563,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty  	}  	StateToPrint = statePrintForState(state, inScriptType); -	styler.ColourTo(lengthDoc - 1, StateToPrint); +		styler.ColourTo(lengthDoc - 1, StateToPrint);  	// Fill in the real level of the next line, keeping the current flags as they will be filled in later  	if (fold) { @@ -1701,9 +1711,9 @@ static void ColouriseHTMLPiece(StyleContext &sc, WordList *keywordlists[]) {  			sc.SetState(SCE_H_ENTITY);  		}  	} else if ((sc.state == SCE_H_OTHER) || (sc.state == SCE_H_VALUE)) { -		if (sc.ch == '\"') { +		if (sc.ch == '\"' && sc.chPrev == '=') {  			sc.SetState(SCE_H_DOUBLESTRING); -		} else if (sc.ch == '\'') { +		} else if (sc.ch == '\'' && sc.chPrev == '=') {  			sc.SetState(SCE_H_SINGLESTRING);  		} else if (IsADigit(sc.ch)) {  			sc.SetState(SCE_H_NUMBER); @@ -1780,7 +1790,7 @@ static void ColourisePHPPiece(StyleContext &sc, WordList *keywordlists[]) {  	// Handle some PHP script  	if (sc.state == SCE_HPHP_WORD) { -		if (!IsAWordStart(sc.ch)) { +		if (!IsPhpWordChar(sc.ch)) {  			sc.SetState(SCE_HPHP_DEFAULT);  		}  	} else if (sc.state == SCE_HPHP_COMMENTLINE) { @@ -1802,7 +1812,7 @@ static void ColourisePHPPiece(StyleContext &sc, WordList *keywordlists[]) {  			sc.ForwardSetState(SCE_HPHP_DEFAULT);  		}  	} else if (sc.state == SCE_HPHP_VARIABLE) { -		if (!IsAWordStart(sc.ch)) { +		if (!IsPhpWordChar(sc.ch)) {  			sc.SetState(SCE_HPHP_DEFAULT);  		}  	} else if (sc.state == SCE_HPHP_OPERATOR) { @@ -1822,7 +1832,7 @@ static void ColourisePHPPiece(StyleContext &sc, WordList *keywordlists[]) {  		}  	}  	if (sc.state == SCE_HPHP_DEFAULT) { -		if (IsAWordStart(sc.ch)) { +		if (IsPhpWordStart(sc.ch)) {  			sc.SetState(SCE_HPHP_WORD);  		} else if (sc.ch == '#') {  			sc.SetState(SCE_HPHP_COMMENTLINE); @@ -1836,7 +1846,7 @@ static void ColourisePHPPiece(StyleContext &sc, WordList *keywordlists[]) {  			sc.SetState(SCE_HPHP_HSTRING);  		} else if (sc.ch == '\'') {  			sc.SetState(SCE_HPHP_SIMPLESTRING); -		} else if (sc.ch == '$') { +		} else if (sc.ch == '$' && IsPhpWordStart(sc.chNext)) {  			sc.SetState(SCE_HPHP_VARIABLE);  		} else if (isoperator(static_cast<char>(sc.ch))) {  			sc.SetState(SCE_HPHP_OPERATOR); | 
