Spell checker dialog is complete.

Originally committed to SVN as r1076.
This commit is contained in:
Rodrigo Braz Monteiro 2007-04-14 15:26:46 +00:00
parent 79341020fd
commit bd03fbc3ce
8 changed files with 283 additions and 153 deletions

View File

@ -181,11 +181,12 @@ public:
bool Parse(wxString data,int version=1); // Parses raw ASS data into everything else
void ParseASSTags(); // Parses text to generate block information (doesn't update data)
void ParseSRTTags(); // Converts tags to ass format and calls ParseASSTags+UpdateData
void ClearBlocks(); // Clear all blocks, ALWAYS call this after you're done processing tags
void ProcessParameters(void (*callback)(wxString,int,AssOverrideParameter*,void *userData),void *userData=NULL); // Callback to process parameters
void ConvertTagsToSRT(); // Converts tags to SRT format
void StripTags(); // Strips all tags from the text
void StripTag(wxString tagName);// Strips a specific tag from the text
void ClearBlocks(); // Clear all blocks, ALWAYS call this after you're done processing tags
void ProcessParameters(void (*callback)(wxString,int,AssOverrideParameter*,void *userData),void *userData=NULL); // Callback to process parameters
wxString GetStrippedText(); // Gets text without tags
void UpdateData(); // Updates raw data from current values + text

View File

@ -39,6 +39,12 @@
// Headers
#include "dialog_spellchecker.h"
#include "spellchecker.h"
#include "subs_grid.h"
#include "frame_main.h"
#include "ass_file.h"
#include "ass_dialogue.h"
#include "utils.h"
#include "subs_edit_box.h"
///////
@ -58,7 +64,7 @@ DialogSpellChecker::DialogSpellChecker(wxFrame *parent)
: wxDialog(parent, -1, _T("Spell Checker"), wxDefaultPosition, wxDefaultSize)
{
// Top sizer
origWord = new wxTextCtrl(this,-1,_T("original"));
origWord = new wxTextCtrl(this,-1,_T("original"),wxDefaultPosition,wxDefaultSize,wxTE_READONLY);
replaceWord = new wxTextCtrl(this,-1,_T("replace with"));
wxFlexGridSizer *topSizer = new wxFlexGridSizer(2,2,5,5);
topSizer->Add(new wxStaticText(this,-1,_("Misspelled word:")),0,wxALIGN_CENTER_VERTICAL);
@ -103,14 +109,116 @@ DialogSpellChecker::DialogSpellChecker(wxFrame *parent)
}
// Go to first match
FindNext(0,0);
SubtitlesGrid *grid = ((FrameMain*)GetParent())->SubsBox;
wxArrayInt sel = grid->GetSelection();
firstLine = (sel.Count()>0) ? sel[0] : 0;
bool hasTypos = FindNext(firstLine,0);
// File is already OK
if (!hasTypos) {
wxMessageBox(_("Aegisub has found no spelling mistakes in this script."),_("Spell checking complete."));
Destroy();
return;
}
// Show
ShowModal();
}
//////////////
// Destructor
DialogSpellChecker::~DialogSpellChecker() {
if (spellchecker) delete spellchecker;
}
///////////////////
// Find next match
void DialogSpellChecker::FindNext(int startLine,int startPos) {
bool DialogSpellChecker::FindNext(int startLine,int startPos) {
// Set start
if (startLine != -1) lastLine = startLine;
if (startPos != -1) lastPos = 0;
// Get grid
SubtitlesGrid *grid = ((FrameMain*)GetParent())->SubsBox;
int rows = grid->GetRows();
// Loop through lines
for (int i=lastLine;i<rows+firstLine;i++) {
startFindNextOuterLoop:
// Get dialogue
int curLine = i % rows;
AssDialogue *diag = grid->GetDialogue(curLine);
// Find list of words in it
IntPairVector results;
GetWordBoundaries(diag->Text,results);
// Look for spelling mistakes
for (size_t j=0;j<results.size();j++) {
// Get word
int s = results[j].first;
if (s < lastPos) continue;
int e = results[j].second;
wxString word = diag->Text.Mid(s,e-s);
// Check if it's on auto ignore
if (autoIgnore.Index(word) != wxNOT_FOUND) continue;
// Mistake
if (!spellchecker->CheckWord(word)) {
// Set word
wordStart = s;
wordEnd = e;
lastLine = i;
lastPos = e;
// Auto replace?
if (autoReplace.find(word) != autoReplace.end()) {
// lol mad h4x
replaceWord->SetValue(autoReplace[word]);
Replace();
goto startFindNextOuterLoop;
}
// Proceed normally
SetWord(word);
return true;
}
}
// Go to next
lastPos = 0;
}
// None found
return false;
}
////////////
// Set word
void DialogSpellChecker::SetWord(wxString word) {
// Get list of suggestions
wxArrayString sugs = spellchecker->GetSuggestions(word);
// Set fields
origWord->SetValue(word);
replaceWord->SetValue((sugs.Count()>0)? sugs[0] : word);
// Set suggestions list
suggestList->Clear();
for (size_t i=0;i<sugs.Count();i++) suggestList->Append(sugs[i]);
// Show word on the main program interface
SubtitlesGrid *grid = ((FrameMain*)GetParent())->SubsBox;
int line = lastLine % grid->GetRows();
grid->SelectRow(line,false);
grid->MakeCellVisible(line,0);
grid->editBox->SetToLine(line);
grid->editBox->TextEdit->SetSelectionU(wordStart,wordEnd);
grid->EndBatch();
}
@ -136,28 +244,74 @@ void DialogSpellChecker::OnClose(wxCommandEvent &event) {
///////////
// Replace
void DialogSpellChecker::OnReplace(wxCommandEvent &event) {
Replace();
FindOrDie();
}
//////////////////////
// Replace all errors
void DialogSpellChecker::OnReplaceAll(wxCommandEvent &event) {
// Add word to autoreplace list
autoReplace[origWord->GetValue()] = replaceWord->GetValue();
// Replace
Replace();
FindOrDie();
}
/////////////////////
// Ignore this error
void DialogSpellChecker::OnIgnore(wxCommandEvent &event) {
// Next
FindOrDie();
}
/////////////////////
// Ignore all errors
void DialogSpellChecker::OnIgnoreAll(wxCommandEvent &event) {
// Add word to autoignore list
autoIgnore.Add(origWord->GetValue());
// Next
FindOrDie();
}
/////////////////////
// Add to dictionary
void DialogSpellChecker::OnAdd(wxCommandEvent &event) {
spellchecker->AddWord(origWord->GetValue());
FindOrDie();
}
///////////////////////////////////////////////
// Goes to next... if it can't find one, close
bool DialogSpellChecker::FindOrDie() {
if (!FindNext()) {
wxMessageBox(_("Aegisub has finished checking spelling of this script."),_("Spell checking complete."));
Destroy();
return false;
}
return true;
}
///////////
// Replace
void DialogSpellChecker::Replace() {
// Get dialog
SubtitlesGrid *grid = ((FrameMain*)GetParent())->SubsBox;
AssDialogue *diag = grid->GetDialogue(lastLine % grid->GetRows());
// Replace
diag->Text = diag->Text.Left(wordStart) + replaceWord->GetValue() + diag->Text.Mid(wordEnd);
lastPos = wordStart + replaceWord->GetValue().Length();
// Commit
grid->ass->FlagAsModified(_("Spell check replace"));
grid->CommitChanges();
}

View File

@ -38,6 +38,7 @@
///////////
// Headers
#include <wx/wxprec.h>
#include <map>
//////////////
@ -51,14 +52,22 @@ class DialogSpellChecker : public wxDialog {
private:
SpellChecker *spellchecker;
std::map<wxString,wxString> autoReplace;
wxArrayString autoIgnore;
int wordStart,wordEnd;
int lastLine;
int lastPos;
int firstLine;
wxTextCtrl *origWord;
wxTextCtrl *replaceWord;
wxListBox *suggestList;
void FindNext(int startLine=-1,int startPos=-1);
bool FindOrDie();
bool FindNext(int startLine=-1,int startPos=-1);
void SetWord(wxString word);
void Replace();
void OnClose(wxCommandEvent &event);
void OnReplace(wxCommandEvent &event);
@ -69,5 +78,6 @@ private:
public:
DialogSpellChecker(wxFrame *parent);
~DialogSpellChecker();
DECLARE_EVENT_TABLE()
};

View File

@ -888,7 +888,7 @@ void FrameMain::OnOpenTranslation(wxCommandEvent& WXUNUSED(event)) {
void FrameMain::OnOpenSpellCheck (wxCommandEvent &event) {
VideoContext::Get()->Stop();
DialogSpellChecker *spell = new DialogSpellChecker(this);
spell->Show();
//spell->ShowModal();
}

View File

@ -74,13 +74,6 @@ SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxWindowID id, const wxStri
// Set thesaurus
thesaurus = Thesaurus::GetThesaurus();
// Delimiters
delim = _T(" .,;:!?-(){}[]\"/\\");
wxChar temp = 0xBF;
delim += temp;
temp = 0xA1;
delim += temp;
// Prototypes for call tips
tipProtoN = -1;
proto.Add(_T("move(x1,y1,x2,y2)"));
@ -660,85 +653,46 @@ void SubsTextEditCtrl::StyleSpellCheck(int start, int len) {
// See if it has a spellchecker
if (!spellchecker) return;
// Variables
wxChar cur;
// Results
wxString text = GetText();
int curPos;
int lastpos = -1;
int end = start+len;
int depth = 0;
if (len < 0) end = text.Length();
wxArrayInt startPos;
wxArrayInt endPos;
bool isDelim;
// Scan
for (int i=start;i<end+1;i++) {
// Current character
curPos = i;
if (i < end) cur = text[i];
else cur = '.';
isDelim = false;
// Increase depth
if (cur == '{') {
depth++;
if (depth == 1) {
if (lastpos+1 != curPos) {
startPos.Add(lastpos+1);
endPos.Add(curPos);
}
continue;
}
}
// Decrease depth
if (cur == '}') {
depth--;
if (depth == 0) {
lastpos = i;
continue;
}
}
// Wrong depth
if (depth != 0) continue;
// Check if it is \n or \N
if (cur == '\\' && i < end-1 && (text[i+1] == 'N' || text[i+1] == 'n' || text[i+1] == 'h')) {
isDelim = true;
i++;
}
// Check for standard delimiters
if (delim.Find(cur) != wxNOT_FOUND) {
isDelim = true;
}
// Is delimiter?
if (isDelim) {
if (lastpos+1 != curPos) {
startPos.Add(lastpos+1);
endPos.Add(curPos);
}
lastpos = i;
}
}
IntPairVector results;
GetWordBoundaries(text,results,start,(len == -1) ? len : start+len);
// Style
int count = startPos.Count();
int count = results.size();
for (int i=0;i<count;i++) {
// Get current word
wxString curWord = text.Mid(startPos[i],endPos[i]-startPos[i]);
int s = results[i].first;
int e = results[i].second;
wxString curWord = text.Mid(s,e-s);
// Check if it's valid
if (!spellchecker->CheckWord(curWord)) {
// Get length before it
int utf8len = GetUnicodePosition(startPos[i]);
int utf8len = GetUnicodePosition(s);
// Set styling
StartStyling(utf8len,32);
SetUnicodeStyling(startPos[i],endPos[i]-startPos[i],32);
SetUnicodeStyling(s,e-s,32);
}
}
}
//////////////////////////////////////
// Get boundaries of word at position
void SubsTextEditCtrl::GetBoundsOfWordAtPosition(int pos,int &_start,int &_end) {
// Results
IntPairVector results;
GetWordBoundaries(GetText(),results);
// Get boundaries
int count = results.size();
for (int i=0;i<count;i++) {
if (results[i].first <= pos && results[i].second >= pos) {
_start = results[i].first;
_end = results[i].second-1;
return;
}
}
}
@ -988,77 +942,6 @@ void SubsTextEditCtrl::ShowPopupMenu(int activePos) {
}
//////////////////////////////////////
// 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 == '{') {
if (i >= pos) {
firstDelimAfter = i;
break;
}
depth++;
}
if (cur == '}') {
if (i < pos) {
lastDelimBefore = i;
}
depth--;
}
if (depth != 0) {
// Picked a location in invalid depth
if (pos == i) {
lastDelimBefore = -1;
firstDelimAfter = 0;
break;
}
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) {

View File

@ -57,7 +57,6 @@ private:
SpellChecker *spellchecker;
Thesaurus *thesaurus;
wxString delim;
wxString currentWord;
wxArrayString sugs;
wxArrayString thesSugs;

View File

@ -212,3 +212,74 @@ int SmallestPowerOf2(int x) {
x++;
return x;
}
///////////////////////
// Get word boundaries
void GetWordBoundaries(const wxString text,IntPairVector &results,int start,int end) {
// Variables
wxChar cur;
int curPos;
int lastpos = -1;
int depth = 0;
if (end < 0) end = text.Length();
bool isDelim;
// Delimiters
wxString delim = _T(" .,;:!?-(){}[]\"/\\");
wxChar temp = 0xBF;
delim += temp;
temp = 0xA1;
delim += temp;
// Scan
for (int i=start;i<end+1;i++) {
// Current character
curPos = i;
if (i < end) cur = text[i];
else cur = '.';
isDelim = false;
// Increase depth
if (cur == '{') {
depth++;
if (depth == 1) {
if (lastpos+1 != curPos) {
results.push_back(std::pair<int,int>(lastpos+1,curPos));
}
continue;
}
}
// Decrease depth
if (cur == '}') {
depth--;
if (depth == 0) {
lastpos = i;
continue;
}
}
// Wrong depth
if (depth != 0) continue;
// Check if it is \n or \N
if (cur == '\\' && i < end-1 && (text[i+1] == 'N' || text[i+1] == 'n' || text[i+1] == 'h')) {
isDelim = true;
i++;
}
// Check for standard delimiters
if (delim.Find(cur) != wxNOT_FOUND) {
isDelim = true;
}
// Is delimiter?
if (isDelim) {
if (lastpos+1 != curPos) {
results.push_back(std::pair<int,int>(lastpos+1,curPos));
}
lastpos = i;
}
}
}

View File

@ -37,6 +37,17 @@
#pragma once
///////////
// Headers
#include <vector>
#include <utility>
////////////
// Typedefs
typedef std::vector<std::pair<int,int> > IntPairVector;
///////////////////////
// Function prototypes
#ifndef __LINUX__
@ -55,6 +66,7 @@ wxString IntegerToString(int value);
wxString PrettySize(int bytes);
wxMenuItem *AppendBitmapMenuItem (wxMenu* parentMenu,int id,wxString text,wxString help,wxBitmap bmp,int pos=-1);
int SmallestPowerOf2(int x);
void GetWordBoundaries(const wxString text,IntPairVector &results,int start=0,int end=-1);
//////////