Add word and accept suggestion are now working

Originally committed to SVN as r607.
This commit is contained in:
Rodrigo Braz Monteiro 2006-12-25 05:43:00 +00:00
parent 4122fa1198
commit 523b79ad20
8 changed files with 308 additions and 98 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;i<n;i++) {
wxString current(results[i],wxConvUTF8);
suggestions.Add(current);
delete results[i];
}
// Delete
delete results;
}
// Return them
return suggestions;
}

View File

@ -56,6 +56,7 @@ public:
HunspellSpellChecker();
~HunspellSpellChecker();
void AddWord(wxString word);
bool CheckWord(wxString word);
wxArrayString GetSuggestions(wxString word);

View File

@ -315,14 +315,6 @@ BEGIN_EVENT_TABLE(SubsEditBox, wxPanel)
EVT_TEXT_ENTER(EFFECT_BOX, SubsEditBox::OnEffectChange)
EVT_CHECKBOX(COMMENT_CHECKBOX, SubsEditBox::OnCommentChange)
EVT_MENU(EDIT_MENU_SPLIT_PRESERVE,SubsEditBox::OnSplitLinePreserve)
EVT_MENU(EDIT_MENU_SPLIT_ESTIMATE,SubsEditBox::OnSplitLineEstimate)
EVT_MENU(EDIT_MENU_CUT,SubsEditBox::OnCut)
EVT_MENU(EDIT_MENU_COPY,SubsEditBox::OnCopy)
EVT_MENU(EDIT_MENU_PASTE,SubsEditBox::OnPaste)
EVT_MENU(EDIT_MENU_UNDO,SubsEditBox::OnUndo)
EVT_MENU(EDIT_MENU_SELECT_ALL,SubsEditBox::OnSelectAll)
EVT_BUTTON(BUTTON_COLOR1,SubsEditBox::OnButtonColor1)
EVT_BUTTON(BUTTON_COLOR2,SubsEditBox::OnButtonColor2)
EVT_BUTTON(BUTTON_COLOR3,SubsEditBox::OnButtonColor3)
@ -789,59 +781,6 @@ void SubsEditBox::CommitText() {
}
///////////////////////////////
// Split line preserving times
void SubsEditBox::OnSplitLinePreserve (wxCommandEvent &event) {
int from,to;
TextEdit->GetSelection(&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) {

View File

@ -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,

View File

@ -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<end;i++) {
// Current/previous characters
prevChar = curChar;
curChar = text[i];
if (i<end-1) nextChar = text[i+1];
else nextChar = 0;
// Erroneous
if (depth < 0 || depth > 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;i<nSugs;i++) suggestions->Append(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;i<len;i++) {
// Current char
cur = text[i];
if (i<len-1) next = text[i+1];
else next = 0;
// Depth
if (cur == '{') depth++;
if (cur == '}') depth--;
if (depth != 0) continue;
// Line breaks
if (cur == '\\' && (next == 'N' || next == 'n' || next == 'h')) {
// Before
if (i < pos) {
i++;
lastDelimBefore = i;
continue;
}
}
// Check for delimiters
if (delim.Find(cur) != wxNOT_FOUND) {
// Before
if (i < pos) lastDelimBefore = i;
// After
else {
firstDelimAfter = i;
break;
}
}
}
// Set start and end
_start = lastDelimBefore+1;
_end = firstDelimAfter-1;
}
//////////////////////////////////
// Get word at specified position
wxString SubsTextEditCtrl::GetWordAtPosition(int pos) {
int start,end;
GetBoundsOfWordAtPosition(pos,start,end);
return GetText().Mid(start,end-start+1);
}
///////////////////////////////
// Split line preserving times
void SubsTextEditCtrl::OnSplitLinePreserve (wxCommandEvent &event) {
int from,to;
GetSelection(&from, &to);
control->grid->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();
}

View File

@ -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
};