internal void Highlight() { if (!this.SafeToContinueHighlight()) { return; } Word.Range range = this.FindRange(); this.UndoHighlightToOriginal(); UnknownWords.Clear(); //it's logical to save the existing highlights //before highlighting but //this will increase run time by 2n //so actually do this ↓ while running loop to highlight //this.SaveExistingHighlight(range); //find numerical indexes of the highlight range LowerAndUpperBounds bounds = new LowerAndUpperBounds(Globals.ThisAddIn.Ribbon, this.GetIndexNames()); bounds.FindLowerUpperBounds(); //this loop also saves highlighted text this.SaveExistingAndHighlightRange(range, bounds); }
//note that this saves existing highlight and highlights //this is because looping through document twice will increase runtime by 2n //where n is around 15 seconds per page \(*o*)/ private void SaveExistingAndHighlightRange(Word.Range range, LowerAndUpperBounds bounds) { //range to search int wordCount = range.Words.Count; //***lower bound for arrays is 1 in Word object model*** // (array[0] does exist but is not used) // (array[1] is the first word in the array) int lowerBoundWordCount = 1; int upperBoundWordCount = wordCount + 1; Word.Words words = range.Words; //we have two saved colors (one for continuing range of same color) //so we can bulk highlight a sequence of words with the same color //for faster runtime (updating word one by one takes too long) Word.WdColorIndex tempColor = Word.WdColorIndex.wdNoHighlight; Word.WdColorIndex tempColor2 = Word.WdColorIndex.wdNoHighlight; Word.Range tempRange = null; Globals.ThisAddIn.Application.System.Cursor = Word.WdCursorType.wdCursorWait; for (int i = lowerBoundWordCount; i < upperBoundWordCount; i++) { Word.Range wordRange = words[i]; //save existing highlight first if (wordRange.HighlightColorIndex != Colors.none) { this.SaveExistingHighlight(wordRange); } //get word string word = wordRange.Text; string cleanWord = CleanWord(word); //move page as necessary (kinda like progress bar but more intuitive) //right now, every 20 words if (i % 20 == 0) { wordRange.Select(); } /* * Periods, commas, etc are considered words * so skip through them if so. * However, for hyphens it may be one word * for example merry-go-round * or it may not be like -this hyphen acts as a bullet point. * Make an exception for hyphens and consider it as one word if necessary */ if (isPunctuation(cleanWord)) { if (tempRange == null) { continue; } //reset highlight color to nothing this.AddColoring(tempRange, tempColor); tempRange = null; tempColor = Word.WdColorIndex.wdNoHighlight; wordRange.HighlightColorIndex = Word.WdColorIndex.wdNoHighlight; continue; } //now highlight /* * For highlighting, looping word by word is extremely slow * 900 words about 1 minute * But highlighting the entire page a single color takes a second.. * So to lessen run time, bulk highlight words with same color. * */ if (Dictionary.ContainsKey(cleanWord)) { int wordIndex = Dictionary[cleanWord]; tempColor2 = bounds.GetColorOfIndex(wordIndex); } else { tempColor2 = Colors.unknown; UnknownWords.Add(cleanWord); } if (tempRange == null) //first instance { tempColor = tempColor2; tempRange = wordRange; } else { if (tempColor == tempColor2) //we continue to the next word { int rangeSize = wordRange.Characters.Count; tempRange.MoveEnd(Word.WdUnits.wdCharacter, rangeSize); } else //we highlight the range before { this.AddColoring(tempRange, tempColor); tempRange = wordRange; tempColor = tempColor2; } } } //end for loop of words Globals.ThisAddIn.Application.System.Cursor = Word.WdCursorType.wdCursorNormal; //pointer back to normal //highlight last set of words if (tempRange != null) //in case last word is a punctuation mark { this.AddColoring(tempRange, tempColor); } //remove selected text Globals.ThisAddIn.Application.Selection.Move(); //save range so the next time we highlight, //we can remove highlight on this range prevRange = range; }