//..............................................................................
//
// Regex Colorizer syntax highlighter
// by default it uses C programming language syntax
//

import "std_Array.jnc"

//..............................................................................

class RegexColorizerHighlighter
{
protected:
	enum StickyMode
	{
		None = 0,
		SlComment,
		MlComment,
		SqLiteral,
		DqLiteral,
	}

protected:
	jnc.RegexDfa* m_regexDfa_mt;
	jnc.RegexDfa* m_regexDfa_lt;
	std.Array* m_attrArray_mt;
	std.Array* m_attrArray_lt;
	jnc.RegexState m_regexState;

public:
	log.RetroColorizeFlags m_retroColorizerFlags;

public:
	construct ()
	{
		m_regexState.m_isIncremental = true;
	}

	prepareRegex_mt ();

	bool errorcode addRegexPattern_mt (
		char const* regexString,
		gui.TextAttr attr
		);

	bool errorcode finalizeRegex_mt (doc.PluginHost* pluginHost);

	write_lt (
		log.Writer* writer,
		void const* p,
		size_t size
		);

	finalizeWrite_lt (log.Writer* writer)
	{
		write_lt (writer, null, 0); // send eof
		m_regexState.reset ();
	}

protected:
	finalizeRegex_lt (
		doc.PluginHost* pluginHost,
		jnc.RegexDfa* regexDfa,
		std.Array* attrArray
		);
}

// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

RegexColorizerHighlighter.prepareRegex_mt ()
{
	m_regexDfa_mt = new jnc.RegexDfa;
	m_attrArray_mt = new std.Array;
}

bool errorcode RegexColorizerHighlighter.addRegexPattern_mt (
	char const* regexString,
	gui.TextAttr attr
	)
{
	m_regexDfa_mt.incrementalCompile (regexString);
	m_attrArray_mt.append (attr);
	return true;
}

bool errorcode RegexColorizerHighlighter.finalizeRegex_mt (doc.PluginHost* pluginHost)
{
	if (m_attrArray_mt.m_count)
	{
		m_regexDfa_mt.incrementalCompile (".");
		m_regexDfa_mt.finalize ();
	}

	pluginHost.m_log.suspend (); // don't resume until our callback has run in log thread
	(finalizeRegex_lt @ pluginHost.m_logThreadScheduler) (pluginHost, m_regexDfa_mt, m_attrArray_mt);
	m_regexDfa_mt = null;
	m_attrArray_mt = null;
	return true;
}

RegexColorizerHighlighter.finalizeRegex_lt (
	doc.PluginHost* pluginHost,
	jnc.RegexDfa* regexDfa,
	std.Array* attrArray
	)
{
	m_regexState.reset ();
	m_regexDfa_lt = regexDfa;
	m_attrArray_lt = attrArray;
	pluginHost.m_log.resume (); // ok to continue converting now
}

RegexColorizerHighlighter.write_lt (
	log.Writer* writer,
	void const* p,
	size_t size
	)
{
	if (!m_attrArray_lt.m_count)
		return;

	m_regexState.m_currentOffset = -size;

	void const* end = p + size;

	size_t result;

	do
	{
		size_t length = end - p;

		result = try m_regexDfa_lt.match (m_regexState, p, length);
		if (result < m_attrArray_lt.m_count)
		{
			writer.retroColorize (
				m_regexState.m_match.m_offset,
				m_regexState.m_match.m_length,
				(gui.TextAttr) m_attrArray_lt [result],
				m_retroColorizerFlags
				);
		}

		p += m_regexState.m_consumedLength;
	} while (result != -1);
}

//..............................................................................
