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