//////////////////////////////////////////////////////////////////////////
//																		//
//																		//
//////////////////////////////////////////////////////////////////////////
BOOL CPreprocessor::ProcessHashInclude(CPreprocessorTokenParser* pcParser)
{
	BOOL						bResult;
	CHeaderFile*				pcIncludeFile;
	CExternalString				cExternalString;
	CChars						sz;
	CHeaderNameMap*				pcHeaderNameMap;
	CHeaderNameMapDirectory*	pcNewDirectory;
	CHeaderNameMapDirectory*	pcCurrentDirectory;
	CChars						szPath;

	pcParser->SkipWhiteSpace();
	bResult = pcParser->GetStringDoubleQuoted(&cExternalString);
	if (!bResult)
	{
		bResult = pcParser->GetQuotedCharacterSequence('<', '>', &cExternalString);
		if (!bResult)
		{
			gcUserError.Set("Error in #include");
			return FALSE;
		}
	}

	FindBestInclude(&cExternalString, FALSE, &pcIncludeFile, &pcHeaderNameMap);
	if (pcIncludeFile)
	{
		pcNewDirectory = mcHeadersStack.Add();
		pcCurrentDirectory = mcHeadersStack.Get(mcHeadersStack.NumElements()-2);

		pcIncludeFile->Path(&szPath);
		pcNewDirectory->Init(pcHeaderNameMap, szPath.Text());
		szPath.Kill();

		bResult = PreprocessBlockSets(pcIncludeFile, mpcCurrentFile);

		pcNewDirectory = mcHeadersStack.Tail();
		pcNewDirectory->Kill();
		mcHeadersStack.Pop();
		return bResult;
	}

	sz.Init("Could not include file ");
	sz.AppendSubString(cExternalString.msz, cExternalString.EndInclusive()+1);
	gcUserError.Set(sz.Text());
	sz.Kill();
	return FALSE;
}
void CPlainTextEditor::Duplicate(void)
{
	int		iStart;
	int		iEnd;
	CChars	szTemp;
	BOOL	bNewLine;

	if (!IsSelected())
	{
		iStart = FindStartOfLine(miEditPos);
		iEnd = FindEndOfLine(miEditPos);
		bNewLine = TRUE;
	}
	else
	{
		if (miSelectionAnchor < miSelectionFloating)
		{
			iStart = miSelectionAnchor;
			iEnd = miSelectionFloating;
		}
		else
		{
			iStart = miSelectionFloating;
			iEnd = miSelectionAnchor;
		}
		bNewLine = FALSE;
	}

	szTemp.Init();
	szTemp.AppendSubString(mszText, iStart, iEnd);
	if (bNewLine)
	{
		szTemp.AppendNewLine();
	}
	mszText.Insert(iStart, &szTemp);
	szTemp.Kill();
	ResetUpDown();
}
//////////////////////////////////////////////////////////////////////////
//																		//
//																		//
//////////////////////////////////////////////////////////////////////////
BOOL CPreprocessor::ProcessHashDefine(CPreprocessorTokenParser* pcParser)
{
	CExternalString		cIdentifier;
	CExternalString		cArgument;
	BOOL				bResult;
	CDefine*			pcDefine;
	CPPText*			pcText;
	CPPReplacement*		pcReplacement;
	int					iReplaceArg;
	CPPToken*			pcToken;
	BOOL				bAllocated;
	BOOL				bAllowWhiteSpace;
	CDefine*			pcExisting;
	CDefine*			pcNew;
	CChars				sz;

	bResult = pcParser->GetIdentifier(&cIdentifier);
	if (bResult)
	{
		pcDefine = AddDefine(&cIdentifier);
		if (pcDefine)
		{
			pcExisting = NULL;
		}
		else
		{
			pcExisting = GetDefine(&cIdentifier);
			pcDefine = (CDefine*)malloc(sizeof(CDefine));
			pcDefine->Init(mcDefines.mcDefinesTree.GetIndexForNew(cIdentifier.msz, cIdentifier.miLen), mcDefines.muiID, NULL);
		}

		bResult = pcParser->GetExactDecorator('(', FALSE);
		if (bResult)
		{
			pcDefine->SetBracketed(TRUE);
			for (;;)
			{
				bResult = pcParser->GetExactDecorator(')');
				if (bResult)
				{
					break;
				}
				bResult = pcParser->GetIdentifier(&cArgument);
				if (bResult)
				{
					pcDefine->AddArgument(&cArgument);
					pcParser->GetExactDecorator(',');
				}
				else
				{
					//Expected an Identifier.
				}
			}
		}

		bAllowWhiteSpace = FALSE;
		while (pcParser->HasToken())
		{
			bAllocated = FALSE;
			pcToken = pcParser->GetToken();
			if (pcToken->IsText())
			{
				pcText = (CPPText*)pcToken;
				if (pcText->meType == PPT_Identifier)
				{
					iReplaceArg = pcDefine->mcArguments.GetIndex(pcText->mcText.msz, pcText->mcText.miLen);
					if (iReplaceArg != -1)
					{
						pcReplacement = CPPReplacement::Construct(mpcStack->Add(sizeof(CPPReplacement)));
						pcReplacement->Init(pcDefine->miIndex, iReplaceArg, -1, -1);
						pcToken = pcReplacement;
						bAllocated = TRUE;
					}
				}
			}

			if (!pcToken->IsWhiteSpace() || bAllowWhiteSpace)  //Stop leading whitespace from being added.
			{
				bAllowWhiteSpace = TRUE;
				if (!bAllocated)
				{
					pcToken = DuplicatePPToken(pcToken, mpcStack);
				}
				pcDefine->AddReplacmentToken(pcToken);
			}

			pcParser->NextToken();
		}

		bResult = TRUE;
		if (pcExisting)
		{
			if (!pcExisting->Equals(pcDefine))
			{
				//Removing a define will not change the index or the ID of our new define.  Phew.
				RemoveDefine(&cIdentifier);
				pcNew = AddDefine(&cIdentifier, pcDefine);
				if (!pcNew)
				{
					sz.Init("Could not redefine #define ");
					sz.AppendSubString(cIdentifier.msz, cIdentifier.EndInclusive()+1);
					sz.Append(".  Probably index or ID is different.");
					gcUserError.Set(sz.Text());
					sz.Kill();
					bResult = FALSE;
				}
			}
			else
			{
				//Only kill the define if the existing one is identical.
				//pcNew depends on the allocations in the non-identical define case.
				pcDefine->Kill();
			}
			free(pcDefine);
		}
	}
	else
	{
		gcUserError.Set("Could not get an identifier for a #define.  Add one.");
	}
	return bResult;
}
//////////////////////////////////////////////////////////////////////////
//																		//
//																		//
//////////////////////////////////////////////////////////////////////////
void CPreprocessor::DeltaDefines(CArrayNamedDefines* pcDelta, CMemoryStackExtended* pcStack)
{
	int					i;
	CNamedDefine*		pcNamedDefine;
	CDefine*			pcExisting;
	CDefine*			pcDefine;
	CDefine*			pcNew;
	BOOL				bResult;
	CExternalString		cIdentifier;
	CChars				sz;

	for (i = 0; i < pcDelta->NumElements(); i++)
	{
		pcNamedDefine = pcDelta->Get(i);
		cIdentifier.Init(pcNamedDefine->mszName.Text(), pcNamedDefine->mszName.Length());
		if (pcNamedDefine->miFlags & NAMED_DEFINE_FLAGS_UNDEFFED)
		{
			RemoveDefine(&cIdentifier);
		}
		else
		{
			pcDefine = AddDefine(&cIdentifier);
			if (pcDefine)
			{
				pcExisting = NULL;
			}
			else
			{
				pcExisting = GetDefine(pcNamedDefine->mszName.Text());
				pcDefine = (CDefine*)malloc(sizeof(CDefine));
				pcDefine->Init(mcDefines.mcDefinesTree.GetIndexForNew(cIdentifier.msz, cIdentifier.miLen), mcDefines.muiID, NULL);
			}

			pcDefine->mcArguments.Copy(&pcNamedDefine->mcArguments);
			pcDefine->mcReplacement.Copy(&pcNamedDefine->mcReplacement, pcStack);
			pcDefine->SetBracketed(pcNamedDefine->IsBacketed());

			bResult = TRUE;
			if (pcExisting)
			{
				if (!pcExisting->Equals(pcDefine))
				{
					//Removing a define will not change the index or the ID of our new define.  Phew.
					RemoveDefine(&cIdentifier);
					pcNew = AddDefine(&cIdentifier, pcDefine);
					if (!pcNew)
					{
						sz.Init("Could not redefine #define ");
						sz.AppendSubString(cIdentifier.msz, cIdentifier.EndInclusive()+1);
						sz.Append(".  Probably index or ID is different.");
						gcUserError.Set(sz.Text());
						sz.Kill();
						bResult = FALSE;
					}
				}
				else
				{
					//Only kill the define if the existing one is identical.
					//pcNew depends on the allocations in the non-identical define case.
					pcDefine->Kill();
				}
				free(pcDefine);
			}
		}
	}
}