private void radRichTextBox_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Space) { double originalOffset = radRichTextBox.VerticalOffset; double originalY = this.radRichTextBox.Document.CaretPosition.Location.Y; using (DocumentPosition originalCaretPosition = new DocumentPosition(this.radRichTextBox.Document.CaretPosition, true)) { Paragraph currentParagraph = radRichTextBox.Document.CaretPosition.GetCurrentParagraph(); // remove any extant links, so that we can reparse them IEnumerable <HyperlinkRangeStart> links = this.radRichTextBox.Document.CaretPosition .GetCurrentParagraph().EnumerateChildrenOfType <HyperlinkRangeStart>(); foreach (HyperlinkRangeStart link in links) { RadDocumentEditor documentEditor = new RadDocumentEditor(radRichTextBox.Document); documentEditor.DeleteAnnotationRange(link); } foreach (Inline inline in currentParagraph.Inlines) { string currentBook = string.Empty; uint currentChapter = 0; uint currentVerse = 0; DocumentTextSearch search = new DocumentTextSearch(radRichTextBox.Document); radRichTextBox.Document.CaretPosition.MoveToFirstPositionInParagraph(); DocumentPosition startDocPos = radRichTextBox.Document.CaretPosition; radRichTextBox.Document.CaretPosition.MoveToLastPositionInParagraph(); DocumentPosition endDocPos = radRichTextBox.Document.CaretPosition; radRichTextBox.Document.CaretPosition.MoveToFirstPositionInParagraph(); foreach (TextRange textRange in search.FindAll("(\\b((1|2|3|I|II|III|i|ii|iii) )?[\\w']+\\b\\s\\d+:\\d*[\\d \\-:]{0,300}\\d)|(, ?\\d+:\\d+)[\\-]*\\d*[\\d \\-:]{0,300}\\d|(, ?\\d+)[\\-]*\\d*|(v\\d{1,3})", startDocPos, originalCaretPosition)) { // textRange will represent a string in one of the following formats: // 1: book chapter:verse (with the possible suffix of "-{chapter:}verse // 2: , chapter:verse (with the possible suffix of "-{chapter:}verse // 3: , verse (with the possible suffix of "-{chapter:}verse // 4: v[verse] RadDocumentEditor documentEditor = new RadDocumentEditor(radRichTextBox.Document); radRichTextBox.Document.Selection.Ranges.Clear(); radRichTextBox.Document.Selection.AddSelectionStart(textRange.StartPosition); radRichTextBox.Document.Selection.AddSelectionEnd(textRange.EndPosition); string currentWord = radRichTextBox.Document.Selection.GetSelectedText(); Debug.WriteLine($"trying to parse {currentWord}"); ParsedReference result = ProcessReference(currentWord, currentBook, currentChapter, currentVerse); if (result.WasParsedSuccessfully) { HyperlinkInfo info = new HyperlinkInfo() { NavigateUri = $"kgb://book={result.Book}&chap={result.Chapter}&verse={result.Verse}", Target = HyperlinkTargets.Blank, IsAnchor = false }; documentEditor.InsertHyperlink(info); currentBook = result.Book; currentChapter = result.Chapter; currentVerse = result.Verse; } radRichTextBox.Document.Selection.Ranges.Clear(); } } radRichTextBox.Document.CaretPosition.MoveToPosition(originalCaretPosition); radRichTextBox.Document.Selection.Ranges.Clear(); radRichTextBox.ActiveEditorPresenter.ScrollToVerticalOffset(originalOffset - originalY + this.radRichTextBox.Document.CaretPosition.Location.Y); } } radRichTextBox.UpdateEditorLayout(false); }
ParsedReference ProcessReference(string input, string currentBook, uint currentChapter, uint currentVerse) { ParsedReference result = new ParsedReference(); result.WasParsedSuccessfully = false; result.Book = currentBook; result.Chapter = currentChapter; result.Verse = currentVerse; try { // let's start by trying to parse a "v[verse]" reference Regex v1Regex = new Regex("(\\b(?<book>((1|2|3|I|II|III|i|ii|iii) )?[\\w']+)\\b\\s(?<chapter>\\d+):(?<verse>\\d*)[\\d \\-:]{0,300})"); Regex v2Regex = new Regex("(, ?(?<chapter>\\d+):)(?<verse>\\d+)[\\-]*\\d*[\\d \\-:]{0,300}\\d"); Regex v3Regex = new Regex("(, ?(?<verse>\\d+))[\\-]*\\d*"); Regex v4Regex = new Regex("(v(?<verse>\\d{1,3}))"); if (v1Regex.IsMatch(input)) { result.WasParsedSuccessfully = true; Match m = v1Regex.Match(input); result.Book = nkjv.GetBookCode(m.Groups["book"].Value).ToLower(); result.Chapter = uint.Parse(m.Groups["chapter"].Value); result.Verse = uint.Parse(m.Groups["verse"].Value); } else if (v2Regex.IsMatch(input)) { result.WasParsedSuccessfully = true; Match m = v2Regex.Match(input); result.Chapter = uint.Parse(m.Groups["chapter"].Value); result.Verse = uint.Parse(m.Groups["verse"].Value); } else if (v3Regex.IsMatch(input)) { result.WasParsedSuccessfully = true; Match m = v3Regex.Match(input); result.Verse = uint.Parse(m.Groups["verse"].Value); } else if (v4Regex.IsMatch(input)) { result.WasParsedSuccessfully = true; Match m = v4Regex.Match(input); result.Verse = uint.Parse(m.Groups["verse"].Value); } // validate that the book name is in the Bible we have. result.WasParsedSuccessfully &= nkjv.IsValidBookName(result.Book); // validate that the chapter number is valid in the bible we have. result.WasParsedSuccessfully &= nkjv.IsValidChapterNumber(result.Book, result.Chapter); result.WasParsedSuccessfully &= nkjv.IsValidBookChapterVerseNumber(result.Book, result.Chapter, result.Verse); } catch (Exception e) { Debug.WriteLine($"failed to parse {input}"); } return(result); }