Beispiel #1
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Loads the footnotes.
        /// </summary>
        /// <param name="footnoteHvo">The footnote hvo.</param>
        /// ------------------------------------------------------------------------------------
        private void LoadFootnotes(int footnoteHvo)
        {
            Debug.Assert(m_cache.GetClassOfObject(footnoteHvo) == StFootnote.kClassId);
            StFootnote foot          = new StFootnote(m_cache, footnoteHvo);
            IScrBook   book          = new ScrBook(m_cache, foot.OwnerHVO);
            int        footnoteCount = GetBookFootnoteCount(book.Hvo);
            FdoOwningSequence <IStFootnote> footnotes = book.FootnotesOS;

            // If the information we want is already in the cache, then do nothing
            if (footnotes.Count == footnoteCount && m_htFootnoteIndex.ContainsKey(footnoteHvo))
            {
                return;
            }

            ScrFootnote footnote = null;
            int         index    = 0;

            for (int i = 0; i < footnotes.Count; i++)
            {
                footnote = new ScrFootnote(m_cache, footnotes.HvoArray[i]);
                if (footnote.FootnoteType == FootnoteMarkerTypes.AutoFootnoteMarker)
                {
                    int oldIndex = GetFootnoteIndex(footnote.Hvo);
                    if (oldIndex != index)
                    {
                        m_htFootnoteIndex[footnote.Hvo] = new FootnoteIndexCacheInfo(index, true);
                    }
                    index++;
                }
            }
            m_htBookFootnoteCount[book.Hvo] = footnotes.Count;
        }
Beispiel #2
0
        /// <summary>
        /// a  factory method for creating the correct type of object label, depending on the
        /// class of the object
        /// </summary>
        static public ObjectLabel CreateObjectLabel(FdoCache cache, int hvo,
                                                    string displayNameProperty, string displayWs)
        {
            if (hvo == 0)
            {
                return(new NullObjectLabel(cache));
            }
            else
            {
                //enhance: this is very expensive currently, it loads the entire object.
                // does it? it's not obvious to the casual observer...
                uint classId     = (uint)cache.GetClassOfObject(hvo);
                uint baseClassId = 0;
                if (classId == CmPossibility.kClassId)
                {
                    baseClassId = classId;                      // not exactly true, but simplifies logic below.
                }
                else
                {
                    baseClassId = cache.MetaDataCacheAccessor.GetBaseClsId(classId);
                }

                if (CmPossibility.kClassId == baseClassId)
                {
                    return(new CmPossibilityLabel(cache, hvo, displayNameProperty, displayWs));
                }
                else if (MoInflClass.kClassId == classId)
                {
                    return(new MoInflClassLabel(cache, hvo, displayNameProperty, displayWs));
                }
                else
                {
                    return(new ObjectLabel(cache, hvo, displayNameProperty, displayWs));
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Create the ordered vector of writing sytems to try for displaying names.
        /// </summary>
        protected void EstablishWritingSystemsToTry(string sDisplayWs)
        {
            if (m_cache == null || m_writingSystemIds != null)
            {
                return;
            }

            if (sDisplayWs == null || sDisplayWs == String.Empty)
            {
                sDisplayWs = "analysis vernacular";                             // very general default.
            }
            int flid = 0;

            if (!string.IsNullOrEmpty(m_displayNameProperty))
            {
                string            className = m_cache.GetClassName((uint)m_cache.GetClassOfObject(Hvo));
                IVwVirtualHandler vh        = m_cache.VwCacheDaAccessor.GetVirtualHandlerName(className, m_displayNameProperty);
                if (vh != null)
                {
                    flid = vh.Tag;
                }
            }
            m_writingSystemIds = LangProject.GetWritingSystemIdsFromLabel(m_cache, sDisplayWs, m_cache.DefaultUserWs, m_hvo, flid, null);
        }
Beispiel #4
0
		/// <summary>
		/// Get a wordform from an HVO that may be a WfiWordform, WfiAnalysis, or WfiGloss (or 0).
		/// Answer 0 if arguent is zero, fail if it is some other class.
		/// </summary>
		public static int GetWordformFromWag(FdoCache cache, int cbaInstanceOf)
		{
			int hvoWordform = 0;
			if (cbaInstanceOf != 0)
			{
				int classid = cache.GetClassOfObject(cbaInstanceOf);
				switch (classid)
				{
					case WfiWordform.kclsidWfiWordform:
						hvoWordform = cbaInstanceOf;
						break;
					case WfiAnalysis.kclsidWfiAnalysis:
						hvoWordform = cache.GetOwnerOfObject(cbaInstanceOf);
						break;
					case WfiGloss.kclsidWfiGloss:
						int hvoAnalysis = cache.GetOwnerOfObject(cbaInstanceOf);
						hvoWordform = cache.GetOwnerOfObject(hvoAnalysis);
						break;
					default:
						Debug.Fail("Actual cba (" + cbaInstanceOf + "): Class of InstanceOf (" +
								   classid + ") is not WfiWordform, WfiAnalysis, or WfiGloss.");
						break;
				}
			}
			return hvoWordform;
		}
Beispiel #5
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Refreshes cache for all footnotes in the StText containing the paragraph.  We only
		/// use this method when verses of a paragraph are changed - this will only happen on
		/// content paragraphs of a ScrSection.
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="hvoObj"></param>
		/// ------------------------------------------------------------------------------------
		internal static void RefreshCacheForParagraph(FdoCache cache, int hvoObj)
		{
			int hvoPara = hvoObj;
			if (cache.GetClassOfObject(hvoObj) == CmTranslation.kClassId)
				hvoPara = cache.GetOwnerOfObject(hvoObj);

			int hvoText = cache.GetOwnerOfObject(hvoPara);
			IStText text = new StText(cache, hvoText);
			ScrSection section = new ScrSection(cache, text.OwnerHVO);
			BCVRef verseRef = new BCVRef(section.VerseRefStart);

			Dictionary<int, FootnoteHashEntry> dict;
			// Don't bother on empty cache - it will be created when needed. Need to use HVO to get GUID so we
			// don't create the book and potentially cause the refresh routine to be called.
			Guid bookGuid = cache.GetGuidFromId(section.OwnerHVO);
			if (!cache.TryGetHashtable<int, FootnoteHashEntry>(bookGuid, out dict) ||
				dict.Count == 0)
			{
				return;
			}

			AddFootnoteRefsInText(text, dict, ref verseRef);
		}
Beispiel #6
0
		/// ------------------------------------------------------------------------------------
		/// <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;
		}
Beispiel #7
0
		/// <summary>
		/// a  factory method for creating the correct type of object label, depending on the
		/// class of the object
		/// </summary>
		static public ObjectLabel CreateObjectLabel(FdoCache cache, int hvo,
			string displayNameProperty, string displayWs)
		{
			if (hvo == 0)
			{
				return new NullObjectLabel(cache);
			}
			else
			{
				//enhance: this is very expensive currently, it loads the entire object.
				// does it? it's not obvious to the casual observer...
				uint classId = (uint)cache.GetClassOfObject(hvo);
				uint baseClassId = 0;
				if (classId == CmPossibility.kClassId)
					baseClassId = classId;	// not exactly true, but simplifies logic below.
				else
					baseClassId = cache.MetaDataCacheAccessor.GetBaseClsId(classId);

				if (CmPossibility.kClassId == baseClassId)
					return new CmPossibilityLabel(cache, hvo, displayNameProperty, displayWs);
				else if (MoInflClass.kClassId == classId)
					return new MoInflClassLabel(cache, hvo, displayNameProperty, displayWs);
				else
					return new ObjectLabel(cache, hvo, displayNameProperty, displayWs);
			}
		}
Beispiel #8
0
		/// <summary>
		///
		/// </summary>
		/// <param name="fdoCache"></param>
		/// <param name="dummyAnnHvo"></param>
		/// <returns></returns>
		public static ICmBaseAnnotation ConvertBaseAnnotationToReal(FdoCache fdoCache, int dummyAnnHvo)
		{
			using (SuppressSubTasks supressActionHandler = new SuppressSubTasks(fdoCache, true))
			{
				Debug.Assert(fdoCache.IsDummyObject(dummyAnnHvo));
				if (!fdoCache.IsDummyObject(dummyAnnHvo) ||
					fdoCache.GetClassOfObject(dummyAnnHvo) != CmBaseAnnotation.kclsidCmBaseAnnotation)
				{
					return null; // indicate no change.
				}
				ISilDataAccess sda = fdoCache.MainCacheAccessor;
				ICmBaseAnnotation cbaDummy = (ICmBaseAnnotation)CmObject.CreateFromDBObject(fdoCache, dummyAnnHvo, false);
				ICmBaseAnnotation cbaReal = CreateRealAnnotation(fdoCache, cbaDummy.AnnotationTypeRAHvo, cbaDummy.InstanceOfRAHvo,
					cbaDummy.BeginObjectRAHvo, cbaDummy.Flid, cbaDummy.BeginOffset, cbaDummy.EndOffset);
				cbaReal.WritingSystemRAHvo = cbaDummy.WritingSystemRAHvo;
				int hvoRealAnn = cbaReal.Hvo;

				// transfer any default analysis (guess)
				int ktagTwficDefault = StTxtPara.TwficDefaultFlid(fdoCache);
				int hvoTwficAnalysisGuess = fdoCache.GetObjProperty(dummyAnnHvo, ktagTwficDefault);
				if (hvoTwficAnalysisGuess != 0)
				{
					fdoCache.VwCacheDaAccessor.CacheObjProp(hvoRealAnn, ktagTwficDefault, hvoTwficAnalysisGuess);
				}
				int textSegType = CmAnnotationDefn.TextSegment(fdoCache).Hvo;
				int twficType = CmAnnotationDefn.Twfic(fdoCache).Hvo;
				if (cbaDummy.AnnotationTypeRAHvo == twficType)
					StTxtPara.CacheReplaceTWFICAnnotation(fdoCache, dummyAnnHvo, hvoRealAnn);
				else if (cbaDummy.AnnotationTypeRAHvo == textSegType)
					StTxtPara.CacheReplaceTextSegmentAnnotation(fdoCache, dummyAnnHvo, hvoRealAnn);
				else
					Debug.Assert(true, "CacheReplace does not yet support annotation type " + cbaDummy.AnnotationTypeRAHvo);
				// now clear it from the cache, since we're done with it.
				if (fdoCache.ActionHandlerAccessor != null)
					fdoCache.ActionHandlerAccessor.AddAction(new ClearInfoOnCommitUndoAction(fdoCache, dummyAnnHvo));
				return cbaReal;
			}
		}
Beispiel #9
0
		/// <summary>
		/// If hvoEntry is the id of a variant, try to find an entry it's a variant of that
		/// has a sense.  Return the corresponding ILexEntryRef for the first such entry.
		/// If this is being called to establish a default monomorphemic guess, skip over
		/// any bound root or bound stem entries that hvoEntry may be a variant of.
		/// </summary>
		public static ILexEntryRef GetVariantRef(FdoCache cache, int hvoEntry, bool fMonoMorphemic)
		{
			ISilDataAccess sda = cache.MainCacheAccessor;
			int cRef = sda.get_VecSize(hvoEntry, (int)LexEntry.LexEntryTags.kflidEntryRefs);
			for (int i = 0; i < cRef; ++i)
			{
				int hvoRef = sda.get_VecItem(hvoEntry,
					(int)LexEntry.LexEntryTags.kflidEntryRefs, i);
				int refType = sda.get_IntProp(hvoRef,
					(int)LexEntryRef.LexEntryRefTags.kflidRefType);
				if (refType == LexEntryRef.krtVariant)
				{
					int cEntries = sda.get_VecSize(hvoRef,
						(int)LexEntryRef.LexEntryRefTags.kflidComponentLexemes);
					if (cEntries != 1)
						continue;
					int hvoComponent = sda.get_VecItem(hvoRef,
						(int)LexEntryRef.LexEntryRefTags.kflidComponentLexemes, 0);
					int clid = cache.GetClassOfObject(hvoComponent);
					if (fMonoMorphemic && IsEntryBound(cache, hvoComponent, clid))
						continue;
					if (clid == LexSense.kclsidLexSense ||
						sda.get_VecSize(hvoComponent, (int)LexEntry.LexEntryTags.kflidSenses) > 0)
					{
						return LexEntryRef.CreateFromDBObject(cache, hvoRef);
					}
					else
					{
						// Should we check for a variant of a variant of a ...?
					}
				}
			}
			return null; // nothing useful we can do.
		}
Beispiel #10
0
		/// <summary>
		/// Get the writing system for the given ReversalIndexEntry.
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="hvoObj"></param>
		/// <param name="wsDefault"></param>
		/// <returns></returns>
		public static int GetReversalIndexEntryWritingSystem(FdoCache cache, int hvoObj, int wsDefault)
		{
			if (cache != null && hvoObj != 0)
			{
				IReversalIndex ri = null;
				int clid = cache.GetClassOfObject(hvoObj);
				switch (clid)
				{
					case ReversalIndex.kclsidReversalIndex:
						ri = ReversalIndex.CreateFromDBObject(cache, hvoObj);
						break;
					case ReversalIndexEntry.kclsidReversalIndexEntry:
						int hvoReversalIndex = cache.GetOwnerOfObjectOfClass(hvoObj, ReversalIndex.kclsidReversalIndex);
						if (hvoReversalIndex > 0)
							ri = ReversalIndex.CreateFromDBObject(cache, hvoReversalIndex);
						break;
					case PartOfSpeech.kclsidPartOfSpeech:
						// It may be nested, but we need the owner (index) of the list,
						// no matter how high up.
						int reversalIndexId = cache.GetOwnerOfObjectOfClass(hvoObj, ReversalIndex.kclsidReversalIndex);
						if (reversalIndexId > 0)
							ri = ReversalIndex.CreateFromDBObject(cache, reversalIndexId);
						break;
					case LexSense.kclsidLexSense:
					// Pick a plausible default reversal index for the LexSense.
					case LexDb.kclsidLexDb: // happens while initializing bulk edit combos
					default: // since this doesn't actually depend on the hvo, it's not a bad general default.
						List<int> rgriCurrent = cache.LangProject.LexDbOA.CurrentReversalIndices;
						if (rgriCurrent.Count > 0)
						{
							ri = ReversalIndex.CreateFromDBObject(cache, (int)rgriCurrent[0]);
						}
						else
						{
							if (cache.LangProject.LexDbOA.ReversalIndexesOC.Count > 0)
							{
								int hvo = cache.LangProject.LexDbOA.ReversalIndexesOC.HvoArray[0];
								ri = (IReversalIndex)CmObject.CreateFromDBObject(cache, hvo);
							}
						}
						break;
				}
				if (ri != null)
					return ri.WritingSystemRAHvo;
			}
			return wsDefault;
		}
Beispiel #11
0
		public static int GetParentOfClass(FdoCache m_cache, int hvo, int classIdOfParentToSearchFor)
		{
			//save the caller the need to see if this property was empty or not
			if(hvo <1)
				return -1;

			int classId = m_cache.GetClassOfObject(hvo) ;

			while((!m_cache.IsSameOrSubclassOf(classId,classIdOfParentToSearchFor))
				&& (classId != FDO.LangProj.LangProject.kClassId))
			{
				hvo = m_cache.GetOwnerOfObject(hvo);
				classId = m_cache.GetClassOfObject(hvo) ;
			}
			if((!m_cache.IsSameOrSubclassOf(classId,classIdOfParentToSearchFor)))
				return -1;
			else
				return hvo;
		}
Beispiel #12
0
		/// <summary>
		/// In many cases we don't really need the FDO object, which can be relatively expensive
		/// to create. This version saves the information, and creates it when needed.
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="hvo"></param>
		/// <returns></returns>
		public static CmObjectUi MakeUi(FdoCache cache, int hvo)
		{
			return MakeUi(cache, hvo, (uint)cache.GetClassOfObject(hvo));
		}
Beispiel #13
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// This variant looks up the type, but never checks validity, and allows control of whether
		/// to load into cache.
		/// </summary>
		/// <param name="fcCache"></param>
		/// <param name="hvo"></param>
		/// <param name="bLoadIntoCache"></param>
		/// <returns></returns>
		/// ------------------------------------------------------------------------------------
		public static ICmObject CreateFromDBObject(FdoCache fcCache, int hvo, bool bLoadIntoCache)
		{
			return CreateFromDBObject(fcCache, hvo,
				GetTypeFromFWClassID(fcCache, fcCache.GetClassOfObject(hvo)),
				false, // don't validity check
				bLoadIntoCache);
		}
Beispiel #14
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Instantiate an object of the correct type, given the hvo.
		/// </summary>
		/// <remarks>
		/// Needed when the signature of the property is CmObject (and the actual class of the
		/// object is unknown).
		/// Notice that, even though the return signature of this method is CmObject, it
		/// will actually be returning an object of either CmObject or one of its subclasses.
		/// Note that in debug builds, this will include a validity check on the object.  If you want
		/// a validity check during a release build, use the version of this method which
		/// includes a parameter to control this explicitly.
		/// </remarks>
		/// <param name="fcCache"></param>
		/// <param name="hvo"></param>
		/// <returns></returns>
		/// ------------------------------------------------------------------------------------
		public static ICmObject CreateFromDBObject(FdoCache fcCache,int hvo)
		{
			Type cSharpType = GetTypeFromFWClassID(fcCache, fcCache.GetClassOfObject(hvo));

			// Now construct the object
			// If the object's class is already cached, assume all the FDO preload data is too.
			// Occasionally we will get a miss, where the class has been loaded some other way,
			// but we will auto-load the properties actually used in that case, and on the other
			// hand we save a huge amount of time not reloading objects we've already loaded.
			bool fLoadIntoCache =
				!fcCache.MainCacheAccessor.get_IsPropInCache(hvo, (int)CmObjectFields.kflidCmObject_Class,
				(int)CellarModuleDefns.kcptInteger, 0);

			return CreateFromDBObject(fcCache, hvo, cSharpType,
//#if DEBUG
//                true/*validity check*/,
//#else
				false,
//#endif
				fLoadIntoCache);
		}
Beispiel #15
0
		/// <summary>
		/// Uses CmObject base class to determine validity, since
		/// subclasses can override IsValidObject() to use different validation logic.
		/// </summary>
		/// <param name="cache"></param>
		/// <param name="hvo"></param>
		/// <returns></returns>
		static public bool IsValidObject(FdoCache cache, int hvo)
		{
			if (hvo == 0)
				return false;
			int clsid = cache.GetClassOfObject(hvo);
			if (clsid == 0)
				return false;
			ICmObject co = CmObject.CreateFromDBObject(cache, hvo, GetTypeFromFWClassID(cache, clsid), false, false);
			return co.IsValidObject();
		}
Beispiel #16
0
		static internal int InsertObjectIntoVirtualBackref(FdoCache cache, Mediator mediator, IVwVirtualHandler vh,
			int hvoSlice, uint clidNewObj, uint clidOwner, uint flid)
		{
			if (vh != null)
			{
				int clidSlice = cache.GetClassOfObject(hvoSlice);
				if (clidNewObj == LexEntry.kclsidLexEntry &&
					clidSlice == LexEntry.kclsidLexEntry &&
					clidOwner == LexDb.kclsidLexDb)
				{
					if (vh.FieldName == "VariantFormEntryBackRefs")
					{
						using (InsertVariantDlg dlg = new InsertVariantDlg())
						{
							ILexEntry entOld = LexEntry.CreateFromDBObject(cache, hvoSlice);
							dlg.SetHelpTopic("khtpInsertVariantDlg");
							dlg.SetDlgInfo(cache, mediator, entOld as IVariantComponentLexeme);
							if (dlg.ShowDialog() == DialogResult.OK && dlg.NewlyCreatedVariantEntryRefResult)
							{
								int insertPos = cache.GetVectorSize(hvoSlice, (int)flid);
								cache.PropChanged(hvoSlice, (int)flid, insertPos, 1, 0);
								return insertPos;
							}
							// say we've handled this.
							return -2;
						}
					}
				}
			}
			return -1;
		}
Beispiel #17
0
		/// <summary>
		/// If hvoWordform is the hvo of a capitalized wordform which has no useful information,
		/// delete it. It is considered useless if
		/// - it has no occurrences
		/// - it has no anlyses
		/// - it doesn't have known incorrect spelling status.
		/// Note that the argument may be some other kind of object (typically a WfiAnalysis or WfiGloss).
		/// If so do nothing.
		/// </summary>
		public static void DeleteRedundantCapitalizedWordform(FdoCache cache, int hvoWordform)
		{
			if (cache.GetClassOfObject(hvoWordform) != WfiWordform.kclsidWfiWordform)
				return;
			if (cache.GetVectorProperty(hvoWordform, OccurrencesFlid(cache), true).Length != 0)
				return;
			if (cache.IsValidObject(hvoWordform))
			{
				// If it's real it might have analyses etc.
				WfiWordform wf = (WfiWordform) CmObject.CreateFromDBObject(cache, hvoWordform);
				if (wf.AnalysesOC.Count > 0)
					return;
				// Arguably we should keep it for known correct spelling status. However, if it's ever been
				// confirmed as an analysis, even temporarily, it will have that.
				if (wf.SpellingStatus == (int)SpellingStatusStates.incorrect)
					return;
			}
			foreach (int ws in cache.LangProject.CurVernWssRS.HvoArray)
			{
				CaseFunctions cf = new CaseFunctions(cache.LanguageWritingSystemFactoryAccessor.get_EngineOrNull(ws).IcuLocale);
				string text = cache.GetMultiStringAlt(hvoWordform, (int) WfiWordformTags.kflidForm, ws).Text;
				if (!String.IsNullOrEmpty(text) && cf.StringCase(text) == StringCaseStatus.allLower)
					return;
			}
		   cache.DeleteObject(hvoWordform);
		}
Beispiel #18
0
		private static int GetWfiAnalysisFromWficInstanceOf(FdoCache cache, int hvoInstanceOf, out int hvoWordform)
		{
			hvoWordform = 0;
			int hvoWfiAnalysis = 0;
			int classid = cache.GetClassOfObject(hvoInstanceOf);
			switch (classid)
			{
				case WfiWordform.kclsidWfiWordform:
					hvoWordform = hvoInstanceOf;
					return 0;  // need use or make a guess for analysis
				case WfiAnalysis.kclsidWfiAnalysis:
					hvoWfiAnalysis = hvoInstanceOf;
					break;
				case WfiGloss.kclsidWfiGloss:
					hvoWfiAnalysis = cache.GetOwnerOfObject(hvoInstanceOf);
					break;
				default:
					throw new ArgumentException("cba.InstanceOf(" + hvoInstanceOf + ") class(" +
							   classid + ") is not WfiWordform, WfiAnalysis, or WfiGloss.");
			}
			return hvoWfiAnalysis;
		}
Beispiel #19
0
		// Is hvoAnn, currently analyzed as hvoAnalysis, fully analyzed?
		// This means:
		//  -- it isn't a default (property InterlinVc.m_vc.ktagTwficDefault isn't cached)
		//  -- It's a WfiGloss, with non-empty form.
		//  -- Owner is a WfiAnalysis with non-empty Category.
		//  -- Owner has at least one WfiMorphBundle.
		//  -- For each WfiMorphBundle, Form, Msa, and Sense are all filled in.
		// Alternatively, if hvoAnalysis is zero, the annotation is punctuation, which we don't analyze further;
		// so return true to indicate that it needs no further attention.
		internal bool FullyAnalyzed(FdoCache fdoCache, WsListManager listman, int hvoAnn, int hvoAnalysis)
		{
			int ktagTwficDefault = StTxtPara.TwficDefaultFlid(fdoCache);
			if (hvoAnalysis == 0)
				return true; // punctuation, treat as fully analyzed.
			ISilDataAccess sda = fdoCache.MainCacheAccessor;
			// Check for default. If the analysis we're showing is a default it needs at least confirmation.
			if (sda.get_IsPropInCache(hvoAnn, ktagTwficDefault, (int)CellarModuleDefns.kcptReferenceAtom, 0)
				&& sda.get_ObjectProp(hvoAnn, ktagTwficDefault) != 0)
				return false;

			int analysisClass = fdoCache.GetClassOfObject(hvoAnalysis);
			if (analysisClass != (int)WfiGloss.kclsidWfiGloss && analysisClass != (int)WfiAnalysis.kclsidWfiAnalysis)
				return false; // Has to BE an analysis...unless pathologically everything is off? Too bad if so...
			int hvoWfiAnalysis = fdoCache.GetOwnerOfObject(hvoAnalysis);
			int hvoWordform;
			if (analysisClass == (int)WfiAnalysis.kclsidWfiAnalysis)
			{
				hvoWordform = hvoWfiAnalysis;
				hvoWfiAnalysis = hvoAnalysis;
			}
			else
			{
				hvoWordform = fdoCache.GetOwnerOfObject(hvoWfiAnalysis);
			}

			foreach (InterlinLineSpec spec in m_vc.LineChoices)
			{
				// see if the information required for this linespec is present.
				switch (spec.Flid)
				{
					case InterlinLineChoices.kflidWord:
						int ws = m_vc.GetRealWs(hvoWordform, spec);
						if (sda.get_MultiStringAlt(hvoWordform, (int)WfiWordform.WfiWordformTags.kflidForm, ws).Length == 0)
							return false;
						break;
					case InterlinLineChoices.kflidLexEntries:
						if (!CheckPropSetForAllMorphs(sda, hvoWfiAnalysis, (int)WfiMorphBundle.WfiMorphBundleTags.kflidMorph))
							return false;
						break;
					case InterlinLineChoices.kflidMorphemes:
						if (!CheckPropSetForAllMorphs(sda, hvoWfiAnalysis, (int)WfiMorphBundle.WfiMorphBundleTags.kflidMorph))
							return false;
						break;
					case InterlinLineChoices.kflidLexGloss:
						if (!CheckPropSetForAllMorphs(sda, hvoWfiAnalysis, (int)WfiMorphBundle.WfiMorphBundleTags.kflidSense))
							return false;
						break;
					case InterlinLineChoices.kflidLexPos:
						if (!CheckPropSetForAllMorphs(sda, hvoWfiAnalysis, (int)WfiMorphBundle.WfiMorphBundleTags.kflidMsa))
							return false;
						break;
					case InterlinLineChoices.kflidWordGloss:
						// If it isn't a WfiGloss the user needs a chance to supply a word gloss.
						if (analysisClass != WfiGloss.kclsidWfiGloss)
							return false;
						// If it is empty for the (possibly magic) ws specified here, it needs filling in.
						int ws1 = m_vc.GetRealWs(hvoAnalysis, spec);
						if (sda.get_MultiStringAlt(hvoAnalysis, (int)WfiGloss.WfiGlossTags.kflidForm, ws1).Length == 0)
							return false;
						break;
					case InterlinLineChoices.kflidWordPos:
						if (sda.get_ObjectProp(hvoWfiAnalysis, (int)WfiAnalysis.WfiAnalysisTags.kflidCategory) == 0)
							return false;
						break;
					case InterlinLineChoices.kflidFreeTrans:
					case InterlinLineChoices.kflidLitTrans:
					case InterlinLineChoices.kflidNote:
					default:
						// unrecognized or non-word-level annotation, nothing required.
						break;
				}
			}

			return true; // If we can't find anything to complain about, it's fully analyzed.
		}
        const int ktagMinVp = 0x7f000000;         // copied from VwCacheDa.h, mimimum value for assigned virtual props.
        /// <summary>
        /// We implement this to record modify times.
        /// </summary>
        /// <param name="hvo"></param>
        /// <param name="tag"></param>
        /// <param name="ivMin"></param>
        /// <param name="cvIns"></param>
        /// <param name="cvDel"></param>
        public void PropChanged(int hvo, int tag, int ivMin, int cvIns, int cvDel)
        {
            CheckDisposed();
            if (m_fModifyChangeInProgress)             // ignore PropChanged on the DateModified property!
            {
                return;
            }
            // Typically an Undo will restore the modify time to what it was before the
            // main change. We don't want to reverse that by recording the time of the Undo!
            // Note that there is one pathological scenario:
            // t1: make a change.
            // t2: undo the change.
            // t3: export all changed records (since before t1).
            // t4: redo the change. Record appears to have been modified at time t2.
            // t5: export all changed records (since t3).
            // If this was the only change to the record, it is not part of either export,
            // and the change might be lost.
            // To prevent this, I think the 'export changed records' function should clear
            // the Undo stack.
            if (m_cache.ActionHandlerAccessor != null && m_cache.ActionHandlerAccessor.IsUndoOrRedoInProgress)
            {
                return;
            }
            if (tag < 0 || tag >= ktagMinVp)
            {
                return;                 // phony or virtual properties, not real changes (e.g., different filter applied, or selection moving in browse).
            }
            try
            {
                DateTime dtNow    = DateTime.Now;
                int      hvoMajor = 0;            // hvo of the 'major' object that has the DateModified property.
                if (SameMinute(dtNow, m_currentMinute))
                {
                    // We can use our Dictionary
                    if (m_recentMods.ContainsKey(hvo))
                    {
                        hvoMajor = m_recentMods[hvo];
                    }
                }
                else
                {
                    ResetDelay();
                }
                int flidModify = 0;
                if (hvoMajor == 0)
                {
                    for (int hvoCandidate = hvo; hvoCandidate != 0;
                         hvoCandidate = m_cache.GetOwnerOfObject(hvoCandidate))
                    {
                        // We assume that this is a dummy object at this point and GetClassOfObject
                        // only accepts real objects. Since it's a dummy object, changes should never
                        // affect the modify time of a real object. Maybe at some point we can get an
                        // interface method to check for dummy objects.
                        if (hvoCandidate < 0)
                        {
                            return;
                        }
                        int clid = m_cache.GetClassOfObject(hvoCandidate);
                        if (clid == 0)
                        {
                            return;                             // maybe a deleted object, no good to us, we can't record modify time.
                        }
                        flidModify = (int)m_mdc.GetFieldId2((uint)clid, "DateModified", true);
                        if (flidModify != 0)
                        {
                            hvoMajor = hvoCandidate;
                            break;
                        }
                    }
                    if (hvoMajor == 0)
                    {
                        return;                         // found no owner with DateCreated property.
                    }
                    m_recentMods[hvo] = hvoMajor;       // lets us find it fast if modified again soon.
                }
                else
                {
                    // We need to set flidModify!
                    int clid = m_cache.GetClassOfObject(hvoMajor);
                    if (clid != 0)
                    {
                        flidModify = (int)m_mdc.GetFieldId2((uint)clid, "DateModified", true);
                    }
                }
                if (flidModify == 0)
                {
                    return;                     // can't set the time prop without a field...
                }
                DateTime oldModifyTime = m_cache.GetTimeProperty(hvoMajor, flidModify);
                // If we already noted a modify time in the current minute, don't do it again.
                // This is intended to keep down the overhead of recording modify times for frequently
                // modified objects.
                if (SameMinute(oldModifyTime, dtNow))
                {
                    //Trace.TraceInformation("New Modify Time ({0}) for {1} is same minute as the old ({2}).\n",
                    //    dtNow, hvoMajor, oldModifyTime);
                    return;
                }
                //				if (m_currentMinute != null &&
                //					m_currentMinute.Date == dtNow.Date && m_currentMinute.Hour = dtNow.Hour && m_currentMinute.Minute == dtNow.Minute)
                //					return;

                // Set the modify time. If possible tack this on to the last Undo task (or the current one, if a
                // transaction is open).
                if (m_cache.ActionHandlerAccessor != null && m_cache.VwOleDbDaAccessor != null &&
                    ((m_cache.DatabaseAccessor != null && m_cache.DatabaseAccessor.IsTransactionOpen()) ||
                     m_cache.CanUndo))
                {
                    m_cache.ContinueUndoTask();
                    m_cache.SetTimeProperty(hvoMajor, flidModify, dtNow);
                    m_cache.EndUndoTask();
                }
                else
                {
                    // We don't have an Undo task to append to, so somehow a Save has occurred
                    // in the midst of the operation that caused the time stamp modification.
                    // If we make an empty undo task, the user will typically have no idea what
                    // could be undone, and will be confused. Best to make it impossible to
                    // undo the timestamp change also.
                    using (new SuppressSubTasks(m_cache))
                    {
                        m_cache.SetTimeProperty(hvoMajor, flidModify, dtNow);
                    }
                }
                //Trace.TraceInformation("Setting new Modify Time ({0}) for {1}\n",
                //        dtNow, hvoMajor);
            }
            finally
            {
                m_fModifyChangeInProgress = false;
            }
        }
Beispiel #21
0
		/// <summary>
		/// Return the hvo for theCmBaseAnnotation that
		/// matches the given boundaries in an StTxtPara object.
		/// If no exact match is found, return the nearest segment (preferably the following word).
		/// </summary>
		/// <param name="hvoStTxtPara"></param>
		/// <param name="ichMin"></param>
		/// <param name="ichLim"></param>
		/// <param name="fOnlyTWFIC">true, if restricted to TWFIC</param>
		/// <param name="fExactMatch"> true if we return an exact match, false otherwise.</param>
		/// <returns>hvo is 0 if not found.</returns>
		static internal int FindAnnotationHvoForStTxtPara(FdoCache cache, int hvoStTxtPara, int ichMin, int ichLim, bool fOnlyTWFIC, out bool fExactMatch)
		{
			int twficType = CmAnnotationDefn.Twfic(cache).Hvo;
			int textSegType = CmAnnotationDefn.TextSegment(cache).Hvo;
			fExactMatch = false;
			int clsid = cache.GetClassOfObject(hvoStTxtPara);
			if (clsid != StTxtPara.kClassId)
			{
				Debug.Assert(clsid != StTxtPara.kClassId, "hvoStTxtPara should be of class StTxtPara.");
				return 0;
			}
			int kflidParaSegment = InterlinVc.ParaSegmentTag(cache);
			ISilDataAccess sda = cache.MainCacheAccessor;
			// first find the closest segment.
			int[] segments = cache.GetVectorProperty(hvoStTxtPara, kflidParaSegment, true);
			ICmBaseAnnotation cbaClosestSeg = FindClosestAnnotation(cache, segments, textSegType, ichMin, ichLim, out fExactMatch);
			if (cbaClosestSeg == null)
				return 0;
			// if it was an exact match for a segment, return it.
			if (cbaClosestSeg != null && fExactMatch && !fOnlyTWFIC)
				return cbaClosestSeg.Hvo;
			// otherwise, see if we can find a closer wordform
			int[] segmentForms = cache.GetVectorProperty(cbaClosestSeg.Hvo, InterlinVc.SegmentFormsTag(cache), true);
			ICmBaseAnnotation cbaClosestWf = FindClosestAnnotation(cache, segmentForms, twficType, ichMin, ichLim, out fExactMatch);
			if (cbaClosestWf == null)
			{
				return fOnlyTWFIC ? 0 : cbaClosestSeg.Hvo;
			}
			return cbaClosestWf.Hvo;
		}