bool SpellCheckerPlugin::DoGetWordStarts(const wxString& word, wxArrayInt& wordStarts, int numWords)
{
    if (numWords <= 0) // finish split
    {
        wordStarts.Add(0); // first word
        wxString currWord;
        for (int i = wordStarts.GetCount() - 1; i > 0; --i) // reverse iteration (so numbers are checked lowest to highest)
        {
            currWord = word(wordStarts[i], wordStarts[i - 1] - wordStarts[i]);
            if (currWord.Length() > 3) // capitalize medium/long words so proper nouns work
                currWord = currWord(0, 1).Upper() + currWord.Mid(1);
            if (!m_pSpellChecker->IsWordInDictionary(currWord))
            {
                wordStarts.RemoveAt(wordStarts.GetCount() - 1);
                return false; // no, fall back a level
            }
        }
        currWord = word.Mid(wordStarts[0]);
        if (currWord.Length() > 3) // capitalize
            currWord = currWord(0, 1).Upper() + currWord.Mid(1);
        if (!m_pSpellChecker->IsWordInDictionary(currWord)) // last word (wordStarts[] is reverse sorted)
        {
            wordStarts.RemoveAt(wordStarts.GetCount() - 1);
            return false; // no, fall back a level
        }
        return true; // all parts are correctly spelled
    }

    // iterate through possibilities of the current word start
    for (int i = (wordStarts.IsEmpty() ? word.Length() : wordStarts[wordStarts.GetCount() - 1]) - 2;
         i >= numWords * 2; --i)
    {
        wordStarts.Add(i);
        if (DoGetWordStarts(word, wordStarts, numWords - 1))
        {
            return true; // yes, fall through and return
        }
        wordStarts.RemoveAt(wordStarts.GetCount() - 1);
    }
    return false; // no, fall back an iteration
}