Code::Blocks  SVN r11506
editorcolourset.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: editorcolourset.cpp 11482 2018-09-29 12:20:40Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/editorcolourset.cpp $
8  */
9 
10 #include "sdk_precomp.h"
11 
12 #ifndef CB_PRECOMP
13  #include <wx/dir.h>
14  #include <wx/settings.h>
15 
16  #include "globals.h"
17  #include "cbeditor.h"
18  #include "configmanager.h"
19  #include "logmanager.h"
20  #include "filemanager.h"
21  #include "manager.h"
22 #endif
23 
24 #include <wx/regex.h>
25 #include <wx/txtstrm.h> // wxTextInputStream
26 #include <wx/wfstream.h> // wxFileInputStream
27 
28 #include "cbcolourmanager.h"
29 #include "cbstyledtextctrl.h"
30 
31 #include "editorcolourset.h"
32 #include "editorlexerloader.h"
33 #include "filefilters.h"
34 
36  : m_Name(setName)
37 {
39 
40  if (setName.IsEmpty())
42  else
43  Load();
44 }
45 
47  m_Name(other.m_Name),
49 {
50  m_Sets.clear();
51 
52  for (OptionSetsMap::const_iterator it = other.m_Sets.begin(); it != other.m_Sets.end(); ++it)
53  {
54  OptionSet& mset = m_Sets[it->first];
55 
56  mset.m_Langs = it->second.m_Langs;
57  mset.m_Lexers = it->second.m_Lexers;
58  for (int i = 0; i <= wxSCI_KEYWORDSET_MAX; ++i)
59  {
60  mset.m_Keywords[i] = it->second.m_Keywords[i];
61  mset.m_originalKeywords[i] = it->second.m_originalKeywords[i];
62  }
63  mset.m_FileMasks = it->second.m_FileMasks;
64  mset.m_originalFileMasks = it->second.m_originalFileMasks;
65  mset.m_SampleCode = it->second.m_SampleCode;
66  mset.m_BreakLine = it->second.m_BreakLine;
67  mset.m_DebugLine = it->second.m_DebugLine;
68  mset.m_ErrorLine = it->second.m_ErrorLine;
69  mset.comment = it->second.comment;
70  mset.m_CaseSensitive = it->second.m_CaseSensitive;
71  const OptionColours& value = it->second.m_Colours;
72  for (unsigned int i = 0; i < value.GetCount(); ++i)
73  {
74  AddOption(it->first, value[i]);
75  }
76  }
77 }
78 
80 {
82 }
83 
85 {
86  for (OptionSetsMap::iterator map_it = m_Sets.begin();
87  map_it != m_Sets.end(); ++map_it)
88  {
89  for (OptionColours::iterator vec_it = (*map_it).second.m_Colours.begin();
90  vec_it != (*map_it).second.m_Colours.end(); ++vec_it)
91  {
92  delete (*vec_it);
93  }
94  }
95  m_Sets.clear();
96 }
97 
99 {
100  // no need for syntax highlighting if batch building
101  if (Manager::IsBatchBuild())
102  return;
103 
104  wxDir dir;
105  wxString filename;
107  std::list<LoaderBase*> loaders;
108  int count = 0;
109 
110  // user paths first
111  wxString path = ConfigManager::GetFolder(sdDataUser) + _T("/lexers/");
112  if (wxDirExists(path) && dir.Open(path))
113  {
114  Manager::Get()->GetLogManager()->Log(F(_("Scanning for lexers in %s..."), path.wx_str()));
115  bool ok = dir.GetFirst(&filename, _T("lexer_*.xml"), wxDIR_FILES);
116  while (ok)
117  {
118  loaders.push_back(fm->Load(path + filename));
119  ok = dir.GetNext(&filename);
120  ++count;
121  }
122  Manager::Get()->GetLogManager()->Log(F(_("Found %d lexers"), count));
123  count = 0;
124  }
125 
126  // global paths next
127  path = ConfigManager::GetFolder(sdDataGlobal) + _T("/lexers/");
128  if (wxDirExists(path) && dir.Open(path))
129  {
130  Manager::Get()->GetLogManager()->Log(F(_("Scanning for lexers in %s..."), path.wx_str()));
131  bool ok = dir.GetFirst(&filename, _T("lexer_*.xml"), wxDIR_FILES);
132  while (ok)
133  {
134  loaders.push_back(fm->Load(path + filename));
135  ok = dir.GetNext(&filename);
136  ++count;
137  }
138  Manager::Get()->GetLogManager()->Log(F(_("Found %d lexers"), count));
139  }
140 
141  EditorLexerLoader lex(this);
142  for (std::list<LoaderBase*>::iterator it = loaders.begin(); it != loaders.end(); ++it)
143  lex.Load(*it);
144 
145  ::Delete(loaders);
146 
147 
148  for (OptionSetsMap::iterator it = m_Sets.begin(); it != m_Sets.end(); ++it)
149  {
150  wxString lang = it->second.m_Langs;
151  if (lang.IsEmpty())
152  continue;
153 
154  // keep the original filemasks and keywords, so we know what needs saving later
155  for (int i = 0; i <= wxSCI_KEYWORDSET_MAX; ++i)
156  {
157  it->second.m_originalKeywords[i] = it->second.m_Keywords[i];
158  }
159  it->second.m_originalFileMasks = it->second.m_FileMasks;
160 
161  // remove old settings, no longer used
162  unsigned int i = 0;
163  while (i < it->second.m_Colours.GetCount())
164  {
165  OptionColour* opt = it->second.m_Colours.Item(i);
166  // valid values are:
167  if (opt->value < 0 && // styles >= 0
168  opt->value != cbSELECTION && // cbSELECTION
169  opt->value != cbHIGHLIGHT_LINE) // cbHIGHLIGHT_LINE
170  {
171  it->second.m_Colours.Remove(opt);
172  delete opt;
173  }
174  else
175  ++i;
176  }
177  }
178 }
179 
181 {
182  if ( lexer < wxSCI_LEX_NULL
183  || lexer > wxSCI_LEX_LAST // this is a C::B extension to wxscintilla.h
184  || name.IsEmpty() )
185  {
186  return HL_NONE;
187  }
188 
189  // fix name to be XML compliant
190  wxString newID;
191  size_t pos = 0;
192  while (pos < name.Length())
193  {
194  wxChar ch = name[pos];
195  if (wxIsalnum(ch) || ch == _T('_'))
196  newID.Append(ch); // valid character
197  else if (wxIsspace(ch))
198  newID.Append(_T('_')); // convert spaces to underscores
199  ++pos;
200  }
201  // make sure it's not starting with a number or underscore.
202  // if it is, prepend an 'A'
203  if (wxIsdigit(newID.GetChar(0)) || newID.GetChar(0) == _T('_'))
204  newID.Prepend(_T('A'));
205 
206  if (GetHighlightLanguage(newID) != HL_NONE)
207  return HL_NONE;
208 
209  m_Sets[newID].m_Langs = name;
210  m_Sets[newID].m_Lexers = lexer;
211 
212  if (lexer == wxSCI_LEX_NULL && name == wxT("Plain text files"))
213  m_PlainTextLexerID = newID;
214 
215  return newID;
216 }
217 
219 {
220  for (OptionSetsMap::iterator it = m_Sets.begin(); it != m_Sets.end(); ++it)
221  {
222  if (it->second.m_Langs.CmpNoCase(name) == 0)
223  return it->first;
224  }
225  return HL_NONE;
226 }
227 
228 // from scintilla lexer (wxSCI_LEX_*)
229 // Warning: the first one found is returned!
231 {
232  for (OptionSetsMap::iterator it = m_Sets.begin(); it != m_Sets.end(); ++it)
233  {
234  if (it->second.m_Lexers == lexer)
235  return it->first;
236  }
237  return HL_NONE;
238 }
239 
240 // sorting helper function
241 static int CompareStringNoCase(const wxString& first, const wxString& second)
242 {
243  return first.CmpNoCase(second);
244 }
245 
247 {
248  wxArrayString ret;
249  for (OptionSetsMap::iterator it = m_Sets.begin(); it != m_Sets.end(); ++it)
250  {
251  // Make sure to skip the "plain text files", because we don't want it in the list. We
252  // manually add "Plain text" to the appropriate places.
253  if (!it->second.m_Langs.IsEmpty() && it->first != m_PlainTextLexerID)
254  ret.Add(it->second.m_Langs);
255  }
257  return ret;
258 }
259 
261 {
262  if (!base)
263  return;
264  // first find the index of this option
265  int idx = -1;
266  OptionSet& mset = m_Sets[lang];
267  for (unsigned int i = 0; i < mset.m_Colours.GetCount(); ++i)
268  {
269  OptionColour* opt = mset.m_Colours.Item(i);
270  if (opt == base)
271  {
272  idx = i;
273  break;
274  }
275  }
276  if (idx == -1)
277  return;
278 
279  // now loop again, but update the other options with the same name
280  for (unsigned int i = 0; i < mset.m_Colours.GetCount(); ++i)
281  {
282  if ((int)i == idx)
283  continue; // skip the base option
284  OptionColour* opt = mset.m_Colours.Item(i);
285  if (!opt->name.Matches(base->name))
286  continue;
287  opt->fore = base->fore;
288  opt->back = base->back;
289  opt->bold = base->bold;
290  opt->italics = base->italics;
291  opt->underlined = base->underlined;
292  }
293 }
294 
295 bool EditorColourSet::AddOption(HighlightLanguage lang, OptionColour* option, bool checkIfExists)
296 {
297  if (lang == HL_NONE)
298  lang = m_PlainTextLexerID;
299 
300  if (checkIfExists && GetOptionByValue(lang, option->value))
301  return false;
302 
303  OptionColours& colours = m_Sets[lang].m_Colours;
304  colours.Add(new OptionColour(*option));
305  return true;
306 }
307 
309  const wxString& name,
310  int value,
311  wxColour fore,
312  wxColour back,
313  bool bold,
314  bool italics,
315  bool underlined,
316  bool isStyle)
317 {
318  if (lang == HL_NONE)
319  lang = m_PlainTextLexerID;
320 
321  OptionColour* opt = new OptionColour;
322  opt->name = name;
323  opt->value = value;
324  opt->fore = fore;
325  opt->back = back;
326  opt->bold = bold;
327  opt->italics = italics;
328  opt->underlined = underlined;
329  opt->isStyle = isStyle;
330 
331  opt->originalfore = fore;
332  opt->originalback = back;
333  opt->originalbold = bold;
334  opt->originalitalics = italics;
335  opt->originalunderlined = underlined;
336  opt->originalisStyle = isStyle;
337 
338  AddOption(lang, opt);
339  delete opt;
340 }
341 
343 {
344  if (lang == HL_NONE)
345  lang = m_PlainTextLexerID;
346 
347  OptionSet& mset = m_Sets[lang];
348  for (unsigned int i = 0; i < mset.m_Colours.GetCount(); ++i)
349  {
350  OptionColour* opt = mset.m_Colours.Item(i);
351  if (opt->name == name)
352  return opt;
353  }
354  return nullptr;
355 }
356 
358 {
359  if (lang == HL_NONE)
360  lang = m_PlainTextLexerID;
361 
362  OptionSet& mset = m_Sets[lang];
363  for (unsigned int i = 0; i < mset.m_Colours.GetCount(); ++i)
364  {
365  OptionColour* opt = mset.m_Colours.Item(i);
366  if (opt->value == value)
367  return opt;
368  }
369  return nullptr;
370 }
371 
373 {
374  if (lang == HL_NONE)
375  return m_Sets[m_PlainTextLexerID].m_Colours.Item(index);
376  return m_Sets[lang].m_Colours.Item(index);
377 }
378 
380 {
381  if (lang != HL_NONE)
382  return m_Sets[lang].m_Colours.GetCount();
383  else
384  return m_Sets[m_PlainTextLexerID].m_Colours.GetCount();
385 }
386 
387 // Encapsulate the getter for the default option. The default option
388 // is the option named "Default" and if there is no such option we use
389 // the option with value/index equal to 0.
391 {
392  if (lang == HL_NONE)
393  lang = m_PlainTextLexerID;
394 
395  OptionSet& mset = m_Sets[lang];
396  OptionColour *defaultOpt = nullptr;
397  for (size_t i = 0; i < mset.m_Colours.GetCount(); ++i)
398  {
399  OptionColour* opt = mset.m_Colours.Item(i);
400  if (opt->name == wxT("Default"))
401  return opt;
402  if (opt->value == 0)
403  defaultOpt = opt;
404  }
405  return defaultOpt;
406 }
407 
409 {
410  // convert filename to lowercase first (m_FileMasks already contains
411  // lowercase-only strings) and allow for filemasks like Makefile.*:
412  wxString lfname = wxFileName(filename.Lower()).GetFullName();
413 
414  // first search in filemasks
415  for (OptionSetsMap::iterator it = m_Sets.begin(); it != m_Sets.end(); ++it)
416  {
417  for (unsigned int x = 0; x < it->second.m_FileMasks.GetCount(); ++x)
418  {
419  if (lfname.Matches(it->second.m_FileMasks.Item(x)))
420  return it->first;
421  }
422  }
423  // parse #! directive
424  if ( wxFileExists(filename) )
425  {
426  wxFileInputStream input(filename);
427  wxTextInputStream text(input);
428  wxString line;
429  if (input.IsOk() && !input.Eof() )
430  line = text.ReadLine();
431  if (!line.IsEmpty())
432  {
433  wxRegEx reSheBang(wxT("#![ \t]*([a-zA-Z/]+)[ \t]*([a-zA-Z/]*)"));
434  if (reSheBang.Matches(line))
435  {
436  wxString prog = reSheBang.GetMatch(line, 1);
437  if (prog.EndsWith(wxT("env")))
438  prog = reSheBang.GetMatch(line, 2);
439  if (prog.Find(wxT('/')) != wxNOT_FOUND)
440  prog = prog.AfterLast(wxT('/'));
441  if (prog == wxT("sh"))
442  prog = wxT("bash");
444  if (lang != HL_NONE)
445  return lang;
446  }
447  else if (line.Trim().StartsWith(wxT("<?xml")))
448  return GetHighlightLanguage(wxT("XML"));
449  }
450  }
451  // standard headers
452  const wxString cppNames = wxT("|"
453  "algorithm|" "atomic|" "array|" "bitset|"
454  "chrono|" "complex|" "condition_variable|" "deque|"
455  "exception|" "fstream|" "forward_list|" "future|"
456  "functional|" "hash_map|" "hash_set|" "initializer_list|"
457  "iomanip|" "ios|" "iostream|" "istream|"
458  "iterator|" "limits|" "list|" "locale|"
459  "map|" "memory|" "mutex|" "new|"
460  "numeric|" "ostream|" "queue|" "random|"
461  "ratio|" "regex|" "set|" "sstream|"
462  "stack|" "stdexcept|" "streambuf|" "string|"
463  "strstream|" "system_error|" "thread|" "tuple|"
464  "typeinfo|" "type_traits|" "unordered_map|" "unordered_set|"
465  "utility|" "valarray|" "vector|"
466 
467  "cassert|" "cctype|" "cerrno|" "cfenv|" "cfloat|"
468  "cinttypes|" "ciso646|" "climits|" "clocale|" "cmath|"
469  "csetjmp|" "csignal|" "cstdarg|" "cstdbool|" "cstddef|"
470  "cstdint|" "cstdio|" "cstdlib|" "cstring|" "ctgmath|"
471  "ctime|" "cuchar|" "cwchar|" "cwctype|" );
472  if (cppNames.Find(wxT("|") + lfname + wxT("|")) != wxNOT_FOUND)
473  return GetHighlightLanguage(wxT("C/C++"));
474 
475  return HL_NONE;
476 }
477 
479 {
480  if (lang != HL_NONE && lang != m_PlainTextLexerID)
481  {
482  wxString name = m_Sets[lang].m_Langs;
483  if (!name.empty())
484  return name;
485  }
486 
487  return _("Plain text");
488 }
489 
491 {
492  // option->value is ignored here...
493  // value is used instead
494  if (option->fore != wxNullColour)
495  control->StyleSetForeground(value, option->fore);
496  if (option->back != wxNullColour)
497  control->StyleSetBackground(value, option->back);
498  control->StyleSetBold(value, option->bold);
499  control->StyleSetItalic(value, option->italics);
500  control->StyleSetUnderline(value, option->underlined);
501 }
502 
504 {
505  if (!editor)
506  return HL_NONE;
507 
508  if (lang == HL_AUTO)
509  lang = GetLanguageForFilename(editor->GetFilename());
510 
511  const bool isC = ( Manager::Get()->GetConfigManager(wxT("editor"))->ReadBool(wxT("no_stl_in_c"), true)
512  && lang == GetHighlightLanguage(wxT("C/C++"))
513  && editor->GetFilename().Lower().EndsWith(wxT(".c")) );
514 
515  Apply(lang, editor->GetLeftSplitViewControl(), isC, colourise);
516  Apply(lang, editor->GetRightSplitViewControl(), isC, colourise);
517 
518  return lang;
519 }
520 
521 
522 
523 // Encapsulate the getter for the default option. The default option
524 // is the option named "Default" and if there is no such option we use
525 // the option with value/index equal to 0.
527 {
528  OptionColour *defaultOpt = nullptr;
529  for (size_t i = 0; i < mset.m_Colours.GetCount(); ++i)
530  {
531  OptionColour* opt = mset.m_Colours.Item(i);
532  if (opt->name == wxT("Default"))
533  return opt;
534  if (opt->value == 0)
535  defaultOpt = opt;
536  }
537  return defaultOpt;
538 }
539 
541  bool colourise)
542 {
543  if (!control)
544  return;
545  control->StyleClearAll();
546 
547  if (lang == HL_NONE)
548  {
550  return;
551  lang = m_PlainTextLexerID;
552  }
553 
554  // first load the default colours to all styles used by the actual lexer (ignoring some built-in styles)
555  OptionSet& mset = m_Sets[lang];
556  OptionColour* defaults = ::GetDefaultOption(mset);
557  control->SetLexer(mset.m_Lexers);
558  control->SetStyleBits(control->GetStyleBitsNeeded());
559  if (defaults)
560  {
561  int countStyles = 1 << control->GetStyleBits();
562  // walk until countStyles, otherwise the background-colour is only set for characters,
563  // not for empty background
564  for (int i = 0; i <= countStyles; ++i)
565  {
566  if (i < 33 || (i > 39 && i < wxSCI_STYLE_MAX))
567  DoApplyStyle(control, i, defaults);
568  }
569  }
570 
571  // Calling StyleClearAll above clears the style for the line numbers, so we have to re-apply it.
573  control->StyleSetForeground(wxSCI_STYLE_LINENUMBER, colours->GetColour(wxT("editor_linenumbers_fg")));
574  control->StyleSetBackground(wxSCI_STYLE_LINENUMBER, colours->GetColour(wxT("editor_linenumbers_bg")));
575 
576  for (unsigned int i = 0; i < mset.m_Colours.GetCount(); ++i)
577  {
578  OptionColour* opt = mset.m_Colours.Item(i);
579 
580  if (opt->isStyle)
581  {
582  DoApplyStyle(control, opt->value, opt);
583  }
584  else
585  {
586  if (opt->value == cbHIGHLIGHT_LINE)
587  {
588  control->SetCaretLineBackground(opt->back);
589  }
590  else if (opt->value == cbSELECTION)
591  {
592  if (opt->back != wxNullColour)
593  {
594  control->SetSelBackground(true, opt->back);
595 // Manager::Get()->GetConfigManager(_T("editor"))->Write(_T("/selection_colour"), opt->back);
596  }
597  else
598  control->SetSelBackground(false, wxColour(0xD9, 0xD9, 0xD9));
599 
600  if (opt->fore != wxNullColour)
601  {
602  control->SetSelForeground(true, opt->fore);
603 // Manager::Get()->GetConfigManager(_T("editor"))->Write(_T("/selection_fgcolour"), opt->fore);
604  }
605  else
606  control->SetSelForeground(false, *wxBLACK);
607  }
608 // else
609 // {
610 // control->MarkerDefine(-opt->value, 1);
611 // control->MarkerSetBackground(-opt->value, opt->back);
612 // }
613  }
614  }
615  for (int i = 0; i <= wxSCI_KEYWORDSET_MAX; ++i)
616  {
617  if (!isC || i != 1) // exclude stl highlights for C
618  control->SetKeyWords(i, mset.m_Keywords[i]);
619  }
620 
621  if (colourise)
622  control->Colourise(0, -1); // the *most* important part!
623 }
624 
626 {
627  // no need for syntax highlighting if batch building
628  if (Manager::IsBatchBuild())
629  return;
630 
631  wxString key;
632  ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("editor"));
633 
634  //FIXME: Commenting out the following line is no definite cure, but it hides the annoying disappearing colourset for now
635  //NOTE (mandrav): uncommenting it doesn't seem to cause any trouble (at least now). What was the problem?
636  cfg->DeleteSubPath(_T("/colour_sets/") + m_Name);
637 
638  // write the theme name
639  cfg->Write(_T("/colour_sets/") + m_Name + _T("/name"), m_Name);
640 
641  for (OptionSetsMap::iterator it = m_Sets.begin(); it != m_Sets.end(); ++it)
642  {
643  if (it->first == HL_NONE || it->first == HL_AUTO)
644  continue;
645  wxString lang = it->first;
646 
647  bool gsaved = false;
648 
649  key.Clear();
650  key << _T("/colour_sets/") << m_Name << _T('/') << lang;
651  for (unsigned int i = 0; i < it->second.m_Colours.GetCount(); ++i)
652  {
653  OptionColour* opt = it->second.m_Colours.Item(i);
654  wxString tmpKey;
655  tmpKey << key << _T("/style") << wxString::Format(_T("%u"), i);
656 
657  bool saved = false;
658 
659  if (opt->fore != opt->originalfore)
660  {
661  cfg->Write(tmpKey + _T("/fore"), opt->fore);
662  saved = true;
663  }
664  if (opt->back != opt->originalback)
665  {
666  cfg->Write(tmpKey + _T("/back"), opt->back);
667  saved = true;
668  }
669  if (opt->bold != opt->originalbold)
670  {
671  cfg->Write(tmpKey + _T("/bold"), opt->bold);
672  saved = true;
673  }
674  if (opt->italics != opt->originalitalics)
675  {
676  cfg->Write(tmpKey + _T("/italics"), opt->italics);
677  saved = true;
678  }
679  if (opt->underlined != opt->originalunderlined)
680  {
681  cfg->Write(tmpKey + _T("/underlined"), opt->underlined);
682  saved = true;
683  }
684  if (opt->isStyle != opt->originalisStyle)
685  {
686  cfg->Write(tmpKey + _T("/isStyle"), opt->isStyle);
687  saved = true;
688  }
689 
690  if (saved)
691  {
692  cfg->Write(tmpKey + _T("/name"), opt->name, true);
693  gsaved = true;
694  }
695  }
696  wxString tmpkey;
697  for (int i = 0; i <= wxSCI_KEYWORDSET_MAX; ++i)
698  {
699  if (it->second.m_Keywords[i] != it->second.m_originalKeywords[i])
700  {
701  tmpkey.Printf(_T("%s/editor/keywords/set%d"), key.c_str(), i);
702  cfg->Write(tmpkey, it->second.m_Keywords[i]);
703  gsaved = true;
704  }
705  }
706  tmpkey.Printf(_T("%s/editor/filemasks"), key.c_str());
707  wxString tmparr = GetStringFromArray(it->second.m_FileMasks, _T(","));
708  wxString tmparrorig = GetStringFromArray(it->second.m_originalFileMasks, _T(","));
709  if (tmparr != tmparrorig)
710  {
711  cfg->Write(tmpkey, tmparr);
712  gsaved = true;
713  }
714 
715  if (gsaved)
716  cfg->Write(key + _T("/name"), it->second.m_Langs);
717  }
718 }
719 
721 {
722  // no need for syntax highlighting if batch building
723  if (Manager::IsBatchBuild())
724  return;
725 
726  static bool s_notifiedUser = false;
727 
728  wxString key;
729  ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("editor"));
730 
731  // read the theme name
732  m_Name = cfg->Read(_T("/colour_sets/") + m_Name + _T("/name"), m_Name);
733 
734  int x = 0;
735  for (OptionSetsMap::iterator it = m_Sets.begin(); it != m_Sets.end(); ++it)
736  {
737  if (it->first == HL_NONE || it->first == HL_AUTO)
738  continue;
739 
740  // look for old-style configuration
741  key.Clear();
742  key << _T("/colour_sets/") << m_Name << _T("/set") << wxString::Format(_T("%d"), x++);
743  if (cfg->Exists(key + _T("/name")))
744  {
745  // old-style configuration
746  // delete it and tell the user about it
747  cfg->DeleteSubPath(key);
748  if (!s_notifiedUser)
749  {
750  cbMessageBox(_("The way editor syntax highlighting configuration is saved, has changed.\n"
751  "Syntax highlighting for all supported languages will revert to defaults now.\n"
752  "We 're sorry for the inconvenience..."),
753  _("Information"),
755  s_notifiedUser = true;
756  }
757  continue;
758  }
759  // make sure we didn't create it accidentally
760  cfg->DeleteSubPath(key);
761 
762  // new-style configuration key
763  key.Clear();
764  key << _T("/colour_sets/") << m_Name << _T('/') << it->first;
765  if (!cfg->Exists(key + _T("/name")))
766  {
767  // make sure we didn't create it accidentally
768  cfg->DeleteSubPath(key);
769  continue;
770  }
771 
772  for (unsigned int i = 0; i < it->second.m_Colours.GetCount(); ++i)
773  {
774  wxString tmpKey;
775  tmpKey << key << _T("/style") << wxString::Format(_T("%u"), i);
776  if (!cfg->Exists(tmpKey + _T("/name")))
777  {
778  // make sure we didn't create it accidentally
779  cfg->DeleteSubPath(tmpKey);
780  continue;
781  }
782  wxString name = cfg->Read(tmpKey + _T("/name"));
783  for (size_t j = 0; j < it->second.m_Colours.GetCount(); ++j)
784  {
785  OptionColour* opt = it->second.m_Colours.Item(j);
786  if (!opt || opt->name != name)
787  continue;
788 
789  if (cfg->Exists(tmpKey + _T("/fore")))
790  opt->fore = cfg->ReadColour(tmpKey + _T("/fore"), opt->fore);
791  if (cfg->Exists(tmpKey + _T("/back")))
792  opt->back = cfg->ReadColour(tmpKey + _T("/back"), opt->back);
793  if (cfg->Exists(tmpKey + _T("/bold")))
794  opt->bold = cfg->ReadBool(tmpKey + _T("/bold"), opt->bold);
795  if (cfg->Exists(tmpKey + _T("/italics")))
796  opt->italics = cfg->ReadBool(tmpKey + _T("/italics"), opt->italics);
797  if (cfg->Exists(tmpKey + _T("/underlined")))
798  opt->underlined = cfg->ReadBool(tmpKey + _T("/underlined"), opt->underlined);
799  if (cfg->Exists(tmpKey + _T("/isStyle")))
800  opt->isStyle = cfg->ReadBool(tmpKey + _T("/isStyle"), opt->isStyle);
801  }
802  }
803  wxString tmpkey;
804  for (int i = 0; i <= wxSCI_KEYWORDSET_MAX; ++i)
805  {
806  tmpkey.Printf(_T("%s/editor/keywords/set%d"), key.c_str(), i);
807  if (cfg->Exists(tmpkey))
808  it->second.m_Keywords[i] = cfg->Read(tmpkey, wxEmptyString);
809  }
810  tmpkey.Printf(_T("%s/editor/filemasks"), key.c_str());
811  if (cfg->Exists(tmpkey))
812  it->second.m_FileMasks = GetArrayFromString(cfg->Read(tmpkey, wxEmptyString), _T(","));
813  }
814 }
815 
817 {
818  // no need for syntax highlighting if batch building
819  if (Manager::IsBatchBuild())
820  return;
821 
822  wxString key;
823  key << _T("/colour_sets/") << m_Name << _T('/') << lang;
824  if (Manager::Get()->GetConfigManager(_T("editor"))->Exists(key + _T("/name")))
825  Manager::Get()->GetConfigManager(_T("editor"))->DeleteSubPath(key);
826 
829  Load();
830 }
831 
833 {
834  if (idx < 0 || idx > wxSCI_KEYWORDSET_MAX)
835  idx = 0;
836  return m_Sets[lang].m_Keywords[idx];
837 }
838 
839 void EditorColourSet::SetKeywords(HighlightLanguage lang, int idx, const wxString& keywords)
840 {
841  if (lang != HL_NONE && idx >=0 && idx <= wxSCI_KEYWORDSET_MAX)
842  {
843  wxString tmp(_T(' '), keywords.length()); // faster than using Alloc()
844 
845  const wxChar *src = keywords.c_str();
846  #if wxCHECK_VERSION(3, 0, 0)
847  wxStringCharType *dst = const_cast<wxStringCharType*>(tmp.wx_str());
848  #else
849  wxChar *dst = (wxChar *) tmp.c_str();
850  #endif
851  wxChar c;
852  size_t len = 0;
853 
854  while ((c = *src))
855  {
856  ++src;
857  if (c > _T(' '))
858  *dst = c;
859  else // white space
860  {
861  *dst = _T(' ');
862  while (*src && *src < _T(' '))
863  ++src;
864  }
865 
866  ++dst;
867  ++len;
868  }
869 
870  tmp.Truncate(len);
871 
872  OptionSet& mset = m_Sets[lang];
873  mset.m_Keywords[idx] = tmp;
874  }
875 }
876 
878 {
879  return m_Sets[lang].m_FileMasks;
880 }
881 
882 void EditorColourSet::SetFileMasks(HighlightLanguage lang, const wxString& masks, const wxString& separator)
883 {
884  if (lang == HL_NONE)
885  lang = m_PlainTextLexerID;
886 
887  m_Sets[lang].m_FileMasks = GetArrayFromString(masks.Lower(), separator);
888 
889  // let's add these filemasks in the file filters master list ;)
890  FileFilters::Add(wxString::Format(_("%s files"), m_Sets[lang].m_Langs.c_str()), masks);
891 }
892 
893 wxString EditorColourSet::GetSampleCode(HighlightLanguage lang, int* breakLine, int* debugLine, int* errorLine)
894 {
895  if (lang == HL_NONE)
896  lang = m_PlainTextLexerID;
897  OptionSet& mset = m_Sets[lang];
898  if (breakLine)
899  *breakLine = mset.m_BreakLine;
900  if (debugLine)
901  *debugLine = mset.m_DebugLine;
902  if (errorLine)
903  *errorLine = mset.m_ErrorLine;
904 
905  wxString shortname;
906  if (mset.m_SampleCode.IsEmpty())
907  shortname = _T("lexer_") + lang + _T(".sample");
908  else
909  shortname = mset.m_SampleCode;
910 
911  // user path first
912  wxString path = ConfigManager::GetFolder(sdDataUser) + _T("/lexers/");
913  if (wxFileExists(path + shortname))
914  return path + shortname;
915  else
916  {
917  // global path next
918  path = ConfigManager::GetFolder(sdDataGlobal) + _T("/lexers/");
919  if (wxFileExists(path + shortname))
920  return path + shortname;
921  }
922  return wxEmptyString;
923 }
924 
925 void EditorColourSet::SetSampleCode(HighlightLanguage lang, const wxString& sample, int breakLine, int debugLine, int errorLine)
926 {
927  if (lang == HL_NONE)
928  lang = m_PlainTextLexerID;
929  OptionSet& mset = m_Sets[lang];
930  mset.m_SampleCode = sample;
931  mset.m_BreakLine = breakLine;
932  mset.m_DebugLine = debugLine;
933  mset.m_ErrorLine = errorLine;
934 }
935 
937 {
938  if (lang == HL_NONE)
939  lang = m_PlainTextLexerID;
940 
941  m_Sets[lang].comment = token;
942 }
943 
945 {
946  CommentToken com;
947  com.lineComment = _T("");
948  com.doxygenLineComment = _T("");
949  com.streamCommentStart = _T("");
950  com.streamCommentEnd = _T("");
951  com.doxygenStreamCommentStart = _T("");
952  com.doxygenStreamCommentEnd = _T("");
953  com.boxCommentStart = _T("");
954  com.boxCommentMid = _T("");
955  com.boxCommentEnd = _T("");
956 
957  if (lang != HL_NONE)
958  com = m_Sets[lang].comment;
959 
960  return com;
961 }
962 
964 {
965  if ( lang == HL_NONE )
966  lang = m_PlainTextLexerID;
967 
968  m_Sets[lang].m_CaseSensitive = CaseSensitive;
969 }
970 
972 {
973  if ( lang == HL_NONE )
974  lang = m_PlainTextLexerID;
975 
976  return m_Sets[lang].m_CaseSensitive;
977 }
978 
979 void EditorColourSet::SetStringLexerStyles(HighlightLanguage lang, const std::set<int> &styles)
980 {
981  if ( lang == HL_NONE )
982  lang = m_PlainTextLexerID;
983 
984  cbStyledTextCtrl::GetStringLexerStyles()[m_Sets[lang].m_Lexers] = styles;
985 }
986 
987 void EditorColourSet::SetCommentLexerStyles(HighlightLanguage lang, const std::set<int> &styles)
988 {
989  if ( lang == HL_NONE )
990  lang = m_PlainTextLexerID;
991 
992  cbStyledTextCtrl::GetCommentLexerStyles()[m_Sets[lang].m_Lexers] = styles;
993 }
994 
995 void EditorColourSet::SetCharacterLexerStyles(HighlightLanguage lang, const std::set<int> &styles)
996 {
997  if ( lang == HL_NONE )
998  lang = m_PlainTextLexerID;
999 
1000  cbStyledTextCtrl::GetCharacterLexerStyles()[m_Sets[lang].m_Lexers] = styles;
1001 }
1002 
1004 {
1005  if ( lang == HL_NONE )
1006  lang = m_PlainTextLexerID;
1007 
1008  cbStyledTextCtrl::GetPreprocessorLexerStyles()[m_Sets[lang].m_Lexers] = styles;
1009 }
void SetSampleCode(HighlightLanguage lang, const wxString &sample, int breakLine, int debugLine, int errorLine)
wxString AfterLast(wxUniChar ch) const
wxString F(const wxChar *msg,...)
sprintf-like function
Definition: logmanager.h:20
DLLIMPORT wxArrayString GetArrayFromString(const wxString &text, const wxString &separator=DEFAULT_ARRAY_SEP, bool trimSpaces=true)
Definition: globals.cpp:134
OptionSetsMap m_Sets
DLLIMPORT bool Add(const wxString &name, const wxString &mask)
Add a new extension filter.
Definition: filefilters.cpp:41
wxString GetLanguageName(HighlightLanguage lang)
wxString doxygenLineComment
wxString lineComment
wxColour * wxBLACK
static wxString GetFolder(SearchDirs dir)
Access one of Code::Blocks&#39; folders.
bool Matches(const wxString &mask) const
Data folder in user&#39;s dir.
Definition: configmanager.h:75
void SetSelForeground(bool useSetting, const wxColour &fore)
Set the foreground colour of the main and additional selections and whether to use this setting...
void StyleClearAll()
Clear all the styles and make equivalent to the global default style.
bool IsOk() const
wxColour originalfore
bool wxIsspace(const wxUniChar &c)
void Delete(std::vector< T > &s)
Definition: safedelete.h:20
OptionColours m_Colours
ConfigManager * GetConfigManager(const wxString &name_space) const
Definition: manager.cpp:474
#define COLORSET_DEFAULT
bool originalunderlined
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
wxString Lower() const
void DoApplyStyle(cbStyledTextCtrl *control, int value, OptionColour *option)
size_t length() const
bool GetFirst(wxString *filename, const wxString &filespec=wxEmptyString, int flags=wxDIR_DEFAULT) const
bool wxFileExists(const wxString &filename)
wxColour wxNullColour
HighlightLanguage GetLanguageForFilename(const wxString &filename)
bool ReadBool(const wxString &name, bool defaultVal=false)
static std::map< int, std::set< int > > & GetCommentLexerStyles()
wxColour ReadColour(const wxString &name, const wxColour &defaultVal= *wxBLACK)
OptionColour * GetDefaultOption(HighlightLanguage lang)
size_t Length() const
bool Open(const wxString &dir)
wxCStrData c_str() const
bool wxDirExists(const wxString &dirname)
bool Matches(const wxString &text, int flags=0) const
static FileManager * Get()
Definition: manager.h:199
#define _T(string)
bool wxIsdigit(const wxUniChar &c)
const wxArrayString & GetFileMasks(HighlightLanguage lang)
wxString & GetKeywords(HighlightLanguage lang, int idx)
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)
wxString m_PlainTextLexerID
Stores the id of the plain text file lexer (see lexer_plain.xml).
void SetCharacterLexerStyles(HighlightLanguage lang, const std::set< int > &styles)
DLLIMPORT wxString GetStringFromArray(const wxArrayString &array, const wxString &separator=DEFAULT_ARRAY_SEP, bool SeparatorAtEnd=true)
Definition: globals.cpp:122
cbStyledTextCtrl * GetLeftSplitViewControl() const
Returns a pointer to the left (or top) split-view cbStyledTextCtrl.
Definition: cbeditor.h:87
#define wxICON_INFORMATION
#define wxT(string)
#define wxNOT_FOUND
void StyleSetBackground(int style, const wxColour &back)
Set the background colour of a style.
CommentToken GetCommentToken(HighlightLanguage lang)
void ClearAllOptionColours()
bool empty() const
int CmpNoCase(const wxString &s) const
wxString m_SampleCode
wxUSE_UNICODE_dependent wxChar
static std::map< int, std::set< int > > & GetCharacterLexerStyles()
wxString ReadLine()
void StyleSetUnderline(int style, bool underline)
Set a style to be underlined or not.
#define wxSCI_STYLE_LINENUMBER
Definition: wxscintilla.h:164
void Write(const wxString &name, const wxString &value, bool ignoreEmpty=false)
void SetCaretLineBackground(const wxColour &back)
Set the colour of the background of the line containing the caret.
virtual const wxString & GetFilename() const
Get the editor&#39;s filename (if applicable).
Definition: editorbase.h:45
wxString streamCommentStart
wxColour GetColour(const wxString &id) const
wxString GetSampleCode(HighlightLanguage lang, int *breakLine, int *debugLine, int *errorLine)
bool Exists(const wxString &name)
void SetSelBackground(bool useSetting, const wxColour &back)
Set the background colour of the main and additional selections and whether to use this setting...
void Load(LoaderBase *loader)
void SetPreprocessorLexerStyles(HighlightLanguage lang, const std::set< int > &styles)
void SetFileMasks(HighlightLanguage lang, const wxString &masks, const wxString &=_(","))
void StyleSetForeground(int style, const wxColour &fore)
Set the foreground colour of a style.
wxUSE_UNICODE_WCHAR_dependent wxStringCharType
void SetKeywords(HighlightLanguage lang, int idx, const wxString &keywords)
#define HL_NONE
Definition: globals.h:167
void SetCaseSensitivity(HighlightLanguage lang, bool CaseSensitive)
static bool IsBatchBuild()
Definition: manager.h:66
bool GetMatch(size_t *start, size_t *len, size_t index=0) const
static std::map< int, std::set< int > > & GetStringLexerStyles()
LogManager * GetLogManager() const
Definition: manager.cpp:439
wxString boxCommentStart
wxString Read(const wxString &key, const wxString &defaultVal=wxEmptyString)
static std::map< int, std::set< int > > & GetPreprocessorLexerStyles()
wxArrayString GetAllHighlightLanguages()
const wxStringCharType * wx_str() const
wxString doxygenStreamCommentEnd
wxString boxCommentEnd
const int cbHIGHLIGHT_LINE
int GetOptionCount(HighlightLanguage lang)
wxString wxEmptyString
void SetCommentLexerStyles(HighlightLanguage lang, const std::set< int > &styles)
const wxString & _(const wxString &string)
wxString & Trim(bool fromRight=true)
OptionColour * GetOptionByName(HighlightLanguage lang, const wxString &name)
wxString m_Keywords[wxSCI_KEYWORDSET_MAX+1]
#define wxSCI_LEX_NULL
Definition: wxscintilla.h:478
#define wxSCI_STYLE_MAX
Definition: wxscintilla.h:172
#define wxSCI_KEYWORDSET_MAX
Maximum value of keywordSet parameter of SetKeyWords.
Definition: wxscintilla.h:404
cb_must_consume_result LoaderBase * Load(const wxString &file, bool reuseEditors=false)
Loads a file, once this function is called, the actually loading process is done in the worker thread...
void SetLexer(int lexer)
Set the lexing language of the document.
bool wxIsalnum(const wxUniChar &c)
wxArrayString m_originalFileMasks
bool m_CaseSensitive
void Colourise(int start, int end)
Colourise a segment of the document using the current lexing language.
void StyleSetItalic(int style, bool italic)
Set a style to be italic or not.
ColourManager * GetColourManager() const
Definition: manager.cpp:489
void SetKeyWords(int keyWordSet, const wxString &keyWords)
Set up the key words used by the lexer.
wxString & Append(const char *psz)
#define wxSCI_LEX_LAST
Definition: wxscintilla.h:599
void Reset(HighlightLanguage lang)
wxString boxCommentMid
A file editor.
Definition: cbeditor.h:43
bool GetNext(wxString *filename) const
void DeleteSubPath(const wxString &strPath)
bool IsEmpty() const
bool GetCaseSensitivity(HighlightLanguage lang)
void Clear()
const int cbSELECTION
void Log(const wxString &msg, int i=app_log, Logger::level lv=Logger::info)
Definition: logmanager.h:140
OptionColour * GetOptionByIndex(HighlightLanguage lang, int index)
static int CompareStringNoCase(const wxString &first, const wxString &second)
bool EndsWith(const wxString &suffix, wxString *rest=NULL) const
void UpdateOptionsWithSameName(HighlightLanguage lang, OptionColour *base)
HighlightLanguage AddHighlightLanguage(int lexer, const wxString &name)
#define HL_AUTO
Definition: globals.h:166
wxString & Prepend(const wxString &str)
size_t Add(const wxString &str, size_t copies=1)
bool StartsWith(const wxString &prefix, wxString *rest=NULL) const
void StyleSetBold(int style, bool bold)
Set a style to be bold or not.
void Sort(bool reverseOrder=false)
wxColour originalback
wxArrayString m_FileMasks
int Find(wxUniChar ch, bool fromEnd=false) const
wxUniChar GetChar(size_t n) const
HighlightLanguage Apply(cbEditor *editor, HighlightLanguage lang, bool colourise)
void SetStringLexerStyles(HighlightLanguage lang, const std::set< int > &styles)
Data folder in base dir.
Definition: configmanager.h:81
cbStyledTextCtrl * GetRightSplitViewControl() const
Returns a pointer to the right (or bottom) split-view cbStyledTextCtrl.
Definition: cbeditor.h:92
int Printf(const wxString &pszFormat,...)
EditorColourSet(const wxString &setName=COLORSET_DEFAULT)
wxString doxygenStreamCommentStart
static wxString Format(const wxString &format,...)
wxString m_originalKeywords[wxSCI_KEYWORDSET_MAX+1]
DLLIMPORT int cbMessageBox(const wxString &message, const wxString &caption=wxEmptyString, int style=wxOK, wxWindow *parent=NULL, int x=-1, int y=-1)
wxMessageBox wrapper.
Definition: globals.cpp:1395
CommentToken comment
HighlightLanguage GetHighlightLanguage(int lexer)
OptionColour * GetOptionByValue(HighlightLanguage lang, int value)
wxString m_Langs
wxString streamCommentEnd