
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#include "StateCache.h"



//////////////////////////////////////////////
StateCacheLineElem::StateCacheLineElem(int prevState)
{
	PrevLineEndState = prevState;
	UnitStateCache.setAutoDelete(true);
}
//////////////////////////////////////////////



//////////////////////////////////////////////
Colorizer* StateCacheLineElem::colorizer;
//////////////////////////////////////////////



//////////////////////////////////////////////
int StateCacheLineElem::reparse(const QString& s)
{
	int start, len;
	int innerState;
	
	
	UnitStateCache.clear();
	int prevState = PrevLineEndState;	
	
		// returns with state after matching text in prevState:
    start = colorizer->match(s, 0, len, innerState, prevState);
		
    while(start != -1)
    {
    	UnitStateCache.append(new StateCacheElem(innerState, prevState, start, len));
		start = colorizer->match(s, start + len, len, innerState, prevState);
	}
	return prevState;
}
//////////////////////////////////////////////



//////////////////////////////////////////////
StateCache::StateCache(Colorizer* c, KSyntaxMultiLineEdit* edit)
{
	StateCacheLineElem::colorizer = c;
	LineStateCache.setAutoDelete(true);
	Edit = edit;
}
//////////////////////////////////////////////



//#include <pthread.h>       

//////////////////////////////////////////////
void* parseThread(void* arg)
{
	printf("parsing...\n");
	StateCache* sc = (StateCache*)arg;
	sc->parse();
	return 0;
}
//////////////////////////////////////////////



//////////////////////////////////////////////
void StateCache::parse()
{
	int state = 0;
	int line;

	LineStateCache.clear();

    for(line = 0; line < Edit->numLines(); line++)
    {	
   		StateCacheLineElem* lsc = new StateCacheLineElem(state);
    	state = lsc->reparse(Edit->textLine(line));
   		LineStateCache.append(lsc);
	}

	if(LineStateCache.isEmpty())
 		LineStateCache.append(new StateCacheLineElem(0));
}
//////////////////////////////////////////////



//////////////////////////////////////////////
int StateCache::reparseFromHere(unsigned int row)
{
	int state;
	if(LineStateCache.isEmpty())
		state = 0;
	else
		state = LineStateCache.at(row)->prevLineEndState();
// warning("line %d prev line end state: %d", row, state);
    
    	// reparse from row until there are no more changes!
    for(int line = row; line < Edit->numLines(); line++)
    {
    	StateCacheLineElem* lsc = new StateCacheLineElem(state);
    	state = lsc->reparse(Edit->textLine(line));
  
// warning("reparse line %d with new end state %d", line, state);
    	
    		// replace object for line:
    	LineStateCache.remove(line);
    	LineStateCache.insert(line, lsc);
    	
   		if(line < Edit->numLines() - 1 && 
   					state == LineStateCache.at(line + 1)->prevLineEndState())
		   	return line;
	}
	
	return Edit->numLines();
}
//////////////////////////////////////////////



//////////////////////////////////////////////
void StateCache::insertLine(unsigned int row, int prevState)
{
        // line 0 must have STATE_NORMAL!
    if(row == 0)
        prevState = STATE_NORMAL;
    else
    	if(prevState == STATE_NORMAL)
	    {
    		if(!LineStateCache.isEmpty())
	    		prevState = LineStateCache.at(row)->prevLineEndState();
		    else
		        prevState = STATE_NORMAL;
    	}
	
	LineStateCache.insert(row, new StateCacheLineElem(prevState));
}
//////////////////////////////////////////////



//////////////////////////////////////////////
void StateCache::removeLine(unsigned int row)
{
	if(!LineStateCache.count())
		return;
		
	assert(LineStateCache.count() > row);
   	LineStateCache.remove(row);
}
//////////////////////////////////////////////

