/// <summary> /// Change the affix to a stem (possibly) /// </summary> /// <param name="entry"></param> /// <param name="selectedHvo"></param> /// <param name="sUndo"></param> /// <param name="sRedo"></param> /// <returns>true if change made; false otherwise</returns> private bool ChangeAffixToStem(ILexEntry entry, int selectedHvo, string sUndo, string sRedo) { IMoAffixForm affix = m_obj as IMoAffixForm; if (affix == null) { throw new ApplicationException("Affix form is not defined"); } List <IMoMorphSynAnalysis> rgmsaOld = new List <IMoMorphSynAnalysis>(); if (m_obj.OwningFlid == (int)LexEntry.LexEntryTags.kflidLexemeForm) { foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC) { if (!(msa is IMoStemMsa)) { rgmsaOld.Add(msa); } } } if (CheckForAffixDataLoss(affix, rgmsaOld)) { return(false); } FdoCache cache = m_cache; cache.BeginUndoTask(sUndo, sRedo); IMoStemAllomorph stem = new MoStemAllomorph(); SwapValues(entry, affix, stem, selectedHvo, rgmsaOld); // may cause slice/button to be disposed... cache.EndUndoTask(); return(true); }
private bool ChangeStemToAffix(ILexEntry entry, int selectedHvo, string sUndo, string sRedo) { IMoStemAllomorph stem = m_obj as IMoStemAllomorph; if (stem == null) { throw new ApplicationException("Stem allomorph is not defined"); } List <IMoMorphSynAnalysis> rgmsaOld = new List <IMoMorphSynAnalysis>(); if (m_obj.OwningFlid == (int)LexEntry.LexEntryTags.kflidLexemeForm) { foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC) { if (msa is IMoStemMsa) { rgmsaOld.Add(msa); } } } if (CheckForStemDataLoss(stem, rgmsaOld)) { return(false); } FdoCache cache = m_cache; cache.BeginUndoTask(sUndo, sRedo); IMoAffixAllomorph affix = new MoAffixAllomorph(); SwapValues(entry, stem, affix, selectedHvo, rgmsaOld); cache.EndUndoTask(); return(true); }
/// <summary> /// Handle launching of the MSA editor. /// </summary> protected override void HandleChooser() { using (MsaCreatorDlg dlg = new MsaCreatorDlg()) { MoMorphSynAnalysis originalMsa = m_obj as MoMorphSynAnalysis; ILexEntry entry = LexEntry.CreateFromDBObject(m_cache, originalMsa.OwnerHVO); dlg.SetDlgInfo(m_cache, m_persistProvider, m_mediator, entry, DummyGenericMSA.Create(originalMsa), originalMsa.Hvo, true, String.Format(LexEdStrings.ksEditX, Slice.Label)); if (dlg.ShowDialog(FindForm()) == DialogResult.OK) { DummyGenericMSA dummyMsa = dlg.DummyMSA; if (!originalMsa.EqualsMsa(dummyMsa)) { m_cache.BeginUndoTask(LexEdStrings.ksUndoEditFunction, LexEdStrings.ksRedoEditFunction); // The UpdateOrReplace call may end up disposing this. So any variables we // need after it must be copied to the stack. FdoCache cache = m_cache; Slice parent = Slice; IMoMorphSynAnalysis newMsa = originalMsa.UpdateOrReplace(dummyMsa); cache.EndUndoTask(); } } } }
public bool OnMoveReversalPOS(object cmd) { FdoCache cache = Cache; ObjectLabelCollection labels = new ObjectLabelCollection(); foreach (IPartOfSpeech pos in MergeOrMoveCandidates) { labels.Add(ObjectLabel.CreateObjectLabelOnly(cache, pos.Hvo, "ShortNameTSS", "best analysis")); } using (SimpleListChooser dlg = new SimpleListChooser(cache, null, labels, 0, LexEdStrings.ksCategoryToMoveTo, null)) { if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { IPartOfSpeech currentPOS = POS; IPartOfSpeech newOwner = PartOfSpeech.CreateFromDBObject(cache, dlg.ChosenOne.Hvo); cache.BeginUndoTask(LexEdStrings.ksUndoMoveRevCategory, LexEdStrings.ksRedoMoveRevCategory); ICmObject newOwningObj = newOwner.MoveIfNeeded(currentPOS); newOwner.SubPossibilitiesOS.Append(currentPOS); cache.EndUndoTask(); // Note: PropChanged should happen on the old owner and the new in the 'Add" method call. // Have to jump to a main PartOfSpeech, as RecordClerk doesn't know anything about subcategories. m_mediator.BroadcastMessageUntilHandled("JumpToRecord", newOwner.MainPossibility.Hvo); } } return(true); }
private bool RunMergeEntryDialog(object argument, bool fLoseNoTextData) { ICmObject obj = m_mediator.PropertyTable.GetValue("ActiveClerkSelectedObject") as ICmObject; Debug.Assert(obj != null); if (obj == null) { return(false); // should never happen, but nothing we can do if it does! } FdoCache cache = (FdoCache)m_mediator.PropertyTable.GetValue("cache"); Debug.Assert(cache != null); Debug.Assert(cache == obj.Cache); ILexEntry currentEntry = obj as ILexEntry; if (currentEntry == null) { int hvoEntry = cache.GetOwnerOfObjectOfClass(obj.Hvo, LexEntry.kclsidLexEntry); if (hvoEntry != 0) { currentEntry = LexEntry.CreateFromDBObject(cache, hvoEntry); } } Debug.Assert(currentEntry != null); if (currentEntry == null) { return(false); } using (MergeEntryDlg dlg = new MergeEntryDlg()) { Debug.Assert(argument != null && argument is XCore.Command); dlg.SetDlgInfo(cache, m_mediator, currentEntry); if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { int entryID = dlg.SelectedID; ILexEntry survivor = LexEntry.CreateFromDBObject(cache, entryID); Debug.Assert(survivor != currentEntry); cache.BeginUndoTask(SIL.FieldWorks.LexText.Controls.LexTextControls.ksUndoMergeEntry, SIL.FieldWorks.LexText.Controls.LexTextControls.ksRedoMergeEntry); // If lexeme forms differ, make the source lexeme form an allomorph of the target entry. if (survivor.LexemeFormOA.Form.VernacularDefaultWritingSystem != currentEntry.LexemeFormOA.Form.VernacularDefaultWritingSystem) { survivor.AlternateFormsOS.Append(currentEntry.LexemeFormOA.Hvo); } survivor.MergeObject(currentEntry, fLoseNoTextData); cache.EndUndoTask(); survivor.DateModified = DateTime.Now; MessageBox.Show(null, SIL.FieldWorks.LexText.Controls.LexTextControls.ksEntriesHaveBeenMerged, SIL.FieldWorks.LexText.Controls.LexTextControls.ksMergeReport, MessageBoxButtons.OK, MessageBoxIcon.Information); m_mediator.SendMessage("JumpToRecord", entryID); } } return(true); }
/// <summary> /// Add the specified type of freeform annotation to the given segment. /// Undoable by default. /// </summary> /// <param name="hvoSeg"></param> /// <param name="hvoType">freeform annotation type</param> /// <returns></returns> public ICmIndirectAnnotation AddFreeformAnnotation(int hvoSeg, int hvoType) { using (SuppressSubTasks suppressor = new SuppressSubTasks(m_fdoCache, true)) { // convert any preceeding dummy segments, so paragraph parser does not push this to the first dummy sentence. (LT-7318) int hvoPara = m_fdoCache.GetObjProperty(hvoSeg, (int)CmBaseAnnotation.CmBaseAnnotationTags.kflidBeginObject); StTxtPara para = StTxtPara.CreateFromDBObject(m_fdoCache, hvoPara) as StTxtPara; para.EnsurePreceedingSegmentsAreReal(hvoSeg); string undoString = ""; string redoString = ""; if (hvoType == ktagSegFF_freeTranslation) { undoString = ITextStrings.ksUndoAddFreeformTranslation; redoString = ITextStrings.ksRedoAddFreeformTranslation; } else if (hvoType == ktagSegFF_literalTranslation) { undoString = ITextStrings.ksUndoAddLiteralTranslation; redoString = ITextStrings.ksRedoAddLiteralTranslation; } else if (hvoType == ktagSegFF_note) { undoString = ITextStrings.ksUndoAddNote; redoString = ITextStrings.ksRedoAddNote; } else { throw new ArgumentException(String.Format("segment freeform type {0} is not yet supported here.", hvoType)); } ICmIndirectAnnotation ann; m_fdoCache.BeginUndoTask(undoString, redoString); { ann = CmIndirectAnnotation.CreateUnownedIndirectAnnotation(m_fdoCache); ann.AppliesToRS.Append(hvoSeg); ann.AnnotationTypeRAHvo = hvoType; // Add it to the cached collection of freeform annotations. This is a bit clumsy because // it isn't a real property so we can't just use the normal methods for modifying a property. // Enhance JohnT: put it with the other ones of the same type. ISilDataAccess sda = m_fdoCache.MainCacheAccessor; IVwCacheDa cda = (IVwCacheDa)sda; int cFreeForm = sda.get_VecSize(hvoSeg, ktagSegFF); int[] freeForms = new int[cFreeForm + 1]; for (int i = 0; i < cFreeForm; i++) { freeForms[i] = sda.get_VecItem(hvoSeg, ktagSegFF, i); } freeForms[cFreeForm] = ann.Hvo; cda.CacheVecProp(hvoSeg, ktagSegFF, freeForms, cFreeForm + 1); sda.PropChanged(null, (int)PropChangeType.kpctNotifyAll, hvoSeg, ktagSegFF, cFreeForm, 1, 0); } m_fdoCache.EndUndoTask(); return(ann); } }
public void HandleDeleteMenuItem(Object src, System.EventArgs ea) { m_cache.BeginUndoTask(DetailControlsStrings.ksUndoDelete, DetailControlsStrings.ksRedoDelete); using (CmObjectUi ui = CmObjectUi.MakeUi(m_cache, m_hvoDeleteTarget)) { ui.Mediator = m_sliceTreeNode.Slice.ContainingDataTree.Mediator; ui.DeleteUnderlyingObject(); } m_cache.EndUndoTask(); }
public override void AddToDatabase(FdoCache cache) { CheckDisposed(); if (m_fInDatabase) { return; // It's already in the database, so nothing more can be done. } cache.BeginUndoTask(MGAStrings.ksUndoCreateInflectionFeature, MGAStrings.ksRedoCreateInflectionFeature); m_featDefn = FsFeatureSystem.AddFeatureAsXml(cache, m_node); cache.EndUndoTask(); }
protected virtual void ReallyDeleteReversalIndex(IReversalIndex ri) { try { Debug.Assert(ri.Hvo == m_list.OwningObject.Hvo); m_list.ListModificationInProgress = true; // can't reload deleted list! (LT-5353) // Clear out any virtual data stored in the cache for this reversal index. IVwCacheDa cda = m_cache.MainCacheAccessor as IVwCacheDa; IVwVirtualHandler vh = cda.GetVirtualHandlerName("LexSense", LexSenseReversalEntriesTextHandler.StandardFieldName); if (vh != null) { int wsDel = ri.WritingSystemRAHvo; IEnumerator <IReversalIndexEntry> erie = ri.EntriesOC.GetEnumerator(); while (erie.MoveNext()) { foreach (LinkedObjectInfo loi in erie.Current.BackReferences) { if (loi.RelObjClass == (int)LexSense.kClassId) { vh.Load(loi.RelObjId, vh.Tag, wsDel, cda); } } } } m_cache.BeginUndoTask(LexEdStrings.ksUndoDelete, LexEdStrings.ksRedoDelete); int cobjOld = m_cache.LangProject.LexDbOA.ReversalIndexesOC.Count; ri.DeleteUnderlyingObject(); int cobjNew; int hvoIdxNew = ReversalIndexAfterDeletion(m_cache, out cobjNew); m_cache.EndUndoTask(); SetReversalIndexHvo(hvoIdxNew); // Without this, switching to the ReversalEntries tool can crash if it was // displaying data from the deleted reversal entry. m_cache.PropChanged(null, PropChangeType.kpctNotifyAll, m_cache.LangProject.LexDbOAHvo, (int)LexDb.LexDbTags.kflidReversalIndexes, 0, cobjNew, cobjOld); } finally { m_list.ListModificationInProgress = false; } // Can't do this until ListModificationInProgress flag is cleared because it // redisplays everything after reloading the list: if the list isn't actually // reloaded, it tries to display a deleted object -- CRASH! ChangeOwningObjectIfPossible(); // Without this, stale data can still display in the BulkEditSenses tool if you // recreate the deleted reversal index. m_mediator.SendMessage("MasterRefresh", null); }
private void AddNewSenseDlg_Closing(object sender, System.ComponentModel.CancelEventArgs e) { switch (DialogResult) { default: { Debug.Assert(false, "Unexpected DialogResult."); break; } case DialogResult.Cancel: { break; } case DialogResult.OK: { if (m_fwtbGloss.Text == String.Empty) { e.Cancel = true; MessageBox.Show(this, LexTextControls.ksFillInGloss, LexTextControls.ksMissingInformation, MessageBoxButtons.OK, MessageBoxIcon.Information); return; } Cursor = Cursors.WaitCursor; m_cache.BeginUndoTask(LexTextControls.ksUndoCreateNewSense, LexTextControls.ksRedoCreateNewSense); ILexSense lsNew = m_le.SensesOS.Append(new LexSense()); lsNew.Gloss.AnalysisDefaultWritingSystem = m_fwtbGloss.Text; (lsNew as LexSense).DummyMSA = m_msaGroupBox.DummyMSA; m_newSenseID = lsNew.Hvo; m_cache.EndUndoTask(); Cursor = Cursors.Default; break; } } }
public bool OnMoveReversalindexEntry(object cmd) { using (ReversalEntryGoDlg dlg = new ReversalEntryGoDlg()) { Slice slice = m_dataEntryForm.CurrentSlice; Debug.Assert(slice != null, "No slice was current"); IReversalIndexEntry currentEntry = (IReversalIndexEntry)slice.Object; List <IReversalIndexEntry> filteredEntries = new List <IReversalIndexEntry>(); filteredEntries.Add(currentEntry); IReversalIndexEntry owningEntry = currentEntry.OwningEntry; if (owningEntry != null) { filteredEntries.Add(owningEntry); } WindowParams wp = new WindowParams(); wp.m_btnText = LexEdStrings.ks_MoveEntry; wp.m_label = LexEdStrings.ks_Find_; wp.m_title = LexEdStrings.ksMoveRevEntry; dlg.SetDlgInfo(m_mediator, wp, filteredEntries); // , true if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { FdoCache cache = (FdoCache)m_mediator.PropertyTable.GetValue("cache"); IReversalIndexEntry newOwner = ReversalIndexEntry.CreateFromDBObject(cache, dlg.SelectedID); cache.BeginUndoTask(LexEdStrings.ksUndoMoveRevEntry, LexEdStrings.ksRedoMoveRevEntry); ICmObject newOwningObj = newOwner.MoveIfNeeded(currentEntry); newOwner.SubentriesOC.Add(currentEntry); cache.EndUndoTask(); RecordClerk clerk = m_mediator.PropertyTable.GetValue("ActiveClerk") as RecordClerk; if (clerk != null) { clerk.RemoveItemsFor(currentEntry.Hvo); } // Note: PropChanged should happen on the old owner and the new in the 'Add" method call. // Have to jump to a main entry, as RecordClerk doesn't know anything about subentries. m_mediator.BroadcastMessageUntilHandled("JumpToRecord", newOwner.MainEntry.Hvo); } } return(true); }
private void DoImport() { _cache.BeginUndoTask(LiftImportStrings.ksUndoLIFTImport, LiftImportStrings.ksRedoLIFTImport); try { FlexLiftMerger flexImporter = new FlexLiftMerger(_cache); this.Cursor = Cursors.WaitCursor; // flexImporter.ImportLiftFile(openFileDialog1.FileName); } //catch (Exception error) //{ // //TODO: shouldn't there be a method on the cache to cancel the undo task? // MessageBox.Show("Something went wrong while FieldWorks was attempting to import."); // //TODO: is it may be better to just let it die of the normal green box death? //} finally { _cache.EndUndoTask(); } }
public override void AddToDatabase(FdoCache cache) { CheckDisposed(); if (m_fInDatabase) { return; // It's already in the database, so nothing more can be done. } string sType = XmlUtils.GetManditoryAttributeValue(m_node, "type"); if (sType == "feature") { cache.BeginUndoTask(MGAStrings.ksUndoCreatePhonologicalFeature, MGAStrings.ksRedoCreatePhonologicalFeature); ILangProject lp = cache.LangProject; IFsFeatureSystem featsys = lp.PhFeatureSystemOA as IFsFeatureSystem; // Since phonological features in the chooser only have features and no values, // we need to create the positive and negative value nodes string sName = XmlUtils.GetManditoryAttributeValue(m_node, "id"); const string sTemplate = "<item id='v{0}Positive' type='value'><abbrev ws='en'>+</abbrev><term ws='en'>positive</term>" + "<fs id='v{0}PositiveFS' type='Phon'><f name='{0}'><sym value='+'/></f></fs></item>" + "<item id='v{0}Negative' type='value'><abbrev ws='en'>-</abbrev><term ws='en'>negative</term>" + "<fs id='v{0}NegativeFS' type='Phon'><f name='{0}'><sym value='-'/></f></fs></item>"; StringBuilder sb = new StringBuilder(); sb.AppendFormat(sTemplate, sName.Substring(1)); m_node.InnerXml += sb.ToString(); // have to use a ndw document or, for some odd reason, it keeps on using an old value and not the new one... XmlDocument doc = new XmlDocument(); doc.LoadXml(m_node.OuterXml); // add positive value; note that the FsFeatDefn will be the same for both XmlNode valueNode = doc.SelectSingleNode("//item[contains(@id,'Positive')]"); m_featDefn = FsFeatureSystem.AddFeatureAsXml(cache, featsys, valueNode); // add negative value valueNode = doc.SelectSingleNode("//item[contains(@id,'Negative')]"); m_featDefn = FsFeatureSystem.AddFeatureAsXml(cache, featsys, valueNode); cache.EndUndoTask(); } }
public void AddToDatabase(FdoCache cache, ICmPossibilityList posList, MasterCategory parent, IPartOfSpeech subItemOwner) { CheckDisposed(); if (m_pos != null) { return; // It's already in the database, so nothing more can be done. } cache.BeginUndoTask(LexTextControls.ksUndoCreateCategory, LexTextControls.ksRedoCreateCategory); int newOwningFlid; int insertLocation; int newOwner = DeterminePOSLocationInfo(subItemOwner, parent, posList, out newOwningFlid, out insertLocation); ILgWritingSystemFactory wsf = cache.LanguageWritingSystemFactoryAccessor; Debug.Assert(m_pos != null); if (m_node == null) { // should not happen, but just in case... we still get something useful m_pos.Name.SetAlternative(m_term, wsf.GetWsFromStr(m_termWs)); m_pos.Abbreviation.SetAlternative(m_abbrev, wsf.GetWsFromStr(m_abbrevWs)); m_pos.Description.SetAlternative(m_def, wsf.GetWsFromStr(m_defWs)); } else { SetContentFromNode(cache, "abbrev", false, m_pos.Abbreviation); SetContentFromNode(cache, "term", true, m_pos.Name); SetContentFromNode(cache, "def", false, m_pos.Description); } m_pos.CatalogSourceId = m_id; // Need a PropChanged, since it isn't done in the 'Append' for some reason. cache.PropChanged(null, PropChangeType.kpctNotifyAll, newOwner, newOwningFlid, insertLocation, 1, 0); cache.EndUndoTask(); }
/// <summary> /// Execute the change requested by the current selection in the combo. /// Basically we want the MoInflClass indicated by m_selectedHvo, (even if 0?? not yet possible), /// to become the InflectionClass of each record that is appropriate to change. /// We do nothing to records where the check box is turned off, /// and nothing to ones that currently have an MSA other than an MoStemMsa, /// and nothing to ones that currently have an MSA with the wrong POS. /// (a) If the owning entry has an MoStemMsa with the right inflection class (and presumably POS), /// set the sense to use it. /// (b) If all senses using the current MoStemMsa are to be changed, just update /// the inflection class of that MoStemMsa. /// We could add this...but very probably unused MSAs would have been taken over /// when setting the POS. /// --(c) If the entry has an MoStemMsa which is not being used at all, change it to /// --the required POS and inflection class and use it. /// (d) Make a new MoStemMsa in the LexEntry with the required POS and inflection class /// and point the sense at it. /// </summary> public void DoIt(Set <int> itemsToChange, ProgressState state) { CheckDisposed(); int hvoPos = GetPOS(); // A Set of eligible parts of speech to use in filtering. Set <int> possiblePOS = GetPossiblePartsOfSpeech(); // Make a Dictionary from HVO of entry to list of modified senses. Dictionary <int, List <ILexSense> > sensesByEntry = new Dictionary <int, List <ILexSense> >(); int tagOwningEntry = m_cache.VwCacheDaAccessor.GetVirtualHandlerName("LexSense", "OwningEntry").Tag; int i = 0; // Report progress 50 times or every 100 items, whichever is more (but no more than once per item!) int interval = Math.Min(100, Math.Max(itemsToChange.Count / 50, 1)); foreach (int hvoSense in itemsToChange) { i++; if (i % interval == 0) { state.PercentDone = i * 20 / itemsToChange.Count; state.Breath(); } if (!IsItemEligible(m_cache.MainCacheAccessor, hvoSense, possiblePOS)) { continue; } ILexSense ls = (ILexSense)CmObject.CreateFromDBObject(m_cache, hvoSense, false); IMoMorphSynAnalysis msa = ls.MorphoSyntaxAnalysisRA; int hvoEntry = m_cache.MainCacheAccessor.get_ObjectProp(ls.Hvo, tagOwningEntry); if (!sensesByEntry.ContainsKey(hvoEntry)) { sensesByEntry[hvoEntry] = new List <ILexSense>(); } sensesByEntry[hvoEntry].Add(ls); } m_cache.BeginUndoTask(FdoUiStrings.ksUndoBEInflClass, FdoUiStrings.ksRedoBEInflClass); BulkEditBar.ForceRefreshOnUndoRedo(m_cache.MainCacheAccessor); i = 0; interval = Math.Min(100, Math.Max(sensesByEntry.Count / 50, 1)); foreach (KeyValuePair <int, List <ILexSense> > kvp in sensesByEntry) { i++; if (i % interval == 0) { state.PercentDone = i * 80 / sensesByEntry.Count + 20; state.Breath(); } ILexEntry entry = (ILexEntry)CmObject.CreateFromDBObject(m_cache, kvp.Key, false); List <ILexSense> sensesToChange = kvp.Value; IMoStemMsa msmTarget = null; foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC) { IMoStemMsa msm = msa as IMoStemMsa; if (msm != null && msm.InflectionClassRAHvo == m_selectedHvo) { // Can reuse this one! msmTarget = msm; break; } } if (msmTarget == null) { // See if we can reuse an existing MoStemMsa by changing it. // This is possible if it is used only by senses in the list, or not used at all. List <ILexSense> otherSenses = new List <ILexSense>(); if (entry.SensesOS.Count != sensesToChange.Count) { foreach (ILexSense ls in entry.SensesOS) { if (!sensesToChange.Contains(ls)) { otherSenses.Add(ls); } } } foreach (IMoMorphSynAnalysis msa in entry.MorphoSyntaxAnalysesOC) { IMoStemMsa msm = msa as IMoStemMsa; if (msm == null) { continue; } bool fOk = true; foreach (ILexSense ls in otherSenses) { if (ls.MorphoSyntaxAnalysisRA == msm) { fOk = false; break; } } if (fOk) { // Can reuse this one! Nothing we don't want to change uses it. // Adjust its POS as well as its inflection class, just to be sure. msmTarget = msm; msmTarget.PartOfSpeechRAHvo = hvoPos; msmTarget.InflectionClassRAHvo = m_selectedHvo; break; } } } if (msmTarget == null) { // Nothing we can reuse...make a new one. msmTarget = new MoStemMsa(); entry.MorphoSyntaxAnalysesOC.Add(msmTarget); msmTarget.PartOfSpeechRAHvo = hvoPos; msmTarget.InflectionClassRAHvo = m_selectedHvo; } // Finally! Make the senses we want to change use it. foreach (ILexSense ls in sensesToChange) { ls.MorphoSyntaxAnalysisRA = msmTarget; } } m_cache.EndUndoTask(); }