Getting word under caret - C++, wxWidgets - c++

I am writing a text editor using the wxWidgets framework. I need to get the word under caret from the text control. Here is what I came up with.
static bool IsWordBoundary(wxString& text)
{
return (text.Cmp(wxT(" ")) == 0 ||
text.Cmp(wxT('\n')) == 0 ||
text.Cmp(wxT('\t')) == 0 ||
text.Cmp(wxT('\r')) == 0);
}
static wxString GetWordUnderCaret(wxTextCtrl* control)
{
int insertion_point = control->GetInsertionPoint();
wxTextPos last_position = control->GetLastPosition();
int start_at, ends_at = 0;
// Finding starting position:
// from the current caret position, move back each character until
// we hit a word boundary.
int caret_pos = insertion_point;
start_at = caret_pos;
while (caret_pos)
{
wxString text = control->GetRange (caret_pos - 1, caret_pos);
if (IsWordBoundary (text)) {
break;
}
start_at = --caret_pos;
}
// Finding ending position:
// from the current caret position, move forward each character until
// we hit a word boundary.
caret_pos = ends_at = insertion_point;
while (caret_pos < last_position)
{
wxString text = control->GetRange (caret_pos, caret_pos + 1);
if (IsWordBoundary (text)) {
break;
}
ends_at = ++caret_pos;
}
return (control->GetRange (start_at, ends_at));
}
This code works as expected. But I am wondering is this the best way to approach the problem? Do you see any possible fixes on the above code?
Any help would be great!

Is punctuation part of a word? It is in your code -- is that what you want?

Here is how I would do it:
wxString word_boundary_marks = " \n\t\r";
wxString text_in_control = control->GetValue();
int ends_at = text_in_control.find_first_of( word_boundary_marks, insertion_point) - 1;
int start_at = text_in_control.Mid(0,insertion_point).find_last_of(word_boundary_marks) + 1;
I haven't tested this, so there likely are one or two "off-by-one" errors and you should add checks for "not found", end of string, and any other word markers. My code should give you the basis for what you need.

Related

Simple text file formatter crashes under Linux, but fine in Windows

I've made a simple .acf file to .json file formatter. But for some reason it runs correctly under Windows with GCC using msys2 - But after executing a string insert or replace - it segmentation faults every time.
What it does is convert the below file into a json compatible format. It appends commas after each entry, applies attribute set symbol and puts braces around it.
Save as test.acf:
"AppState"
{
"appid" "730"
"Universe" "1"
"name" "Counter-Strike: Global Offensive"
"StateFlags" "4"
"installdir" "Counter-Strike Global Offensive"
"LastUpdated" "1462547468"
"UpdateResult" "0"
"SizeOnDisk" "14990577143"
"buildid" "1110931"
"LastOwner" "76561198013962068"
"BytesToDownload" "8768"
"BytesDownloaded" "8768"
"AutoUpdateBehavior" "1"
"AllowOtherDownloadsWhileRunning" "0"
"UserConfig"
{
"Language" "english"
}
"MountedDepots"
{
"731" "205709710082221598"
"734" "5169984513691014102"
}
}
Minimal main code with defects triple slashed:
#include <iostream>
#include <fstream>
#include <string>
int main(int argc, char* argv[])
{
file.open("test.acf");
std::string data((std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>()));
int indexQuote = 0;
int index[4];
int insertCommaNext = -1;
string delims = "\"{}"; // It skips between braces and quotes only
std::size_t found = data.find_first_of(delims);
while(found != std::string::npos)
{
int inc = 1; // 0-4 depending on the quote - 0"key1" 2"value3" 4{
char c = data.at(found);
if (c != '"') {
if (c == '}')
insertCommaNext = found + 1; // Record index to insert comma after (following closing brace)
else if (c == '{') {
///data.insert(index[1] + 1, ":");
///inc++;
}
indexQuote = 0;
} else {
if (insertCommaNext != -1) {
///data.insert(insertCommaNext, ",");
///inc++;
insertCommaNext = -1;
}
index[indexQuote] = found;
if (indexQuote == 2) { // Join 'key: value' by placing the comma
///data.replace(index[1] + 1, 1, ":");
} else if (indexQuote == 4) { // Add comma after each key/value entry
indexQuote = 0;
///data.insert(index[3] + 1, ",");
///inc++;
}
indexQuote++;
}
found = data.find_first_of(delims, found + inc);
}
data = "{" + data + "}";
}
If you uncomment any of the triple slashed /// lines - containing an insert/replace, it will crash.
I'm certian the code quality is not great, there's probably better ways to achieve this. Cheers.
The problem is that indexQuote gets higher than 3, so index[indexQuote] = found; goes out of bounds. You have the case below that resets indexQuote to 0, you have to do that before you try to call index[indexQuote].
For reference, I debugged this by adding prints everywhere and printing all the variables until I found where it crashed.

How to save specific part of a TRichEdit text RTF (c++ codegear)

I'm creating a search features in an existing c++ CodeGear project.
When you double-click a word, the background of all occurrences of the word is paint in green like in notepad++.
Before color is applied, I'm saving the original TRichEDit text in a TMemoryStream to be able to get the original text back. I reset the color back to normal on click event in the TRichEdit.
I would like to know if there is a way to save each occurrence of the search word in a TMemoryStream or maybe by using a Message like EM_STREAMOUT?
Right now everything works fine, but when the TRichEdit text is too big, it takes forever to reload the big memo of all the text. I think it would be better to only remember the color of the word that changed rather then reload all the text.
I'm really a beginner in programming, any help is appreciate. Tell me if it's not clear enough.
Here is my code that is working and putting background color to occurrences of word:
`
void SearchInText::searchWordInText(TRichEdit* reTextToSearch, AnsiString strWordToFind)
{
lstOccurrences->Clear(); //reset lst
strTextToParse = AnsiReplaceText(strTextToParse, "\r\n", "\n");
int nPrevTagPos = 0;
int nTagPos = strTextToParse.AnsiPos(strWordToFind);
while (nTagPos != 0)
{
int nPosMin = nPrevTagPos + nTagPos - 1;
//List of all the occurrence in the TRichEdit with their position in the text
//It's not a list of int, but it POINT to adresses of INT so it's the same result =)
lstOccurrences->Add((TObject*) nPosMin);
//Change color of background when there is an occurrence
changeBgColor(reTextToSearch, strWordToFind, nPosMin +1, 155, 255, 155); //lime
bColorWasApplied = true;
nPrevTagPos = nPosMin + strWordToFind.Length();
strTextToParse = strTextToParse.SubString(nTagPos + strWordToFind.Length(), strTextToParse.Length());
nTagPos = strTextToParse.AnsiPos(strWordToFind);
}
}
`
Try something like this:
#include <vector>
struct WordOccurrence
{
CHARRANGE Range;
CHARFORMAT2 OriginalFormat;
};
std::vector<WordOccurrence> WordOccurrences;
void TMyForm::HighlightWords(const String &WordToFind)
{
// disable the RichEdit's notification messages
int OriginalEventMask = RichEdit1->Perform(EM_SETEVENTMASK, 0, 0);
// disable the RichEdit's painting
RichEdit1->Perform(WM_SETREDRAW, FALSE, 0);
// save the RichEdit's current selection
CHARRANGE OriginalSelection;
RichEdit1->Perform(EM_EXGETSEL, 0, (LPARAM)&OriginalSelection);
// assign values to use while searching
int WordLen = WordToFind.Length();
int TextLen = RichEdit1->GetTextLen();
TSearchTypes SearchTypes = TSearchTypes() << stWholeWord << stMatchCase;
// find the first occurrence of the word
int StartPos = RichEdit1->FindText(WordToFind, 0, TextLen, SearchTypes);
while (StartPos != -1)
{
WordOccurrence Occurrence;
Occurrence.Range.cpMin = StartPos;
Occurrence.Range.cpMax = StartPos + WordLen;
// select the word
RichEdit1->Perform(EM_EXSETSEL, 0, (LPARAM)&Occurrence.Range);
// get the word's current formatting
Occurrence.OriginalFormat.cbSize = sizeof(CHARFORMAT2);
RichEdit1->Perform(EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&Occurrence.OriginalFormat);
// save it for later
WordOccurrences.push_back(Occurrence);
// set the word's new formatting
CHARFORMAT2 NewFormat = Occurrence.OriginalFormat;
NewFormat.dwMask |= (CFM_COLOR | CFM_BACKCOLOR);
NewFormat.crTextColor = ...;
newFormat.crBackColor = ...;
RichEdit1->Perform(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&NewFormat);
// find the next occurrence of the word
StartPos = RichEdit1->FindText(WordToFind, Occurrence.Range.cpMax, TextLen - Occurence.Range.cpMax, SearchTypes);
}
// restore the RichEdit's original selection
RichEdit1->Perform(EM_EXSETSEL, 0, (LPARAM)&OriginalSelection);
// re-enable the RichEdit's painting
RichEdit1->Perform(WM_SETREDRAW, TRUE, 0);
RichEdit1->Invalidate();
// re-enable the RichEdit's notification messages
RichEdit1->Perform(EM_SETEVENTMASK, 0, OriginalEventMask);
}
void TMyForm::RestoreHighlightedWords()
{
// are there any occurrences to restore?
if (WordOccurances.empty())
return;
// disable the RichEdit's notification messages
int OriginalEventMask = RichEdit1->Perform(EM_SETEVENTMASK, 0, 0);
// disable the RichEdit's painting
RichEdit1->Perform(WM_SETREDRAW, FALSE, 0);
// save the RichEdit's current selection
CHARRANGE OriginalSelection;
RichEdit1->Perform(EM_EXGETSEL, 0, (LPARAM)&OriginalSelection);
// restore the formatting of each occurrence
for (std::vector<WordOccurrence>::iterator iter = WordOccurrences.begin();
iter != WordOccurrences.end();
++iter)
{
WordOccurrence &occurrence = *iter;
// select the word
RichEdit1->Perform(EM_EXSETSEL, 0, (LPARAM)&occurrence.Range);
// restore the word's original formatting
RichEdit1->Perform(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&occurrence.OriginalFormat);
}
// clear the list
WordOccurances.clear();
// restore the RichEdit's original selection
RichEdit1->Perform(EM_EXSETSEL, 0, (LPARAM)&OriginalSelection);
// re-enable the RichEdit's painting
RichEdit1->Perform(WM_SETREDRAW, TRUE, 0);
RichEdit1->Invalidate();
// re-enable the RichEdit's notification messages
RichEdit1->Perform(EM_SETEVENTMASK, 0, OriginalEventMask);
}
Ok, so I finally get it!
I add a struct in my .h
Inside it, I store:
-the position in the TRichEdit of the word found (nStart)
-the length of the word (nLength)
-the actual text and his RTF
struct sSelectedWord : public TObject
{
public:
__fastcall ~sSelectedWord(); //destructor
int nStart;
int nLength;
TMemoryStream* memoRTF;
};
Here is the code that save the RTF of my TRichEdit in my struct I just created in the .h.
void SearchInText::searchWordInText(TRichEdit* reTextToSearch, AnsiString strWordToFind)
{
lstOccurrences->Clear(); //reset lst
lstOccWithRTFMemo->Clear();
nCountOccurrence = 0;
strTextToParse = AnsiReplaceText(strTextToParse, "\r\n", "\n");
int nPrevTagPos = 0;
int nTagPos = strTextToParse.AnsiPos(strWordToFind);
while (nTagPos != 0)
{
int nPosMin = nPrevTagPos + nTagPos - 1;
//List of all the occurrence in the TRichEdit with their position in the text
//It's not a list of int, but it POINT to adresses of INT so it's the same result =)
lstOccurrences->Add((TObject*) nPosMin);
nCountOccurrence++;
//selected the word in the TRichEdit to save it with is RTF
reTextToSearch->SelStart = nPosMin;
reTextToSearch->SelLength = strWordToFind.Length();
TMemoryStream* memo = new TMemoryStream;
//important part!
rtfSaveStream(reTextToSearch,memo);
sSelectedWord* currentWord = new sSelectedWord;
currentWord->nStart = nPosMin;
currentWord->nLength = strWordToFind.Length();
currentWord->memoRTF = memo;
//Here we go, we add our new object in a list to be able to loop through it when we will want to reset the color
lstOccWithRTFMemo->Add(currentWord);
lstOccWithRTFMemo->Count;
//Change color of background when there is an occurrence
changeBgColor(reTextToSearch, strWordToFind, nPosMin +1, 155, 255, 155); //lime
bColorWasApplied = true;
nPrevTagPos = nPosMin + strWordToFind.Length();
strTextToParse = strTextToParse.SubString(nTagPos + strWordToFind.Length(), strTextToParse.Length());
nTagPos = strTextToParse.AnsiPos(strWordToFind);
}
}
The important part was done with the EM_STREAMOUT message.
void SearchInText::rtfSaveStream(TRichEdit* re, TMemoryStream* memo)
{
// Create an instance of an EDITSTREAM that will contain:
// - The detail of our callback (StreamInCallback)
// - The TMemoryStream that contains the text to paste
EDITSTREAM es = {0};
ZeroMemory(&es, sizeof(es));
es.dwCookie = (DWORD_PTR) memo;
es.dwError = 0;
es.pfnCallback = &StreamSaveInCallback ; //pointer to function callBack
//To save the selected word of the TRichEdit, use STREAMOUT
re->Perform(EM_STREAMOUT, SF_RTF | SFF_SELECTION, (LPARAM)&es);
}
DWORD CALLBACK SearchInText::StreamSaveInCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
TMemoryStream *memo = (TMemoryStream*)dwCookie;
memo->Write(pbBuff, cb);
*pcb = cb;
return 0;
}
In the pbuff, you can see the word that you selected in your TRichEdit with his RTF!
Hope it will help others with the same issue! Thanks for those who suggested code =)

syntax highlight richedit control not working poperly

I am trying to implement a syntax highlight editor with a richedit, it has works well with the current selected line, but I may be missing something. The CRichEdit is my own wrapper implementation of the richedit controller, the problem seems that the text is not selected properly even though I made sure the selected range generated with the code were what I get with the EM_EXGETSEL message.
The selection seems increasing 1 as the lines goes down, so I decided to ed_source.sendMessage(EM_LINEFROMCHAR, pos, 0) to the range which partially fix the problem except for some few lines where the coloring seems some time one or to position before and the real appropriate, so that is why I thing I may not be understanding something.
void parse(WIN::CRichEdit &ed_source, bool curseline)
{
int pos, offset = 0;
char delimiter[]={" \n\r(){};"}, *tok, *start;
CStringA s;
CString text;
CWnd api;
if(curseline){
ed_source.getLine(ed_source.getRow() - 1, text);
offset = ed_source.sendMessage(EM_LINEINDEX, -1, 0);
}else{
text = ed_source.getCaption();
}
s = text;
start = s.c_str();
if(!start) return;
tok = strtok(s.c_str(), delimiter);
CHARRANGE cr = ed_source.getSelecteRange();
ed_source.sendMessage(EM_HIDESELECTION, 1, 0) ;
CHARRANGE range;
while(tok)
{
int len = strlen(tok);
pos = (tok - start);
int x = ed_source.sendMessage(EM_LINEFROMCHAR, pos, 0);
range.cpMin = offset + pos - x;
range.cpMax = range.cpMin + len;
ed_source.selectRange(range);
if(isReserved(tok)){
ed_source.setTextStyle(true, false);
ed_source.setTextColor(keyboardColor);
}else
if(isType(tok)){
ed_source.setTextStyle(false, false);
ed_source.setTextColor(typeColor);
}else {
ed_source.setTextStyle(false, true);
ed_source.setTextColor(textColor);
}
tok = strtok(0, delimiter);
}
ed_source.sendMessage(EM_HIDESELECTION, 0, 0) ;
ed_source.selectRange(cr);
}
just to be more specific the moment I call the above function is immediately after loading the text on it. I assumed you may want to see the implementation of some of the above functions so here they are.
CHARRANGE CRichEdit::getSelecteRange()
{
CHARRANGE crg = {0} ;
sendMessage(EM_EXGETSEL, 0, (LPARAM)&crg);
return crg;
}
void CRichEdit::selectRange(const CHARRANGE &cr)
{
sendMessage( EM_EXSETSEL, 0, (LPARAM) &cr);
}
void CRichEdit::setTextColor(COLORREF col)
{
CHARFORMAT format;
memset(&format, 0, sizeof(CHARFORMAT));
format.cbSize = sizeof(CHARFORMAT);
format.dwMask = CFM_COLOR;
format.crTextColor = col;
sendMessage( EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &format);
}
Have a look at this article for some ideas:
Faster rich edit syntax highlighting
http://bcbjournal.org/articles/vol3/9910/Faster_rich_edit_syntax_highlighting.htm
It was written for the TRichEdit control in C++Builder, but the majority of the tips in it use straight Win32 API calls, and the few places that use VCL idioms can be easily adapted into Win32 equivilents.
Update: Try removing EM_LINEFROMCHAR from your loop. offset + pos is already an absolute character position within the RichEdit, there should be no need to adjust it on each loop iteration. If you really want to take line indexes into account then you should be looping through the lines one row at a time parsing each row individually, not parsing the entire content as a single string. Try something more like this instead:
void parse(WIN::CRichEdit &ed_source, bool curseline)
{
int startLine, endLine, offset;
const char* delimiters = " \n\r(){};";
char *tok, *start;
CStringA s;
CWnd api;
if (curseline)
{
startLine = ed_source.getRow() - 1;
endLine = startLine + 1;
}
else
{
startLine = 0;
endLine = ed_source.sendMessage(EM_GETLINECOUNT, 0, 0);
}
CHARRANGE cr = ed_source.getSelecteRange();
int eventMask = ed_source.SendMessage(EM_SETEVENTMASK, 0, 0);
ed_source.SendMessage(WM_SETREDRAW, FALSE, 0);
for (int line = startLine; line < endLine; ++line)
{
CString text;
ed_source.getLine(line, text);
s = text;
start = s.c_str();
if (!start) continue;
offset = ed_source.sendMessage(EM_LINEINDEX, line, 0);
tok = strtok(start, delimiters);
while (tok)
{
CHARRANGE range;
range.cpMin = offset + (int)(tok - start);
range.cpMax = range.cpMin + strlen(tok);
ed_source.selectRange(range);
if (isReserved(tok))
{
ed_source.setTextStyle(true, false);
ed_source.setTextColor(keyboardColor);
}
else if (isType(tok))
{
ed_source.setTextStyle(false, false);
ed_source.setTextColor(typeColor);
}
else
{
ed_source.setTextStyle(false, true);
ed_source.setTextColor(textColor);
}
tok = strtok(0, delimiters);
}
}
ed_source.SendMessage(WM_SETREDRAW, TRUE, 0);
ed_source.Invalidate(); // whatever your wrapper does to call ::InvalidateRect()
ed_source.SendMessage(EM_SETEVENTMASK, 0, eventMask);
ed_source.selectRange(cr);
}
With that said, instead of using getLine() and strtok() to parse text, you might consider using EM_FINDWORDBREAK to locate words and EM_EXSETSEL/EM_GETSELTEXT to retreive the characters of each word. That way, you are using less memory and letting the RichEdit do more of the searching for you. You can use EM_SETWORDBREAKPROC/EX if you want to customize the word delimiters searched for.

Output formatted text to Screen

I have a vector that stores pairs. Each pair contains a CString and a bool.
If the CString is meant to be underlined then bool is true, else it is false.
I want to output the text in the vector to the screen making sure that text is underlined in the correct places.
So far I have the following code:
void CEmergenceView::AppendText( CString msg ) {
int nBegin;
CRichEditCtrl &rec = GetRichEditCtrl();
nBegin = rec.GetTextLength();
rec.SetSel(nBegin, nBegin); // Select last character
rec.ReplaceSel(msg); // Append, move cursor to end of text
rec.SetSel(-1,0); // Remove Black selection bars
nBegin = rec.GetTextLength(); // Get New Length
rec.SetSel(nBegin,nBegin); // Cursor to End of new text
// Fix annoying "do you want to save your changes?" when program exits
GetDocument()->SetModifiedFlag(FALSE); // -Optional- (sometimes you want this)
}
int nEnd = 0;
// loop through start of text to end of text
for(int k = 0; k < groups.size(); k++) {
rEditCtrl.SetSel(nEnd, nEnd);
rEditCtrl.GetSelectionCharFormat(cf);
if(groups.at(k).second) {
if(!cf.dwEffects & !CFE_UNDERLINE) {
CRichEditView::OnCharUnderline();
}
}
else if(!groups.at(k).second) {
if(cf.dwEffects & CFE_UNDERLINE) {
CRichEditView::OnCharUnderline();
}
}
AppendText(groups.at(k).first);
nEnd = nEnd + (groups.at(k).first.GetLength());
}
However, this is not underlining at all....Can anyone tell me what I'm doing wrong?? Thanks!
I think you should implement the OnCharUnderline
Try to call yours own function instead of the default one:
You can get it from here:
void CMyRichEditView::OnCharUnderline ()
{
CHARFORMAT2 cf;
cf = GetCharFormatSelection();
if (!(cf.dwMask & CFM_UNDERLINE) || !(cf.dwEffects & CFE_UNDERLINE))
cf.dwEffects = CFE_UNDERLINE;
else
cf.dwEffects = 0;
cf.dwMask = CFM_UNDERLINE;
SetCharFormat(cf);
}

c++ cli comparing hexadecimal bytes from a file not working

I have this file called ab.exe it contains this in hexadecimal
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BBAAE8CAFDFFFF83C408000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054AAE8CAFDFFFF83C40800000000000000000000000000000000000000000000000000000000000000000000000000AAE8CAFDFFFF83C4088D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
I have this code in c++ that is suppose to detect if a string of hexadecimal is in a file or not and if it is add it to the list box.
array<Byte>^ target1 = { 0xAA,0xE8,0xCA,0xFD,0xFF,0xFF,0x83,0xC4,0x08,0x8D };
array<Byte>^ target2 = { 0x54,0xAA,0xE8,0xCA,0xFD,0xFF,0xFF,0x83,0xC4,0x08 };
array<Byte>^ target3 = { 0xBB,0xAA,0xE8,0xCA,0xFD,0xFF,0xFF,0x83,0xC4,0x08 };
int matched1 = 0;
int matched2 = 0;
int matched3 = 0;
FileStream^ fs2 = gcnew FileStream(line, FileMode::Open, FileAccess::Read, FileShare::ReadWrite);
int value;
do
{
value = fs2->ReadByte();
if (value == target1[matched1]) {
matched1++;
}
else
matched1 = 0;
if (value == target2[matched2]) {
matched2++;
}
else
matched2 = 0;
if (value == target3[matched3]) {
matched3++;
}
else
matched3 = 0;
if(matched1 == target1->Length)
{
listBox1->Items->Add(line + "1");
}
if(matched2 == target2->Length)
{
listBox1->Items->Add(line + "2");
}
if(matched3 == target3->Length)
{
listBox1->Items->Add(line + "3");
}
} while (value != -1);
fs2->Close();
the problem is that it only adds line + 3 to the list box and not line + 1 or line + 2 to the list box
I do not know why that is because all 3 of the strings are in the file so they all should be added to the list box. for some reason only the last one is being added because I tried just having 2 and the second one got added.can someone show me why they are not all being added to the list box.
thanks
Update1
after playing around with it some more it is not the last target that gets added each time, It is the first string that appears in the file that gets added. I stepped through the program using message boxes and what is happening is lets say 54AAE8CAFDFFFF83C408 is the first string to appear in the file then line + 2 will be added, but then for some reason the matched integer for all 3 stop counting they just = 0 the rest of the file. can someone explain to me why that is and how to fix it.
Update2
here is the answer to the problem. all I needed to do was just add a matched = 0; after each add to list box command.
listBox1->Items->Add(line + "1");
matched1 = 0;
listBox1->Items->Add(line + "2");
matched2 = 0;
listBox1->Items->Add(line + "3");
matched3 = 0;
It seems to me that after the first matching of one pattern (here target3) you read beyond last byte of target3 (because of matched3++), this may cause undesired behavior.
Update1:
if(matched1 == target1->Length)
{
matched1 = 0; // pattern matched so reset counter
...
}