// This is the main DLL file.

#include "stdafx.h"
#include <stdlib.h>
#include "LexAnalyser.h"
#include "SyntaxRichTextBox.h"
#include <vcclr.h>

namespace SyntaxTextBox   {
	void SyntaxRichTextBox::WndProc(Message% m) 
	{
		if(m.Msg == 0x00f)
		{
			if(m_bPaint)
			{
				System::Windows::Forms::RichTextBox::WndProc(m);
			}
			else
			{
				m.Result = System::IntPtr::Zero;
			}
		}
		else
		{
			System::Windows::Forms::RichTextBox::WndProc(m);
		}
	};

	void SyntaxRichTextBox::OnTextChanged(EventArgs^ e)
	{	if(! m_bPaint) return;
		m_bPaint = false;
		m_nContentLength = this->TextLength;
		int nCurrentSelectionStart = SelectionStart;
		int nCurrentSelectionLength = SelectionLength;

		

		// Начало текущей строки
		m_nLineStart = nCurrentSelectionStart;
		while ((m_nLineStart > 0) && (Text[m_nLineStart - 1] != '\n'))
			m_nLineStart--;
		// Конец текущей строки
		m_nLineEnd = nCurrentSelectionStart;
		while ((m_nLineEnd < Text->Length) && (Text[m_nLineEnd] != '\n'))
			m_nLineEnd++;
		// Считаем длинну строки
		m_nLineLength = m_nLineEnd - m_nLineStart;
		// Получаем текущую строчку
		m_strLine = Text->Substring(m_nLineStart, m_nLineLength);

		// Обрабатываем строчку
		ProcessLine();

		m_bPaint = true;
	};

	//Выделение синтаксических конструкций в текущей строке
	void SyntaxRichTextBox::ProcessLine()
	{
		// Save the position and make the whole line black
		int nPosition = SelectionStart;
		SelectionStart = m_nLineStart;
		SelectionLength = m_nLineLength;
		SelectionColor = System::Drawing::Color::Black;
		
		Lex::LexAnalyser* lex = new Lex::LexAnalyser();		
		pin_ptr<const wchar_t> pinnedLinePtr = PtrToStringChars(this->m_strLine);
		//Выполняем анализ текущей строки
		std::vector<Lex::ints> lexemmes;
		lex->Syntax(pinnedLinePtr, lexemmes);
		// Process line
		for(unsigned int i=0; i < lexemmes.size(); i++)
		{
			switch(lexemmes[i].type)
			{
			case Lex::Type_CC:
				this->ColoringWord(lexemmes[i].pos, lexemmes[i].len, m_settings->m_colorKeywords);
				break;
			case Lex::Type_DC:
				this->ColoringWord(lexemmes[i].pos, lexemmes[i].len, m_settings->m_colorDelimiter);
				break;
			case Lex::Type_CN:
				this->ColoringWord(lexemmes[i].pos, lexemmes[i].len, m_settings->m_colorDecimal);
				break;
			case Lex::Type_ID:
				this->ColoringWord(lexemmes[i].pos, lexemmes[i].len, m_settings->m_colorIdent);
				break;
			}
		}

		this->SelectionStart = nPosition;
		this->SelectionLength = 0;
		this->SelectionColor = System::Drawing::Color::Black;
		m_nCurSelection = nPosition;
	};

	void SyntaxRichTextBox::ColoringWord(int nStart, int nLength, System::Drawing::Color^ color)
	{
			this->SelectionStart = nStart+this->m_nLineStart-1;
			this->SelectionLength = nLength;
			this->SelectionColor = *color;
	};


	void SyntaxRichTextBox::ProcessAllLines()
	{
		m_bPaint = false;

		int nStartPos = 0;
		int i = 0;
		int nOriginalPos = SelectionStart;
		while (i < Lines->Length)
		{
			m_strLine = Lines[i];
			m_nLineStart = nStartPos;
			m_nLineEnd = m_nLineStart + m_strLine->Length;

			ProcessLine();
			i++;

			nStartPos += m_strLine->Length+1;
		}

		m_bPaint = true;
	};
}
