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.
176 lines
5.1 KiB
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=colorGroup().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"
|