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