Code::Blocks  SVN r11506
editorlexerloader.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  *
5  * $Revision: 11482 $
6  * $Id: editorlexerloader.cpp 11482 2018-09-29 12:20:40Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/editorlexerloader.cpp $
8  */
9 
10 #include "sdk_precomp.h"
11 
12 #ifndef CB_PRECOMP
13  #include "globals.h"
14  #include "manager.h"
15  #include "logmanager.h"
16  #include <wx/dynarray.h>
17  #include <wx/regex.h>
18  #include <wx/wxscintilla.h>
19 #endif
20 
21 #include "editorcolourset.h"
22 #include "editorlexerloader.h"
23 #include "filemanager.h"
24 
26  : m_pTarget(target)
27 {
28  //ctor
29 }
30 
32 {
33  //dtor
34 }
35 
37 {
38  Manager::Get()->GetLogManager()->Log(_("Loading ") + wxFileName(loader->FileName()).GetName());
39 
40  TiXmlDocument doc;
41  doc.Parse(loader->GetData());
42 
43  if (doc.Error())
44  {
45  Manager::Get()->GetLogManager()->Log(_("Failed."));
46  Manager::Get()->GetLogManager()->Log(_("TinyXML error: ") + cbC2U(doc.ErrorDesc()));
47  return;
48  }
49 
50  TiXmlElement* root;
51  TiXmlElement* lexer;
52 
53  root = doc.FirstChildElement("CodeBlocks_lexer_properties");
54  if (!root)
55  {
56  // old tag
57  root = doc.FirstChildElement("Code::Blocks_lexer_properties");
58  if (!root)
59  {
60  Manager::Get()->GetLogManager()->Log(_("Not a valid Code::Blocks lexer file..."));
61  return;
62  }
63  }
64  lexer = root->FirstChildElement("Lexer");
65  if (!lexer)
66  {
67  Manager::Get()->GetLogManager()->Log(_("No 'Lexer' element in file..."));
68  return;
69  }
70 
71  DoLexer(lexer);
72 }
73 
74 void EditorLexerLoader::DoLexer(TiXmlElement* node)
75 {
76  if (!node->Attribute("name") || !node->Attribute("index"))
77  {
78  Manager::Get()->GetLogManager()->Log(_("No name or index..."));
79  return;
80  }
81 
82  wxString name = wxString( node->Attribute("name"), wxConvUTF8 );
83  int lexer = atol(node->Attribute("index"));
84  wxString masks = wxString ( node->Attribute("filemasks"), wxConvUTF8 );
85  HighlightLanguage style = m_pTarget->AddHighlightLanguage(lexer, name);
86  if (style == HL_NONE)
87  return; // wasn't added
88  m_pTarget->SetFileMasks(style, masks);
89 // LOGSTREAM << "Found lexer: " << name << " (" << style << ")\n";
90 
91  DoStyles(style, node);
92  DoKeywords(style, node);
93  DoSampleCode(style, node);
94  DoLangAttributes(style, node);
95 }
96 
97 void EditorLexerLoader::DoStyles(HighlightLanguage language, TiXmlElement* node)
98 {
99  bool foundSelection = false, foundActiveLine = false;
100  bool foundMatchBrace = false, foundBraceError = false;
101  bool foundIndentationGuide = false;
102 
103  TiXmlElement* style = node->FirstChildElement("Style");
104  while (style)
105  {
106  if (style->Attribute("name") && style->Attribute("index"))
107  {
108  wxString name = wxString ( style->Attribute("name"), wxConvUTF8 );
109  wxString index = wxString ( style->Attribute("index"), wxConvUTF8 ); // comma-separated indices
110  wxString fg = wxString ( style->Attribute("fg"), wxConvUTF8 );
111  wxString bg = wxString ( style->Attribute("bg"), wxConvUTF8 );
112  bool bold = style->Attribute("bold") ? atol(style->Attribute("bold")) != 0 : false;
113  bool italics = style->Attribute("italics") ? atol(style->Attribute("italics")) != 0 : false;
114  bool underlined = style->Attribute("underlined") ? atol(style->Attribute("underlined")) != 0 : false;
115 
116  // break-up arrays
117  wxArrayString indices = GetArrayFromString(index, _T(","));
118  wxArrayString fgarray = GetArrayFromString(fg, _T(","));
119  wxArrayString bgarray = GetArrayFromString(bg, _T(","));
120 
121  wxColour fgcolour = wxNullColour;
122  if (fgarray.GetCount() == 3)
123  {
124  long R=0, G=0, B=0;
125  fgarray[0].ToLong(&R);
126  fgarray[1].ToLong(&G);
127  fgarray[2].ToLong(&B);
128  fgcolour.Set((unsigned char)R,(unsigned char)G,(unsigned char)B);
129  }
130  wxColour bgcolour = wxNullColour;
131  if (bgarray.GetCount() == 3)
132  {
133  long R=0, G=0, B=0;
134  bgarray[0].ToLong(&R);
135  bgarray[1].ToLong(&G);
136  bgarray[2].ToLong(&B);
137  bgcolour.Set((unsigned char)R,(unsigned char)G,(unsigned char)B);
138  }
139 
140  for (size_t i = 0; i < indices.GetCount(); ++i)
141  {
142  if (indices[i].IsEmpty())
143  continue;
144  long value = 0;
145  indices[i].ToLong(&value);
146 
147  switch (value)
148  {
149  case cbSELECTION:
150  foundSelection = true;
151  break;
152  case cbHIGHLIGHT_LINE:
153  foundActiveLine = true;
154  break;
156  foundMatchBrace = true;
157  break;
159  foundBraceError = true;
160  break;
162  foundIndentationGuide = true;
163  break;
164  }
165 
166 // LOGSTREAM << _("Adding style: ") << name << _T("(") << value << _T(")\n");
167  m_pTarget->AddOption(language, name, value,
168  fgcolour,
169  bgcolour,
170  bold,
171  italics,
172  underlined,
173  value >= 0);
174  }
175  }
176  style = style->NextSiblingElement("Style");
177  }
178 
179  if (!foundSelection)
180  {
181  m_pTarget->AddOption(language, wxT("Selection"), cbSELECTION, wxNullColour,
182  wxColour(217, 217, 217), false, false, false, false);
183  }
184  if (!foundActiveLine)
185  {
186  m_pTarget->AddOption(language, wxT("Active line"), cbHIGHLIGHT_LINE, wxNullColour,
187  wxColour(255, 255, 160), false, false, false, false);
188  }
189  if (!foundMatchBrace)
190  {
191  m_pTarget->AddOption(language, wxT("Matching brace highlight"), wxSCI_STYLE_BRACELIGHT,
192  wxColour(0, 0, 0), wxColour(128, 255, 255), true, false, false, true);
193  }
194  if (!foundBraceError)
195  {
196  m_pTarget->AddOption(language, wxT("No matching brace highlight"), wxSCI_STYLE_BRACEBAD,
197  wxColour(255, 255, 255), wxColour(255, 0, 0), true, false, false, true);
198  }
199  if (!foundIndentationGuide)
200  {
201  m_pTarget->AddOption(language, wxT("Indentation guide"), wxSCI_STYLE_INDENTGUIDE,
202  wxColour(55, 55, 55), wxNullColour, false, false, false, true);
203  }
204 }
205 
206 void EditorLexerLoader::DoKeywords(HighlightLanguage language, TiXmlElement* node)
207 {
208  TiXmlElement* keywords = node->FirstChildElement("Keywords");
209  if (!keywords)
210  return;
211  DoSingleKeywordNode(language, keywords, _T("Language"));
212  DoSingleKeywordNode(language, keywords, _T("Documentation"));
213  DoSingleKeywordNode(language, keywords, _T("User"));
214  DoSingleKeywordNode(language, keywords, _T("Set"));
215 }
216 
217 void EditorLexerLoader::DoSingleKeywordNode(HighlightLanguage language, TiXmlElement* node, const wxString& nodename)
218 {
219  TiXmlElement* keywords = node->FirstChildElement(nodename.mb_str());
220  while (keywords)
221  {
222  // LOGSTREAM << "Found " << nodename << '\n';
223  int keyidx = keywords->Attribute("index") ? atol(keywords->Attribute("index")) : -1;
224  // LOGSTREAM << "keyidx=" << keyidx << '\n';
225  if (keyidx != -1)
226  {
227  // the lexer file contains keywords indented - remove the extra spacing and EOLs
228  wxRegEx regex(_T("[[:space:]]+"));
229  wxString value(keywords->Attribute("value"), wxConvUTF8);
230  regex.Replace(&value, _T(" "));
231 
232  #if wxCHECK_VERSION(3, 0, 0)
233  m_pTarget->SetKeywords(language, keyidx, value );
234  #else
235  m_pTarget->SetKeywords(language, keyidx, wxString ( value, wxConvUTF8 ) );
236  #endif
237  }
238 
239  keywords = keywords->NextSiblingElement(nodename.mb_str());
240  }
241 }
242 
243 void EditorLexerLoader::DoSampleCode(HighlightLanguage language, TiXmlElement* node)
244 {
245  TiXmlElement* sample = node->FirstChildElement("SampleCode");
246  if (!sample)
247  return;
248  wxString code = wxString ( sample->Attribute("value"), wxConvUTF8 );
249  if (code.IsEmpty())
250  return;
251  int breakLine = sample->Attribute("breakpoint_line") ? atol(sample->Attribute("breakpoint_line")) : -1;
252  int debugLine = sample->Attribute("debug_line") ? atol(sample->Attribute("debug_line")) : -1;
253  int errorLine = sample->Attribute("error_line") ? atol(sample->Attribute("error_line")) : -1;
254  m_pTarget->SetSampleCode(language, code, breakLine, debugLine, errorLine);
255 }
256 
257 void EditorLexerLoader::DoLangAttributes(HighlightLanguage language, TiXmlElement* node)
258 {
259  TiXmlElement* attribs = node->FirstChildElement("LanguageAttributes");
260  if ( !attribs )
261  return;
262 
263  bool CaseSensitive = attribs->Attribute("CaseSensitive") ? atol(attribs->Attribute("CaseSensitive")) != 0 : false;
264  m_pTarget->SetCaseSensitivity(language, CaseSensitive);
265 
266 
267  CommentToken token;
268  token.lineComment = wxString( attribs->Attribute("LineComment"), wxConvUTF8 );
269  token.doxygenLineComment = wxString( attribs->Attribute("DoxygenLineComment"), wxConvUTF8 );
270  token.streamCommentStart = wxString( attribs->Attribute("StreamCommentStart"), wxConvUTF8 );
271  token.streamCommentEnd = wxString( attribs->Attribute("StreamCommentEnd"), wxConvUTF8 );
272  token.doxygenStreamCommentStart = wxString( attribs->Attribute("DoxygenStreamCommentStart"), wxConvUTF8 );
273  token.doxygenStreamCommentEnd = wxString( attribs->Attribute("DoxygenStreamCommentEnd"), wxConvUTF8 );
274  token.boxCommentStart = wxString( attribs->Attribute("BoxCommentStart"), wxConvUTF8 );
275  token.boxCommentMid = wxString( attribs->Attribute("BoxCommentMid"), wxConvUTF8 );
276  token.boxCommentEnd = wxString( attribs->Attribute("BoxCommentEnd"), wxConvUTF8 );
277 
278  m_pTarget->SetCommentToken(language, token);
279 
280  std::set<int> CommentLexerStyles, CharacterLexerStyles, StringLexerStyles, PreprocessorLexerStyles;
281  bool hasLexerStylesSet = false;
282  hasLexerStylesSet |= DoLangAttributesLexerStyles(attribs, "LexerCommentStyles", CommentLexerStyles);
283  hasLexerStylesSet |= DoLangAttributesLexerStyles(attribs, "LexerCharacterStyles", CharacterLexerStyles);
284  hasLexerStylesSet |= DoLangAttributesLexerStyles(attribs, "LexerStringStyles", StringLexerStyles);
285  hasLexerStylesSet |= DoLangAttributesLexerStyles(attribs, "LexerPreprocessorStyles", PreprocessorLexerStyles);
286 
287  // only set styles if configured. Since different languages use the same lexer.
288  // So if any of the languages has these styles configured we use them.
289  // If another language has not configured them the previously defined wont get lost.
290  if ( hasLexerStylesSet )
291  {
292  m_pTarget->SetCommentLexerStyles(language, CommentLexerStyles);
293  m_pTarget->SetStringLexerStyles(language, StringLexerStyles);
294  m_pTarget->SetCharacterLexerStyles(language, CharacterLexerStyles);
295  m_pTarget->SetPreprocessorLexerStyles(language, PreprocessorLexerStyles);
296  }
297 }
298 
299 bool EditorLexerLoader::DoLangAttributesLexerStyles(TiXmlElement* attribs, const char *attributeName, std::set<int> &styles)
300 {
301  styles.clear();
302  wxString str = wxString ( attribs->Attribute(attributeName), wxConvUTF8 );
303  wxArrayString strarray = GetArrayFromString(str, _T(","));
304 
305  for ( unsigned int i = 0; i < strarray.Count(); ++i )
306  {
307  long style;
308  strarray[i].ToLong(&style);
309  styles.insert((unsigned int)style);
310  }
311 
312  return !str.IsEmpty();
313 }
void SetSampleCode(HighlightLanguage lang, const wxString &sample, int breakLine, int debugLine, int errorLine)
DLLIMPORT wxArrayString GetArrayFromString(const wxString &text, const wxString &separator=DEFAULT_ARRAY_SEP, bool trimSpaces=true)
Definition: globals.cpp:134
wxString doxygenLineComment
wxString lineComment
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
wxColour wxNullColour
#define wxSCI_STYLE_INDENTGUIDE
Definition: wxscintilla.h:168
void DoLexer(TiXmlElement *node)
#define _T(string)
void DoSingleKeywordNode(HighlightLanguage language, TiXmlElement *node, const wxString &nodename)
void AddOption(HighlightLanguage lang, const wxString &name, int value, wxColour fore=wxNullColour, wxColour back=wxNullColour, bool bold=false, bool italics=false, bool underlined=false, bool isStyle=true)
void SetCommentToken(HighlightLanguage lang, CommentToken token)
void SetCharacterLexerStyles(HighlightLanguage lang, const std::set< int > &styles)
const wxCharBuffer mb_str(const wxMBConv &conv=wxConvLibc) const
void DoLangAttributes(HighlightLanguage language, TiXmlElement *node)
#define wxT(string)
void Set(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha=wxALPHA_OPAQUE)
#define wxSCI_STYLE_BRACEBAD
Definition: wxscintilla.h:166
void DoSampleCode(HighlightLanguage language, TiXmlElement *node)
EditorLexerLoader(EditorColourSet *target)
int Replace(wxString *text, const wxString &replacement, size_t maxMatches=0) const
wxString streamCommentStart
wxString FileName() const
Definition: filemanager.h:59
DLLIMPORT wxString cbC2U(const char *str)
Return str as a proper unicode-compatible string.
Definition: globals.cpp:733
void Load(LoaderBase *loader)
void SetPreprocessorLexerStyles(HighlightLanguage lang, const std::set< int > &styles)
void SetFileMasks(HighlightLanguage lang, const wxString &masks, const wxString &=_(","))
void SetKeywords(HighlightLanguage lang, int idx, const wxString &keywords)
#define HL_NONE
Definition: globals.h:167
void SetCaseSensitivity(HighlightLanguage lang, bool CaseSensitive)
LogManager * GetLogManager() const
Definition: manager.cpp:439
wxString boxCommentStart
wxString doxygenStreamCommentEnd
wxString boxCommentEnd
const int cbHIGHLIGHT_LINE
void SetCommentLexerStyles(HighlightLanguage lang, const std::set< int > &styles)
const wxString & _(const wxString &string)
EditorColourSet * m_pTarget
wxString boxCommentMid
bool IsEmpty() const
const int cbSELECTION
void Log(const wxString &msg, int i=app_log, Logger::level lv=Logger::info)
Definition: logmanager.h:140
HighlightLanguage AddHighlightLanguage(int lexer, const wxString &name)
char * GetData()
Definition: filemanager.cpp:42
bool DoLangAttributesLexerStyles(TiXmlElement *attribs, const char *attributeName, std::set< int > &styles)
size_t GetCount() const
void SetStringLexerStyles(HighlightLanguage lang, const std::set< int > &styles)
void DoStyles(HighlightLanguage language, TiXmlElement *node)
#define wxSCI_STYLE_BRACELIGHT
Definition: wxscintilla.h:165
void DoKeywords(HighlightLanguage language, TiXmlElement *node)
wxString doxygenStreamCommentStart
wxString streamCommentEnd