public override void Initialize() { CheckDisposed(); base.Initialize(); m_inMemoryCache.InitializeAnnotationDefs(); InstallVirtuals(@"Language Explorer\Configuration\Words\AreaConfiguration.xml", new string[] { "SIL.FieldWorks.IText.ParagraphSegmentsVirtualHandler", "SIL.FieldWorks.IText.OccurrencesInTextsVirtualHandler" }); m_text = new Text(); Cache.LangProject.TextsOC.Add(m_text); m_para = new ScrTxtPara(); m_stText = new StText(); m_text.ContentsOA = m_stText; m_stText.ParagraphsOS.Append(m_para); ktagParaSegments = InterlinVc.ParaSegmentTag(Cache); m_wsVern = Cache.DefaultVernWs; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Creates a Back Translation for the stuff in Exodus with the following layout: /// /// () /// BT Heading 1 /// BT Intro text /// BT Heading 2 /// (1)1BT Verse one. /// /// (1) = chapter number 1 /// </summary> /// ------------------------------------------------------------------------------------ protected void CreatePartialExodusBT(int wsAnal) { IScrBook book = ScrBook.FindBookByID(m_scr, 2); IScrSection section = book.SectionsOS[0]; ScrTxtPara para = new ScrTxtPara(Cache, section.HeadingOA.ParagraphsOS.HvoArray[0]); CmTranslation trans = (CmTranslation)para.GetOrCreateBT(); m_scrInMemoryCache.AddRunToMockedTrans(trans, wsAnal, "BT Heading 1", null); para = new ScrTxtPara(Cache, section.ContentOA.ParagraphsOS.HvoArray[0]); trans = (CmTranslation)para.GetOrCreateBT(); m_scrInMemoryCache.AddRunToMockedTrans(trans, wsAnal, "BT Intro text", null); section = book.SectionsOS[1]; para = new ScrTxtPara(Cache, section.HeadingOA.ParagraphsOS.HvoArray[0]); trans = (CmTranslation)para.GetOrCreateBT(); m_scrInMemoryCache.AddRunToMockedTrans(trans, wsAnal, "BT Heading 2", null); para = new ScrTxtPara(Cache, section.ContentOA.ParagraphsOS.HvoArray[0]); trans = (CmTranslation)para.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> /// 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> /// Given a position in a back translation string, try to locate the corresponding /// verse in the vernacular, and insert the verse number in the BT. /// </summary> /// <param name="hvoObj">The id of the translation being modified</param> /// <param name="propTag">The flid (i.e. Translation)</param> /// <param name="selHelper">The selection helper</param> /// <param name="wsAlt">The writing system of the back trans multiString alt</param> /// <param name="ich">The character position at which to insert verse number</param> /// <param name="tssBt">The given BT string, in which we will insert the verse number</param> /// <param name="sVerseNumIns">output: String containing the inserted verse number, /// or null if no verse number inserted</param> /// <param name="sChapterNumIns">output: String containing the inserted chapter number, /// or null if no chapter number inserted</param> /// <param name="ichLimIns">output: Gets set to the end of the new BT chapter/verse numbers /// inserted</param> /// <returns> /// <c>true</c> if we inserted a verse number/bridge; <c>false</c> if not /// </returns> /// ------------------------------------------------------------------------------------------ private bool InsertNextVerseNumberInBt(int hvoObj, int propTag, SelectionHelper selHelper, int wsAlt, int ich, ref ITsString tssBt, out string sVerseNumIns, out string sChapterNumIns, out int ichLimIns) { // Get the corresponding verse number from the vernacular sVerseNumIns = GetBtVerseNumberFromVern(selHelper, tssBt, ich, wsAlt, true, out sChapterNumIns); ReplaceRangeInBt(hvoObj, propTag, wsAlt, ich, ich, ref sChapterNumIns, ref sVerseNumIns, ref tssBt, out ichLimIns); // Remove any chapter numbers not in the chapter range of the vernacular para that owns this BT ScrTxtPara vernPara = new ScrTxtPara(m_cache, selHelper.LevelInfo[1].hvo); BCVRef startRef; BCVRef endRef; FindParaRefRange(vernPara, out startRef, out endRef); CleanChapterInBtPara(hvoObj, wsAlt, ref tssBt, startRef, endRef); return true; }
///// ------------------------------------------------------------------------------------ ///// <summary> ///// Goes to the closest match in the given section or following section starting at the ///// given paragraph and character offsets and ending at the given paragraph and character ///// offsets ///// </summary> ///// <param name="targetRef">ScrReference to find</param> ///// <param name="bookIndex">index of book to look in</param> ///// <param name="section">section to search</param> ///// <param name="startingParaIndex">starting paragraph to look in</param> ///// <param name="startingCharIndex">starting character index to look at</param> ///// <param name="endingParaIndex">last paragraph to look in (-1 for end)</param> ///// <param name="endingCharIndex">ending character index to look at (-1 for end)</param> ///// <returns><c>false</c> if we can't go to the closest match </returns> ///// ------------------------------------------------------------------------------------ //protected virtual bool GotoClosestMatch(ScrReference targetRef, // int bookIndex, ScrSection section, int startingParaIndex, int startingCharIndex, // int endingParaIndex, int endingCharIndex) //{ // int paraCount = section.ContentParagraphCount; // if (startingParaIndex >= paraCount) // return false; // if (endingParaIndex == -1) // endingParaIndex = paraCount - 1; // if (endingCharIndex == -1) // endingCharIndex = section.LastContentParagraph.Contents.Length; // // only process this section if we have content to check // if (startingParaIndex == endingParaIndex && startingCharIndex == endingCharIndex) // return false; // // Indicator to look for the min of a section. // bool findMin = false; // // If the section does not contain this reference, then look to see if we want to // // put the selection between this section and the next one. // if (!section.ContainsReference(targetRef)) // { // // If there is no previous section and the reference is less than the // // min of this section, then place the IP at the start of this section // if (section.VerseRefMin > targetRef && section.PreviousSection == null) // { // SetInsertionPoint((int)ScrSection.ScrSectionTags.kflidContent, // bookIndex, section.IndexInBook, 0, 0, true, VwScrollSelOpts.kssoNearTop); // return true; // } // ScrSection nextSection = section.NextSection; // if (nextSection == null) // { // // If there is no following section and the reference is larger then the // // max of this section, then place it at the end of this section // if (section.VerseRefMax <= targetRef) // { // SetIpAtEndOfSection(bookIndex, section); // return true; // } // else // return false; // } // // If the reference falls between the max of this section and the max of the next // // section, then the IP will either be at the end of this section or in the next section. // if (section.VerseRefMax <= targetRef && targetRef <= nextSection.VerseRefMax) // { // // If the reference falls between the two sections, then place it at the edge of the section // // that has a reference closest to the target reference. // if (targetRef <= nextSection.VerseRefMin || section.VerseRefEnd > nextSection.VerseRefStart) // { // if (targetRef.ClosestTo(section.VerseRefMax, nextSection.VerseRefMin) == 0) // { // // set selection to the end of this section // SetInsertionPoint((int)ScrSection.ScrSectionTags.kflidContent, // bookIndex, section.IndexInBook, paraCount - 1, // section.LastContentParagraph.Contents.Length, true, // VwScrollSelOpts.kssoNearTop); // return true; // } // else // { // // Place the selection at the min reference of the next section, so // // set the target reference to the min reference so it will be // // found below. // targetRef.BBCCCVVV = nextSection.VerseRefMin; // findMin = true; // } // } // section = nextSection; // // reset index limits for changed section // paraCount = section.ContentParagraphCount; // startingParaIndex = 0; // endingParaIndex = paraCount - 1; // endingCharIndex = startingCharIndex = -1; // ADDED 8-7-2008 TLB // } // else // return false; // } // ScrVerse prevVerse = null; // REVIEW: This might need to go outside this for loop // // The reference goes somewhere in this section, so look for the spot to put it // for (int paraIndex = startingParaIndex; paraIndex <= endingParaIndex; ++paraIndex) // { // ScrTxtPara para = new ScrTxtPara(m_cache, section[paraIndex].Hvo); // ScrVerseSet verseSet = new ScrVerseSet(para); // int currentEndingCharIndex = (paraIndex == endingParaIndex && endingCharIndex != -1)? endingCharIndex: para.Contents.Length - 1; // foreach (ScrVerse verse in verseSet) // { // if (verse.VerseStartIndex >= currentEndingCharIndex) // past the end // break; // // If we haven't gotten to the beginning position where we want to start // // looking or we're looking for the minimum reference in the section, and // // this is not it, then continue looking. // if (verse.VerseStartIndex >= startingCharIndex || // (findMin && verse.StartRef == section.VerseRefMin)) // { // // When the target reference is found, set the IP // if (verse.StartRef >= targetRef) // { // // REVIEW: what to do when prevVerse is null // int ich = verse.VerseStartIndex; // if (verse.StartRef > targetRef && prevVerse != null) // { // ich = prevVerse.TextStartIndex; // if (prevVerse.HvoPara != para.Hvo) // paraIndex--; // } // // set the IP here now // GoToPosition(targetRef, bookIndex, section, paraIndex, ich); // return true; // } // } // prevVerse = verse; // } // // after the first paragraph, start looking at 0 // startingCharIndex = 0; // } // return false; //} /// ------------------------------------------------------------------------------------ /// <summary> /// Goes to the closest match in the given book. /// </summary> /// <param name="targetRef">ScrReference to find</param> /// <param name="book">index of book to look in</param> /// <returns><c>false</c> if we can't go to the closest match </returns> /// ------------------------------------------------------------------------------------ protected virtual void GotoClosestPrecedingRef(ScrReference targetRef, ScrBook book) { Debug.Assert(book != null); Debug.Assert(book.SectionsOS.Count > 0); ScrSection section = null; // Move backward through the sections in the book to find the one // whose start reference is less than the one we're looking for. for (int iSection = book.SectionsOS.Count - 1; iSection >= 0; iSection--) { section = book[iSection]; // If the reference we're looking for is greater than the current // section's start reference, then get out of the loop because we've // found the section in which we need to place the IP. if (targetRef >= section.VerseRefStart) break; } // At this point, we know we have the section in which we think the // IP should be located. int iBook = BookFilter.GetBookIndex(book.Hvo); // If the reference we're looking for is before the section's start reference, // then we need to put the IP at the beginning of the book's first section, // but after a chapter number if the sections begins with one. if (targetRef < section.VerseRefStart) { GoToFirstChapterInSection(iBook, section); return; } int paraCount = section.ContentParagraphCount; // If there are no paragraphs in the section, then we're out of luck. Debug.Assert(paraCount > 0); // Go through the paragraphs and find the one in which we // think the IP should be located. for (int iPara = paraCount - 1; iPara >= 0; iPara--) { ScrTxtPara para = new ScrTxtPara(m_cache, section[iPara].Hvo); ScrVerseList verses = new ScrVerseList(para); // Go backward through the verses in the paragrah, looking for the // first one that is less than the reference we're looking for. for (int iVerse = verses.Count - 1; iVerse >= 0; iVerse--) { // If the current reference is before (i.e. less) the one we're looking // for, then put the IP right after the it's verse number. if (verses[iVerse].StartRef <= targetRef) { GoToPosition(targetRef, iBook, section, iPara, verses[iVerse].TextStartIndex); return; } } } // At this point, we have failed to find a good location for the IP. // Therefore, just place it at the beginning of the section. GoToSectionStart(iBook, section.IndexInBook); }
/// <summary> /// Go to the indicated verse in the BT. We've already determined the index of the book, the section, /// the paragraph, and the character index in the vernacular. We want to figure the corresponding /// position in the BT, which should be the non-label segment closest to (hopefully containing) the /// vernacular position, and select it. /// </summary> /// <param name="targetRef"></param> /// <param name="bookIndex"></param> /// <param name="section"></param> /// <param name="paraIndex"></param> /// <param name="para"></param> /// <param name="ichMainPosition">The position where this verse occurs in the main paragraph.</param> protected virtual void GotoVerseBtSeg(ScrReference targetRef, int bookIndex, ScrSection section, int paraIndex, ScrTxtPara para, int ichMainPosition) { int isegTarget = GetBtSegIndexForVernChar(para, ichMainPosition, ViewConstructorWS); // Select the appropriate segment (or if nothing matched, the last place we can edit). if (isegTarget < 0) return; // pathological. SelectRangeOfChars(bookIndex, section.IndexInBook, (int)ScrSection.ScrSectionTags.kflidContent, paraIndex, isegTarget, 0, 0, true, true, false, VwScrollSelOpts.kssoDefault); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Look for the given picture's ORC in the given verse. /// </summary> /// <param name="targetRef">The verse reference to look for</param> /// <param name="hvoPict">The hvo of the picture to look for.</param> /// <param name="iSection">The index of the section where the ORC was found.</param> /// <param name="iPara">The index of the para where the ORC was found.</param> /// <param name="ichOrcPos">The character position of the ORC in the paragraph.</param> /// <returns> /// <c>true</c> if the given picture is found in the given verse. /// </returns> /// ------------------------------------------------------------------------------------ public bool FindPictureInVerse(ScrReference targetRef, int hvoPict, out int iSection, out int iPara, out int ichOrcPos) { CheckDisposed(); iSection = iPara = ichOrcPos = -1; // Find the book that the reference is in IScrBook book = ScrBook.FindBookByID(m_scr, targetRef.Book); if (book == null) return false; iSection = 0; // Look through the sections for the target reference foreach (ScrSection section in book.SectionsOS) { if (section.ContainsReference(targetRef)) { iPara = 0; // Look through each paragraph in the section foreach (StTxtPara para in section.ContentOA.ParagraphsOS) { // Search for target reference in the verses in the paragraph ScrTxtPara scrPara = new ScrTxtPara(m_cache, para.Hvo); ScrVerseSet verseSet = new ScrVerseSet(scrPara); foreach (ScrVerse verse in verseSet) { if (verse.StartRef <= targetRef && targetRef <= verse.EndRef) { // If the paragraph has a chapter number, the verse iterator // returns this as a separate string with the same reference // as the following verse. // We want to return the verse string, not the chapter number // run, so we skip a string that has only numeric characters. ITsString tssVerse = verse.Text; for (int iRun = 0; iRun < tssVerse.RunCount; iRun++) { string sRun = tssVerse.get_RunText(iRun); if (sRun.Length == 1 && sRun[0] == StringUtils.kchObject) { string str = tssVerse.get_Properties(iRun).GetStrPropValue( (int)FwTextPropType.ktptObjData); if (!String.IsNullOrEmpty(str) && str[0] == (char)(int)FwObjDataTypes.kodtGuidMoveableObjDisp) { Guid guid = MiscUtils.GetGuidFromObjData(str.Substring(1)); if (m_cache.GetIdFromGuid(guid) == hvoPict) { ichOrcPos = tssVerse.get_MinOfRun(iRun) + verse.VerseStartIndex; return true; } } } } } } iPara++; } } iSection++; } return false; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Handles the Reset Paragraph Style menu/toolbar command. /// /// Resets the style of the paragraph to be the default style for the current context. /// </summary> /// ----------------------------------------------------------------------------------- public void ResetParagraphStyle() { CheckDisposed(); if (ParagraphHvo == 0) return; // Reset paragraph style only active when selection is in a single // paragraph, so can just get selected paragraph from anchor ScrTxtPara para = new ScrTxtPara(m_cache, ParagraphHvo); ApplyStyle(para.DefaultStyleName); }
/// ----------------------------------------------------------------------------------- /// <summary> /// If user presses Enter and a new style is applied to the following paragraph, we /// need to mark that style as being in use. If in a section Head, we might need to fix /// the structure. /// </summary> /// <param name="fCalledFromKeyDown">True if this method gets called from OnKeyDown</param> /// <param name="stuInput">input string</param> /// <param name="cchBackspace">number of backspace characters in stuInput</param> /// <param name="cchDelForward">number of delete characters in stuInput</param> /// <param name="ss">Status of Shift/Control/Alt key</param> /// <param name="graphics">graphics for processing input</param> /// <param name="modifiers">key modifiers - shift status, etc.</param> /// <remarks>I (EberhardB) added the parameter <paramref name="fCalledFromKeyDown"/> /// to be able to distinguish between Ctrl-Delete and Ctrl-Backspace.</remarks> /// ----------------------------------------------------------------------------------- protected void HandleEnterKey(bool fCalledFromKeyDown, string stuInput, int cchBackspace, int cchDelForward, VwShiftStatus ss, IVwGraphics graphics, Keys modifiers) { if (IsPictureSelected) // Enter should do nothing if a picture or caption is selected. return; SelLevInfo[] levInfo; // If we are at the end of a heading paragraph, we need to check the "next" style to // see if it is a body type. If it is not, then allow processing to proceed as normal. // If it is a body type, then don't create a new paragraph, just move down to the start // of the first body paragraph in the section. if (InSectionHead) { // if the selection is a range selection then try to delete the selected text first. if (CurrentSelection.Selection.IsRange) { ITsStrFactory factory = TsStrFactoryClass.Create(); CurrentSelection.Selection.ReplaceWithTsString( factory.MakeString("", m_cache.DefaultVernWs)); // If selection is still a range selection, the deletion failed and we don't // need to do anything else. if (CurrentSelection.Selection.IsRange || !InSectionHead) return; } // If the heading style has a following style that is a body style and we are at the // end of the paragraph then move the IP to the beginning of the body paragraph. levInfo = CurrentSelection.GetLevelInfo(SelectionHelper.SelLimitType.Anchor); // This is the paragraph that was originally selected ScrTxtPara headPara = new ScrTxtPara(m_cache, levInfo[0].hvo); IStStyle headParaStyle = m_scr.FindStyle(headPara.StyleName); IStStyle followStyle = headParaStyle != null ? headParaStyle.NextRA : null; if (followStyle != null && followStyle.Structure == StructureValues.Body && SelectionAtEndParagraph()) { // if there is another section head paragraph, then the section needs to be split ScrSection section = new ScrSection(m_cache, ((ITeView)Control).LocationTracker.GetSectionHvo(CurrentSelection, SelectionHelper.SelLimitType.Anchor)); if (CurrentSelection.LevelInfo[0].ihvo < section.HeadingOA.ParagraphsOS.Count - 1) { // Setting the style rules destroys the selection, so we have to remember // the current location before we change the style rules. int iBook = BookIndex; int iSection = SectionIndex; // break the section // create a new empty paragraph in the first section // set the IP to the start of the new paragraph CreateSection(BCVRef.GetVerseFromBcv(section.VerseRefMin) == 0); Debug.Assert(CurrentSelection != null && CurrentSelection.IsValid, "Creating the section didn't set a selection"); StTxtPara contentPara = new StTxtPara(m_cache, CurrentSelection.LevelInfo[0].hvo); contentPara.StyleRules = StyleUtils.ParaStyleTextProps(followStyle.Name); SetInsertionPoint(iBook, iSection, 0, 0, false); } else { SetInsertionPoint(BookIndex, SectionIndex, 0, 0, false); // If the first paragraph is not empty, then insert a new paragraph with the // follow-on style of the section head. StTxtPara contentPara = new StTxtPara(m_cache, CurrentSelection.LevelInfo[0].hvo); if (contentPara.Contents.Length > 0) { StTxtParaBldr bldr = new StTxtParaBldr(m_cache); bldr.ParaProps = StyleUtils.ParaStyleTextProps(followStyle.Name); bldr.AppendRun(String.Empty, StyleUtils.CharStyleTextProps(null, m_cache.DefaultVernWs)); bldr.CreateParagraph(contentPara.OwnerHVO, 0); SetInsertionPoint(BookIndex, SectionIndex, 0, 0, false); } } return; } } // Call the base to handle the key base.OnCharAux('\r', fCalledFromKeyDown, stuInput, cchBackspace, cchDelForward, ss, graphics, modifiers); try { levInfo = CurrentSelection.GetLevelInfo(SelectionHelper.SelLimitType.Anchor); ScrTxtPara para = new ScrTxtPara(m_cache, levInfo[0].hvo); IStStyle style = m_scr.FindStyle(para.StyleName); if (style != null) style.InUse = true; } catch { // Oh, well. We tried. } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Calls ParseStTxtPara to carry out the desired side effects: re-parsing the paragraph /// for wordforms, ???. /// </summary> /// <param name="hvoPara">The Paragraph that was changed</param> /// <param name="ivMin">the starting character index where the change occurred</param> /// <param name="cvIns">the number of characters inserted</param> /// <param name="cvDel">the number of characters deleted</param> /// ------------------------------------------------------------------------------------ protected override void DoEffectsOfPropChange(int hvoPara, int ivMin, int cvIns, int cvDel) { // If nothing really changed, don't do anything. if (cvIns == 0 && cvDel == 0) return; // Check that the paragraph is truly Scripture, and not a footnote or some other kind // of non-Scripture paragraph int hvoOfStTextThatOwnsPara = m_cache.GetOwnerOfObject(hvoPara); switch (m_cache.GetOwningFlidOfObject(hvoOfStTextThatOwnsPara)) { case (int)ScrSection.ScrSectionTags.kflidContent: { ScrTxtPara para = new ScrTxtPara(m_cache, hvoPara, false, false); // get para props to determine para style - Intro? para.ProcessChapterVerseNums(ivMin, cvIns, cvDel); // Mark any back translations as unfinished para.MarkBackTranslationsAsUnfinished(); break; } case (int)ScrBook.ScrBookTags.kflidFootnotes: case (int)ScrSection.ScrSectionTags.kflidHeading: { ScrTxtPara para = new ScrTxtPara(m_cache, hvoPara, false, false); // Mark any back translations as stale para.MarkBackTranslationsAsUnfinished(); break; } default: // REVIEW TETeam(TomB): Is any checking needed for anything else? break; } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Adjusts the references of the section and creates any needed BT's /// </summary> /// <param name="hvoText">The StText that was changed</param> /// <param name="ivMin">the starting index where the change occurred</param> /// <param name="cvIns">the number of paragraphs inserted</param> /// <param name="cvDel">the number of paragraphs deleted</param> /// ------------------------------------------------------------------------------------ protected override void DoEffectsOfPropChange(int hvoText, int ivMin, int cvIns, int cvDel) { if (cvIns == 0 && cvDel == 0) return; // Nothing actually changed int flid = m_cache.GetOwningFlidOfObject(hvoText); StText text = new StText(m_cache, hvoText, false, false); FdoOwningSequence<IStPara> paras = text.ParagraphsOS; // Create back translations for any new paragraphs if (flid == (int)ScrSection.ScrSectionTags.kflidContent || flid == (int)ScrSection.ScrSectionTags.kflidHeading || flid == (int)ScrBook.ScrBookTags.kflidTitle) { for (int iPara = ivMin; iPara < ivMin + cvIns; iPara++) { ScrTxtPara para = new ScrTxtPara(m_cache, paras.HvoArray[iPara]); para.GetOrCreateBT(); } } // Adjust section references for section contents if we have some paragraphs left if (flid == (int)ScrSection.ScrSectionTags.kflidContent && paras.Count > 0) ScrTxtPara.AdjustSectionRefsForStTextParaChg(text, ivMin); // If we show boundary markers and we insert or delete a paragraph, we have to // update the marker of the previous paragraph as well, as that might // now be no longer the last paragraph (and thus needs to show the paragraph // marker instead of the section marker). if (((cvIns > 0 && cvDel == 0) || (cvIns == 0 && cvDel > 0)) && ivMin > 0 && Options.ShowFormatMarksSetting) { text.Cache.PropChanged(null, PropChangeType.kpctNotifyAll, hvoText, (int)StText.StTextTags.kflidParagraphs, ivMin - 1, 1, 1); } }
public void MoveNext_SpacesInVerses() { CheckDisposed(); ScrSection sectionCur = new ScrSection(); m_genesis.SectionsOS.Append(sectionCur); // Create a section head for this section sectionCur.HeadingOA = new StText(); StTxtParaBldr paraBldr = new StTxtParaBldr(Cache); paraBldr.ParaProps = StyleUtils.ParaStyleTextProps(ScrStyleNames.SectionHead); paraBldr.AppendRun("My aching head!", StyleUtils.CharStyleTextProps(null, Cache.DefaultVernWs)); paraBldr.CreateParagraph(sectionCur.HeadingOAHvo); sectionCur.ContentOA = new StText(); paraBldr = new StTxtParaBldr(Cache); paraBldr.ParaProps = StyleUtils.ParaStyleTextProps(ScrStyleNames.NormalParagraph); paraBldr.AppendRun("1", StyleUtils.CharStyleTextProps(ScrStyleNames.ChapterNumber, Cache.DefaultVernWs)); paraBldr.AppendRun("Verse One. ", StyleUtils.CharStyleTextProps(null, Cache.DefaultVernWs)); paraBldr.AppendRun("2", StyleUtils.CharStyleTextProps(ScrStyleNames.VerseNumber, Cache.DefaultVernWs)); paraBldr.AppendRun(" Verse Two. ", StyleUtils.CharStyleTextProps(null, Cache.DefaultVernWs)); paraBldr.AppendRun("3", StyleUtils.CharStyleTextProps(ScrStyleNames.VerseNumber, Cache.DefaultVernWs)); paraBldr.AppendRun("Verse Three.", StyleUtils.CharStyleTextProps(null, Cache.DefaultVernWs)); paraBldr.AppendRun("4", StyleUtils.CharStyleTextProps(ScrStyleNames.VerseNumber, Cache.DefaultVernWs)); paraBldr.AppendRun(" ", StyleUtils.CharStyleTextProps(null, Cache.DefaultVernWs)); StTxtPara para = paraBldr.CreateParagraph(sectionCur.ContentOA.Hvo); sectionCur.AdjustReferences(); ScrTxtPara stPara = new ScrTxtPara(Cache, para.Hvo); ScrVerseSet verseSet = new ScrVerseSet(stPara); // Iterate through the verses in the paragraph ScrVerse verse; Assert.IsTrue(verseSet.MoveNext()); verse = (ScrVerse)verseSet.Current; Assert.AreEqual("1", verse.Text.Text); Assert.AreEqual(01001001, verse.StartRef); Assert.AreEqual(01001001, verse.EndRef); Assert.IsTrue(verseSet.MoveNext()); verse = (ScrVerse)verseSet.Current; Assert.AreEqual("Verse One. ", verse.Text.Text); Assert.AreEqual(01001001, verse.StartRef); Assert.AreEqual(01001001, verse.EndRef); Assert.IsTrue(verseSet.MoveNext()); verse = (ScrVerse)verseSet.Current; Assert.AreEqual("2 Verse Two. ", verse.Text.Text); Assert.AreEqual(01001002, verse.StartRef); Assert.AreEqual(01001002, verse.EndRef); Assert.IsTrue(verseSet.MoveNext()); verse = (ScrVerse)verseSet.Current; Assert.AreEqual("3Verse Three.", verse.Text.Text); Assert.AreEqual(01001003, verse.StartRef); Assert.AreEqual(01001003, verse.EndRef); Assert.IsTrue(verseSet.MoveNext()); verse = (ScrVerse)verseSet.Current; Assert.AreEqual("4 ", verse.Text.Text); Assert.AreEqual(01001004, verse.StartRef); Assert.AreEqual(01001004, verse.EndRef); Assert.IsFalse(verseSet.MoveNext()); }
/// ----------------------------------------------------------------------------------- ///<summary> /// Verify the specified ScrVerse ///</summary> ///<param name="verse">specified ScrVerse</param> ///<param name="cache">database</param> ///<param name="verseText">expected text within the ScrVerse</param> ///<param name="styleName">expected stylename for the ScrVerse paragraph</param> ///<param name="startRef">expected starting reference</param> ///<param name="endRef">expected ending reference</param> /// ----------------------------------------------------------------------------------- public static void VerifyScrVerse(ScrVerse verse, FdoCache cache, string verseText, string styleName, BCVRef startRef, BCVRef endRef) { ScrTxtPara versePara = new ScrTxtPara(cache, verse.HvoPara); if (string.IsNullOrEmpty(verseText)) Assert.IsTrue(verse.Text == null || string.IsNullOrEmpty(verse.Text.Text)); else Assert.AreEqual(verseText, verse.Text.Text); Assert.AreEqual(styleName, ScrStyleNames.GetStyleName(versePara.Hvo, cache)); Assert.AreEqual(startRef, verse.StartRef); Assert.AreEqual(endRef, verse.EndRef); }
public void MoveNext_EmptyPara() { CheckDisposed(); IScrSection section = m_scrInMemoryCache.AddSectionToMockedBook(m_genesis.Hvo); StTxtPara emptyPara = AddEmptyPara(section, ScrStyleNames.SpeechLine1); section.AdjustReferences(); // Create and iterate through the verses in the StText. ScrTxtPara emptyScrPara = new ScrTxtPara(m_inMemoryCache.Cache, emptyPara.Hvo); ScrVerseSet verseSet = new ScrVerseSet(emptyScrPara); Assert.IsFalse(verseSet.MoveNext(), "The iterator provided a ScrVerse for an empty para that wasn't a Stanza Break."); }
public void MoveNext_StanzaBreak() { CheckDisposed(); IScrSection section = m_scrInMemoryCache.AddSectionToMockedBook(m_genesis.Hvo); StTxtPara emptyPara = AddEmptyPara(section, ScrStyleNames.StanzaBreak); section.AdjustReferences(); // Create and iterate through the verses in the StText. ScrTxtPara emptyScrPara = new ScrTxtPara(m_inMemoryCache.Cache, emptyPara.Hvo); ScrVerseSet verseSet = new ScrVerseSet(emptyScrPara); Assert.IsTrue(verseSet.MoveNext()); VerifyScrVerse((ScrVerse)verseSet.Current, m_inMemoryCache.Cache, null, ScrStyleNames.StanzaBreak, 01001001, 01001001); Assert.IsFalse(verseSet.MoveNext()); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Override ApplyParagraphStyle so that changes in text structure can be handled /// correctly. /// </summary> /// <param name="newParagraphStyle"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ public override bool ApplyParagraphStyle(string newParagraphStyle) { CheckDisposed(); // Paragraph style changes are not permitted in a back translation view. if (IsBackTranslation) { MiscUtils.ErrorBeep(); return false; } // Paragraph style changes are restricted to paragraphs in a single StText if (!IsSingleTextSelection()) return false; // Check contexts of new and existing paragraph style SelLevInfo[] levInfo = CurrentSelection.GetLevelInfo(SelectionHelper.SelLimitType.Anchor); // only apply a paragraph style to a paragraph.... if (m_cache.GetClassOfObject(levInfo[0].hvo) != StTxtPara.kClassId) return false; ScrTxtPara para = new ScrTxtPara(m_cache, levInfo[0].hvo); string curStyleName = para.StyleName; IStStyle curStyle = m_scr.FindStyle(curStyleName); IStStyle newStyle = m_scr.FindStyle(newParagraphStyle); if (curStyle == null) curStyle = ((FwStyleSheet)Callbacks.EditedRootBox.Stylesheet).FindStyle(para.DefaultStyleName); if (curStyle == null || newStyle == null) { // This should no longer be possible, but to be safe... Debug.Assert(curStyle != null); Debug.Assert(newStyle != null); return true; } //REVIEW: If you apply IntroPara style to a section head, what behavior?? //TODO (MarkB): If Contexts are not equal, do not apply the change. This should // only happen in case of a program error so some kind of debug message // might be appropriate. Maybe do this in the AdjustTextStructure function. //REVIEW (MarkB): AdjustTextStructure only if (Context = "Intro" OR "Text") AND // Structures are not equal. Maybe do this in the AdjustTextStructure function. bool applyStyleChange = true; if ((curStyle.Context != newStyle.Context && newStyle.Context != ContextValues.General) || curStyle.Structure != newStyle.Structure) { applyStyleChange = AdjustTextStructure(CurrentSelection, curStyle, newStyle); } if (applyStyleChange) return base.ApplyParagraphStyle(newStyle.Name); else return true; }
public void DiffEditAsPartOfImport() { CheckDisposed(); m_settings.ImportTranslation = true; MockScrObjWrapper.s_fSimulateCancel = false; int origActCount = m_cache.ActionHandlerAccessor.UndoableActionCount; IScrBook jude = m_scr.FindBook(65); Assert.IsNotNull(jude, "This test is invalid if Jude isn't in the test DB."); int cBooksOrig = m_scr.ScriptureBooksOS.Count; List<SegmentInfo> al = new List<SegmentInfo>(3); // process a \id segment to import an existing a book al.Add(new SegmentInfo(@"\id", "JUD", ImportDomain.Main, new BCVRef(65, 0, 0))); al.Add(new SegmentInfo(@"\s", "Section head", ImportDomain.Main, new BCVRef(65, 1, 1))); al.Add(new SegmentInfo(@"\p", "Contents", ImportDomain.Main, new BCVRef(65, 1, 1))); m_importMgr.CallImportWithUndoTask(m_settings, al); Assert.AreEqual(1, m_importMgr.NewSavedVersions.Count, "We should have an imported version but not a backup saved version."); Assert.AreEqual(origActCount + 4, m_cache.ActionHandlerAccessor.UndoableActionCount, "Should have 4 extra undo actions (create backup, create imported version & first book, create second book, delete {empty} backup)."); // Call ProcessChapterVerseNums to simulate an edit in the diff dialog. jude = m_scr.FindBook(65); ScrTxtPara sc1Para = new ScrTxtPara(m_cache, jude.SectionsOS[0].ContentOA.ParagraphsOS.HvoArray[0]); sc1Para.ProcessChapterVerseNums(0, 1, 0); Assert.AreEqual("&Undo Import", m_cache.UndoText); Assert.AreEqual(1, m_importMgr.m_cDisplayImportedBooksDlgCalled); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Makes changes in text structure when the context of the new paragraph style does not /// match the context of the current paragraph style. /// </summary> /// <remarks>This method properly adjusts the text structure for newStyle; the style is /// not applied here - the caller should do that.</remarks> /// <param name="selHelper">the selection to which the new style is being applied</param> /// <param name="curStyle">current style at the selection anchor</param> /// <param name="newStyle">new style to be applied (has a new style context)</param> /// <returns>Returns true if the style change can now be applied.</returns> /// ------------------------------------------------------------------------------------ protected virtual bool AdjustTextStructure(SelectionHelper selHelper, IStStyle curStyle, IStStyle newStyle) { SelLevInfo[] top = selHelper.GetLevelInfo(SelectionHelper.SelLimitType.Top); SelLevInfo[] bottom = selHelper.GetLevelInfo(SelectionHelper.SelLimitType.Bottom); ILocationTracker tracker = ((ITeView)Control).LocationTracker; int scrLevelCount = tracker.GetLevelCount((int)ScrSection.ScrSectionTags.kflidContent); // Adjustments will only be done in section level selections. if (top.Length != scrLevelCount || bottom.Length != scrLevelCount) return true; // CASE 1: Change a section head to a content paragraph // If style of paragraphs of the section heading are changed to something // that is not a section head style, restructure heading paragraphs if (top[1].tag == (int)ScrSection.ScrSectionTags.kflidHeading && newStyle.Structure == StructureValues.Body) { // these will be adjusted to the new indices after the structure is changed int iSection = tracker.GetSectionIndexInBook(selHelper, SelectionHelper.SelLimitType.Top); int iPara; bool firstSectionInContext = (iSection == 0); int iBook = tracker.GetBookIndex(selHelper, SelectionHelper.SelLimitType.Top); ScrBook book = BookFilter.GetBook(iBook); ScrSection section = (ScrSection)book.SectionsOS[iSection]; // for an interior section, need to check context of next section if (!firstSectionInContext) { IScrSection prevSection = book.SectionsOS[iSection - 1]; firstSectionInContext = !SectionsHaveSameContext(section, prevSection); } // If all paragraphs of heading are selected, merge selected section // with previous section if (AreAllParagraphsSelected(top, bottom, section.HeadingOA)) { if (!firstSectionInContext) { iPara = ScrSection.MergeIntoPreviousSectionContent(m_cache, book, iSection); iSection--; } else { // Just need to move all heading paragraphs to the content. The move // method will create a new empty heading paragraph. iPara = 0; section.MoveHeadingParasToContent(0); } } // If selection starts at first paragraph of the heading, move heading paragraphs to // content of previous section. else if (top[0].ihvo == 0) { if (!firstSectionInContext) { iPara = ScrSection.MoveHeadingToPreviousSectionContent(m_cache, book, iSection, bottom[0].ihvo); iSection--; } else { // In this case, we want the selected paragraphs to become the content // of a new section, and the preceding paragraph(s) to become the // heading of the new section. section.ChangeParagraphToSectionContent(top[0].ihvo, bottom[0].ihvo - top[0].ihvo + 1); // update insertion point to first paragraph(s) of new section content iPara = 0; } } else { // If selection bottoms at the last paragraph of the heading, move heading // paragraphs to content of this section if (section.HeadingOA.ParagraphsOS.Count - 1 == bottom[0].ihvo) { section.MoveHeadingParasToContent(top[0].ihvo); iPara = 0; } else // The selection must be only inner paragraphs in the section head, // not including the first or last paragraphs. // In this case, we want the selected paragraph(s) to become content for // the heading paragraph(s) above it, and the following section head // paragraph(s) become the heading of a new section object. { int iParaStart = top[0].ihvo; int iParabottom = bottom[0].ihvo; section.SplitSectionHeading(iSection, iParaStart, iParabottom); iPara = 0; } } // Select all paragraphs in content that were part of section heading (and have // now been moved to iSection, iPara) SetInsertionPoint(iBook, iSection, iPara, 0, false); // Get bottom point of selection and update it to point to beginning of // last paragraph of old heading. Use offsets of current selection. SelectionHelper newHelper = SelectionHelper.Create(Callbacks.EditedRootBox.Site); SelLevInfo[] levInfo = newHelper.GetLevelInfo(SelectionHelper.SelLimitType.End); levInfo[0].ihvo += bottom[0].ihvo - top[0].ihvo; newHelper.SetLevelInfo(SelectionHelper.SelLimitType.End, levInfo); newHelper.IchAnchor = selHelper.GetIch(SelectionHelper.SelLimitType.Top); newHelper.IchEnd = selHelper.GetIch(SelectionHelper.SelLimitType.Bottom); newHelper.SetSelection(true); } //bottom of CASE 1 "Change a section head to a scripture paragraph" // CASE 2: Change scripture paragraph to a section head // - only if the new style has "section head" structure, the selection is in // one paragraph, and that paragraph is part of the section content else if (top[1].tag == (int)ScrSection.ScrSectionTags.kflidContent && newStyle.Structure == StructureValues.Heading) { // Check selected paragraphs for chapter or verse numbers - style will not be // changed if any are found. ScrSection section = new ScrSection(m_cache, tracker.GetSectionHvo(selHelper, SelectionHelper.SelLimitType.Top)); for (int i = top[0].ihvo; i <= bottom[0].ihvo; i++) { ScrTxtPara para = new ScrTxtPara(m_cache, section.ContentOA.ParagraphsOS.HvoArray[i]); if (para.HasChapterOrVerseNumbers()) { // Cancel the request if chapter or verse numbers are present. // display message box if not running in a test if (!InTestMode) { MessageBox.Show(Control, TeResourceHelper.GetResourceString("kstidParaHasNumbers"), TeResourceHelper.GetResourceString("kstidApplicationName"), MessageBoxButtons.OK); } return false; } } int iBook = tracker.GetBookIndex(selHelper, SelectionHelper.SelLimitType.Top); int iSection = tracker.GetSectionIndexInBook(selHelper, SelectionHelper.SelLimitType.Top); int iPara; ScrBook book = section.OwningBook; // End of book is end of context type bool lastSectionInContext = (iSection == book.SectionsOS.Count - 1); // for an interior section, need to check context of next section if (!lastSectionInContext) { IScrSection nextSection = book.SectionsOS[iSection + 1]; lastSectionInContext = !SectionsHaveSameContext(section, nextSection); } if (AreAllParagraphsSelected(top, bottom, section.ContentOA)) { if (!lastSectionInContext) { // Need to combine this section with the following section. // Heading of combined section will be section1.Heading + // section1.Content + section2.Heading iPara = section.HeadingOA.ParagraphsOS.Count; IScrSection nextSection = book.SectionsOS[iSection + 1]; StText.MoveTextContents(section.ContentOA, nextSection.HeadingOA, false); StText.MoveTextContents(section.HeadingOA, nextSection.HeadingOA, false); nextSection.AdjustReferences(); book.SectionsOS.RemoveAt(iSection); } else { // Just need to move all content paragraphs to the heading. The move // method will create a new empty content paragraph. iPara = section.HeadingOA.ParagraphsOS.Count; section.MoveContentParasToHeading(section.ContentOA.ParagraphsOS.Count - 1); } } else if (top[0].ihvo == 0) { // Move the first content paragraphs to become the last para of the // section head section.MoveContentParasToHeading(bottom[0].ihvo); iPara = section.HeadingOA.ParagraphsOS.Count - (bottom[0].ihvo - top[0].ihvo + 1); } else if (bottom[0].ihvo == section.ContentOA.ParagraphsOS.Count - 1 && !lastSectionInContext) { // Move the last content paragraphs to become the first para of the next // section in the book. ScrSection.MoveContentParasToNextSectionHeading(m_cache, book, iSection, top[0].ihvo); // update insertion point to first paragraph(s) of next section head iSection++; iPara = 0; } else { // In this case, we want the selected paragraph to become the heading // of a new section, and the following paragraph(s) to become the // content of the new section object. section.ChangeParagraphToSectionHead(top[0].ihvo, bottom[0].ihvo - top[0].ihvo + 1); // update insertion point to first paragraph(s) of next section head iSection++; iPara = 0; } // Select all paragraphs in content that were part of section heading (and have // now been moved to iSection, iPara) SetInsertionPoint((int)ScrSection.ScrSectionTags.kflidHeading, iBook, iSection, iPara); // Get bottom point of selection and update it to point to beginning of // last paragraph of old heading. Use offsets of current selection. SelectionHelper newHelper = SelectionHelper.Create(Callbacks.EditedRootBox.Site); SelLevInfo[] levInfo = newHelper.GetLevelInfo(SelectionHelper.SelLimitType.End); levInfo[0].ihvo += bottom[0].ihvo - top[0].ihvo; newHelper.SetLevelInfo(SelectionHelper.SelLimitType.End, levInfo); newHelper.IchAnchor = selHelper.GetIch(SelectionHelper.SelLimitType.Top); newHelper.IchEnd = selHelper.GetIch(SelectionHelper.SelLimitType.Bottom); newHelper.SetSelection(true); } return true; }
public void FindPrevBackTrans_SecondBookTitleToFirstBook_LastParaFinished() { CheckDisposed(); // add new book with a BT IScrBook book = m_scrInMemoryCache.AddBookToMockedScripture(3, "Leviticus"); StText text = m_scrInMemoryCache.AddTitleToMockedBook(book.Hvo, "Title for Leviticus"); m_scrInMemoryCache.AddBtToMockedParagraph((StTxtPara)text.ParagraphsOS[0], Cache.DefaultAnalWs); // add BT for the last section heading of the first book ScrTxtPara para = new ScrTxtPara(Cache, m_book.SectionsOS[2].HeadingOA.ParagraphsOS.HvoArray[0]); m_inMemoryCache.AddBtToMockedParagraph(para, Cache.DefaultAnalWs); // add BT for last para of first book para = new ScrTxtPara(Cache, m_book.SectionsOS[2].ContentOA.ParagraphsOS.HvoArray[0]); ICmTranslation trans = m_inMemoryCache.AddBtToMockedParagraph(para, Cache.DefaultAnalWs); m_btDraftView.SetTransStatus(trans, BackTranslationStatus.Finished); m_btDraftView.RefreshDisplay(); m_btDraftView.SetInsertionPoint((int)ScrBook.ScrBookTags.kflidTitle, 1, 0); m_btDraftView.CallPrevUnfinishedBackTrans(); SelectionHelper helper = m_btDraftView.EditingHelper.CurrentSelection; Assert.AreEqual(0, helper.IchAnchor); Assert.AreEqual(0, m_btDraftView.TeEditingHelper.BookIndex); Assert.AreEqual(2, m_btDraftView.TeEditingHelper.SectionIndex); Assert.AreEqual(0, m_btDraftView.ParagraphIndex); Assert.AreEqual((int)ScrSection.ScrSectionTags.kflidHeading, m_btDraftView.EditingHelper.CurrentSelection.LevelInfo[2].tag); Assert.IsFalse(m_btDraftView.TeEditingHelper.InBookTitle); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Find a verse and return the text of the verse in one or more /// <see cref="VerseTextSubstring"/> objects. /// </summary> /// <param name="scr">The scripture.</param> /// <param name="targetRef">The verse reference to look for</param> /// <param name="ichStart">The starting character where the (first part of the) verse /// text is located within the (first) containing paragraph</param> /// <returns> /// A list of <see cref="VerseTextSubstring"/> objects, each representing /// one paragraph worth of verse text (e.g., to deal with poetry) /// </returns> /// <remarks>Verses would not normally be split across sections, but there are a few /// places, such as the end of I Cor. 12, where it can happen. /// </remarks> /// ------------------------------------------------------------------------------------ public static List<VerseTextSubstring> GetVerseText(IScripture scr, ScrReference targetRef, out int ichStart) { ichStart = -1; if (scr.Versification != targetRef.Versification) targetRef = new ScrReference(targetRef, scr.Versification); List<VerseTextSubstring> verseText = new List<VerseTextSubstring>(); // Find the book that the reference is in IScrBook book = ScrBook.FindBookByID(scr, targetRef.Book); if (book == null) return verseText; if (targetRef.IsBookTitle) { foreach (StTxtPara para in book.TitleOA.ParagraphsOS) { verseText.Add(new VerseTextSubstring(para.Contents.UnderlyingTsString, -1, para.IndexInOwner, (int)ScrBook.ScrBookTags.kflidTitle)); ichStart = 0; } return verseText; } int iSection = 0; // Look through the sections for the target reference foreach (ScrSection section in book.SectionsOS) { if (!section.ContainsReference(targetRef)) { if (verseText.Count > 0) return verseText; } else { int iPara = 0; // Look through each paragraph in the section foreach (StTxtPara para in section.ContentOA.ParagraphsOS) { // Search for target reference in the verses in the paragraph ScrTxtPara scrPara = new ScrTxtPara(scr.Cache, para.Hvo); ScrVerseSet verseSet = new ScrVerseSet(scrPara); foreach (ScrVerse verse in verseSet) { if (verse.StartRef <= targetRef && targetRef <= verse.EndRef) { // If the paragraph has a chapter number, the verse iterator // returns this as a separate string with the same reference // as the following verse. // We want to return the verse string, not the chapter number // run, so we skip a string that has only numeric characters. ITsString verseTextInPara = verse.Text; if (verse.Text.RunCount > 0) { string styleName = verse.Text.get_PropertiesAt(0).GetStrPropValue( (int)FwTextPropType.ktptNamedStyle); if (styleName == ScrStyleNames.VerseNumber) verseTextInPara = StringUtils.Substring(verseTextInPara, verse.Text.get_LimOfRun(0)); } if (!IsNumber(verseTextInPara.Text)) // skip chapter number strings { if (verseText.Count == 0) ichStart = verse.TextStartIndex; verseText.Add(new VerseTextSubstring(verseTextInPara, iSection, iPara, (int)ScrSection.ScrSectionTags.kflidContent)); break; } } else if (verseText.Count > 0) return verseText; } iPara++; } } iSection++; } return verseText; }
public void FindNextBackTrans_SectionContentToTitle() { CheckDisposed(); // add new book IScrBook book = m_scrInMemoryCache.AddBookToMockedScripture(3, "Leviticus"); StText text = m_scrInMemoryCache.AddTitleToMockedBook(book.Hvo, "Title for Leviticus"); // add BT for last para of first book ScrTxtPara para = new ScrTxtPara(Cache, m_book.SectionsOS[2].ContentOA.ParagraphsOS.HvoArray[0]); m_inMemoryCache.AddBtToMockedParagraph(para, Cache.DefaultAnalWs); // add BT for title para of the last book para = new ScrTxtPara(Cache, text.ParagraphsOS.HvoArray[0]); m_inMemoryCache.AddBtToMockedParagraph(para, Cache.DefaultAnalWs); m_btDraftView.RefreshDisplay(); int iLastSectionInExodus = m_book.SectionsOS.Count - 1; m_btDraftView.SetInsertionPoint((int)ScrSection.ScrSectionTags.kflidContent, 0, iLastSectionInExodus, m_book.SectionsOS[iLastSectionInExodus].ContentOA.ParagraphsOS.Count -1); m_btDraftView.CallNextUnfinishedBackTrans(); SelectionHelper helper = m_btDraftView.EditingHelper.CurrentSelection; Assert.AreEqual(0, helper.IchAnchor); Assert.AreEqual(1, m_btDraftView.TeEditingHelper.BookIndex); Assert.AreEqual(-1, m_btDraftView.TeEditingHelper.SectionIndex); Assert.AreEqual(0, m_btDraftView.ParagraphIndex); Assert.IsTrue(m_btDraftView.TeEditingHelper.InBookTitle); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Goes to the verse reference in the back translation paragraph or the closest /// location to where it would occur /// </summary> /// ------------------------------------------------------------------------------------ protected virtual void GotoVerseBT(ScrReference targetRef, int bookIndex, ScrSection section, int paraIndex, ScrTxtPara para) { ScrVerseSet verseSet = new ScrVerseSetBT(para, ViewConstructorWS); // Look for an exact match of the target verse number in the BT para foreach (ScrVerse verse in verseSet) { if (!verse.VerseNumberRun) continue; if (verse.StartRef <= targetRef && targetRef <= verse.EndRef) { // set the IP here now SetInsertionPoint(bookIndex, section.IndexInBook, paraIndex, verse.TextStartIndex, false); return; } } // An exact match was not found, so look for a best guess spot for it foreach (ScrVerse verse in verseSet) { if (!verse.VerseNumberRun) continue; if (verse.StartRef >= targetRef) { // set the IP here now SetInsertionPoint(bookIndex, section.IndexInBook, paraIndex, verse.VerseStartIndex, false); return; } } // A best guess spot was not found so put the selection at the end of the paragraph SetIpAtEndOfPara(bookIndex, section.IndexInBook, paraIndex, para); }
public void FindNextBackTrans_SectionContentToNextBook_TitleFinished() { CheckDisposed(); // add new book IScrBook book = m_scrInMemoryCache.AddBookToMockedScripture(3, "Leviticus"); StText text = m_scrInMemoryCache.AddTitleToMockedBook(book.Hvo, "Title for Leviticus"); IScrSection section = m_scrInMemoryCache.AddSectionToMockedBook(book.Hvo); m_scrInMemoryCache.AddSectionHeadParaToSection(section.Hvo, "Heading", ScrStyleNames.SectionHead); // add BT for last para of first book ScrTxtPara para = new ScrTxtPara(Cache, m_book.SectionsOS[2].ContentOA.ParagraphsOS.HvoArray[0]); m_inMemoryCache.AddBtToMockedParagraph(para, Cache.DefaultAnalWs); // add BT for title para of the last book para = new ScrTxtPara(Cache, text.ParagraphsOS.HvoArray[0]); ICmTranslation trans = m_inMemoryCache.AddBtToMockedParagraph(para, Cache.DefaultAnalWs); m_btDraftView.SetTransStatus(trans, BackTranslationStatus.Finished); // add BT for the first section head of the last book para = new ScrTxtPara(Cache, book.SectionsOS[0].HeadingOA.ParagraphsOS.HvoArray[0]); m_inMemoryCache.AddBtToMockedParagraph(para, Cache.DefaultAnalWs); m_btDraftView.RefreshDisplay(); int iLastSectionInExodus = m_book.SectionsOS.Count - 1; m_btDraftView.SetInsertionPoint((int)ScrSection.ScrSectionTags.kflidContent, 0, iLastSectionInExodus, m_book.SectionsOS[iLastSectionInExodus].ContentOA.ParagraphsOS.Count -1); m_btDraftView.CallNextUnfinishedBackTrans(); SelectionHelper helper = m_btDraftView.EditingHelper.CurrentSelection; Assert.AreEqual(0, helper.IchAnchor); Assert.AreEqual(1, m_btDraftView.TeEditingHelper.BookIndex); Assert.AreEqual(0, m_btDraftView.TeEditingHelper.SectionIndex); Assert.AreEqual(0, m_btDraftView.ParagraphIndex); Assert.AreEqual((int)ScrSection.ScrSectionTags.kflidHeading, m_btDraftView.EditingHelper.CurrentSelection.LevelInfo[2].tag); Assert.IsFalse(m_btDraftView.TeEditingHelper.InBookTitle); }
/// <summary> /// Given a character position in the contents of an ScrTxtPara, return the index of the corresponding segment /// (or the closest editable one). /// </summary> static public int GetBtSegIndexForVernChar(ScrTxtPara para, int ichMainPosition, int btWs) { StTxtPara.LoadSegmentFreeTranslations(new int[] { para.Hvo }, para.Cache, btWs); int ktagParaSegments = StTxtPara.SegmentsFlid(para.Cache); int cseg = para.Cache.GetVectorSize(para.Hvo, ktagParaSegments); int kflidFT = StTxtPara.SegmentFreeTranslationFlid(para.Cache); ISilDataAccess sda = para.Cache.MainCacheAccessor; int isegTarget = -1; for (int iseg = 0; iseg < cseg; iseg++) { int hvoSeg = sda.get_VecItem(para.Hvo, ktagParaSegments, iseg); CmBaseAnnotation seg = CmObject.CreateFromDBObject(para.Cache, hvoSeg) as CmBaseAnnotation; // If it's a 'label' segment, it's not where we want to put the IP. ITsString tssSeg = seg.TextAnnotated; if (SegmentBreaker.HasLabelText(tssSeg, 0, tssSeg.Length)) continue; isegTarget = iseg; if (ichMainPosition <= seg.EndOffset) break; // don't consider any later segment } return isegTarget; }
public void CreateBtsWhenContentParagraphIsReplacedByMultipleOtherParagraphs() { CheckDisposed(); // add scripture section and paragraph IScrSection section = m_scrInMemoryCache.AddSectionToMockedBook(m_book.Hvo); StTxtPara para1 = m_scrInMemoryCache.AddParaToMockedSectionContent(section.Hvo, ScrStyleNames.IntroParagraph); StTxtPara para2 = m_scrInMemoryCache.AddParaToMockedSectionContent(section.Hvo, ScrStyleNames.IntroParagraph); StTxtPara para3 = m_scrInMemoryCache.AddParaToMockedSectionContent(section.Hvo, ScrStyleNames.IntroParagraph); // set up the Scripture paragraph ChangeWatcher ScriptureChangeWatcher.Create(Cache); // Issue a PropChanged that should create a back translation paragraph. Cache.MainCacheAccessor.PropChanged(null, (int)PropChangeType.kpctNotifyAll, section.ContentOA.Hvo, (int)StText.StTextTags.kflidParagraphs, 0, 3, 1); // make sure the back translations got created. ScrTxtPara scrPara = new ScrTxtPara(Cache, para1.Hvo); ICmTranslation bt = scrPara.GetBT(); Assert.IsNotNull(bt); Assert.IsNull(bt.Status.AnalysisDefaultWritingSystem); scrPara = new ScrTxtPara(Cache, para2.Hvo); bt = scrPara.GetBT(); Assert.IsNotNull(bt); Assert.IsNull(bt.Status.AnalysisDefaultWritingSystem); scrPara = new ScrTxtPara(Cache, para3.Hvo); bt = scrPara.GetBT(); Assert.IsNotNull(bt); Assert.IsNull(bt.Status.AnalysisDefaultWritingSystem); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Find the beginning and ending reference for a given paragraph. /// </summary> /// <param name="para">given paragraph</param> /// <param name="startRef">out: reference at start of paragraph</param> /// <param name="endRef">out: reference at end of paragraph</param> /// ------------------------------------------------------------------------------------ private void FindParaRefRange(ScrTxtPara para, out BCVRef startRef, out BCVRef endRef) { BCVRef notUsed; para.GetBCVRefAtPosition(0, false, out startRef, out notUsed); para.GetBCVRefAtPosition(para.Contents.Length, out notUsed, out endRef); }
public void CreateBtWhenHeadingParagraphIsAdded() { CheckDisposed(); // add scripture section and paragraph IScrSection section = m_scrInMemoryCache.AddSectionToMockedBook(m_book.Hvo); StTxtPara para = m_scrInMemoryCache.AddSectionHeadParaToSection(section.Hvo, "Intro to Genesis or whatever", ScrStyleNames.IntroSectionHead); // set up the Scripture paragraph ChangeWatcher ScriptureChangeWatcher.Create(Cache); // Issue a PropChanged that should create a back translation paragraph. Cache.MainCacheAccessor.PropChanged(null, (int)PropChangeType.kpctNotifyAll, section.HeadingOA.Hvo, (int)StText.StTextTags.kflidParagraphs, 0, 1, 0); // make sure the back translation is created. ScrTxtPara scrPara = new ScrTxtPara(Cache, para.Hvo); ICmTranslation bt = scrPara.GetBT(); Assert.IsNotNull(bt); Assert.IsNull(bt.Status.AnalysisDefaultWritingSystem); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Remove any duplicate verse numbers following the new verse number in the following /// text in the current as well as the following section, if any. /// </summary> /// <param name="hvoObj">The id of the para or translation being modified</param> /// <param name="propTag">The flid (Contents or Translation)</param> /// <param name="tss">The structured string or the para or trans with the new verse /// number</param> /// <param name="wsAlt">The writing system, if a back trans multiString alt</param> /// <param name="chapterToRemove">A string representation of the duplicate chapter number /// to remove.</param> /// <param name="verseRangeToRemove">A string representation of the duplicate verse number to /// remove. This may also be a verse bridge, in which case we will remove all verse /// numbers up to the end value of the bridge</param> /// <param name="ich">The character offset after which we start looking for dups</param> /// ------------------------------------------------------------------------------------ private void RemoveDuplicateVerseNumbers(int hvoObj, int propTag, ITsString tss, int wsAlt, string chapterToRemove, string verseRangeToRemove, int ich) { // Determine the verse number we will remove up to int removeUpToVerse = ScrReference.VerseToIntEnd(verseRangeToRemove); bool inBackTrans = (m_cache.GetClassOfObject(hvoObj) == CmTranslation.kClassId); // Get my current StText, ScrSection and ScrBook int hvoCurrPara = inBackTrans ? (new CmTranslation(m_cache, hvoObj)).OwnerHVO : hvoObj; ScrTxtPara currentPara = new ScrTxtPara(m_cache, hvoCurrPara); // Determine the last chapter reference to remove. int removeChapter = (chapterToRemove != null && chapterToRemove.Length > 0) ? ScrReference.ChapterToInt(chapterToRemove) : 0; // First look in the paragraph where the verse was inserted. if (RemoveDuplicateVerseNumbersInPara(hvoObj, propTag, tss, wsAlt, removeChapter, removeUpToVerse, ich)) { return; } // Search through current and subsequent section (if any) for duplicate verse numbers. StText text = new StText(m_cache, currentPara.OwnerHVO); ScrSection currentSection = new ScrSection(m_cache, text.OwnerHVO); IScrBook currentBook = currentSection.OwningBook; // First look through successive paragraphs for duplicate verse numbers, and then // try the next section if necessary. if (!RemoveDuplicateVerseNumbersInText(text, currentPara.IndexInOwner + 1, inBackTrans, propTag, wsAlt, removeChapter, removeUpToVerse)) { ScrSection nextSection = currentSection.NextSection; if (nextSection != null) { RemoveDuplicateVerseNumbersInText(nextSection.ContentOA, 0, inBackTrans, propTag, wsAlt, removeChapter, removeUpToVerse); } } }
public void CreateBtWhenBookTitleParagraphIsAdded() { CheckDisposed(); // add title paragraphs StText title = m_scrInMemoryCache.AddTitleToMockedBook(m_book.Hvo, "Genesis or whatever"); StTxtPara para2 = m_scrInMemoryCache.AddParaToMockedText(title.Hvo, "An anthology"); StTxtPara para3 = m_scrInMemoryCache.AddParaToMockedText(title.Hvo, "Written by God"); m_scrInMemoryCache.AddParaToMockedText(title.Hvo, "For Israel and everyone else"); // set up the Scripture paragraph ChangeWatcher ScriptureChangeWatcher.Create(Cache); // Issue a PropChanged that should create a back translation paragraph. Cache.MainCacheAccessor.PropChanged(null, (int)PropChangeType.kpctNotifyAll, title.Hvo, (int)StText.StTextTags.kflidParagraphs, 1, 2, 0); // Make sure the back translations got created. ScrTxtPara scrPara = new ScrTxtPara(Cache, para2.Hvo); ICmTranslation bt = scrPara.GetBT(); Assert.IsNotNull(bt); Assert.IsNull(bt.Status.AnalysisDefaultWritingSystem); scrPara = new ScrTxtPara(Cache, para3.Hvo); bt = scrPara.GetBT(); Assert.IsNotNull(bt); Assert.IsNull(bt.Status.AnalysisDefaultWritingSystem); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the start and end reference of the specified position <paramref name="ivPos"/> /// in the paragraph. Section reference could be used, if available, to fill in missing /// information, but (at least for now) we will not search back into previous sections. /// </summary> /// <param name="wsBT">HVO of the writing system of the BT to search, or -1 to search /// the vernacular.</param> /// <param name="ivPos">Character offset in the paragraph.</param> /// <param name="fAssocPrev">Consider this position to be associated with any preceding /// text in the paragraph (in the case where ichPos is at a chapter boundary).</param> /// <param name="refStart">[out] Start reference</param> /// <param name="refEnd">[out] End reference</param> /// <remarks><p><paramref name="refStart"/> and <paramref name="refEnd"/> are only /// different if we have bridged verse numbers.</p> /// <p>May return incomplete or invalid reference if, for example, the section /// object does not have a valid start reference.</p> /// <p>If ivPos LT zero, we will not search this para, but look only in previous /// paragraphs</p></remarks> /// ------------------------------------------------------------------------------------ public void GetBCVRefAtPosition(int wsBT, int ivPos, bool fAssocPrev, out BCVRef refStart, out BCVRef refEnd) { refStart = new BCVRef(); refEnd = new BCVRef(); // Might be trying to get the BCVRef in a footnote int ownerOwnFlid = m_cache.GetOwningFlidOfObject(OwnerHVO); if (ownerOwnFlid == (int)ScrBook.ScrBookTags.kflidFootnotes) { ScrFootnote footnote = new ScrFootnote(m_cache, OwnerHVO); refStart = footnote.StartRef; refEnd = footnote.StartRef; return; } BCVRef refStartT = new BCVRef(); BCVRef refEndT = new BCVRef(); ChapterVerseFound found = ChapterVerseFound.None; bool fGotVerse = false; ScrTxtPara para = this; // curent paragraph being examined for reference int chvoParas = 0; // count of paragraphs in the section int ihvoPara = 0; // index of the paragraph within the section BCVRef sectRefStart; BCVRef sectRefEnd; GetSectionStartAndEndRefs(out sectRefStart, out sectRefEnd); while (true) { if (para == this) { found = para.GetBCVRefAtPosWithinPara(wsBT, ivPos, fAssocPrev, out refStartT, out refEndT); } else { found = para.GetBCVRefAtEndOfPara(out refStartT, out refEndT); } // if we found a verse, remember it if (!fGotVerse && ((found & ChapterVerseFound.Verse) != 0)) { refStart.Verse = refStartT.Verse; refEnd.Verse = refEndT.Verse; fGotVerse = true; } // if we found a chapter, process it if ((found & ChapterVerseFound.Chapter) != 0) { if (sectRefStart != null && !sectRefStart.IsEmpty) { refStart.Book = refEnd.Book = sectRefStart.Book; //may not exist } refStart.Chapter = refEnd.Chapter = refStartT.Chapter; // GetBCVwithinPara always returns a verse if it finds a chapter number // so we have already built the full reference Debug.Assert(fGotVerse); return; } // We got to the beginning of the paragraph being edited and still haven't // found a decent reference for our edited text, so keep looking back to // get it from a previous paragraph. // First time thru, figure out which paragraph we are in if (chvoParas == 0) { // REVIEW (EberhardB): does this work if not all paragraphs are // loaded in the cache? chvoParas = m_cache.GetVectorSize(OwnerHVO, (int)StText.StTextTags.kflidParagraphs); // Go forward through vector of paragraphs to find the one being parsed for (ihvoPara = 0; ihvoPara < chvoParas; ihvoPara++) { int hvoPara = m_cache.GetVectorItem(OwnerHVO, (int)StText.StTextTags.kflidParagraphs, ihvoPara); if (hvoPara == Hvo) { break; // found our current para } } } // Move to the previous paragraph ihvoPara--; if (ihvoPara < 0) { // We are at the beginning of the section. We can't look back any further. // ENHANCE TomB: If we search all the way through to the beginning of the // section and never get a valid reference, this section begins in the // middle of a verse or chapter (unlikely in the case of a verse, but // quite likely in the case of a chapter). OR (most likely) this edit // happened at the very beginning of the section, and when we start // parsing, the first thing we'll get is a decent reference. // REVIEW: we're using the section reference, but since they don't get // updated, a change (like removing a chapter) in a previous section // could mess up this section. if (fGotVerse) { // Use the verse we got previously (already set), along with the // first chapter for the section and the book, if available. if (sectRefStart != 0) { refStart.Chapter = refEnd.Chapter = sectRefStart.Chapter; refStart.Book = refEnd.Book = sectRefStart.Book; } } else { // REVIEW: // For now, we're just using the first verse for the section, but this // could be wrong if the section begins in the middle of a verse bridge // or misleading if the section just doesn't yet have verse numbers // marked. if (sectRefStart != 0) { refStart = new BCVRef(sectRefStart); refEnd = new BCVRef(sectRefStart); } // If we are looking for a negative position in the first para of a section // the needed result is not precisely defined yet, // but this is where you could set it // if (para == this && ivPos < 0) // refStart.Verse = refEnd.Verse = ????; } return; } // Set up for the previous paragraph in this section, and we'll try again int hvoNewPara = m_cache.GetVectorItem(OwnerHVO, (int)StText.StTextTags.kflidParagraphs, ihvoPara); // use a special constructor since we already know the section refs para = new ScrTxtPara(m_cache, hvoNewPara, false, 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; }