GetLevelInfo() public method

Gets the array of VwSelLevInfo. Array elements should indicate the chain of objects that needs to be traversed to get from the root object to object where the selection is to be made. The tag for item n should be the flid in which the children of the root object are owned. The 0th element of this array must have its tag value set to BaseStText.StTextTags.kflidParagraphs. This is set automatically whenever the array is resized using Cvsli.
public GetLevelInfo ( SelLimitType type ) : SIL.FieldWorks.Common.COMInterfaces.SelLevInfo[]
type SelLimitType type
return SIL.FieldWorks.Common.COMInterfaces.SelLevInfo[]
示例#1
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Merges the paras in table.
		/// </summary>
		/// <param name="helper">The helper.</param>
		/// <param name="dpt">The problem deletion type.</param>
		/// <returns><c>true</c> if we merged the paras, otherwise <c>false</c>.</returns>
		/// ------------------------------------------------------------------------------------
		protected internal bool MergeParasInTable(SelectionHelper helper, VwDelProbType dpt)
		{
			SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top);
			if (levInfo[0].tag != StTextTags.kflidParagraphs)
				return false;
			IStText text;
			int iPara;
			int tag;
			IStTxtPara currPara = GetPara(helper, out text, out iPara, out tag);

			// Backspace at beginning of paragraph
			ITsStrBldr bldr;
			if (dpt == VwDelProbType.kdptBsAtStartPara)
			{
				if (iPara <= 0)
				{
					MiscUtils.ErrorBeep();
					return false;
				}

				IStTxtPara prevPara = text[iPara - 1];
				int prevParaLen = prevPara.Contents.Length;

				prevPara.MergeParaWithNext();

				helper.SetIch(SelectionHelper.SelLimitType.Top, prevParaLen);
				helper.SetIch(SelectionHelper.SelLimitType.Bottom, prevParaLen);
				levInfo[0].ihvo = iPara - 1;
				helper.SetLevelInfo(SelectionHelper.SelLimitType.Top, levInfo);
				helper.SetLevelInfo(SelectionHelper.SelLimitType.Bottom, levInfo);
				if (DeferSelectionUntilEndOfUOW)
				{
					// We are within a unit of work, so setting the selection will not work now.
					// we request that a selection be made after the unit of work.
					Debug.Assert(!helper.IsRange,
						"Currently, a selection made during a unit of work can only be an insertion point.");
					helper.SetIPAfterUOW(EditedRootBox.Site);
				}
				else
				{
					helper.SetSelection(true);
				}
				return true;
			}
			// delete at end of a paragraph
			int cParas = text.ParagraphsOS.Count;
			if (iPara + 1 >= cParas)
				return false; // We don't handle merging across StTexts

			currPara.MergeParaWithNext();

			if (DeferSelectionUntilEndOfUOW)
			{
				// We are within a unit of work, so setting the selection will not work now.
				// we request that a selection be made after the unit of work.
				Debug.Assert(!helper.IsRange,
					"Currently, a selection made during a unit of work can only be an insertion point.");
				helper.SetIPAfterUOW(EditedRootBox.Site);
			}
			else
			{
				helper.SetSelection(true);
			}
			return true;
		}
		protected override int GetCell(SelectionHelper sel, SelectionHelper.SelLimitType limit)
		{
			if (sel == null)
				return -1;

			int tag = sel.GetTextPropId(limit);
			if (tag == AffixRuleFormulaVc.ktagLeftEmpty
				|| tag == AffixRuleFormulaVc.ktagRightEmpty
				|| tag == MoAffixProcessTags.kflidOutput)
				return tag;

			foreach (SelLevInfo level in sel.GetLevelInfo(limit))
			{
				if (level.tag == MoAffixProcessTags.kflidOutput)
					return level.tag;
				if (level.tag == MoAffixProcessTags.kflidInput)
					return level.hvo;
			}

			return -1;
		}
示例#3
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Convert the scripture book tag to a filter tag.  Also, convert book indices to
		/// filtered book indices.  This is done when loading a selection to make it work
		/// in the context of the book filter.
		/// </summary>
		/// <param name="helper"></param>
		/// <param name="selType"></param>
		/// ------------------------------------------------------------------------------------
		private void ConvertBookTagAndIndex(SelectionHelper helper,
			SelectionHelper.SelLimitType selType)
		{
			SelLevInfo[] info = helper.GetLevelInfo(selType);
			int bookPos = info.Length - 1;
			if (info[bookPos].tag == ScriptureTags.kflidScriptureBooks)
			{
				info[bookPos].tag = BookFilter.Tag;
				info[bookPos].ihvo = BookFilter.GetBookIndex(
					m_fdoCache.ServiceLocator.GetInstance<IScrBookRepository>().GetObject(info[bookPos].hvo));
				helper.SetLevelInfo(selType, info);
			}
		}
示例#4
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Handles deletion of empty section content paragraph on delete key being pressed at
		/// text boundary.
		/// </summary>
		/// <param name="helper">The selection helper.</param>
		/// <returns><c>true</c> if we merged the sections, otherwise <c>false</c>.</returns>
		/// ------------------------------------------------------------------------------------
		private bool HandleDeleteBeforeEmptySectionContentParagraph(SelectionHelper helper)
		{
			// delete problem deletion will occur at end of section heading
			SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top);
			ILocationTracker tracker = ((ITeView)Control).LocationTracker;
			ScrBook book = new ScrBook(m_cache, tracker.GetBookHvo(helper,
				SelectionHelper.SelLimitType.Top));
			int iSection = tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top);
			IScrSection section = book.SectionsOS[iSection];
			int cParas = section.ContentOA != null ? section.ContentOA.ParagraphsOS.Count : 0;
			if (cParas > 0)
			{
				// If we are the end of heading before a multi-paragraph content
				// and the first paragraph is empty, we delete the first paragraph of
				// the content.
				if (cParas > 1)
				{
					StTxtPara para = (StTxtPara)section.ContentOA.ParagraphsOS[0];
					if (para.Contents.Length == 0)
					{
						section.ContentOA.ParagraphsOS.RemoveAt(0);
						return true;
					}
				}
				// If we are at end of section heading or beginning of section content
				// and not in the last section, we should merge sections.
				else
				{
					if (iSection == book.SectionsOS.Count - 1)
						return false;
					StTxtPara para = (StTxtPara)section.ContentOA.ParagraphsOS[0];
					if (para.Contents.Length == 0)
					{
						return MergeWithFollowingSectionIfInSameContext(helper, book, iSection,
							section, true);
					}
				}
			}
			else
			{
				return MergeWithFollowingSectionIfInSameContext(helper, book, iSection,
					section, true);
			}
			return false;
		}
示例#5
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Deletes a section heading.
		/// </summary>
		/// <param name="helper">Selection information</param>
		/// <param name="allowHeadingText">if <code>true</code> section head will be deleted
		/// even if heading contains text</param>
		/// <param name="positionAtEnd">if <code>true</code> IP will be at end of paragraph
		/// before top point of current selection</param>
		/// <returns><code>true</code> if deletion was done</returns>
		/// ------------------------------------------------------------------------------------
		private bool DeleteSectionHead(SelectionHelper helper, bool allowHeadingText,
			bool positionAtEnd)
		{
			ILocationTracker tracker = ((ITeView)Control).LocationTracker;
			if (helper.GetNumberOfLevels(SelectionHelper.SelLimitType.Top) !=
				tracker.GetLevelCount((int)ScrSection.ScrSectionTags.kflidContent))
				return false;
			int tag = helper.GetTextPropId(SelectionHelper.SelLimitType.Top);
			if (tag != (int)StTxtPara.StTxtParaTags.kflidContents &&
				tag != SimpleRootSite.kTagUserPrompt)
			{
				// Currently this is the only possible leaf property in draft view;
				// if this changes somehow, we'll probably need to enhance this code.
				Debug.Assert(false);
				return false;
			}
			int hvoBook = tracker.GetBookHvo(helper, SelectionHelper.SelLimitType.Top);
			if (hvoBook < 0)
			{
				Debug.Assert(false);
				return false;
			}
			ScrBook book = new ScrBook(m_cache, hvoBook);

			int iSection = tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top);
			if (iSection < 0)
			{
				// Something changed catastrophically. Book has something in it other than sections.
				Debug.Assert(false);
				return false;
			}
			IScrSection section = book.SectionsOS[iSection];

			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;
			}
			// For now we just handle the heading.
			if (helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[1].tag !=
				(int)ScrSection.ScrSectionTags.kflidHeading)
			{
				// Add code here if desired to handle bsp/del at boundary of body.
				return false;
			}

			// OK, we're dealing with a change at the boundary of a section heading
			// (in a paragraph of an StText that is the heading of an ScrSection in an ScrBook).
			IStText text = section.HeadingOA;
			int ihvoPara = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[0].ihvo;
			IStTxtPara para = (IStTxtPara)(text.ParagraphsOS[ihvoPara]);

			if (!allowHeadingText && para.Contents.Length > 0)
			{
				// The current heading paragraph has something in it!
				// For now we won't try to handle this.
				// (The problem is knowing what to do with the undeleted header text...
				// make it part of the previous section? The previous header? Delete it?)
				return false;
			}
			if (text.ParagraphsOS.Count != 1)
			{
				// Backspace at start or delete at end of non-empty section, and the paragraph is
				// empty. Do nothing.
				return false;

				// Other options:
				// - delete the section? But what do we do with the rest of its heading?
				// - delete the empty paragraph? That's easy...just
				//		text.ParagraphsOS.RemoveAt(ihvoPara);
				// But where do we put the IP afterwards? At the end of the previous body,
				// for bsp, or the start of our own body, for del? Or keep it in the heading?
			}
			// OK, we're in a completely empty section heading.
			// If it's the very first section of the book, we can't join it to the previous
			// section, so do nothing. (May eventually enhance to join the two books...
			// perhaps after asking for confirmation!)
			if (iSection == 0)
				return false;
			// Finally...we know we're going to merge the two sections.
			MergeContentWithPreviousSection(helper, book, section, iSection, positionAtEnd);
			return true;
		}
示例#6
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Handles deletions where the selection is not contained within paragraphs of a
		/// single section.
		/// </summary>
		/// <param name="helper"></param>
		/// <returns><code>true</code> if deletion was handled</returns>
		/// ------------------------------------------------------------------------------------
		internal protected bool HandleComplexDeletion(SelectionHelper helper)
		{
			SelLevInfo[] topInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top);
			SelLevInfo[] bottomInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Bottom);

			// Determine if whole section head was deleted
			if (IsSectionHeadDeletion(helper, topInfo, bottomInfo))
			{
				return DeleteSectionHead(helper, true, false);
			}
			else if (IsSectionDeletion(helper, topInfo, bottomInfo))
			{
				return DeleteSections(helper, topInfo, bottomInfo);
			}
			else if (IsMultiSectionContentSelection(helper, topInfo, bottomInfo) &&
				SectionsHaveSameContext(helper, topInfo, bottomInfo))
			{
				return DeleteMultiSectionContentRange(helper);
			}
			else if (IsBookTitleSelection(helper, topInfo, bottomInfo))
			{
				return DeleteBookTitle();
			}
			else if (IsBookSelection(helper, topInfo, bottomInfo))
			{
				// Don't use BookIndex, since it will use anchor which may be wrong book.
				RemoveBook(((ITeView)Control).LocationTracker.GetBookIndex(
					helper, SelectionHelper.SelLimitType.Top));
				return true;
			}
			// TODO: Add complex deletion when deleting a range selection that includes two
			// partial sections.
			return false;
		}
示例#7
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Handles deletion of empty section heading paragraph on delete key being pressed at
		/// text boundary.
		/// </summary>
		/// <param name="helper"></param>
		/// <returns><c>true</c> if we handled the deletion, otherwise <c>false</c></returns>
		/// ------------------------------------------------------------------------------------
		private bool HandleDeleteBeforeEmptySectionHeadParagraph(SelectionHelper helper)
		{
			SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top);
			ScrBook book = new ScrBook(m_cache, ((ITeView)Control).LocationTracker.GetBookHvo(
				helper, SelectionHelper.SelLimitType.Top));

			// Delete problem deletion will be at end of last paragraph of content,
			// need to check following section head (if available)

			// Get next section of book.
			int iSection = ((ITeView)Control).LocationTracker.GetSectionIndexInBook(
				helper, SelectionHelper.SelLimitType.Top);

			bool positionAtEnd = false;
			if (!InSectionHead)
			{
				iSection++;
				if (iSection > book.SectionsOS.Count - 1)
					return false;
				positionAtEnd = true;
			}
			else if (iSection == 0)
				return false;

			IScrSection section = book.SectionsOS[iSection];

			if (section.HeadingOA == null || section.HeadingOA.ParagraphsOS.Count == 0)
			{
				// don't crash if database is corrupt - allow user to merge the two
				// sections (TE-4869)
				return MergeWithPreviousSectionIfInSameContext(helper, book,
					section, iSection, positionAtEnd);
			}
			else
			{
				// if there are more than one paragraph in heading, check to see if first
				// paragraph can be deleted.
				if (section.HeadingOA.ParagraphsOS.Count > 1)
				{
					StTxtPara para = (StTxtPara)section.HeadingOA.ParagraphsOS[0];
					if (para.Contents.Length == 0)
					{
						section.HeadingOA.ParagraphsOS.RemoveAt(0);
						return true;
					}
				}
				// If we are at end of content before an empty section head,
				// we should merge sections.
				else
				{
					StTxtPara para = (StTxtPara)section.HeadingOA.ParagraphsOS[0];
					if (para.Contents.Length == 0)
					{
						return MergeWithPreviousSectionIfInSameContext(helper, book,
							section, iSection, positionAtEnd);
					}
				}
			}

			return false;
		}
		protected override ICmObject GetItem(SelectionHelper sel, SelectionHelper.SelLimitType limit)
		{
			if (Rule.StrucDescOS.Count == 0 || sel.GetNumberOfLevels(limit) == 0)
				return null;

			var levels = sel.GetLevelInfo(limit);
			return m_cache.ServiceLocator.GetObject(levels[levels.Length - 1].hvo);
		}
示例#9
0
			/// ------------------------------------------------------------------------------------
			/// <summary>
			/// Set both book and section. Don't make a selection; typically the caller will proceed
			/// to do that.
			/// </summary>
			/// <param name="selHelper">The selection helper.</param>
			/// <param name="selLimitType">Which end of the selection</param>
			/// <param name="iBook">The index of the book (in the book filter).</param>
			/// <param name="iSection">The index of the section (relative to
			/// <paramref name="iBook"/>), or -1 for a selection that is not in a section (e.g.
			/// title).</param>
			/// <remarks>This method should change only the book and section levels of the
			/// selection, but not any other level.</remarks>
			/// ------------------------------------------------------------------------------------
			public override void SetBookAndSection(SelectionHelper selHelper,
				SelectionHelper.SelLimitType selLimitType, int iBook, int iSection)
			{
				if (selHelper == null)
					return;

				// we can only deal with one book
				if (iBook != GetBookIndex(null, selLimitType) || iSection < 0)
					return;

				int nLevels = selHelper.GetNumberOfLevels(selLimitType);
				selHelper.GetLevelInfo(selLimitType)[nLevels - 1].tag =
					(int)ScrBook.ScrBookTags.kflidSections;
				selHelper.GetLevelInfo(selLimitType)[nLevels - 1].ihvo = iSection;
			}
示例#10
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Get the index of the section (relative to RootBox), or -1 if we're not in a section
		/// (e.g. the IP is in a title).
		/// </summary>
		/// <param name="selHelper">The selection helper.</param>
		/// <param name="selLimitType">Which end of the selection</param>
		/// <returns>
		/// Index of the section, or -1 if we're not in a section.
		/// </returns>
		/// <remarks>The returned value is suitable for making a selection.</remarks>
		/// ------------------------------------------------------------------------------------
		public virtual int GetSectionIndexInView(SelectionHelper selHelper,
			SelectionHelper.SelLimitType selLimitType)
		{
			int sectionLevel = GetSectionLevel(selHelper, selLimitType);
			return sectionLevel >= 0 ? selHelper.GetLevelInfo(selLimitType)[sectionLevel].ihvo : -1;
		}
示例#11
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Set both book and section. Don't make a selection; typically the caller will proceed
		/// to do that.
		/// </summary>
		/// <param name="selHelper">The selection helper.</param>
		/// <param name="selLimitType">Which end of the selection</param>
		/// <param name="iBook">The index of the book (in the book filter).</param>
		/// <param name="iSection">The index of the section (relative to
		/// <paramref name="iBook"/>), or -1 for a selection that is not in a section (e.g.
		/// title).</param>
		/// <remarks>This method should change only the book and section levels of the
		/// selection, but not any other level.</remarks>
		/// ------------------------------------------------------------------------------------
		public virtual void SetBookAndSection(SelectionHelper selHelper,
			SelectionHelper.SelLimitType selLimitType, int iBook, int iSection)
		{
			if (!Visible)
				return;

			int newHvoBook = m_bookFilter.GetBook(iBook).Hvo;
			ScrBook book = new ScrBook(m_cache, newHvoBook);
			int[] hvoAllSections = book.SectionsOS.HvoArray;
			if (iSection < 0 || iSection >= hvoAllSections.Length)
				return; // We won't be able to find our section (TE-8242)

			foreach (DivisionLayoutMgr div in Divisions)
			{
				if (div.Configurer.MainObjectId != newHvoBook)
					continue; // We don't care about the division if it doesn't use our book

				FocusedStream = div.MainLayoutStream;

				TePrintLayoutConfig configurer = div.Configurer as TePrintLayoutConfig;
				if (configurer == null)
					continue;

				int hvoSection = hvoAllSections[iSection];
				IFilter filter = configurer.SectionFilter.Filter;
				if (!filter.MatchesCriteria(hvoSection))
				{
					// This division doesn't contain the desired section, so we try
					// the following section
					continue;
				}

				// Find the index of the section in the filtered section list,
				// i.e. in the view
				int iSectionInView = -1;
				int iSectionLim = Math.Min(hvoAllSections.Length, iSection + 1);
				for (int iSectionInBook = 0; iSectionInBook < iSectionLim;
					iSectionInBook++)
				{
					if (filter.MatchesCriteria(hvoAllSections[iSectionInBook]))
						iSectionInView++;
				}

				if (iSectionInView < 0)
					continue;

				selHelper.GetLevelInfo(selLimitType)[selHelper.GetNumberOfLevels(selLimitType) - 1].tag =
					GetSectionTag(configurer);
				selHelper.GetLevelInfo(selLimitType)[selHelper.GetNumberOfLevels(selLimitType) - 1].ihvo =
					iSectionInView;

				// We found the division that used the book we care about so lets quit
				return;
			}

			ApplicationException e = new ApplicationException(
				"Can't find division for given book and index");
			e.Data.Add("iBook", iBook);
			e.Data.Add("iSection", iSection);
			e.Data.Add("View name", Name);
			throw e;
		}
示例#12
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Gets the current section, or null if we're not in a section (e.g. the IP is in a title).
		/// </summary>
		/// <param name="selHelper">The selection helper.</param>
		/// <param name="selLimitType">Which end of the selection</param>
		/// <returns>The current section, or null</returns>
		/// ------------------------------------------------------------------------------------
		public virtual IScrSection GetSection(SelectionHelper selHelper,
			SelectionHelper.SelLimitType selLimitType)
		{
			int sectionLevel = GetSectionLevel(selHelper, selLimitType);
			int hvoSection = (sectionLevel >= 0) ?
				selHelper.GetLevelInfo(selLimitType)[sectionLevel].hvo : -1;
			// section may have been deleted - stale reference can happen if this view is not active when book
			// is deleted
			ICmObject section;
			if (hvoSection >= 0 && Cache.ServiceLocator.ObjectRepository.TryGetObject(hvoSection, out section))
				return section as IScrSection;
			return null;
		}
示例#13
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Finds the nearest footnote before the given selection.
		/// </summary>
		/// <param name="helper">The selection helper.</param>
		/// <param name="book">The book that owns the footnote collection.</param>
		/// <param name="fSearchForward">True to also search forward within the current paragraph</param>
		/// <returns></returns>
		/// ------------------------------------------------------------------------------------
		private IStFootnote FindFootnoteNearSelection(SelectionHelper helper, IScrBook book,
			bool fSearchForward)
		{
			CheckDisposed();

			if (helper == null)
				helper = CurrentSelection;
			if (helper == null || book == null)
				return null;

			SelLevInfo[] levels = helper.GetLevelInfo(SelectionHelper.SelLimitType.Anchor);

			int iParagraph = -1;
			int tag = 0;
			int ich = helper.IchAnchor;
			int paraLev = helper.GetLevelForTag(StTextTags.kflidParagraphs);
			int contentLev = helper.GetLevelForTag(StTxtParaTags.kflidContents);

			Debug.Assert(paraLev != -1, "Need a paragraph for this method");
			iParagraph = levels[paraLev].ihvo;

			int iSection = ((ITeView)Control).LocationTracker.GetSectionIndexInBook(
				helper, SelectionHelper.SelLimitType.Anchor);

			if (iSection < 0)
				tag = ScrBookTags.kflidTitle;
			else
			{
				tag = (helper.GetLevelForTag(ScrSectionTags.kflidContent) >= 0 ?
					ScrSectionTags.kflidContent : ScrSectionTags.kflidHeading);
			}

			// Special case: if we're in the caption of a picture, get the ich from
			// the first level instead of the anchor. (TE-4696)
			if (contentLev >= 0 && levels[contentLev].ihvo == -1)
				ich = levels[contentLev].ich;

			IScrFootnote prevFootnote = null;
			if (fSearchForward) // look first at our current position, if we are searching foward
				prevFootnote = book.FindCurrentFootnote(iSection, iParagraph, ich, (int)tag);

			if (prevFootnote == null)
			{
				IScrTxtPara para = m_repoScrTxtPara.GetObject(levels[paraLev].hvo);
				ITsString tss = para.Contents;
				if (ich != 0)
				{
					// look backwards in our current paragraph - skip the current run, except when
					// at the end of the text.
					prevFootnote = para.FindPrevFootnoteInContents(ref ich, ich < tss.Length);
				}
				else if (iParagraph > 0)
				{
					// look at the previous paragraph for a footnote at the end
					IStText text = m_repoStText.GetObject(levels[paraLev + 1].hvo);
					IScrTxtPara prevPara = (IScrTxtPara)text[iParagraph - 1];
					ITsString prevTss = prevPara.Contents;
					int ichTmp = -1;
					prevFootnote = prevPara.FindPrevFootnoteInContents(ref ichTmp, false);
					if (prevFootnote != null)
					{
						if (ichTmp == prevTss.Length - 1)
							ich = ichTmp;
						else
							prevFootnote = null;
					}
					// ENHANCE: Look across contexts.
				}
			}
			if (prevFootnote == null && fSearchForward)
			{
				// look ahead in the same paragraph
				IScrTxtPara para = m_repoScrTxtPara.GetObject(levels[paraLev].hvo);
				ITsString tss = para.Contents;
				prevFootnote = para.FindNextFootnoteInContents(ref ich, true);
			}
			if (prevFootnote == null)
			{
				// just go back until we find one
				prevFootnote = book.FindPrevFootnote(ref iSection, ref iParagraph, ref ich, ref tag);
			}

			return prevFootnote;
		}
示例#14
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;
		}
示例#15
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Try to do something about an IP selection deletion that is at the start or end of an
		/// StText. If successful return true, otherwise false.
		/// </summary>
		/// <param name="helper"></param>
		/// <param name="dpt"></param>
		/// <returns><c>true</c> if we successfully handled the deletion.</returns>
		/// ------------------------------------------------------------------------------------
		internal bool HandleBsOrDelAtTextBoundary(SelectionHelper helper, VwDelProbType dpt)
		{
			CheckDisposed();

			SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Anchor);

			ILocationTracker tracker = ((ITeView)Control).LocationTracker;
			// bail out if we are not in a paragraph within a scripture section
			if (levInfo.Length !=
				tracker.GetLevelCount((int)ScrSection.ScrSectionTags.kflidContent) ||
				tracker.GetSectionIndexInView(helper, SelectionHelper.SelLimitType.Anchor) < 0 ||
				levInfo[0].tag != (int)StText.StTextTags.kflidParagraphs)
			{
				// Assume we are in a book title
				SelLevInfo dummyInfo;
				if (helper.GetLevelInfoForTag((int)ScrBook.ScrBookTags.kflidTitle, out dummyInfo))
					return MergeParasInTable(helper, dpt);
				return false;
			}

			// Level 1 will have tags showing which field of section is selected
			int iLevelSection = helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidHeading);
			if (iLevelSection >= 0)
			{
				if (levInfo[0].ihvo == 0 && dpt == VwDelProbType.kdptBsAtStartPara)
				{
					// first paragraph of section head
					return HandleBackspaceAfterEmptyContentParagraph(helper);
				}
				else if (levInfo[0].ihvo == 0 && helper.IchAnchor == 0)
				{
					// Delete was pressed in an empty section head - try to combine with previous
					// return DeleteSectionHead(helper, false, false);
					if (dpt == VwDelProbType.kdptBsAtStartPara)
						return HandleBackspaceAfterEmptySectionHeadParagraph(helper);
					return HandleDeleteBeforeEmptySectionHeadParagraph(helper);
				}
				// NOTE: we check the vector size for the parent of the paragraph (levInfo[1].hvo)
				// but with our own tag (levInfo[0].tag)!
				else if (levInfo[0].ihvo == m_cache.GetVectorSize(levInfo[iLevelSection].hvo,
					levInfo[0].tag) - 1
					&& dpt == VwDelProbType.kdptDelAtEndPara)
				{
					// last paragraph of section head
					return HandleDeleteBeforeEmptySectionContentParagraph(helper);
				}
				else
				{
					// other problem deletion: e.g. delete in BT side-by-side view. Because
					// we're displaying the paragraphs in a table with two columns, the views
					// code can't handle that. We have to merge the two paragraphs manually.
					return MergeParasInTable(helper, dpt);
				}
			}
			else if (helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidContent) >= 0)
			{
				iLevelSection = helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidContent);
				if (levInfo[0].ihvo == 0 && dpt == VwDelProbType.kdptBsAtStartPara)
				{
					// first paragraph of section
					return HandleBackspaceAfterEmptySectionHeadParagraph(helper);
				}
				else if (levInfo[0].ihvo == 0 && helper.IchAnchor == 0)
				{
					// Delete was pressed in an empty section content - try to combine with previous
					if (dpt == VwDelProbType.kdptBsAtStartPara)
						return HandleBackspaceAfterEmptyContentParagraph(helper);
					return HandleDeleteBeforeEmptySectionContentParagraph(helper);
				}
				// NOTE: we check the vector size for the parent of the paragraph (levInfo[1].hvo)
				// but with our own tag (levInfo[0].tag)!
				else if (levInfo[0].ihvo == m_cache.GetVectorSize(levInfo[iLevelSection].hvo,
					levInfo[0].tag) - 1 && dpt == VwDelProbType.kdptDelAtEndPara)
				{
					// last paragraph of section
					return HandleDeleteBeforeEmptySectionHeadParagraph(helper);
				}
				else
				{
					// other problem deletion: e.g. delete in BT side-by-side view. Because
					// we're displaying the paragraphs in a table with two columns, the views
					// code can't handle that. We have to merge the two paragraphs manually.
					return MergeParasInTable(helper, dpt);
				}
			}
			return false;
		}
示例#16
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);
			}
示例#17
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Merges the paras in table.
		/// </summary>
		/// <param name="helper">The helper.</param>
		/// <param name="dpt">The problem deletion type.</param>
		/// <returns><c>true</c> if we merged the paras, otherwise <c>false</c>.</returns>
		/// ------------------------------------------------------------------------------------
		internal protected bool MergeParasInTable(SelectionHelper helper, VwDelProbType dpt)
		{
			SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top);
			if (levInfo[0].tag != (int)StText.StTextTags.kflidParagraphs)
				return false;

			ILocationTracker tracker = ((ITeView)Control).LocationTracker;
			IScrBook book = new ScrBook(m_cache, tracker.GetBookHvo(
				helper, SelectionHelper.SelLimitType.Anchor));

			SelLevInfo tmpInfo;
			IStText text;
			if (helper.GetLevelInfoForTag((int)ScrBook.ScrBookTags.kflidTitle, out tmpInfo))
				text = book.TitleOA;
			else
			{
				IScrSection section = book.SectionsOS[tracker.GetSectionIndexInBook(
					helper,	SelectionHelper.SelLimitType.Anchor)];

				text = (levInfo[1].tag == (int)ScrSection.ScrSectionTags.kflidHeading ?
					section.HeadingOA :	text = section.ContentOA);
			}

			int iPara = helper.GetLevelInfoForTag((int)StText.StTextTags.kflidParagraphs).ihvo;
			StTxtPara currPara = (StTxtPara)text.ParagraphsOS[iPara];
			ITsStrBldr bldr;

			// Backspace at beginning of paragraph
			if (dpt == VwDelProbType.kdptBsAtStartPara)
			{
				if (iPara <= 0)
				{
					MiscUtils.ErrorBeep();
					return false;
				}

				StTxtPara prevPara = (StTxtPara)text.ParagraphsOS[iPara - 1];
				int prevParaLen = prevPara.Contents.Length;

				// Need to make sure we move the back translations
				AboutToDelete(helper, currPara.Hvo, text.Hvo,
					(int)StText.StTextTags.kflidParagraphs, iPara, false);

				bldr = prevPara.Contents.UnderlyingTsString.GetBldr();
				bldr.ReplaceTsString(prevPara.Contents.Length, prevPara.Contents.Length,
					currPara.Contents.UnderlyingTsString);
				prevPara.Contents.UnderlyingTsString = bldr.GetString();
				text.ParagraphsOS.RemoveAt(iPara);
				helper.SetIch(SelectionHelper.SelLimitType.Top, prevParaLen);
				helper.SetIch(SelectionHelper.SelLimitType.Bottom, prevParaLen);
				levInfo[0].ihvo = iPara - 1;
				helper.SetLevelInfo(SelectionHelper.SelLimitType.Top, levInfo);
				helper.SetLevelInfo(SelectionHelper.SelLimitType.Bottom, levInfo);
				helper.SetSelection(true);
				return true;
			}
			// delete at end of a paragraph
			int cParas = text.ParagraphsOS.Count;
			if (iPara + 1 >= cParas)
				return false; // We don't handle merging across StTexts

			StTxtPara nextPara = (StTxtPara)text.ParagraphsOS[iPara + 1];

			// Need to make sure we move the back translations
			AboutToDelete(helper, nextPara.Hvo, text.Hvo,
				(int)StText.StTextTags.kflidParagraphs, iPara + 1, false);

			bldr = currPara.Contents.UnderlyingTsString.GetBldr();
			bldr.ReplaceTsString(currPara.Contents.Length, currPara.Contents.Length,
				nextPara.Contents.UnderlyingTsString);
			currPara.Contents.UnderlyingTsString = bldr.GetString();
			text.ParagraphsOS.RemoveAt(iPara + 1);
			helper.SetSelection(true);
			return true;
		}
示例#18
0
		protected override int GetItemHvo(SelectionHelper sel, SelectionHelper.SelLimitType limit)
		{
			if (Rule.StrucDescOS.Count == 0 || sel.GetNumberOfLevels(limit) == 0)
				return 0;

			SelLevInfo[] levels = sel.GetLevelInfo(limit);
			return levels[levels.Length - 1].hvo;
		}
示例#19
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;
		}
示例#20
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Deletes footnotes when there is a range selection.
		/// </summary>
		/// <param name="helper"></param>
		/// ------------------------------------------------------------------------------------
		private void DeleteFootnoteRange(SelectionHelper helper)
		{
			int nTopLevels = helper.GetNumberOfLevels(SelectionHelper.SelLimitType.Top);
			int nBottomLevels = helper.GetNumberOfLevels(SelectionHelper.SelLimitType.Bottom);

			// Get the index of the book containing the first footnote in the selection.
			// Then get the index of the footnote within that book.
			int iFirstBook =
				helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[nTopLevels-1].ihvo;
			int iFirstFootnote =
				helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[nTopLevels-2].ihvo;

			// Get the index of the book containing the last footnote in the selection.
			// Then get the index of the footnote within that book.
			int iLastBook =
				helper.GetLevelInfo(SelectionHelper.SelLimitType.Bottom)[nBottomLevels-1].ihvo;
			int iLastFootnote =
				helper.GetLevelInfo(SelectionHelper.SelLimitType.Bottom)[nBottomLevels-2].ihvo;

			// Loop through the books containing footnotes in the selection.
			for (int iBook = iFirstBook; iBook <= iLastBook; iBook++)
			{
				ScrBook book = BookFilter.GetBook(iBook);

				int iBeg = iFirstFootnote;
				if (iFirstBook != iLastBook && iBook > iFirstBook)
					iBeg = 0;

				int iEnd = iLastFootnote;
				if (iFirstBook != iLastBook && iBook < iLastBook)
					iEnd = book.FootnotesOS.Count - 1;

				// Loop through the footnotes from the selection that are in the
				// current book. Go in reverse order through the collection.
				for (int i = iEnd; i >= iBeg; i--)
				{
					// TODO: check filter for each HVO
					ScrFootnote footnote = new ScrFootnote(m_fdoCache, book.FootnotesOS[i].Hvo);
					ScrFootnote.DeleteFootnoteAndMarker(footnote);
				}
			}
		}
示例#21
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Handles deletion of empty section heading paragraph on backspace key being pressed
		/// at text boundary.
		/// </summary>
		/// <param name="helper">The selection helper.</param>
		/// <returns><c>true</c> if we handled the deletion, otherwise <c>false</c></returns>
		/// ------------------------------------------------------------------------------------
		private bool HandleBackspaceAfterEmptySectionHeadParagraph(SelectionHelper helper)
		{
			ILocationTracker tracker = ((ITeView)Control).LocationTracker;
			SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top);
			ScrBook book = new ScrBook(m_cache, tracker.GetBookHvo(helper,
				SelectionHelper.SelLimitType.Top));
			ScrSection section = new ScrSection(m_cache, tracker.GetSectionHvo(helper,
				SelectionHelper.SelLimitType.Top));
			int iSection = tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top);
			int cParas = section.HeadingOA != null ? section.HeadingOA.ParagraphsOS.Count : 0;
			if (cParas > 0)
			{
				// If we are the beginning of content before a multi-paragraph heading
				// and the last paragraph is empty, we delete the last paragraph of
				// the heading.
				if (cParas > 1)
				{
					StTxtPara para = (StTxtPara)section.HeadingOA.ParagraphsOS[cParas - 1];
					if (para.Contents.Length == 0)
					{
						section.HeadingOA.ParagraphsOS.RemoveAt(cParas - 1);
						return true;
					}
				}
				// If we are at beginning of content before an empty section head and
				// not in the first section, we should merge sections.
				else if (iSection > 0)
				{
					StTxtPara para = (StTxtPara)section.HeadingOA.ParagraphsOS[cParas - 1];
					if (para.Contents.Length == 0)
					{
						return MergeWithPreviousSectionIfInSameContext(helper, book, section,
							iSection, false);
					}
				}
				return false;	// heading is not empty
			}

			// don't crash if database is corrupt - allow user to merge with
			// previous section (TE-4869)
			if (iSection > 0)
			{
				return MergeWithPreviousSectionIfInSameContext(helper, book,
					section, iSection, false);
			}
			return false;
		}
示例#22
0
		private ComplexConcPatternNode GetNode(SelectionHelper sel, SelectionHelper.SelLimitType limit)
		{
			if (sel == null || m_patternModel.Root.IsLeaf)
				return null;

			SelLevInfo[] levels = sel.GetLevelInfo(limit);
			if (levels.Length == 0)
				return null;

			SelLevInfo level = levels.First(l => l.tag == ComplexConcPatternSda.ktagChildren);
			return m_patternModel.GetNode(level.hvo);
		}
示例#23
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Handles deletion of empty section content paragraph on backspace key being pressed
		/// at text boundary.
		/// </summary>
		/// <param name="helper">The selection helper.</param>
		/// <returns><c>true</c> if we merged the sections, otherwise <c>false</c>.</returns>
		/// ------------------------------------------------------------------------------------
		private bool HandleBackspaceAfterEmptyContentParagraph(SelectionHelper helper)
		{
			SelLevInfo[] levInfo = helper.GetLevelInfo(SelectionHelper.SelLimitType.Top);
			ILocationTracker tracker = ((ITeView)Control).LocationTracker;
			ScrBook book = new ScrBook(m_cache, tracker.GetBookHvo(helper, SelectionHelper.SelLimitType.Top));
			int iSection = tracker.GetSectionIndexInBook(helper, SelectionHelper.SelLimitType.Top);
			if (iSection == 0)
				return false;
			IScrSection prevSection = book.SectionsOS[iSection - 1];
			int cParas = prevSection.ContentOA != null ? prevSection.ContentOA.ParagraphsOS.Count : 0;
			if (cParas > 0)
			{
				// If we are the beginning of heading before a multi-paragraph content
				// and the last paragraph is empty, we delete the last paragraph of
				// the content.
				if (cParas > 1)
				{
					StTxtPara para = (StTxtPara)prevSection.ContentOA.ParagraphsOS[cParas - 1];
					if (para.Contents.Length == 0)
					{
						prevSection.ContentOA.ParagraphsOS.RemoveAt(cParas - 1);
						return true;
					}
				}
				// If we are at beginning of heading before an empty section content and
				// not in the first section, we should merge sections.
				else
				{
					StTxtPara para = (StTxtPara)prevSection.ContentOA.ParagraphsOS[cParas - 1];
					if (para.Contents.Length == 0)
					{
						return MergeWithFollowingSectionIfInSameContext(helper, book,
							iSection - 1, prevSection, false);
					}
				}
			}
			else
			{
				return MergeWithFollowingSectionIfInSameContext(helper, book, iSection - 1,
					prevSection, false);
			}
			return false;
		}
示例#24
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Finds the nearest footnote before the given selection.
		/// </summary>
		/// <param name="helper">The selection helper.</param>
		/// <param name="book">The book that owns the footnote collection.</param>
		/// <param name="fSearchForward">True to also search forward within the current paragraph</param>
		/// <returns></returns>
		/// ------------------------------------------------------------------------------------
		private StFootnote FindFootnoteNearSelection(SelectionHelper helper, IScrBook book,
			bool fSearchForward)
		{
			CheckDisposed();

			if (helper == null)
				helper = CurrentSelection;
			if (helper == null || book == null)
				return null;

			SelLevInfo[] levels = helper.GetLevelInfo(SelectionHelper.SelLimitType.Anchor);

			int iParagraph = -1;
			int tag = 0;
			int ich = helper.IchAnchor;
			int paraLev = helper.GetLevelForTag((int)StText.StTextTags.kflidParagraphs);
			int contentLev = helper.GetLevelForTag((int)StTxtPara.StTxtParaTags.kflidContents);

			Debug.Assert(paraLev != -1, "Need a paragraph for this method");
			iParagraph = levels[paraLev].ihvo;

			int iSection = ((ITeView)Control).LocationTracker.GetSectionIndexInBook(
				helper, SelectionHelper.SelLimitType.Anchor);

			if (iSection < 0)
				tag = (int)ScrBook.ScrBookTags.kflidTitle;
			else
			{
				tag = (helper.GetLevelForTag((int)ScrSection.ScrSectionTags.kflidContent) >= 0 ?
					(int)ScrSection.ScrSectionTags.kflidContent :
					(int)ScrSection.ScrSectionTags.kflidHeading);
			}

			// Special case: if we're in the caption of a picture, get the ich from
			// the first level instead of the anchor. (TE-4696)
			if (contentLev >= 0 && levels[contentLev].ihvo == -1)
				ich = levels[contentLev].ich;

			ScrFootnote prevFootnote = null;
			if (fSearchForward) // look first at our current position, if we are searching foward
			{
				prevFootnote = ScrFootnote.FindCurrentFootnote(m_cache, book, iSection,
					iParagraph, ich, tag);
			}

			if (prevFootnote == null)
			{
				StTxtPara para = new StTxtPara(m_cache, levels[paraLev].hvo);
				ITsString tss = para.Contents.UnderlyingTsString;
				if (ich != 0)
				{
					// look backwards in our current paragraph
					prevFootnote = ScrFootnote.FindLastFootnoteInString(m_cache, tss, ref ich, true);
				}
				else if (iParagraph > 0)
				{
					// look at the previous paragraph for a footnote at the end
					StText text = new StText(m_cache, levels[paraLev + 1].hvo);
					StTxtPara prevPara = (StTxtPara)text.ParagraphsOS[iParagraph - 1];
					ITsString prevTss = prevPara.Contents.UnderlyingTsString;
					int ichTmp = -1;
					prevFootnote = ScrFootnote.FindLastFootnoteInString(m_cache, prevTss, ref ichTmp, false);
					if (prevFootnote != null)
					{
						if (ichTmp == prevTss.Length - 1)
							ich = ichTmp;
						else
							prevFootnote = null;
					}
					// ENHANCE: Look across contexts.
				}
			}
			if (prevFootnote == null && fSearchForward)
			{
				// look ahead in the same paragraph
				StTxtPara para = new StTxtPara(m_cache, levels[paraLev].hvo);
				ITsString tss = para.Contents.UnderlyingTsString;
				prevFootnote = ScrFootnote.FindFirstFootnoteInString(m_cache, tss, ref ich, true);
			}
			if (prevFootnote == null)
			{
				// just go back until we find one
				prevFootnote = ScrFootnote.FindPreviousFootnote(m_cache,
					book, ref iSection, ref iParagraph, ref ich, ref tag);
			}

			return prevFootnote;
		}
示例#25
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Merges content of given section into the content of the previous section and then
		/// deletes the given section.
		/// </summary>
		/// <param name="helper"> </param>
		/// <param name="book"></param>
		/// <param name="section"></param>
		/// <param name="ihvoSection"></param>
		/// <param name="fPositionAtEnd">If true position of Selection is placed at end of
		/// paragraph, else at the beginning.</param>
		/// ------------------------------------------------------------------------------------
		private void MergeContentWithPreviousSection(SelectionHelper helper, ScrBook book,
			IScrSection section, int ihvoSection, bool fPositionAtEnd)
		{
			//REVIEW: Can the methods that call this be refactored
			//to use (a refactored?) ScrSection.MergeWithPreviousSection?
			//
			// Get the previous section and move the paragraphs.
			IScrSection sectionPrev = book.SectionsOS[ihvoSection - 1];
			IStText textPrev = sectionPrev.ContentOA;
			ILocationTracker tracker = ((ITeView)Control).LocationTracker;
			int iBook = tracker.GetBookIndex(helper, SelectionHelper.SelLimitType.Top);
			int cparaPrev = 0;
			if (textPrev == null)
			{
				// Prevent crash when dealing with corrupt database (TE-4869)
				// Since the previous section doesn't have a text, we simply move the entire text
				// object from the current section to the previous section.
				m_cache.ChangeOwner(section.ContentOAHvo, sectionPrev.Hvo,
					(int)ScrSection.ScrSectionTags.kflidContent);
			}
			else
			{
				cparaPrev = textPrev.ParagraphsOS.Count;
				IStText textOldContents = section.ContentOA;
				m_cache.MoveOwningSequence(textOldContents.Hvo, (int)StText.StTextTags.kflidParagraphs,
					0, textOldContents.ParagraphsOS.Count - 1,
					textPrev.Hvo, (int)StText.StTextTags.kflidParagraphs, cparaPrev);
			}
			// protected for some reason...textPrev.ParagraphsOS.Append(text.ParagraphsOS.HvoArray);
			book.SectionsOS.RemoveAt(ihvoSection);
			// Now we have to re-establish a selection. Whatever happens, it will be in the
			// same book as before, and the previous section, and in the body.
			if (InSectionHead || !fPositionAtEnd)
			{
				tracker.SetBookAndSection(helper, SelectionHelper.SelLimitType.Top, iBook,
					ihvoSection - 1);
				helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[1].tag =
					(int)ScrSection.ScrSectionTags.kflidContent;
			}
			Debug.Assert(helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[1].tag ==
				(int)ScrSection.ScrSectionTags.kflidContent);

			if (fPositionAtEnd)
			{
				// we want selection at end of last paragraph of old previous section.
				// (That is, at the end of paragraph cparaPrev - 1.)
				Debug.Assert(cparaPrev > 0);
				helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[0].ihvo = cparaPrev - 1;
				StTxtPara paraPrev = (StTxtPara)(textPrev.ParagraphsOS[cparaPrev - 1]);

				int cchParaPrev = paraPrev.Contents.Length;
				helper.IchAnchor = cchParaPrev;
				helper.IchEnd = cchParaPrev;
				helper.AssocPrev = true;
			}
			else
			{
				// want selection at start of old first paragraph of deleted section.
				// (That is, at the start of paragraph cparaPrev.)
				helper.GetLevelInfo(SelectionHelper.SelLimitType.Top)[0].ihvo = cparaPrev;
				helper.IchAnchor = 0;
				helper.IchEnd = 0;
				helper.AssocPrev = false;
			}
			helper.SetLevelInfo(SelectionHelper.SelLimitType.Bottom,
				helper.GetLevelInfo(SelectionHelper.SelLimitType.Top));
			helper.SetSelection(true);
		}
示例#26
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Get the Hvo of the surviving paragraph. This will be either the paragraph before
		/// the selected paragraph if we have an IP or the paragraph at the top of a range
		/// selection.
		/// </summary>
		/// ------------------------------------------------------------------------------------
		private int SurvivorParagraphHvo(SelectionHelper selHelper, IStText text, int ihvo, bool fMergeNext)
		{
			if (!selHelper.IsRange)
			{
				int iSurvivor = fMergeNext ? ihvo + 1 : ihvo - 1;
				return (iSurvivor >= 0 && iSurvivor < text.ParagraphsOS.Count ?
					text.ParagraphsOS.HvoArray[iSurvivor] : -1);
			}

			int paraLev = selHelper.GetLevelForTag((int)StText.StTextTags.kflidParagraphs, SelectionHelper.SelLimitType.Top);
			SelLevInfo[] rgSelLevInfo = selHelper.GetLevelInfo(SelectionHelper.SelLimitType.Top);
			return rgSelLevInfo[paraLev].hvo;
		}
		protected override ICmObject GetCmObject(SelectionHelper sel, SelectionHelper.SelLimitType limit)
		{
			if (sel == null)
				return null;

			foreach (SelLevInfo level in sel.GetLevelInfo(limit))
			{
				if (level.tag == MoAffixProcessTags.kflidInput
					|| level.tag == PhSequenceContextTags.kflidMembers
					|| level.tag == MoAffixProcessTags.kflidOutput)
					return m_cache.ServiceLocator.GetObject(level.hvo);
			}

			return null;
		}
示例#28
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;
		}
示例#29
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Replace the filter book tag with a scrpiture books tag.  This is done before
		/// persisting the selection because the filter tag is not valid across sessions.
		/// Also, any filtered book indices are replaced with real scripture book indices
		/// for the same reason.
		/// </summary>
		/// <param name="helper"></param>
		/// <param name="selType"></param>
		/// ------------------------------------------------------------------------------------
		private void ReplaceBookTagAndIndex(SelectionHelper helper,
			SelectionHelper.SelLimitType selType)
		{
			SelLevInfo[] info = helper.GetLevelInfo(selType);
			int bookPos = info.Length - 1;
			if (info[bookPos].tag == BookFilter.Tag)
			{
				info[bookPos].tag = ScriptureTags.kflidScriptureBooks;
				info[bookPos].ihvo = BookFilter.GetUnfilteredIndex(info[bookPos].ihvo);
				helper.SetLevelInfo(selType, info);
			}
		}
示例#30
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;
		}