Progress update.
Sun, Nov 8, 2009.
The Multi-line Search and replace algorithm has been finished and tested successfully, in an unsaved file, with default EOL mode set to CRLF.
The EOL conversion of the search and replace expressions is done inside replacedlg.cpp. Inside EditorManager::Replace and EditorManager::ReplaceInFiles we check the search expression for LFs and CRs. If there's a match, the whole file is converted to the current EOL mode to avoid false positives/negatives. Then the search takes place normally.
Search & Replace in a single file works, for both normal and regex searches.
Extended Regular Expressions is enabled.
Before:
<html>
<body>
hola mundo!
</body>
</html>
Search Expression:
<html>
<body>
(.*)
</body>
</html>
Replace expression:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Hello world!</title>
</head>
<body>
\1
</body>
</html>
After:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Hello world!</title>
</head>
<body>
hola mundo!
</body>
</html>
There are still some quirks in the UI that need to be worked on.
Multi-line S&R in files has not been tested yet.
Will continue to report tomorrow.
Good night!
seems very very cool.
Absolutely correct.
Does it also work with mixed line-edings ?
It didn't work with mixed line-endings at first. I needed to convert the line endings of both the search/replace expressions AND of files. What I do is checking if the search/replace expressions contain a LF or CR. In that case, we convert the current file to the configured EOL mode so line endings aren't mixed anymore. We're going to search/replace, so it's not a problem if the file is modified. Of course, this is done INSIDE the undo action, so that if the match isn't found, the file is undo'ed. The undoing is already done with existing code inside EditorManager, i only had to move the begin-undo-action before the line conversion.
Here's the patch for EditorManager:
int EditorManager::Replace(cbStyledTextCtrl* control, cbFindReplaceData* data)
{
if (!control || !data)
return -1;
if (control->GetReadOnly())
{
cbMessageBox(_("This file is read-only.\nReplacing in a read-only file is not possible."),
_("Warning"), wxICON_EXCLAMATION);
return -1;
}
bool AdvRegex=false;
int replacecount=0;
int foundcount=0;
int flags = 0;
control->BeginUndoAction(); // The undo is set at this point in case we need to convert the EOLs.
if((data->findText.Find(_T("\n")) != wxNOT_FOUND) || (data->findText.Find(_T("\r")) != wxNOT_FOUND))
{
// If it's a multi-line S&R, We need to convert the EOLs, or the find may be inaccurate.
// This will slow down processing as the whole file needs to be preprocessed, but it's a small price
// compared to searching and replacing multiple lines by hand.
static const int default_eol = platform::windows ? wxSCI_EOL_CRLF : wxSCI_EOL_LF;
int eolMode = Manager::Get()->GetConfigManager(_T("editor"))->ReadInt(_T("/eol/eolmode"), default_eol);
control->SetEOLMode(eolMode);
control->ConvertEOLs(eolMode);
}
CalculateFindReplaceStartEnd(control, data);
// ... the rest of the code is kept as it was.
For find in files, it's a similar code.
This check is done only for the find string, since having a multiline replace string isn't a problem. It's the find string that gives us all the problems.
Algorithm aside, my real problem right now is getting the ctrl-tab key to work. I don't want the tabs to change between the single-line and multiple-line tabs, but between the Replace and Replace in files. How do I disable a wxNotebook control from accepting ctrl-tab keys?
Just in case, I'm going to change the wxNotebook for a wxChoicebook. I hope ctrl-tab isn't affected this way. (And I think it looks prettier and less bulky).