public GetLevelInfoForTag ( int tag ) : SIL.FieldWorks.Common.COMInterfaces.SelLevInfo | ||
tag | int | The field tag to search for /// (i.e. BaseStText.StTextTags.kflidParagraphs) |
return | SIL.FieldWorks.Common.COMInterfaces.SelLevInfo |
/// ------------------------------------------------------------------------------------ /// <summary> /// Common utility for the CurrentRef* properties /// </summary> /// <param name="selection"></param> /// <param name="selLimit">The limit of the selection (anchor, end, etc.) to get the /// reference of</param> /// <returns>the start and end reference of the given selection, as an array of two /// ScrReference objects</returns> /// ------------------------------------------------------------------------------------ protected virtual ScrReference[] GetCurrentRefRange(SelectionHelper selection, SelectionHelper.SelLimitType selLimit) { if (m_cache == null || selection == null || BookFilter == null) return new ScrReference[] {ScrReference.Empty, ScrReference.Empty}; ILocationTracker tracker = ((ITeView)Control).LocationTracker; // If there is a current book... BCVRef start = new BCVRef(); BCVRef end = new BCVRef(); int iBook = tracker.GetBookIndex(selection, selLimit); if (iBook >= 0 && BookFilter.BookCount > 0) { try { ScrBook book = BookFilter.GetBook(iBook); // if there is not a current section, then use the book and chapter/verse of 0. int hvoSection = tracker.GetSectionHvo(CurrentSelection, selLimit); if (hvoSection >= 0) { // If there is a section... ScrSection section = new ScrSection(m_cache, hvoSection); int paraHvo = selection.GetLevelInfoForTag( (int)StText.StTextTags.kflidParagraphs, selLimit).hvo; ScrTxtPara scrPara = new ScrTxtPara(m_cache, paraHvo); // Get the ich at either the beginning or the end of the selection, // as specified with limit. (NB that this is relative to the property, not the whole paragraph.) int ich; // Get the TsString, whether in vern or BT ITsString tss; SelLevInfo segInfo; int refWs; if (selection.GetLevelInfoForTag(StTxtPara.SegmentsFlid(Cache), selLimit, out segInfo)) { // selection is in a segmented BT segment. Figure the reference based on where the segment is // in the underlying paragraph. tss = scrPara.Contents.UnderlyingTsString; // for check below on range of ich. CmBaseAnnotation seg = new CmBaseAnnotation(Cache, segInfo.hvo); ich = seg.BeginOffset; Debug.Assert(seg.BeginObjectRAHvo == scrPara.Hvo); refWs = -1; // ich is in the paragraph itself, not some CmTranslation } else { ich = selection.GetIch(selLimit); // Get the TsString, whether in vern or BT tss = selection.GetTss(selLimit); refWs = GetCurrentBtWs(selLimit); // figures out whether it's in a CmTranslation or the para itself. } Debug.Assert(tss == null || ich <= tss.Length); if (tss != null && ich <= tss.Length) { scrPara.GetBCVRefAtPosition(refWs, ich, true, out start, out end); // If the chapter number is 0, then use the chapter from the section reference if (end.Chapter == 0) end.Chapter = BCVRef.GetChapterFromBcv(section.VerseRefMin); if (start.Chapter == 0) start.Chapter = BCVRef.GetChapterFromBcv(section.VerseRefMin); } } else { // either it didn't find a level or it didn't find an index. Either way, // it couldn't find a section. start.Book = end.Book = book.CanonicalNum; } } catch { // Bummer man, something went wrong... don't sweat it though, it happens... // This can occur if you are in the introduction or other location that lacks // relevant information or other necessary stuff. } } return new ScrReference[] {new ScrReference(start, m_scr.Versification), new ScrReference(end, m_scr.Versification)}; ; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Merges the paras in table. /// </summary> /// <param name="helper">The helper.</param> /// <param name="dpt">The problem deletion type.</param> /// <returns><c>true</c> if we merged the paras, otherwise <c>false</c>.</returns> /// ------------------------------------------------------------------------------------ internal protected bool MergeParasInTable(SelectionHelper helper, VwDelProbType dpt) { SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top); if (levInfo[0].tag != (int)StText.StTextTags.kflidParagraphs) return false; ILocationTracker tracker = ((ITeView)Control).LocationTracker; IScrBook book = new ScrBook(m_cache, tracker.GetBookHvo( helper, SelectionHelper.SelLimitType.Anchor)); SelLevInfo tmpInfo; IStText text; if (helper.GetLevelInfoForTag((int)ScrBook.ScrBookTags.kflidTitle, out tmpInfo)) text = book.TitleOA; else { IScrSection section = book.SectionsOS[tracker.GetSectionIndexInBook( helper, SelectionHelper.SelLimitType.Anchor)]; text = (levInfo[1].tag == (int)ScrSection.ScrSectionTags.kflidHeading ? section.HeadingOA : text = section.ContentOA); } int iPara = helper.GetLevelInfoForTag((int)StText.StTextTags.kflidParagraphs).ihvo; StTxtPara currPara = (StTxtPara)text.ParagraphsOS[iPara]; ITsStrBldr bldr; // Backspace at beginning of paragraph if (dpt == VwDelProbType.kdptBsAtStartPara) { if (iPara <= 0) { MiscUtils.ErrorBeep(); return false; } StTxtPara prevPara = (StTxtPara)text.ParagraphsOS[iPara - 1]; int prevParaLen = prevPara.Contents.Length; // Need to make sure we move the back translations AboutToDelete(helper, currPara.Hvo, text.Hvo, (int)StText.StTextTags.kflidParagraphs, iPara, false); bldr = prevPara.Contents.UnderlyingTsString.GetBldr(); bldr.ReplaceTsString(prevPara.Contents.Length, prevPara.Contents.Length, currPara.Contents.UnderlyingTsString); prevPara.Contents.UnderlyingTsString = bldr.GetString(); text.ParagraphsOS.RemoveAt(iPara); helper.SetIch(SelectionHelper.SelLimitType.Top, prevParaLen); helper.SetIch(SelectionHelper.SelLimitType.Bottom, prevParaLen); levInfo[0].ihvo = iPara - 1; helper.SetLevelInfo(SelectionHelper.SelLimitType.Top, levInfo); helper.SetLevelInfo(SelectionHelper.SelLimitType.Bottom, levInfo); helper.SetSelection(true); return true; } // delete at end of a paragraph int cParas = text.ParagraphsOS.Count; if (iPara + 1 >= cParas) return false; // We don't handle merging across StTexts StTxtPara nextPara = (StTxtPara)text.ParagraphsOS[iPara + 1]; // Need to make sure we move the back translations AboutToDelete(helper, nextPara.Hvo, text.Hvo, (int)StText.StTextTags.kflidParagraphs, iPara + 1, false); bldr = currPara.Contents.UnderlyingTsString.GetBldr(); bldr.ReplaceTsString(currPara.Contents.Length, currPara.Contents.Length, nextPara.Contents.UnderlyingTsString); currPara.Contents.UnderlyingTsString = bldr.GetString(); text.ParagraphsOS.RemoveAt(iPara + 1); helper.SetSelection(true); return true; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Deletes the picture specified by the hvo. /// </summary> /// <param name="helper">Selection containing the picture.</param> /// <param name="hvoPic">hvo of picture.</param> /// ------------------------------------------------------------------------------------ protected void DeletePicture(SelectionHelper helper, int hvoPic) { int paraHvo = helper.GetLevelInfoForTag((int)StText.StTextTags.kflidParagraphs).hvo; Debug.Assert(paraHvo != 0); int iBook, iSection; iBook = ((ITeView)Control).LocationTracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Anchor); iSection = ((ITeView)Control).LocationTracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Anchor); StTxtPara para = new StTxtPara(m_cache, paraHvo); // Find the ORC and delete it from the paragraph ITsString contents = para.Contents.UnderlyingTsString; int startOfRun = 0; for(int i = 0; i < contents.RunCount; i++) { string str = contents.get_Properties(i).GetStrPropValue( (int)FwTextPropType.ktptObjData); if (str != null) { Guid guid = MiscUtils.GetGuidFromObjData(str.Substring(1)); int hvo = m_cache.GetIdFromGuid(guid); if (hvo == hvoPic) { ITsStrBldr bldr = contents.GetBldr(); startOfRun = contents.get_MinOfRun(i); bldr.Replace(startOfRun, contents.get_LimOfRun(i), string.Empty, null); para.Contents.UnderlyingTsString = bldr.GetString(); break; } } } // TODO (TE-4967): do a prop change that actually works. // m_cache.PropChanged(null, PropChangeType.kpctNotifyAll, // para.Hvo, (int)StTxtPara.StTxtParaTags.kflidContents, // startOfRun, 0, 1); if (FwApp.App != null) FwApp.App.RefreshAllViews(m_cache); m_cache.DeleteObject(hvoPic); // TODO (TimS): This code to create a selection in the paragraph the picture was // in probably won't work when deleting a picture in back translation // material (which isn't possible to insert yet). ((ITeView)Control).LocationTracker.SetBookAndSection(helper, SelectionHelper.SelLimitType.Anchor, iBook, iSection); helper.RemoveLevel((int)StTxtPara.StTxtParaTags.kflidContents); if (Callbacks != null && Callbacks.EditedRootBox != null) // may not exist in tests. { try { MakeSimpleTextSelection(helper.LevelInfo, (int)StTxtPara.StTxtParaTags.kflidContents, startOfRun); } catch { // If we couldn't make the selection in the contents, it's probably because // we are in a user prompt, so try that instead. MakeSimpleTextSelection(helper.LevelInfo, (int)SimpleRootSite.kTagUserPrompt, startOfRun); } Callbacks.EditedRootBox.Site.ScrollSelectionIntoView(Callbacks.EditedRootBox.Selection, VwScrollSelOpts.kssoNearTop); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Inserts a footnote at the given selection /// </summary> /// <param name="selHelper">Current selection information</param> /// <param name="styleName">style name for created footnote</param> /// <param name="iFootnote">out: If selHelper is in vernacular para, the ihvo of the /// footnote just inserted. If selHelper is in back trans, the ihvo of the footnote /// corresponding to the ref ORC just inserted in the BT, or -1 no corresponding</param> /// <returns>The created/corresponding footnote</returns> /// ------------------------------------------------------------------------------------ public virtual ScrFootnote InsertFootnote(SelectionHelper selHelper, string styleName, out int iFootnote) { CheckDisposed(); // Get any selected text. ITsString tssSelected; IVwSelection vwsel = selHelper.Selection; if (IsSelectionInOneEditableProp(vwsel)) vwsel.GetSelectionString(out tssSelected, string.Empty); else tssSelected = StringUtils.MakeTss(string.Empty, m_cache.DefaultVernWs); int hvoObj; ITsString tssPara; int propTag; int ws; selHelper.ReduceToIp(SelectionHelper.SelLimitType.Bottom, false, false); int ichSel = GetSelectionInfo(selHelper, out hvoObj, out propTag, out tssPara, out ws); if (propTag == (int)StTxtPara.StTxtParaTags.kflidContents) ws = Cache.DefaultVernWs; // get book info IScrBook book = GetCurrentBook(m_cache); // get paragraph info int paraHvo = selHelper.GetLevelInfoForTag((int)StText.StTextTags.kflidParagraphs).hvo; StTxtPara para = new StTxtPara(m_cache, paraHvo); if (tssSelected.Length > 0) { tssSelected = StringUtils.RemoveORCsAndStylesFromTSS(tssSelected, new List<string>(new string[] {ScrStyleNames.ChapterNumber, ScrStyleNames.VerseNumber}), false, m_cache.LanguageWritingSystemFactoryAccessor); if (tssSelected.Length > 0) { ITsStrBldr bldr = tssSelected.GetBldr(); bldr.SetStrPropValue(0, bldr.Length, (int) FwTextPropType.ktptNamedStyle, ScrStyleNames.ReferencedText); bldr.ReplaceRgch(bldr.Length, bldr.Length, " ", 1, StyleUtils.CharStyleTextProps(null, ws)); tssSelected = bldr.GetString(); } } ScrFootnote footnote = null; string undo; string redo; if (styleName == ScrStyleNames.CrossRefFootnoteParagraph) TeResourceHelper.MakeUndoRedoLabels("kstidInsertCrossReference", out undo, out redo); else TeResourceHelper.MakeUndoRedoLabels("kstidInsertFootnote", out undo, out redo); using (UndoTaskHelper undoTaskHelper = new UndoTaskHelper(Callbacks.EditedRootBox.Site, undo, redo, true)) { try { if (propTag == (int)StTxtPara.StTxtParaTags.kflidContents) { // Inserting footnote into the vernacular paragraph iFootnote = FindFootnotePosition(book, selHelper); ITsStrBldr tsStrBldr = para.Contents.UnderlyingTsString.GetBldr(); // create the footnote and insert its marker into the paragraph's string // builder. footnote = ScrFootnote.InsertFootnoteAt(book, styleName, iFootnote, tsStrBldr, ichSel); // BEFORE we insert the ORC in the paragraph, we need to insert an empty // paragraph into the new StFootnote, because the para style is needed to // determine the footnote marker type. StTxtPara footnotePara = new StTxtPara(); footnote.ParagraphsOS.Append(footnotePara); // If we wait for this to be created by the VC, its creation won't be part of the // Undo task, and we won't be able to Undo creating the footnote, because the paragraph // will own something that Undo doesn't know to delete (TE-7988). footnotePara.GetOrCreateBT(); ITsPropsBldr propsBldr = TsPropsBldrClass.Create(); propsBldr.SetStrPropValue((int)FwTextPropType.ktptNamedStyle, styleName); footnotePara.StyleRules = propsBldr.GetTextProps(); // Record information, as if we were typing the footnote caller, that allows // segment boundaries to be adjusted properly. OnAboutToEdit(); // update the paragraph contents to include the footnote marker para.Contents.UnderlyingTsString = tsStrBldr.GetString(); // Finish off any necessary annotation adjustments. m_annotationAdjuster.OnFinishedEdit(); // Insert the selected text (or an empty run) into the footnote paragraph. footnotePara.Contents.UnderlyingTsString = tssSelected; // Do a prop change to get the footnote updated in all views m_cache.PropChanged(null, PropChangeType.kpctNotifyAll, book.Hvo, (int)ScrBook.ScrBookTags.kflidFootnotes, iFootnote, 1, 0); } else { // Inserting footnote reference ORC into a back translation ICmTranslation btParaTrans = para.GetOrCreateBT(); ITsString btTss = btParaTrans.Translation.GetAlternative(ws).UnderlyingTsString; footnote = FindVernParaFootnote(ichSel, btTss, para); if (footnote != null) { // Insert footnote reference ORC into back translation paragraph. ITsStrBldr tssBldr = btTss.GetBldr(); //if reference to footnote already somewhere else in para, delete it first int ichDel = StTxtPara.DeleteBtFootnoteMarker(tssBldr, footnote.Guid); if (ichDel >= 0 && ichSel > ichDel) ichSel -= footnote.FootnoteMarker.Length; footnote.InsertRefORCIntoTrans(tssBldr, ichSel, ws); btParaTrans.Translation.SetAlternative(tssBldr.GetString(), ws); iFootnote = footnote.IndexInOwner; if (tssSelected.Length > 0) { ICmTranslation btFootnoteTrans = ((StTxtPara) footnote.ParagraphsOS[0]).GetOrCreateBT(); ITsString btFootnoteTss = btFootnoteTrans.Translation.GetAlternative(ws).UnderlyingTsString; // Insert any selected text into this back translation for the footnote paragraph. btFootnoteTrans.Translation.SetAlternative(tssSelected, ws); } } else { iFootnote = -1; MiscUtils.ErrorBeep(); // No footnote reference ORC inserted } } } catch { undoTaskHelper.EndUndoTask = false; throw; // rethrow the original exception } } return footnote; }
/// ------------------------------------------------------------------------------------ /// <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> /// Get the index of the current book in the book filter, or -1 if there is no /// current book (e.g. no selection or empty view). /// </summary> /// <param name="selHelper">The selection helper.</param> /// <param name="selLimitType">Which end of the selection</param> /// <returns> /// Index of the current book, or -1 if there is no current book. /// </returns> /// <remarks>The returned value is suitable for making a selection.</remarks> /// ------------------------------------------------------------------------------------ public virtual int GetBookIndex(SelectionHelper selHelper, SelectionHelper.SelLimitType selLimitType) { if (selHelper == null) return -1; SelLevInfo levInfo; if (selHelper.GetLevelInfoForTag(BookTag, selLimitType, out levInfo)) return levInfo.ihvo; return -1; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Common utility for the CurrentRef* properties /// </summary> /// <param name="selhelper">The selection helper representing the current selection /// (or sometimes the current reduced to an IP)</param> /// <param name="selLimit">The limit of the selection (anchor, end, etc.) to get the /// reference of</param> /// <returns>the start and end reference of the given selection, as an array of two /// ScrReference objects</returns> /// ------------------------------------------------------------------------------------ protected ScrReference[] GetCurrentRefRange(SelectionHelper selhelper, SelectionHelper.SelLimitType selLimit) { if (m_cache == null || selhelper == null || BookFilter == null) return new ScrReference[] {ScrReference.Empty, ScrReference.Empty}; ILocationTracker tracker = ((ITeView)Control).LocationTracker; // If there is a current book... BCVRef start = new BCVRef(); BCVRef end = new BCVRef(); int iBook = tracker.GetBookIndex(selhelper, selLimit); if (iBook >= 0 && BookFilter.BookCount > 0) { try { IScrBook book = BookFilter.GetBook(iBook); // if there is not a current section, then use the book and chapter/verse of 0. IScrSection section = tracker.GetSection(selhelper, selLimit); if (section != null) { // If there is a section... int paraHvo = selhelper.GetLevelInfoForTag(StTextTags.kflidParagraphs, selLimit).hvo; IScrTxtPara scrPara = m_cache.ServiceLocator.GetInstance<IScrTxtParaRepository>().GetObject(paraHvo); // Get the ich at either the beginning or the end of the selection, // as specified with limit. (NB that this is relative to the property, not the whole paragraph.) int ich; // Get the TsString, whether in vern or BT ITsString tss; int refWs; SelLevInfo segInfo; int textPropTag = 0; if (selhelper.GetLevelInfoForTag(StTxtParaTags.kflidSegments, selLimit, out segInfo)) { // selection is in a segmented BT segment. Figure the reference based on where the segment is // in the underlying paragraph. tss = scrPara.Contents; // for check below on range of ich. ISegment seg = m_repoSegment.GetObject(segInfo.hvo); ich = seg.BeginOffset; Debug.Assert(seg.Paragraph == scrPara); refWs = -1; // ich is in the paragraph itself, not some CmTranslation } else { textPropTag = selhelper.GetTextPropId(selLimit); if (textPropTag == SimpleRootSite.kTagUserPrompt) { ich = 0; tss = null; } else { ich = selhelper.GetIch(selLimit); tss = selhelper.GetTss(selLimit); // Get the TsString, whether in vern or BT if (ich < 0 || tss == null) { HandleFootnoteAnchorIconSelected(selhelper.Selection, (hvo, flid, wsDummy, ichAnchor) => { SelectionHelper helperTemp = new SelectionHelper(selhelper); ich = helperTemp.IchAnchor = helperTemp.IchEnd = ichAnchor; helperTemp.SetSelection(false, false); tss = helperTemp.GetTss(selLimit); }); } } refWs = GetCurrentBtWs(selLimit); // figures out whether it's in a CmTranslation or the para itself. } Debug.Assert(tss == null || ich <= tss.Length); if ((tss != null && ich <= tss.Length) || textPropTag == SimpleRootSite.kTagUserPrompt) { scrPara.GetRefsAtPosition(refWs, ich, true, out start, out end); // If the chapter number is 0, then use the chapter from the section reference if (end.Chapter == 0) end.Chapter = BCVRef.GetChapterFromBcv(section.VerseRefMin); if (start.Chapter == 0) start.Chapter = BCVRef.GetChapterFromBcv(section.VerseRefMin); } } else { // either it didn't find a level or it didn't find an index. Either way, // it couldn't find a section. start.Book = end.Book = book.CanonicalNum; } } catch { // Bummer man, something went wrong... don't sweat it though, it happens... // This can occur if you are in the introduction or other location that lacks // relevant information or other necessary stuff. } } return new ScrReference[] {new ScrReference(start, m_scr.Versification), new ScrReference(end, m_scr.Versification)}; ; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Deletes the picture specified by the hvo. /// </summary> /// <param name="helper">Selection containing the picture.</param> /// <param name="hvoPic">hvo of picture.</param> /// ------------------------------------------------------------------------------------ protected void DeletePicture(SelectionHelper helper, int hvoPic) { SelLevInfo info = helper.GetLevelInfoForTag(StTextTags.kflidParagraphs); int paraHvo = info.hvo; Debug.Assert(paraHvo != 0); int iPara = info.ihvo; IStTxtPara para = m_repoScrTxtPara.GetObject(paraHvo); int tag, hvo; bool fGotSelectedScrElement = GetSelectedScrElement(out tag, out hvo); Debug.Assert(fGotSelectedScrElement); int iBook = ((ITeView)Control).LocationTracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Anchor); int iSection = ((ITeView)Control).LocationTracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Anchor); int ichOrc = -1; int iSegment = -1; if (IsBackTranslation) { ICmPictureRepository repo = Cache.ServiceLocator.GetInstance<ICmPictureRepository>(); ISegment segment; if (helper.GetLevelInfoForTag(StTxtParaTags.kflidSegments, out info)) { segment = m_cache.ServiceLocator.GetInstance<ISegmentRepository>().GetObject(info.hvo); iSegment = segment.IndexInOwner; } else segment = para.GetSegmentForOffsetInFreeTranslation(helper.GetIch(SelectionHelper.SelLimitType.Top), RootVcDefaultWritingSystem); ITsString contents = segment.FreeTranslation.get_String(RootVcDefaultWritingSystem); Guid guidPic = Cache.ServiceLocator.GetInstance<ICmPictureRepository>().GetObject(hvoPic).Guid; for (int i = 0; i < contents.RunCount; i++) { string str = contents.get_Properties(i).GetStrPropValue((int)FwTextPropType.ktptObjData); if (str != null && MiscUtils.GetGuidFromObjData(str.Substring(1)) == guidPic) { ichOrc = contents.get_MinOfRun(i); int limOfRun = contents.get_LimOfRun(i); ITsStrBldr bldr = contents.GetBldr(); bldr.Replace(ichOrc, limOfRun, string.Empty, null); segment.FreeTranslation.set_String(RootVcDefaultWritingSystem, bldr.GetString()); if (ContentType == StVc.ContentTypes.kctSimpleBT) ichOrc += para.GetOffsetInFreeTranslationForStartOfSegment(segment, RootVcDefaultWritingSystem); break; } } } else ichOrc = para.DeletePicture(hvoPic); Debug.Assert(ichOrc >= 0); // TODO (TE-4967): do a prop change that actually works. // m_cache.DomainDataByFlid.PropChanged(null, (int)PropChangeType.kpctNotifyAll, // para.Hvo, StTxtParaTags.kflidContents, // startOfRun, 0, 1); if (m_app != null) m_app.RefreshAllViews(); SelectRangeOfChars(iBook, iSection, tag, iPara, iSegment, ichOrc, ichOrc, true, true, true, VwScrollSelOpts.kssoDefault); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Low-level implementation of insert verse number. /// </summary> /// <param name="selHelper">the given SelectionHelper</param> /// ------------------------------------------------------------------------------------ public void InsertVerseNumber(SelectionHelper selHelper) { CheckDisposed(); Debug.Assert(selHelper != null); Debug.Assert(!selHelper.IsRange || IsSelectionInPrompt(selHelper)); // Get the details about the current selection int ichSelOrig; //the character offset of the selection in the ITsString int hvoObj; //the id of the object the selection is in (StTxtPara or CmTranslation) int propTag; //property tag of object ITsString tssSel; //ITsString containing the selection int wsAlt; //the WS of the multiString alt, if selection is in a back translation ichSelOrig = GetSelectionInfo(selHelper, out hvoObj, out propTag, out tssSel, out wsAlt); // The current run is a chapter number and IP is either at the beginning of the line or // in the middle of the chapter number, we need to jump past it to insert the verse number // otherwise it will insert it before the chapter number or in the chapter number. int iRun = tssSel.get_RunAt(ichSelOrig); if (tssSel.Style(iRun) == ScrStyleNames.ChapterNumber && (ichSelOrig == 0 || ichSelOrig > tssSel.get_MinOfRun(iRun))) ichSelOrig = tssSel.get_LimOfRun(iRun); // Adjust the insertion position to the beginning of a word - not in the middle // (may move to an existing verse number too) int ichWord = tssSel.FindWordBoundary(ichSelOrig, UnicodeCharProps, ScrStyleNames.ChapterAndVerse); // TomB and MarkB have decided we won't do this, at least for now // // If the start of the Bt does not match the vernacular, adjust it if required. // if (ichWord > 0) // cInsDel = SetVerseAtStartOfBtIfNeeded(); // ichWord += cInsDel; //adjust // some key variables set by Update or Insert methods, etc string sVerseNumIns = null; // will hold the verse number string we inserted; could be // a simple number, a verse bridge, or the end number added to a bridge string sChapterNumIns = null; // will hold chapter number string inserted or null if none int ichLimIns = -1; //will hold the end of the new chapter/verse numbers we update or insert // Is ichWord in or next to a verse number? (if so, get its ich range) bool fCheckForChapter = (wsAlt != 0); //check for chapter in BT only int ichMin; // min of the verse number run, if we are on one int ichLim; // lim of the verse number run, if we are on one bool fFoundExistingRef = InReference(tssSel, ichWord, fCheckForChapter, out ichMin, out ichLim); SelLevInfo paraInfo = selHelper.GetLevelInfoForTag(StTextTags.kflidParagraphs); IScrTxtPara para = m_cache.ServiceLocator.GetInstance<IScrTxtParaRepository>().GetObject(paraInfo.hvo); // If we moved the selection forward (over spaces or punctuation) to an // existing verse number ... if (fFoundExistingRef && (ichSelOrig < ichWord)) { //Attempt to insert a verse number at the IP, if one is missing there. // if selection is in vernacular... if (propTag == StTxtParaTags.kflidContents) { // Insert missing verse number in vernacular para.InsertMissingVerseNumberInVern(ichSelOrig, ichWord, out sVerseNumIns, out ichLimIns); } } // if a verse number was not inserted, sVerseNumIns is null // If no verse number inserted yet... if (sVerseNumIns == null) { if (fFoundExistingRef) { //We must update the existing verse number at ichWord // is selection in vern or BT? if (propTag == StTxtParaTags.kflidContents) { // Update verse number in vernacular para.UpdateExistingVerseNumberInVern(ichMin, ichLim, out sVerseNumIns, out ichLimIns); } else { //Update verse number in back translation para.UpdateExistingVerseNumberInBt(wsAlt, ichMin, ichLim, out sVerseNumIns, out sChapterNumIns, out ichLimIns); } } else { // We're NOT on an existing verse number, so insert the next appropriate one. // is selection in vern or BT? if (propTag == StTxtParaTags.kflidContents) { para.InsertNextVerseNumberInVern(ichWord, out sVerseNumIns, out ichLimIns); } else { para.InsertNextVerseNumberInBt(wsAlt, ichWord, out sVerseNumIns, out sChapterNumIns, out ichLimIns); selHelper.SetTextPropId(SelectionHelper.SelLimitType.Anchor, CmTranslationTags.kflidTranslation); selHelper.SetTextPropId(SelectionHelper.SelLimitType.End, CmTranslationTags.kflidTranslation); } } } if (sVerseNumIns == null) { MiscUtils.ErrorBeep(); // No verse number inserted or updated return; } // set new IP behind the verse number selHelper.IchAnchor = ichLimIns; selHelper.IchEnd = ichLimIns; selHelper.AssocPrev = true; selHelper.SetIPAfterUOW(); // Remove any duplicate chapter/verse numbers following the new verse number. para.RemoveDuplicateVerseNumbers(wsAlt, sChapterNumIns, sVerseNumIns, ichLimIns); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Selects the paragraph in the DraftView or FootnoteView associated with the style. /// </summary> /// <param name="origSelection">selection user originally made</param> /// <param name="view">The DraftView or FootnoteView</param> /// ------------------------------------------------------------------------------------ private void SelectAssociatedPara(SelectionHelper origSelection, IVwRootSite view) { SelLevInfo paraInfoAnchor = origSelection.GetLevelInfoForTag( StTextTags.kflidParagraphs, SelectionHelper.SelLimitType.Top); SelLevInfo paraInfoEnd = origSelection.GetLevelInfoForTag( StTextTags.kflidParagraphs, SelectionHelper.SelLimitType.Bottom); if (paraInfoAnchor.hvo != m_prevPara1Hvo || paraInfoEnd.hvo != m_prevPara2Hvo) { // The selection changed paragraphs, so update the selection in the // DraftView or FootnoteView IStTxtPara para1 = m_fdoCache.ServiceLocator.GetInstance<IStTxtParaRepository>().GetObject(paraInfoAnchor.hvo); IStTxtPara para2 = m_fdoCache.ServiceLocator.GetInstance<IStTxtParaRepository>().GetObject(paraInfoEnd.hvo); SelectionHelper helper = MakeSelection(para1, para2, view); IVwSelection sel = helper.SetSelection(view, true, false); // If the selection fails then try selecting the user prompt. if (sel == null) { AdjustSelectionForPrompt(helper, para1, para2); sel = helper.SetSelection(view, true, false); } Debug.Assert(sel != null || ((SimpleRootSite)view).ReadOnlyView); m_prevPara1Hvo = paraInfoAnchor.hvo; m_prevPara2Hvo = paraInfoEnd.hvo; } }
/// ------------------------------------------------------------------------------------ /// <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> /// Gets the current section, or null if we're not in a section (e.g. the IP is in a /// title). /// </summary> /// <param name="selHelper">The selection helper.</param> /// <param name="selLimitType">Which end of the selection</param> /// <returns>The section or null if we're not in a section.</returns> /// ------------------------------------------------------------------------------------ public virtual IScrSection GetSection(SelectionHelper selHelper, SelectionHelper.SelLimitType selLimitType) { if (selHelper == null) return null; SelLevInfo levInfo; if (selHelper.GetLevelInfoForTag(ScrBookTags.kflidSections, selLimitType, out levInfo)) { IScrSection section; if (m_cache.ServiceLocator.GetInstance<IScrSectionRepository>().TryGetObject(levInfo.hvo, out section)) return section; } return null; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the index of the section (relative to RootBox), or -1 if we're not in a section /// (e.g. the IP is in a title). /// </summary> /// <param name="selHelper">The selection helper.</param> /// <param name="selLimitType">Which end of the selection</param> /// <returns> /// Index of the section, or -1 if we're not in a section. /// </returns> /// <remarks>The returned value is suitable for making a selection.</remarks> /// ------------------------------------------------------------------------------------ public virtual int GetSectionIndexInView(SelectionHelper selHelper, SelectionHelper.SelLimitType selLimitType) { if (selHelper == null) return -1; SelLevInfo levInfo; if (selHelper.GetLevelInfoForTag(ScrBookTags.kflidSections, selLimitType, out levInfo)) { return levInfo.ihvo; } return -1; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets the current book, or null if there is no current book (e.g. no selection or /// empty view). /// </summary> /// <param name="selHelper">The selection helper.</param> /// <param name="selLimitType">Which end of the selection</param> /// <returns>The book, or null if there isn't a current book.</returns> /// ------------------------------------------------------------------------------------ public virtual IScrBook GetBook(SelectionHelper selHelper, SelectionHelper.SelLimitType selLimitType) { if (selHelper == null) return null; SelLevInfo levInfo; if (selHelper.GetLevelInfoForTag(BookTag, selLimitType, out levInfo)) return m_cache.ServiceLocator.GetInstance<IScrBookRepository>().GetObject(levInfo.hvo); return null; }
/// ------------------------------------------------------------------------------------ /// <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> /// Inserts a footnote at the given selection /// </summary> /// <param name="selHelper">Current selection information</param> /// <param name="styleName">style name for created footnote</param> /// <param name="iFootnote">out: If selHelper is in vernacular para, the ihvo of the /// footnote just inserted. If selHelper is in back trans, the ihvo of the footnote /// corresponding to the ref ORC just inserted in the BT, or -1 no corresponding</param> /// <returns>The created/corresponding footnote</returns> /// ------------------------------------------------------------------------------------ public virtual IStFootnote InsertFootnote(SelectionHelper selHelper, string styleName, out int iFootnote) { CheckDisposed(); // Get any selected text. ITsString tssSelectedText; IVwSelection vwsel = selHelper.Selection; if (!IsSelectionInUserPrompt && IsSelectionInOneEditableProp(vwsel)) vwsel.GetSelectionString(out tssSelectedText, string.Empty); else tssSelectedText = TsStringUtils.MakeTss(string.Empty, m_cache.DefaultVernWs); int hvoObj; ITsString tssSel; // This is either the vernacular or the BT, depending on the selection location. int propTag; int ws; selHelper.ReduceToIp(SelectionHelper.SelLimitType.Bottom, false, false); int ichSel = GetSelectionInfo(selHelper, out hvoObj, out propTag, out tssSel, out ws); if (propTag == StTxtParaTags.kflidContents) ws = Cache.DefaultVernWs; // Make sure the selection is updated with the new ich position in case it was wrong // (e.g. If the selection is in a user prompt) (TE-8919) selHelper.IchAnchor = selHelper.IchEnd = ichSel; // get book info IScrBook book = GetCurrentBook(m_cache); // get paragraph info int paraHvo = selHelper.GetLevelInfoForTag(StTextTags.kflidParagraphs).hvo; IScrTxtPara para = m_repoScrTxtPara.GetObject(paraHvo); tssSelectedText = TsStringUtils.GetCleanTsString(tssSelectedText, ScrStyleNames.ChapterAndVerse); Debug.Assert(tssSelectedText != null); if (tssSelectedText.Length > 0) { ITsStrBldr bldr = tssSelectedText.GetBldr(); bldr.SetStrPropValue(0, bldr.Length, (int)FwTextPropType.ktptNamedStyle, ScrStyleNames.ReferencedText); bldr.ReplaceRgch(bldr.Length, bldr.Length, " ", 1, StyleUtils.CharStyleTextProps(null, ws)); tssSelectedText = bldr.GetString(); } //Cache.ActionHandlerAccessor.AddAction(new UndoWithRefreshAction()); IScrFootnote footnote = null; iFootnote = -1; if (propTag == StTxtParaTags.kflidContents) { // Inserting footnote into the vernacular paragraph iFootnote = FindFootnotePosition(book, selHelper); ITsStrBldr tsStrBldr = para.Contents.GetBldr(); // create the footnote and insert its marker into the paragraph's string // builder. footnote = book.InsertFootnoteAt(iFootnote, tsStrBldr, ichSel); // BEFORE we insert the ORC in the paragraph, we need to insert an empty // paragraph into the new StFootnote, because the para style is needed to // determine the footnote marker type. IStTxtPara footnotePara = footnote.AddNewTextPara(styleName); // update the paragraph contents to include the footnote marker para.Contents = tsStrBldr.GetString(); // Insert the selected text (or an empty run) into the footnote paragraph. footnotePara.Contents = tssSelectedText; } else { IMultiString bt = null; if (propTag == SegmentTags.kflidFreeTranslation) { // Inserting footnote reference ORC into a segment free translation ISegment segment = m_repoSegment.GetObject(selHelper.GetLevelInfoForTag(StTxtParaTags.kflidSegments).hvo); bt = segment.FreeTranslation; footnote = FindVernParaFootnote(segment, ws); } else if (propTag == CmTranslationTags.kflidTranslation) { // Inserting footnote reference ORC into a back translation footnote = FindVernParaFootnote(ichSel, tssSel, para); bt = para.GetBT().Translation; } if (footnote != null) { // Insert footnote reference ORC into back translation paragraph. ITsStrBldr tssBldr = tssSel.GetBldr(); //if reference to footnote already somewhere else in para, delete it first int ichDel = TsStringUtils.DeleteOrcFromBuilder(tssBldr, footnote.Guid); if (ichDel >= 0 && ichSel > ichDel) ichSel--; TsStringUtils.InsertOrcIntoPara(footnote.Guid, FwObjDataTypes.kodtNameGuidHot, tssBldr, ichSel, ichSel, ws); bt.set_String(ws, tssBldr.GetString()); iFootnote = footnote.IndexInOwner; if (tssSelectedText.Length > 0) { ICmTranslation btFootnoteTrans = ((IStTxtPara)footnote.ParagraphsOS[0]).GetBT(); ITsString btFootnoteTss = btFootnoteTrans.Translation.get_String(ws); // Insert any selected text into this back translation for the footnote paragraph. btFootnoteTrans.Translation.set_String(ws, tssSelectedText); } } } if (footnote == null) MiscUtils.ErrorBeep(); // No footnote reference ORC inserted else { // Update the selection in the view that the footnote was inserted. selHelper.UpdateScrollLocation(); // Make sure this is up-to-date selHelper = new SelectionHelper(selHelper); // Get a new copy, so any subsequent changes won't affect us. selHelper.IchAnchor++; selHelper.AssocPrev = false; // Associate away from the newly inserted marker to avoid shifting scroll position by a couple pixels selHelper.IchEnd = selHelper.IchAnchor; Callbacks.RequestVisibleSelectionAtEndOfUow(selHelper); } return footnote; }
/// ------------------------------------------------------------------------------------ /// <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> /// 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(); } } } }