diff --git a/core/options.cpp b/core/options.cpp index e897fb991..8f83a2fae 100644 --- a/core/options.cpp +++ b/core/options.cpp @@ -137,6 +137,7 @@ void OptionsManager::LoadDefaults() { SetColour(_T("Syntax Highlight Tags"),wxColour(90,90,90)); SetColour(_T("Syntax Highlight Numbers"),wxColour(0,90,0)); SetColour(_T("Syntax Highlight Error"),wxColour(200,0,0)); + SetColour(_T("Syntax Highlight Line Break"),wxColour(160,160,160)); SetColour(_T("Edit Box Need Enter Background"),wxColour(192,192,255)); #if defined(__WINDOWS__) SetInt(_T("Font Size"),9); diff --git a/core/spellchecker.h b/core/spellchecker.h index 8e39ab116..d715307eb 100644 --- a/core/spellchecker.h +++ b/core/spellchecker.h @@ -51,6 +51,7 @@ public: SpellChecker() {} virtual ~SpellChecker() {} + virtual void AddWord(wxString word)=0; virtual bool CheckWord(wxString word)=0; virtual wxArrayString GetSuggestions(wxString word)=0; diff --git a/core/spellchecker_hunspell.cpp b/core/spellchecker_hunspell.cpp index 7e40ee6cf..2e8d32ed8 100644 --- a/core/spellchecker_hunspell.cpp +++ b/core/spellchecker_hunspell.cpp @@ -60,6 +60,13 @@ HunspellSpellChecker::~HunspellSpellChecker() { } +////////////////////////// +// Add word to dictionary +void HunspellSpellChecker::AddWord(wxString word) { + if (hunspell) hunspell->put_word(word.mb_str(wxConvUTF8)); +} + + ////////////////////////////// // Check if the word is valid bool HunspellSpellChecker::CheckWord(wxString word) { @@ -71,7 +78,27 @@ bool HunspellSpellChecker::CheckWord(wxString word) { //////////////////////////// // Get suggestions for word wxArrayString HunspellSpellChecker::GetSuggestions(wxString word) { + // Array wxArrayString suggestions; + + // Get suggestions + if (hunspell) { + // Grab raw from Hunspell + char **results; + int n = hunspell->suggest(&results,word.mb_str(wxConvUTF8)); + + // Convert each + for (int i=0;iGetSelection(&from, &to); - grid->SplitLine(linen,from,0); -} - - -/////////////////////////////// -// Split line estimating times -void SubsEditBox::OnSplitLineEstimate (wxCommandEvent &event) { - int from,to; - TextEdit->GetSelection(&from, &to); - grid->SplitLine(linen,from,1); -} - - -/////// -// Cut -void SubsEditBox::OnCut(wxCommandEvent &event) { - TextEdit->Cut(); -} - - -//////// -// Copy -void SubsEditBox::OnCopy(wxCommandEvent &event) { - TextEdit->Copy(); -} - - -///////// -// Paste -void SubsEditBox::OnPaste(wxCommandEvent &event) { - TextEdit->Paste(); -} - - -//////// -// Undo -void SubsEditBox::OnUndo(wxCommandEvent &event) { - TextEdit->Undo(); -} - - -////////////// -// Select All -void SubsEditBox::OnSelectAll(wxCommandEvent &event) { - TextEdit->SetSelection(-1,-1); -} - - ////////////////////////////////////// // Gets block number at text position int SubsEditBox::BlockAtPos(int pos) { diff --git a/core/subs_edit_box.h b/core/subs_edit_box.h index 0d0cbf8d2..a0396d6b8 100644 --- a/core/subs_edit_box.h +++ b/core/subs_edit_box.h @@ -127,14 +127,6 @@ private: void OnCommentChange(wxCommandEvent &event); void OnEffectChange(wxCommandEvent &event); - void OnSplitLinePreserve(wxCommandEvent &event); - void OnSplitLineEstimate(wxCommandEvent &event); - void OnCut(wxCommandEvent &event); - void OnCopy(wxCommandEvent &event); - void OnPaste(wxCommandEvent &event); - void OnUndo(wxCommandEvent &event); - void OnSelectAll(wxCommandEvent &event); - public: int linen; AudioDisplay *audio; @@ -188,13 +180,6 @@ enum { MARGINV_BOX, EFFECT_BOX, COMMENT_CHECKBOX, - EDIT_MENU_SPLIT_PRESERVE, - EDIT_MENU_SPLIT_ESTIMATE, - EDIT_MENU_CUT, - EDIT_MENU_COPY, - EDIT_MENU_PASTE, - EDIT_MENU_UNDO, - EDIT_MENU_SELECT_ALL, BUTTON_BOLD, BUTTON_ITALICS, diff --git a/core/subs_edit_ctrl.cpp b/core/subs_edit_ctrl.cpp index a7d27b109..bdd3f3878 100644 --- a/core/subs_edit_ctrl.cpp +++ b/core/subs_edit_ctrl.cpp @@ -39,6 +39,8 @@ #include "subs_edit_ctrl.h" #include "subs_edit_box.h" #include "options.h" +#include "subs_grid.h" +#include "utils.h" //////////////////////// @@ -99,12 +101,21 @@ SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxWindowID id, const wxStri StyleSetSize(5,size); StyleSetForeground(5,Options.AsColour(_T("Syntax Highlight Numbers"))); + // Line breaks style + StyleSetFont(6,font); + StyleSetSize(6,size); + StyleSetBold(6,true); + StyleSetForeground(6,Options.AsColour(_T("Syntax Highlight Line Break"))); + // Misspelling indicator IndicatorSetStyle(0,wxSCI_INDIC_SQUIGGLE); IndicatorSetForeground(0,wxColour(255,0,0)); // Set spellchecker spellchecker = SpellChecker::GetSpellChecker(); + + // Delimiters + delim = _T(" .,;:!?żĄ(){}[]\"/\\"); } @@ -135,12 +146,15 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { int curPos = 0; wxChar curChar = 0; wxChar prevChar = 0; + wxChar nextChar = 0; // Loop through for (int i=start;i 1) { @@ -171,11 +185,23 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { } // Outside - else if (depth == 0 && curStyle != 0) { - SetUnicodeStyling(curPos,ran,curStyle); - curPos += ran; - ran = 0; - curStyle = 0; + else if (depth == 0) { + // Is \n, \N or \h? + if (curChar == _T('\\') && (nextChar == 'n' || nextChar == 'N' || nextChar == 'h')) { + SetUnicodeStyling(curPos,ran,curStyle); + curPos += ran + 1; + ran = 1; + curStyle = 6; + i++; + } + + // Normal text + else if (curStyle != 0) { + SetUnicodeStyling(curPos,ran,curStyle); + curPos += ran; + ran = 0; + curStyle = 0; + } } // Inside @@ -239,9 +265,6 @@ void SubsTextEditCtrl::StyleSpellCheck(int start, int len) { // See if it has a spellchecker if (!spellchecker) return; - // Delimiters - wxString delim = _T(" .,;:!?żĄ(){}[]\"/\\"); - // Variables wxChar cur; wxString text = GetText(); @@ -287,7 +310,7 @@ void SubsTextEditCtrl::StyleSpellCheck(int start, int len) { if (depth != 0) continue; // Check if it is \n or \N - if (cur == '\\' && i < end-1 && (text[i+1] == 'N' || text[i+1] == 'n')) { + if (cur == '\\' && i < end-1 && (text[i+1] == 'N' || text[i+1] == 'n' || text[i+1] == 'h')) { isDelim = true; i++; } @@ -365,6 +388,16 @@ void SubsTextEditCtrl::SetTextTo(const wxString _text) { // Control event table BEGIN_EVENT_TABLE(SubsTextEditCtrl,wxScintilla) EVT_MOUSE_EVENTS(SubsTextEditCtrl::OnMouseEvent) + + EVT_MENU(EDIT_MENU_SPLIT_PRESERVE,SubsTextEditCtrl::OnSplitLinePreserve) + EVT_MENU(EDIT_MENU_SPLIT_ESTIMATE,SubsTextEditCtrl::OnSplitLineEstimate) + EVT_MENU(EDIT_MENU_CUT,SubsTextEditCtrl::OnCut) + EVT_MENU(EDIT_MENU_COPY,SubsTextEditCtrl::OnCopy) + EVT_MENU(EDIT_MENU_PASTE,SubsTextEditCtrl::OnPaste) + EVT_MENU(EDIT_MENU_UNDO,SubsTextEditCtrl::OnUndo) + EVT_MENU(EDIT_MENU_SELECT_ALL,SubsTextEditCtrl::OnSelectAll) + EVT_MENU(EDIT_MENU_ADD_TO_DICT,SubsTextEditCtrl::OnAddToDictionary) + EVT_MENU_RANGE(EDIT_MENU_SUGGESTIONS,EDIT_MENU_SUGGESTIONS+16,SubsTextEditCtrl::OnUseSuggestion) END_EVENT_TABLE() @@ -374,22 +407,211 @@ void SubsTextEditCtrl::OnMouseEvent(wxMouseEvent &event) { // Right click if (event.ButtonUp(wxMOUSE_BTN_RIGHT)) { if (control->linen >= 0) { - // Popup - wxMenu menu; - menu.Append(EDIT_MENU_UNDO,_("&Undo"))->Enable(CanUndo()); - menu.AppendSeparator(); - menu.Append(EDIT_MENU_CUT,_("Cu&t"))->Enable(GetSelectionStart()-GetSelectionEnd() != 0); - menu.Append(EDIT_MENU_COPY,_("&Copy"))->Enable(GetSelectionStart()-GetSelectionEnd() != 0); - menu.Append(EDIT_MENU_PASTE,_("&Paste"))->Enable(CanPaste()); - menu.AppendSeparator(); - menu.Append(EDIT_MENU_SELECT_ALL,_("Select &All")); - menu.AppendSeparator(); - menu.Append(EDIT_MENU_SPLIT_PRESERVE,_("Split at cursor (preserve times)")); - menu.Append(EDIT_MENU_SPLIT_ESTIMATE,_("Split at cursor (estimate times)")); - PopupMenu(&menu); + int pos = PositionFromPoint(event.GetPosition()); + ShowPopupMenu(pos); return; } } event.Skip(); } + + +/////////////////// +// Show popup menu +void SubsTextEditCtrl::ShowPopupMenu(int activePos) { + // Menu + wxMenu menu; + + // Position + if (activePos == -1) activePos = GetCurrentPos(); + + // Standard actions + menu.Append(EDIT_MENU_UNDO,_("&Undo"))->Enable(CanUndo()); + menu.AppendSeparator(); + menu.Append(EDIT_MENU_CUT,_("Cu&t"))->Enable(GetSelectionStart()-GetSelectionEnd() != 0); + menu.Append(EDIT_MENU_COPY,_("&Copy"))->Enable(GetSelectionStart()-GetSelectionEnd() != 0); + menu.Append(EDIT_MENU_PASTE,_("&Paste"))->Enable(CanPaste()); + menu.AppendSeparator(); + menu.Append(EDIT_MENU_SELECT_ALL,_("Select &All")); + + // Split + menu.AppendSeparator(); + menu.Append(EDIT_MENU_SPLIT_PRESERVE,_("Split at cursor (preserve times)")); + menu.Append(EDIT_MENU_SPLIT_ESTIMATE,_("Split at cursor (estimate times)")); + + // Spell check + int style = GetStyleAt(activePos); + if (style & 32 && spellchecker) { + // Get word + currentWord = GetWordAtPosition(activePos); + currentWordPos = activePos; + sugs.Clear(); + + // Word is really a typo + if (!spellchecker->CheckWord(currentWord)) { + // Append "add word" + menu.AppendSeparator(); + menu.Append(EDIT_MENU_ADD_TO_DICT,wxString::Format(_("Add \"%s\" to dictionary"),currentWord.c_str())); + + // Get suggestions + sugs = spellchecker->GetSuggestions(currentWord); + + // Build menu + int nSugs = sugs.Count(); + if (nSugs > 0) { + wxMenu *suggestions = new wxMenu(); + for (int i=0;iAppend(EDIT_MENU_SUGGESTIONS+i,sugs[i]); + menu.AppendSubMenu(suggestions,_("Corrections")); + } + + // No suggestions + else menu.Append(EDIT_MENU_SUGGESTION,_("No correction suggestions"))->Enable(false); + } + } + + // Pop the menu + PopupMenu(&menu); +} + + +////////////////////////////////////// +// Get boundaries of word at position +void SubsTextEditCtrl::GetBoundsOfWordAtPosition(int pos,int &_start,int &_end) { + // Variables + wxString text = GetText(); + int len = text.Length(); + int lastDelimBefore = -1; + int firstDelimAfter = len; + wxChar cur,next; + int depth=0; + + // Scan for delimiters + for (int i=0;igrid->SplitLine(control->linen,from,0); +} + + +/////////////////////////////// +// Split line estimating times +void SubsTextEditCtrl::OnSplitLineEstimate (wxCommandEvent &event) { + int from,to; + GetSelection(&from, &to); + control->grid->SplitLine(control->linen,from,1); +} + + +/////// +// Cut +void SubsTextEditCtrl::OnCut(wxCommandEvent &event) { + Cut(); +} + + +//////// +// Copy +void SubsTextEditCtrl::OnCopy(wxCommandEvent &event) { + Copy(); +} + + +///////// +// Paste +void SubsTextEditCtrl::OnPaste(wxCommandEvent &event) { + Paste(); +} + + +//////// +// Undo +void SubsTextEditCtrl::OnUndo(wxCommandEvent &event) { + Undo(); +} + + +////////////// +// Select All +void SubsTextEditCtrl::OnSelectAll(wxCommandEvent &event) { + SelectAll(); +} + + +////////////////////////// +// Add word to dictionary +void SubsTextEditCtrl::OnAddToDictionary(wxCommandEvent &event) { + if (spellchecker) spellchecker->AddWord(currentWord); + SetFocus(); +} + + +////////////////// +// Use suggestion +void SubsTextEditCtrl::OnUseSuggestion(wxCommandEvent &event) { + // Get suggestion + wxString suggestion = sugs[event.GetId()-EDIT_MENU_SUGGESTIONS]; + + // Get boundaries of text being replaced + int start,end; + GetBoundsOfWordAtPosition(currentWordPos,start,end); + + // Replace + wxString text = GetText(); + SetText(text.Left(MAX(0,start)) + suggestion + text.Mid(end+1)); + + // Set selection + SetSelection(start,start+suggestion.Length()); + SetFocus(); +} diff --git a/core/subs_edit_ctrl.h b/core/subs_edit_ctrl.h index 4fd067ee1..583fe3fc9 100644 --- a/core/subs_edit_ctrl.h +++ b/core/subs_edit_ctrl.h @@ -54,9 +54,27 @@ class SubsEditBox; class SubsTextEditCtrl : public wxScintilla { private: SpellChecker *spellchecker; + wxString delim; + wxString currentWord; + wxArrayString sugs; + int currentWordPos; + void OnMouseEvent(wxMouseEvent &event); + wxString GetWordAtPosition(int pos); + void GetBoundsOfWordAtPosition(int pos,int &start,int &end); void SetUnicodeStyling(int start,int length,int style); + void ShowPopupMenu(int activePos=-1); + + void OnSplitLinePreserve(wxCommandEvent &event); + void OnSplitLineEstimate(wxCommandEvent &event); + void OnCut(wxCommandEvent &event); + void OnCopy(wxCommandEvent &event); + void OnPaste(wxCommandEvent &event); + void OnUndo(wxCommandEvent &event); + void OnSelectAll(wxCommandEvent &event); + void OnAddToDictionary(wxCommandEvent &event); + void OnUseSuggestion(wxCommandEvent &event); public: SubsEditBox *control; @@ -70,3 +88,19 @@ public: DECLARE_EVENT_TABLE() }; + + +/////// +// IDs +enum { + EDIT_MENU_SPLIT_PRESERVE = 1400, + EDIT_MENU_SPLIT_ESTIMATE, + EDIT_MENU_CUT, + EDIT_MENU_COPY, + EDIT_MENU_PASTE, + EDIT_MENU_UNDO, + EDIT_MENU_SELECT_ALL, + EDIT_MENU_ADD_TO_DICT, + EDIT_MENU_SUGGESTION, + EDIT_MENU_SUGGESTIONS +};