summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/apps/embeddedkonsole/TEWidget.cpp21
1 files changed, 18 insertions, 3 deletions
diff --git a/core/apps/embeddedkonsole/TEWidget.cpp b/core/apps/embeddedkonsole/TEWidget.cpp
index d0850e3..ec1b30c 100644
--- a/core/apps/embeddedkonsole/TEWidget.cpp
+++ b/core/apps/embeddedkonsole/TEWidget.cpp
@@ -1,1358 +1,1373 @@
1/* ------------------------------------------------------------------------ */ 1/* ------------------------------------------------------------------------ */
2/* */ 2/* */
3/* [TEWidget.C] Terminal Emulation Widget */ 3/* [TEWidget.C] Terminal Emulation Widget */
4/* */ 4/* */
5/* ------------------------------------------------------------------------ */ 5/* ------------------------------------------------------------------------ */
6/* */ 6/* */
7/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */ 7/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
8/* */ 8/* */
9/* This file is part of Konsole - an X terminal for KDE */ 9/* This file is part of Konsole - an X terminal for KDE */
10/* */ 10/* */
11/* ------------------------------------------------------------------------ */ 11/* ------------------------------------------------------------------------ */
12/* */ 12/* */
13/* Ported Konsole to Qt/Embedded */ 13/* Ported Konsole to Qt/Embedded */
14/* */ 14/* */
15/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */ 15/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
16/* */ 16/* */
17/* -------------------------------------------------------------------------- */ 17/* -------------------------------------------------------------------------- */
18/*! \class TEWidget 18/*! \class TEWidget
19 19
20 \brief Visible screen contents 20 \brief Visible screen contents
21 21
22 This class is responsible to map the `image' of a terminal emulation to the 22 This class is responsible to map the `image' of a terminal emulation to the
23 display. All the dependency of the emulation to a specific GUI or toolkit is 23 display. All the dependency of the emulation to a specific GUI or toolkit is
24 localized here. Further, this widget has no knowledge about being part of an 24 localized here. Further, this widget has no knowledge about being part of an
25 emulation, it simply work within the terminal emulation framework by exposing 25 emulation, it simply work within the terminal emulation framework by exposing
26 size and key events and by being ordered to show a new image. 26 size and key events and by being ordered to show a new image.
27 27
28 <ul> 28 <ul>
29 <li> The internal image has the size of the widget (evtl. rounded up) 29 <li> The internal image has the size of the widget (evtl. rounded up)
30 <li> The external image used in setImage can have any size. 30 <li> The external image used in setImage can have any size.
31 <li> (internally) the external image is simply copied to the internal 31 <li> (internally) the external image is simply copied to the internal
32 when a setImage happens. During a resizeEvent no painting is done 32 when a setImage happens. During a resizeEvent no painting is done
33 a paintEvent is expected to follow anyway. 33 a paintEvent is expected to follow anyway.
34 </ul> 34 </ul>
35 35
36 \sa TEScreen \sa Emulation 36 \sa TEScreen \sa Emulation
37*/ 37*/
38 38
39/* FIXME: 39/* FIXME:
40 - 'image' may also be used uninitialized (it isn't in fact) in resizeEvent 40 - 'image' may also be used uninitialized (it isn't in fact) in resizeEvent
41 - 'font_a' not used in mouse events 41 - 'font_a' not used in mouse events
42 - add destructor 42 - add destructor
43*/ 43*/
44 44
45/* TODO 45/* TODO
46 - evtl. be sensitive to `paletteChange' while using default colors. 46 - evtl. be sensitive to `paletteChange' while using default colors.
47 - set different 'rounding' styles? I.e. have a mode to show clipped chars? 47 - set different 'rounding' styles? I.e. have a mode to show clipped chars?
48*/ 48*/
49 49
50// #include "config.h" 50// #include "config.h"
51#include "TEWidget.h" 51#include "TEWidget.h"
52#include "session.h" 52#include "session.h"
53#include <qpe/config.h> 53#include <qpe/config.h>
54 54
55#include <qpe/resource.h> 55#include <qpe/resource.h>
56#include <qpe/sound.h> 56#include <qpe/sound.h>
57 57
58#if !(QT_NO_COP) 58#if !(QT_NO_COP)
59#include <qpe/qcopenvelope_qws.h> 59#include <qpe/qcopenvelope_qws.h>
60#endif 60#endif
61 61
62#include <qcursor.h> 62#include <qcursor.h>
63#include <qregexp.h> 63#include <qregexp.h>
64#include <qpainter.h> 64#include <qpainter.h>
65#include <qclipboard.h> 65#include <qclipboard.h>
66#include <qstyle.h> 66#include <qstyle.h>
67#include <qfile.h> 67#include <qfile.h>
68#include <qdragobject.h> 68#include <qdragobject.h>
69 69
70#include <stdio.h> 70#include <stdio.h>
71#include <stdlib.h> 71#include <stdlib.h>
72#include <unistd.h> 72#include <unistd.h>
73#include <ctype.h> 73#include <ctype.h>
74#include <sys/stat.h> 74#include <sys/stat.h>
75#include <sys/types.h> 75#include <sys/types.h>
76#include <signal.h> 76#include <signal.h>
77 77
78#include <assert.h> 78#include <assert.h>
79 79
80// #include "TEWidget.moc" 80// #include "TEWidget.moc"
81//#include <kapp.h> 81//#include <kapp.h>
82//#include <kcursor.h> 82//#include <kcursor.h>
83//#include <kurl.h> 83//#include <kurl.h>
84//#include <kdebug.h> 84//#include <kdebug.h>
85//#include <klocale.h> 85//#include <klocale.h>
86 86
87#define HERE printf("%s(%d): %s\n",__FILE__,__LINE__,__FUNCTION__) 87#define HERE printf("%s(%d): %s\n",__FILE__,__LINE__,__FUNCTION__)
88#define HCNT(Name) // { static int cnt = 1; printf("%s(%d): %s %d\n",__FILE__,__LINE__,Name,cnt++); } 88#define HCNT(Name) // { static int cnt = 1; printf("%s(%d): %s %d\n",__FILE__,__LINE__,Name,cnt++); }
89 89
90#define loc(X,Y) ((Y)*columns+(X)) 90#define loc(X,Y) ((Y)*columns+(X))
91 91
92//FIXME: the rim should normally be 1, 0 only when running in full screen mode. 92//FIXME: the rim should normally be 1, 0 only when running in full screen mode.
93#define rimX 0 // left/right rim width 93#define rimX 0 // left/right rim width
94#define rimY 0 // top/bottom rim high 94#define rimY 0 // top/bottom rim high
95 95
96#define SCRWIDTH 16 // width of the scrollbar 96#define SCRWIDTH 16 // width of the scrollbar
97 97
98#define yMouseScroll 1 98#define yMouseScroll 1
99// scroll increment used when dragging selection at top/bottom of window. 99// scroll increment used when dragging selection at top/bottom of window.
100 100
101/* ------------------------------------------------------------------------- */ 101/* ------------------------------------------------------------------------- */
102/* */ 102/* */
103/* Colors */ 103/* Colors */
104/* */ 104/* */
105/* ------------------------------------------------------------------------- */ 105/* ------------------------------------------------------------------------- */
106 106
107//FIXME: the default color table is in session.C now. 107//FIXME: the default color table is in session.C now.
108// We need a way to get rid of this one, here. 108// We need a way to get rid of this one, here.
109static const ColorEntry base_color_table[TABLE_COLORS] = 109static const ColorEntry base_color_table[TABLE_COLORS] =
110// The following are almost IBM standard color codes, with some slight 110// The following are almost IBM standard color codes, with some slight
111// gamma correction for the dim colors to compensate for bright X screens. 111// gamma correction for the dim colors to compensate for bright X screens.
112// It contains the 8 ansiterm/xterm colors in 2 intensities. 112// It contains the 8 ansiterm/xterm colors in 2 intensities.
113{ 113{
114 // Fixme: could add faint colors here, also. 114 // Fixme: could add faint colors here, also.
115 // normal 115 // normal
116 ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 1, 0 ), // Dfore, Dback 116 ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 1, 0 ), // Dfore, Dback
117 ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red 117 ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red
118 ColorEntry(QColor(0x18,0xB2,0x18), 0, 0 ), ColorEntry( QColor(0xB2,0x68,0x18), 0, 0 ), // Green, Yellow 118 ColorEntry(QColor(0x18,0xB2,0x18), 0, 0 ), ColorEntry( QColor(0xB2,0x68,0x18), 0, 0 ), // Green, Yellow
119 ColorEntry(QColor(0x18,0x18,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), // Blue, Magenta 119 ColorEntry(QColor(0x18,0x18,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), // Blue, Magenta
120 ColorEntry(QColor(0x18,0xB2,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 0, 0 ), // Cyan, White 120 ColorEntry(QColor(0x18,0xB2,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 0, 0 ), // Cyan, White
121 // intensiv 121 // intensiv
122 ColorEntry(QColor(0x00,0x00,0x00), 0, 1 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 1, 0 ), 122 ColorEntry(QColor(0x00,0x00,0x00), 0, 1 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 1, 0 ),
123 ColorEntry(QColor(0x68,0x68,0x68), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0x54), 0, 0 ), 123 ColorEntry(QColor(0x68,0x68,0x68), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0x54), 0, 0 ),
124 ColorEntry(QColor(0x54,0xFF,0x54), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0x54), 0, 0 ), 124 ColorEntry(QColor(0x54,0xFF,0x54), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0x54), 0, 0 ),
125 ColorEntry(QColor(0x54,0x54,0xFF), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), 125 ColorEntry(QColor(0x54,0x54,0xFF), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ),
126 ColorEntry(QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 ) 126 ColorEntry(QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 )
127}; 127};
128 128
129/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb) 129/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb)
130 130
131 Code 0 1 2 3 4 5 6 7 131 Code 0 1 2 3 4 5 6 7
132 ----------- ------- ------- ------- ------- ------- ------- ------- ------- 132 ----------- ------- ------- ------- ------- ------- ------- ------- -------
133 ANSI (bgr) Black Red Green Yellow Blue Magenta Cyan White 133 ANSI (bgr) Black Red Green Yellow Blue Magenta Cyan White
134 IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White 134 IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White
135*/ 135*/
136 136
137QColor TEWidget::getDefaultBackColor() 137QColor TEWidget::getDefaultBackColor()
138{ 138{
139 return color_table[DEFAULT_BACK_COLOR].color; 139 return color_table[DEFAULT_BACK_COLOR].color;
140} 140}
141 141
142const ColorEntry* TEWidget::getColorTable() const 142const ColorEntry* TEWidget::getColorTable() const
143{ 143{
144 return color_table; 144 return color_table;
145} 145}
146 146
147const ColorEntry* TEWidget::getdefaultColorTable() const 147const ColorEntry* TEWidget::getdefaultColorTable() const
148{ 148{
149 return base_color_table; 149 return base_color_table;
150} 150}
151 151
152 152
153const QPixmap *TEWidget::backgroundPixmap() 153const QPixmap *TEWidget::backgroundPixmap()
154{ 154{
155 static QPixmap *bg = new QPixmap("~/qpim/main/pics/faded_bg.xpm"); 155 static QPixmap *bg = new QPixmap("~/qpim/main/pics/faded_bg.xpm");
156 const QPixmap *pm = bg; 156 const QPixmap *pm = bg;
157 return pm; 157 return pm;
158} 158}
159 159
160void TEWidget::setColorTable(const ColorEntry table[]) 160void TEWidget::setColorTable(const ColorEntry table[])
161{ 161{
162 for (int i = 0; i < TABLE_COLORS; i++) color_table[i] = table[i]; 162 for (int i = 0; i < TABLE_COLORS; i++) color_table[i] = table[i];
163 163
164 const QPixmap* pm = backgroundPixmap(); 164 const QPixmap* pm = backgroundPixmap();
165 if (!pm) setBackgroundColor(color_table[DEFAULT_BACK_COLOR].color); 165 if (!pm) setBackgroundColor(color_table[DEFAULT_BACK_COLOR].color);
166 update(); 166 update();
167} 167}
168 168
169//FIXME: add backgroundPixmapChanged. 169//FIXME: add backgroundPixmapChanged.
170 170
171/* ------------------------------------------------------------------------- */ 171/* ------------------------------------------------------------------------- */
172/* */ 172/* */
173/* Font */ 173/* Font */
174/* */ 174/* */
175/* ------------------------------------------------------------------------- */ 175/* ------------------------------------------------------------------------- */
176 176
177/* 177/*
178 The VT100 has 32 special graphical characters. The usual vt100 extended 178 The VT100 has 32 special graphical characters. The usual vt100 extended
179 xterm fonts have these at 0x00..0x1f. 179 xterm fonts have these at 0x00..0x1f.
180 180
181 QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals 181 QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals
182 come in here as proper unicode characters. 182 come in here as proper unicode characters.
183 183
184 We treat non-iso10646 fonts as VT100 extended and do the requiered mapping 184 We treat non-iso10646 fonts as VT100 extended and do the requiered mapping
185 from unicode to 0x00..0x1f. The remaining translation is then left to the 185 from unicode to 0x00..0x1f. The remaining translation is then left to the
186 QCodec. 186 QCodec.
187*/ 187*/
188 188
189// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i. 189// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.
190 190
191unsigned short vt100_graphics[32] = 191unsigned short vt100_graphics[32] =
192{ // 0/8 1/9 2/10 3/11 4/12 5/13 6/14 7/15 192{ // 0/8 1/9 2/10 3/11 4/12 5/13 6/14 7/15
193 0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 193 0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0,
194 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 194 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,
195 0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534, 195 0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534,
196 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7 196 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7
197}; 197};
198 198
199static QChar vt100extended(QChar c) 199static QChar vt100extended(QChar c)
200{ 200{
201 switch (c.unicode()) 201 switch (c.unicode())
202 { 202 {
203 case 0x25c6 : return 1; 203 case 0x25c6 : return 1;
204 case 0x2592 : return 2; 204 case 0x2592 : return 2;
205 case 0x2409 : return 3; 205 case 0x2409 : return 3;
206 case 0x240c : return 4; 206 case 0x240c : return 4;
207 case 0x240d : return 5; 207 case 0x240d : return 5;
208 case 0x240a : return 6; 208 case 0x240a : return 6;
209 case 0x00b0 : return 7; 209 case 0x00b0 : return 7;
210 case 0x00b1 : return 8; 210 case 0x00b1 : return 8;
211 case 0x2424 : return 9; 211 case 0x2424 : return 9;
212 case 0x240b : return 10; 212 case 0x240b : return 10;
213 case 0x2518 : return 11; 213 case 0x2518 : return 11;
214 case 0x2510 : return 12; 214 case 0x2510 : return 12;
215 case 0x250c : return 13; 215 case 0x250c : return 13;
216 case 0x2514 : return 14; 216 case 0x2514 : return 14;
217 case 0x253c : return 15; 217 case 0x253c : return 15;
218 case 0xf800 : return 16; 218 case 0xf800 : return 16;
219 case 0xf801 : return 17; 219 case 0xf801 : return 17;
220 case 0x2500 : return 18; 220 case 0x2500 : return 18;
221 case 0xf803 : return 19; 221 case 0xf803 : return 19;
222 case 0xf804 : return 20; 222 case 0xf804 : return 20;
223 case 0x251c : return 21; 223 case 0x251c : return 21;
224 case 0x2524 : return 22; 224 case 0x2524 : return 22;
225 case 0x2534 : return 23; 225 case 0x2534 : return 23;
226 case 0x252c : return 24; 226 case 0x252c : return 24;
227 case 0x2502 : return 25; 227 case 0x2502 : return 25;
228 case 0x2264 : return 26; 228 case 0x2264 : return 26;
229 case 0x2265 : return 27; 229 case 0x2265 : return 27;
230 case 0x03c0 : return 28; 230 case 0x03c0 : return 28;
231 case 0x2260 : return 29; 231 case 0x2260 : return 29;
232 case 0x00a3 : return 30; 232 case 0x00a3 : return 30;
233 case 0x00b7 : return 31; 233 case 0x00b7 : return 31;
234 } 234 }
235 return c; 235 return c;
236} 236}
237 237
238static QChar identicalMap(QChar c) 238static QChar identicalMap(QChar c)
239{ 239{
240 return c; 240 return c;
241} 241}
242 242
243void TEWidget::fontChange(const QFont &) 243void TEWidget::fontChange(const QFont &)
244{ 244{
245 QFontMetrics fm(font()); 245 QFontMetrics fm(font());
246 font_h = fm.height(); 246 font_h = fm.height();
247 font_w = fm.maxWidth(); 247
248 font_a = fm.ascent(); 248 // font_w = max width of ASCII chars (U.B.)
249 font_w = 0;
250 int fw;
251 for (int i = 0x20; i < 0x80; i++) {
252 if (isprint(i) && font_w < (fw = fm.width(i))) {
253 font_w = fw;
254 }
255 }
256 //font_w = fm.maxWidth();
257
258 font_a = fm.ascent();
249//printf("font_h: %d\n",font_h); 259//printf("font_h: %d\n",font_h);
250//printf("font_w: %d\n",font_w); 260//printf("font_w: %d\n",font_w);
251//printf("font_a: %d\n",font_a); 261//printf("font_a: %d\n",font_a);
252//printf("charset: %s\n",QFont::encodingName(font().charSet()).ascii()); 262//printf("charset: %s\n",QFont::encodingName(font().charSet()).ascii());
253//printf("rawname: %s\n",font().rawName().ascii()); 263//printf("rawname: %s\n",font().rawName().ascii());
254 fontMap = 264 fontMap =
255#if QT_VERSION < 300 265#if QT_VERSION < 300
256 strcmp(QFont::encodingName(font().charSet()).ascii(),"iso10646") 266 strcmp(QFont::encodingName(font().charSet()).ascii(),"iso10646")
257 ? vt100extended 267 ? vt100extended
258 : 268 :
259#endif 269#endif
260 identicalMap; 270 identicalMap;
261 propagateSize(); 271 propagateSize();
262 update(); 272 update();
263} 273}
264 274
265void TEWidget::setVTFont(const QFont& f) 275void TEWidget::setVTFont(const QFont& f)
266{ 276{
267 QFrame::setFont(f); 277 QFrame::setFont(f);
268} 278}
269 279
270QFont TEWidget::getVTFont() { 280QFont TEWidget::getVTFont() {
271 return font(); 281 return font();
272} 282}
273 283
274void TEWidget::setFont(const QFont &) 284void TEWidget::setFont(const QFont &)
275{ 285{
276 // ignore font change request if not coming from konsole itself 286 // ignore font change request if not coming from konsole itself
277} 287}
278 288
279/* ------------------------------------------------------------------------- */ 289/* ------------------------------------------------------------------------- */
280/* */ 290/* */
281/* Constructor / Destructor */ 291/* Constructor / Destructor */
282/* */ 292/* */
283/* ------------------------------------------------------------------------- */ 293/* ------------------------------------------------------------------------- */
284 294
285TEWidget::TEWidget(QWidget *parent, const char *name) : QFrame(parent,name) 295TEWidget::TEWidget(QWidget *parent, const char *name) : QFrame(parent,name)
286{ 296{
287#ifndef QT_NO_CLIPBOARD 297#ifndef QT_NO_CLIPBOARD
288 cb = QApplication::clipboard(); 298 cb = QApplication::clipboard();
289 QObject::connect( (QObject*)cb, SIGNAL(dataChanged()), 299 QObject::connect( (QObject*)cb, SIGNAL(dataChanged()),
290 this, SLOT(onClearSelection()) ); 300 this, SLOT(onClearSelection()) );
291#endif 301#endif
292 302
293 scrollbar = new QScrollBar(this); 303 scrollbar = new QScrollBar(this);
294 scrollbar->setCursor( arrowCursor ); 304 scrollbar->setCursor( arrowCursor );
295 connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int))); 305 connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
296 306
297 hScrollbar = new QScrollBar(this); 307 hScrollbar = new QScrollBar(this);
298 hScrollbar->setCursor( arrowCursor ); 308 hScrollbar->setCursor( arrowCursor );
299 hScrollbar->setOrientation(QScrollBar::Horizontal); 309 hScrollbar->setOrientation(QScrollBar::Horizontal);
300 hScrollbar->setMaximumHeight(16); 310 hScrollbar->setMaximumHeight(16);
301 311
302 connect( hScrollbar, SIGNAL(valueChanged(int)), this, SLOT( hScrollChanged(int))); 312 connect( hScrollbar, SIGNAL(valueChanged(int)), this, SLOT( hScrollChanged(int)));
303 313
304 Config cfg("Konsole"); 314 Config cfg("Konsole");
305 cfg.setGroup("ScrollBar"); 315 cfg.setGroup("ScrollBar");
306 switch( cfg.readNumEntry("Position",2)){ 316 switch( cfg.readNumEntry("Position",2)){
307 case 0: 317 case 0:
308 scrollLoc = SCRNONE; 318 scrollLoc = SCRNONE;
309 break; 319 break;
310 case 1: 320 case 1:
311 scrollLoc = SCRLEFT; 321 scrollLoc = SCRLEFT;
312 break; 322 break;
313 case 2: 323 case 2:
314 scrollLoc = SCRRIGHT; 324 scrollLoc = SCRRIGHT;
315 break; 325 break;
316 }; 326 };
317 327
318 useHorzScroll=cfg.readBoolEntry("HorzScroll",0); 328 useHorzScroll=cfg.readBoolEntry("HorzScroll",0);
319 329
320 blinkT = new QTimer(this); 330 blinkT = new QTimer(this);
321 connect(blinkT, SIGNAL(timeout()), this, SLOT(blinkEvent())); 331 connect(blinkT, SIGNAL(timeout()), this, SLOT(blinkEvent()));
322 // blinking = FALSE; 332 // blinking = FALSE;
323 blinking = TRUE; 333 blinking = TRUE;
324 334
325 resizing = FALSE; 335 resizing = FALSE;
326 actSel = 0; 336 actSel = 0;
327 image = 0; 337 image = 0;
328 lines = 1; 338 lines = 1;
329 columns = 1; 339 columns = 1;
330 font_w = 1; 340 font_w = 1;
331 font_h = 1; 341 font_h = 1;
332 font_a = 1; 342 font_a = 1;
333 word_selection_mode = FALSE; 343 word_selection_mode = FALSE;
334 hposition = 0; 344 hposition = 0;
335 vcolumns = 0; 345 vcolumns = 0;
336 useBeep = true; 346 useBeep = true;
337 347
338 setMouseMarks(TRUE); 348 setMouseMarks(TRUE);
339 setVTFont( QFont("fixed") ); 349 setVTFont( QFont("fixed") );
340 setColorTable(base_color_table); // init color table 350 setColorTable(base_color_table); // init color table
341 351
342 qApp->installEventFilter( this ); //FIXME: see below 352 qApp->installEventFilter( this ); //FIXME: see below
343// KCursor::setAutoHideCursor( this, true ); 353// KCursor::setAutoHideCursor( this, true );
344 354
345 // Init DnD //////////////////////////////////////////////////////////////// 355 // Init DnD ////////////////////////////////////////////////////////////////
346 currentSession = NULL; 356 currentSession = NULL;
347// setAcceptDrops(true); // attempt 357// setAcceptDrops(true); // attempt
348// m_drop = new QPopupMenu(this); 358// m_drop = new QPopupMenu(this);
349// m_drop->insertItem( QString("Paste"), 0); 359// m_drop->insertItem( QString("Paste"), 0);
350// m_drop->insertItem( QString("cd"), 1); 360// m_drop->insertItem( QString("cd"), 1);
351// connect(m_drop, SIGNAL(activated(int)), SLOT(drop_menu_activated(int))); 361// connect(m_drop, SIGNAL(activated(int)), SLOT(drop_menu_activated(int)));
352 362
353 // we need focus so that the auto-hide cursor feature works 363 // we need focus so that the auto-hide cursor feature works
354 setFocus(); 364 setFocus();
355 setFocusPolicy( WheelFocus ); 365 setFocusPolicy( WheelFocus );
356} 366}
357 367
358//FIXME: make proper destructor 368//FIXME: make proper destructor
359// Here's a start (David) 369// Here's a start (David)
360TEWidget::~TEWidget() 370TEWidget::~TEWidget()
361{ 371{
362 qApp->removeEventFilter( this ); 372 qApp->removeEventFilter( this );
363 if (image) free(image); 373 if (image) free(image);
364} 374}
365 375
366/* ------------------------------------------------------------------------- */ 376/* ------------------------------------------------------------------------- */
367/* */ 377/* */
368/* Display Operations */ 378/* Display Operations */
369/* */ 379/* */
370/* ------------------------------------------------------------------------- */ 380/* ------------------------------------------------------------------------- */
371 381
372/*! 382/*!
373 attributed string draw primitive 383 attributed string draw primitive
374*/ 384*/
375 385
376void TEWidget::drawAttrStr(QPainter &paint, QRect rect, 386void TEWidget::drawAttrStr(QPainter &paint, QRect rect,
377 QString& str, ca attr, BOOL pm, BOOL clear) 387 QString& str, ca attr, BOOL pm, BOOL clear)
378{ 388{
379 if (pm && color_table[attr.b].transparent) 389 if (pm && color_table[attr.b].transparent)
380 { 390 {
381 paint.setBackgroundMode( TransparentMode ); 391 paint.setBackgroundMode( TransparentMode );
382 if (clear) erase(rect); 392 if (clear) erase(rect);
383 } 393 }
384 else 394 else
385 { 395 {
386 if (blinking) 396 if (blinking)
387 paint.fillRect(rect, color_table[attr.b].color); 397 paint.fillRect(rect, color_table[attr.b].color);
388 else 398 else
389 { 399 {
390 paint.setBackgroundMode( OpaqueMode ); 400 paint.setBackgroundMode( OpaqueMode );
391 paint.setBackgroundColor( color_table[attr.b].color ); 401 paint.setBackgroundColor( color_table[attr.b].color );
392 } 402 }
393 } 403 }
394 404
395 if (color_table[attr.f].bold) 405 if (color_table[attr.f].bold)
396 paint.setPen(QColor( 0x8F, 0x00, 0x00 )); 406 paint.setPen(QColor( 0x8F, 0x00, 0x00 ));
397 else 407 else
398 paint.setPen(color_table[attr.f].color); 408 paint.setPen(color_table[attr.f].color);
399 409
400 paint.drawText(rect.x(),rect.y()+font_a, str); 410 paint.drawText(rect.x(),rect.y()+font_a, str);
401 411
402 if (attr.r & RE_UNDERLINE) 412 if (attr.r & RE_UNDERLINE)
403 paint.drawLine(rect.left(), rect.y()+font_a+1, rect.right(),rect.y()+font_a+1 ); 413 paint.drawLine(rect.left(), rect.y()+font_a+1, rect.right(),rect.y()+font_a+1 );
404} 414}
405 415
406/*! 416/*!
407 The image can only be set completely. 417 The image can only be set completely.
408 418
409 The size of the new image may or may not match the size of the widget. 419 The size of the new image may or may not match the size of the widget.
410*/ 420*/
411 421
412void TEWidget::setImage(const ca* const newimg, int lines, int columns) 422void TEWidget::setImage(const ca* const newimg, int lines, int columns)
413{ int y,x,len; 423{ int y,x,len;
414 const QPixmap* pm = backgroundPixmap(); 424 const QPixmap* pm = backgroundPixmap();
415 QPainter paint; 425 QPainter paint;
416 setUpdatesEnabled(FALSE); 426 setUpdatesEnabled(FALSE);
417 paint.begin( this ); 427 paint.begin( this );
418HCNT("setImage"); 428HCNT("setImage");
419 429
420 QPoint tL = contentsRect().topLeft(); 430 QPoint tL = contentsRect().topLeft();
421 int tLx = tL.x(); 431 int tLx = tL.x();
422 int tLy = tL.y(); 432 int tLy = tL.y();
423 hasBlinker = FALSE; 433 hasBlinker = FALSE;
424 434
425 int cf = -1; // undefined 435 int cf = -1; // undefined
426 int cb = -1; // undefined 436 int cb = -1; // undefined
427 int cr = -1; // undefined 437 int cr = -1; // undefined
428 438
429 int lins = QMIN(this->lines, QMAX(0,lines )); 439 int lins = QMIN(this->lines, QMAX(0,lines ));
430 int cols = QMIN(this->columns,QMAX(0,columns)); 440 int cols = QMIN(this->columns,QMAX(0,columns));
431 QChar *disstrU = new QChar[cols]; 441 QChar *disstrU = new QChar[cols];
432 for (y = 0; y < lins; y++) { 442 for (y = 0; y < lins; y++) {
433 const ca* lcl = &image[y*this->columns]; 443 const ca* lcl = &image[y*this->columns];
434 const ca* const ext = &newimg[y*columns]; 444 const ca* const ext = &newimg[y*columns];
435 if (!resizing) // not while resizing, we're expecting a paintEvent 445 if (!resizing) // not while resizing, we're expecting a paintEvent
436 for (x = 0; x < cols; x++) 446 for (x = 0; x < cols; x++)
437 { 447 {
438 hasBlinker |= (ext[x].r & RE_BLINK); 448 hasBlinker |= (ext[x].r & RE_BLINK);
439 if (ext[x] != lcl[x]) 449 if (ext[x] != lcl[x])
440 { 450 {
441 cr = ext[x].r; 451 cr = ext[x].r;
442 cb = ext[x].b; 452 cb = ext[x].b;
443 if (ext[x].f != cf) cf = ext[x].f; 453 if (ext[x].f != cf) cf = ext[x].f;
444 int lln = cols - x; 454 int lln = cols - x;
445 disstrU[0] = fontMap(ext[x+0].c); 455 disstrU[0] = fontMap(ext[x+0].c);
446 for (len = 1; len < lln; len++) 456 for (len = 1; len < lln; len++)
447 { 457 {
448 if (ext[x+len].f != cf || ext[x+len].b != cb || ext[x+len].r != cr || 458 if (ext[x+len].f != cf || ext[x+len].b != cb || ext[x+len].r != cr ||
449 ext[x+len] == lcl[x+len] ) 459 ext[x+len] == lcl[x+len] )
450 break; 460 break;
451 disstrU[len] = fontMap(ext[x+len].c); 461 disstrU[len] = fontMap(ext[x+len].c);
452 } 462 }
453 QString unistr(disstrU,len); 463 QString unistr(disstrU,len);
454 drawAttrStr(paint, 464 drawAttrStr(paint,
455 QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h), 465 QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
456 unistr, ext[x], pm != NULL, true); 466 unistr, ext[x], pm != NULL, true);
457 x += len - 1; 467 x += len - 1;
458 } 468 }
459 } 469 }
460 // finally, make `image' become `newimg'. 470 // finally, make `image' become `newimg'.
461 memcpy((void*)lcl,(const void*)ext,cols*sizeof(ca)); 471 memcpy((void*)lcl,(const void*)ext,cols*sizeof(ca));
462 } 472 }
463 drawFrame( &paint ); 473 drawFrame( &paint );
464 paint.end(); 474 paint.end();
465 setUpdatesEnabled(TRUE); 475 setUpdatesEnabled(TRUE);
466 if ( hasBlinker && !blinkT->isActive()) blinkT->start(1000); // 1000 ms 476 if ( hasBlinker && !blinkT->isActive()) blinkT->start(1000); // 1000 ms
467 if (!hasBlinker && blinkT->isActive()) { blinkT->stop(); blinking = FALSE; } 477 if (!hasBlinker && blinkT->isActive()) { blinkT->stop(); blinking = FALSE; }
468 delete [] disstrU; 478 delete [] disstrU;
469} 479}
470 480
471// paint Event //////////////////////////////////////////////////// 481// paint Event ////////////////////////////////////////////////////
472 482
473/*! 483/*!
474 The difference of this routine vs. the `setImage' is, 484 The difference of this routine vs. the `setImage' is,
475 that the drawing does not include a difference analysis 485 that the drawing does not include a difference analysis
476 between the old and the new image. Instead, the internal 486 between the old and the new image. Instead, the internal
477 image is used and the painting bound by the PaintEvent box. 487 image is used and the painting bound by the PaintEvent box.
478*/ 488*/
479 489
480void TEWidget::paintEvent( QPaintEvent* pe ) 490void TEWidget::paintEvent( QPaintEvent* pe )
481{ 491{
482 492
483//{ static int cnt = 0; printf("paint %d\n",cnt++); } 493//{ static int cnt = 0; printf("paint %d\n",cnt++); }
484 const QPixmap* pm = backgroundPixmap(); 494 const QPixmap* pm = backgroundPixmap();
485 QPainter paint; 495 QPainter paint;
486 setUpdatesEnabled(FALSE); 496 setUpdatesEnabled(FALSE);
487 paint.begin( this ); 497 paint.begin( this );
488 paint.setBackgroundMode( TransparentMode ); 498 paint.setBackgroundMode( TransparentMode );
489HCNT("paintEvent"); 499HCNT("paintEvent");
490 500
491 // Note that the actual widget size can be slightly larger 501 // Note that the actual widget size can be slightly larger
492 // that the image (the size is truncated towards the smaller 502 // that the image (the size is truncated towards the smaller
493 // number of characters in `resizeEvent'. The paint rectangle 503 // number of characters in `resizeEvent'. The paint rectangle
494 // can thus be larger than the image, but less then the size 504 // can thus be larger than the image, but less then the size
495 // of one character. 505 // of one character.
496 506
497 QRect rect = pe->rect().intersect(contentsRect()); 507 QRect rect = pe->rect().intersect(contentsRect());
498 508
499 QPoint tL = contentsRect().topLeft(); 509 QPoint tL = contentsRect().topLeft();
500 int tLx = tL.x(); 510 int tLx = tL.x();
501 int tLy = tL.y(); 511 int tLy = tL.y();
502 512
503 int lux = QMIN(columns-1, QMAX(0,(rect.left() - tLx - blX ) / font_w)); 513 int lux = QMIN(columns-1, QMAX(0,(rect.left() - tLx - blX ) / font_w));
504 int luy = QMIN(lines-1, QMAX(0,(rect.top() - tLy - bY ) / font_h)); 514 int luy = QMIN(lines-1, QMAX(0,(rect.top() - tLy - bY ) / font_h));
505 int rlx = QMIN(columns-1, QMAX(0,(rect.right() - tLx - blX ) / font_w)); 515 int rlx = QMIN(columns-1, QMAX(0,(rect.right() - tLx - blX ) / font_w));
506 int rly = QMIN(lines-1, QMAX(0,(rect.bottom() - tLy - bY ) / font_h)); 516 int rly = QMIN(lines-1, QMAX(0,(rect.bottom() - tLy - bY ) / font_h));
507 517
508 /* 518 /*
509 printf("paintEvent: %d..%d, %d..%d (%d..%d, %d..%d)\n",lux,rlx,luy,rly, 519 printf("paintEvent: %d..%d, %d..%d (%d..%d, %d..%d)\n",lux,rlx,luy,rly,
510 rect.left(), rect.right(), rect.top(), rect.bottom()); 520 rect.left(), rect.right(), rect.top(), rect.bottom());
511 */ 521 */
512 522
513 // if (pm != NULL && color_table[image->b].transparent) 523 // if (pm != NULL && color_table[image->b].transparent)
514 // erase(rect); 524 // erase(rect);
515 // BL: I have no idea why we need this, and it breaks the refresh. 525 // BL: I have no idea why we need this, and it breaks the refresh.
516 526
517 QChar *disstrU = new QChar[columns]; 527 QChar *disstrU = new QChar[columns];
518 for (int y = luy; y <= rly; y++) 528 for (int y = luy; y <= rly; y++)
519 for (int x = lux; x <= rlx; x++) 529 for (int x = lux; x <= rlx; x++)
520 { 530 {
521 int len = 1; 531 int len = 1;
522 disstrU[0] = fontMap(image[loc(x,y)].c); 532 disstrU[0] = fontMap(image[loc(x,y)].c);
523 int cf = image[loc(x,y)].f; 533 int cf = image[loc(x,y)].f;
524 int cb = image[loc(x,y)].b; 534 int cb = image[loc(x,y)].b;
525 int cr = image[loc(x,y)].r; 535 int cr = image[loc(x,y)].r;
526 while (x+len <= rlx && 536 while (x+len <= rlx &&
527 image[loc(x+len,y)].f == cf && 537 image[loc(x+len,y)].f == cf &&
528 image[loc(x+len,y)].b == cb && 538 image[loc(x+len,y)].b == cb &&
529 image[loc(x+len,y)].r == cr ) 539 image[loc(x+len,y)].r == cr )
530 { 540 {
531 disstrU[len] = fontMap(image[loc(x+len,y)].c); 541 disstrU[len] = fontMap(image[loc(x+len,y)].c);
532 len += 1; 542 len += 1;
533 } 543 }
534 QString unistr(disstrU,len); 544 QString unistr(disstrU,len);
535 drawAttrStr(paint, 545 drawAttrStr(paint,
536 QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h), 546 QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
537 unistr, image[loc(x,y)], pm != NULL, false); 547 unistr, image[loc(x,y)], pm != NULL, false);
538 x += len - 1; 548 x += len - 1;
539 } 549 }
540 delete [] disstrU; 550 delete [] disstrU;
541 drawFrame( &paint ); 551 drawFrame( &paint );
542 paint.end(); 552 paint.end();
543 setUpdatesEnabled(TRUE); 553 setUpdatesEnabled(TRUE);
544} 554}
545 555
546void TEWidget::blinkEvent() 556void TEWidget::blinkEvent()
547{ 557{
548 blinking = !blinking; 558 blinking = !blinking;
549 repaint(FALSE); 559 repaint(FALSE);
550} 560}
551 561
552/* ------------------------------------------------------------------------- */ 562/* ------------------------------------------------------------------------- */
553/* */ 563/* */
554/* Resizing */ 564/* Resizing */
555/* */ 565/* */
556/* ------------------------------------------------------------------------- */ 566/* ------------------------------------------------------------------------- */
557 567
558void TEWidget::resizeEvent(QResizeEvent* ev) 568void TEWidget::resizeEvent(QResizeEvent* ev)
559{ 569{
560// printf("resize: %d,%d\n",ev->size().width(),ev->size().height()); 570// printf("resize: %d,%d\n",ev->size().width(),ev->size().height());
561 //printf("approx: %d,%d\n",ev->size().width()/font_w,ev->size().height()/font_h); 571 //printf("approx: %d,%d\n",ev->size().width()/font_w,ev->size().height()/font_h);
562 //printf("leaves: %d,%d\n",ev->size().width()%font_w,ev->size().height()%font_h); 572 //printf("leaves: %d,%d\n",ev->size().width()%font_w,ev->size().height()%font_h);
563 //printf("curren: %d,%d\n",width(),height()); 573 //printf("curren: %d,%d\n",width(),height());
564HCNT("resizeEvent"); 574HCNT("resizeEvent");
565 575
566 // see comment in `paintEvent' concerning the rounding. 576 // see comment in `paintEvent' concerning the rounding.
567 //FIXME: could make a routine here; check width(),height() 577 //FIXME: could make a routine here; check width(),height()
568 assert(ev->size().width() == width()); 578 assert(ev->size().width() == width());
569 assert(ev->size().height() == height()); 579 assert(ev->size().height() == height());
570 580
571 propagateSize(); 581 propagateSize();
572} 582}
573 583
574void TEWidget::propagateSize() 584void TEWidget::propagateSize()
575{ 585{
576 ca* oldimg = image; 586 ca* oldimg = image;
577 int oldlin = lines; 587 int oldlin = lines;
578 int oldcol = columns; 588 int oldcol = columns;
579 makeImage(); 589 makeImage();
580 // we copy the old image to reduce flicker 590 // we copy the old image to reduce flicker
581 int lins = QMIN(oldlin,lines); 591 int lins = QMIN(oldlin,lines);
582 int cols = QMIN(oldcol,columns); 592 int cols = QMIN(oldcol,columns);
583 if (oldimg) 593 if (oldimg)
584 { 594 {
585 for (int lin = 0; lin < lins; lin++) 595 for (int lin = 0; lin < lins; lin++)
586 memcpy((void*)&image[columns*lin], 596 memcpy((void*)&image[columns*lin],
587 (void*)&oldimg[oldcol*lin],cols*sizeof(ca)); 597 (void*)&oldimg[oldcol*lin],cols*sizeof(ca));
588 free(oldimg); //FIXME: try new,delete 598 free(oldimg); //FIXME: try new,delete
589 } 599 }
590 else 600 else
591 clearImage(); 601 clearImage();
592 602
593 //NOTE: control flows from the back through the chest right into the eye. 603 //NOTE: control flows from the back through the chest right into the eye.
594 // `emu' will call back via `setImage'. 604 // `emu' will call back via `setImage'.
595 605
596 resizing = TRUE; 606 resizing = TRUE;
597 emit changedImageSizeSignal(lines, columns); // expose resizeEvent 607 emit changedImageSizeSignal(lines, columns); // expose resizeEvent
598 resizing = FALSE; 608 resizing = FALSE;
599} 609}
600 610
601/* ------------------------------------------------------------------------- */ 611/* ------------------------------------------------------------------------- */
602/* */ 612/* */
603/* Scrollbar */ 613/* Scrollbar */
604/* */ 614/* */
605/* ------------------------------------------------------------------------- */ 615/* ------------------------------------------------------------------------- */
606 616
607void TEWidget::scrollChanged(int) { 617void TEWidget::scrollChanged(int) {
608 emit changedHistoryCursor(scrollbar->value()); //expose 618 emit changedHistoryCursor(scrollbar->value()); //expose
609} 619}
610 620
611void TEWidget::hScrollChanged(int loc) { 621void TEWidget::hScrollChanged(int loc) {
612 hposition = loc; 622 hposition = loc;
613 propagateSize(); 623 propagateSize();
614 update(); 624 update();
615 625
616// emit changedHorzCursor( hScrollbar->value()); //expose 626// emit changedHorzCursor( hScrollbar->value()); //expose
617} 627}
618 628
619void TEWidget::setScroll(int cursor, int slines) 629void TEWidget::setScroll(int cursor, int slines)
620{ 630{
621 disconnect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int))); 631 disconnect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
622 scrollbar->setRange(0,slines); 632 scrollbar->setRange(0,slines);
623 scrollbar->setSteps(1,lines); 633 scrollbar->setSteps(1,lines);
624 scrollbar->setValue(cursor); 634 scrollbar->setValue(cursor);
625 connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int))); 635 connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
626} 636}
627 637
628void TEWidget::setScrollbarLocation(int loc) 638void TEWidget::setScrollbarLocation(int loc)
629{ 639{
630 if (scrollLoc == loc) return; // quickly 640 if (scrollLoc == loc) return; // quickly
631 scrollLoc = loc; 641 scrollLoc = loc;
632 propagateSize(); 642 propagateSize();
633 update(); 643 update();
634} 644}
635 645
636/* ------------------------------------------------------------------------- */ 646/* ------------------------------------------------------------------------- */
637/* */ 647/* */
638/* Mouse */ 648/* Mouse */
639/* */ 649/* */
640/* ------------------------------------------------------------------------- */ 650/* ------------------------------------------------------------------------- */
641 651
642/*! 652/*!
643 Three different operations can be performed using the mouse, and the 653 Three different operations can be performed using the mouse, and the
644 routines in this section serve all of them: 654 routines in this section serve all of them:
645 655
646 1) The press/release events are exposed to the application 656 1) The press/release events are exposed to the application
647 2) Marking (press and move left button) and Pasting (press middle button) 657 2) Marking (press and move left button) and Pasting (press middle button)
648 3) The right mouse button is used from the configuration menu 658 3) The right mouse button is used from the configuration menu
649 659
650 NOTE: During the marking process we attempt to keep the cursor within 660 NOTE: During the marking process we attempt to keep the cursor within
651 the bounds of the text as being displayed by setting the mouse position 661 the bounds of the text as being displayed by setting the mouse position
652 whenever the mouse has left the text area. 662 whenever the mouse has left the text area.
653 663
654 Two reasons to do so: 664 Two reasons to do so:
655 1) QT does not allow the `grabMouse' to confine-to the TEWidget. 665 1) QT does not allow the `grabMouse' to confine-to the TEWidget.
656 Thus a `XGrapPointer' would have to be used instead. 666 Thus a `XGrapPointer' would have to be used instead.
657 2) Even if so, this would not help too much, since the text area 667 2) Even if so, this would not help too much, since the text area
658 of the TEWidget is normally not identical with it's bounds. 668 of the TEWidget is normally not identical with it's bounds.
659 669
660 The disadvantage of the current handling is, that the mouse can visibly 670 The disadvantage of the current handling is, that the mouse can visibly
661 leave the bounds of the widget and is then moved back. Because of the 671 leave the bounds of the widget and is then moved back. Because of the
662 current construction, and the reasons mentioned above, we cannot do better 672 current construction, and the reasons mentioned above, we cannot do better
663 without changing the overall construction. 673 without changing the overall construction.
664*/ 674*/
665 675
666/*! 676/*!
667*/ 677*/
668 678
669void TEWidget::mousePressEvent(QMouseEvent* ev) 679void TEWidget::mousePressEvent(QMouseEvent* ev)
670{ 680{
671//printf("press [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button()); 681//printf("press [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button());
672 if ( !contentsRect().contains(ev->pos()) ) return; 682 if ( !contentsRect().contains(ev->pos()) ) return;
673 QPoint tL = contentsRect().topLeft(); 683 QPoint tL = contentsRect().topLeft();
674 int tLx = tL.x(); 684 int tLx = tL.x();
675 int tLy = tL.y(); 685 int tLy = tL.y();
676 686
677 word_selection_mode = FALSE; 687 word_selection_mode = FALSE;
678 688
679//printf("press top left [%d,%d] by=%d\n",tLx,tLy, bY); 689//printf("press top left [%d,%d] by=%d\n",tLx,tLy, bY);
680 if ( ev->button() == LeftButton) 690 if ( ev->button() == LeftButton)
681 { 691 {
682 QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h); 692 QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
683 693
684 if ( ev->state() & ControlButton ) preserve_line_breaks = FALSE ; 694 if ( ev->state() & ControlButton ) preserve_line_breaks = FALSE ;
685 695
686 if (mouse_marks || (ev->state() & ShiftButton)) 696 if (mouse_marks || (ev->state() & ShiftButton))
687 { 697 {
688 emit clearSelectionSignal(); 698 emit clearSelectionSignal();
689 iPntSel = pntSel = pos; 699 iPntSel = pntSel = pos;
690 actSel = 1; // left mouse button pressed but nothing selected yet. 700 actSel = 1; // left mouse button pressed but nothing selected yet.
691 grabMouse( /*crossCursor*/ ); // handle with care! 701 grabMouse( /*crossCursor*/ ); // handle with care!
692 } 702 }
693 else 703 else
694 { 704 {
695 emit mouseSignal( 0, pos.x() + 1, pos.y() + 1 ); // left button 705 emit mouseSignal( 0, pos.x() + 1, pos.y() + 1 ); // left button
696 } 706 }
697 } 707 }
698 if ( ev->button() == MidButton ) 708 if ( ev->button() == MidButton )
699 { 709 {
700 emitSelection(); 710 emitSelection();
701 } 711 }
702 if ( ev->button() == RightButton ) // Configure 712 if ( ev->button() == RightButton ) // Configure
703 { 713 {
704 emit configureRequest( this, ev->state()&(ShiftButton|ControlButton), ev->x(), ev->y() ); 714 emit configureRequest( this, ev->state()&(ShiftButton|ControlButton), ev->x(), ev->y() );
705 } 715 }
706} 716}
707 717
708void TEWidget::mouseMoveEvent(QMouseEvent* ev) 718void TEWidget::mouseMoveEvent(QMouseEvent* ev)
709{ 719{
710 // for auto-hiding the cursor, we need mouseTracking 720 // for auto-hiding the cursor, we need mouseTracking
711 if (ev->state() == NoButton ) return; 721 if (ev->state() == NoButton ) return;
712 722
713 if (actSel == 0) return; 723 if (actSel == 0) return;
714 724
715 // don't extend selection while pasting 725 // don't extend selection while pasting
716 if (ev->state() & MidButton) return; 726 if (ev->state() & MidButton) return;
717 727
718 //if ( !contentsRect().contains(ev->pos()) ) return; 728 //if ( !contentsRect().contains(ev->pos()) ) return;
719 QPoint tL = contentsRect().topLeft(); 729 QPoint tL = contentsRect().topLeft();
720 int tLx = tL.x(); 730 int tLx = tL.x();
721 int tLy = tL.y(); 731 int tLy = tL.y();
722 int scroll = scrollbar->value(); 732 int scroll = scrollbar->value();
723// int hScroll = hScrollbar->value(); 733// int hScroll = hScrollbar->value();
724 734
725 // we're in the process of moving the mouse with the left button pressed 735 // we're in the process of moving the mouse with the left button pressed
726 // the mouse cursor will kept catched within the bounds of the text in 736 // the mouse cursor will kept catched within the bounds of the text in
727 // this widget. 737 // this widget.
728 738
729 // Adjust position within text area bounds. See FIXME above. 739 // Adjust position within text area bounds. See FIXME above.
730 QPoint pos = ev->pos(); 740 QPoint pos = ev->pos();
731 if ( pos.x() < tLx+blX ) pos.setX( tLx+blX ); 741 if ( pos.x() < tLx+blX ) pos.setX( tLx+blX );
732 if ( pos.x() > tLx+blX+columns*font_w-1 ) pos.setX( tLx+blX+columns*font_w ); 742 if ( pos.x() > tLx+blX+columns*font_w-1 ) pos.setX( tLx+blX+columns*font_w );
733 if ( pos.y() < tLy+bY ) pos.setY( tLy+bY ); 743 if ( pos.y() < tLy+bY ) pos.setY( tLy+bY );
734 if ( pos.y() > tLy+bY+lines*font_h-1 ) pos.setY( tLy+bY+lines*font_h-1 ); 744 if ( pos.y() > tLy+bY+lines*font_h-1 ) pos.setY( tLy+bY+lines*font_h-1 );
735 // check if we produce a mouse move event by this 745 // check if we produce a mouse move event by this
736 if ( pos != ev->pos() ) cursor().setPos(mapToGlobal(pos)); 746 if ( pos != ev->pos() ) cursor().setPos(mapToGlobal(pos));
737 747
738 if ( pos.y() == tLy+bY+lines*font_h-1 ) 748 if ( pos.y() == tLy+bY+lines*font_h-1 )
739 { 749 {
740 scrollbar->setValue(scrollbar->value()+yMouseScroll); // scrollforward 750 scrollbar->setValue(scrollbar->value()+yMouseScroll); // scrollforward
741 } 751 }
742 if ( pos.y() == tLy+bY ) 752 if ( pos.y() == tLy+bY )
743 { 753 {
744 scrollbar->setValue(scrollbar->value()-yMouseScroll); // scrollback 754 scrollbar->setValue(scrollbar->value()-yMouseScroll); // scrollback
745 } 755 }
746 756
747 QPoint here = QPoint((pos.x()-tLx-blX)/font_w,(pos.y()-tLy-bY)/font_h); 757 QPoint here = QPoint((pos.x()-tLx-blX)/font_w,(pos.y()-tLy-bY)/font_h);
748 QPoint ohere; 758 QPoint ohere;
749 bool swapping = FALSE; 759 bool swapping = FALSE;
750 760
751 if ( word_selection_mode ) 761 if ( word_selection_mode )
752 { 762 {
753 // Extend to word boundaries 763 // Extend to word boundaries
754 int i; 764 int i;
755 int selClass; 765 int selClass;
756 766
757 bool left_not_right = ( here.y() < iPntSel.y() || 767 bool left_not_right = ( here.y() < iPntSel.y() ||
758 here.y() == iPntSel.y() && here.x() < iPntSel.x() ); 768 here.y() == iPntSel.y() && here.x() < iPntSel.x() );
759 bool old_left_not_right = ( pntSel.y() < iPntSel.y() || 769 bool old_left_not_right = ( pntSel.y() < iPntSel.y() ||
760 pntSel.y() == iPntSel.y() && pntSel.x() < iPntSel.x() ); 770 pntSel.y() == iPntSel.y() && pntSel.x() < iPntSel.x() );
761 swapping = left_not_right != old_left_not_right; 771 swapping = left_not_right != old_left_not_right;
762 772
763 // Find left (left_not_right ? from here : from start) 773 // Find left (left_not_right ? from here : from start)
764 QPoint left = left_not_right ? here : iPntSel; 774 QPoint left = left_not_right ? here : iPntSel;
765 i = loc(left.x(),left.y()); 775 i = loc(left.x(),left.y());
766 selClass = charClass(image[i].c); 776 selClass = charClass(image[i].c);
767 while ( left.x() > 0 && charClass(image[i-1].c) == selClass ) 777 while ( left.x() > 0 && charClass(image[i-1].c) == selClass )
768 { i--; left.rx()--; } 778 { i--; left.rx()--; }
769 779
770 // Find left (left_not_right ? from start : from here) 780 // Find left (left_not_right ? from start : from here)
771 QPoint right = left_not_right ? iPntSel : here; 781 QPoint right = left_not_right ? iPntSel : here;
772 i = loc(right.x(),right.y()); 782 i = loc(right.x(),right.y());
773 selClass = charClass(image[i].c); 783 selClass = charClass(image[i].c);
774 while ( right.x() < columns-1 && charClass(image[i+1].c) == selClass ) 784 while ( right.x() < columns-1 && charClass(image[i+1].c) == selClass )
775 { i++; right.rx()++; } 785 { i++; right.rx()++; }
776 786
777 // Pick which is start (ohere) and which is extension (here) 787 // Pick which is start (ohere) and which is extension (here)
778 if ( left_not_right ) 788 if ( left_not_right )
779 { 789 {
780 here = left; ohere = right; 790 here = left; ohere = right;
781 } 791 }
782 else 792 else
783 { 793 {
784 here = right; ohere = left; 794 here = right; ohere = left;
785 } 795 }
786 } 796 }
787 797
788 if (here == pntSel && scroll == scrollbar->value()) return; // not moved 798 if (here == pntSel && scroll == scrollbar->value()) return; // not moved
789 799
790 if ( word_selection_mode ) { 800 if ( word_selection_mode ) {
791 if ( actSel < 2 || swapping ) { 801 if ( actSel < 2 || swapping ) {
792 emit beginSelectionSignal( ohere.x(), ohere.y() ); 802 emit beginSelectionSignal( ohere.x(), ohere.y() );
793 } 803 }
794 } else if ( actSel < 2 ) { 804 } else if ( actSel < 2 ) {
795 emit beginSelectionSignal( pntSel.x(), pntSel.y() ); 805 emit beginSelectionSignal( pntSel.x(), pntSel.y() );
796 } 806 }
797 807
798 actSel = 2; // within selection 808 actSel = 2; // within selection
799 pntSel = here; 809 pntSel = here;
800 emit extendSelectionSignal( here.x(), here.y() ); 810 emit extendSelectionSignal( here.x(), here.y() );
801} 811}
802 812
803void TEWidget::mouseReleaseEvent(QMouseEvent* ev) 813void TEWidget::mouseReleaseEvent(QMouseEvent* ev)
804{ 814{
805//printf("release [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button()); 815//printf("release [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button());
806 if ( ev->button() == LeftButton) 816 if ( ev->button() == LeftButton)
807 { 817 {
808 if ( actSel > 1 ) emit endSelectionSignal(preserve_line_breaks); 818 if ( actSel > 1 ) emit endSelectionSignal(preserve_line_breaks);
809 preserve_line_breaks = TRUE; 819 preserve_line_breaks = TRUE;
810 actSel = 0; 820 actSel = 0;
811 821
812 //FIXME: emits a release event even if the mouse is 822 //FIXME: emits a release event even if the mouse is
813 // outside the range. The procedure used in `mouseMoveEvent' 823 // outside the range. The procedure used in `mouseMoveEvent'
814 // applies here, too. 824 // applies here, too.
815 825
816 QPoint tL = contentsRect().topLeft(); 826 QPoint tL = contentsRect().topLeft();
817 int tLx = tL.x(); 827 int tLx = tL.x();
818 int tLy = tL.y(); 828 int tLy = tL.y();
819 829
820 if (!mouse_marks && !(ev->state() & ShiftButton)) 830 if (!mouse_marks && !(ev->state() & ShiftButton))
821 emit mouseSignal( 3, // release 831 emit mouseSignal( 3, // release
822 (ev->x()-tLx-blX)/font_w + 1, 832 (ev->x()-tLx-blX)/font_w + 1,
823 (ev->y()-tLy-bY)/font_h + 1 ); 833 (ev->y()-tLy-bY)/font_h + 1 );
824 releaseMouse(); 834 releaseMouse();
825 } 835 }
826} 836}
827 837
828void TEWidget::mouseDoubleClickEvent(QMouseEvent* ev) 838void TEWidget::mouseDoubleClickEvent(QMouseEvent* ev)
829{ 839{
830 if ( ev->button() != LeftButton) return; 840 if ( ev->button() != LeftButton) return;
831 841
832 QPoint tL = contentsRect().topLeft(); 842 QPoint tL = contentsRect().topLeft();
833 int tLx = tL.x(); 843 int tLx = tL.x();
834 int tLy = tL.y(); 844 int tLy = tL.y();
835 QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h); 845 QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
836 846
837 // pass on double click as two clicks. 847 // pass on double click as two clicks.
838 if (!mouse_marks && !(ev->state() & ShiftButton)) 848 if (!mouse_marks && !(ev->state() & ShiftButton))
839 { 849 {
840 emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button 850 emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button
841 emit mouseSignal( 3, pos.x()+1, pos.y()+1 ); // release 851 emit mouseSignal( 3, pos.x()+1, pos.y()+1 ); // release
842 emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button 852 emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button
843 return; 853 return;
844 } 854 }
845 855
846 856
847 emit clearSelectionSignal(); 857 emit clearSelectionSignal();
848 QPoint bgnSel = pos; 858 QPoint bgnSel = pos;
849 QPoint endSel = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h); 859 QPoint endSel = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
850 int i = loc(bgnSel.x(),bgnSel.y()); 860 int i = loc(bgnSel.x(),bgnSel.y());
851 iPntSel = bgnSel; 861 iPntSel = bgnSel;
852 862
853 word_selection_mode = TRUE; 863 word_selection_mode = TRUE;
854 864
855 // find word boundaries... 865 // find word boundaries...
856 int selClass = charClass(image[i].c); 866 int selClass = charClass(image[i].c);
857 { 867 {
858 // set the start... 868 // set the start...
859 int x = bgnSel.x(); 869 int x = bgnSel.x();
860 while ( x > 0 && charClass(image[i-1].c) == selClass ) 870 while ( x > 0 && charClass(image[i-1].c) == selClass )
861 { i--; x--; } 871 { i--; x--; }
862 bgnSel.setX(x); 872 bgnSel.setX(x);
863 emit beginSelectionSignal( bgnSel.x(), bgnSel.y() ); 873 emit beginSelectionSignal( bgnSel.x(), bgnSel.y() );
864 874
865 // set the end... 875 // set the end...
866 i = loc( endSel.x(), endSel.y() ); 876 i = loc( endSel.x(), endSel.y() );
867 x = endSel.x(); 877 x = endSel.x();
868 while( x < columns-1 && charClass(image[i+1].c) == selClass ) 878 while( x < columns-1 && charClass(image[i+1].c) == selClass )
869 { i++; x++ ; } 879 { i++; x++ ; }
870 endSel.setX(x); 880 endSel.setX(x);
871 actSel = 2; // within selection 881 actSel = 2; // within selection
872 emit extendSelectionSignal( endSel.x(), endSel.y() ); 882 emit extendSelectionSignal( endSel.x(), endSel.y() );
873 emit endSelectionSignal(preserve_line_breaks); 883 emit endSelectionSignal(preserve_line_breaks);
874 preserve_line_breaks = TRUE; 884 preserve_line_breaks = TRUE;
875 } 885 }
876} 886}
877 887
878void TEWidget::focusInEvent( QFocusEvent * ) 888void TEWidget::focusInEvent( QFocusEvent * )
879{ 889{
880 890
881 // do nothing, to prevent repainting 891 // do nothing, to prevent repainting
882} 892}
883 893
884 894
885void TEWidget::focusOutEvent( QFocusEvent * ) 895void TEWidget::focusOutEvent( QFocusEvent * )
886{ 896{
887 // do nothing, to prevent repainting 897 // do nothing, to prevent repainting
888} 898}
889 899
890bool TEWidget::focusNextPrevChild( bool next ) 900bool TEWidget::focusNextPrevChild( bool next )
891{ 901{
892 if (next) 902 if (next)
893 return false; // This disables changing the active part in konqueror 903 return false; // This disables changing the active part in konqueror
894 // when pressing Tab 904 // when pressing Tab
895 return QFrame::focusNextPrevChild( next ); 905 return QFrame::focusNextPrevChild( next );
896} 906}
897 907
898 908
899int TEWidget::charClass(char ch) const 909int TEWidget::charClass(char ch) const
900{ 910{
901 // This might seem like overkill, but imagine if ch was a Unicode 911 // This might seem like overkill, but imagine if ch was a Unicode
902 // character (Qt 2.0 QChar) - it might then be sensible to separate 912 // character (Qt 2.0 QChar) - it might then be sensible to separate
903 // the different language ranges, etc. 913 // the different language ranges, etc.
904 914
905 if ( isspace(ch) ) return ' '; 915 if ( isspace(ch) ) return ' ';
906 916
907 static const char *word_characters = ":@-./_~"; 917 static const char *word_characters = ":@-./_~";
908 if ( isalnum(ch) || strchr(word_characters, ch) ) 918 if ( isalnum(ch) || strchr(word_characters, ch) )
909 return 'a'; 919 return 'a';
910 920
911 // Everything else is weird 921 // Everything else is weird
912 return 1; 922 return 1;
913} 923}
914 924
915void TEWidget::setMouseMarks(bool on) 925void TEWidget::setMouseMarks(bool on)
916{ 926{
917 mouse_marks = on; 927 mouse_marks = on;
918 setCursor( mouse_marks ? ibeamCursor : arrowCursor ); 928 setCursor( mouse_marks ? ibeamCursor : arrowCursor );
919} 929}
920 930
921/* ------------------------------------------------------------------------- */ 931/* ------------------------------------------------------------------------- */
922/* */ 932/* */
923/* Clipboard */ 933/* Clipboard */
924/* */ 934/* */
925/* ------------------------------------------------------------------------- */ 935/* ------------------------------------------------------------------------- */
926 936
927#undef KeyPress 937#undef KeyPress
928 938
929void TEWidget::emitSelection() 939void TEWidget::emitSelection()
930// Paste Clipboard by simulating keypress events 940// Paste Clipboard by simulating keypress events
931{ 941{
932#ifndef QT_NO_CLIPBOARD 942#ifndef QT_NO_CLIPBOARD
933 QString text = QApplication::clipboard()->text(); 943 QString text = QApplication::clipboard()->text();
934 //qDebug(text); 944 //qDebug(text);
935 if ( ! text.isNull()) 945 if ( ! text.isNull())
936 { 946 {
937 text.replace(QRegExp("\n"), "\r"); 947 text.replace(QRegExp("\n"), "\r");
938 QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text); 948 QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text);
939 emit keyPressedSignal(&e); // expose as a big fat keypress event 949 emit keyPressedSignal(&e); // expose as a big fat keypress event
940 emit clearSelectionSignal(); 950 emit clearSelectionSignal();
941 } 951 }
942#endif 952#endif
943} 953}
944 954
945void TEWidget::emitText(QString text) 955void TEWidget::emitText(QString text)
946{ 956{
947 QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text); 957 QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text);
948 emit keyPressedSignal(&e); // expose as a big fat keypress event 958 emit keyPressedSignal(&e); // expose as a big fat keypress event
949} 959}
950 960
951void TEWidget::pasteClipboard( ) 961void TEWidget::pasteClipboard( )
952{ 962{
953 emitSelection(); 963 emitSelection();
954} 964}
955 965
956void TEWidget::setSelection(const QString& t) 966void TEWidget::setSelection(const QString& t)
957{ 967{
958#ifndef QT_NO_CLIPBOARD 968#ifndef QT_NO_CLIPBOARD
959 // Disconnect signal while WE set the clipboard 969 // Disconnect signal while WE set the clipboard
960 QObject *cb = QApplication::clipboard(); 970 QObject *cb = QApplication::clipboard();
961 QObject::disconnect( cb, SIGNAL(dataChanged()), 971 QObject::disconnect( cb, SIGNAL(dataChanged()),
962 this, SLOT(onClearSelection()) ); 972 this, SLOT(onClearSelection()) );
963 973
964 QApplication::clipboard()->setText(t); 974 QApplication::clipboard()->setText(t);
965 975
966 QObject::connect( cb, SIGNAL(dataChanged()), 976 QObject::connect( cb, SIGNAL(dataChanged()),
967 this, SLOT(onClearSelection()) ); 977 this, SLOT(onClearSelection()) );
968#endif 978#endif
969} 979}
970 980
971void TEWidget::onClearSelection() 981void TEWidget::onClearSelection()
972{ 982{
973 emit clearSelectionSignal(); 983 emit clearSelectionSignal();
974} 984}
975 985
976/* ------------------------------------------------------------------------- */ 986/* ------------------------------------------------------------------------- */
977/* */ 987/* */
978/* Keyboard */ 988/* Keyboard */
979/* */ 989/* */
980/* ------------------------------------------------------------------------- */ 990/* ------------------------------------------------------------------------- */
981 991
982//FIXME: an `eventFilter' has been installed instead of a `keyPressEvent' 992//FIXME: an `eventFilter' has been installed instead of a `keyPressEvent'
983// due to a bug in `QT' or the ignorance of the author to prevent 993// due to a bug in `QT' or the ignorance of the author to prevent
984// repaint events being emitted to the screen whenever one leaves 994// repaint events being emitted to the screen whenever one leaves
985// or reenters the screen to/from another application. 995// or reenters the screen to/from another application.
986// 996//
987// Troll says one needs to change focusInEvent() and focusOutEvent(), 997// Troll says one needs to change focusInEvent() and focusOutEvent(),
988// which would also let you have an in-focus cursor and an out-focus 998// which would also let you have an in-focus cursor and an out-focus
989// cursor like xterm does. 999// cursor like xterm does.
990 1000
991// for the auto-hide cursor feature, I added empty focusInEvent() and 1001// for the auto-hide cursor feature, I added empty focusInEvent() and
992// focusOutEvent() so that update() isn't called. 1002// focusOutEvent() so that update() isn't called.
993// For auto-hide, we need to get keypress-events, but we only get them when 1003// For auto-hide, we need to get keypress-events, but we only get them when
994// we have focus. 1004// we have focus.
995 1005
996void TEWidget::doScroll(int lines) 1006void TEWidget::doScroll(int lines)
997{ 1007{
998 scrollbar->setValue(scrollbar->value()+lines); 1008 scrollbar->setValue(scrollbar->value()+lines);
999} 1009}
1000 1010
1001void TEWidget::doHScroll(int lines) { 1011void TEWidget::doHScroll(int lines) {
1002 hScrollbar->setValue( hScrollbar->value()+lines); 1012 hScrollbar->setValue( hScrollbar->value()+lines);
1003} 1013}
1004 1014
1005bool TEWidget::eventFilter( QObject *obj, QEvent *e ) 1015bool TEWidget::eventFilter( QObject *obj, QEvent *e )
1006{ 1016{
1007 if ( (e->type() == QEvent::Accel || 1017 if ( (e->type() == QEvent::Accel ||
1008 e->type() == QEvent::AccelAvailable ) && qApp->focusWidget() == this ) { 1018 e->type() == QEvent::AccelAvailable ) && qApp->focusWidget() == this ) {
1009 static_cast<QKeyEvent *>( e )->ignore(); 1019 static_cast<QKeyEvent *>( e )->ignore();
1010 return true; 1020 return true;
1011 } 1021 }
1012 if ( obj != this /* when embedded */ && obj != parent() /* when standalone */ ) 1022 if ( obj != this /* when embedded */ && obj != parent() /* when standalone */ )
1013 return FALSE; // not us 1023 return FALSE; // not us
1014 if ( e->type() == QEvent::Wheel) { 1024 if ( e->type() == QEvent::Wheel) {
1015 QApplication::sendEvent(scrollbar, e); 1025 QApplication::sendEvent(scrollbar, e);
1016 } 1026 }
1017 1027
1018#ifdef FAKE_CTRL_AND_ALT 1028#ifdef FAKE_CTRL_AND_ALT
1019 static bool control = FALSE; 1029 static bool control = FALSE;
1020 static bool alt = FALSE; 1030 static bool alt = FALSE;
1021// qDebug(" Has a keyboard with no CTRL and ALT keys, but we fake it:"); 1031// qDebug(" Has a keyboard with no CTRL and ALT keys, but we fake it:");
1022 bool dele=FALSE; 1032 bool dele=FALSE;
1033
1023 if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease ) { 1034 if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease ) {
1024 QKeyEvent* ke = (QKeyEvent*)e; 1035 QKeyEvent* ke = (QKeyEvent*)e;
1025 bool keydown = e->type() == QEvent::KeyPress || ke->isAutoRepeat(); 1036 bool keydown = e->type() == QEvent::KeyPress || ke->isAutoRepeat();
1026 switch (ke->key()) { 1037 switch (ke->key()) {
1027 case Key_F9: // let this be "Control" 1038 case Key_F9: // let this be "Control"
1028 control = keydown; 1039 control = keydown;
1029 e = new QKeyEvent(QEvent::KeyPress, Key_Control, 0, ke->state()); 1040 e = new QKeyEvent(QEvent::KeyPress, Key_Control, 0, ke->state());
1030 dele=TRUE; 1041 dele=TRUE;
1031 break; 1042 break;
1032 case Key_F13: // let this be "Alt" 1043 case Key_F13: // let this be "Alt"
1033 alt = keydown; 1044 alt = keydown;
1034 e = new QKeyEvent(QEvent::KeyPress, Key_Alt, 0, ke->state()); 1045 e = new QKeyEvent(QEvent::KeyPress, Key_Alt, 0, ke->state());
1035 dele=TRUE; 1046 dele=TRUE;
1036 break; 1047 break;
1037 default: 1048 default:
1038 if ( control ) { 1049 if ( control ) {
1039 int a = toupper(ke->ascii())-64; 1050 int a = toupper(ke->ascii())-64;
1040 if ( a >= 0 && a < ' ' ) { 1051 if ( a >= 0 && a < ' ' ) {
1041 e = new QKeyEvent(e->type(), ke->key(), 1052 e = new QKeyEvent(e->type(), ke->key(),
1042 a, ke->state()|ControlButton, QChar(a,0)); 1053 a, ke->state()|ControlButton, QChar(a,0));
1043 dele=TRUE; 1054 dele=TRUE;
1044 } 1055 }
1045 } 1056 }
1046 if ( alt ) { 1057 if ( alt ) {
1047 e = new QKeyEvent(e->type(), ke->key(), 1058 e = new QKeyEvent(e->type(), ke->key(),
1048 ke->ascii(), ke->state()|AltButton, ke->text()); 1059 ke->ascii(), ke->state()|AltButton, ke->text());
1049 dele=TRUE; 1060 dele=TRUE;
1050 } 1061 }
1051 } 1062 }
1052 } 1063 }
1053#endif 1064#endif
1054 1065
1055 if ( e->type() == QEvent::KeyPress ) { 1066 if ( e->type() == QEvent::KeyPress ) {
1056 QKeyEvent* ke = (QKeyEvent*)e; 1067 QKeyEvent* ke = (QKeyEvent*)e;
1057 actSel=0; // Key stroke implies a screen update, so TEWidget won't 1068 actSel=0; // Key stroke implies a screen update, so TEWidget won't
1058 // know where the current selection is. 1069 // know where the current selection is.
1059 1070
1060// qDebug("key pressed is 0x%x, ascii is 0x%x, state %d", ke->key(), ke->ascii(), ke->state()); 1071// qDebug("key pressed is 0x%x, ascii is 0x%x, state %d", ke->key(), ke->ascii(), ke->state());
1061 1072 if(ke->key() == Key_Escape) {
1073 qDebug("key pressed is 0x%x, ascii is 0x%x, state %d", ke->key(), ke->ascii(), ke->state());
1074
1075 }
1076
1062 if( ke->state() == ShiftButton && ke->key() == Key_Tab) { 1077 if( ke->state() == ShiftButton && ke->key() == Key_Tab) {
1063 //lets hardcode this sucker 1078 //lets hardcode this sucker
1064 1079
1065// qDebug("key pressed 2 is 0x%x", ke->key()); 1080// qDebug("key pressed 2 is 0x%x", ke->key());
1066 emitText("\\"); // expose 1081 emitText("\\"); // expose
1067 } 1082 }
1068 else if( ke->state() == ControlButton && ke->key() == Key_V) { 1083 else if( ke->state() == ControlButton && ke->key() == Key_V) {
1069 pasteClipboard(); 1084 pasteClipboard();
1070 } 1085 }
1071// else if( ke->state() == ControlButton && ke->key() == Key_C) { 1086// else if( ke->state() == ControlButton && ke->key() == Key_C) {
1072// pasteClipboard(); 1087// pasteClipboard();
1073// } 1088// }
1074 else 1089 else
1075 emit keyPressedSignal(ke); // expose 1090 emit keyPressedSignal(ke); // expose
1076 ke->accept(); 1091 ke->accept();
1077#ifdef FAKE_CTRL_AND_ALT 1092#ifdef FAKE_CTRL_AND_ALT
1078 if ( dele ) delete e; 1093 if ( dele ) delete e;
1079#endif 1094#endif
1080 return true; // stop the event 1095 return true; // stop the event
1081 } 1096 }
1082 if ( e->type() == QEvent::Enter ) { 1097 if ( e->type() == QEvent::Enter ) {
1083 QObject::disconnect( (QObject*)cb, SIGNAL(dataChanged()), 1098 QObject::disconnect( (QObject*)cb, SIGNAL(dataChanged()),
1084 this, SLOT(onClearSelection()) ); 1099 this, SLOT(onClearSelection()) );
1085 } 1100 }
1086 if ( e->type() == QEvent::Leave ) { 1101 if ( e->type() == QEvent::Leave ) {
1087 QObject::connect( (QObject*)cb, SIGNAL(dataChanged()), 1102 QObject::connect( (QObject*)cb, SIGNAL(dataChanged()),
1088 this, SLOT(onClearSelection()) ); 1103 this, SLOT(onClearSelection()) );
1089 } 1104 }
1090 return QFrame::eventFilter( obj, e ); 1105 return QFrame::eventFilter( obj, e );
1091} 1106}
1092 1107
1093/* ------------------------------------------------------------------------- */ 1108/* ------------------------------------------------------------------------- */
1094/* */ 1109/* */
1095/* Frame */ 1110/* Frame */
1096/* */ 1111/* */
1097/* ------------------------------------------------------------------------- */ 1112/* ------------------------------------------------------------------------- */
1098 1113
1099void TEWidget::frameChanged() 1114void TEWidget::frameChanged()
1100{ 1115{
1101 propagateSize(); 1116 propagateSize();
1102 update(); 1117 update();
1103} 1118}
1104 1119
1105/* ------------------------------------------------------------------------- */ 1120/* ------------------------------------------------------------------------- */
1106/* */ 1121/* */
1107/* Sound */ 1122/* Sound */
1108/* */ 1123/* */
1109/* ------------------------------------------------------------------------- */ 1124/* ------------------------------------------------------------------------- */
1110 1125
1111void TEWidget::Bell() 1126void TEWidget::Bell()
1112{ 1127{
1113//#ifdef QT_QWS_SL5XXX 1128//#ifdef QT_QWS_SL5XXX
1114//# ifndef QT_NO_COP 1129//# ifndef QT_NO_COP
1115 if(useBeep) 1130 if(useBeep)
1116 QCopEnvelope( "QPE/TaskBar", "soundAlarm()" ); 1131 QCopEnvelope( "QPE/TaskBar", "soundAlarm()" );
1117 1132
1118//# endif 1133//# endif
1119//#else 1134//#else
1120//# ifndef QT_NO_SOUND 1135//# ifndef QT_NO_SOUND
1121// QSound::play(Resource::findSound("alarm")); 1136// QSound::play(Resource::findSound("alarm"));
1122//# endif 1137//# endif
1123//#endif 1138//#endif
1124 1139
1125// QApplication::beep(); 1140// QApplication::beep();
1126} 1141}
1127 1142
1128/* ------------------------------------------------------------------------- */ 1143/* ------------------------------------------------------------------------- */
1129/* */ 1144/* */
1130/* Auxiluary */ 1145/* Auxiluary */
1131/* */ 1146/* */
1132/* ------------------------------------------------------------------------- */ 1147/* ------------------------------------------------------------------------- */
1133 1148
1134void TEWidget::clearImage() 1149void TEWidget::clearImage()
1135// initialize the image 1150// initialize the image
1136// for internal use only 1151// for internal use only
1137{ 1152{
1138 for (int y = 0; y < lines; y++) 1153 for (int y = 0; y < lines; y++)
1139 for (int x = 0; x < columns; x++) 1154 for (int x = 0; x < columns; x++)
1140 { 1155 {
1141 image[loc(x,y)].c = 0xff; //' '; 1156 image[loc(x,y)].c = 0xff; //' ';
1142 image[loc(x,y)].f = 0xff; //DEFAULT_FORE_COLOR; 1157 image[loc(x,y)].f = 0xff; //DEFAULT_FORE_COLOR;
1143 image[loc(x,y)].b = 0xff; //DEFAULT_BACK_COLOR; 1158 image[loc(x,y)].b = 0xff; //DEFAULT_BACK_COLOR;
1144 image[loc(x,y)].r = 0xff; //DEFAULT_RENDITION; 1159 image[loc(x,y)].r = 0xff; //DEFAULT_RENDITION;
1145 } 1160 }
1146} 1161}
1147 1162
1148// Create Image /////////////////////////////////////////////////////// 1163// Create Image ///////////////////////////////////////////////////////
1149 1164
1150void TEWidget::calcGeometry() 1165void TEWidget::calcGeometry()
1151{ 1166{
1152 int showhscrollbar = 1; 1167 int showhscrollbar = 1;
1153 int hwidth = 0; 1168 int hwidth = 0;
1154 int dcolumns; 1169 int dcolumns;
1155 Config cfg("Konsole"); 1170 Config cfg("Konsole");
1156 cfg.setGroup("ScrollBar"); 1171 cfg.setGroup("ScrollBar");
1157 useHorzScroll=cfg.readBoolEntry("HorzScroll",0); 1172 useHorzScroll=cfg.readBoolEntry("HorzScroll",0);
1158 1173
1159 if(vcolumns == 0) showhscrollbar = 0; 1174 if(vcolumns == 0) showhscrollbar = 0;
1160 if(showhscrollbar == 1) hwidth = QApplication::style().scrollBarExtent().width(); 1175 if(showhscrollbar == 1) hwidth = QApplication::style().scrollBarExtent().width();
1161 1176
1162 scrollbar->resize(QApplication::style().scrollBarExtent().width(), 1177 scrollbar->resize(QApplication::style().scrollBarExtent().width(),
1163 contentsRect().height() - hwidth); 1178 contentsRect().height() - hwidth);
1164 1179
1165 switch(scrollLoc) { 1180 switch(scrollLoc) {
1166 case SCRNONE : 1181 case SCRNONE :
1167 columns = ( contentsRect().width() - 2 * rimX ) / font_w; 1182 columns = ( contentsRect().width() - 2 * rimX ) / font_w;
1168 dcolumns = columns; 1183 dcolumns = columns;
1169 if(vcolumns) columns = vcolumns; 1184 if(vcolumns) columns = vcolumns;
1170 blX = (contentsRect().width() - (columns*font_w) ) / 2; 1185 blX = (contentsRect().width() - (columns*font_w) ) / 2;
1171 if(showhscrollbar) 1186 if(showhscrollbar)
1172 blX = -hposition * font_w; 1187 blX = -hposition * font_w;
1173 brX = blX; 1188 brX = blX;
1174 scrollbar->hide(); 1189 scrollbar->hide();
1175 break; 1190 break;
1176 case SCRLEFT : 1191 case SCRLEFT :
1177 columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w; 1192 columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w;
1178 dcolumns = columns; 1193 dcolumns = columns;
1179 if(vcolumns) columns = vcolumns; 1194 if(vcolumns) columns = vcolumns;
1180 brX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2; 1195 brX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2;
1181 if(showhscrollbar) 1196 if(showhscrollbar)
1182 brX = -hposition * font_w; 1197 brX = -hposition * font_w;
1183 blX = brX + scrollbar->width(); 1198 blX = brX + scrollbar->width();
1184 scrollbar->move(contentsRect().topLeft()); 1199 scrollbar->move(contentsRect().topLeft());
1185 scrollbar->show(); 1200 scrollbar->show();
1186 break; 1201 break;
1187 case SCRRIGHT: 1202 case SCRRIGHT:
1188 columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w; 1203 columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w;
1189 dcolumns = columns; 1204 dcolumns = columns;
1190 if(vcolumns) columns = vcolumns; 1205 if(vcolumns) columns = vcolumns;
1191 blX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2; 1206 blX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2;
1192 if(showhscrollbar) 1207 if(showhscrollbar)
1193 blX = -hposition * font_w; 1208 blX = -hposition * font_w;
1194 brX = blX; 1209 brX = blX;
1195 scrollbar->move(contentsRect().topRight() - QPoint(scrollbar->width()-1,0)); 1210 scrollbar->move(contentsRect().topRight() - QPoint(scrollbar->width()-1,0));
1196 scrollbar->show(); 1211 scrollbar->show();
1197 break; 1212 break;
1198 } 1213 }
1199 //FIXME: support 'rounding' styles 1214 //FIXME: support 'rounding' styles
1200 lines = ( contentsRect().height() - 2 * rimY ) / font_h; 1215 lines = ( contentsRect().height() - 2 * rimY ) / font_h;
1201 bY = (contentsRect().height() - (lines *font_h)) / 2; 1216 bY = (contentsRect().height() - (lines *font_h)) / 2;
1202 1217
1203 if(showhscrollbar == 1) { 1218 if(showhscrollbar == 1) {
1204 hScrollbar->resize(contentsRect().width() - hwidth, hwidth); 1219 hScrollbar->resize(contentsRect().width() - hwidth, hwidth);
1205 hScrollbar->setRange(0, vcolumns - dcolumns); 1220 hScrollbar->setRange(0, vcolumns - dcolumns);
1206 1221
1207 QPoint p = contentsRect().bottomLeft(); 1222 QPoint p = contentsRect().bottomLeft();
1208 if(scrollLoc == SCRLEFT) 1223 if(scrollLoc == SCRLEFT)
1209 hScrollbar->move(QPoint(p.x()+hwidth, p.y() - hwidth)); 1224 hScrollbar->move(QPoint(p.x()+hwidth, p.y() - hwidth));
1210 else 1225 else
1211 hScrollbar->move(QPoint(p.x(), p.y() - hwidth)); 1226 hScrollbar->move(QPoint(p.x(), p.y() - hwidth));
1212 1227
1213 hScrollbar->show(); 1228 hScrollbar->show();
1214 } 1229 }
1215 else hScrollbar->hide(); 1230 else hScrollbar->hide();
1216 1231
1217 if(showhscrollbar == 1) { 1232 if(showhscrollbar == 1) {
1218 lines = lines - (hwidth / font_h) - 1; 1233 lines = lines - (hwidth / font_h) - 1;
1219 if(lines < 1) lines = 1; 1234 if(lines < 1) lines = 1;
1220 } 1235 }
1221 //FIXME: support 'rounding' styles 1236 //FIXME: support 'rounding' styles
1222} 1237}
1223 1238
1224void TEWidget::makeImage() 1239void TEWidget::makeImage()
1225//FIXME: rename 'calcGeometry? 1240//FIXME: rename 'calcGeometry?
1226{ 1241{
1227 calcGeometry(); 1242 calcGeometry();
1228 image = (ca*) malloc(lines*columns*sizeof(ca)); 1243 image = (ca*) malloc(lines*columns*sizeof(ca));
1229 clearImage(); 1244 clearImage();
1230} 1245}
1231 1246
1232// calculate the needed size 1247// calculate the needed size
1233QSize TEWidget::calcSize(int cols, int lins) const 1248QSize TEWidget::calcSize(int cols, int lins) const
1234{ 1249{
1235 int frw = width() - contentsRect().width(); 1250 int frw = width() - contentsRect().width();
1236 int frh = height() - contentsRect().height(); 1251 int frh = height() - contentsRect().height();
1237 int scw = (scrollLoc==SCRNONE?0:scrollbar->width()); 1252 int scw = (scrollLoc==SCRNONE?0:scrollbar->width());
1238 return QSize( font_w*cols + 2*rimX + frw + scw, font_h*lins + 2*rimY + frh ); 1253 return QSize( font_w*cols + 2*rimX + frw + scw, font_h*lins + 2*rimY + frh );
1239} 1254}
1240 1255
1241QSize TEWidget::sizeHint() const 1256QSize TEWidget::sizeHint() const
1242{ 1257{
1243 return size(); 1258 return size();
1244} 1259}
1245 1260
1246void TEWidget::styleChange(QStyle &) 1261void TEWidget::styleChange(QStyle &)
1247{ 1262{
1248 propagateSize(); 1263 propagateSize();
1249} 1264}
1250 1265
1251#ifndef QT_NO_DRAGANDDROP 1266#ifndef QT_NO_DRAGANDDROP
1252 1267
1253/* --------------------------------------------------------------------- */ 1268/* --------------------------------------------------------------------- */
1254/* */ 1269/* */
1255/* Drag & Drop */ 1270/* Drag & Drop */
1256/* */ 1271/* */
1257/* --------------------------------------------------------------------- */ 1272/* --------------------------------------------------------------------- */
1258 1273
1259 1274
1260void TEWidget::dragEnterEvent(QDragEnterEvent* e) 1275void TEWidget::dragEnterEvent(QDragEnterEvent* e)
1261{ 1276{
1262 e->accept(QTextDrag::canDecode(e) || 1277 e->accept(QTextDrag::canDecode(e) ||
1263 QUriDrag::canDecode(e)); 1278 QUriDrag::canDecode(e));
1264} 1279}
1265 1280
1266void TEWidget::dropEvent(QDropEvent* event) 1281void TEWidget::dropEvent(QDropEvent* event)
1267{ 1282{
1268 // The current behaviour when url(s) are dropped is 1283 // The current behaviour when url(s) are dropped is
1269 // * if there is only ONE url and if it's a LOCAL one, ask for paste or cd 1284 // * if there is only ONE url and if it's a LOCAL one, ask for paste or cd
1270 // * in all other cases, just paste 1285 // * in all other cases, just paste
1271 // (for non-local ones, or for a list of URLs, 'cd' is nonsense) 1286 // (for non-local ones, or for a list of URLs, 'cd' is nonsense)
1272 QStrList strlist; 1287 QStrList strlist;
1273 int file_count = 0; 1288 int file_count = 0;
1274 dropText = ""; 1289 dropText = "";
1275 bool bPopup = true; 1290 bool bPopup = true;
1276 1291
1277 if(QUriDrag::decode(event, strlist)) { 1292 if(QUriDrag::decode(event, strlist)) {
1278 if (strlist.count()) { 1293 if (strlist.count()) {
1279 for(const char* p = strlist.first(); p; p = strlist.next()) { 1294 for(const char* p = strlist.first(); p; p = strlist.next()) {
1280 if(file_count++ > 0) { 1295 if(file_count++ > 0) {
1281 dropText += " "; 1296 dropText += " ";
1282 bPopup = false; // more than one file, don't popup 1297 bPopup = false; // more than one file, don't popup
1283 } 1298 }
1284 1299
1285/* 1300/*
1286 KURL url(p); 1301 KURL url(p);
1287 if (url.isLocalFile()) { 1302 if (url.isLocalFile()) {
1288 dropText += url.path(); // local URL : remove protocol 1303 dropText += url.path(); // local URL : remove protocol
1289 } 1304 }
1290 else { 1305 else {
1291 dropText += url.prettyURL(); 1306 dropText += url.prettyURL();
1292 bPopup = false; // a non-local file, don't popup 1307 bPopup = false; // a non-local file, don't popup
1293 } 1308 }
1294*/ 1309*/
1295 1310
1296 } 1311 }
1297 1312
1298 if (bPopup) 1313 if (bPopup)
1299 // m_drop->popup(pos() + event->pos()); 1314 // m_drop->popup(pos() + event->pos());
1300 m_drop->popup(mapToGlobal(event->pos())); 1315 m_drop->popup(mapToGlobal(event->pos()));
1301 else 1316 else
1302 { 1317 {
1303 if (currentSession) { 1318 if (currentSession) {
1304 currentSession->getEmulation()->sendString(dropText.local8Bit()); 1319 currentSession->getEmulation()->sendString(dropText.local8Bit());
1305 } 1320 }
1306// kdDebug() << "Drop:" << dropText.local8Bit() << "\n"; 1321// kdDebug() << "Drop:" << dropText.local8Bit() << "\n";
1307 } 1322 }
1308 } 1323 }
1309 } 1324 }
1310 else if(QTextDrag::decode(event, dropText)) { 1325 else if(QTextDrag::decode(event, dropText)) {
1311// kdDebug() << "Drop:" << dropText.local8Bit() << "\n"; 1326// kdDebug() << "Drop:" << dropText.local8Bit() << "\n";
1312 if (currentSession) { 1327 if (currentSession) {
1313 currentSession->getEmulation()->sendString(dropText.local8Bit()); 1328 currentSession->getEmulation()->sendString(dropText.local8Bit());
1314 } 1329 }
1315 // Paste it 1330 // Paste it
1316 } 1331 }
1317} 1332}
1318#endif 1333#endif
1319 1334
1320 1335
1321void TEWidget::drop_menu_activated(int item) 1336void TEWidget::drop_menu_activated(int item)
1322{ 1337{
1323#ifndef QT_NO_DRAGANDDROP 1338#ifndef QT_NO_DRAGANDDROP
1324 switch (item) 1339 switch (item)
1325 { 1340 {
1326 case 0: // paste 1341 case 0: // paste
1327 currentSession->getEmulation()->sendString(dropText.local8Bit()); 1342 currentSession->getEmulation()->sendString(dropText.local8Bit());
1328// KWM::activate((Window)this->winId()); 1343// KWM::activate((Window)this->winId());
1329 break; 1344 break;
1330 case 1: // cd ... 1345 case 1: // cd ...
1331 currentSession->getEmulation()->sendString("cd "); 1346 currentSession->getEmulation()->sendString("cd ");
1332 struct stat statbuf; 1347 struct stat statbuf;
1333 if ( ::stat( QFile::encodeName( dropText ), &statbuf ) == 0 ) 1348 if ( ::stat( QFile::encodeName( dropText ), &statbuf ) == 0 )
1334 { 1349 {
1335 if ( !S_ISDIR(statbuf.st_mode) ) 1350 if ( !S_ISDIR(statbuf.st_mode) )
1336 { 1351 {
1337/* 1352/*
1338 KURL url; 1353 KURL url;
1339 url.setPath( dropText ); 1354 url.setPath( dropText );
1340 dropText = url.directory( true, false ); // remove filename 1355 dropText = url.directory( true, false ); // remove filename
1341*/ 1356*/
1342 } 1357 }
1343 } 1358 }
1344 dropText.replace(QRegExp(" "), "\\ "); // escape spaces 1359 dropText.replace(QRegExp(" "), "\\ "); // escape spaces
1345 currentSession->getEmulation()->sendString(dropText.local8Bit()); 1360 currentSession->getEmulation()->sendString(dropText.local8Bit());
1346 currentSession->getEmulation()->sendString("\n"); 1361 currentSession->getEmulation()->sendString("\n");
1347// KWM::activate((Window)this->winId()); 1362// KWM::activate((Window)this->winId());
1348 break; 1363 break;
1349 } 1364 }
1350#endif 1365#endif
1351} 1366}
1352 1367
1353void TEWidget::setWrapAt(int columns) 1368void TEWidget::setWrapAt(int columns)
1354{ 1369{
1355 vcolumns = columns; 1370 vcolumns = columns;
1356 propagateSize(); 1371 propagateSize();
1357 update(); 1372 update();
1358} 1373}