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