You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
konversation/konversation/src/multilinetextedit.cpp

176 lines
5.1 KiB

/*
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.
*/
/*
Copyright (C) 2006 Dario Abatianni <eisfuchs@tigress.com>
*/
#include "multilinetextedit.h"
#include <tqpainter.h>
#include <tqregexp.h>
#include <kdebug.h>
MultilineTextEdit::MultilineTextEdit(TQWidget* parent,const char* name) : TQTextEdit(parent,name)
{
// make sure, our whitespace highlighting gets called whenever needed
connect(this,TQT_SIGNAL(textChanged()),this,TQT_SLOT(drawWhitespaces()));
connect(this,TQT_SIGNAL(cursorPositionChanged(int,int)),this,TQT_SLOT(cursorChanged(int,int)));
}
MultilineTextEdit::~MultilineTextEdit()
{
}
void MultilineTextEdit::drawContents(TQPainter* p,int clipx,int clipy,int clipw,int cliph)
{
// redraw text
TQTextEdit::drawContents(p,clipx,clipy,clipw,cliph);
// overlay whitespace markup
drawWhitespaces();
}
void MultilineTextEdit::drawWhitespaces()
{
// prepare a rectangle to store the width of the whitespace found
TQRect space;
// get the painter for the text area
TQPainter pa(viewport());
// get a sane color
TQColor col=tqcolorGroup().link();
// and a brush of the same color
TQBrush fillBrush(col);
// use it for line drawing
pa.setPen(col);
// and for filling
pa.setBrush(fillBrush);
// prepare the carriage return coordinates array
TQPointArray cr(4);
// and the tabulator arrow coordinate array
TQPointArray tab(7);
// whitespace expression
TQRegExp regex("\\s");
// line buffer
TQString line;
int x,y,pos,paragraph;
// start looking in every paragraph
for(paragraph=0;paragraph<paragraphs();paragraph++)
{
// get paragraph text
line=text(paragraph);
// start looking for whitespaces from the beginning
pos=0;
while((pos=line.find(regex,pos))!=-1)
{
// whitespace found is not the carriage return at the end of the line?
if(pos<((int)line.length()-1))
{
// get whitespace rectangle
space=mapToView(paragraph,pos);
// extract x/y coordinates
x=space.width()/2-1+space.x();
y=space.height()/2-1+space.y();
// if it was a regular blank ...
if(regex.cap(0)==" ")
{
// dras a simple small square
pa.drawRect(x-1,y,2,2);
}
// if it was a tabulator
else if(regex.cap(0)=="\t")
{
// calculate arrow points and draw them filled
tab.putPoints(0,7, x-5,y-1, x,y-1, x,y-3, x+3,y, x,y+3, x,y+1, x-5,y+1);
pa.drawPolygon(tab);
}
}
// go to next position and resume looking for more whitespaces
pos++;
} // while
// end of line, get carriage return position
space=mapToView(paragraph,line.length()-1);
// extract x/y positions
x=space.width()/2-1+space.x();
y=space.height()/2-1+space.y();
// calculate carriage return triangle coordinates and draw them filled
cr.putPoints(0,4, x,y, x,y+1, x+4, y+5, x+4, y-4);
pa.drawPolygon(cr);
} // for
}
void MultilineTextEdit::cursorChanged(int /* p */ ,int /* i */)
{
// update markup, since cursor destroys it
drawWhitespaces();
}
// code below from kbabel and adapted by me (Eisfuchs). Thanks, Guys!
TQRect MultilineTextEdit::mapToView(int para,int index)
{
if( para < 0 || para > paragraphs() ||
index < 0 || index > paragraphLength(para) )
return TQRect(); //invalid rectangle
const TQFontMetrics& fm = fontMetrics();
const TQString& paratext = text(para);
// Find index of the first character on the same line as parameter
// 'index' using binary search. Very fast, even for long texts.
int linestart = 0;
int indexline = lineOfChar( para, index );
if ( indexline > 0 )
{
int min = 0, max = index;
int i = (min + max)/2;
int iline = lineOfChar( para, i );
while ( iline != indexline-1 ||
lineOfChar( para, i+1 ) != indexline )
{
Q_ASSERT( min != max && min != i && max != i );
if ( iline < indexline )
min = i;
else
max = i;
i = (min + max)/2;
iline = lineOfChar( para, i );
}
linestart = i+1;
}
Q_ASSERT( linestart >= 0 );
int linewidth = fm.size(ExpandTabs, paratext.mid( linestart, index-linestart )).width();
int linewidth2 = fm.size(ExpandTabs, paratext.mid( linestart, index-linestart+1 )).width();
// FIXME as soon as it's possible to ask real margins from TQTextEdit:
const int left_margin = 4;
// const int top_margin = 4;
TQPainter painter( viewport());
const TQRect& linerect = paragraphRect(para);
return TQRect(
contentsToViewport( TQPoint(
left_margin + linerect.left() + linewidth ,
/*top_margin + */linerect.top() + indexline * fm.lineSpacing() + fm.leading())),
TQSize(
linewidth2-linewidth,
fm.lineSpacing()
));
}
#include "multilinetextedit.moc"