public GetLevelForTag ( int tag ) : int | ||
tag | int | The field tag to search for /// (i.e. BaseStText.StTextTags.kflidParagraphs) |
return | int |
/// ------------------------------------------------------------------------------------ /// <summary> /// Refresh highlighted text in diff view. /// </summary> /// <param name="selHelper">selection used to get hvo of paragraph to notify for /// refreshing diff highlight</param> /// ------------------------------------------------------------------------------------ private void RefreshDiffViewHighlighting(SelectionHelper selHelper) { if (selHelper != null) { int paraIndex = selHelper.GetLevelForTag((int)StText.StTextTags.kflidParagraphs); NotifyParagraph(selHelper.LevelInfo[paraIndex].hvo); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Find and select the next translation meeting a given condition /// </summary> /// <param name="selection">The selection where to start the search. /// NOTE: The selection must have all of the info set in the LevelInfo (hvo, ihvo)</param> /// <param name="condition">Condition the cack translation must meet</param> /// ------------------------------------------------------------------------------------ private void MoveToNextTranslation(SelectionHelper selection, Func<ICmTranslation, bool> condition) { SelLevInfo bookInfo; SelLevInfo paraInfo; SelLevInfo sectionInfo; bool fFoundBookLevel = selection.GetLevelInfoForTag(BookFilter.Tag, out bookInfo); bool fFoundSectionLevel = selection.GetLevelInfoForTag( ScrBookTags.kflidSections, out sectionInfo); int secLev = selection.GetLevelForTag(ScrBookTags.kflidSections); bool fFoundParaLevel = selection.GetLevelInfoForTag( StTextTags.kflidParagraphs, out paraInfo); if (!fFoundBookLevel || !fFoundParaLevel) return; // Look through all the books in the book filter int bookStartIndex = bookInfo.ihvo; int sectionStartIndex = 0; int sectionTag; int paraStartIndex = paraInfo.ihvo + 1; int paraIndex; if (fFoundSectionLevel) { // start with current section sectionStartIndex = sectionInfo.ihvo; sectionTag = selection.LevelInfo[secLev - 1].tag; } else { // no section, so this must be the title - Look through the title paragraphs IScrBook checkBook = BookFilter.GetBook(bookStartIndex); paraIndex = FindNextTranslationInText(checkBook.TitleOA, paraStartIndex, condition); if (paraIndex >= 0) { // select the title paragraph SetInsertionPoint(ScrBookTags.kflidTitle, bookStartIndex, 0, paraIndex); return; } // continue the search with the current book sectionTag = ScrSectionTags.kflidHeading; paraStartIndex = 0; } for (int bookIndex = bookStartIndex; bookIndex < BookFilter.BookCount; bookIndex++) { IScrBook checkBook = BookFilter.GetBook(bookIndex); if (bookIndex > bookStartIndex) { // Look through the title paragraphs paraIndex = FindNextTranslationInText(checkBook.TitleOA, 0, condition); if (paraIndex >= 0) { // select the title paragraph SetInsertionPoint(ScrBookTags.kflidTitle, bookIndex, 0, paraIndex); return; } } // Look through the sections in order. for (int sectionIndex = sectionStartIndex; sectionIndex < checkBook.SectionsOS.Count; sectionIndex++) { IScrSection checkSection = checkBook.SectionsOS[sectionIndex]; // Look in the paragraphs (could be either content or heading) IStText text = (sectionTag == ScrSectionTags.kflidHeading) ? checkSection.HeadingOA : checkSection.ContentOA; paraIndex = FindNextTranslationInText(text, paraStartIndex, condition); if (paraIndex >= 0) { // select the paragraph SetInsertionPoint(sectionTag, bookIndex, sectionIndex, paraIndex); return; } // Look in the content paragraphs, if we haven't already if (sectionTag == ScrSectionTags.kflidHeading) { sectionTag = ScrSectionTags.kflidContent; paraIndex = FindNextTranslationInText(checkSection.ContentOA, 0, condition); if (paraIndex >= 0) { // select the content paragraph SetInsertionPoint(sectionTag, bookIndex, sectionIndex, paraIndex); return; } } sectionTag = ScrSectionTags.kflidHeading; paraStartIndex = 0; } sectionStartIndex = 0; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Find and select the previous translation with a given state /// </summary> /// <param name="selection">The selection where to start the search. /// NOTE: The selection must have all of the info set in the LevelInfo (hvo, ihvo)</param> /// <param name="searchStatus">Back translation status to search for</param> /// ------------------------------------------------------------------------------------ private void MoveToPrevTranslation(SelectionHelper selection, BackTranslationStatus searchStatus) { SelLevInfo bookInfo; SelLevInfo paraInfo; SelLevInfo sectionInfo; bool fFoundBookLevel = selection.GetLevelInfoForTag(BookFilter.Tag, out bookInfo); bool fFoundSectionLevel = selection.GetLevelInfoForTag( ScrBookTags.kflidSections, out sectionInfo); int secLev = selection.GetLevelForTag(ScrBookTags.kflidSections); bool fFoundParaLevel = selection.GetLevelInfoForTag( StTextTags.kflidParagraphs, out paraInfo); if (!fFoundBookLevel || !fFoundParaLevel) return; // Look through all the books in the book filter int bookStartIndex = bookInfo.ihvo; int sectionStartIndex = -1; int sectionTag = ScrSectionTags.kflidContent; int paraStartIndex = paraInfo.ihvo - 1; int paraIndex; if (fFoundSectionLevel) { // start with current section sectionStartIndex = sectionInfo.ihvo; sectionTag = selection.LevelInfo[secLev - 1].tag; } else { // no section, so this must be the title - Look through the title paragraphs IScrBook checkBook = BookFilter.GetBook(bookStartIndex); paraIndex = FindPrevTranslationInText(checkBook.TitleOA, searchStatus, paraStartIndex); if (paraIndex >= 0) { // select the title paragraph SetInsertionPoint(ScrBookTags.kflidTitle, bookStartIndex, 0, paraIndex); return; } // continue the search with the previous book bookStartIndex--; paraStartIndex = -2; } for (int bookIndex = bookStartIndex; bookIndex >= 0 ; bookIndex--) { IScrBook checkBook = BookFilter.GetBook(bookIndex); if (sectionStartIndex == -1) { sectionStartIndex = checkBook.SectionsOS.Count - 1; sectionTag = ScrSectionTags.kflidContent; } // Look through the sections in reverse order. for (int sectionIndex = sectionStartIndex; sectionIndex >= 0; sectionIndex--) { IScrSection checkSection = checkBook.SectionsOS[sectionIndex]; if (paraStartIndex == -2) { paraStartIndex = checkSection.ContentOA.ParagraphsOS.Count - 1; sectionTag = ScrSectionTags.kflidContent; } // Look in the paragraphs (could be either content or heading) IStText text = (sectionTag == ScrSectionTags.kflidHeading) ? checkSection.HeadingOA : checkSection.ContentOA; paraIndex = FindPrevTranslationInText(text, searchStatus, paraStartIndex); if (paraIndex >= 0) { // select the paragraph SetInsertionPoint(sectionTag, bookIndex, sectionIndex, paraIndex); return; } // Look in the heading paragraphs, if we haven't already if (sectionTag == ScrSectionTags.kflidContent) { sectionTag = ScrSectionTags.kflidHeading; int startHeadPara = checkSection.HeadingOA.ParagraphsOS.Count - 1; paraIndex = FindPrevTranslationInText(checkSection.HeadingOA, searchStatus, startHeadPara); if (paraIndex >= 0) { // select the heading paragraph SetInsertionPoint(sectionTag, bookIndex, sectionIndex, paraIndex); return; } } paraStartIndex = -2; } sectionStartIndex = -1; // Look through the title paragraphs int startTitlePara = checkBook.TitleOA.ParagraphsOS.Count - 1; paraIndex = FindPrevTranslationInText(checkBook.TitleOA, searchStatus, startTitlePara); if (paraIndex >= 0) { // select the title paragraph SetInsertionPoint(ScrBookTags.kflidTitle, bookIndex, 0, paraIndex); return; } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determine whether this is a selection that goes from the content of one section to /// the content of another. /// </summary> /// <param name="helper"></param> /// <param name="topInfo"></param> /// <param name="bottomInfo"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private bool IsMultiSectionContentSelection(SelectionHelper helper, SelLevInfo[] topInfo, SelLevInfo[] bottomInfo) { bool multiSectionSelection = false; ILocationTracker tracker = ((ITeView)Control).LocationTracker; int sectionTag = (int)ScrSection.ScrSectionTags.kflidContent; int clev = tracker.GetLevelCount(sectionTag); if (topInfo.Length == clev && bottomInfo.Length == clev) { int paraTag = (int)StText.StTextTags.kflidParagraphs; // if selection starts in content of section in one book and goes to content // of another section in the same book int sectionLevelTop = helper.GetLevelForTag(sectionTag, SelectionHelper.SelLimitType.Top); if (sectionLevelTop == -1) return false; if (tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top) == tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Bottom) && tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top) < tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Bottom) && sectionLevelTop == helper.GetLevelForTag(sectionTag, SelectionHelper.SelLimitType.Bottom) && helper.GetLevelForTag(paraTag, SelectionHelper.SelLimitType.Top) == helper.GetLevelForTag(paraTag, SelectionHelper.SelLimitType.Bottom)) { multiSectionSelection = true; } } return multiSectionSelection; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determines if the selection starts at the beginning of the section head and ends at /// the beginning of the section content. /// </summary> /// <param name="helper"></param> /// <param name="topInfo"></param> /// <param name="bottomInfo"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private bool IsSectionHeadDeletion(SelectionHelper helper, SelLevInfo[] topInfo, SelLevInfo[] bottomInfo) { int levelText = helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidContent); if (levelText < 0) levelText = helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidHeading); if (levelText < 0) return false; bool sectionHeadDeletion = false; int levelPara = helper.GetLevelForTag((int)StText.StTextTags.kflidParagraphs); ILocationTracker tracker = ((ITeView)Control).LocationTracker; int clev = tracker.GetLevelCount((int)ScrSection.ScrSectionTags.kflidContent); if (topInfo.Length == clev && bottomInfo.Length == clev && levelPara >= 0) { if (tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top) == tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Bottom) && tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top) == tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Bottom) && topInfo[levelText].tag == (int)ScrSection.ScrSectionTags.kflidHeading && bottomInfo[levelText].tag == (int)ScrSection.ScrSectionTags.kflidContent && topInfo[levelText].ihvo == 0 && bottomInfo[levelText].ihvo == 0 && topInfo[levelPara].tag == (int)StText.StTextTags.kflidParagraphs && bottomInfo[levelPara].tag == (int)StText.StTextTags.kflidParagraphs && topInfo[levelPara].ihvo == 0 && bottomInfo[levelPara].ihvo == 0) { sectionHeadDeletion = (helper.IchAnchor == 0 && helper.IchEnd == 0); if (sectionHeadDeletion) { StTxtPara para = new StTxtPara(m_cache, bottomInfo[levelPara].hvo); sectionHeadDeletion = (para.Contents.Text != null); } } } return sectionHeadDeletion; }
/// ------------------------------------------------------------------------------------ /// <summary> /// If a single section is wholly selected or the selection goes from the top of one /// section to the top of the following section, then the selected section may be /// deleted. /// </summary> /// <param name="helper"></param> /// <param name="topInfo"></param> /// <param name="bottomInfo"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private bool IsSectionDeletion(SelectionHelper helper, SelLevInfo[] topInfo, SelLevInfo[] bottomInfo) { bool sectionDeletion = false; ILocationTracker tracker = ((ITeView)Control).LocationTracker; int clev = tracker.GetLevelCount((int)ScrSection.ScrSectionTags.kflidContent); int levelText = helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidContent); if (levelText < 0) levelText = helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidHeading); int levelPara = helper.GetLevelForTag((int)StText.StTextTags.kflidParagraphs); // the selection must be the right number of levels deep. if (topInfo.Length == clev && bottomInfo.Length == clev && levelText >= 0 && levelPara >= 0) { // if the selection is in the same scripture and the same book... if (tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top) == tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Bottom) && // not selecting something weird topInfo[levelText - 1].tag == (int)StText.StTextTags.kflidParagraphs && bottomInfo[levelText - 1].tag == (int)StText.StTextTags.kflidParagraphs) { // Selection top is in one section and bottom is in a following one if (tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top) <= tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Bottom) - 1 && // if the selection begins and ends in section heading topInfo[levelText].tag == (int)ScrSection.ScrSectionTags.kflidHeading && bottomInfo[levelText].tag == (int)ScrSection.ScrSectionTags.kflidHeading && topInfo[levelText].ihvo == 0 && bottomInfo[levelText].ihvo == 0 && // and the selection begins and ends in the first paragraph of those headings topInfo[levelPara].ihvo == 0 && bottomInfo[levelPara].ihvo == 0) { // Does selection go from the beginning of one heading to the beginning of another? sectionDeletion = (helper.IchAnchor == 0 && helper.IchEnd == 0); } // Selection starts at beginning of one section heading and ends // at end of content of another section. else if (tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top) <= tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Bottom) && // Selection top is in section heading and bottom is in content topInfo[levelText].tag == (int)ScrSection.ScrSectionTags.kflidHeading && bottomInfo[levelText].tag == (int)ScrSection.ScrSectionTags.kflidContent && topInfo[levelText].ihvo == 0 && bottomInfo[levelText].ihvo == 0 && // Top of selection is in first heading paragraph topInfo[levelPara].ihvo == 0) { int ichTop = helper.GetIch(SelectionHelper.SelLimitType.Top); sectionDeletion = ichTop == 0 && IsSelectionAtEndOfSection(helper, bottomInfo, clev); } } } return sectionDeletion; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Selections at end of section. /// </summary> /// <param name="helper">The helper.</param> /// <param name="bottomInfo">The bottom info.</param> /// <param name="clev">The clev.</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private bool IsSelectionAtEndOfSection(SelectionHelper helper, SelLevInfo[] bottomInfo, int clev) { bool atEndOfSection = false; // Is the bottom of the selection in the last para of the section? ScrSection bottomSection = new ScrSection(m_cache, ((ITeView)Control).LocationTracker.GetSectionHvo( helper, SelectionHelper.SelLimitType.Bottom)); IStText bottomContent = bottomSection.ContentOA; int levelPara = helper.GetLevelForTag((int)StText.StTextTags.kflidParagraphs); if (bottomInfo[levelPara].ihvo == bottomContent.ParagraphsOS.Count - 1) { StTxtPara lastPara = new StTxtPara(m_cache, bottomInfo[levelPara].hvo); ITsString lastParaContents = lastPara.Contents.UnderlyingTsString; int ichBottom = helper.GetIch(SelectionHelper.SelLimitType.Bottom); atEndOfSection = ichBottom == lastParaContents.Length; } return atEndOfSection; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the Hvo of the surviving paragraph. This will be either the paragraph before /// the selected paragraph if we have an IP or the paragraph at the top of a range /// selection. /// </summary> /// ------------------------------------------------------------------------------------ private int SurvivorParagraphHvo(SelectionHelper selHelper, IStText text, int ihvo, bool fMergeNext) { if (!selHelper.IsRange) { int iSurvivor = fMergeNext ? ihvo + 1 : ihvo - 1; return (iSurvivor >= 0 && iSurvivor < text.ParagraphsOS.Count ? text.ParagraphsOS.HvoArray[iSurvivor] : -1); } int paraLev = selHelper.GetLevelForTag((int)StText.StTextTags.kflidParagraphs, SelectionHelper.SelLimitType.Top); SelLevInfo[] rgSelLevInfo = selHelper.GetLevelInfo(SelectionHelper.SelLimitType.Top); return rgSelLevInfo[paraLev].hvo; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Try to do something about an IP selection deletion that is at the start or end of an /// StText. If successful return true, otherwise false. /// </summary> /// <param name="helper"></param> /// <param name="dpt"></param> /// <returns><c>true</c> if we successfully handled the deletion.</returns> /// ------------------------------------------------------------------------------------ internal bool HandleBsOrDelAtTextBoundary(SelectionHelper helper, VwDelProbType dpt) { CheckDisposed(); SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Anchor); ILocationTracker tracker = ((ITeView)Control).LocationTracker; // bail out if we are not in a paragraph within a scripture section if (levInfo.Length != tracker.GetLevelCount((int)ScrSection.ScrSectionTags.kflidContent) || tracker.GetSectionIndexInView(helper, SelectionHelper.SelLimitType.Anchor) < 0 || levInfo[0].tag != (int)StText.StTextTags.kflidParagraphs) { // Assume we are in a book title SelLevInfo dummyInfo; if (helper.GetLevelInfoForTag((int)ScrBook.ScrBookTags.kflidTitle, out dummyInfo)) return MergeParasInTable(helper, dpt); return false; } // Level 1 will have tags showing which field of section is selected int iLevelSection = helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidHeading); if (iLevelSection >= 0) { if (levInfo[0].ihvo == 0 && dpt == VwDelProbType.kdptBsAtStartPara) { // first paragraph of section head return HandleBackspaceAfterEmptyContentParagraph(helper); } else if (levInfo[0].ihvo == 0 && helper.IchAnchor == 0) { // Delete was pressed in an empty section head - try to combine with previous // return DeleteSectionHead(helper, false, false); if (dpt == VwDelProbType.kdptBsAtStartPara) return HandleBackspaceAfterEmptySectionHeadParagraph(helper); return HandleDeleteBeforeEmptySectionHeadParagraph(helper); } // NOTE: we check the vector size for the parent of the paragraph (levInfo[1].hvo) // but with our own tag (levInfo[0].tag)! else if (levInfo[0].ihvo == m_cache.GetVectorSize(levInfo[iLevelSection].hvo, levInfo[0].tag) - 1 && dpt == VwDelProbType.kdptDelAtEndPara) { // last paragraph of section head return HandleDeleteBeforeEmptySectionContentParagraph(helper); } else { // other problem deletion: e.g. delete in BT side-by-side view. Because // we're displaying the paragraphs in a table with two columns, the views // code can't handle that. We have to merge the two paragraphs manually. return MergeParasInTable(helper, dpt); } } else if (helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidContent) >= 0) { iLevelSection = helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidContent); if (levInfo[0].ihvo == 0 && dpt == VwDelProbType.kdptBsAtStartPara) { // first paragraph of section return HandleBackspaceAfterEmptySectionHeadParagraph(helper); } else if (levInfo[0].ihvo == 0 && helper.IchAnchor == 0) { // Delete was pressed in an empty section content - try to combine with previous if (dpt == VwDelProbType.kdptBsAtStartPara) return HandleBackspaceAfterEmptyContentParagraph(helper); return HandleDeleteBeforeEmptySectionContentParagraph(helper); } // NOTE: we check the vector size for the parent of the paragraph (levInfo[1].hvo) // but with our own tag (levInfo[0].tag)! else if (levInfo[0].ihvo == m_cache.GetVectorSize(levInfo[iLevelSection].hvo, levInfo[0].tag) - 1 && dpt == VwDelProbType.kdptDelAtEndPara) { // last paragraph of section return HandleDeleteBeforeEmptySectionHeadParagraph(helper); } else { // other problem deletion: e.g. delete in BT side-by-side view. Because // we're displaying the paragraphs in a table with two columns, the views // code can't handle that. We have to merge the two paragraphs manually. return MergeParasInTable(helper, dpt); } } return false; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets Scripture reference for a selection /// </summary> /// <param name="helper">The selection helper that represents the selection</param> /// <param name="fInclusive"><c>true</c> if the reference returned should include the /// reference of the text of the verse where the selection is, even if that selection /// is not at the start of the verse; <c>false</c> if the reference should be that of /// the first full verse at or following the selection</param> /// <param name="scriptureRef">returns the scripture reference found</param> /// <returns>A TsString representing the reference of the selection, or null if the /// selection represents a book title or something weird.</returns> /// ------------------------------------------------------------------------------------ private ITsString GetSelectionReference(SelectionHelper helper, bool fInclusive, out BCVRef scriptureRef) { scriptureRef = new BCVRef(); if (helper != null && m_page.Publication != null && m_page.Publication is ScripturePublication) { ScripturePublication scrPub = m_page.Publication as ScripturePublication; int iParaLevel = helper.GetLevelForTag((int)StText.StTextTags.kflidParagraphs); if (iParaLevel >= 0) { ScrTxtPara para = new ScrTxtPara(m_cache, helper.LevelInfo[iParaLevel].hvo); // Look through the verses of the paragraph until we pass the location // where the page break occurs. This verse reference will then be the // first one on the page. ScrVerse firstVerseOnPage = null; int ichPageBreak = helper.IchAnchor; foreach (ScrVerse verse in para) { if (!fInclusive) firstVerseOnPage = verse; if (verse.VerseStartIndex > ichPageBreak || (verse.VerseStartIndex == ichPageBreak && !fInclusive)) break; if (fInclusive) firstVerseOnPage = verse; } ITsString tssBookName = GetBookName(helper); if (tssBookName != null) { ITsStrBldr bldr = tssBookName.GetBldr(); int cch = bldr.Length; if (firstVerseOnPage != null) { if (firstVerseOnPage.StartRef.Verse != 0) { bldr.Replace(cch, cch, " " + ((Scripture)m_scr).ChapterVerseRefAsString(firstVerseOnPage.StartRef, m_wsDefault), null); } scriptureRef = firstVerseOnPage.StartRef; } return bldr.GetString(); } //else //{ // // Probably no verses were found in the paragraph // IVwSelection sel = FindNextPara(helper); // helper = SelectionHelper.Create(sel, helper.RootSite); // return GetSelectionReference(helper, fInclusive, out scriptureRef); //} } } return null; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Finds the nearest footnote before the given selection. /// </summary> /// <param name="helper">The selection helper.</param> /// <param name="book">The book that owns the footnote collection.</param> /// <param name="fSearchForward">True to also search forward within the current paragraph</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private StFootnote FindFootnoteNearSelection(SelectionHelper helper, IScrBook book, bool fSearchForward) { CheckDisposed(); if (helper == null) helper = CurrentSelection; if (helper == null || book == null) return null; SelLevInfo[] levels = helper.GetLevelInfo(SelectionHelper.SelLimitType.Anchor); int iParagraph = -1; int tag = 0; int ich = helper.IchAnchor; int paraLev = helper.GetLevelForTag((int)StText.StTextTags.kflidParagraphs); int contentLev = helper.GetLevelForTag((int)StTxtPara.StTxtParaTags.kflidContents); Debug.Assert(paraLev != -1, "Need a paragraph for this method"); iParagraph = levels[paraLev].ihvo; int iSection = ((ITeView)Control).LocationTracker.GetSectionIndexInBook( helper, SelectionHelper.SelLimitType.Anchor); if (iSection < 0) tag = (int)ScrBook.ScrBookTags.kflidTitle; else { tag = (helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidContent) >= 0 ? (int)ScrSection.ScrSectionTags.kflidContent : (int)ScrSection.ScrSectionTags.kflidHeading); } // Special case: if we're in the caption of a picture, get the ich from // the first level instead of the anchor. (TE-4696) if (contentLev >= 0 && levels[contentLev].ihvo == -1) ich = levels[contentLev].ich; ScrFootnote prevFootnote = null; if (fSearchForward) // look first at our current position, if we are searching foward { prevFootnote = ScrFootnote.FindCurrentFootnote(m_cache, book, iSection, iParagraph, ich, tag); } if (prevFootnote == null) { StTxtPara para = new StTxtPara(m_cache, levels[paraLev].hvo); ITsString tss = para.Contents.UnderlyingTsString; if (ich != 0) { // look backwards in our current paragraph prevFootnote = ScrFootnote.FindLastFootnoteInString(m_cache, tss, ref ich, true); } else if (iParagraph > 0) { // look at the previous paragraph for a footnote at the end StText text = new StText(m_cache, levels[paraLev + 1].hvo); StTxtPara prevPara = (StTxtPara)text.ParagraphsOS[iParagraph - 1]; ITsString prevTss = prevPara.Contents.UnderlyingTsString; int ichTmp = -1; prevFootnote = ScrFootnote.FindLastFootnoteInString(m_cache, prevTss, ref ichTmp, false); if (prevFootnote != null) { if (ichTmp == prevTss.Length - 1) ich = ichTmp; else prevFootnote = null; } // ENHANCE: Look across contexts. } } if (prevFootnote == null && fSearchForward) { // look ahead in the same paragraph StTxtPara para = new StTxtPara(m_cache, levels[paraLev].hvo); ITsString tss = para.Contents.UnderlyingTsString; prevFootnote = ScrFootnote.FindFirstFootnoteInString(m_cache, tss, ref ich, true); } if (prevFootnote == null) { // just go back until we find one prevFootnote = ScrFootnote.FindPreviousFootnote(m_cache, book, ref iSection, ref iParagraph, ref ich, ref tag); } return prevFootnote; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets the level for the section tag. /// </summary> /// <param name="selHelper">The selection helper.</param> /// <param name="selLimitType">Which end of the selection</param> /// <returns>The level for the section, or -1 if there is no section tag (e.g. in a /// title)</returns> /// ------------------------------------------------------------------------------------ private int GetSectionLevel(SelectionHelper selHelper, SelectionHelper.SelLimitType selLimitType) { int sectionTag = -1; if (selHelper == TeEditingHelper.CurrentSelection && FocusedDivision != null) { TePrintLayoutConfig configurer = ((DivisionLayoutMgr)FocusedDivision).Configurer as TePrintLayoutConfig; if (configurer != null) sectionTag = GetSectionTag(configurer); } if (sectionTag < 0 && selHelper.Selection != null && selHelper.Selection.RootBox != null) { int iDiv = DivisionIndexForMainStream(selHelper.Selection.RootBox as IVwLayoutStream); if (iDiv >= 0) sectionTag = GetSectionTag((TePrintLayoutConfig)Divisions[iDiv].Configurer); } if (sectionTag < 0) return -1; return selHelper.GetLevelForTag(sectionTag, selLimitType); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Finds the nearest footnote before the given selection. /// </summary> /// <param name="helper">The selection helper.</param> /// <param name="book">The book that owns the footnote collection.</param> /// <param name="fSearchForward">True to also search forward within the current paragraph</param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private IStFootnote FindFootnoteNearSelection(SelectionHelper helper, IScrBook book, bool fSearchForward) { CheckDisposed(); if (helper == null) helper = CurrentSelection; if (helper == null || book == null) return null; SelLevInfo[] levels = helper.GetLevelInfo(SelectionHelper.SelLimitType.Anchor); int iParagraph = -1; int tag = 0; int ich = helper.IchAnchor; int paraLev = helper.GetLevelForTag(StTextTags.kflidParagraphs); int contentLev = helper.GetLevelForTag(StTxtParaTags.kflidContents); Debug.Assert(paraLev != -1, "Need a paragraph for this method"); iParagraph = levels[paraLev].ihvo; int iSection = ((ITeView)Control).LocationTracker.GetSectionIndexInBook( helper, SelectionHelper.SelLimitType.Anchor); if (iSection < 0) tag = ScrBookTags.kflidTitle; else { tag = (helper.GetLevelForTag(ScrSectionTags.kflidContent) >= 0 ? ScrSectionTags.kflidContent : ScrSectionTags.kflidHeading); } // Special case: if we're in the caption of a picture, get the ich from // the first level instead of the anchor. (TE-4696) if (contentLev >= 0 && levels[contentLev].ihvo == -1) ich = levels[contentLev].ich; IScrFootnote prevFootnote = null; if (fSearchForward) // look first at our current position, if we are searching foward prevFootnote = book.FindCurrentFootnote(iSection, iParagraph, ich, (int)tag); if (prevFootnote == null) { IScrTxtPara para = m_repoScrTxtPara.GetObject(levels[paraLev].hvo); ITsString tss = para.Contents; if (ich != 0) { // look backwards in our current paragraph - skip the current run, except when // at the end of the text. prevFootnote = para.FindPrevFootnoteInContents(ref ich, ich < tss.Length); } else if (iParagraph > 0) { // look at the previous paragraph for a footnote at the end IStText text = m_repoStText.GetObject(levels[paraLev + 1].hvo); IScrTxtPara prevPara = (IScrTxtPara)text[iParagraph - 1]; ITsString prevTss = prevPara.Contents; int ichTmp = -1; prevFootnote = prevPara.FindPrevFootnoteInContents(ref ichTmp, false); if (prevFootnote != null) { if (ichTmp == prevTss.Length - 1) ich = ichTmp; else prevFootnote = null; } // ENHANCE: Look across contexts. } } if (prevFootnote == null && fSearchForward) { // look ahead in the same paragraph IScrTxtPara para = m_repoScrTxtPara.GetObject(levels[paraLev].hvo); ITsString tss = para.Contents; prevFootnote = para.FindNextFootnoteInContents(ref ich, true); } if (prevFootnote == null) { // just go back until we find one prevFootnote = book.FindPrevFootnote(ref iSection, ref iParagraph, ref ich, ref tag); } return prevFootnote; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets an StTxtPara representing the paragraph of the given selection. /// </summary> /// ------------------------------------------------------------------------------------ private IStTxtPara GetPara(SelectionHelper helper, out IStText text, out int iPara, out int tag) { SelLevInfo paraLevInfo; if (!helper.GetLevelInfoForTag(StTextTags.kflidParagraphs, out paraLevInfo)) { text = null; iPara = tag = -1; return null; } iPara = paraLevInfo.ihvo; ILocationTracker tracker = ((ITeView)Control).LocationTracker; IScrBook book = tracker.GetBook(helper, SelectionHelper.SelLimitType.Top); IScrSection section = tracker.GetSection(helper, SelectionHelper.SelLimitType.Top); if (section == null) { text = book.TitleOA; tag = ScrBookTags.kflidTitle; } else { tag = (helper.GetLevelForTag(ScrSectionTags.kflidContent) >= 0 ? ScrSectionTags.kflidContent : ScrSectionTags.kflidHeading); text = (tag == ScrSectionTags.kflidHeading ? section.HeadingOA : section.ContentOA); } return text[iPara]; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Refresh highlighted text in diff view. /// </summary> /// <param name="selHelper">selection used to get hvo of paragraph to notify for /// refreshing diff highlight</param> /// ------------------------------------------------------------------------------------ private void RefreshDiffViewHighlighting(SelectionHelper selHelper) { if (selHelper != null) { int paraIndex = selHelper.GetLevelForTag(StTextTags.kflidParagraphs); IScrTxtPara para = m_cache.ServiceLocator.GetInstance<IScrTxtParaRepository>() .GetObject(selHelper.LevelInfo[paraIndex].hvo); NotifyParagraph(para, selHelper.RootSite.RootBox); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// This is called by a view when the views code is about to delete a paragraph. We /// need to save the back translations by moving them to whatever paragraph the deleted /// one is merging with. /// </summary> /// <param name="selHelper">The selection helper</param> /// <param name="hvoObject">Paragraph to be deleted</param> /// <param name="hvoOwner">StText that owns the para</param> /// <param name="tag">flid in which para is owned</param> /// <param name="ihvo">index of paragraph in text</param> /// <param name="fMergeNext"><c>true</c> if this paragraph is merging with the /// following paragraph.</param> /// ------------------------------------------------------------------------------------ public virtual void AboutToDelete(SelectionHelper selHelper, int hvoObject, int hvoOwner, int tag, int ihvo, bool fMergeNext) { CheckDisposed(); if (tag != (int)StText.StTextTags.kflidParagraphs) return; StTxtPara paraToDelete = new StTxtPara(m_cache, hvoObject); // If the paragraph that is being deleted is empty, then do not attempt to save a back // translation for it. if (paraToDelete.Contents.Text == null) return; // ihvoTop is either the paragraph before the IP or the first paragraph in a range selection int ihvoTop = ihvo - 1; int hvoOwnerSurviving = hvoOwner; // Figure out what is being deleted and what is staying. // NOTE: it is possible that the selection is no longer valid. This is ok for our purposes here, // since all information we access here is already retrieved and stored in member variables of // SelectionHelper. if (selHelper.IsRange) { int paraLev = selHelper.GetLevelForTag(tag, SelectionHelper.SelLimitType.Top); SelLevInfo[] rgSelLevInfo = selHelper.GetLevelInfo(SelectionHelper.SelLimitType.Top); ihvoTop = rgSelLevInfo[paraLev].ihvo; if (paraLev + 1 < rgSelLevInfo.Length) hvoOwnerSurviving = rgSelLevInfo[paraLev + 1].hvo; int ihvoBottom = selHelper.GetLevelInfoForTag(tag, SelectionHelper.SelLimitType.Bottom).ihvo; // Pretty sure that if we get here top will NEVER equal bottom. Debug.Assert(ihvoTop != ihvoBottom || hvoOwnerSurviving != hvoOwner); if (hvoOwnerSurviving == hvoOwner) { if (ihvoTop == ihvoBottom) return; int ichEnd = selHelper.GetIch(SelectionHelper.SelLimitType.Bottom); // No need to merge because entire paragraph (with its contents) is going away. if (ihvo == ihvoBottom && ichEnd == paraToDelete.Contents.Length) return; // No need to merge because entire paragraph (with its contents) is going away. if (ihvo > ihvoTop && ihvo < ihvoBottom) return; } } // Determine the surviving paragraph. StText text = new StText(m_cache, hvoOwnerSurviving); StTxtPara paraSurviving; if (fMergeNext) { // when merging with next and there are no more paragraphs, then the BT can be discarded. if (text.ParagraphsOS.Count < ihvo + 1) return; // The surviving paragraph will be the one following the one that is deleted paraSurviving = (StTxtPara)text.ParagraphsOS[ihvo + 1]; } else { // If we are deleting the first paragraph in the surviving text, the BT should // also be deleted, so we're done. if (ihvo == 0 && hvoOwnerSurviving == hvoOwner) return; // The surviving paragraph will be the top one in the selection paraSurviving = (StTxtPara)text.ParagraphsOS[ihvoTop]; } ITsStrBldr bldr; ILgWritingSystemFactory wsf; List<int> writingSystems = GetWsList(out wsf); foreach (ICmTranslation transToDelete in paraToDelete.TranslationsOC) { // Find or create surviving translation of the same type. ICmTranslation transSurviving = paraSurviving.GetOrCreateTrans(transToDelete.TypeRA); // Merge back translations of the surviving and paragraph to be deleted for each writing system foreach (int ws in writingSystems) { TsStringAccessor tssAccToDelete = transToDelete.Translation.GetAlternative(ws); if (tssAccToDelete.Text != null) { TsStringAccessor tssAccSurviving = transSurviving.Translation.GetAlternative(ws); bldr = tssAccSurviving.UnderlyingTsString.GetBldr(); // If the surviving paragraph ends with white space of the paragraph to delete // begins with white space, add white space. string textSurviving = bldr.Text; ILgCharacterPropertyEngine charPropEng = m_cache.UnicodeCharProps; if (textSurviving != null && !charPropEng.get_IsSeparator(textSurviving[textSurviving.Length - 1]) && !charPropEng.get_IsSeparator(tssAccToDelete.Text[0])) { bldr.ReplaceRgch(textSurviving.Length, textSurviving.Length, " ", 1, null); } int cch = bldr.Length; bldr.ReplaceTsString(cch, cch, tssAccToDelete.UnderlyingTsString); tssAccSurviving.UnderlyingTsString = bldr.GetString(); } } } }