void CQuickParseView::OnQuickParseGo()
{
	CWaitCursor wc;

	//---- BRING THE CONTROL FILES UP TO DATE ON THE DISK (added feb 8, 99)
	theApp.getProject()->synchronizeExternals();


	CQuickParseDoc* pDoc = (CQuickParseDoc*)GetDocument();
	UpdateData(TRUE); // get data out of form and into our members
	m_sInput.TrimLeft();
	if(m_sInput.IsEmpty())
		return;

	try
	{
//		sndPlaySound("QuickParse", SND_ASYNC );

		CCarlaLanguage* pSourceLang = pDoc->m_pSourceLang;
		ASSERTX(pSourceLang);
		pSourceLang->prepareMFSForProcessors(); // among other things, get the comment character into the MFS

		CSrcTextProcessingPrefs procPrefs(pSourceLang,
									NULL,
									CProcessingPrefs::kSourceAna);


		CProcessStatus status(	&procPrefs,
								m_sInput,
								pSourceLang,
								pSourceLang->getMFS(),
								NULL,	// output lang
								NULL); // output mfs

		// jdh 3/14/2000 changed to this from some custom code
		if (!status.setupTempDir(pSourceLang->getName()))
			return;	// assumes the user has already been informed

	// added jdh 3/13/2000
		m_bDidRefresh = FALSE; // will be set to TRUE if we refresh
		BOOL bDidGetPreprocessedDicts = status.loadPreprocessedSrcDictsArrayFromLang();
		if(!bDidGetPreprocessedDicts || m_bManualRefreshPending || getNeedDictPreprocessing(status))
			if(!this->preprocessDicts(&status))
				return;

		prepareAmpleProcess();
		loadAmpleOptions();
		m_sOutput = ""; // in case of an exception
		CString sTraceOutput;


		CString sPath;
		sPath.Format(_T("%s\\QP-Ample-Trace.log"), (LPCTSTR)status.getTempDirectory());


#ifndef hab218
		if (m_bTrace && m_bManualParse)
		  {
			m_sTraceMorphs = _T("");
			loadAmpleOptions();
			getManualParse(status, sPath, pSourceLang);
			status.m_sRAWString = m_sInput;
			loadAmpleOptions();
		  }
#endif // hab218
	// DO THE PARSING
		if(!m_bTrace)
		{	// !!! this path is needed if we want to check for errors
			m_pAmpleProcess->processRAWTextString(status, sPath);
		}
		else
		{
			m_pAmpleProcess->processRAWTextString(status, sPath);
		//	m_sOutput = status.m_sRAWString;

			TRY
			{
				CFile log(sPath, CFile::modeRead);
				DWORD sz = log.GetLength();
				if(sz)
				{
					/* If the buffer is ridiculously big (e.g. > 1MB) then the likelyhood
					 * a stack overflow increases - so we truncate early rather than later
					 * let's say that 3 bytes for one UTF8 char is a good guess
					 */
					if (sz > MAX_TRACEOUTPUT * 3)
						sz = MAX_TRACEOUTPUT * 3;
					// on the heap rather than on the stack - stack overflows are easily created
					char* buf = (char *) malloc(sz+2);
					ASSERTX(buf);
					int iReadBytes = log.Read(buf, sz);
					buf[iReadBytes] = '\0'; //terminate it
					USES_CONVERSION_U8;
					sTraceOutput = U82CT(buf);
					free(buf);
				}
				log.Close();
			}
			CATCH( CFileException, e )
			{
#ifdef Before1_04
				checkForFileError(PATH);
#else  // hab 1.04
				checkForFileError(sPath);
#endif // Before1_04
			}
			END_CATCH
		}

		// build the parse part of the answer
		CAmpleResult* pAResult = CAmpleResult::buildResult(status.m_sRAWString);
		if(pAResult)
		{
#ifndef hab218
			m_sOutput += pAResult->getStringRepresentation();
#else //hab218
			m_sOutput = pAResult->getStringRepresentation();
#endif // hab218
			delete pAResult;
		}
		else
			m_sOutput.Format (_T("You have encountered a bug in either CarlaStudio or the Ample DLL.  CarlaStudio could not understand the Ample DLL's answer, which was: %s"), (LPCTSTR)status.m_sRAWString);

		// add the trace part of the answer
		if(m_bTrace)
			m_sOutput += sTraceOutput;

		// do we need to truncate the result?
		TRACE(_T("m_sOutput.GetLength() =%d"), m_sOutput.GetLength());
		if(m_sOutput.GetLength() > MAX_TRACEOUTPUT)
		{
			m_sOutput = m_sOutput.Left(MAX_TRACEOUTPUT);
			m_sOutput += _T("\r\n--Ample's output is too long to fit here.  It has been truncated. ");
		}

		// jdh 3/14/2000 store this set of dictionaries.  we do it only now in so that an error in processing them will be in the user's face
		status.storePreprocessedSrcDictsArrayInLang();

	}
// returns an XML document as a string
CString CPhraseParser::parseString(CString sPhrase, BOOL bTrace, CString sTraceMorphs, BOOL bForceRefresh)
{
	CString sResult;
	try
	{
		//---- BRING THE CONTROL FILES UP TO DATE ON THE DISK
		//jdh 10-june-2000
		if (theApp.getProject()->IsModified())
		{
			throw "Sorry, you have modified the CarlaStudio project and must save it before parsing.  This is a bug which I have not been able to squash.";
			/*			//the following synchronizeExternals() will throw an exception
			//this happens when the MFC code tries to set a waitcursor
			::SetForegroundWindow(theApp.GetMainWnd()->m_hWnd);
			theApp.getProject()->synchronizeExternals();
*/ 		}

		if(bForceRefresh)
			m_bManualRefreshPending = TRUE;

		sPhrase.TrimLeft();
		if(sPhrase.IsEmpty())
			throw "Phrase was empty";


		ASSERTX(m_pSourceLang);
		m_pSourceLang->prepareMFSForProcessors(); // among other things, get the comment character into the MFS

		CSrcTextProcessingPrefs procPrefs(m_pSourceLang,
									NULL,
									CProcessingPrefs::kSourceAna);


		CProcessStatus status(	&procPrefs,
								sPhrase,
								m_pSourceLang,
								m_pSourceLang->getMFS(),
								NULL,	// output lang
								NULL); // output mfs

		// jdh 3/14/2000 changed to this from some custom code
		if (!status.setupTempDir(m_pSourceLang->getName()))
			throw "CS Couldn't setup the temp directory";	// assumes the user has already been informed

	// added jdh 3/13/2000
		m_bDidRefresh = FALSE; // will be set to TRUE if we refresh
		BOOL bDidGetPreprocessedDicts = status.loadPreprocessedSrcDictsArrayFromLang();
		if(!bDidGetPreprocessedDicts || m_bManualRefreshPending || getNeedDictPreprocessing(status))
			if(!this->preprocessDicts(&status))
				throw "CS had problems preprocessing the dictionaries";

		prepareAmpleProcess();
		loadAmpleOptions(bTrace, sTraceMorphs);
		sResult = ""; // in case of an exception
		CString sTraceOutput;


		CString sPath;
		sPath.Format("%s\\QP-Ample-Trace.log", status.getTempDirectory());


	// DO THE PARSING
		if(!bTrace)
		{	// !!! this path is needed if we want to check for errors
			m_pAmpleProcess->processRAWTextString(status, sPath);
		}
		else
		{
			m_pAmpleProcess->processRAWTextString(status, sPath);

			TRY
			{
				CFile log(sPath, CFile::modeRead);
				DWORD sz = log.GetLength();
				if(sz)
				{
					char* buf = new char[sz+2];
					ASSERTX(buf);
					int iReadBytes = log.Read(buf, sz);
					buf[iReadBytes] = '\0'; //terminate it
					sTraceOutput = buf;
					delete buf;
				}
				log.Close();
			}
			CATCH( CFileException, e )
			{
				checkForFileError(sPath);
			}
			END_CATCH
		}

		// jdh 3/14/2000 store this set of dictionaries.  we do it only now in so that an error in processing them will be in the user's face
		status.storePreprocessedSrcDictsArrayInLang();
		sResult = status.m_sRAWString;
	}