/* * Copyright 2005-2007 Gerald Schmidt. * * This file is part of Xml Copy Editor. * * Xml Copy Editor is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * Xml Copy Editor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Xml Copy Editor; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "aspell.h" #include "styledialog.h" #include "nocasecompare.h" #define ngettext wxGetTranslation #ifdef __WXMSW__ #include "aspellpaths.h" #endif BEGIN_EVENT_TABLE ( StyleDialog, wxDialog ) EVT_BUTTON ( ID_STYLE_REPORT, StyleDialog::OnReport ) EVT_BUTTON ( ID_STYLE_IGNORE_ALL, StyleDialog::OnStyleIgnoreAll ) EVT_BUTTON ( ID_STYLE_CHANGE_ALL, StyleDialog::OnStyleChangeAll ) EVT_BUTTON ( ID_STYLE_EDIT, StyleDialog::OnStyleEdit ) EVT_BUTTON ( ID_STYLE_WEB_REPORT, StyleDialog::OnStyleWebReport ) EVT_BUTTON ( ID_STYLE_WEB_SUMMARY, StyleDialog::OnStyleWebSummary ) EVT_BUTTON ( wxID_CANCEL, StyleDialog::OnCancel ) EVT_MENU ( ID_MENU_CHANGE_ONCE, StyleDialog::OnMenuChangeOnce ) EVT_MENU ( ID_MENU_CHANGE_ALL, StyleDialog::OnMenuChangeAll ) EVT_MENU ( ID_MENU_IGNORE_ONCE, StyleDialog::OnMenuIgnoreOnce ) EVT_MENU ( ID_MENU_IGNORE_ALL, StyleDialog::OnMenuIgnoreAll ) EVT_MENU ( ID_MENU_NEW_SUGGESTION, StyleDialog::OnMenuNewSuggestion ) EVT_MENU ( ID_MENU_APPLY_SUGGESTION_ALL, StyleDialog::OnMenuApplySuggestionAll ) EVT_LIST_COL_CLICK ( ID_STYLE_TABLE, StyleDialog::OnColumnClick ) EVT_LIST_ITEM_ACTIVATED ( ID_STYLE_TABLE, StyleDialog::OnItemActivated ) EVT_LIST_ITEM_RIGHT_CLICK ( ID_STYLE_TABLE, StyleDialog::OnItemRightClick ) EVT_UPDATE_UI_RANGE ( ID_STYLE_EDIT, ID_STYLE_CHANGE_ALL, StyleDialog::OnUpdateTableRange ) END_EVENT_TABLE() StyleDialog::StyleDialog ( wxWindow *parent, wxIcon icon, const std::string& bufferParameterUtf8, const wxString& fileNameParameter, const wxString& ruleSetDirectoryParameter, const wxString& filterDirectoryParameter, const wxString& browserParameter, const wxString& ruleSetPresetParameter, const wxString& filterPresetParameter, int typeParameter, bool readOnlyParameter, wxPoint position, wxSize size ) : wxDialog ( parent, wxID_ANY, wxString ( ( typeParameter == ID_TYPE_STYLE) ? _ ( "Style" ) : _ ( "Spelling" ) ), position, size, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX ), bufferUtf8 ( bufferParameterUtf8 ), fileName ( fileNameParameter ), ruleSetDirectory ( ruleSetDirectoryParameter ), filterDirectory ( filterDirectoryParameter ), browser ( browserParameter ), ruleSetPreset ( ruleSetPresetParameter ), filterPreset ( filterPresetParameter ), type(typeParameter), readOnly ( readOnlyParameter ) { SetIcon ( icon ); // top box ruleSetCombo = new wxComboBox ( this, ID_STYLE_COMBO_RULESET, _T ( "" ), wxDefaultPosition, wxSize ( 200, -1 ) ); int width, height; ruleSetCombo->GetSize ( &width, &height ); wxSize buttonSize ( 100, height ); filterCombo = new wxComboBox ( this, ID_STYLE_COMBO_FILTER, _T ( "" ), wxDefaultPosition, wxSize ( 200, -1 ) ); //if (type != ID_TYPE_STYLE) // from v. 1.1.0.7: never show filterCombo->Show ( false ); wxButton *createReportButton = new wxButton ( this, ID_STYLE_REPORT, _ ( "&Check" ), wxDefaultPosition, buttonSize, 0 ); wxBoxSizer *comboSizer = new wxBoxSizer ( wxHORIZONTAL ); comboSizer->Add ( ruleSetCombo, 0, wxRIGHT, 10 ); comboSizer->Add ( filterCombo, 0, wxRIGHT, 10 ); comboSizer->Add ( createReportButton, 0, wxRIGHT, 10 ); // middle box wxListCtrl *myTable = new wxListCtrl ( this, ID_STYLE_TABLE, wxPoint ( 0, 0 ), wxSize ( -1, -1 ), wxLC_REPORT ); int widthUnit = 35; myTable->InsertColumn ( 0, _ ( "No." ), wxLIST_FORMAT_LEFT, widthUnit * 1 ); myTable->InsertColumn ( 1, _ ( "Context" ), wxLIST_FORMAT_RIGHT, widthUnit * 3 ); myTable->InsertColumn ( 2, _ ( "Error" ), wxLIST_FORMAT_CENTER, widthUnit * 3 ); myTable->InsertColumn ( 3, _ ( "Context" ), wxLIST_FORMAT_LEFT, widthUnit * 3 ); myTable->InsertColumn ( 4, _ ( "Suggestion" ), wxLIST_FORMAT_LEFT, widthUnit * 3 ); myTable->InsertColumn ( 5, _ ( "Rule" ), wxLIST_FORMAT_LEFT, widthUnit * 3 ); myTable->InsertColumn ( 6, _ ( "Action" ), wxLIST_FORMAT_LEFT, widthUnit * 3 ); table = myTable; // lower box wxButton *editItemsButton = new wxButton ( this, ID_STYLE_EDIT, _ ( "&Apply changes" ), wxDefaultPosition, wxSize ( -1, buttonSize.GetHeight() ), 0 ); wxButton *webReportButton = new wxButton ( this, ID_STYLE_WEB_REPORT, _ ( "&Printable report" ), wxDefaultPosition, wxSize ( -1, buttonSize.GetHeight() ), 0 ); wxButton *webSummaryButton = new wxButton ( this, ID_STYLE_WEB_SUMMARY, _ ( "Pr&intable summary" ), wxDefaultPosition, wxSize ( -1, buttonSize.GetHeight() ), 0 ); wxButton *selectAllButton = new wxButton ( this, ID_STYLE_CHANGE_ALL, _ ( "C&hange all" ), wxDefaultPosition, wxSize ( -1, buttonSize.GetHeight() ), 0 ); wxButton *deselectAllButton = new wxButton ( this, ID_STYLE_IGNORE_ALL, _ ( "I&gnore all" ), wxDefaultPosition, wxSize ( -1, buttonSize.GetHeight() ), 0 ); wxButton *cancelButton = new wxButton ( this, wxID_CANCEL, _ ( "Ca&ncel" ), wxDefaultPosition, wxSize ( -1, buttonSize.GetHeight() ), 0 ); wxBoxSizer *reportButtonSizer = new wxBoxSizer ( wxHORIZONTAL ); reportButtonSizer->Add ( editItemsButton, 0, wxRIGHT, 10 ); reportButtonSizer->Add ( webReportButton, 0, wxLEFT | wxRIGHT, 10 ); reportButtonSizer->Add ( webSummaryButton, 0, wxRIGHT, 10 ); reportButtonSizer->Add ( selectAllButton, 0, wxLEFT | wxRIGHT, 10 ); reportButtonSizer->Add ( deselectAllButton, 0, wxRIGHT, 10 ); reportButtonSizer->Add ( cancelButton, 0, wxLEFT, 10 ); // status bar status = new wxStatusBar ( this, wxID_ANY ); // overall sizer wxBoxSizer *reportTopSizer = new wxBoxSizer ( wxVERTICAL ); reportTopSizer->Add ( comboSizer, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 ); reportTopSizer->Add ( table, 1, wxEXPAND | wxALL, 5 ); reportTopSizer->Add ( reportButtonSizer, 0, wxALL, 5 ); reportTopSizer->Add ( status, 0 ); this->SetSizer ( reportTopSizer ); createReportButton->SetFocus(); if ( readOnly ) filterCombo->Enable ( false ); // keyboard shortcuts wxAcceleratorEntry entries[7]; entries[0].Set ( wxACCEL_ALT, ( int ) 'C', ID_STYLE_REPORT ); entries[1].Set ( wxACCEL_ALT, ( int ) 'A', ID_STYLE_EDIT ); entries[2].Set ( wxACCEL_ALT, ( int ) 'W', ID_STYLE_WEB_REPORT ); entries[3].Set ( wxACCEL_ALT, ( int ) 'B', ID_STYLE_WEB_SUMMARY ); entries[4].Set ( wxACCEL_ALT, ( int ) 'H', ID_STYLE_CHANGE_ALL ); entries[5].Set ( wxACCEL_ALT, ( int ) 'I', ID_STYLE_IGNORE_ALL ); entries[6].Set ( wxACCEL_ALT, ( int ) 'N', wxID_CANCEL ); wxAcceleratorTable accel ( 7, entries ); this->SetAcceleratorTable ( accel ); // update combo lists // special case spellcheck if (type == ID_TYPE_SPELL) { AspellConfig *config; AspellDictInfoList *dlist; AspellDictInfoEnumeration *dels; const AspellDictInfo *entry; config = new_aspell_config(); #ifdef __WXMSW__ aspell_config_replace ( config, "data-dir", ASPELL_DATA_PATH ); aspell_config_replace ( config, "dict-dir", ASPELL_DICT_PATH ); #endif dlist = get_aspell_dict_info_list( config ); delete_aspell_config ( config ); dels = aspell_dict_info_list_elements ( dlist ); bool anyFound = false; while ( ( entry = aspell_dict_info_enumeration_next ( dels ) ) != 0 ) { anyFound = true; std::string stdEntry = entry->name; wxString entry = wxString ( stdEntry.c_str(), wxConvUTF8, stdEntry.size() ); ruleSetCombo->Append ( entry ); } if ( anyFound ) { if ( ruleSetPreset.empty() ) ruleSetPreset = _ ( "en_US" ); ruleSetCombo->SetValue ( ruleSetPreset ); } else { ruleSetCombo->Append ( _ ( "(No dictionaries found)" ) ); ruleSetCombo->Select ( 0 ); createReportButton->Enable ( false ); } return; } // all other branches if ( wxFileName::DirExists ( ruleSetDirectory ) ) { wxString ruleMask, ruleFile; ruleMask = ruleSetDirectory + wxFileName::GetPathSeparator() + _T ( "*.xml" ); ruleFile = wxFindFirstFile ( ruleMask, wxFILE ); if ( !ruleFile.empty() ) { ruleFile.Replace ( _T ( ".xml" ), _T ( "" ) ); ruleSetCombo->Append ( wxFileNameFromPath ( ruleFile ) ); for ( ;; ) { ruleFile = wxFindNextFile(); if ( ruleFile.empty() ) break; ruleFile.Replace ( _T ( ".xml" ), _T ( "" ) ); ruleSetCombo->Append ( wxFileNameFromPath ( ruleFile ) ); } } if ( ruleSetPreset.empty() ) ruleSetPreset = _ ( "Default" ); ruleSetCombo->SetValue ( ruleSetPreset ); } else { ruleSetCombo->Append ( _ ( "(No rule sets found)" ) ); ruleSetCombo->Select ( 0 ); } if ( wxFileName::DirExists ( filterDirectory ) ) { filterCombo->Append ( _ ( "(No filter)" ) ); wxString filterMask, filterFile; filterMask = filterDirectory + wxFileName::GetPathSeparator() + _T ( "*.xml" ); filterFile = wxFindFirstFile ( filterMask, wxFILE ); if ( !filterFile.empty() ) { filterFile.Replace ( _T ( ".xml" ), _T ( "" ) ); filterCombo->Append ( wxFileNameFromPath ( filterFile ) ); for ( ;; ) { filterFile = wxFindNextFile(); if ( filterFile.empty() ) break; filterFile.Replace ( _T ( ".xml" ), _T ( "" ) ); filterCombo->Append ( wxFileNameFromPath ( filterFile ) ); } } filterCombo->SetValue ( filterPreset ); } else { filterCombo->Append ( _ ( "(No filters found)" ) ); filterCombo->Select ( 0 ); } } StyleDialog::~StyleDialog() { std::set::iterator it; for ( it = tempFiles.begin(); it != tempFiles.end(); it++ ) wxRemoveFile ( *it ); } void StyleDialog::OnColumnClick ( wxListEvent& event ) { std::auto_ptr data ( new SortData ); data->column = event.GetColumn(); data->table = table; table->SortItems ( MyCompareFunction, ( long ) data.get() ); long itemCount = table->GetItemCount(); for ( int i = 0; i < itemCount; ++i ) table->SetItemData ( i, i ); } void StyleDialog::OnItemActivated ( wxListEvent& event ) { int index = event.GetIndex(); bool ignore = ( getTextByColumn ( table, index, 6 ) == _ ( "Ignore" ) ); setIgnore ( index, ( ignore ) ? false : true ); } void StyleDialog::OnItemRightClick ( wxListEvent& event ) { int index = indexForContextMenu = event.GetIndex(); wxString match, suggestion; match = getTextByColumn ( table, index, 2 ); suggestion = getTextByColumn ( table, index, 4 ); wxMenu contextMenu; contextMenu.Append ( ID_MENU_IGNORE_ONCE, _ ( "Ignore once" ) ); contextMenu.Append ( ID_MENU_IGNORE_ALL, _ ( "Ignore all" ) ); contextMenu.AppendSeparator(); contextMenu.Append ( ID_MENU_CHANGE_ONCE, _ ( "Change once" ) ); contextMenu.Append ( ID_MENU_CHANGE_ALL, _ ( "Change all" ) ); contextMenu.AppendSeparator(); contextMenu.Append ( ID_MENU_NEW_SUGGESTION, _ ( "New suggestion..." ) ); wxString menuString; menuString.Printf ( _T ( "Change '%s' to '%s' throughout" ), match.c_str(), suggestion.c_str() ); contextMenu.Append ( ID_MENU_APPLY_SUGGESTION_ALL, menuString ); bool ignore = ( getTextByColumn ( table, index, 6 ) == _ ( "Ignore" ) ); contextMenu.Enable ( ( ignore ) ? ID_MENU_IGNORE_ONCE : ID_MENU_CHANGE_ONCE, false ); PopupMenu ( &contextMenu, wxPoint ( -1, -1 ) ); } void StyleDialog::OnCancel ( wxCommandEvent& event ) { updateSizeInformation(); event.Skip(); } void StyleDialog::OnReport ( wxCommandEvent& event ) { table->DeleteAllItems(); matchVector.clear(); status->SetStatusText ( _ ( "Checking document..." ) ); // update presets ruleSetPreset = ruleSetCombo->GetValue(); filterPreset = filterCombo->GetValue(); // reconstitute short filenames wxString ruleSet, filter; ruleSet = ruleSetPreset + _T ( ".xml" ); filter = filterPreset + _T ( ".xml" ); std::string ruleSetDirectoryUtf8, ruleSetUtf8, filterDirectoryUtf8, filterUtf8, pathSeparatorUtf8; ruleSetDirectoryUtf8 = ruleSetDirectory.mb_str ( wxConvUTF8 ); ruleSetUtf8 = ruleSet.mb_str ( wxConvUTF8 ); filterDirectoryUtf8 = filterDirectory.mb_str ( wxConvUTF8 ); filterUtf8 = filter.mb_str ( wxConvUTF8 ); wxString separator = wxFileName::GetPathSeparator(); pathSeparatorUtf8 = separator.mb_str ( wxConvUTF8 ); std::auto_ptr hs ( new HouseStyle ( (type == ID_TYPE_SPELL) ? HS_TYPE_SPELL : HS_TYPE_STYLE, bufferUtf8, ruleSetDirectoryUtf8, ruleSetUtf8, filterDirectoryUtf8, filterUtf8, pathSeparatorUtf8, 5 ) ); status->SetStatusText ( _ ( "Checking document..." ) ); if ( !hs->createReport() ) { std::string lastError = hs->getLastError(); wxString error = wxString ( lastError.c_str(), wxConvUTF8, lastError.size() ); status->SetStatusText ( _ ( "Cannot check document: " ) + error ); return; } matchVector = hs->getMatchVector(); vector::iterator it; std::string prelogUtf8, matchUtf8, postlogUtf8, replaceUtf8, reportUtf8; wxString matchNo, prelog, match, postlog, replace, report; int i = 0; for ( it = matchVector.begin(); it != matchVector.end(); it++ ) { matchNo.Printf ( _T ( "%i" ), i + 1 ); // display numbers from 1 prelogUtf8 = flatWhiteSpace ( ( *it ).prelog ); matchUtf8 = flatWhiteSpace ( ( *it ).match ); postlogUtf8 = flatWhiteSpace ( ( *it ).postlog ); replaceUtf8 = flatWhiteSpace ( ( *it ).replace ); reportUtf8 = flatWhiteSpace ( ( *it ).report ); prelog = wxString ( prelogUtf8.c_str(), wxConvUTF8, ( *it ).prelog.size() ); match = wxString ( matchUtf8.c_str(), wxConvUTF8, ( *it ).match.size() ); postlog = wxString ( postlogUtf8.c_str(), wxConvUTF8, ( *it ).postlog.size() ); replace = wxString ( replaceUtf8.c_str(), wxConvUTF8, ( *it ).replace.size() ); report = wxString ( reportUtf8.c_str(), wxConvUTF8, ( *it ).report.size() ); table->InsertItem ( i, matchNo, 0 ); table->SetItem ( i, 1, prelog ); table->SetItem ( i, 2, match ); table->SetItem ( i, 3, postlog ); table->SetItem ( i, 4, replace ); table->SetItem ( i, 5, report ); setIgnore ( i, ( *it ).tentative ); table->SetItemData ( i, i ); ++i; } wxString message; message.Printf ( ngettext ( L"%i error", L"%i errors", i ), i ); status->SetStatusText ( message ); if ( i ) table->SetFocus(); } void StyleDialog::OnStyleEdit ( wxCommandEvent& event ) { updateSizeInformation(); std::vector v; getSelectedMatches ( v ); if ( v.empty() ) { status->SetStatusText ( _ ( "No items selected" ) ); return; } sort ( v.begin(), v.end(), elementAndOffsetCompareFunction ); /* HouseStyleWriter hsw ( v ); if ( !hsw.parse ( bufferUtf8 ) ) { std::string error = hsw.getLastError(); wxString wideError = wxString ( error.c_str(), wxConvUTF8, error.size() ); status->SetStatusText ( wideError ); return; } bufferUtf8 = hsw.getOutput(); */ //unsigned elementCount = 1; // from v. 1.1.0.7: one raw text element only int vectorsize, os_adjust, exclusion; vectorsize = v.size(); os_adjust = exclusion = 0; string cmp1, cmp2, buffer; buffer = bufferUtf8; for ( int i = 0; i < vectorsize; ++i ) { /* unsigned vectorElementCount = v[i].elementCount; if ( vectorElementCount < elementCount ) continue; else if ( vectorElementCount > elementCount ) break; else if ( vectorElementCount == elementCount ) { */ int offset = ( int ) v[i].offset + os_adjust; if ( offset < exclusion ) continue; try { cmp1 = v[i].match; cmp2 = buffer.substr ( offset, v[i].match.size() ); } catch ( std::exception& e ) { continue; } if ( cmp1.compare ( cmp2 ) ) continue; buffer.replace ( offset, v[i].match.size(), v[i].replace.c_str() ); os_adjust += v[i].replace.size() - v[i].match.size(); exclusion = offset + v[i].replace.size(); //} } bufferUtf8 = buffer; wxCommandEvent e; EndModal ( wxID_OK ); } std::string StyleDialog::getEditedString() { return bufferUtf8; } void StyleDialog::OnStyleIgnoreAll ( wxCommandEvent& event ) { styleSetIgnoreAll ( true ); } void StyleDialog::OnStyleChangeAll ( wxCommandEvent& event ) { styleSetIgnoreAll ( false ); } void StyleDialog::OnStyleWebReport ( wxCommandEvent& event ) { std::vector v; getAllMatches ( v ); sort ( v.begin(), v.end(), reportCompareFunction ); // temporary file should be in default temporary folder wxString tempNameWide = wxFileName::CreateTempFileName ( _T ( "" ) ); if ( tempNameWide.empty() ) return; tempNameWide.Replace ( _T ( ".tmp" ), _T ( "_report.html" ), true ); tempFiles.insert ( tempNameWide ); std::string tempNameUtf8 = ( const char * ) tempNameWide.mb_str ( wxConvUTF8 ); std::ofstream ofs ( tempNameUtf8.c_str() ); if ( !ofs ) return; ofs << XHTML_START; ofs << "

"; ofs << fileName.mb_str ( wxConvUTF8 ); ofs << "

"; ofs << ""; ofs << ""; ofs << ""; ofs << ""; ofs << ""; std::vector::iterator it; int matchCount = 0; for ( it = v.begin(); it != v.end(); it++ ) { ofs << ""; ofs << ""; } ofs << "
No.ContextMatchContextSuggestionReport
"; ofs << ++matchCount; ofs << ""; ofs << it->prelog; ofs << ""; ofs << it->match; ofs << ""; ofs << it->postlog; ofs << ""; ofs << it->replace; ofs << ""; ofs << it->report; ofs << "
"; ofs << XHTML_END; ofs.close(); // display file in browser if ( !wxFileName::FileExists ( tempNameWide ) ) return; wxString cmd = browser + _T ( " \"" ) + tempNameWide + _T ( "\"" ); wxExecute ( cmd, wxEXEC_SYNC ); } void StyleDialog::OnStyleWebSummary ( wxCommandEvent& event ) { std::vector v; getAllMatches ( v ); std::map matchMap; std::vector::iterator vectorIterator; for ( vectorIterator = v.begin(); vectorIterator != v.end(); vectorIterator++ ) { if ( ( matchMap.find ( vectorIterator->match ) ) != matchMap.end() ) ++ ( matchMap[vectorIterator->match] ); else matchMap[vectorIterator->match] = 1; } // temporary file should be in default temporary folder wxString tempNameWide = wxFileName::CreateTempFileName ( _T ( "" ) ); if ( tempNameWide.empty() ) return; tempNameWide.Replace ( _T ( ".tmp" ), _T ( "_summary.html" ), true ); tempFiles.insert ( tempNameWide ); std::string tempNameUtf8 = ( const char * ) tempNameWide.mb_str ( wxConvUTF8 ); std::ofstream ofs ( tempNameUtf8.c_str() ); if ( !ofs ) return; ofs << XHTML_START; ofs << "

"; ofs << fileName.mb_str ( wxConvUTF8 ); ofs << "

"; WrapExpat we; ofs << ""; std::map::iterator mapIterator; int matchTotal = 0; for ( mapIterator = matchMap.begin(); mapIterator != matchMap.end(); mapIterator++ ) { ofs << ""; } ofs << "
TermFrequency
"; ofs << we.xmliseTextNode ( mapIterator->first ); ofs << ""; // handle number of matches matchTotal += mapIterator->second; ofs << mapIterator->second; ofs << "
Total"; ofs << matchTotal; ofs << "
"; ofs << XHTML_END; ofs.close(); // display file in browser if ( !wxFileName::FileExists ( tempNameWide ) ) return; wxString cmd = browser + _T ( " \"" ) + tempNameWide + _T ( "\"" ); wxExecute ( cmd, wxEXEC_SYNC ); } void StyleDialog::styleSetIgnoreAll ( bool ignore ) { int count = table->GetItemCount(); for ( int i = 0; i < count; ++i ) setIgnore ( i, ignore ); } bool StyleDialog::isIgnore ( int item ) { wxString field = getTextByColumn ( table, item, 6 ); return ( field == _ ( "Ignore" ) ) ? true : false; } void StyleDialog::setIgnore ( int item, bool ignore ) { table->SetItem ( item, 6, ( ignore ) ? _ ( "Ignore" ) : _ ( "Change" ) ); table->SetItemTextColour ( item, ( ignore ) ? *wxBLUE : *wxBLACK ); } void StyleDialog::getAllMatches ( vector &v ) { v.clear(); int count = table->GetItemCount(); wxString matchNoString; long matchNo; for ( int i = 0; i < count; ++i ) { matchNoString = table->GetItemText ( i ); if ( !matchNoString.ToLong ( &matchNo ) || matchNo < 1 ) continue; v.push_back ( matchVector.at ( matchNo - 1 ) ); // vector index starts at 0 } } void StyleDialog::getSelectedMatches ( vector &v ) { v.clear(); int count = table->GetItemCount(); wxString selectionString, matchNoString; long matchNo; for ( int i = 0; i < count; ++i ) { selectionString = getTextByColumn ( table, i, 6 ); if ( selectionString != _ ( "Change" ) ) continue; matchNoString = table->GetItemText ( i ); if ( !matchNoString.ToLong ( &matchNo ) || matchNo < 1 ) continue; v.push_back ( matchVector.at ( matchNo - 1 ) ); // vector index starts at 0 } } int wxCALLBACK StyleDialog::MyCompareFunction ( long item1, long item2, long sortData ) { SortData *data = ( SortData * ) sortData; int column; wxListCtrl *table; column = data->column; table = data->table; wxString string1 = getTextByColumn ( table, item1, column ); wxString string2 = getTextByColumn ( table, item2, column ); // special case: numerical content if ( string1.IsNumber() && string2.IsNumber() ) { long value1, value2; string1.ToLong ( &value1 ); string2.ToLong ( &value2 ); if ( value1 < value2 ) return -1; else if ( value1 > value2 ) return 1; else return 0; } if ( string1.CmpNoCase ( string2 ) < 0 ) return -1; else if ( string1.CmpNoCase ( string2 ) > 0 ) return 1; else return 0; } bool StyleDialog::elementAndOffsetCompareFunction ( ContextMatch m1, ContextMatch m2 ) { if ( m1.elementCount == m2.elementCount ) return ( m1.offset < m2.offset ); return ( m1.elementCount < m2.elementCount ); } bool StyleDialog::reportCompareFunction ( ContextMatch m1, ContextMatch m2 ) { return ( m1.report < m2.report ); } wxString StyleDialog::getTextByColumn ( wxListCtrl *table, long index, int col ) { wxListItem Item; Item.SetId ( index ); Item.SetColumn ( col ); Item.SetMask ( wxLIST_MASK_TEXT ); table->GetItem ( Item ); return Item.GetText(); } void StyleDialog::OnUpdateTableRange ( wxUpdateUIEvent& event ) { if ( event.GetId() == ID_STYLE_EDIT && readOnly ) { event.Enable ( false ); return; } event.Enable ( table->GetItemCount() ); } void StyleDialog::OnMenuChangeOnce ( wxCommandEvent& event ) { setIgnore ( indexForContextMenu, false ); } void StyleDialog::OnMenuChangeAll ( wxCommandEvent& event ) { wxString match, suggestion; match = getTextByColumn ( table, indexForContextMenu, 2 ); suggestion = getTextByColumn ( table, indexForContextMenu, 4 ); long itemCount = table->GetItemCount(); for ( int i = 0; i < itemCount; ++i ) { if ( getTextByColumn ( table, i, 2 ) == match ) setIgnore ( i, false ); } } void StyleDialog::OnMenuIgnoreOnce ( wxCommandEvent& event ) { setIgnore ( indexForContextMenu, true ); } void StyleDialog::OnMenuIgnoreAll ( wxCommandEvent& event ) { wxString match, suggestion; match = getTextByColumn ( table, indexForContextMenu, 2 ); suggestion = getTextByColumn ( table, indexForContextMenu, 4 ); long itemCount = table->GetItemCount(); for ( int i = 0; i < itemCount; ++i ) { if ( getTextByColumn ( table, i, 2 ) == match ) { table->SetItem ( i, 4, suggestion ); setIgnore ( i, true ); } } } void StyleDialog::OnMenuNewSuggestion ( wxCommandEvent& event ) { wxString suggestion = getTextByColumn ( table, indexForContextMenu, 4 ); wxTextEntryDialog *dlg = new wxTextEntryDialog ( this, _ ( "Enter new suggestion:" ), _ ( "New Suggestion" ), suggestion ); if ( !dlg ) return; int ret = dlg->ShowModal(); if ( ret == wxID_CANCEL ) return; // identify item in match vector wxString noString = getTextByColumn ( table, indexForContextMenu, 0 ); long no; if ( !noString.ToLong ( &no ) || no < 1 || no > ( long ) matchVector.size() ) return; --no; // reverse display offset wxString wideReplace = dlg->GetValue(); std::string replace = ( const char * ) wideReplace.mb_str ( wxConvUTF8 ); matchVector[no].replace = replace; table->SetItem ( indexForContextMenu, 4, dlg->GetValue() ); setIgnore ( indexForContextMenu, false ); } void StyleDialog::OnMenuApplySuggestionAll ( wxCommandEvent& event ) { wxString match, suggestion; match = getTextByColumn ( table, indexForContextMenu, 2 ); suggestion = getTextByColumn ( table, indexForContextMenu, 4 ); long itemCount = table->GetItemCount(); for ( int i = 0; i < itemCount; ++i ) { if ( getTextByColumn ( table, i, 2 ) != match ) continue; // identify item in match vector wxString noString = getTextByColumn ( table, i, 0 ); long no; if ( !noString.ToLong ( &no ) || no < 1 || no > ( long ) matchVector.size() ) continue; --no; // reverse display offset std::string replace = ( const char * ) suggestion.mb_str ( wxConvUTF8 ); matchVector[no].replace = replace; table->SetItem ( i, 4, suggestion ); setIgnore ( i, false ); } } std::string StyleDialog::flatWhiteSpace ( std::string& s ) { std::string::iterator it; std::string output; output.reserve ( s.size() ); for ( it = s.begin(); it != s.end(); it++ ) { if ( *it == '\t' || *it == '\r' || *it == '\n' ) output += ' '; else output += *it; } return output; } void StyleDialog::updateSizeInformation() { framePosition = GetPosition(); frameSize = GetSize(); } wxPoint StyleDialog::getPosition() { return framePosition; } wxSize StyleDialog::getSize() { return frameSize; }