views:

145

answers:

2

I have a TextBox to search all occurences of the entered text in RichTextBox Control. The result will be populated in a listbox for traversal pupose after the search gets over.

I have written following function to achieve thedesired result.. but its taking good amount of time to complete.. I need some suggestion to fix this issue

In short I need to implement FindAll feature..

public void FindSearchResults(string searchWord)
{
    CheckState matchCase = default(CheckState);
    CheckState matchWholeWords = default(CheckState);
    RichTextBox tvc = this._rt;
    List<string> retVal = new List<string>();
    RichTextBoxFinds FindOptions = default(RichTextBoxFinds);

    currentSearchWord = searchWord;
    FindOptions = RichTextBoxFinds.None;
    // Location to begin the search. 
    FindOptions = RichTextBoxFinds.None;

    int searchResult = -2;
    int start = 0;
    string expandedValue = "";
    if ((matchWholeWords == CheckState.Checked) & (matchCase == CheckState.Checked))
    {
        FindOptions = RichTextBoxFinds.MatchCase | RichTextBoxFinds.WholeWord;
    }
    else if ((matchWholeWords == CheckState.Checked))
    {
        FindOptions = RichTextBoxFinds.WholeWord;
    }
    else if ((matchCase == CheckState.Checked))
    {
        FindOptions = RichTextBoxFinds.MatchCase;
    }
    else
    {
        FindOptions = RichTextBoxFinds.None;
    }
    while (searchResult != -1 & start < tvc.Text.Length)
    {
        searchResult = tvc.Find(searchWord, start, FindOptions);
        if ((searchResult != -1))
        {
            expandedValue = Expand(searchWord, searchResult);
            while (searchResultList.ContainsKey(expandedValue))
            {
                // just to keep uniqueness 
                expandedValue = expandedValue + " ";
            }

            retVal.Add(expandedValue);
            searchResultList[expandedValue] = searchResult;
            start = searchResult + searchWord.Length;
        }
    }

}

private string Expand(string searchWord, int searchResult)
{
    string retVal = null;
    int startPos = 0;
    int endPos = 0;
    int spaceCount = 0;
    RichTextBox tvc = this._rt;

    startPos = searchResult;
    spaceCount = 0;
    while (spaceCount < 2 & startPos > 0)
    {
        startPos = startPos - 1;
        char[] ch=tvc.Text.Substring(startPos,1).ToCharArray();
        if (ch[0] == (Char)32)
        {
            spaceCount = spaceCount + 1;
        }
    }

    spaceCount = 0;
    endPos = searchResult + 1;

    while (spaceCount < 4 & endPos < tvc.Text.Length)
    {
        int asciiVal = 0;
        asciiVal = Strings.Asc(tvc.Text.Substring(endPos,1));
        if (asciiVal == 10 | asciiVal == 13 | asciiVal == 32)
        {
            spaceCount = spaceCount + 1;
        }
        endPos = endPos + 1;
    }

    retVal = tvc.Text.Substring(startPos, endPos - startPos);
    retVal = retVal.Replace(Environment.NewLine, string.Empty);
    return retVal;
}
A: 

IMHO your code is not very clear currently. To start with, I would:

  • Do a clear split between the bits that determine search parameters
  • Do the actual search (this method shouldn't reference any UI components)
  • Display the results

It is not obvious (for me at least) what are your methods doing. What is the Expand method doing? Why is it using the edit box?

Grzenio
A: 

This code is not the cleanest and could definitely use refactoring, but I think you should probably look at executing the Find method in chunks when searching for text. Additionally when you're looking for stop chars like ' ' you should search in chunks. My queries seem to run pretty fast against the Find method.

private void FindButton_Click(object sender, EventArgs e)
    {
        findOptions = default(RichTextBoxFinds);
        resultsListBox.Items.Clear();

        if (MatchCaseCheckBox.Checked)
        {
            findOptions = findOptions | RichTextBoxFinds.MatchCase;
        }

        if (MatchEntireWordCheckBox.Checked)
        {
            findOptions = findOptions | RichTextBoxFinds.WholeWord;
        }

        int[] foundLocations = FindSearchResults(TextToSearchTextBox.Text.Trim());
        string[] words = null;
        if (foundLocations.Length > 0)
        {
            words = GetWords(foundLocations);

        }
        foreach (string word in words)
        {
            resultsListBox.Items.Add(word);
        }
    }

    private string[] GetWords(int[] foundLocations)
    {
        string textChunk = string.Empty;
        int chunkSize = 64;
        int textLength = MyRichTextBox.TextLength;
        int startIndex = 0;
        int endIndex = 0;
        List<string> words = new List<string>();
        int lastSpaceIndex = -1;
        int firstSpaceIndex = -1;
        foreach (int location in foundLocations)
        {
            textChunk = string.Empty;
            startIndex = location;
            endIndex = location;
            firstSpaceIndex = -1;
            lastSpaceIndex = -1;

            //get the start index.
            while (startIndex >= 0)
            {
                if (startIndex - chunkSize >= 0)
                {
                    startIndex -= chunkSize;
                }
                else
                {
                    startIndex -= Math.Abs(startIndex);
                }

                textChunk += MyRichTextBox.Text.Substring(startIndex, location - startIndex);
                firstSpaceIndex = textChunk.LastIndexOf(' ');
                if (firstSpaceIndex > -1)
                {
                    firstSpaceIndex = location - (textChunk.Length - firstSpaceIndex);
                    break;
                }
            }
            textChunk = string.Empty;
            startIndex = location;
            if (firstSpaceIndex == -1)
            {
                firstSpaceIndex = 0;
            }

            while (textChunk.Length <= textLength)
            {
                if (chunkSize + location < textLength)
                {
                    endIndex = chunkSize;
                }
                else
                {
                    endIndex = (textLength - startIndex);
                }

                textChunk += MyRichTextBox.Text.Substring(firstSpaceIndex + 1,
                    endIndex);
                lastSpaceIndex = textChunk.IndexOf(' ');
                if (lastSpaceIndex > -1)
                {
                    words.Add(textChunk.Substring(0, lastSpaceIndex));
                    break;
                }
            }
        }
        return words.ToArray();
    }

    private int[] FindSearchResults(string textToSearchFor)
    {

        int textLength = MyRichTextBox.TextLength;
        int chunkSize = 128;
        int startIndex = 0;
        int endIndex = 0;
        int foundIndex = -1;
        List<int> foundLocations = new List<int>();

        while (startIndex < textLength)
        {
            if ((chunkSize + startIndex) < textLength)
            {
                endIndex += chunkSize;
            }
            else
            {
                endIndex += textLength - endIndex;
            }

            foundIndex = MyRichTextBox.Find(textToSearchFor, startIndex, endIndex, findOptions);
            if (foundIndex > -1)
            {
                foundLocations.Add(foundIndex);
            }
            startIndex += chunkSize;
        }

        return foundLocations.ToArray();
    }
Wil P