Rewrite the subtitles edit control's syntax highlighting

Simplify and clean up the parsing code to better represent how VSFilter
actually handles many odd edge cases as well as making it significantly
faster.

Use an enum for syntax style IDs rather than magic numbers.

Add styles for comments, draw mode and karaoke templater variables
rather than reusing other styles and move some hardcoded style
information to the config file.

Operate on the utf-8 representation of the edit box text rather than a
wxString, as it's both faster and simpler.

Originally committed to SVN as r5615.
This commit is contained in:
Thomas Goyne 2011-09-28 19:44:34 +00:00
parent 67ab06e830
commit a25c5c1909
4 changed files with 218 additions and 269 deletions

View File

@ -91,7 +91,7 @@ void Options::LoadConfig(std::istream& stream) {
LOG_E("option/load") << "json::Exception: " << e.what(); LOG_E("option/load") << "json::Exception: " << e.what();
} }
ConfigVisitor config_visitor(values, std::string("")); ConfigVisitor config_visitor(values, "");
config_root.Accept(config_visitor); config_root.Accept(config_visitor);
} }

View File

@ -136,16 +136,42 @@
"Subtitle" : { "Subtitle" : {
"Syntax" : { "Syntax" : {
"Background" : { "Background" : {
"Error" : "rgb(255, 200, 200)" "Brackets" : "",
"Comment" : "",
"Drawing" : "",
"Error" : "rgb(255, 200, 200)",
"Karaoke Template" : "",
"Karaoke Variable" : "",
"Line Break" : "",
"Normal" : "",
"Parameters" : "",
"Slashes" : "",
"Tags" : ""
},
"Bold" : {
"Brackets" : false,
"Comment" : true,
"Drawing" : true,
"Error" : false,
"Karaoke Template" : true,
"Karaoke Variable" : true,
"Line Break" : true,
"Normal" : false,
"Parameters" : false,
"Slashes" : false,
"Tags" : true
}, },
"Brackets" : "rgb(20, 50, 255)", "Brackets" : "rgb(20, 50, 255)",
"Comment" : "rgb(0,0,0)",
"Drawing" : "rgb(0,0,0)",
"Error" : "rgb(200, 0, 0)", "Error" : "rgb(200, 0, 0)",
"Highlight Tags" : "rgb(90, 90, 90)",
"Karaoke Template" : "rgb(128, 0, 192)", "Karaoke Template" : "rgb(128, 0, 192)",
"Karaoke Variable" : "rgb(128, 0, 192)",
"Line Break" : "rgb(160, 160, 160)", "Line Break" : "rgb(160, 160, 160)",
"Normal" : "rgb(0,0,0)", "Normal" : "rgb(0,0,0)",
"Parameters" : "rgb(40, 90, 40)", "Parameters" : "rgb(40, 90, 40)",
"Slashes" : "rgb(255, 0, 200)" "Slashes" : "rgb(255, 0, 200)",
"Tags" : "rgb(90, 90, 90)"
} }
}, },
"Video Dummy" : { "Video Dummy" : {

View File

@ -75,18 +75,6 @@ enum {
EDIT_MENU_THES_LANGS EDIT_MENU_THES_LANGS
}; };
/// @brief Edit box constructor
/// @param parent
/// @param id
/// @param value
/// @param pos
/// @param wsize
/// @param style
/// @param validator
/// @param name
/// @return
///
SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxSize wsize, long style, SubtitlesGrid *grid) SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxSize wsize, long style, SubtitlesGrid *grid)
: ScintillaTextCtrl(parent, wxID_ANY) : ScintillaTextCtrl(parent, wxID_ANY)
, spellchecker(SpellCheckerFactory::GetSpellChecker()) , spellchecker(SpellCheckerFactory::GetSpellChecker())
@ -186,17 +174,19 @@ SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxSize wsize, long style, S
OPT_SUB("Subtitle/Edit Box/Font Face", &SubsTextEditCtrl::SetStyles, this); OPT_SUB("Subtitle/Edit Box/Font Face", &SubsTextEditCtrl::SetStyles, this);
OPT_SUB("Subtitle/Edit Box/Font Size", &SubsTextEditCtrl::SetStyles, this); OPT_SUB("Subtitle/Edit Box/Font Size", &SubsTextEditCtrl::SetStyles, this);
OPT_SUB("Colour/Subtitle/Syntax/Normal", &SubsTextEditCtrl::SetStyles, this); Subscribe("Normal");
OPT_SUB("Colour/Subtitle/Syntax/Brackets", &SubsTextEditCtrl::SetStyles, this); Subscribe("Comment");
OPT_SUB("Colour/Subtitle/Syntax/Slashes", &SubsTextEditCtrl::SetStyles, this); Subscribe("Drawing");
OPT_SUB("Colour/Subtitle/Syntax/Highlight Tags", &SubsTextEditCtrl::SetStyles, this); Subscribe("Brackets");
OPT_SUB("Colour/Subtitle/Syntax/Error", &SubsTextEditCtrl::SetStyles, this); Subscribe("Slashes");
OPT_SUB("Colour/Subtitle/Syntax/Background/Error", &SubsTextEditCtrl::SetStyles, this); Subscribe("Tags");
OPT_SUB("Colour/Subtitle/Syntax/Parameters", &SubsTextEditCtrl::SetStyles, this); Subscribe("Error");
OPT_SUB("Colour/Subtitle/Syntax/Line Break", &SubsTextEditCtrl::SetStyles, this); Subscribe("Parameters");
OPT_SUB("Colour/Subtitle/Syntax/Karaoke Template", &SubsTextEditCtrl::SetStyles, this); Subscribe("Line Break");
Subscribe("Karaoke Template");
Subscribe("Karaoke Variable");
OPT_SUB("Subtitle/Highlight/Syntax", &SubsTextEditCtrl::UpdateStyle, this, 0, -1); OPT_SUB("Subtitle/Highlight/Syntax", &SubsTextEditCtrl::UpdateStyle, this);
static wxStyledTextEvent evt; static wxStyledTextEvent evt;
OPT_SUB("App/Call Tips", &SubsTextEditCtrl::UpdateCallTip, this, ref(evt)); OPT_SUB("App/Call Tips", &SubsTextEditCtrl::UpdateCallTip, this, ref(evt));
} }
@ -205,6 +195,12 @@ SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxSize wsize, long style, S
SubsTextEditCtrl::~SubsTextEditCtrl() { SubsTextEditCtrl::~SubsTextEditCtrl() {
} }
void SubsTextEditCtrl::Subscribe(std::string const& name) {
OPT_SUB("Colour/Subtitle/Syntax/" + name, &SubsTextEditCtrl::SetStyles, this);
OPT_SUB("Colour/Subtitle/Syntax/Background/" + name, &SubsTextEditCtrl::SetStyles, this);
OPT_SUB("Colour/Subtitle/Syntax/Bold/" + name, &SubsTextEditCtrl::SetStyles, this);
}
BEGIN_EVENT_TABLE(SubsTextEditCtrl,wxStyledTextCtrl) BEGIN_EVENT_TABLE(SubsTextEditCtrl,wxStyledTextCtrl)
EVT_KILL_FOCUS(SubsTextEditCtrl::OnLoseFocus) EVT_KILL_FOCUS(SubsTextEditCtrl::OnLoseFocus)
@ -222,279 +218,207 @@ void SubsTextEditCtrl::OnLoseFocus(wxFocusEvent &event) {
event.Skip(); event.Skip();
} }
enum {
STYLE_NORMAL = 0,
STYLE_COMMENT,
STYLE_DRAWING,
STYLE_OVERRIDE,
STYLE_PUNCTUATION,
STYLE_TAG,
STYLE_ERROR,
STYLE_PARAMETER,
STYLE_LINE_BREAK,
STYLE_KARAOKE_TEMPLATE,
STYLE_KARAOKE_VARIABLE
};
void SubsTextEditCtrl::SetStyle(int id, wxFont &font, std::string const& name) {
StyleSetFont(id, font);
StyleSetBold(id, OPT_GET("Colour/Subtitle/Syntax/Bold/" + name)->GetBool());
StyleSetForeground(id, lagi_wxColour(OPT_GET("Colour/Subtitle/Syntax/" + name)->GetColour()));
const agi::OptionValue *background = OPT_GET("Colour/Subtitle/Syntax/Background/" + name);
if (background->GetType() == agi::OptionValue::Type_Colour)
StyleSetBackground(id, lagi_wxColour(background->GetColour()));
}
void SubsTextEditCtrl::SetStyles() { void SubsTextEditCtrl::SetStyles() {
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
font.SetEncoding(wxFONTENCODING_DEFAULT); // this solves problems with some fonts not working properly font.SetEncoding(wxFONTENCODING_DEFAULT); // this solves problems with some fonts not working properly
wxString fontname = lagi_wxString(OPT_GET("Subtitle/Edit Box/Font Face")->GetString()); wxString fontname = lagi_wxString(OPT_GET("Subtitle/Edit Box/Font Face")->GetString());
if (!fontname.empty()) font.SetFaceName(fontname); if (!fontname.empty()) font.SetFaceName(fontname);
int size = OPT_GET("Subtitle/Edit Box/Font Size")->GetInt(); font.SetPointSize(OPT_GET("Subtitle/Edit Box/Font Size")->GetInt());
// Normal style SetStyle(STYLE_NORMAL, font, "Normal");
StyleSetFont(0,font); SetStyle(STYLE_COMMENT, font, "Comment");
StyleSetSize(0,size); SetStyle(STYLE_DRAWING, font, "Drawing");
StyleSetForeground(0,lagi_wxColour(OPT_GET("Colour/Subtitle/Syntax/Normal")->GetColour())); SetStyle(STYLE_OVERRIDE, font, "Brackets");
SetStyle(STYLE_PUNCTUATION, font, "Slashes");
// Brackets style SetStyle(STYLE_TAG, font, "Tags");
StyleSetFont(1,font); SetStyle(STYLE_ERROR, font, "Error");
StyleSetSize(1,size); SetStyle(STYLE_PARAMETER, font, "Parameters");
StyleSetForeground(1,lagi_wxColour(OPT_GET("Colour/Subtitle/Syntax/Brackets")->GetColour())); SetStyle(STYLE_LINE_BREAK, font, "Line Break");
SetStyle(STYLE_KARAOKE_TEMPLATE, font, "Karaoke Template");
// Slashes/Parenthesis/Comma style SetStyle(STYLE_KARAOKE_VARIABLE, font, "Karaoke Variable");
StyleSetFont(2,font);
StyleSetSize(2,size);
StyleSetForeground(2,lagi_wxColour(OPT_GET("Colour/Subtitle/Syntax/Slashes")->GetColour()));
// Tags style
StyleSetFont(3,font);
StyleSetSize(3,size);
StyleSetBold(3,true);
StyleSetForeground(3,lagi_wxColour(OPT_GET("Colour/Subtitle/Syntax/Highlight Tags")->GetColour()));
// Error style
StyleSetFont(4,font);
StyleSetSize(4,size);
StyleSetForeground(4,lagi_wxColour(OPT_GET("Colour/Subtitle/Syntax/Error")->GetColour()));
StyleSetBackground(4,lagi_wxColour(OPT_GET("Colour/Subtitle/Syntax/Background/Error")->GetColour()));
// Tag Parameters style
StyleSetFont(5,font);
StyleSetSize(5,size);
StyleSetForeground(5,lagi_wxColour(OPT_GET("Colour/Subtitle/Syntax/Parameters")->GetColour()));
// Line breaks style
StyleSetFont(6,font);
StyleSetSize(6,size);
StyleSetBold(6,true);
StyleSetForeground(6,lagi_wxColour(OPT_GET("Colour/Subtitle/Syntax/Line Break")->GetColour()));
// Karaoke template code block style
StyleSetFont(7,font);
StyleSetSize(7,size);
StyleSetBold(7,true);
//StyleSetItalic(7,true);
StyleSetForeground(7,lagi_wxColour(OPT_GET("Colour/Subtitle/Syntax/Karaoke Template")->GetColour()));
// Misspelling indicator // Misspelling indicator
IndicatorSetStyle(0,wxSTC_INDIC_SQUIGGLE); IndicatorSetStyle(0,wxSTC_INDIC_SQUIGGLE);
IndicatorSetForeground(0,wxColour(255,0,0)); IndicatorSetForeground(0,wxColour(255,0,0));
} }
void SubsTextEditCtrl::UpdateStyle(int start, int _length) { void SubsTextEditCtrl::UpdateStyle() {
StartUnicodeStyling(0,255); StartStyling(0,255);
std::string text = STD_STR(GetText());
if (!OPT_GET("Subtitle/Highlight/Syntax")->GetBool()) { if (!OPT_GET("Subtitle/Highlight/Syntax")->GetBool()) {
SetUnicodeStyling(start, _length, 0); SetStyling(text.size(), 0);
return; return;
} }
if (text.empty()) return;
// Check if it's a template line // Check if it's a template line
AssDialogue *diag = grid->GetActiveLine(); AssDialogue *diag = grid->GetActiveLine();
bool templateLine = diag && diag->Comment && diag->Effect.Lower().StartsWith("template"); bool templateLine = diag && diag->Comment && diag->Effect.Lower().StartsWith("template");
//bool templateCodeLine = diag && diag->Comment && diag->Effect.Lower().StartsWith("code");
// Template code lines get Lua highlighting instead of ASS highlighting bool in_parens = false;
// This is broken and needs some extra work bool in_unparened_arg = false;
/*if (templateCodeLine) { bool in_draw_mode = false;
SetLexer(wxSTC_LEX_LUA); bool in_ovr = false;
Colourise(start, start+_length); bool in_karaoke_template = false;
return;
}
else {
SetLexer(wxSTC_LEX_CONTAINER);
}*/
// Set variables int range_len = 0;
wxString text = GetText(); int style = STYLE_NORMAL;
int end = start + _length;
if (_length < 0) end = text.Length();
// Flags char cur_char = 0;
bool numMode = false; // everything is considered a number/parameter until this is unset char next_char = text[0];
bool drawingMode = false; // for \p1 -> \p0 stuff
// Begin styling size_t eat_chars = 0;
int ran = 0; // length of current range
int depth = 0; // brace nesting depth
int curStyle = 0; // style to apply to current range
int curPos = 0; // start of current range?
wxChar curChar = 0;
wxChar prevChar = 0;
wxChar nextChar = 0;
// Loop through for (size_t i = 0; i < text.size(); ++i) {
for (int i=start;i<end;i++) {
// Current/previous characters // Current/previous characters
prevChar = curChar; char prev_char = cur_char;
curChar = text[i]; cur_char = next_char;
if (i<end-1) nextChar = text[i+1]; next_char = i + 1 < text.size() ? text[i + 1] : 0;
else nextChar = 0;
// Erroneous if (eat_chars > 0) {
if (depth < 0 || depth > 1) { ++range_len;
SetUnicodeStyling(curPos,ran,curStyle); --eat_chars;
curPos += ran; continue;
ran = 0;
curStyle = 4;
numMode = false;
} }
int new_style = style;
// Start override block // Start override block
if (curChar == '{' && depth >= 0) { if (cur_char == '{') {
SetUnicodeStyling(curPos,ran,curStyle); new_style = in_ovr ? STYLE_ERROR : STYLE_OVERRIDE;
curPos += ran; in_ovr = true;
ran = 0; in_parens = false;
depth++;
if (depth == 1) curStyle = 1;
else curStyle = 4;
numMode = false;
} }
// End override block // End override block
else if (curChar == '}' && depth <= 1) { else if (cur_char == '}') {
SetUnicodeStyling(curPos,ran,curStyle); new_style = in_ovr ? STYLE_OVERRIDE : STYLE_ERROR;
curPos += ran; in_ovr = false;
ran = 0;
depth--;
if (depth == 0) curStyle = 1;
else curStyle = 4;
numMode = false;
} }
// Start karaoke template
// Karaoke template block else if (templateLine && style != STYLE_KARAOKE_TEMPLATE && cur_char == '!') {
else if (templateLine && curChar == '!') { new_style = STYLE_KARAOKE_TEMPLATE;
// Apply previous style in_karaoke_template = true;
SetUnicodeStyling(curPos,ran,curStyle);
curPos += ran;
ran = -1; // such that ran++ later on resets it to 0 !
// Eat entire template block
int endPos = i+1;
while (endPos < end && text[endPos] != '!')
endPos++;
SetUnicodeStyling(curPos,endPos-curPos+1,7);
curPos = endPos+1;
i = endPos+0;
} }
// Karaoke template variable // End karaoke template
else if (templateLine && curChar == '$') { else if (style == STYLE_KARAOKE_TEMPLATE && cur_char == '!') {
// Apply previous style in_karaoke_template = false;
SetUnicodeStyling(curPos,ran,curStyle);
curPos += ran;
ran = -1; // such that ran++ later on resets it to 0 !
// Eat entire variable
int endPos = i+1;
while (endPos < end) {
wxChar ch = text[endPos];
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_')
endPos++;
else
break;
} }
SetUnicodeStyling(curPos,endPos-curPos,7); // Continue karaoke template
curPos = endPos; else if (in_karaoke_template) {
i = curPos-1; // Do nothing and just continue the karaoke template style
} }
// Start karaoke template variable
// Outside else if (templateLine && style != STYLE_KARAOKE_TEMPLATE && cur_char == '$') {
else if (depth == 0) { new_style = STYLE_KARAOKE_VARIABLE;
// Reset number mode }
numMode = false; // Continue karaoke template variable
else if (style == STYLE_KARAOKE_VARIABLE && ((cur_char >= 'A' && cur_char <= 'Z') || (cur_char >= 'a' && cur_char <= 'z') || cur_char == '_')) {
// Do nothing and just continue the karaoke variable style
}
// Plain text
else if (!in_ovr) {
// Is \n, \N or \h? // Is \n, \N or \h?
if (curChar == '\\' && (nextChar == 'n' || nextChar == 'N' || nextChar == 'h')) { if (cur_char == '\\' && (next_char == 'n' || next_char == 'N' || next_char == 'h')) {
SetUnicodeStyling(curPos,ran,curStyle); new_style = STYLE_LINE_BREAK;
curPos += ran; eat_chars = 1;
ran = 1;
curStyle = 6;
i++;
} }
else if (in_draw_mode)
// Normal text new_style = STYLE_DRAWING;
else if (curStyle != 0) { else
SetUnicodeStyling(curPos,ran,curStyle); new_style = STYLE_NORMAL;
curPos += ran;
ran = 0;
if (drawingMode) curStyle = 6;
else curStyle = 0;
} }
} // Inside override tag
// Inside
else if (depth == 1) {
// Special character
if (curChar == '\\' || curChar == '(' || curChar == ')' || curChar == ',') {
if (curStyle != 2) {
SetUnicodeStyling(curPos,ran,curStyle);
curPos += ran;
ran = 0;
curStyle = 2;
numMode = false;
}
}
else { else {
// Number // Special character
if (prevChar != '\\' && (numMode || (curChar >= '0' && curChar <= '9') || curChar == '.' || curChar == '&' || curChar == '+' || curChar == '-' || (curChar == 'H' && prevChar == '&'))) { if (cur_char == '\\' || cur_char == '(' || cur_char == ')' || cur_char == ',') {
if (curStyle != 5) { new_style = STYLE_PUNCTUATION;
SetUnicodeStyling(curPos,ran,curStyle); in_unparened_arg = false;
curPos += ran;
ran = 0; if (style == STYLE_TAG && cur_char == '(')
curStyle = 5; in_parens = true;
numMode = true; // This is technically wrong for nested tags, but it doesn't
// matter as \t doesn't have any arguments after the subtag(s)
else if (cur_char == ')')
in_parens = false;
} }
// Beginning of a tag
else if (prev_char == '\\') {
new_style = STYLE_TAG;
// \r and \fn are special as their argument is an
// unparenthesized string
if (cur_char == 'r')
in_unparened_arg = true;
else if (cur_char == 'f' && next_char == 'n') {
eat_chars = 1;
in_unparened_arg = true;
} }
// For \p we need to check if it's entering or leaving draw mode
// Tag name // Luckily draw mode can't be set in the style, so no argument
else if (curStyle != 3) { // always means leave draw mode
SetUnicodeStyling(curPos,ran,curStyle); else if (cur_char == 'p' && (next_char < 'a' || next_char > 'z')) {
curPos += ran; in_draw_mode = false;
ran = 0; for (size_t idx = i + 1; idx < text.size(); ++idx) {
curStyle = 3; char c = text[idx];
// I have no idea why one would use leading zeros for
// Set parameter if it's \fn or \r // the scale, but vsfilter allows it
int tagLen = 0; if (c >= '1' && c <= '9')
if (text.Mid(curPos,2) == "fn") tagLen = 2; in_draw_mode = true;
else if (text.Mid(curPos,1) == "r") tagLen = 1; else if (c != '0')
if (tagLen) {
numMode = true;
ran = tagLen-1;
i+=ran;
}
// Set drawing mode if it's \p
if (text.Mid(curPos,1) == "p") {
if (curPos+2 < (signed) text.Length()) {
// Disable
wxChar nextNext = text[curPos+2];
if ((nextNext == '\\' || nextNext == '}') && nextChar == '0') drawingMode = false;
// Enable
if (nextChar >= '1' && nextChar <= '9') {
for(int testPos = curPos+2;testPos < (signed) text.Length();testPos++) {
nextNext = text[testPos];
if (nextNext == '\\' || nextNext == '}') {
drawingMode = true;
break; break;
} }
if (nextNext < '0' || nextNext > '9') break;
}
}
} }
// All tags start with letters or numbers
else if (cur_char < '0' || (cur_char > '9' && cur_char < 'A') || (cur_char > 'Z' && cur_char < 'a') || cur_char > 'z')
new_style = STYLE_ERROR;
} }
else if ((in_parens && style != STYLE_TAG) || in_unparened_arg || (style == STYLE_TAG && ((cur_char < 'A' || cur_char > 'z') || (cur_char > 'Z' && cur_char < 'a')))) {
new_style = STYLE_PARAMETER;
} }
else if (style != STYLE_TAG && style != STYLE_PARAMETER) {
new_style = STYLE_COMMENT;
} }
} }
// Increase ran length if (new_style != style) {
ran++; SetStyling(range_len, style);
style = new_style;
range_len = 0;
} }
SetUnicodeStyling(curPos,ran,curStyle);
StyleSpellCheck(start,_length); ++range_len;
}
SetStyling(range_len, style);
StyleSpellCheck();
wxStyledTextEvent evt; wxStyledTextEvent evt;
UpdateCallTip(evt); UpdateCallTip(evt);
} }
/// @brief Update call tip /// @brief Update call tip
void SubsTextEditCtrl::UpdateCallTip(wxStyledTextEvent &) { void SubsTextEditCtrl::UpdateCallTip(wxStyledTextEvent &) {
if (!OPT_GET("App/Call Tips")->GetBool()) return; if (!OPT_GET("App/Call Tips")->GetBool()) return;
@ -709,13 +633,13 @@ void SubsTextEditCtrl::UpdateCallTip(wxStyledTextEvent &) {
CallTipSetHighlight(highStart,highEnd); CallTipSetHighlight(highStart,highEnd);
} }
void SubsTextEditCtrl::StyleSpellCheck(int start, int len) { void SubsTextEditCtrl::StyleSpellCheck() {
if (!spellchecker.get()) return; if (!spellchecker.get()) return;
// Results // Results
wxString text = GetText(); wxString text = GetText();
IntPairVector results; IntPairVector results;
GetWordBoundaries(text,results,start,(len == -1) ? len : start+len); GetWordBoundaries(text,results);
// Style // Style
int count = results.size(); int count = results.size();
@ -727,11 +651,7 @@ void SubsTextEditCtrl::StyleSpellCheck(int start, int len) {
// Check if it's valid // Check if it's valid
if (!spellchecker->CheckWord(curWord)) { if (!spellchecker->CheckWord(curWord)) {
// Get length before it StartUnicodeStyling(s,32);
int utf8len = GetUnicodePosition(s);
// Set styling
StartStyling(utf8len,32);
SetUnicodeStyling(s,e-s,32); SetUnicodeStyling(s,e-s,32);
} }
} }
@ -752,7 +672,6 @@ void SubsTextEditCtrl::SetTextTo(wxString text) {
int from=0,to=0; int from=0,to=0;
GetSelection(&from,&to); GetSelection(&from,&to);
Clear();
SetText(text); SetText(text);
UpdateStyle(); UpdateStyle();
@ -999,10 +918,10 @@ void SubsTextEditCtrl::OnSetDicLanguage(wxCommandEvent &event) {
// Set dictionary // Set dictionary
int index = event.GetId() - EDIT_MENU_DIC_LANGS - 1; int index = event.GetId() - EDIT_MENU_DIC_LANGS - 1;
wxString lang; if (index >= 0) {
if (index >= 0) lang = langs[index]; spellchecker->SetLanguage(langs[index]);
spellchecker->SetLanguage(lang); OPT_SET("Tool/Spell Checker/Language")->SetString(STD_STR(langs[index]));
OPT_SET("Tool/Spell Checker/Language")->SetString(STD_STR(lang)); }
UpdateStyle(); UpdateStyle();
} }
@ -1012,10 +931,10 @@ void SubsTextEditCtrl::OnSetThesLanguage(wxCommandEvent &event) {
// Set language // Set language
int index = event.GetId() - EDIT_MENU_THES_LANGS - 1; int index = event.GetId() - EDIT_MENU_THES_LANGS - 1;
wxString lang; if (index >= 0) {
if (index >= 0) lang = langs[index]; thesaurus->SetLanguage(langs[index]);
thesaurus->SetLanguage(lang); OPT_SET("Tool/Thesaurus/Language")->SetString(STD_STR(langs[index]));
OPT_SET("Tool/Thesaurus/Language")->SetString(STD_STR(lang)); }
UpdateStyle(); UpdateStyle();
} }

View File

@ -88,15 +88,19 @@ class SubsTextEditCtrl : public ScintillaTextCtrl {
void OnSetThesLanguage(wxCommandEvent &event); void OnSetThesLanguage(wxCommandEvent &event);
void OnLoseFocus(wxFocusEvent &event); void OnLoseFocus(wxFocusEvent &event);
void SetStyle(int id, wxFont &font, std::string const& name);
void Subscribe(std::string const& name);
void StyleSpellCheck();
void UpdateCallTip(wxStyledTextEvent &);
void SetStyles();
public: public:
SubsTextEditCtrl(wxWindow* parent, wxSize size, long style, SubtitlesGrid *grid); SubsTextEditCtrl(wxWindow* parent, wxSize size, long style, SubtitlesGrid *grid);
~SubsTextEditCtrl(); ~SubsTextEditCtrl();
void SetTextTo(wxString text); void SetTextTo(wxString text);
void UpdateStyle(int start=0,int length=-1); void UpdateStyle();
void StyleSpellCheck(int start=0,int length=-1);
void UpdateCallTip(wxStyledTextEvent &);
void SetStyles();
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };