1*61ef93eeSZhong Yang // Scintilla source code edit control 2*61ef93eeSZhong Yang // Copyright 1998-2001 by Neil Hodgson <[email protected]> 3*61ef93eeSZhong Yang // The License.txt file describes the conditions under which this software may be distributed. 4*61ef93eeSZhong Yang 5*61ef93eeSZhong Yang //用于解析LRC歌词 6*61ef93eeSZhong Yang 7*61ef93eeSZhong Yang #include <stdlib.h> 8*61ef93eeSZhong Yang #include <string.h> 9*61ef93eeSZhong Yang #include <stdio.h> 10*61ef93eeSZhong Yang #include <stdarg.h> 11*61ef93eeSZhong Yang #include <assert.h> 12*61ef93eeSZhong Yang #include <ctype.h> 13*61ef93eeSZhong Yang #include <string_view> 14*61ef93eeSZhong Yang 15*61ef93eeSZhong Yang #include "ILexer.h" 16*61ef93eeSZhong Yang #include "Scintilla.h" 17*61ef93eeSZhong Yang #include "SciLexer.h" 18*61ef93eeSZhong Yang 19*61ef93eeSZhong Yang #include "WordList.h" 20*61ef93eeSZhong Yang #include "LexAccessor.h" 21*61ef93eeSZhong Yang #include "Accessor.h" 22*61ef93eeSZhong Yang #include "StyleContext.h" 23*61ef93eeSZhong Yang #include "CharacterSet.h" 24*61ef93eeSZhong Yang #include "LexerModule.h" 25*61ef93eeSZhong Yang 26*61ef93eeSZhong Yang using namespace Scintilla; 27*61ef93eeSZhong Yang using std::string_view; 28*61ef93eeSZhong Yang 29*61ef93eeSZhong Yang 30*61ef93eeSZhong Yang static inline bool AtEOL(Accessor &styler, Sci_PositionU i) { 31*61ef93eeSZhong Yang return (styler[i] == '\n') || 32*61ef93eeSZhong Yang ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); 33*61ef93eeSZhong Yang } 34*61ef93eeSZhong Yang 35*61ef93eeSZhong Yang static inline bool IsLetterOrNumber(int ch) 36*61ef93eeSZhong Yang { 37*61ef93eeSZhong Yang return ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')); 38*61ef93eeSZhong Yang } 39*61ef93eeSZhong Yang 40*61ef93eeSZhong Yang 41*61ef93eeSZhong Yang static void ColouriseMakeLine(char *lineBuffer, Sci_PositionU lengthLine, Sci_PositionU startLine, Sci_PositionU endPos, Accessor &styler, WordList* keywordlists[]) 42*61ef93eeSZhong Yang { 43*61ef93eeSZhong Yang WordList &keywords = *keywordlists[0]; 44*61ef93eeSZhong Yang string_view strBuff{ lineBuffer }; 45*61ef93eeSZhong Yang styler.ColourTo(startLine - 1, SCE_LYRIC_DEFAULT); 46*61ef93eeSZhong Yang 47*61ef93eeSZhong Yang int i = 0; 48*61ef93eeSZhong Yang int curStyle = SCE_LYRIC_DEFAULT; 49*61ef93eeSZhong Yang int tag_start_pos{ -1 }; 50*61ef93eeSZhong Yang int tag_end_pos{ -1 }; 51*61ef93eeSZhong Yang int separator_end{ -1 }; 52*61ef93eeSZhong Yang for (auto ch : strBuff) 53*61ef93eeSZhong Yang { 54*61ef93eeSZhong Yang if (ch == '[') 55*61ef93eeSZhong Yang { 56*61ef93eeSZhong Yang tag_start_pos = i; 57*61ef93eeSZhong Yang styler.ColourTo(startLine + i - 1, curStyle); 58*61ef93eeSZhong Yang curStyle = SCE_LYRIC_TIMETAG; 59*61ef93eeSZhong Yang } 60*61ef93eeSZhong Yang if (ch == ':') 61*61ef93eeSZhong Yang { 62*61ef93eeSZhong Yang std::string str{ strBuff.substr(tag_start_pos + 1, i - tag_start_pos - 1) }; 63*61ef93eeSZhong Yang 64*61ef93eeSZhong Yang if (keywords.InList(str.c_str())) 65*61ef93eeSZhong Yang { 66*61ef93eeSZhong Yang styler.ColourTo(startLine + tag_start_pos, curStyle); 67*61ef93eeSZhong Yang curStyle = SCE_LYRIC_TIME_TAG_KEYWORD; 68*61ef93eeSZhong Yang styler.ColourTo(startLine + i - 1, curStyle); 69*61ef93eeSZhong Yang curStyle = SCE_LYRIC_TIMETAG; 70*61ef93eeSZhong Yang } 71*61ef93eeSZhong Yang } 72*61ef93eeSZhong Yang if (ch == ']') 73*61ef93eeSZhong Yang { 74*61ef93eeSZhong Yang tag_end_pos = i; 75*61ef93eeSZhong Yang styler.ColourTo(startLine + i, curStyle); 76*61ef93eeSZhong Yang curStyle = SCE_LYRIC_TEXT; 77*61ef93eeSZhong Yang } 78*61ef93eeSZhong Yang if (i > 2 && lineBuffer[i - 2] == ' ' && lineBuffer[i - 1] == '/' && lineBuffer[i] == ' ') 79*61ef93eeSZhong Yang { 80*61ef93eeSZhong Yang separator_end = i; 81*61ef93eeSZhong Yang styler.ColourTo(startLine + i - 3, curStyle); 82*61ef93eeSZhong Yang curStyle = SCE_LYRIC_SEPARATOR; 83*61ef93eeSZhong Yang styler.ColourTo(startLine + i, curStyle); 84*61ef93eeSZhong Yang curStyle = SCE_LYRIC_TRANSLATION; 85*61ef93eeSZhong Yang } 86*61ef93eeSZhong Yang 87*61ef93eeSZhong Yang i++; 88*61ef93eeSZhong Yang } 89*61ef93eeSZhong Yang styler.ColourTo(endPos, curStyle); 90*61ef93eeSZhong Yang 91*61ef93eeSZhong Yang } 92*61ef93eeSZhong Yang 93*61ef93eeSZhong Yang static void ColouriseLyricDoc(Sci_PositionU startPos, Sci_Position length, int, WordList* keywordlists[], 94*61ef93eeSZhong Yang Accessor &styler) { 95*61ef93eeSZhong Yang char lineBuffer[1024]; 96*61ef93eeSZhong Yang styler.StartAt(startPos); 97*61ef93eeSZhong Yang styler.StartSegment(startPos); 98*61ef93eeSZhong Yang Sci_PositionU linePos = 0; 99*61ef93eeSZhong Yang Sci_PositionU startLine = startPos; 100*61ef93eeSZhong Yang for (Sci_PositionU i = startPos; i < startPos + length; i++) { 101*61ef93eeSZhong Yang lineBuffer[linePos++] = styler[i]; 102*61ef93eeSZhong Yang if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { 103*61ef93eeSZhong Yang // End of line (or of line buffer) met, colourise it 104*61ef93eeSZhong Yang lineBuffer[linePos] = '\0'; 105*61ef93eeSZhong Yang ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler, keywordlists); 106*61ef93eeSZhong Yang linePos = 0; 107*61ef93eeSZhong Yang startLine = i + 1; 108*61ef93eeSZhong Yang } 109*61ef93eeSZhong Yang } 110*61ef93eeSZhong Yang if (linePos > 0) { // Last line does not have ending characters 111*61ef93eeSZhong Yang ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler, keywordlists); 112*61ef93eeSZhong Yang } 113*61ef93eeSZhong Yang } 114*61ef93eeSZhong Yang 115*61ef93eeSZhong Yang LexerModule lmLyric(SCLEX_LYRIC, ColouriseLyricDoc, "Lyric"); 116