/*
Program WinCaml: Graphical User Interface
for interactive use of Caml-Light and Ocaml.
Copyright (C) 2005-2015 Jean Mouric 35700 Rennes France
email: jean.mouric@orange.fr

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. 
*/

// File CHighlighter.h

#include <deque>
#include <cstring>

#ifndef CHIGHLIGHTER_H
#define CHIGHLIGHTER_H

#define TOKENMAX 37

extern const int COLORCOUNT;
extern const int otherColor;
extern const int commentColor;
extern const int stringColor;
extern const int numberColor;
extern const int keywordColor;
extern const int delimiterColor;
extern const int operatorColor;
extern const int inputBackground;
extern const int bufferBackground;
extern const int matchingBackground;

extern size_t token_begin, token_end;

extern int stringToken[];
extern int operatorToken[];
extern int commentToken[];
extern int numberToken[];
extern int keywordToken[];
extern int delimiterToken[];
extern int otherToken[];	

using namespace std;

class CHighlighter;
class CInput;

class tokenClass
{
	friend class CHighlighter;

	int tokenType;
	size_t tokenBegin;
	size_t tokenEnd;
	int str;
	int depth;
	bool needsRefresh;
	int color;

	tokenClass(int tokType, size_t tokBegin, size_t tokEnd)
	{
		tokenType = tokType;
		tokenBegin = tokBegin;
		tokenEnd = tokEnd;
		str = -1;
		depth = - 1;
		needsRefresh = true;
		color = otherColor;
	}
public:
    size_t getTokenBegin()
    {
        return tokenBegin;
    }
    size_t getTokenEnd()
    {
        return tokenEnd;
    }
    int getTokenColor()
    {
        return color;
    }
};

class CHighlighter
{
	size_t tkMin, tkMax;
	deque<tokenClass*>* tokenArray;
	int* tokenColor;
public:
	CInput* textEdit;
private:
	bool shouldBlink;
	bool blinking;
	size_t toMatch;
	size_t p1;
	size_t p2;
	bool setTokenState(size_t i);
	void update();
	size_t tokenIndexFromCharIndex(size_t charIndex);
	size_t matching(size_t n);
	void doBlink(size_t tokenIndex);

public:
	bool textChanged;
	size_t location;

	CHighlighter(CInput* ifr);
	void colorizeAll();
	void invalidate(size_t startPos, size_t endPos);
	void invalidate();
	void updateColors();
	void updateColor(int tokenType[]);
	void colorize();
	void tokenize(size_t firstPos, size_t lastPos, size_t d, bool negative);
    deque<tokenClass*>* getTokenArray()
    {
        return tokenArray;
    }
};	
#endif