public: void move(std::shared_ptr<Model_Rule> rule, Controller_Helper_RuleMover_AbstractStrategy::Direction direction)
	{
		auto proxy = this->grublistCfg->proxies.getProxyByRule(rule);
		auto& ruleList = proxy->getRuleList(proxy->getParentRule(rule));

		auto visibleRules = this->findVisibleRules(ruleList, rule);

		auto nextRule = this->getNextRule(visibleRules, rule, direction);
		if (nextRule == nullptr) {
			throw Controller_Helper_RuleMover_MoveFailedException("no next rule found", __FILE__, __LINE__);
		}

		this->removeFromList(ruleList, rule);
		this->insertBehind(ruleList, rule, nextRule, direction);
	}
BOOL CSentransModel::loadFromFile(LPCTSTR lpszPathName,
								  CWCommonModel& commonModel,
								  BOOL bLogIfMissing)
{
	ASSERTX(lpszPathName);
	SFMFile f(lpszPathName, commonModel.m_cCommentChar);

	if(!f.ensureOpen("Sentrans File", bLogIfMissing))
		return FALSE;

	char cCommentChar = commonModel.m_cCommentChar;
#ifndef hab17a1
	CCommentOrTestDataCollector coOrTdCollector;
	BOOL bSeenSenTransField = FALSE; // 1.7a1 need to ignore comments from non-Sentrans specific items; using this flag to do so
#else // hab17a1
	CCommentCollector commentCollector;	// jdh 11/9/99
#endif //hab17a1

#ifndef hab211
	CWList * pLastList = 0;
#endif //hab211

	CString sMarker, sField;
	BOOL bEnabled;
	BOOL bIsDisambig = this->IsKindOf(RUNTIME_CLASS(CSentransDisambigModel));
try
	{
		while(f.getField(sMarker, sField, &bEnabled))
		{
			try
			{
				if(sMarker == "ru")
				{
					if(!bIsDisambig)
					{
#ifndef hab17a1
						coOrTdCollector.disgorge(((CSentransTransferModel*)this)->m_rules);
#else // hab17a1
						commentCollector.disgorge(((CSentransTransferModel*)this)->m_rules); // jdh 11/9/99
#endif // hab17a1
						CSentransTransferRule *r = new CSentransTransferRule(sField, bEnabled, cCommentChar);
						((CSentransTransferModel*)this)->m_rules.addItem(r);
#ifndef hab17a1
						bSeenSenTransField = TRUE;
#endif // hab17a1
					}
					else
					{
						CString s("SENTRANS-Disambig files can't have transfer rules.");
						f.logSkip("SENTRANS-Disambig", sMarker, sField, s);
					}
				}
#ifndef hab17a1
				else if(sMarker == "co" || sMarker == "cm")
#else // hab17a1
				else if(sMarker == "co")
#endif // hab17a1
				{
				 /*
				 // JDH 5/25/99 3:28:36 PM Added List Comment Capbility (\co)
					CListEntryComment *com = new CListEntryComment(sField);
					if(bIsDisambig)
						((CSentransDisambigModel*)this)->m_rules.addItem(com);
					else
						((CSentransTransferModel*)this)->m_rules.addItem(com);
					*/

				// jdh 11/9/99 changed to use the commentCollector because now have two lists (rules and \cl list)
#ifndef hab17a1
					coOrTdCollector.add(sField, "co");
#else // hab17a1
					commentCollector.add(sField);
#endif // hab17a1
				 }
				else if(sMarker == "am" || sMarker == "rej" || sMarker == "reject"
						|| sMarker == "amun" || sMarker == "rejun")
				{
					bool bAccept = (sMarker == "am" || sMarker == "amun" );
					bool bUnanimousEnvirons = (sMarker == "amun" || sMarker == "rejun");
					if(bIsDisambig)
					{
#ifndef hab17a1
						coOrTdCollector.disgorge(((CSentransDisambigModel*)this)->m_rules);
#else // hab17a1
						commentCollector.disgorge(((CSentransDisambigModel*)this)->m_rules);
#endif // hab17a1
						CSentransDisambigRule *r = new CSentransDisambigRule(sField, bAccept, bEnabled, bUnanimousEnvirons, cCommentChar);
						((CSentransDisambigModel*)this)->m_rules.addItem(r);
#ifndef hab17a1
						bSeenSenTransField = TRUE;
#endif // hab17a1
					}
					else
					{
						CString s("SENTRANS-Transfer files can't have disambiguation rules.");
						f.logSkip("SENTRANS-Transfer", sMarker, sField, s);
						//MessageBox( NULL, s, "Parsing Error", MB_OK);
					}
				}

				// various SentransDirectiveTypes

				// jdh 11/9/99 todo: add commentCollector.disgorge() in each of these
				else if(sMarker == "...")
				{
#ifndef hab17a1
					coOrTdCollector.disgorge(((CSentransDisambigModel*)this)->m_rules);
					bSeenSenTransField = TRUE;
#endif // hab17a1
					addRule( new CSentransDirective(CSentransDirective::kLimit, sField, bEnabled, cCommentChar));
				}
				else if(sMarker == "ruleset")
				{
#ifndef hab17a1
					coOrTdCollector.disgorge(((CSentransDisambigModel*)this)->m_rules);
					bSeenSenTransField = TRUE;
#endif // hab17a1
					addRule( new CSentransDirective(CSentransDirective::kBeginRuleSet, sField, bEnabled, cCommentChar));
				}
				else if(sMarker == "endruleset")
				{
#ifndef hab17a1
					coOrTdCollector.disgorge(((CSentransDisambigModel*)this)->m_rules);
					bSeenSenTransField = TRUE;
#endif // hab17a1
					addRule( new CSentransDirective(CSentransDirective::kEndRuleSet, sField, bEnabled, cCommentChar));
				}
				else if(sMarker == "ruleson")
				{
#ifndef hab17a1
					coOrTdCollector.disgorge(((CSentransDisambigModel*)this)->m_rules);
					bSeenSenTransField = TRUE;
#endif // hab17a1
					addRule( new CSentransDirective(CSentransDirective::kRulesOn, sField, bEnabled, cCommentChar));
				}
				else if(sMarker == "rulesoff")
				{
#ifndef hab17a1
					coOrTdCollector.disgorge(((CSentransDisambigModel*)this)->m_rules);
					bSeenSenTransField = TRUE;
#endif // hab17a1
					addRule( new CSentransDirective(CSentransDirective::kRulesOff, sField, bEnabled, cCommentChar));
				}

				// jdh 11/9/99 add \cl field
				else if(sMarker == "cl")
				{
#ifndef hab17a1
#ifndef hab264
					coOrTdCollector.disgorge(m_genericClasses);
#else
					coOrTdCollector.disgorge(commonModel.morphemeClasses);
#endif // hab264
#else // hab17a1
					commentCollector.disgorge(commonModel.morphemeClasses);
					bSeenSenTransField = TRUE;
#endif // hab17a1
					CWClass *c = new CWClass(sField, bEnabled, commonModel.m_cCommentChar);
					m_genericClasses.addItem(c);
				}

				// jdh 5/29/01 add \pat field
				else if(sMarker == "pat")
				{
#ifndef hab264
					coOrTdCollector.disgorge(m_patterns);
#else
					coOrTdCollector.disgorge(commonModel.morphemeClasses);	// why these, why here?  I just copied from the generic_class code above.
#endif // hab264
					CWClass *c = new CWClass(sField, bEnabled, commonModel.m_cCommentChar);
					m_patterns.addItem(c);
				}

				// punctuation fields
				else if(sMarker == "sentpunc")
				{
					m_sSentencePunctuation.setData(sField);
				}

				else if(sMarker == "punc")
				{
					m_sPunctuation.setData(sField);
				}
				else if(sMarker == "bpunc")
				{
					m_sBeginPunctuation.setData(sField);
				}
				else if(sMarker == "tagchar") // tagchar added feb 99
				{
					if(sField.GetLength()>0)
						m_cTagChar.setData(sField[0]);
				}
				else if(sMarker == "CarlaStudioPrefs")
					getRuleList()->readPrefsField(sField);

				// fields to ignore
				else if(sMarker == "id")
					{}	// skip it
				else if(sMarker == "_sh")	// shoebox
				{}	// skip it
				else if(sMarker == "mcl" /*|| sMarker == "cl" jdh commented out 11/9/99*/
						|| sMarker=="scl" ||
						sMarker == "ca" || sMarker=="ccl" || sMarker=="ap" || sMarker=="mp")
#ifndef hab17a1
					{
					  // skip these, which are duplicated in several files,  but don't bother the user
					  coOrTdCollector.removeAll();
					}
#else // hab17a1
					{} // skip these, which are duplicated in several files,  but don't bother the user
#endif // hab17a1
#ifndef hab17a1
				else if(sMarker == "td") // 1.7a1 hab test data
				{
				  coOrTdCollector.add(sField, "td");
				}
#endif //hab17a1
#ifndef hab211
				else if(sMarker == "CSbegca")
				{
				  pLastList = 0; // belongs in ad file
				}
				else if(sMarker == "CSbegmp")
				{
				  pLastList = 0; // belongs in ad file
				}
				else if(sMarker == "CSbegap")
				{
				  pLastList = 0; // belongs in ad file
				}
				else if(sMarker == "CSbegccl")
				{
				  pLastList = 0; // belongs in ad file
				}
				else if(sMarker == "CSbegmcl")
				{
				  pLastList = 0; // belongs in ad file
				}
				else if(sMarker == "CSbegcl")
				{
				  pLastList = &m_genericClasses;
				}
				else if(sMarker == "CSbegpat")	//jdh 5/29/01
				{
				  pLastList = &m_patterns;
				}
				else if(sMarker == "CSbegru")
				{
				  pLastList = &((CSentransTransferModel*)this)->m_rules;
				}
				else if(sMarker == "CSend") // CS-specific section end marker
				{
				  if (pLastList)
					{ // dump any comments or test data to list
					  coOrTdCollector.disgorge(*pLastList);
					  pLastList = 0;
					}
				  else
					coOrTdCollector.removeAll();
				}
#endif //hab211
				else
				{	if(bIsDisambig)
					{	f.logSkip("SENTRANS-Disambig", sMarker, sField);
					}
					else
						f.logSkip("SENTRANS-Transfer", sMarker, sField);
				}
			}
			catch(CString sProblemStr) // these ones we can keep going
			{
				f.logParseFailure("Sentrans", sMarker, sField);
			}
		}