161ef93eeSZhong Yang // Scintilla source code edit control
261ef93eeSZhong Yang // Copyright 1998-2001 by Neil Hodgson <[email protected]>
361ef93eeSZhong Yang // The License.txt file describes the conditions under which this software may be distributed.
461ef93eeSZhong Yang
561ef93eeSZhong Yang //用于解析LRC歌词
661ef93eeSZhong Yang
761ef93eeSZhong Yang #include <stdlib.h>
8*247322b4Szhongyang219 #include <string>
961ef93eeSZhong Yang #include <stdio.h>
1061ef93eeSZhong Yang #include <stdarg.h>
1161ef93eeSZhong Yang #include <assert.h>
1261ef93eeSZhong Yang #include <ctype.h>
1361ef93eeSZhong Yang #include <string_view>
1461ef93eeSZhong Yang
1561ef93eeSZhong Yang #include "ILexer.h"
1661ef93eeSZhong Yang #include "Scintilla.h"
1761ef93eeSZhong Yang #include "SciLexer.h"
1861ef93eeSZhong Yang
1961ef93eeSZhong Yang #include "WordList.h"
2061ef93eeSZhong Yang #include "LexAccessor.h"
2161ef93eeSZhong Yang #include "Accessor.h"
2261ef93eeSZhong Yang #include "StyleContext.h"
2361ef93eeSZhong Yang #include "CharacterSet.h"
2461ef93eeSZhong Yang #include "LexerModule.h"
2561ef93eeSZhong Yang
2661ef93eeSZhong Yang using namespace Scintilla;
2761ef93eeSZhong Yang using std::string_view;
2861ef93eeSZhong Yang
2961ef93eeSZhong Yang
AtEOL(Accessor & styler,Sci_PositionU i)3061ef93eeSZhong Yang static inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
3161ef93eeSZhong Yang return (styler[i] == '\n') ||
3261ef93eeSZhong Yang ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
3361ef93eeSZhong Yang }
3461ef93eeSZhong Yang
IsLetterOrNumber(int ch)3561ef93eeSZhong Yang static inline bool IsLetterOrNumber(int ch)
3661ef93eeSZhong Yang {
3761ef93eeSZhong Yang return ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'));
3861ef93eeSZhong Yang }
3961ef93eeSZhong Yang
4061ef93eeSZhong Yang
ColouriseMakeLine(char * lineBuffer,Sci_PositionU lengthLine,Sci_PositionU startLine,Sci_PositionU endPos,Accessor & styler,WordList * keywordlists[])4161ef93eeSZhong Yang static void ColouriseMakeLine(char *lineBuffer, Sci_PositionU lengthLine, Sci_PositionU startLine, Sci_PositionU endPos, Accessor &styler, WordList* keywordlists[])
4261ef93eeSZhong Yang {
4361ef93eeSZhong Yang WordList &keywords = *keywordlists[0];
4461ef93eeSZhong Yang string_view strBuff{ lineBuffer };
4561ef93eeSZhong Yang styler.ColourTo(startLine - 1, SCE_LYRIC_DEFAULT);
4661ef93eeSZhong Yang
4761ef93eeSZhong Yang int i = 0;
4861ef93eeSZhong Yang int curStyle = SCE_LYRIC_DEFAULT;
4961ef93eeSZhong Yang int tag_start_pos{ -1 };
5061ef93eeSZhong Yang int tag_end_pos{ -1 };
5161ef93eeSZhong Yang int separator_end{ -1 };
5261ef93eeSZhong Yang for (auto ch : strBuff)
5361ef93eeSZhong Yang {
5461ef93eeSZhong Yang if (ch == '[')
5561ef93eeSZhong Yang {
5661ef93eeSZhong Yang tag_start_pos = i;
5761ef93eeSZhong Yang styler.ColourTo(startLine + i - 1, curStyle);
5861ef93eeSZhong Yang curStyle = SCE_LYRIC_TIMETAG;
5961ef93eeSZhong Yang }
6061ef93eeSZhong Yang if (ch == ':')
6161ef93eeSZhong Yang {
6261ef93eeSZhong Yang std::string str{ strBuff.substr(tag_start_pos + 1, i - tag_start_pos - 1) };
6361ef93eeSZhong Yang
6461ef93eeSZhong Yang if (keywords.InList(str.c_str()))
6561ef93eeSZhong Yang {
6661ef93eeSZhong Yang styler.ColourTo(startLine + tag_start_pos, curStyle);
6761ef93eeSZhong Yang curStyle = SCE_LYRIC_TIME_TAG_KEYWORD;
6861ef93eeSZhong Yang styler.ColourTo(startLine + i - 1, curStyle);
6961ef93eeSZhong Yang curStyle = SCE_LYRIC_TIMETAG;
7061ef93eeSZhong Yang }
7161ef93eeSZhong Yang }
7261ef93eeSZhong Yang if (ch == ']')
7361ef93eeSZhong Yang {
7461ef93eeSZhong Yang tag_end_pos = i;
7561ef93eeSZhong Yang styler.ColourTo(startLine + i, curStyle);
7661ef93eeSZhong Yang curStyle = SCE_LYRIC_TEXT;
7761ef93eeSZhong Yang }
7861ef93eeSZhong Yang if (i > 2 && lineBuffer[i - 2] == ' ' && lineBuffer[i - 1] == '/' && lineBuffer[i] == ' ')
7961ef93eeSZhong Yang {
8061ef93eeSZhong Yang separator_end = i;
8161ef93eeSZhong Yang styler.ColourTo(startLine + i - 3, curStyle);
8261ef93eeSZhong Yang curStyle = SCE_LYRIC_SEPARATOR;
8361ef93eeSZhong Yang styler.ColourTo(startLine + i, curStyle);
8461ef93eeSZhong Yang curStyle = SCE_LYRIC_TRANSLATION;
8561ef93eeSZhong Yang }
8661ef93eeSZhong Yang
8761ef93eeSZhong Yang i++;
8861ef93eeSZhong Yang }
8961ef93eeSZhong Yang styler.ColourTo(endPos, curStyle);
9061ef93eeSZhong Yang
9161ef93eeSZhong Yang }
9261ef93eeSZhong Yang
ColouriseLyricDoc(Sci_PositionU startPos,Sci_Position length,int,WordList * keywordlists[],Accessor & styler)9361ef93eeSZhong Yang static void ColouriseLyricDoc(Sci_PositionU startPos, Sci_Position length, int, WordList* keywordlists[],
9461ef93eeSZhong Yang Accessor &styler) {
9561ef93eeSZhong Yang char lineBuffer[1024];
9661ef93eeSZhong Yang styler.StartAt(startPos);
9761ef93eeSZhong Yang styler.StartSegment(startPos);
9861ef93eeSZhong Yang Sci_PositionU linePos = 0;
9961ef93eeSZhong Yang Sci_PositionU startLine = startPos;
10061ef93eeSZhong Yang for (Sci_PositionU i = startPos; i < startPos + length; i++) {
10161ef93eeSZhong Yang lineBuffer[linePos++] = styler[i];
10261ef93eeSZhong Yang if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
10361ef93eeSZhong Yang // End of line (or of line buffer) met, colourise it
10461ef93eeSZhong Yang lineBuffer[linePos] = '\0';
10561ef93eeSZhong Yang ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler, keywordlists);
10661ef93eeSZhong Yang linePos = 0;
10761ef93eeSZhong Yang startLine = i + 1;
10861ef93eeSZhong Yang }
10961ef93eeSZhong Yang }
11061ef93eeSZhong Yang if (linePos > 0) { // Last line does not have ending characters
11161ef93eeSZhong Yang ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler, keywordlists);
11261ef93eeSZhong Yang }
11361ef93eeSZhong Yang }
11461ef93eeSZhong Yang
11561ef93eeSZhong Yang LexerModule lmLyric(SCLEX_LYRIC, ColouriseLyricDoc, "Lyric");
116