/// ------------------------------------------------------------------------------------ /// <summary> /// Given a TS string and an index, find the closest start of a word before that /// position (or after that position if at a word boundary already or in the last word /// of the string. If in a run marked using one of the special styles, always returns /// the position at the end of that run. Runs having these special styles are also /// always regarded as word boundaries. /// </summary> /// <param name="tss">the structured string of the paragraph or translation</param> /// <param name="ich">the given index</param> /// <param name="specialStyles">The special styles.</param> /// <returns>adjusted character index</returns> /// ------------------------------------------------------------------------------------ public static int FindWordBoundary(this ITsString tss, int ich, params string[] specialStyles) { if (ich < 0 || ich > tss.Length) { throw new ArgumentOutOfRangeException("ich"); } if (ich == 0 || ich == tss.Length) { return(ich); } string text = tss.Text; string startingStyle = tss.StyleAt(ich); string prevStyle = ich > 0 ? tss.StyleAt(ich - 1) : startingStyle; if (!specialStyles.Contains(startingStyle) || prevStyle == null) { startingStyle = null; } else if (startingStyle != null) { startingStyle = prevStyle; } // Advance to the next word boundary if appropriate) while (ich < text.Length) { // if the current character is space... if (Icu.IsSeparator(text[ich])) { ich++; } else if (Icu.IsPunct(text[ich]) && ich > 0 && !Icu.IsSeparator(text[ich - 1])) { // if word-final punctuation advance ich++; } else if (startingStyle != null && tss.StyleAt(ich) == startingStyle) { ich++; } else { break; } } // NEVER move backward if at the end of the paragraph. if (ich < text.Length) { // While the insertion point is in the middle of a word then back up to the // start of the word or the start of a paragraph. while (ich > 0 && !Icu.IsSeparator(text[ich - 1]) && !specialStyles.Contains(tss.StyleAt(ich - 1))) { ich--; } } return(ich); }