/****************************************************************************
**
** Modifications by Romain Gaucher for Modelib
**   >> http://neuroo.kouette.com/modelib
**
** One line to give the program's name and a brief idea of what it does.
** Copyright (C) 2005      Romain Gaucher, Modelib::Project port
** Copyright (C) 2004-2005 Trolltech AS.
**
** 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 2 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, write to the
** Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**
****************************************************************************/

#include <QtGui>

#include "highlighter.h"

Highlighter::Highlighter(QObject *parent)
    : QObject(parent)
{
}

void Highlighter::addToDocument(QTextDocument *doc)
{
    connect(doc, SIGNAL(contentsChange(int, int, int)),
            this, SLOT(highlight(int, int, int)));
}

void Highlighter::addMapping(const QString &pattern,
                             const QTextCharFormat &format)
{
    mappings[pattern] = format;
}


void Highlighter::highlight(int position, int removed, int added)
{
    QTextDocument *doc = qobject_cast<QTextDocument *>(sender());

    QTextBlock block = doc->findBlock(position);
    if (!block.isValid())
        return;

    QTextBlock endBlock;
    if (added > removed)
        endBlock = doc->findBlock(position + added);
    else
        endBlock = block;

    while (block.isValid() && !(endBlock < block)) {
        highlightBlock(block);
        block = block.next();
    }
}

void Highlighter::highlightBlock(QTextBlock& block)
{
    QTextLayout *layout = block.layout();
    const QString text = block.text();

    QList<QTextLayout::FormatRange> overrides;

    foreach (QString pattern, mappings.keys())
	{
        if (pattern != "\\\\(.*)")
		{
			QRegExp expression(pattern,Qt::CaseInsensitive);
			int i = text.indexOf(expression);
			while (i >= 0)
			{
				QTextLayout::FormatRange range;
				range.start = i;
				range.length = expression.matchedLength();
				range.format = mappings[pattern];
				overrides << range;

				i = text.indexOf(expression, i + expression.matchedLength());
			}
		}
    }

	// re-highlight for comments
	QRegExp expression("\\\\(.*)",Qt::CaseInsensitive);
	int i = text.indexOf(expression);
	while (i >= 0)
	{
		QTextLayout::FormatRange range;
		range.start = i;
		range.length = expression.matchedLength();
		range.format = mappings["\\\\(.*)"];
		overrides << range;

		i = text.indexOf(expression, i + expression.matchedLength());
	}

    layout->setAdditionalFormats(overrides);
    const_cast<QTextDocument *>(block.document())->markContentsDirty(block.position(), block.length());
}
