JBoolean
CBCtagsUser::ProcessFile
	(
	const JCharacter*		fileName,
	const CBTextFileType	fileType,
	JString*				result,
	CBLanguage*				lang
	)
{
	if (!StartProcess(fileType, lang))
		{
		result->Clear();
		return kJFalse;
		}

	*itsCmdPipe << fileName << endl;

	JBoolean found;
	*result = JReadUntil(itsResultFD, kDelimiter, &found);
	if (found)
		{
		return kJTrue;
		}
	else if (itsTryRestartFlag)
		{
		DeleteProcess();

		itsTryRestartFlag = kJFalse;
		const JBoolean ok = ProcessFile(fileName, fileType, result, lang);
		itsTryRestartFlag = kJTrue;
		return ok;
		}
	else
		{
		DeleteProcess();
		itsIsActiveFlag = kJFalse;

		if (!CBInUpdateThread())
			{
			(JGetUserNotification())->ReportError(
				"ctags is not responding correctly, "
				"so some features will not work.");
			}

		return kJFalse;
		}
}
JBoolean
CBSymbolList::UpdateFinished
	(
	const JArray<JFAID_t>&	deadFileList,
	JProgressDisplay&		pg
	)
{
	DeleteProcess();

	// reset to lenient search

	itsSymbolList->SetCompareFunction(CompareSymbols);

	// toss files that no longer exist

	const JSize fileCount = deadFileList.GetElementCount();
	if (fileCount > 0)
		{
		pg.FixedLengthProcessBeginning(fileCount, JGetString(kCleaningUpID), kJFalse, kJTrue);

		for (JIndex i=1; i<=fileCount; i++)
			{
			RemoveFile(deadFileList.GetElement(i));
			pg.IncrementProgress();
			}

		pg.ProcessFinished();
		}

	if (itsChangedDuringParseFlag && !CBInUpdateThread())
		{
		itsReparseAllFlag = kJFalse;
		Broadcast(Changed());
		}

	return itsChangedDuringParseFlag;
}