public void ParagraphBreak_RemoveCharStyleFromAdjacentWhiteSpace() { CheckDisposed(); m_draftView.RefreshDisplay(); // *** Test setup *** // Insert text with a character style. StTxtPara para1 = (StTxtPara)m_exodus.SectionsOS[0].ContentOA.ParagraphsOS[0]; ITsStrBldr tssBldr = para1.Contents.UnderlyingTsString.GetBldr(); ITsPropsBldr ttpBldr = TsPropsBldrClass.Create(); ttpBldr.SetStrPropValue((int)FwTextPropType.ktptNamedStyle, "Emphasis"); tssBldr.ReplaceRgch(15, 15, "really, really", 6, ttpBldr.GetTextProps()); int paraCount = m_exodus.SectionsOS[0].ContentOA.ParagraphsOS.Count; // Set the IP in the white space within the inserted text. m_draftView.SetInsertionPoint(0, 0, 0, 23, true); IVwSelection sel0 = m_draftView.RootBox.Selection; Assert.IsNotNull(sel0); // Insert paragraph break m_draftView.OnKeyPress(new KeyPressEventArgs('\r')); Assert.AreEqual(paraCount + 1, m_exodus.SectionsOS[0].ContentOA.ParagraphsOS.Count, "Should have one more paragraph in the intro section"); // We expect that the last run of the first paragraph and first run of the new // paragraph will be a space character with no character style. ITsString tss1 = para1.Contents.UnderlyingTsString; Assert.AreEqual(3, tss1.RunCount, "First intro paragraph should have three runs"); Assert.AreEqual("really,", tss1.get_RunText(1)); ITsTextProps ttp = tss1.get_Properties(1); Assert.AreEqual("Emphasis", ttp.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle)); ttp = tss1.get_Properties(2); Assert.AreEqual(" ", tss1.get_RunText(2)); Assert.AreEqual(null, ttp.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle)); ITsString tss2 = ((StTxtPara)m_exodus.SectionsOS[0].ContentOA.ParagraphsOS[1]).Contents.UnderlyingTsString; Assert.AreEqual(3, tss2.RunCount); Assert.AreEqual(" ", tss2.get_RunText(0)); ttp = tss1.get_Properties(0); Assert.AreEqual(null, ttp.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle)); ttp = tss1.get_Properties(1); Assert.AreEqual("Emphasis", ttp.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle)); Assert.AreEqual("really", tss2.get_RunText(0)); }
public void InsertFootnote() { CheckDisposed(); FdoCache cache = m_firstMainWnd.Cache; // Set the IP to the second section in the first book at the 10th character in // the first paragraph m_firstDraftView.SetInsertionPoint(0, 1, 0, 10, false); ScrBook book = (ScrBook)cache.LangProject.TranslatedScriptureOA.ScriptureBooksOS[0]; int nFootnotes = book.FootnotesOS.Count; m_firstMainWnd.CallInsertFootnote(); Assert.AreEqual(nFootnotes + 1, book.FootnotesOS.Count); // Test footnote string expectedMarker = new String((char)((int)'a' + nFootnotes), 1); StFootnote footnote = (StFootnote)book.FootnotesOS[nFootnotes]; Assert.AreEqual(expectedMarker, footnote.FootnoteMarker.Text, "Wrong footnote marker in footnote"); ITsString tsString = footnote.FootnoteMarker.UnderlyingTsString; ITsTextProps ttp = tsString.get_PropertiesAt(0); string styleName = ttp.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); Assert.AreEqual(ScrStyleNames.FootnoteMarker, styleName, "Wrong style for footnote marker in footnote"); // Test footnote marker in text IVwSelection sel = m_firstDraftView.RootBox.Selection; ITsString tss; int ich, hvoObj, tag, enc; bool fAssocPrev; sel.TextSelInfo(true, out tss, out ich, out fAssocPrev, out hvoObj, out tag, out enc); string strPara = tss.Text; Assert.AreEqual(StringUtils.kchObject, strPara[ich]); ttp = tss.get_PropertiesAt(ich); int nDummy; int wsActual = ttp.GetIntPropValues((int)FwTextPropType.ktptWs, out nDummy); Assert.AreEqual(cache.LangProject.DefaultVernacularWritingSystem, wsActual, "Wrong writing system for footnote marker in text"); string objData = ttp.GetStrPropValue((int)FwTextPropType.ktptObjData); Assert.AreEqual((char)(int)FwObjDataTypes.kodtOwnNameGuidHot, objData[0]); }
private void spyOnTextProps(ITsTextProps ttp) { int tpt; // ?? // look at integer props int cintProps = ttp.IntPropCount; for (int i = 0; i < cintProps; i++) { int nVar; int intProp = ttp.GetIntProp(i, out tpt, out nVar); int Value = ttp.GetIntPropValues(tpt, out nVar); Value = 34; // need something so Value can be looked at } // look at string props int cstrProps = ttp.StrPropCount; for (int i = 0; i < cstrProps; i++) { string strProp = ttp.GetStrProp(i, out tpt); string Value = ttp.GetStrPropValue(tpt); Value = "why?"; // need something so Value can be looked at } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Answer the spelling status of the indicated character in the string, unless it is an /// ORC, in which case, for each ORC we answer a different value (that is not any of the /// valid spelling statuses). /// Enhance JohnT: we don't want to consider embedded-picture ORCs to count as /// different; we may strip them out before we start checking the word. /// </summary> /// ------------------------------------------------------------------------------------ int SpellCheckProps(ITsString tss, int ich, IVwStylesheet styles) { // For our purposes here, ORC (0xfffc) is considered to have a different spelling status from everything else, // even from every other ORC in the string. This means we always offer to insert spaces adjacent to them. if (ich < tss.Length && tss.GetChars(ich, ich + 1)[0] == 0xfffc) { return(-50 - ich); } ITsTextProps props = tss.get_PropertiesAt(ich); string style = props.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); int var, val; if (styles != null && !string.IsNullOrEmpty(style)) { ITsTextProps styleProps = styles.GetStyleRgch(style.Length, style); if (styleProps != null) { val = styleProps.GetIntPropValues((int)FwTextPropType.ktptSpellCheck, out var); if (var != -1) { return(val); // style overrides } } } val = props.GetIntPropValues((int)FwTextPropType.ktptSpellCheck, out var); if (var == -1) { return(0); // treat unspecified the same as default. } else { return(val); } }
/// ------------------------------------------------------------------------------------- /// <summary> /// For any footnote in the specified book whose first paragraph has a run marked with /// the Note Target Reference style, remove that run and set the property on the footnote /// to display the target reference in the footnote view. /// </summary> /// <param name="book">The ScrBook whose footnotes are to be searched</param> /// ------------------------------------------------------------------------------------- private void RemoveDirectUsesOfFootnoteTargetRef(IScrBook book) { foreach (IStFootnote footnote in book.FootnotesOS) { // Probably only need to worry about first para if (footnote.ParagraphsOS.Count == 0) { continue; } IStTxtPara para = (IStTxtPara)footnote.ParagraphsOS[0]; ITsString tss = para.Contents; ITsStrBldr bldr = null; for (int iRun = 0; iRun < tss.RunCount; iRun++) { ITsTextProps props = tss.get_Properties(iRun); string style = props.GetStrPropValue( (int)FwTextPropType.ktptNamedStyle); if (style == ScrStyleNames.FootnoteTargetRef) { if (bldr == null) { bldr = tss.GetBldr(); } bldr.Replace(tss.get_MinOfRun(iRun), tss.get_LimOfRun(iRun), string.Empty, null); } } if (bldr != null) { para.Contents = bldr.GetString(); } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Asserts the properties of a run are set correctly to be a hyperlink for the given /// URL. /// </summary> /// <param name="props">The properties.</param> /// <param name="expectedWs">The expected writing system.</param> /// <param name="sUrl">The URL.</param> /// ------------------------------------------------------------------------------------ public static void VerifyHyperlinkPropsAreCorrect(ITsTextProps props, int expectedWs, string sUrl) { Assert.AreEqual(1, props.IntPropCount); int nDummy; Assert.AreEqual(expectedWs, props.GetIntPropValues((int)FwTextPropType.ktptWs, out nDummy)); Assert.AreEqual(2, props.StrPropCount); Assert.AreEqual(StyleServices.Hyperlink, props.GetStrPropValue((int)FwTextPropType.ktptNamedStyle)); string sObjData = props.GetStrPropValue((int)FwTextPropType.ktptObjData); Assert.AreEqual(Convert.ToChar((int)FwObjDataTypes.kodtExternalPathName), sObjData[0]); Assert.AreEqual(sUrl, sObjData.Substring(1)); }
public void TypingBeforeHyperlink_WithPrecedingItalicsText() { var selection = MakeMockSelection(false); var selHelper = SelectionHelper.s_mockedSelectionHelper = MockRepository.GenerateStub <SelectionHelper>(); selHelper.Stub(selH => selH.Selection).Return(selection); ITsPropsBldr bldr = m_ttpNormal.GetBldr(); bldr.SetStrPropValue((int)FwTextPropType.ktptNamedStyle, "Italics"); SimulateTextFollowedByHyperlink(selHelper, bldr.GetTextProps(), IchPosition.StartOfHyperlink, IchPosition.StartOfHyperlink); using (FwEditingHelper editingHelper = new FwEditingHelper(Cache, m_callbacks)) { editingHelper.OnKeyPress(new KeyPressEventArgs('b'), Keys.None); IList <object[]> argsSentToSetTypingProps = selection.GetArgumentsForCallsMadeOn(sel => sel.SetTypingProps(null)); Assert.AreEqual(1, argsSentToSetTypingProps.Count); ITsTextProps ttpSentToSetTypingProps = (ITsTextProps)argsSentToSetTypingProps[0][0]; Assert.AreEqual(1, ttpSentToSetTypingProps.StrPropCount); Assert.AreEqual(1, ttpSentToSetTypingProps.IntPropCount); int nVar; Assert.AreEqual("Italics", ttpSentToSetTypingProps.GetStrPropValue((int)FwTextPropType.ktptNamedStyle)); Assert.AreEqual(911, ttpSentToSetTypingProps.GetIntPropValues((int)FwTextPropType.ktptWs, out nVar)); } }
///---------------------------------------------------------------------------------- /// <summary> /// Asserts that the named style is equal to the expected style. /// </summary> ///---------------------------------------------------------------------------------- public void StyleEqual(string expectedStyle, ITsString tss, int iRun) { ITsTextProps props = GetProperties(tss, iRun); Assert.AreEqual(1, props.StrPropCount); Assert.AreEqual(expectedStyle, props.GetStrPropValue((int)FwTextPropType.ktptNamedStyle)); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the font for the specified TsString and writing system. /// </summary> /// ------------------------------------------------------------------------------------ private Font GetValuesFont(ITsString tss, int ws) { if (tss == null || tss.RunCount == 0 || m_cache == null) { return(null); } ITsTextProps ttp = tss.get_Properties(0); // Figure out what the font size of the string should be. int var; int fontSize = ttp.GetIntPropValues((int)FwTextPropType.ktptFontSize, out var); if (fontSize == -1) { fontSize = FontInfo.kDefaultFontSize; } // Font size, at this point, is in millipoints, so convert it to points. fontSize /= 1000; // Figure out what the style name is and use it to get the font face name. string styleName = ttp.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); string faceName; if (m_styleSheet != null) { // When there is a stylesheet, use it to get the font face name for the style // name specified in the text props. If there is no style name in the text props, // GetFaceNameFromStyle() should return the font face for the normal style. faceName = m_styleSheet.GetFaceNameFromStyle(styleName, ws, m_cache); } else { // When there is no stylesheet, use the default serif font for the writing // system. IWritingSystem iws = m_cache.LanguageWritingSystemFactoryAccessor.get_EngineOrNull(ws); faceName = iws.DefaultSerif; } if (string.IsNullOrEmpty(faceName)) { return(null); } // Check if the font is in our font cache. If not, add it. string key = string.Format("{0}{1}", faceName, fontSize); Font fnt; if (!m_fontCache.TryGetValue(key, out fnt)) { fnt = new Font(faceName, (float)fontSize, GraphicsUnit.Point); m_fontCache[key] = fnt; } return(fnt); }
///---------------------------------------------------------------------------------- /// <summary> /// Asserts that the object data is as expected /// </summary> ///---------------------------------------------------------------------------------- public void ObjDataEqual(string expectedObjData, ITsString tss) { ITsTextProps props = GetProperties(tss, 0); Assert.AreEqual(1, props.StrPropCount); Assert.AreEqual(expectedObjData, props.GetStrPropValue((int)FwTextPropType.ktptObjData)); }
/// <inheritdoc/> public IStStyle FindStyle(ITsTextProps ttp) { if (ttp == null) { return(null); } return(FindStyle(ttp.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle))); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get the font for the specified TsString and writing system. /// </summary> /// ------------------------------------------------------------------------------------ private Font GetValuesFont(ITsString tss, int ws) { if (tss == null || tss.RunCount == 0 || m_cache == null) { return(null); } ITsTextProps ttp = tss.get_Properties(0); // Figure out what the font size of the string should be. int var; int fontSize = ttp.GetIntPropValues((int)FwTextPropType.ktptFontSize, out var); if (fontSize == -1) { fontSize = FontInfo.kDefaultFontSize; } else { // Font size, at this point, is in millipoints, so convert it to points. fontSize /= 1000; } // Figure out what the style name is and use it to get the font face name. string styleName = ttp.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); string faceName; if (m_styleSheet != null) { using (var font = FontHeightAdjuster.GetFontForStyle(styleName, m_styleSheet, ws, m_cache.WritingSystemFactory)) { faceName = font == null ? null : font.Name; } } else { // When there is no stylesheet, use the default serif font for the writing // system. faceName = m_cache.ServiceLocator.WritingSystemManager.Get(ws).DefaultFontName; } if (string.IsNullOrEmpty(faceName)) { return(null); } // Check if the font is in our font cache. If not, add it. string key = string.Format("{0}{1}", faceName, fontSize); Font fnt; if (!m_fontCache.TryGetValue(key, out fnt)) { fnt = new Font(faceName, fontSize, GraphicsUnit.Point); m_fontCache[key] = fnt; } return(fnt); }
public void ApplyStyle_CharStyleNotAppliedToBorderingWhiteSpace() { CheckDisposed(); m_draftView.RefreshDisplay(); // Select a word in the book intro with white space around it: " text. " m_draftView.SetInsertionPoint(0, 0, 0, 5, false); IVwSelection sel0 = m_draftView.RootBox.Selection; Assert.IsNotNull(sel0); m_draftView.SetInsertionPoint(0, 0, 0, 12, true); IVwSelection sel1 = m_draftView.RootBox.Selection; Assert.IsNotNull(sel1); IVwSelection rangeSel = m_draftView.RootBox.MakeRangeSelection(sel0, sel1, true); ITsString tssSelected; rangeSel.GetSelectionString(out tssSelected, "*"); Assert.AreEqual(" text. ", tssSelected.Text); // Apply a character style to the selected text. m_draftView.ApplyStyle("Emphasis"); // The selection should be updated to omit bordering white space in the original selection. m_draftView.RootBox.Selection.GetSelectionString(out tssSelected, "*"); Assert.AreEqual("text.", tssSelected.Text); // Confirm that the character styles are applied correctly: Emphasis style applied only to "text." ScrSection introSection = (ScrSection)m_exodus.SectionsOS[0]; ITsString paraContents = ((StTxtPara)introSection.ContentOA.ParagraphsOS[0]).Contents.UnderlyingTsString; Assert.AreEqual(3, paraContents.RunCount); Assert.AreEqual(7, paraContents.get_MinOfRun(1)); Assert.AreEqual(11, paraContents.get_LimOfRun(1)); ITsTextProps ttp = paraContents.get_Properties(0); Assert.IsNull(ttp.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle), "First run should be 'Default Paragraph Characters'"); ttp = paraContents.get_Properties(1); Assert.AreEqual("Emphasis", ttp.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle)); ttp = paraContents.get_Properties(2); Assert.IsNull(ttp.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle), "Third run should be 'Default Paragraph Characters'"); }
/// ------------------------------------------------------------------------------------- /// <summary> /// Make sure that all runs of the given ts string will fit within the given height. /// </summary> /// <param name="tss">(Potentially) unadjusted TsString -- may have some pre-existing /// adjustments, but if it does, we (probably) ignore those and recheck every run</param> /// <param name="dympMaxHeight">The maximum height (in millipoints) of the Ts String.</param> /// <param name="styleSheet"></param> /// <param name="writingSystemFactory"></param> /// ------------------------------------------------------------------------------------- public static ITsString GetAdjustedTsString(ITsString tss, int dympMaxHeight, IVwStylesheet styleSheet, ILgWritingSystemFactory writingSystemFactory) { if (dympMaxHeight == 0) { return(tss); } ITsStrBldr bldr = null; int runCount = tss.RunCount; for (int irun = 0; irun < runCount; irun++) { ITsTextProps props = tss.get_Properties(irun); int var; int wsTmp = props.GetIntPropValues((int)FwTextPropType.ktptWs, out var); string styleName = props.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle); Font f = GetFontForStyle(styleName, styleSheet, wsTmp, writingSystemFactory); int height = GetFontHeight(f); int curHeight = height; // incrementally reduce the size of the font until the text can fit while (curHeight > dympMaxHeight) { f = new Font(f.Name, f.SizeInPoints - 0.25f); curHeight = GetFontHeight(f); } if (curHeight != height) { // apply formatting to the problem run if (bldr == null) { bldr = tss.GetBldr(); } int iStart = tss.get_MinOfRun(irun); int iEnd = tss.get_LimOfRun(irun); bldr.SetIntPropValues(iStart, iEnd, (int)FwTextPropType.ktptFontSize, (int)FwTextPropVar.ktpvMilliPoint, (int)(f.SizeInPoints * 1000.0f)); } } if (bldr != null) { return(bldr.GetString()); } else { return(tss); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initializes a new instance of the <see cref="XmlHyperlinkRun"/> class. /// </summary> /// ------------------------------------------------------------------------------------ public XmlHyperlinkRun(int wsDefault, ILgWritingSystemFactory lgwsf, string text, ITsTextProps props) : base(wsDefault, lgwsf, text, props) { Href = StringUtils.GetURL(props.GetStrPropValue((int)FwTextPropType.ktptObjData)); if (!string.IsNullOrEmpty(Href)) { Href = Href.TrimEnd(Environment.NewLine.ToCharArray()); } }
public void InsertChars_WhiteSpaceOnBorderOfStyleUsesDefaultStyle() { CheckDisposed(); m_draftView.RefreshDisplay(); // *** Test setup *** // Insert a word with a character style. StTxtPara para = (StTxtPara)m_exodus.SectionsOS[0].ContentOA.ParagraphsOS[0]; ITsStrBldr tssBldr = para.Contents.UnderlyingTsString.GetBldr(); ITsPropsBldr ttpBldr = TsPropsBldrClass.Create(); ttpBldr.SetStrPropValue((int)FwTextPropType.ktptNamedStyle, "Emphasis"); tssBldr.ReplaceRgch(15, 15, "really", 6, ttpBldr.GetTextProps()); para.Contents.UnderlyingTsString = tssBldr.GetString(); Assert.AreEqual(3, para.Contents.UnderlyingTsString.RunCount); // Set the IP immediately before this inserted text. m_draftView.SetInsertionPoint(0, 0, 0, 15, true); IVwSelection sel0 = m_draftView.RootBox.Selection; Assert.IsNotNull(sel0); // *** Test *** // Type two spaces. m_draftView.OnKeyDown(new KeyEventArgs(Keys.Space)); m_draftView.OnKeyDown(new KeyEventArgs(Keys.Space)); // We expect that the spaces will be in "Default Paragraph Characters" // not in a character style ITsString tss = para.Contents.UnderlyingTsString; // the word "really" is in the Emphasis style but the inserted white space is not. Assert.AreEqual("really", tss.get_RunText(1)); ITsTextProps ttp = tss.get_Properties(1); Assert.AreEqual("Emphasis", ttp.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle)); ttp = tss.get_Properties(0); Assert.IsNull(ttp.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle), "Style of the first run should be 'Default Paragraph Characters'"); Assert.AreEqual("Intro text. We ", tss.get_RunText(0)); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initializes a new instance of the <see cref="XmlTextRun"/> class, based on the given /// run information /// </summary> /// <param name="wsDefault">The default writing system of the paragraph.</param> /// <param name="lgwsf">The writing system factory.</param> /// <param name="text">The text of the run.</param> /// <param name="props">The properties of the run.</param> /// ------------------------------------------------------------------------------------ public XmlTextRun(int wsDefault, ILgWritingSystemFactory lgwsf, string text, ITsTextProps props) { int dummy; int wsRun = props.GetIntPropValues((int)FwTextPropType.ktptWs, out dummy); if (wsRun != wsDefault) { IcuLocale = lgwsf.GetStrFromWs(wsRun); } StyleName = props.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); m_text = text; }
public void MakeProps_NonNullStyle_CreatesTextProps() { var tpf = new TsPropsFactory(); ITsTextProps tps = tpf.MakeProps("Style", 2, 1); Assert.That(tps.IntPropCount, Is.EqualTo(1)); int var; Assert.That(tps.GetIntPropValues((int)FwTextPropType.ktptWs, out var), Is.EqualTo(2)); Assert.That(var, Is.EqualTo(1)); Assert.That(tps.StrPropCount, Is.EqualTo(1)); Assert.That(tps.GetStrPropValue((int)FwTextPropType.ktptNamedStyle), Is.EqualTo("Style")); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Determine the default font to use for the specified writing system, /// displayed in the default Normal style of the specified stylesheet. /// This is duplicated in SimpleRootSite/EditingHelper. /// </summary> /// <param name="hvoWs"></param> /// <param name="styleSheet"></param> /// <param name="wsf"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ static public Font GetFontForNormalStyle(int hvoWs, IVwStylesheet styleSheet, ILgWritingSystemFactory wsf) { ITsTextProps ttpNormal = styleSheet.NormalFontStyle; string styleName = StStyle.NormalStyleName; if (ttpNormal != null) { styleName = ttpNormal.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); } return(GetFontForStyle(styleName, styleSheet, hvoWs, wsf)); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Checks the final space in reference label. /// </summary> /// ------------------------------------------------------------------------------------ private void CheckFinalSpaceInReferenceLabel(ITsString tss) { int iRun = tss.RunCount - 1; Assert.AreEqual(" ", tss.get_RunText(iRun)); ITsTextProps ttp = tss.get_Properties(iRun); Assert.AreEqual(null, ttp.GetStrPropValue((int)FwTextPropType.ktptNamedStyle)); int var; Assert.AreEqual(Cache.WritingSystemFactory.UserWs, ttp.GetIntPropValues((int)FwTextPropType.ktptWs, out var)); }
/// <summary> /// Get the name of the paragraph style. /// </summary> /// <param name="hvoPara">the id of the paragraph</param> /// <param name="cache">database cache</param> public static string GetStyleName(int hvoPara, FdoCache cache) { ISilDataAccess dataAccess = cache.MainCacheAccessor; ITsTextProps tsTextProps = dataAccess.get_UnknownProp(hvoPara, (int)StPara.StParaTags.kflidStyleRules) as ITsTextProps; string styleName = NormalParagraph; if (tsTextProps != null) { styleName = tsTextProps.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); } return(styleName); }
public void SavingDeserializedAnnotationsToCache_WithHyperlink() { DateTime now = DateTime.Now; DateTime utcNow = now.ToUniversalTime(); XmlScrNote ann = CreateNote(); ann.BeginScrRef = "GEN 2:8"; ann.ResolutionStatus = NoteStatus.Closed; ann.AnnotationTypeGuid = CmAnnotationDefnTags.kguidAnnTranslatorNote.ToString(); ann.DateTimeCreated = utcNow.ToString(CultureInfo.InvariantCulture); ann.DateTimeModified = utcNow.AddDays(1).ToString(CultureInfo.InvariantCulture); ann.DateTimeResolved = utcNow.AddDays(2).ToString(CultureInfo.InvariantCulture); AddParasTo(ann.Discussion, "This is my", "discussion"); AddParasTo(ann.Resolution, "This is my", "resolution for", "the note"); AddParasTo(ann.Quote, "This is the", "quoted text"); AddParasTo(ann.Suggestion, "This is", "my", "suggestion"); AddHyperTo(ann.Suggestion[1], "http://www.tim.david.com/cooldudes.html"); DummyXmlScrAnnotationsList list = new DummyXmlScrAnnotationsList(); list.Annotations.Add(ann); list.CallWriteToCache(Cache, m_stylesheet); IScrBookAnnotations annotations = m_scr.BookAnnotationsOS[0]; Assert.AreEqual(1, annotations.NotesOS.Count); IScrScriptureNote note = annotations.NotesOS[0]; Assert.AreEqual(NoteType.Translator, note.AnnotationType); Assert.IsTrue(AreDateTimesClose(now, note.DateCreated)); Assert.IsTrue(AreDatesClose(now.AddDays(1), note.DateModified)); Assert.IsTrue(AreDatesClose(now.AddDays(2), note.DateResolved)); TestAnnotationField(note.QuoteOA, "This is the", "quoted text"); TestAnnotationField(note.DiscussionOA, "This is my", "discussion"); TestAnnotationField(note.ResolutionOA, "This is my", "resolution for", "the note"); TestAnnotationField(note.RecommendationOA, "This is", "mymy link", "suggestion"); // Check the hyperlink location ITsTextProps props = ((IStTxtPara)note.RecommendationOA.ParagraphsOS[1]).Contents.get_Properties(1); string href = TsStringUtils.GetURL(props.GetStrPropValue((int)FwTextPropType.ktptObjData)); Assert.AreEqual("http://www.tim.david.com/cooldudes.html", href); Assert.AreEqual(0, note.ResponsesOS.Count); }
/// <summary> /// This is a demonstration of one way to handle special tricks as the user types. /// This is an oversimplified way of forcing numbers to be treated as verse numbers... /// for example, it will cause '5000' in the 'feeding of the 5000' to be treated as a verse number. /// </summary> /// <param name="vwselNew"></param> protected override void HandleSelectionChange(IVwSelection vwselNew) { base.HandleSelectionChange(vwselNew); if (vwselNew == null) { return; // Not sure whether this happens, but best to be sure. } int ichSel, hvoObj, tag, ws; bool fAssocPrev; ITsString tss; vwselNew.TextSelInfo(false, out tss, out ichSel, out fAssocPrev, out hvoObj, out tag, out ws); string text = tss.get_Text(); if (text == null) { return; // empty string. } ITsStrBldr tsb = null; for (int ich = 0; ich < text.Length; ++ich) { if (Char.IsDigit(text[ich])) { ITsTextProps ttp = tss.get_PropertiesAt(ich); string styleName = ttp.GetStrPropValue((int)FwKernelLib.FwTextPropType.ktptNamedStyle); if (styleName != "verseNumber") { // We'll change just this one character. We could make this more efficient for dealing with // long strings of digits, but it's unlikely we'll ever have to deal with more than one. if (tsb == null) { tsb = tss.GetBldr(); } tsb.SetStrPropValue(ich, ich + 1, (int)FwKernelLib.FwTextPropType.ktptNamedStyle, "verseNumber"); } } } if (tsb != null) { ISilDataAccess sda = m_rootb.get_DataAccess(); // In this sample the only string is a multistring. If in doubt, we could test for ws == 0 to // see whether it is a simple string. sda.SetMultiStringAlt(hvoObj, tag, ws, tsb.GetString()); sda.PropChanged(null, (int)FwViews.PropChangeType.kpctNotifyAll, hvoObj, tag, 0, tss.get_Length(), tss.get_Length()); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Tests that the processing of a footnote has resulted in the the ORC (Object /// Replacement Character) being inserted in the proper place in the dummy /// importer's NormalParaStrBldr. /// </summary> /// <param name="iRun">Zero-base index of the run that should contain the ORC</param> /// <param name="iFootnoteIndex">zero-based footnote index</param> /// ------------------------------------------------------------------------------------ protected void VerifyBldrFootnoteOrcRun(int iRun, int iFootnoteIndex) { ITsTextProps orcProps = m_importer.NormalParaStrBldr.get_Properties(iRun); IStFootnote footnote = GetFootnote(iFootnoteIndex); string objData = orcProps.GetStrPropValue((int)FwTextPropType.ktptObjData); Assert.AreEqual((char)(int)FwObjDataTypes.kodtOwnNameGuidHot, objData[0]); // Send the objData string without the first character because the first character // is the object replacement character and the rest of the string is the GUID. Assert.AreEqual(footnote.Guid, MiscUtils.GetGuidFromObjData(objData.Substring(1))); string sOrc = m_importer.NormalParaStrBldr.get_RunText(iRun); Assert.AreEqual(StringUtils.kChObject, sOrc[0]); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Use this method to move part of one StText to an adjacent one when the fromText /// must be left with at least one empty paragraph. /// </summary> /// <param name="fromText">StText from which the contents is moved</param> /// <param name="toText">StText to which the contents is moved. This StText should be /// empty.</param> /// <param name="divIndex">Index of last whole paragraph to be moved</param> /// <param name="toIsPreceding">Should equal true if the toText preceeds the fromText. /// If true, the moved paragraphs will be appended to the toText. /// If false, they will be placed at the beginning of the toText.</param> /// ------------------------------------------------------------------------------------ public static void MoveTextParagraphsAndFixEmpty(IStText fromText, IStText toText, int divIndex, bool toIsPreceding) { // Save the paragraph props. We might need it to create an empty paragraph. ITsTextProps paraPropsSave = ((StTxtPara)fromText.ParagraphsOS[divIndex]).StyleRules; MoveTextParagraphs(fromText, toText, divIndex, toIsPreceding); // If fromText is now empty, create a new empty paragraph. if (fromText.ParagraphsOS.Count == 0) { string styleName = paraPropsSave.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); StTxtParaBldr.CreateEmptyPara(fromText.Cache, fromText.Hvo, styleName, fromText.Cache.DefaultVernWs); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Parse the existing Contents to determine the object match criteria and set member /// data needed by MatchesCriteria. /// </summary> /// ------------------------------------------------------------------------------------ public void ParseObjectMatchCriteria() { lock (SyncRoot) { string criteria = Contents.Text; m_comparisonType = ComparisonTypes.kUndefined; m_matchValue = 0; m_matchSubitems = criteria.IndexOf("+subitems", StringComparison.Ordinal) >= 0; m_matchEmpty = criteria.IndexOf("Empty", StringComparison.Ordinal) >= 0; if (criteria.IndexOf("Matches", StringComparison.Ordinal) >= 0) { m_comparisonType = ComparisonTypes.kMatches; } else if (m_matchEmpty) { m_comparisonType = ComparisonTypes.kEmpty; } Debug.Assert(m_comparisonType != ComparisonTypes.kUndefined); m_matchValues = null; // Check to see whether the criteria specifies a specific (default) object. if (criteria.IndexOf(StringUtils.kChObject) >= 0) { ITsTextProps ttp = Contents.get_Properties(1); //assume second run string objData = ttp.GetStrPropValue((int)FwTextPropType.ktptObjData); if (objData[0] == (char)FwObjDataTypes.kodtNameGuidHot) { Guid guid = MiscUtils.GetGuidFromObjData(objData.Substring(1)); ICmPossibility poss; ICmPossibilityRepository repo = Cache.ServiceLocator.GetInstance <ICmPossibilityRepository>(); if (repo.TryGetObject(guid, out poss)) { m_matchValue = poss.Hvo; } } InitializeMatchValuesArray(); } } }
/// <summary> /// Any ORCs in the given string with ktptObjData of type kodtOwnNameGuidHot (meaning a GUID that /// 'owns' the footnote) should be changed to kodtNameGuidHot, since the BT does NOT own /// the footnote. /// </summary> /// <param name="tssFt"></param> /// <returns></returns> private static ITsString CorrectFootnotes(ITsString tssFt) { ITsStrBldr bldr = null; int crun = tssFt.RunCount; for (int iRun = 0; iRun < crun; iRun++) { string sOrc = tssFt.get_RunText(iRun); if (String.IsNullOrEmpty(sOrc)) { continue; } if (StringUtils.kchObject != sOrc[0]) { continue; } ITsTextProps orcPropsParaFootnote = tssFt.get_Properties(iRun); string objData = orcPropsParaFootnote.GetStrPropValue((int)FwTextPropType.ktptObjData); if (String.IsNullOrEmpty(objData)) { continue; } if ((char)(int)FwObjDataTypes.kodtOwnNameGuidHot != objData[0]) { continue; } // OK, need to fix it. if (bldr == null) { bldr = tssFt.GetBldr(); } objData = ((char)(int)FwObjDataTypes.kodtNameGuidHot).ToString() + objData.Substring(1); bldr.SetStrPropValue(tssFt.get_MinOfRun(iRun), tssFt.get_LimOfRun(iRun), (int)FwTextPropType.ktptObjData, objData); } if (bldr == null) { return(tssFt); // no change } else { return(bldr.GetString()); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Scans a specified paragaph for runs with the verse number style. Then checks those /// runs for verse bridges. /// </summary> /// <param name="para">The paragraph to scan for runs containing verse bridges.</param> /// <param name="oldBridge">the old bridge sequence to replace</param> /// <param name="newBridge">The new verse bridge string.</param> /// ------------------------------------------------------------------------------------ private void UpdateVerseBridgesInParagraph(IScrTxtPara para, string oldBridge, string newBridge) { const int kStyleNameProp = (int)FwTextPropType.ktptNamedStyle; ITsString paraContents = para.Contents; ITsStrBldr bldr = null; // Iterate through the runs in the paragraph. for (int i = 0; i < paraContents.RunCount; i++) { // Get the run info and check to see if it is a verse number TsRunInfo runInfo; ITsTextProps props = paraContents.FetchRunInfo(i, out runInfo); // Check if the run is a verse number run. if (props.GetStrPropValue(kStyleNameProp) == ScrStyleNames.VerseNumber) { // Look to see if this verse is a bridge. If so, then reform it // with the new verse bridge string. string oldVerseText = paraContents.get_RunText(i); int bridgeIndex = oldVerseText.IndexOf(oldBridge, StringComparison.Ordinal); if (bridgeIndex != -1) { string newVerseText = oldVerseText.Replace(oldBridge, newBridge); // get a builder for the paragraph if one has not been gotten yet. if (bldr == null) { bldr = paraContents.GetBldr(); } // Save the verse number text in the paragraph bldr.Replace(runInfo.ichMin, runInfo.ichLim, newVerseText, props); } } } // If any run was found to contain a verse bridge, then rewrite the paragraph. if (bldr != null) { para.Contents = bldr.GetString(); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Make sure footnote exists and is referred to properly in the paragraph contents /// </summary> /// <param name="footnote"></param> /// <param name="para"></param> /// <param name="ich">Character position where ORC should be</param> /// ------------------------------------------------------------------------------------ public static void VerifyFootnote(IStFootnote footnote, IStTxtPara para, int ich) { Guid guid = footnote.Cache.GetGuidFromId(footnote.Hvo); ITsString tss = para.Contents.UnderlyingTsString; int iRun = tss.get_RunAt(ich); ITsTextProps orcPropsParaFootnote = tss.get_Properties(iRun); string objData = orcPropsParaFootnote.GetStrPropValue( (int)FwTextPropType.ktptObjData); Assert.AreEqual((char)(int)FwObjDataTypes.kodtOwnNameGuidHot, objData[0]); // Send the objData string without the first character because the first character // is the object replacement character and the rest of the string is the GUID. Guid newFootnoteGuid = MiscUtils.GetGuidFromObjData(objData.Substring(1)); Assert.AreEqual(guid, newFootnoteGuid); Assert.AreEqual(footnote.Hvo, footnote.Cache.GetIdFromGuid(newFootnoteGuid)); string sOrc = tss.get_RunText(iRun); Assert.AreEqual(StringUtils.kchObject, sOrc[0]); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Tests that a footnote marker ORC (Object Replacement Character) has been inserted /// as the iRunth run in the given TsString. /// </summary> /// <param name="tssPara">TsString to check</param> /// <param name="iRun">Zero-based index of run to check for the ORC</param> /// <param name="ws">Writing system that should be used for the ORC</param> /// <param name="fBT">Indicates whether this is checking a back translation.</param> /// ------------------------------------------------------------------------------------ public static void VerifyFootnoteMarkerOrcRun(ITsString tssPara, int iRun, int ws, bool fBT) { Debug.Assert(tssPara.RunCount > iRun, "Trying to access run #" + iRun + " when there are only " + tssPara.RunCount + " run(s)."); string sOrcRun = tssPara.get_RunText(iRun); Assert.AreEqual(1, sOrcRun.Length); Assert.AreEqual(StringUtils.kChObject, sOrcRun[0]); ITsTextProps ttpOrcRun = tssPara.get_Properties(iRun); int nDummy; int wsActual = ttpOrcRun.GetIntPropValues((int)FwTextPropType.ktptWs, out nDummy); Assert.AreEqual(ws, wsActual, "Wrong writing system for footnote marker in text"); string objData = ttpOrcRun.GetStrPropValue((int)FwTextPropType.ktptObjData); FwObjDataTypes orcType = (fBT) ? FwObjDataTypes.kodtNameGuidHot : FwObjDataTypes.kodtOwnNameGuidHot; Assert.AreEqual((char)(int)orcType, objData[0]); }
public const string DefaultMonospace = "<default monospace>"; // CANNOT BE LOCALIZED AS PUBLIC CONST STRING. #endregion #region Public methods /// ------------------------------------------------------------------------------------ /// <summary> /// Check the given text props to see if they specify the given style /// </summary> /// <param name="ttp">Text props</param> /// <param name="sStyle">Style</param> /// <returns>true if the given text props use the given named style</returns> /// ------------------------------------------------------------------------------------ public static bool IsStyle(ITsTextProps ttp, string sStyle) { return (ttp.GetStrPropValue( (int)FwTextPropType.ktptNamedStyle) == sStyle); }
/// ------------------------------------------------------------------------------------ /// <summary> /// If the embedded object is a footnote or picture, write it out. /// </summary> /// <param name="ttp">Properties contain information about the embedded object</param> /// ------------------------------------------------------------------------------------ private void ExportEmbeddedObject(ITsTextProps ttp) { string objData = ttp.GetStrPropValue((int)FwTextPropType.ktptObjData); // if ORC doesn't have properties, continue with next run. if (!String.IsNullOrEmpty(objData)) { switch (objData[0]) { case (char)FwObjDataTypes.kodtOwnNameGuidHot: case (char)FwObjDataTypes.kodtNameGuidHot: Guid footnoteGuid = MiscUtils.GetGuidFromObjData(objData.Substring(1)); IScrFootnote footnote; if (m_cache.ServiceLocator.GetInstance<IScrFootnoteRepository>().TryGetFootnote(footnoteGuid, out footnote)) { ExportFootnote(footnote); } break; case (char)FwObjDataTypes.kodtGuidMoveableObjDisp: Guid pictureGuid = MiscUtils.GetGuidFromObjData(objData.Substring(1)); ICmPicture picture; if (m_cache.ServiceLocator.GetInstance<ICmPictureRepository>().TryGetObject(pictureGuid, out picture)) ExportPicture(picture); break; case (char)FwObjDataTypes.kodtPictEvenHot: m_writer.WriteComment("object type PictEven not handled"); break; case (char)FwObjDataTypes.kodtPictOddHot: m_writer.WriteComment("object type PictOdd not handled"); break; case (char)FwObjDataTypes.kodtExternalPathName: m_writer.WriteComment("object type ExternalPathName not handled"); break; case (char)FwObjDataTypes.kodtEmbeddedObjectData: m_writer.WriteComment("object type EmbeddedObjectData not handled"); break; case (char)FwObjDataTypes.kodtContextString: m_writer.WriteComment("object type ContextString not handled"); break; default: m_writer.WriteComment( String.Format("unknown object type ({0}) not handled", (int)objData[0])); break; } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// If the embedded object is a footnote or picture, write it out. /// </summary> /// ------------------------------------------------------------------------------------ private void ExportEmbeddedObject(ITsTextProps ttp) { string objData = ttp.GetStrPropValue((int)FwTextPropType.ktptObjData); // if ORC doesn't have properties, continue with next run. if (!String.IsNullOrEmpty(objData)) { switch (objData[0]) { case (char)FwObjDataTypes.kodtOwnNameGuidHot: case (char)FwObjDataTypes.kodtNameGuidHot: Guid footnoteGuid = MiscUtils.GetGuidFromObjData(objData.Substring(1)); int hvoFootnote = m_cache.GetIdFromGuid(footnoteGuid); if (hvoFootnote != 0) ExportFootnote(new ScrFootnote(m_cache, hvoFootnote)); break; case (char)FwObjDataTypes.kodtGuidMoveableObjDisp: Guid pictureGuid = MiscUtils.GetGuidFromObjData(objData.Substring(1)); int hvoPicture = m_cache.GetIdFromGuid(pictureGuid); if (hvoPicture != 0) ExportPicture(new CmPicture(m_cache, hvoPicture)); break; case (char)FwObjDataTypes.kodtPictEven: m_writer.WriteComment("object type PictEven not handled"); break; case (char)FwObjDataTypes.kodtPictOdd: m_writer.WriteComment("object type PictOdd not handled"); break; case (char)FwObjDataTypes.kodtExternalPathName: m_writer.WriteComment("object type ExternalPathName not handled"); break; case (char)FwObjDataTypes.kodtEmbeddedObjectData: m_writer.WriteComment("object type EmbeddedObjectData not handled"); break; case (char)FwObjDataTypes.kodtContextString: m_writer.WriteComment("object type ContextString not handled"); break; default: m_writer.WriteComment( String.Format("unknown object type ({0}) not handled", (int)objData[0])); break; } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Get a Guid from the given run in a structured text string. /// </summary> /// <param name="tss">given structured text string</param> /// <param name="iRun">given run</param> /// <param name="odt">object data type, 0 if no ORC guid located</param> /// <param name="tri">run information</param> /// <param name="ttp">text properties of the run (if incoming value is null and the /// run is an object, this will be set to the run props)</param> /// <param name="desiredOrcTypes">The desired ORC types, or null to return any type of /// ORC</param> /// <returns> /// The GUID associated with the specified run of the tss, if any; otherwise Guid.Empty /// </returns> /// ------------------------------------------------------------------------------------ private static Guid GetGuidFromRun(ITsString tss, int iRun, Set<FwObjDataTypes> desiredOrcTypes, out FwObjDataTypes odt, out TsRunInfo tri, ref ITsTextProps ttp) { odt = 0; tss.FetchRunInfo(iRun, out tri); if (tri.ichLim - tri.ichMin == 1 && tss.get_RunText(iRun)[0] == kchObject) { // determine if single-character run contains an ORC ttp = ttp ?? tss.get_Properties(iRun); string sObjData = ttp.GetStrPropValue( (int)FwTextPropType.ktptObjData); if (sObjData != null) { odt = (FwObjDataTypes)Convert.ToByte(sObjData[0]); // See if it's one of the types of objects we want. if (desiredOrcTypes == null || desiredOrcTypes.Contains(odt)) { // Get GUID for ORC return MiscUtils.GetGuidFromObjData(sObjData.Substring(1)); } } } return Guid.Empty; }
/// <summary> /// Compute the assembled styles that results from applying the properties specified in the text props to this. /// We might start with a root assembled styles that says to use a 10-point font, /// then apply a paragraph style which says to use a 12-point font, except for French use 14-point. /// Then in another text props we may tell it the writing system is French, and must get 14-point as the /// result. Or, in a single TsTextProps, we may tell it the WS is French and to apply a character /// style which says to use 16-point, except for French 18-point; the result needs to be 18-point. /// It's also theoretically possible that the same text props again says directly to use 20-point; that /// should win over all the others. /// We achieve most of this by simply looking for the ws, then the named style, then everything else /// (and when we process a style, if we already know a ws we include the overrides for that ws). /// However, when we process the paragraph style, we don't know what ws a run in that paragraph will have. /// </summary> /// <param name="props"></param> /// <returns></returns> public AssembledStyles ApplyTextProps(ITsTextProps props) { AssembledStyles result = this; // Apply writing system, if present, first, so that it can be used to select // a named style effect. int ttv; int ws = props.GetIntPropValues((int) FwTextPropType.ktptWs, out ttv); if (ttv != -1) result = result.WithWs(ws); // Apply named style next, if present, so that style effects can be overridden by explicit ones. var namedStyle = props.GetStrPropValue((int) FwTextPropType.ktptNamedStyle); if (namedStyle != null) result = result.WithNamedStyle(namedStyle); int count = props.IntPropCount; for (int i = 0; i < count; i++) { int tpt; int val = props.GetIntProp(i, out tpt, out ttv); switch (tpt) { case (int) FwTextPropType.ktptWs: // handled first break; case (int) FwTextPropType.ktptBold: int weight; Debug.Assert(ttv == (int) FwTextPropVar.ktpvEnum); switch (val) { case (int) FwTextToggleVal.kttvForceOn: weight = (int) VwFontWeight.kvfwBold; break; // todo JohnT: several others. default: weight = (int)VwFontWeight.kvfwNormal; break; } result = result.WithFontWeight(weight); break; } } return result; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Export whatever goes with an ORC (e.g. footnote, picture, etc.) /// </summary> /// <param name="ttp">Text properties of the run containing the ORC (from which we get /// the footnote GUID).</param> /// <param name="exportMode">The export mode.</param> /// <param name="iWs">index into the available analysis writing systems (should be -1 if /// exportMode is ExportMode.VernacularOnly; should be 0 if exportMode is /// ExportMode.BackTransOnly)</param> /// <param name="vernFootnotes">If this is a non-interleaved back translation, this is /// the list of footnotes in the (vernacular) paragraph being exported.</param> /// ------------------------------------------------------------------------------------ private void ExportOrcRun(ITsTextProps ttp, ExportMode exportMode, int iWs, List<IScrFootnote> vernFootnotes) { Debug.Assert(exportMode != ExportMode.VernacularOnly || iWs == -1); Debug.Assert(exportMode != ExportMode.BackTransOnly || iWs == 0); string objData = ttp.GetStrPropValue((int)FwTextPropType.ktptObjData); if (objData == null) { // We encountered a bogus ORC. Ignore it. return; } switch (objData[0]) { case (char)FwObjDataTypes.kodtNameGuidHot: case (char)FwObjDataTypes.kodtOwnNameGuidHot: { Guid footnoteGuid = MiscUtils.GetGuidFromObjData(objData.Substring(1)); IScrFootnote footnote; if (m_cache.ServiceLocator.GetInstance<IScrFootnoteRepository>().TryGetFootnote(footnoteGuid, out footnote)) { ExportFootnote(footnote, exportMode, iWs); if (vernFootnotes != null) vernFootnotes.Remove(footnote); } break; } case (char)FwObjDataTypes.kodtGuidMoveableObjDisp: { Guid pictureGuid = MiscUtils.GetGuidFromObjData(objData.Substring(1)); ICmPicture picture; if (m_cache.ServiceLocator.GetInstance<ICmPictureRepository>().TryGetObject(pictureGuid, out picture)) { // TODO (TE-3619): Need to pass export mode once we can handle putting picture ORCs in back translations. ExportPicture(picture); } break; } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initializes a new instance of the <see cref="XmlTextRun"/> class, based on the given /// run information /// </summary> /// <param name="wsDefault">The default writing system of the paragraph.</param> /// <param name="lgwsf">The writing system factory.</param> /// <param name="text">The text of the run.</param> /// <param name="props">The properties of the run.</param> /// ------------------------------------------------------------------------------------ public XmlTextRun(int wsDefault, ILgWritingSystemFactory lgwsf, string text, ITsTextProps props) { int dummy; int wsRun = props.GetIntPropValues((int)FwTextPropType.ktptWs, out dummy); if (wsRun != wsDefault) IcuLocale = lgwsf.GetStrFromWs(wsRun); StyleName = props.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); m_text = text; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Initializes a new instance of the <see cref="XmlHyperlinkRun"/> class. /// </summary> /// ------------------------------------------------------------------------------------ public XmlHyperlinkRun(int wsDefault, ILgWritingSystemFactory lgwsf, string text, ITsTextProps props) : base(wsDefault, lgwsf, text, props) { Href = TsStringUtils.GetURL(props.GetStrPropValue((int)FwTextPropType.ktptObjData)); if (!string.IsNullOrEmpty(Href)) Href = Href.TrimEnd(Environment.NewLine.ToCharArray()); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Obtain a style object from character properties. /// </summary> /// <param name="ttp">Properties containing a named style</param> /// ------------------------------------------------------------------------------------ public IStStyle FindStyle(ITsTextProps ttp) { if (ttp == null) return null; return FindStyle(ttp.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle)); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Compares two TsTextProps /// </summary> /// <param name="ttp1">expected</param> /// <param name="ttp2">actual</param> /// <param name="sHowDifferent">Human(geek)-readable string telling how the props are /// different, or indicating no difference</param> /// <returns>True if they contain the same props, false otherwise</returns> /// ------------------------------------------------------------------------------------ public static bool PropsAreEqual(ITsTextProps ttp1, ITsTextProps ttp2, out string sHowDifferent) { // check how intProps compare int cProps1 = ttp1.IntPropCount; int cProps2 = ttp2.IntPropCount; int tpv1, tpv2; // prop values int nVar1, nVar2; // variation info int tpt; // prop type for (int iprop = 0; iprop < cProps1; iprop++) { tpv1 = ttp1.GetIntProp(iprop, out tpt, out nVar1); tpv2 = ttp2.GetIntPropValues(tpt, out nVar2); if (tpv1 != tpv2 || nVar1 != nVar2) { if (tpt == (int)FwTextPropType.ktptWs) sHowDifferent = string.Format("Props differ in ktptWs property. " + "Expected <{0}>, but was <{1}>.", tpv1, tpv2); else sHowDifferent = string.Format("Props differ in intProp type {0}. " + "Expected <{1},{2}>, but was <{3},{4}>.", tpt, tpv1, nVar1, tpv2, nVar2); return false; } } // if count of intProps differs, it will be difficult to report exact difference // so just issue a simple response for now if (cProps1 != cProps2) { sHowDifferent = string.Format("Props differ in count of intProps. " + "Expected <{0}>, but was <{1}>.", cProps1, cProps2); return false; } // check for string properties differences int s1count = ttp1.StrPropCount; int s2count = ttp2.StrPropCount; int strtype; string strval1, strval2; // prop values for (int iprop = 0; iprop < s1count; iprop++) { strval1 = ttp1.GetStrProp(iprop, out strtype); strval2 = ttp2.GetStrPropValue(strtype); if (strval1 != strval2) { if (strtype == (int)FwTextPropType.ktptNamedStyle) sHowDifferent = string.Format("Props differ in ktptNamedStyle property. " + "Expected <{0}>, but was <{1}>.", strval1, strval2); else if (strtype == (int)FwTextPropType.ktptObjData) sHowDifferent = string.Format("Props differ in ktptObjData property. " + "Expected <{0}>, but was <{1}>.", strval1, strval2); // we could detail the objectDataType and Guid if needed else sHowDifferent = string.Format("Props differ in strProp type {0}. " + "Expected <{1}>, but was <{2}>.", strtype, strval1, strval2); return false; } } // if count of strProps differs, it will be difficult to report exact difference // so just issue a simple response for now if (s1count != s2count) { sHowDifferent = string.Format("Props differ in count of strProps. " + "Expected <{0}>, but was <{1}>.", s1count, s2count); return false; } // if we reach this point, no differences were found sHowDifferent = "TextProps objects appear to contain the same properties."; return true; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Handle insertion of paragraphs (i.e., from clipboard) with properties that don't /// match the properties of the paragraph where they are being inserted. This gives us /// the opportunity to create/modify the DB structure to recieve the paragraphs being /// inserted and to reject certain types of paste operations (such as attempting to /// paste a book). /// </summary> /// <param name="rootBox">the sender</param> /// <param name="ttpDest">properties of destination paragraph</param> /// <param name="cPara">number of paragraphs to be inserted</param> /// <param name="ttpSrcArray">Array of props of each para to be inserted</param> /// <param name="tssParas">Array of TsStrings for each para to be inserted</param> /// <param name="tssTrailing">Text of an incomplete paragraph to insert at end (with /// the properties of the destination paragraph.</param> /// <returns>One of the following: /// kidprDefault - causes the base implementation to insert the material as part of the /// current StText in the usual way; /// kidprFail - indicates that we have decided that this text should not be pasted at /// this location at all, causing entire operation to roll back; /// kidprDone - indicates that we have handled the paste ourselves, inserting the data /// whereever it ought to go and creating any necessary new structure.</returns> /// ------------------------------------------------------------------------------------ public VwInsertDiffParaResponse InsertDiffParas(IVwRootBox rootBox, ITsTextProps ttpDest, int cPara, ITsTextProps[] ttpSrcArray, ITsString[] tssParas, ITsString tssTrailing) { CheckDisposed(); Debug.Assert(!IsBackTranslation); if (cPara != ttpSrcArray.Length || cPara != tssParas.Length || ttpDest == null || IsBackTranslation) return VwInsertDiffParaResponse.kidprFail; // Get the context of the style we are inserting into string destStyleName = ttpDest.GetStrPropValue((int)FwTextStringProp.kstpNamedStyle); IStStyle destStyle = null; if (destStyleName != null) destStyle = m_scr.FindStyle(destStyleName); if (destStyle == null) return VwInsertDiffParaResponse.kidprFail; ContextValues destContext = destStyle.Context; StructureValues destStructure = destStyle.Structure; // If pasted data came from a non-FW app, all elements in the source props array // will be null. In this case, the default behavior will work fine. if (ttpSrcArray[0] == null) { int i; for (i = 1; i < ttpSrcArray.Length; i++) { if (ttpSrcArray[i] != null) break; } if (i >= ttpSrcArray.Length) return VwInsertDiffParaResponse.kidprDefault; } // Look through the source data (being inserted) to see if there is a conflict. ContextValues srcContext; StructureValues srcStructure; if (!GetSourceContextAndStructure(ttpSrcArray, out srcContext, out srcStructure)) { MiscUtils.ErrorBeep(); return VwInsertDiffParaResponse.kidprFail; } // If context of the style is Title then throw out the entire insert. // REVIEW: Should this allow insertion of a title para within an existing title? if (srcContext == ContextValues.Title) { MiscUtils.ErrorBeep(); return VwInsertDiffParaResponse.kidprFail; } // Set a flag if the src context/structure is different from the dest context/structure bool foundMismatch = (srcContext != destContext) || (srcStructure != destStructure); if (!foundMismatch) // let the views handle it! return VwInsertDiffParaResponse.kidprDefault; bool noTrailingText = (tssTrailing == null || tssTrailing.Length == 0); // If insertion point is at beginning of paragraph and there is no trailing text if (CurrentSelection.IchAnchor == 0 && noTrailingText) { if (InBookTitle) { if (InsertParagraphsBeforeBook(ttpSrcArray, tssParas, srcContext)) return VwInsertDiffParaResponse.kidprDone; } else if (InSectionHead) { if (SectionIndex > 0 && ParagraphIndex == 0 && InsertParagraphsBeforeSection(ttpSrcArray, tssParas, srcContext)) return VwInsertDiffParaResponse.kidprDone; } else if (srcContext == destContext && InsertParagraphsInSection(ttpSrcArray, tssParas)) return VwInsertDiffParaResponse.kidprDone; } // The contexts don't match and we don't handle it so fail. // Case not handled - beep and return failure MiscUtils.ErrorBeep(); return VwInsertDiffParaResponse.kidprFail; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Write out a reference to a footnote. A reference should only be exported from a back /// translation. /// </summary> /// <param name="ttp">Properties contain information about the embedded object</param> /// ------------------------------------------------------------------------------------ private void ExportRefToEmbeddedObject(ITsTextProps ttp) { string objData = ttp.GetStrPropValue((int) FwTextPropType.ktptObjData); // if ORC doesn't have properties, continue with next run. if (!String.IsNullOrEmpty(objData)) { switch (objData[0]) { case (char) FwObjDataTypes.kodtNameGuidHot: IScrFootnote footnote; if (!GetReferencedFootnote(ttp, out footnote)) return; // unable to find referenced footnote m_writer.WriteStartElement("note"); m_writer.WriteAttributeString("noteRef", "f" + m_sCurrentBookId + (footnote.IndexInOwner + 1)); m_writer.WriteEndElement(); // end <note> element break; default: // give warning about dropped pictures in BT, but only give it once. if (!m_droppedBtPictureWarningGiven) { MessageBoxUtils.Show( "OXES file format does not support pictures in back translation. Location of pictures in BT will be lost.", m_app.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Information); m_droppedBtPictureWarningGiven = true; } break; } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Checks to see if the text properties are for a hyperlink. /// </summary> /// <param name="ttp">The text properties.</param> /// <returns><c>true</c> if the properties are for a hyperlink; <c>false</c> otherwise. /// </returns> /// ------------------------------------------------------------------------------------ public static bool IsHyperlink(ITsTextProps ttp) { string objData = ttp.GetStrPropValue((int)FwTextPropType.ktptObjData); if (!String.IsNullOrEmpty(objData) && objData.Length > 1 && objData[0] == Convert.ToChar((int)FwObjDataTypes.kodtExternalPathName)) { return true; } return false; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Gets footnote hvo from reference in text properties /// </summary> /// <param name="cache"></param> /// <param name="tprops"></param> /// <returns>Hvo of the footnote that was found or 0 if none was found</returns> /// ------------------------------------------------------------------------------------ protected static int GetFootnoteFromProps(FdoCache cache, ITsTextProps tprops) { string footnoteRef = tprops.GetStrPropValue((int)FwTextPropType.ktptObjData); if (footnoteRef != null) { // first char. of strData is type code - GUID will follow it. Guid objGuid = MiscUtils.GetGuidFromObjData(footnoteRef.Substring(1)); int hvo = cache.GetIdFromGuid(objGuid); if (hvo > 0 && cache.GetClassOfObject(hvo) == StFootnote.kClassId) return hvo; } return 0; }
/// ------------------------------------------------------------------------------------ /// <summary> /// Change the paragraph style. /// </summary> /// ------------------------------------------------------------------------------------ protected override void ChangeParagraphStyle(ISilDataAccess sda, ITsTextProps ttp, int hvoPara) { if (ttp != null) { string style = ttp.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); string undo, redo; ResourceHelper.MakeUndoRedoLabels("kstidUndoStyleChanges", out undo, out redo); undo = string.Format(undo, style); redo = string.Format(redo, style); UndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(undo, redo, Cache.ServiceLocator.GetInstance<IActionHandler>(), () => CallBaseChangeParagraphStyle(sda, ttp, hvoPara)); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Export whatever goes with an ORC (e.g. footnote, picture, etc.) /// </summary> /// <param name="ttp">Text properties of the run containing the ORC (from which we get /// the footnote GUID).</param> /// <param name="exportMode">The export mode.</param> /// <param name="iWs">index into the available analysis writing systems (should be -1 if /// exportMode is ExportMode.VernacularOnly; should be 0 if exportMode is /// ExportMode.BackTransOnly)</param> /// ------------------------------------------------------------------------------------ private void ExportOrcRun(ITsTextProps ttp, ExportMode exportMode, int iWs) { Debug.Assert(exportMode != ExportMode.VernacularOnly || iWs == -1); Debug.Assert(exportMode != ExportMode.BackTransOnly || iWs == 0); string objData = ttp.GetStrPropValue((int)FwTextPropType.ktptObjData); if (objData == null) { // We encountered a bogus ORC. Ignore it. return; } switch (objData[0]) { case (char)FwObjDataTypes.kodtNameGuidHot: case (char)FwObjDataTypes.kodtOwnNameGuidHot: { Guid footnoteGuid = MiscUtils.GetGuidFromObjData(objData.Substring(1)); int hvoFootnote = m_cache.GetIdFromGuid(footnoteGuid); if (hvoFootnote > 0) ExportFootnote(new ScrFootnote(m_cache, hvoFootnote), exportMode, iWs); break; } case (char)FwObjDataTypes.kodtGuidMoveableObjDisp: { Guid pictureGuid = MiscUtils.GetGuidFromObjData(objData.Substring(1)); int hvoPicture = m_cache.GetIdFromGuid(pictureGuid); // TODO (TE-3619): Need to pass export mode once we can handle putting picture ORCs in back translations. if (hvoPicture > 0) ExportPicture(new CmPicture(m_cache, hvoPicture)); break; } } }
//#if DEBUG // private void WriteSegmentedBackTransDebugInfo(BTSegment bts, int iseg) // { // foreach (int ws1 in bts.AvailableTranslations) // { // ITsString tssBT = bts.GetTransForWs(ws1); // string sBTDebug = String.Format("Seg[{0}] begin={1,4}, end={2,4}; [{3}]='{4}'", // iseg, bts.BeginOffset, bts.EndOffset, // m_cache.LanguageWritingSystemFactoryAccessor.GetStrFromWs(ws1), // tssBT == null ? "<NULL>" : tssBT.Text); // Debug.WriteLine(sBTDebug); // } // } //#endif /// ------------------------------------------------------------------------------------ /// <summary> /// If the text props contains a footnote pointer, return the Guid which refers to the /// footnote. Otherwise, return Guid.Empty. /// </summary> /// <param name="props"></param> /// <returns></returns> /// ------------------------------------------------------------------------------------ private static Guid GetFootnoteGuidIfAny(ITsTextProps props) { string objData = props.GetStrPropValue((int)FwTextPropType.ktptObjData); if (!String.IsNullOrEmpty(objData) && (objData[0] == (char)FwObjDataTypes.kodtOwnNameGuidHot || objData[0] == (char)FwObjDataTypes.kodtNameGuidHot)) { return MiscUtils.GetGuidFromObjData(objData.Substring(1)); } return Guid.Empty; }