/// ------------------------------------------------------------------------------------ /// <summary> /// Set the IP to the end of the section. Check for vernacular or BT. /// </summary> /// ------------------------------------------------------------------------------------ private void SetIpAtEndOfPara(int bookIndex, int sectionIndex, int paraIndex, StTxtPara para) { int paraLength; if (IsBackTranslation) { ICmTranslation trans = para.GetOrCreateBT(); paraLength = trans.Translation.GetAlternative(ViewConstructorWS).UnderlyingTsString.Length; } else paraLength = para.Contents.Length; SetInsertionPoint(bookIndex, sectionIndex, paraIndex, paraLength, true); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Append a run of text to a back translation of a paragraph. /// </summary> /// <param name="para">given paragraph</param> /// <param name="ws">given writing system for the back translation</param> /// <param name="runText">given text to append to back translation</param> /// ------------------------------------------------------------------------------------ private void AppendRunToBt(StTxtPara para, int ws, string runText) { ICmTranslation trans = para.GetOrCreateBT(); ITsStrBldr bldr = trans.Translation.GetAlternative(ws).UnderlyingTsString.GetBldr(); ITsTextProps ttp = StyleUtils.CharStyleTextProps(null, ws); int bldrLength = bldr.Length; bldr.ReplaceRgch(bldrLength, bldrLength, runText, runText.Length, ttp); trans.Translation.SetAlternative(bldr.GetString(), ws); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Create a footnote reference marker (ref orc) /// </summary> /// <param name="footnote">given footnote</param> /// <param name="para">paragraph owning the translation to insert footnote marker into</param> /// <param name="ws">given writing system for the back translation</param> /// <param name="ichPos">The 0-based character offset into the translation</param> /// ------------------------------------------------------------------------------------ protected void InsertTestBtFootnote(StFootnote footnote, StTxtPara para, int ws, int ichPos) { ICmTranslation trans = para.GetOrCreateBT(); ITsStrBldr bldr = trans.Translation.GetAlternative(ws).UnderlyingTsString.GetBldr(); footnote.InsertRefORCIntoTrans(bldr, ichPos, ws); trans.Translation.SetAlternative(bldr.GetString(), ws); }
/// ------------------------------------------------------------------------------------ /// <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; }
public static void UpdateMainTransFromSegmented(StTxtPara para, int[] wss) { if (!para.IsValidObject()) return; // in merge, paragraph may be modified then deleted. FdoCache cache = para.Cache; BtConverter.EnsureMainParaSegments(para, wss[0]); ISilDataAccess sda = cache.MainCacheAccessor; List<int> segments = para.Segments; int kflidFT = StTxtPara.SegmentFreeTranslationFlid(cache); ITsString tssContents = para.Contents.UnderlyingTsString; IScripture scr = para.Cache.LangProject.TranslatedScriptureOA; ICmTranslation originalBT = para.GetBT(); // Can be null string sUnfinished = BackTranslationStatus.Unfinished.ToString(); foreach (int ws in wss) { ITsStrBldr bldr = TsStrBldrClass.Create(); bool wantNextSpace = false; // suppresses space before the first thing we add. bool haveBtText = false; // Text that isn't segment label text foreach (int hvoSeg in segments) { // If it's a label, insert it directly. Suppress following space. int beginOffset = sda.get_IntProp(hvoSeg, (int) CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginOffset); int endOffset = sda.get_IntProp(hvoSeg, (int) CmBaseAnnotation.CmBaseAnnotationTags.kflidEndOffset); ITsString tssFt; // Whether we want to insert a space before the current segment is determined by the previous one. // Save that value so we can set wantSpace appropriately for the following one. bool wantSpace = wantNextSpace; if (SegmentBreaker.HasLabelText(tssContents, beginOffset, endOffset)) { tssFt = (new CmBaseAnnotation(cache, hvoSeg)).TextAnnotated; tssFt = scr.ConvertCVNumbersInStringForBT(CorrectFootnotes(tssFt), ws); wantNextSpace = false; } else { int hvoFt = sda.get_ObjectProp(hvoSeg, kflidFT); tssFt = sda.get_MultiStringAlt(hvoFt, (int) CmAnnotation.CmAnnotationTags.kflidComment, ws); haveBtText |= (tssFt.Length > 0); wantNextSpace = EndsWithNonSpace(tssFt); } if (tssFt.Length > 0) { if (wantSpace) { // The preceding segment should typically be followed by a space. if (!StartsWithSpaceOrOrc(tssFt)) bldr.Replace(bldr.Length, bldr.Length, " ", null); } bldr.ReplaceTsString(bldr.Length, bldr.Length, tssFt); } } // If the back translation doesn't have text, we don't want to create verse // segment labels. This prevents the problem where the book thinks it has a // back translation because of automatically generated verse labels (TE-8283). if (!haveBtText) { // This check might not be needed, but it shouldn't hurt anything. if (originalBT != null) { if (originalBT.Translation.GetAlternative(ws).Length > 0) { string origStatus = originalBT.Status.GetAlternative(ws); if (!String.IsNullOrEmpty(origStatus) && origStatus != sUnfinished) originalBT.Status.SetAlternative(sUnfinished, ws); } } continue; } ITsString newFt = bldr.GetString(); ICmTranslation trans; if (newFt.Length == 0) { trans = para.GetBT(); if (trans == null) return; // don't bother creating one to store an empty translation! } else { trans = para.GetOrCreateBT(); } // Don't write unless it changed...PropChanged can be expensive. if (!trans.Translation.GetAlternative(ws).UnderlyingTsString.Equals(newFt)) { trans.Translation.SetAlternative(newFt, ws); trans.Status.SetAlternative(sUnfinished, ws); } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the hvo of the (for now, first) translation of a paragraph /// </summary> /// <param name="hvoPara"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ protected int GetTranslationForPara(int hvoPara) { StTxtPara para = new StTxtPara(Cache, hvoPara); return para.GetOrCreateBT().Hvo; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Adds content to the book of Matthew: one intro section and one Scripture section. /// Both sections will have vernacular and back translation text for the headings /// and content. /// </summary> /// ------------------------------------------------------------------------------------ private void AddDataToMatthew() { // Add vernacular text. IScrSection introSection = m_scrInMemoryCache.AddIntroSectionToMockedBook(m_book.Hvo); m_scrInMemoryCache.AddSectionHeadParaToSection(introSection.Hvo, "Heading 1", ScrStyleNames.IntroSectionHead); StTxtPara introPara = m_scrInMemoryCache.AddParaToMockedSectionContent(introSection.Hvo, ScrStyleNames.IntroParagraph); m_scrInMemoryCache.AddRunToMockedPara(introPara, "Intro text. We need lots of stuff here so that our footnote tests will work.", null); introSection.AdjustReferences(); IScrSection scrSection = m_scrInMemoryCache.AddSectionToMockedBook(m_book.Hvo); m_scrInMemoryCache.AddSectionHeadParaToSection(scrSection.Hvo, "Heading 2", ScrStyleNames.SectionHead); StTxtPara scrPara = m_scrInMemoryCache.AddParaToMockedSectionContent(scrSection.Hvo, ScrStyleNames.NormalParagraph); m_scrInMemoryCache.AddRunToMockedPara(scrPara, "1", ScrStyleNames.ChapterNumber); m_scrInMemoryCache.AddRunToMockedPara(scrPara, "1", ScrStyleNames.VerseNumber); m_scrInMemoryCache.AddRunToMockedPara(scrPara, "Verse one. ", null); m_scrInMemoryCache.AddRunToMockedPara(scrPara, "2", ScrStyleNames.VerseNumber); m_scrInMemoryCache.AddRunToMockedPara(scrPara, "Verse two.", null); scrSection.AdjustReferences(); // Add back translation text. int wsAnal = m_scrInMemoryCache.Cache.DefaultAnalWs; StTxtPara heading1Para = (StTxtPara)introSection.HeadingOA.ParagraphsOS[0]; CmTranslation trans = (CmTranslation)heading1Para.GetOrCreateBT(); m_scrInMemoryCache.AddRunToMockedTrans(trans, wsAnal, "BT Heading 1", null); trans = (CmTranslation)introPara.GetOrCreateBT(); m_scrInMemoryCache.AddRunToMockedTrans(trans, wsAnal, "BT Intro text", null); StTxtPara scrHeadingPara = new StTxtPara(Cache, scrSection.HeadingOA.ParagraphsOS.HvoArray[0]); trans = (CmTranslation)scrHeadingPara.GetOrCreateBT(); m_scrInMemoryCache.AddRunToMockedTrans(trans, wsAnal, "BT Heading 2", null); trans = (CmTranslation)scrPara.GetOrCreateBT(); m_scrInMemoryCache.AddRunToMockedTrans(trans, wsAnal, "1", ScrStyleNames.ChapterNumber); m_scrInMemoryCache.AddRunToMockedTrans(trans, wsAnal, "1", ScrStyleNames.VerseNumber); m_scrInMemoryCache.AddRunToMockedTrans(trans, wsAnal, "BT Verse one", null); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Creates a new StFootnote owned by the given book created from the given string /// representation (Created from GetTextRepresentation()) /// </summary> /// <param name="owner">The object that owns the sequence of footnotes into which the /// new footnote is to be inserted</param> /// <param name="flid">The field id of the property in which the footnotes are owned /// </param> /// <param name="sTextRepOfFootnote">The given string representation of a footnote /// </param> /// <param name="footnoteIndex">0-based index where the footnote will be inserted</param> /// <param name="footnoteMarkerStyleName">style name for footnote markers</param> /// <returns>An StFootnote with the properties set to the properties in the /// given string representation</returns> /// ------------------------------------------------------------------------------------ public static StFootnote CreateFromStringRep(CmObject owner, int flid, string sTextRepOfFootnote, int footnoteIndex, string footnoteMarkerStyleName) { StFootnote createdFootnote = new StFootnote(owner, flid, footnoteIndex); // create an XML reader to read in the string representation System.IO.StringReader reader = new System.IO.StringReader(sTextRepOfFootnote); XmlDocument doc = new XmlDocument(); try { doc.Load(reader); } catch (XmlException) { throw new ArgumentException("Unrecognized XML format for footnote."); } XmlNodeList tagList = doc.SelectNodes("FN"); foreach (XmlNode bla in tagList[0].ChildNodes) { // Footnote marker if (bla.Name == "M") { ITsPropsBldr propBlr = TsPropsBldrClass.Create(); propBlr.SetStrPropValue((int)FwTextPropType.ktptNamedStyle, footnoteMarkerStyleName); ITsStrBldr tss = TsStrBldrClass.Create(); tss.Replace(0, 0, bla.InnerText, propBlr.GetTextProps()); createdFootnote.FootnoteMarker.UnderlyingTsString = tss.GetString(); } // Display footnote marker else if (bla.Name == "ShowMarker") createdFootnote.DisplayFootnoteMarker = true; // display footnote scripture reference else if (bla.Name == "ShowReference") createdFootnote.DisplayFootnoteReference = true; // start of a paragraph else if (bla.Name == "P") { StTxtPara newPara = new StTxtPara(); createdFootnote.ParagraphsOS.Append(newPara); ITsIncStrBldr paraBldr = TsIncStrBldrClass.Create(); CmTranslation trans = null; //ITsStrBldr paraBldr = TsStrBldrClass.Create(); foreach (XmlNode paraTextNode in bla.ChildNodes) { if (paraTextNode.Name == "PS") { // paragraph style ITsPropsBldr propBldr = TsPropsBldrClass.Create(); if (!String.IsNullOrEmpty(paraTextNode.InnerText)) { propBldr.SetStrPropValue((int)FwTextPropType.ktptNamedStyle, paraTextNode.InnerText); } else { Debug.Fail("Attempting to create a footnote paragraph with no paragraph style specified!"); } newPara.StyleRules = propBldr.GetTextProps(); } else if (paraTextNode.Name == "RUN") { CreateRunFromStringRep(owner, paraBldr, paraTextNode); paraBldr.Append(paraTextNode.InnerText); } else if (paraTextNode.Name == "TRANS") { if (trans == null) trans = (CmTranslation)newPara.GetOrCreateBT(); // Determine which writing system where the string run(s) will be added. string iculocale = paraTextNode.Attributes.GetNamedItem("WS").Value; if (iculocale == null || iculocale == string.Empty) { throw new ArgumentException( "Unknown ICU locale encountered: " + iculocale); } int transWS = owner.Cache.LanguageEncodings.GetWsFromIcuLocale(iculocale); Debug.Assert(transWS != 0, "Unable to find ws from ICU Locale"); // Build a TsString from the run(s) description. ITsIncStrBldr strBldr = TsIncStrBldrClass.Create(); foreach (XmlNode transTextNode in paraTextNode.ChildNodes) { if (transTextNode.Name != "RUN") { throw new ArgumentException("Unexpected translation element '" + transTextNode.Name + "' encountered for ws '" + iculocale + "'"); } CreateRunFromStringRep(owner, strBldr, transTextNode); strBldr.Append(transTextNode.InnerText); } trans.Translation.SetAlternative(strBldr.GetString(), transWS); } } newPara.Contents.UnderlyingTsString = paraBldr.GetString(); } } owner.Cache.PropChanged(null, PropChangeType.kpctNotifyAll, owner.Hvo, flid, footnoteIndex, 1, 0); return createdFootnote; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Create a back translation from a format string, and attach it to the /// given paragraph. /// </summary> /// <param name="scrInMemoryCache">in-memory cache to use for testing</param> /// <param name="book">book to use</param> /// <param name="para">the paragraph that will own this back translation</param> /// <param name="format">(See CreateText for the definition of the format string)</param> /// <param name="ws">writing system of the back translation</param> /// ------------------------------------------------------------------------------------ internal static void AddBackTranslation(ScrInMemoryFdoCache scrInMemoryCache, IScrBook book, StTxtPara para, string format, int ws) { ICmTranslation cmTrans = para.GetOrCreateBT(); // Set the translation string for the given WS cmTrans.Translation.GetAlternative(ws).UnderlyingTsString = ScrInMemoryFdoCache.CreateFormatText(book, null, format, ws); }