xref: /MusicPlayer2/scintilla/lexers/LexLyric.cxx (revision 247322b4bde9ecbb86907ed519971fd87b77b0e0)
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