GetIch() public méthode

Gets the 0-based index of the character for the given limit of the selection.
public GetIch ( SelLimitType type ) : int
type SelLimitType
Résultat int
Exemple #1
0
		/// ------------------------------------------------------------------------------------
		/// <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)}; ;
		}
Exemple #2
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Determines if the selection is an entire book
		/// </summary>
		/// <param name="helper"></param>
		/// <param name="topInfo"></param>
		/// <param name="bottomInfo"></param>
		/// <returns></returns>
		/// ------------------------------------------------------------------------------------
		private bool IsBookSelection (SelectionHelper helper, SelLevInfo[] topInfo,
			SelLevInfo[] bottomInfo)
		{
			ILocationTracker tracker = ((ITeView)Control).LocationTracker;
			int bookTitleLevelCount = tracker.GetLevelCount((int)ScrBook.ScrBookTags.kflidTitle);
			if (topInfo.Length == bookTitleLevelCount && bottomInfo.Length == bookTitleLevelCount)
			{
				// Verify that selection goes from beginning of book title to
				// beginning of title in next book.
				return (tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top) ==
					tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Bottom) - 1 &&
					topInfo[1].tag == (int)ScrBook.ScrBookTags.kflidTitle &&
					topInfo[1].ihvo == 0 &&
					topInfo[0].tag == (int)StText.StTextTags.kflidParagraphs &&
					topInfo[0].ihvo == 0 &&
					bottomInfo[1].tag == (int)ScrBook.ScrBookTags.kflidTitle &&
					bottomInfo[1].ihvo == 0 &&
					bottomInfo[0].tag == (int)StText.StTextTags.kflidParagraphs &&
					bottomInfo[0].ihvo == 0 &&
					helper.IchAnchor == 0 &&
					helper.IchEnd == 0);
			}
			else if (topInfo.Length == bookTitleLevelCount && bottomInfo.Length ==
				tracker.GetLevelCount((int)ScrSection.ScrSectionTags.kflidContent))
			{
				// Check that selection is at start of title
				bool bookSel = (tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top) ==
					tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Bottom) &&
					topInfo[1].tag == (int)ScrBook.ScrBookTags.kflidTitle &&
					topInfo[1].ihvo == 0 &&
					topInfo[0].tag == (int)StText.StTextTags.kflidParagraphs &&
					topInfo[0].ihvo == 0 &&
					helper.GetIch(SelectionHelper.SelLimitType.Top) == 0);

				if (bookSel)
				{
					// Get information about last paragraph of the book
					ScrBook book = new ScrBook(m_cache,
						tracker.GetBookHvo(helper, SelectionHelper.SelLimitType.Top));
					int iSection = book.SectionsOS.Count - 1;
					IScrSection section = book.SectionsOS[iSection];
					int iPara = section.ContentOA.ParagraphsOS.Count - 1;
					StTxtPara para = (StTxtPara) section.ContentOA.ParagraphsOS[iPara];
					int ichEnd = para.Contents.Length;

					// Check that selection is at end of last paragraph of book
					bookSel = (tracker.GetSectionIndexInBook(helper,
						SelectionHelper.SelLimitType.Bottom) == iSection &&
						bottomInfo[1].tag == (int)ScrSection.ScrSectionTags.kflidContent &&
						bottomInfo[0].ihvo == iPara &&
						bottomInfo[0].tag == (int)StText.StTextTags.kflidParagraphs &&
						helper.GetIch(SelectionHelper.SelLimitType.Bottom) == ichEnd);
				}

				return bookSel;
			}
			return false;
		}
Exemple #3
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Delete the given selection, removing any spanned sections. Selection is assumed to
		/// start in content of one section and end in content of another section.
		/// </summary>
		/// <param name="helper"></param>
		/// <returns></returns>
		/// ------------------------------------------------------------------------------------
		private bool DeleteMultiSectionContentRange(SelectionHelper helper)
		{
			ILocationTracker tracker = ((ITeView)Control).LocationTracker;
			int ihvoBook = tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top);
			int ihvoSectionStart =
				tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top);
			int ihvoSectionEnd =
				tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Bottom);
			if (ihvoBook < 0 || ihvoSectionStart < 0 || ihvoSectionEnd < 0)
			{
				// Something changed catastrophically. Maybe we added introductory material?
				Debug.Assert(false);
				return false;
			}
			ScrBook book = BookFilter.GetBook(ihvoBook);
			IScrSection sectionStart = book.SectionsOS[ihvoSectionStart];
			IScrSection sectionEnd = book.SectionsOS[ihvoSectionEnd];
			int ihvoParaStart = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[0].ihvo;
			StTxtPara paraStart = (StTxtPara) sectionStart.ContentOA.ParagraphsOS[ihvoParaStart];
			int ihvoParaEnd = helper.GetLevelInfo(SelectionHelper.SelLimitType.Bottom)[0].ihvo;
			StTxtPara paraEnd = (StTxtPara) sectionEnd.ContentOA.ParagraphsOS[ihvoParaEnd];
			int ichStart = helper.GetIch(SelectionHelper.SelLimitType.Top);
			int ichEnd = helper.GetIch(SelectionHelper.SelLimitType.Bottom);

			if (helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[0].tag !=
				(int)StText.StTextTags.kflidParagraphs)
			{
				// Something changed catastrophically. StText has something in it other than paragraphs!
				Debug.Assert(false);
				return false;
			}

			// Remove footnotes of sections that will be deleted entirely
			int iSection = ihvoSectionStart;
			int iPara = ihvoParaStart;
			int ich = ichStart;
			int tag = (int)ScrSection.ScrSectionTags.kflidContent;
			ScrFootnote firstFootnoteToDelete = ScrFootnote.FindNextFootnote(m_cache,
				book, ref iSection, ref iPara, ref ich, ref tag, false);
			if (iSection < ihvoSectionEnd || (iSection == ihvoSectionEnd &&
				(iPara < ihvoParaEnd || (iPara == ihvoParaEnd && ich <= ichEnd))) ||
				tag != (int)ScrSection.ScrSectionTags.kflidContent)
			{
				iSection = ihvoSectionEnd;
				iPara = ihvoParaEnd;
				ich = ichEnd;
				tag = (int)ScrSection.ScrSectionTags.kflidContent;
				ScrFootnote lastFootnoteToDelete = ScrFootnote.FindPreviousFootnote(m_cache,
					book, ref iSection, ref iPara, ref ich, ref tag, true);
				if (iSection > ihvoSectionStart || (iSection == ihvoSectionStart &&
					(iPara > ihvoParaStart || (iPara == ihvoParaStart && ich >= ichStart))) ||
					tag != (int)ScrSection.ScrSectionTags.kflidContent)
				{
					DeleteFootnotes(book, firstFootnoteToDelete, lastFootnoteToDelete,
						paraStart.Hvo, paraEnd.Hvo);
				}
			}

			// Remove any trailing portion of the start section that is selected
			IStText content = sectionStart.ContentOA;
			for (iPara = content.ParagraphsOS.Count - 1; iPara > ihvoParaStart; iPara--)
				content.ParagraphsOS.RemoveAt(iPara);

			ITsStrBldr startContentBldr = paraStart.Contents.UnderlyingTsString.GetBldr();
			startContentBldr.Replace(ichStart, startContentBldr.Length, string.Empty, null);

			// Copy any trailing portion (not selected) of the end section to the start section.
			int ihvoMoveStart;
			// Move whole ending paragraph of the selection if selection ends at the beginning
			// of the paragraph
			if (ichEnd == 0)
				ihvoMoveStart = ihvoParaEnd;
			else
				ihvoMoveStart = ihvoParaEnd + 1;
			if (ihvoMoveStart < sectionEnd.ContentOA.ParagraphsOS.Count)
				m_cache.MoveOwningSequence(sectionEnd.ContentOAHvo,
					(int)StText.StTextTags.kflidParagraphs, ihvoMoveStart,
					sectionEnd.ContentOA.ParagraphsOS.Count - 1, sectionStart.ContentOAHvo,
					(int)StText.StTextTags.kflidParagraphs,
					sectionStart.ContentOA.ParagraphsOS.Count);

			// Copy end of last paragraph of selection to end of first paragraph of selection
			if (ichEnd > 0)
			{
				AboutToDelete(helper, paraEnd.Hvo, sectionEnd.ContentOA.Hvo,
					(int)StText.StTextTags.kflidParagraphs, ihvoParaEnd, false);

				ITsStrBldr endContentBldr = paraEnd.Contents.UnderlyingTsString.GetBldr();
				endContentBldr.Replace(0, ichEnd, string.Empty, null);
				int curEnd = startContentBldr.Length;
				startContentBldr.ReplaceTsString(curEnd, curEnd, endContentBldr.GetString());

				paraStart.StyleRules = paraEnd.StyleRules;
			}
			paraStart.Contents.UnderlyingTsString = startContentBldr.GetString();

			// Remove whole sections between start and end of selection, including the
			// ending section since content we want from it has been moved to the
			// starting section.
			for (iSection = ihvoSectionEnd; iSection > ihvoSectionStart; iSection--)
				book.SectionsOS.RemoveAt(iSection);
			// if selection starts at beginning of section head remove the whole beginning
			// section
			if (helper.IchAnchor == 0 &&
				helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[1].tag ==
				(int)ScrSection.ScrSectionTags.kflidHeading)
			{
				book.SectionsOS.RemoveAt(ihvoSectionStart);
				//set the IP to the end of the previous section
				if (ihvoSectionStart > 0)
				{
					ihvoSectionStart--;
					IScrSection section = book.SectionsOS[ihvoSectionStart];
					ihvoParaStart = section.ContentOA.ParagraphsOS.Count - 1;
					StTxtPara para = (StTxtPara) section.ContentOA.ParagraphsOS[ihvoParaStart];
					ichStart = para.Contents.Length;
				}
			}
			// Set the insertion point.
			SetInsertionPoint(ihvoBook, ihvoSectionStart, ihvoParaStart, ichStart,
				helper.AssocPrev);

			return true;
		}
Exemple #4
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// If a single section is wholly selected or the selection goes from the top of one
		/// section to the top of the following section, then the selected section may be
		/// deleted.
		/// </summary>
		/// <param name="helper"></param>
		/// <param name="topInfo"></param>
		/// <param name="bottomInfo"></param>
		/// <returns></returns>
		/// ------------------------------------------------------------------------------------
		private bool IsSectionDeletion(SelectionHelper helper, SelLevInfo[] topInfo,
			SelLevInfo[] bottomInfo)
		{
			bool sectionDeletion = false;
			ILocationTracker tracker = ((ITeView)Control).LocationTracker;

			int clev = tracker.GetLevelCount((int)ScrSection.ScrSectionTags.kflidContent);
			int levelText = helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidContent);
			if (levelText < 0)
				levelText = helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidHeading);
			int levelPara = helper.GetLevelForTag((int)StText.StTextTags.kflidParagraphs);
			// the selection must be the right number of levels deep.
			if (topInfo.Length == clev && bottomInfo.Length == clev && levelText >= 0 && levelPara >= 0)
			{
				// if the selection is in the same scripture and the same book...
				if (tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top) ==
					tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Bottom) &&
					// not selecting something weird
					topInfo[levelText - 1].tag == (int)StText.StTextTags.kflidParagraphs &&
					bottomInfo[levelText - 1].tag == (int)StText.StTextTags.kflidParagraphs)
				{
					// Selection top is in one section and bottom is in a following one
					if (tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top) <=
						tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Bottom) - 1 &&
						// if the selection begins and ends in section heading
						topInfo[levelText].tag == (int)ScrSection.ScrSectionTags.kflidHeading &&
						bottomInfo[levelText].tag == (int)ScrSection.ScrSectionTags.kflidHeading &&
						topInfo[levelText].ihvo == 0 &&
						bottomInfo[levelText].ihvo == 0 &&
						// and the selection begins and ends in the first paragraph of those headings
						topInfo[levelPara].ihvo == 0 &&
						bottomInfo[levelPara].ihvo == 0)
					{
						// Does selection go from the beginning of one heading to the beginning of another?
						sectionDeletion = (helper.IchAnchor == 0 && helper.IchEnd == 0);
					}
					// Selection starts at beginning of one section heading and ends
					// at end of content of another section.
					else if (tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top) <=
						tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Bottom) &&
						// Selection top is in section heading and bottom is in content
						topInfo[levelText].tag == (int)ScrSection.ScrSectionTags.kflidHeading &&
						bottomInfo[levelText].tag == (int)ScrSection.ScrSectionTags.kflidContent &&
						topInfo[levelText].ihvo == 0 &&
						bottomInfo[levelText].ihvo == 0 &&
						// Top of selection is in first heading paragraph
						topInfo[levelPara].ihvo == 0)
					{
						int ichTop = helper.GetIch(SelectionHelper.SelLimitType.Top);
						sectionDeletion =
							ichTop == 0 && IsSelectionAtEndOfSection(helper, bottomInfo, clev);
					}
				}
			}
			return sectionDeletion;
		}
Exemple #5
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Selections at end of section.
		/// </summary>
		/// <param name="helper">The helper.</param>
		/// <param name="bottomInfo">The bottom info.</param>
		/// <param name="clev">The clev.</param>
		/// <returns></returns>
		/// ------------------------------------------------------------------------------------
		private bool IsSelectionAtEndOfSection(SelectionHelper helper, SelLevInfo[] bottomInfo,
			int clev)
		{
			bool atEndOfSection = false;
			// Is the bottom of the selection in the last para of the section?
			ScrSection bottomSection = new ScrSection(m_cache,
				((ITeView)Control).LocationTracker.GetSectionHvo(
				helper, SelectionHelper.SelLimitType.Bottom));

			IStText bottomContent = bottomSection.ContentOA;
			int levelPara = helper.GetLevelForTag((int)StText.StTextTags.kflidParagraphs);
			if (bottomInfo[levelPara].ihvo == bottomContent.ParagraphsOS.Count - 1)
			{
				StTxtPara lastPara = new StTxtPara(m_cache, bottomInfo[levelPara].hvo);
				ITsString lastParaContents = lastPara.Contents.UnderlyingTsString;
				int ichBottom = helper.GetIch(SelectionHelper.SelLimitType.Bottom);
				atEndOfSection = ichBottom == lastParaContents.Length;
			}
			return atEndOfSection;
		}
		private void GetInsertionIndex(SelectionHelper sel, out ComplexConcPatternNode parent, out int index)
		{
			ComplexConcPatternNode curNode = GetNode(sel, SelectionHelper.SelLimitType.Top);
			if (m_patternModel.Root.IsLeaf || curNode == null)
			{
				parent = m_patternModel.Root;
				index = 0;
				return;
			}

			parent = curNode.Parent;
			int ich = sel.GetIch(SelectionHelper.SelLimitType.Top);
			index = GetNodeIndex(curNode);
			if (ich != 0)
				index++;
		}
Exemple #7
0
		/// ------------------------------------------------------------------------------------
		/// <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;
		}
		protected virtual int GetInsertionIndex(int[] hvos, SelectionHelper sel)
		{
			if (hvos.Length == 0)
			{
				return 0;
			}
			else
			{
				int curHvo = GetItemHvo(sel, SelectionHelper.SelLimitType.Top);
				int ich = sel.GetIch(SelectionHelper.SelLimitType.Top);
				for (int i = 0; i < hvos.Length; i++)
				{
					// if the current ich is 0, then we can safely assume we are at the beginning of
					// the current item, so insert before it, otherwise we are in the middle in which
					// case the entire item is selected or at the end, so we insert after
					if (hvos[i] == curHvo)
						return ich == 0 ? i : i + 1;
				}
				return hvos.Length;
			}
		}
Exemple #9
0
			/// --------------------------------------------------------------------------------
			/// <summary>
			/// Initializes a new instance of the <see cref="LocationInfo"/> class.
			/// </summary>
			/// <param name="helper">The selection helper used to initialize this location.
			/// </param>
			/// --------------------------------------------------------------------------------
			public LocationInfo(SelectionHelper helper)
			{
				m_location = helper.GetLevelInfo(SelectionHelper.SelLimitType.Bottom);
				m_tag = helper.GetTextPropId(SelectionHelper.SelLimitType.Bottom);
				m_ichMin = m_ichLim = helper.GetIch(SelectionHelper.SelLimitType.Bottom);
				m_cpropPrev = helper.GetNumberOfPreviousProps(SelectionHelper.SelLimitType.Bottom);
				m_ws = SelectionHelper.GetFirstWsOfSelection(helper.Selection);
			}
Exemple #10
0
		/// ------------------------------------------------------------------------------------
		/// <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)}; ;
		}
		protected virtual int GetInsertionIndex(ICmObject[] objs, SelectionHelper sel)
		{
			if (objs.Length == 0)
			{
				return 0;
			}
			ICmObject curObj = GetCmObject(sel, SelectionHelper.SelLimitType.Top);
			int ich = sel.GetIch(SelectionHelper.SelLimitType.Top);
			for (int i = 0; i < objs.Length; i++)
			{
				// if the current ich is 0, then we can safely assume we are at the beginning of
				// the current item, so insert before it, otherwise we are in the middle in which
				// case the entire item is selected or at the end, so we insert after
				if (objs[i] == curObj)
					return ich == 0 ? i : i + 1;
			}
			return objs.Length;
		}
Exemple #12
0
		/// ------------------------------------------------------------------------------------
		/// <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);
		}
Exemple #13
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Delete the given selection, removing any spanned sections. Selection is assumed to
		/// start in content of one section and end in content of another section.
		/// </summary>
		/// <param name="helper"></param>
		/// <returns></returns>
		/// ------------------------------------------------------------------------------------
		private bool DeleteMultiSectionContentRange(SelectionHelper helper)
		{
			if (helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[0].tag !=
				StTextTags.kflidParagraphs)
			{
				// Something changed catastrophically. StText has something in it other than paragraphs!
				Debug.Assert(false);
				return false;
			}

			ILocationTracker tracker = ((ITeView)Control).LocationTracker;
			int iBook = tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top);
			int iSectionStart = tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top);
			int iSectionEnd = tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Bottom);
			if (iBook < 0 || iSectionStart < 0 || iSectionEnd < 0)
			{
				// Something changed catastrophically. Maybe we added introductory material?
				Debug.Assert(false);
				return false;
			}

			int iParaStart = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[0].ihvo;
			int iParaEnd = helper.GetLevelInfo(SelectionHelper.SelLimitType.Bottom)[0].ihvo;
			int ichStart = helper.GetIch(SelectionHelper.SelLimitType.Top);
			int ichEnd = helper.GetIch(SelectionHelper.SelLimitType.Bottom);

			// Do the deletion
			IScrBook book = BookFilter.GetBook(iBook);
			book.DeleteMultiSectionContentRange(iSectionStart, iSectionEnd, iParaStart,
				iParaEnd, ichStart, ichEnd);

			// Set the insertion point.
			SetInsertionPoint(iBook, iSectionStart, iParaStart, ichStart,
				helper.AssocPrev);

			return true;
		}
Exemple #14
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Makes changes in text structure when the context of the new paragraph style does not
		/// match the context of the current paragraph style, and applies the new paragraph style.
		/// </summary>
		/// <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>
		/// ------------------------------------------------------------------------------------
		private void 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(ScrSectionTags.kflidContent);

			// Adjustments will only be done in section level selections.
			if (top.Length != scrLevelCount || bottom.Length != scrLevelCount)
				return;

			// 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 == ScrSectionTags.kflidHeading &&
				newStyle.Structure == StructureValues.Body)
			{
				// These current indices will be adjusted after the structure is changed
				// to indicate where the new selection should be
				int iSection = tracker.GetSectionIndexInBook(selHelper, SelectionHelper.SelLimitType.Top);
				int iPara;
				int iBook = tracker.GetBookIndex(selHelper, SelectionHelper.SelLimitType.Top);
				IScrBook book = BookFilter.GetBook(iBook);
				IScrSection section = book[iSection];

				// bool indicates if this section is the first one in either Intro or Scripture
				bool firstSectionInContext;
				if (iSection == 0)
					firstSectionInContext = true;
				else
					firstSectionInContext = !SectionsHaveSameContext(section, section.PreviousSection);

				// If all paragraphs of heading are selected, merge selected section
				// with previous section
				if (AreAllParagraphsSelected(top, bottom, section.HeadingOA))
				{
					if (!firstSectionInContext)
					{
						iPara = book.MergeSectionIntoPreviousSectionContent(iSection, newStyle);
						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, newStyle);
					}
				}
				// 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 = book.MoveHeadingParasToPreviousSectionContent(iSection, bottom[0].ihvo, newStyle);
						iSection--;
					}
					else
					{
						// This is the first section in context, and the selection includes the first para of the heading.
						// In this case, we want the selected paragraphs to become the content
						// of the first section, and the following section head
						// paragraph(s) become the heading of a new section object.
						section.SplitSectionHeading_ExistingParaBecomesContent(top[0].ihvo,
							bottom[0].ihvo, newStyle);
						// 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, newStyle);
						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) to become the heading of a new section object.
					{
						int iParaStart = top[0].ihvo;
						int iParabottom = bottom[0].ihvo;
						section.SplitSectionHeading_ExistingParaBecomesContent(iParaStart, iParabottom, newStyle);

						iPara = 0;
					}
				}

				// Select the original range of paragraphs and characters, now in the new content para
				// TODO: FWR-1542 Currently, a selection made during a unit of work can only be an insertion point.
				SelectRangeOfChars(iBook, iSection, ScrSectionTags.kflidContent, iPara,
					selHelper.GetIch(SelectionHelper.SelLimitType.Top),
					selHelper.GetIch(SelectionHelper.SelLimitType.Top),
					true, true, selHelper.AssocPrev);

			} //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 and the paragraph(s)
			// is/are part of the section content.
			else if (top[1].tag == ScrSectionTags.kflidContent &&
				newStyle.Structure == StructureValues.Heading)
			{
				IScrSection section = tracker.GetSection(selHelper, SelectionHelper.SelLimitType.Top);
				int iBook = tracker.GetBookIndex(selHelper, SelectionHelper.SelLimitType.Top);
				int iSection = tracker.GetSectionIndexInBook(selHelper, SelectionHelper.SelLimitType.Top);
				int iPara;
				IScrBook book = (IScrBook)section.Owner;

				// bool indicates if this section is the last one in either Intro or Scripture
				bool lastSectionInContext;
				if (iSection == book.SectionsOS.Count - 1) // last section ends book
					lastSectionInContext = true;
				else
					lastSectionInContext = !SectionsHaveSameContext(section, section.NextSection);

				try
				{
					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 = book.MergeSectionIntoNextSectionHeading(iSection, newStyle);
						}
						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, newStyle);
						}
					}
					else if (top[0].ihvo == 0) //selection starts at first content para
					{
						// Move the first content paragraphs to become the last para of the
						// section head
						section.MoveContentParasToHeading(bottom[0].ihvo, newStyle);

						iPara = section.HeadingOA.ParagraphsOS.Count -
								(bottom[0].ihvo - top[0].ihvo + 1);
					}
					else if (bottom[0].ihvo == section.ContentOA.ParagraphsOS.Count - 1 //selection ends at last content para
							 && !lastSectionInContext) // this is not the last Intro or Scripture section
					{
						// Move the last content paragraphs to become the first para of the next
						// section in the book.
						book.MoveContentParasToNextSectionHeading(iSection, top[0].ihvo, newStyle);
						// update insertion point to first paragraph(s) of next section head
						iSection++;
						iPara = 0;
					}
					else
					{
						// Selection is of middle paragraph(s) in the contents,
						// or selection includes the last para of the last intro section or last Scripture section.
						// In this case, we want the selected paragraph to become the heading
						// of a new section, and the following paragraph(s), if any, become the
						// content of the new section object.
						section.SplitSectionContent_ExistingParaBecomesHeading(
							top[0].ihvo, bottom[0].ihvo - top[0].ihvo + 1, newStyle);
						// update insertion point to first paragraph(s) of next section head
						iSection++;
						iPara = 0;
					}
				}
				catch (InvalidStructureException e)
				{
					// Cancel the request if chapter or verse numbers are present.
					DisplayMessage(TeResourceHelper.GetResourceString("kstidParaHasNumbers"));
					return;
				}

				// Select the original range of paragraphs and characters, now in the new heading
				// TODO: FWR-1542 Currently, a selection made during a unit of work can only be an insertion point.
				SelectRangeOfChars(iBook, iSection, ScrSectionTags.kflidHeading, iPara,
					selHelper.GetIch(SelectionHelper.SelLimitType.Top),
					selHelper.GetIch(SelectionHelper.SelLimitType.Top),
					true, true, selHelper.AssocPrev);
			}
			return;
		}
		private void UpdateSelectionForReplacingPreeditText(SelectionHelper selHelper, int countBackspace)
		{
			if ((m_ActionHandler == null || !m_ActionHandler.get_TasksSinceMark(true))
				&& m_InitialSelection != null && m_EndOfPreedit != null)
			{
				// we don't have an action handler (or we have nothing to rollback) which means
				// we didn't roll back the preedit. This means we have to create a range selection
				// that deletes the preedit.
				var bottom = selHelper.GetIch(SelectionHelper.SelLimitType.Bottom);
				selHelper.IchAnchor = Math.Max(0,
					m_InitialSelection.SelectionHelper.GetIch(SelectionHelper.SelLimitType.Top) - countBackspace);
				selHelper.IchEnd = Math.Max(bottom,
					m_EndOfPreedit.GetIch(SelectionHelper.SelLimitType.Bottom));
				selHelper.SetSelection(true);
			}
		}
		/// ------------------------------------------------------------------------------------
		/// <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();
					}
				}
			}
		}