1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
/*
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,TQ_SIGNAL(textChanged()),this,TQ_SLOT(drawWhitespaces()));
connect(this,TQ_SIGNAL(cursorPositionChanged(int,int)),this,TQ_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"
|