mirror of https://github.com/odrling/Aegisub
Spell checker dialog is complete.
Originally committed to SVN as r1076.
This commit is contained in:
parent
79341020fd
commit
bd03fbc3ce
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -57,7 +57,6 @@ private:
|
|||
SpellChecker *spellchecker;
|
||||
Thesaurus *thesaurus;
|
||||
|
||||
wxString delim;
|
||||
wxString currentWord;
|
||||
wxArrayString sugs;
|
||||
wxArrayString thesSugs;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
//////////
|
||||
|
|
Loading…
Reference in New Issue