=begin
Timba language interpreter.
Copyright (C) 2016  Nicolas Guzzo

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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
=end

class Highlighter < Qt::Object
	
	slots	'highlight(int, int, int)'
	
	def initialize(parent = nil)
	    super(parent)
		@mappings = {}
	end
	
	def addToDocument(doc)
	    connect(doc, SIGNAL('contentsChange(int, int, int)'),
	            self, SLOT('highlight(int, int, int)'))
	end
	
	def addMapping(pattern, format)
	    @mappings[pattern] = format
	end
	
	def highlight(position, removed, added)
	    doc = sender()
	
	    block = doc.findBlock(position)
	    if !block.valid?
	        return
		end
	
	    if added > removed
	        endBlock = doc.findBlock(position + added)
	    else
	        endBlock = block
		end

	    while block.valid? and !(endBlock < block) do
	        highlightBlock(block)
	        block = block.next
	    end
	end

	def highlight_all(doc)	    
	
	    block = doc.begin
	    if !block.valid?
	        return
		end	
	    endBlock = doc.end	    
	    while block.valid?  do	    	
	        highlightBlock(block)
	        block = block.next
	    end
	end
	
	def highlightBlock(block)
	    layout = block.layout
	    text = block.text
		if text.nil?
			return
		end

	    overrides = []
		@mappings.each do |pattern, value|
	        expression = Regexp.new(pattern)
	        i = text.index(expression)
	        while !i.nil?
	            range = Qt::TextLayout::FormatRange.new
	            range.start = i
	            range.length = $&.length
	            range.format = value
	            overrides << range

	            i = text.index(expression, i + $&.length)
	        end
	    end
	
	   layout.additionalFormats = overrides
	   block.document.markContentsDirty(block.position, block.length)
	end
end
