/// ----------------------------------------------------------------------------------- /// <summary> /// Static method to create a new structured text. It creates an StText object owned by /// hvoOwner in property tag, then creates an StTxtPara owned by the new StText. It /// sets the contents of the paragraph to be an empty string in the specified writing system, /// and Normal paragraph style. /// </summary> /// ENHANCE JohnT: probably we will identify styles by something other than name. /// REVIEW JohnT(TomB): Are we supposed to be supplying a style name rather than just /// using "Normal"? /// /// <param name="cache">FieldWorks database access</param> /// <param name="hvoOwner">id of object to own the new StText</param> /// <param name="propTag">property (field) type of the new StText</param> /// <param name="ws">language writing system of empty paragraph</param> /// <returns>HVO of the newly created StText object</returns> /// ----------------------------------------------------------------------------------- public static int MakeEmptyStText(FdoCache cache, int hvoOwner, int propTag, int ws) { // REVIEW TomB: Lastparm should really be null if Randy changes CreateObject. // Response from RandyR: I changed CreateObject. Null should work for // everything now. // Most of this code could be moved into the FDO objects, if desired. int hvoStText = cache.CreateObject(StText.kclsidStText, hvoOwner, propTag, 0); int hvoPara = cache.CreateObject(StTxtPara.kclsidStTxtPara, hvoStText, (int)StText.StTextTags.kflidParagraphs, 0); // Set the style of the paragraph to Normal ITsTextProps ttpNormal; ITsPropsBldr tsPropsBldr = TsPropsBldrClass.Create(); tsPropsBldr.SetStrPropValue((int)FwTextPropType.ktptNamedStyle, StyleNames.ksNormal); ttpNormal = tsPropsBldr.GetTextProps(); cache.MainCacheAccessor.SetUnknown(hvoPara, (int)StPara.StParaTags.kflidStyleRules, ttpNormal); // Set its contents to an empty string in the right writing system. ITsStrFactory tsFactory = TsStrFactoryClass.Create(); cache.SetTsStringProperty(hvoPara, (int)StTxtPara.StTxtParaTags.kflidContents, tsFactory.MakeStringRgch("", 0, ws)); return(hvoStText); }
/// ----------------------------------------------------------------------------------- /// <summary> /// We need to show something, since the current view code can't handle a property /// containing no boxes. Check to see if the StText is missing or if there are /// no paragraphs. If so, then put in an empty string placeholder. /// TODO (FWR-1688): If we prevent the occurrence of texts with no paragraphs in FDO, /// this code can be removed. /// </summary> /// <param name="vwenv">view environment</param> /// <param name="hvo">id of object to be displayed</param> /// <returns>true if an empty string was substituted for missing/empty StText</returns> /// ----------------------------------------------------------------------------------- protected bool HandleEmptyText(IVwEnv vwenv, int hvo) { if (hvo == 0 || vwenv.DataAccess.get_VecSize(hvo, StTextTags.kflidParagraphs) > 0) { return(false); } // Either we have no ST object at all, or it is empty of paragraphs. The // current view code can't handle either, so stick something in. // ENHANCE JohnT: come up with a real solution. This makes it look right, // but we should (a) be able to edit and have the first paragraph and // if necessary the text itself be created; and (b) if someone adds a real // paragraph and/or text in some other view, have them show up. ITsStrFactory tsStrFactory = TsStrFactoryClass.Create(); int ws = vwenv.DataAccess.WritingSystemFactory.UserWs; ITsString tssMissing = tsStrFactory.MakeStringRgch("", 0, ws); vwenv.set_IntProperty((int)FwTextPropType.ktptParaColor, (int)FwTextPropVar.ktpvDefault, m_BackColor.ToArgb()); vwenv.set_StringProperty((int)FwTextPropType.ktptNamedStyle, m_sDefaultParaStyle); vwenv.set_IntProperty((int)FwTextPropType.ktptEditable, (int)FwTextPropVar.ktpvEnum, (int)TptEditable.ktptNotEditable); // This sets the current default writing system from the relevant field spec. vwenv.set_IntProperty((int)FwTextPropType.ktptBaseWs, (int)FwTextPropVar.ktpvDefault, m_wsDefault); vwenv.AddString(tssMissing); return(true); }
/// ------------------------------------------------------------------------------------ /// <summary> /// This is the main interesting method of displaying objects and fragments of them. /// A Scripture is displayed by displaying its Books; /// and a Book is displayed by displaying its Title and Sections; /// and a Section is diplayed by displaying its Heading and Content; /// which are displayed by showing the style for each paragraph in the StText. /// </summary> /// <param name="vwenv"></param> /// <param name="hvo"></param> /// <param name="frag"></param> /// ------------------------------------------------------------------------------------ public override void Display(IVwEnv vwenv, int hvo, int frag) { CheckDisposed(); ISilDataAccess silDataAccess = vwenv.DataAccess; int wsUser = Cache.WritingSystemFactory.UserWs; switch (frag) { case (int)FootnoteFrags.kfrBook: case (int)ScrFrags.kfrBook: { vwenv.OpenDiv(); if (m_displayForFootnotes) { vwenv.AddObjVecItems(ScrBookTags.kflidFootnotes, this, (int)FootnoteFrags.kfrFootnoteStyles); } else { vwenv.AddObjProp(ScrBookTags.kflidTitle, this, (int)ScrFrags.kfrTextStyles); vwenv.AddLazyVecItems(ScrBookTags.kflidSections, this, (int)ScrFrags.kfrSection); InsertBookSeparator(hvo, vwenv); } vwenv.CloseDiv(); break; } case (int)ScrFrags.kfrSection: { vwenv.OpenDiv(); vwenv.AddObjProp(ScrSectionTags.kflidHeading, this, (int)ScrFrags.kfrTextStyles); vwenv.AddObjProp(ScrSectionTags.kflidContent, this, (int)ScrFrags.kfrTextStyles); vwenv.CloseDiv(); break; } case (int)ScrFrags.kfrTextStyles: { // We need to show something, since the current view code can't handle a property // containing no boxes. if (HandleEmptyText(vwenv, hvo)) { break; } if (m_fLazy) { vwenv.AddLazyVecItems(StTextTags.kflidParagraphs, this, (int)ScrFrags.kfrParaStyles); } else { vwenv.AddObjVecItems(StTextTags.kflidParagraphs, this, (int)ScrFrags.kfrParaStyles); } break; } case (int)FootnoteFrags.kfrFootnoteStyles: { if (HandleEmptyText(vwenv, hvo)) { break; } vwenv.AddObjVecItems(StTextTags.kflidParagraphs, this, (int)ScrFrags.kfrParaStyles); break; } case (int)ScrFrags.kfrParaStyles: { var tsTextProps = silDataAccess.get_UnknownProp(hvo, StParaTags.kflidStyleRules) as ITsTextProps; string styleName = ScrStyleNames.Normal; if (tsTextProps != null) { styleName = tsTextProps.GetStrPropValue((int)FwTextPropType.ktptNamedStyle); } // To insert it into the view it has to be an ITsString ITsStrFactory tsStrFactory = TsStrFactoryClass.Create(); // Last arg is writing system. Should we use English? UI writing system? // Note that when we support localization of style names this code will need // to be enhanced as the stylename from the TsTextProps will be a raw name or // GUID that the user shouldn't see. ITsString tssStyle = tsStrFactory.MakeStringRgch(styleName, styleName.Length, wsUser); // To make the pile align things properly, top and bottom margins for the // matching boxes must be the same as the original. // A 'concordance' paragraph is a way of preventing wrapping. vwenv.OpenConcPara(0, 0, 0, 0); vwenv.AddString(tssStyle); // Since we looked up this property directly rather than going through the vwenv (which // there seems to be no way to do for Unknown-type properties as yet), we need to tell // the view to update this paragraph if the properties of the paragraph are changed. vwenv.NoteDependency(new[] { hvo }, new[] { StParaTags.kflidStyleRules }, 1); vwenv.CloseParagraph(); break; } default: base.Display(vwenv, hvo, frag); break; } }
public ICollection <SpellCorrectMenuItem> GetSuggestions(Point mousePos, SimpleRootSite rootsite, out int hvoObj, out int tag, out int wsAlt, out int wsText, out string word, out Dictionary dict, out bool nonSpellingError) { hvoObj = tag = wsAlt = wsText = 0; // make compiler happy for early returns word = null; dict = null; nonSpellingError = true; IVwRootBox rootb = rootsite != null ? rootsite.RootBox : null; if (rootb == null) { return(null); } // Get a selection at the indicated point. IVwSelection sel = rootsite.GetSelectionAtPoint(mousePos, false); // Get the selected word and verify that it is a single run within a single // editable string. if (sel != null) { sel = sel.GrowToWord(); } if (sel == null || !sel.IsRange || sel.SelType != VwSelType.kstText || !SelectionHelper.IsEditable(sel)) { return(null); } ITsString tss; bool fAssocPrev; int ichAnchor; sel.TextSelInfo(false, out tss, out ichAnchor, out fAssocPrev, out hvoObj, out tag, out wsAlt); int ichEnd, hvoObjE, tagE, wsE; sel.TextSelInfo(true, out tss, out ichEnd, out fAssocPrev, out hvoObjE, out tagE, out wsE); if (hvoObj != hvoObjE || tag != tagE || wsAlt != wsE) { return(null); } int ichMin = Math.Min(ichEnd, ichAnchor); int ichLim = Math.Max(ichEnd, ichAnchor); ILgWritingSystemFactory wsf = rootsite.RootBox.DataAccess.WritingSystemFactory; // May need to enlarge the word beyond what GrowToWord does, if there is adjacent wordforming material. int ichMinAdjust = AdjustWordBoundary(wsf, tss, ichMin, -1, 0) + 1; // further expanded start of word. int ichLimAdjust = AdjustWordBoundary(wsf, tss, ichLim - 1, 1, tss.Length); // further expanded lim of word. // From the ends we can strip stuff with different spell-checking properties. IVwStylesheet styles = rootsite.RootBox.Stylesheet; int spellProps = SpellCheckProps(tss, ichMin, styles); while (ichMinAdjust < ichMin && SpellCheckProps(tss, ichMinAdjust, styles) != spellProps) { ichMinAdjust++; } while (ichLimAdjust > ichLim && SpellCheckProps(tss, ichLimAdjust - 1, styles) != spellProps) { ichLimAdjust--; } ichMin = ichMinAdjust; ichLim = ichLimAdjust; ITsStrFactory tsf = TsStrFactoryClass.Create(); // Now we have the specific range we will check. Get the actual string. ITsStrBldr bldr = tss.GetBldr(); if (ichLim < bldr.Length) { bldr.ReplaceTsString(ichLim, bldr.Length, null); } if (ichMin > 0) { bldr.ReplaceTsString(0, ichMin, null); } ITsString tssWord = bldr.GetString(); // See whether we need the special blue underline, which is used mainly for adjacent words in different writing systems. List <int> wss = TsStringUtils.GetWritingSystems(tssWord); if (wss.Count > 1) { return(MakeWssSuggestions(tssWord, wss, rootb, hvoObj, tag, wsAlt, ichMin, ichLim)); } ITsString keepOrcs; // holds any ORCs we found in the original word that we need to keep rather than reporting. IList <SpellCorrectMenuItem> result = MakeEmbeddedNscSuggestion(ref tssWord, styles, rootb, hvoObj, tag, wsAlt, ichMin, ichLim, out keepOrcs); if (result.Count > 0) { return(result); } // Determine whether it is a spelling problem. wsText = TsStringUtils.GetWsOfRun(tssWord, 0); dict = EnchantHelper.GetDictionary(wsText, wsf); if (dict == null) { return(null); } word = tssWord.get_NormalizedForm(FwNormalizationMode.knmNFC).Text; if (word == null) { return(null); // don't think this can happen, but... } if (dict.Check(word)) { return(null); // not mis-spelled. } // Get suggestions. Make sure to return an empty collection rather than null, even if no suggestions, // to indicate an error. ICollection <string> suggestions = dict.Suggest(word); foreach (string suggest in suggestions) { ITsString replacement = tsf.MakeStringRgch(suggest, suggest.Length, wsText); if (keepOrcs != null) { ITsStrBldr bldrRep = keepOrcs.GetBldr(); bldrRep.ReplaceTsString(0, 0, replacement); replacement = bldrRep.GetString(); } result.Add(new SpellCorrectMenuItem(rootb, hvoObj, tag, wsAlt, ichMin, ichLim, suggest, replacement)); } nonSpellingError = false; // it IS a spelling problem. return(result); }