summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-console/TECommon.h114
-rw-r--r--noncore/apps/opie-console/TEHistory.cpp212
-rw-r--r--noncore/apps/opie-console/TEHistory.h75
-rw-r--r--noncore/apps/opie-console/TEScreen.cpp1197
-rw-r--r--noncore/apps/opie-console/TEScreen.h259
-rw-r--r--noncore/apps/opie-console/TEWidget.cpp1264
-rw-r--r--noncore/apps/opie-console/TEWidget.h202
-rw-r--r--noncore/apps/opie-console/TEmuVt102.cpp1020
-rw-r--r--noncore/apps/opie-console/TEmuVt102.h135
-rw-r--r--noncore/apps/opie-console/TEmulation.cpp363
-rw-r--r--noncore/apps/opie-console/TEmulation.h117
-rw-r--r--noncore/apps/opie-console/default.cpp12
-rw-r--r--noncore/apps/opie-console/default.h4
-rw-r--r--noncore/apps/opie-console/history.cpp4
-rw-r--r--noncore/apps/opie-console/io_layer.cpp2
-rw-r--r--noncore/apps/opie-console/io_layer.h8
-rw-r--r--noncore/apps/opie-console/mainwindow.cpp8
-rw-r--r--noncore/apps/opie-console/opie-console.pro28
-rw-r--r--noncore/apps/opie-console/profilemanager.cpp15
-rw-r--r--noncore/apps/opie-console/session.cpp22
-rw-r--r--noncore/apps/opie-console/session.h10
21 files changed, 5023 insertions, 48 deletions
diff --git a/noncore/apps/opie-console/TECommon.h b/noncore/apps/opie-console/TECommon.h
new file mode 100644
index 0000000..5db41ad
--- a/dev/null
+++ b/noncore/apps/opie-console/TECommon.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 ca
67 * \brief a character with rendition attributes.
68*/
69
70class ca
71{
72public:
73 inline ca(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 == (ca a, ca b);
85 friend BOOL operator != (ca a, ca b);
86};
87
88inline BOOL operator == (ca a, ca 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 != (ca a, ca 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/TEHistory.cpp b/noncore/apps/opie-console/TEHistory.cpp
new file mode 100644
index 0000000..317ce57
--- a/dev/null
+++ b/noncore/apps/opie-console/TEHistory.cpp
@@ -0,0 +1,212 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [TEHistory.C] History Buffer */
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#include "TEHistory.h"
20#include <stdlib.h>
21#include <assert.h>
22#include <stdio.h>
23#include <sys/types.h>
24#include <unistd.h>
25#include <errno.h>
26
27#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
28
29/*
30 An arbitrary long scroll.
31
32 One can modify the scroll only by adding either cells
33 or newlines, but access it randomly.
34
35 The model is that of an arbitrary wide typewriter scroll
36 in that the scroll is a serie of lines and each line is
37 a serie of cells with no overwriting permitted.
38
39 The implementation provides arbitrary length and numbers
40 of cells and line/column indexed read access to the scroll
41 at constant costs.
42
43FIXME: some complain about the history buffer comsuming the
44 memory of their machines. This problem is critical
45 since the history does not behave gracefully in cases
46 where the memory is used up completely.
47
48 I put in a workaround that should handle it problem
49 now gracefully. I'm not satisfied with the solution.
50
51FIXME: Terminating the history is not properly indicated
52 in the menu. We should throw a signal.
53
54FIXME: There is noticable decrease in speed, also. Perhaps,
55 there whole feature needs to be revisited therefore.
56 Disadvantage of a more elaborated, say block-oriented
57 scheme with wrap around would be it's complexity.
58*/
59
60//FIXME: tempory replacement for tmpfile
61// this is here one for debugging purpose.
62
63//#define tmpfile xTmpFile
64
65FILE* xTmpFile()
66{
67 static int fid = 0;
68 char fname[80];
69 sprintf(fname,"TmpFile.%d",fid++);
70 return fopen(fname,"w");
71}
72
73
74// History Buffer ///////////////////////////////////////////
75
76/*
77 A Row(X) data type which allows adding elements to the end.
78*/
79
80HistoryBuffer::HistoryBuffer()
81{
82 ion = -1;
83 length = 0;
84}
85
86HistoryBuffer::~HistoryBuffer()
87{
88 setScroll(FALSE);
89}
90
91void HistoryBuffer::setScroll(bool on)
92{
93 if (on == hasScroll()) return;
94
95 if (on)
96 {
97 assert( ion < 0 );
98 assert( length == 0);
99 FILE* tmp = tmpfile(); if (!tmp) { perror("konsole: cannot open temp file.\n"); return; }
100 ion = dup(fileno(tmp)); if (ion<0) perror("konsole: cannot dup temp file.\n");
101 fclose(tmp);
102 }
103 else
104 {
105 assert( ion >= 0 );
106 close(ion);
107 ion = -1;
108 length = 0;
109 }
110}
111
112bool HistoryBuffer::hasScroll()
113{
114 return ion >= 0;
115}
116
117void HistoryBuffer::add(const unsigned char* bytes, int len)
118{ int rc;
119 assert(hasScroll());
120 rc = lseek(ion,length,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::add.seek"); setScroll(FALSE); return; }
121 rc = write(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::add.write"); setScroll(FALSE); return; }
122 length += rc;
123}
124
125void HistoryBuffer::get(unsigned char* bytes, int len, int loc)
126{ int rc;
127 assert(hasScroll());
128 if (loc < 0 || len < 0 || loc + len > length)
129 fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc);
130 rc = lseek(ion,loc,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::get.seek"); setScroll(FALSE); return; }
131 rc = read(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::get.read"); setScroll(FALSE); return; }
132}
133
134int HistoryBuffer::len()
135{
136 return length;
137}
138
139// History Scroll //////////////////////////////////////
140
141/*
142 The history scroll makes a Row(Row(Cell)) from
143 two history buffers. The index buffer contains
144 start of line positions which refere to the cells
145 buffer.
146
147 Note that index[0] addresses the second line
148 (line #1), while the first line (line #0) starts
149 at 0 in cells.
150*/
151
152HistoryScroll::HistoryScroll()
153{
154}
155
156HistoryScroll::~HistoryScroll()
157{
158}
159
160void HistoryScroll::setScroll(bool on)
161{
162 index.setScroll(on);
163 cells.setScroll(on);
164}
165
166bool HistoryScroll::hasScroll()
167{
168 return index.hasScroll() && cells.hasScroll();
169}
170
171int HistoryScroll::getLines()
172{
173 if (!hasScroll()) return 0;
174 return index.len() / sizeof(int);
175}
176
177int HistoryScroll::getLineLen(int lineno)
178{
179 if (!hasScroll()) return 0;
180 return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(ca);
181}
182
183int HistoryScroll::startOfLine(int lineno)
184{
185 if (lineno <= 0) return 0;
186 if (!hasScroll()) return 0;
187 if (lineno <= getLines())
188 { int res;
189 index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int));
190 return res;
191 }
192 return cells.len();
193}
194
195void HistoryScroll::getCells(int lineno, int colno, int count, ca res[])
196{
197 assert(hasScroll());
198 cells.get((unsigned char*)res,count*sizeof(ca),startOfLine(lineno)+colno*sizeof(ca));
199}
200
201void HistoryScroll::addCells(ca text[], int count)
202{
203 if (!hasScroll()) return;
204 cells.add((unsigned char*)text,count*sizeof(ca));
205}
206
207void HistoryScroll::addLine()
208{
209 if (!hasScroll()) return;
210 int locn = cells.len();
211 index.add((unsigned char*)&locn,sizeof(int));
212}
diff --git a/noncore/apps/opie-console/TEHistory.h b/noncore/apps/opie-console/TEHistory.h
new file mode 100644
index 0000000..8339ec6
--- a/dev/null
+++ b/noncore/apps/opie-console/TEHistory.h
@@ -0,0 +1,75 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [TEHistory.H] History Buffer */
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#ifndef TEHISTORY_H
20#define TEHISTORY_H
21
22#include "TECommon.h"
23
24/*
25 An extendable tmpfile(1) based buffer.
26*/
27class HistoryBuffer
28{
29public:
30 HistoryBuffer();
31 ~HistoryBuffer();
32
33public:
34 void setScroll(bool on);
35 bool hasScroll();
36
37public:
38 void add(const unsigned char* bytes, int len);
39 void get(unsigned char* bytes, int len, int loc);
40 int len();
41
42private:
43 int ion;
44 int length;
45};
46
47class HistoryScroll
48{
49public:
50 HistoryScroll();
51 ~HistoryScroll();
52
53public:
54 void setScroll(bool on);
55 bool hasScroll();
56
57public: // access to history
58 int getLines();
59 int getLineLen(int lineno);
60 void getCells(int lineno, int colno, int count, ca res[]);
61
62public: // backward compatibility (obsolete)
63 ca getCell(int lineno, int colno) { ca res; getCells(lineno,colno,1,&res); return res; }
64
65public: // adding lines.
66 void addCells(ca a[], int count);
67 void addLine();
68
69private:
70 int startOfLine(int lineno);
71 HistoryBuffer index; // lines Row(int)
72 HistoryBuffer cells; // text Row(ca)
73};
74
75#endif // TEHISTORY_H
diff --git a/noncore/apps/opie-console/TEScreen.cpp b/noncore/apps/opie-console/TEScreen.cpp
new file mode 100644
index 0000000..a3d115d
--- a/dev/null
+++ b/noncore/apps/opie-console/TEScreen.cpp
@@ -0,0 +1,1197 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [TEScreen.C] Screen Data Type */
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
20*/
21
22/*! \class TEScreen
23
24 \brief The image manipulated by the emulation.
25
26 This class implements the operations of the terminal emulation framework.
27 It is a complete passive device, driven by the emulation decoder
28 (TEmuVT102). By this it forms in fact an ADT, that defines operations
29 on a rectangular image.
30
31 It does neither know how to display its image nor about escape sequences.
32 It is further independent of the underlying toolkit. By this, one can even
33 use this module for an ordinary text surface.
34
35 Since the operations are called by a specific emulation decoder, one may
36 collect their different operations here.
37
38 The state manipulated by the operations is mainly kept in `image', though
39 it is a little more complex bejond this. See the header file of the class.
40
41 \sa TEWidget \sa VT102Emulation
42*/
43
44#include <stdio.h>
45#include <stdlib.h>
46#include <unistd.h>
47// #include <kdebug.h>
48
49#include <assert.h>
50#include <string.h>
51#include <ctype.h>
52
53#include "TEScreen.h"
54
55#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
56
57//FIXME: this is emulation specific. Use FALSE for xterm, TRUE for ANSI.
58//FIXME: see if we can get this from terminfo.
59#define BS_CLEARS FALSE
60
61#define loc(X,Y) ((Y)*columns+(X))
62
63/*! creates a `TEScreen' of `lines' lines and `columns' columns.
64*/
65
66TEScreen::TEScreen(int lines, int columns)
67{
68 this->lines = lines;
69 this->columns = columns;
70
71 image = (ca*) malloc(lines*columns*sizeof(ca));
72 tabstops = NULL; initTabStops();
73
74 histCursor = 0;
75
76 clearSelection();
77 reset();
78}
79
80/*! Destructor
81*/
82
83TEScreen::~TEScreen()
84{
85 free(image);
86 if (tabstops) free(tabstops);
87}
88
89/* ------------------------------------------------------------------------- */
90/* */
91/* Normalized Screen Operations */
92/* */
93/* ------------------------------------------------------------------------- */
94
95// Cursor Setting --------------------------------------------------------------
96
97/*! \section Cursor
98
99 The `cursor' is a location within the screen that is implicitely used in
100 many operations. The operations within this section allow to manipulate
101 the cursor explicitly and to obtain it's value.
102
103 The position of the cursor is guarantied to be between (including) 0 and
104 `columns-1' and `lines-1'.
105*/
106
107/*!
108 Move the cursor up.
109
110 The cursor will not be moved beyond the top margin.
111*/
112
113void TEScreen::cursorUp(int n)
114//=CUU
115{
116 if (n == 0) n = 1; // Default
117 int stop = cuY < tmargin ? 0 : tmargin;
118 cuX = QMIN(columns-1,cuX); // nowrap!
119 cuY = QMAX(stop,cuY-n);
120}
121
122/*!
123 Move the cursor down.
124
125 The cursor will not be moved beyond the bottom margin.
126*/
127
128void TEScreen::cursorDown(int n)
129//=CUD
130{
131 if (n == 0) n = 1; // Default
132 int stop = cuY > bmargin ? lines-1 : bmargin;
133 cuX = QMIN(columns-1,cuX); // nowrap!
134 cuY = QMIN(stop,cuY+n);
135}
136
137/*!
138 Move the cursor left.
139
140 The cursor will not move beyond the first column.
141*/
142
143void TEScreen::cursorLeft(int n)
144//=CUB
145{
146 if (n == 0) n = 1; // Default
147 cuX = QMIN(columns-1,cuX); // nowrap!
148 cuX = QMAX(0,cuX-n);
149}
150
151/*!
152 Move the cursor left.
153
154 The cursor will not move beyond the rightmost column.
155*/
156
157void TEScreen::cursorRight(int n)
158//=CUF
159{
160 if (n == 0) n = 1; // Default
161 cuX = QMIN(columns-1,cuX+n);
162}
163
164/*!
165 Set top and bottom margin.
166*/
167
168void TEScreen::setMargins(int top, int bot)
169//=STBM
170{
171 if (top == 0) top = 1; // Default
172 if (bot == 0) bot = lines; // Default
173 top = top - 1; // Adjust to internal lineno
174 bot = bot - 1; // Adjust to internal lineno
175 if ( !( 0 <= top && top < bot && bot < lines ) )
176 { fprintf(stderr,"%s(%d) : setRegion(%d,%d) : bad range.\n",
177 __FILE__,__LINE__,top,bot);
178 return; // Default error action: ignore
179 }
180 tmargin = top;
181 bmargin = bot;
182 cuX = 0;
183 cuY = getMode(MODE_Origin) ? top : 0;
184}
185
186/*!
187 Move the cursor down one line.
188
189 If cursor is on bottom margin, the region between the
190 actual top and bottom margin is scrolled up instead.
191*/
192
193void TEScreen::index()
194//=IND
195{
196 if (cuY == bmargin)
197 {
198 if (tmargin == 0 && bmargin == lines-1) addHistLine(); // hist.history
199 scrollUp(tmargin,1);
200 }
201 else if (cuY < lines-1)
202 cuY += 1;
203}
204
205/*!
206 Move the cursor up one line.
207
208 If cursor is on the top margin, the region between the
209 actual top and bottom margin is scrolled down instead.
210*/
211
212void TEScreen::reverseIndex()
213//=RI
214{
215 if (cuY == tmargin)
216 scrollDown(tmargin,1);
217 else if (cuY > 0)
218 cuY -= 1;
219}
220
221/*!
222 Move the cursor to the begin of the next line.
223
224 If cursor is on bottom margin, the region between the
225 actual top and bottom margin is scrolled up.
226*/
227
228void TEScreen::NextLine()
229//=NEL
230{
231 Return(); index();
232}
233
234// Line Editing ----------------------------------------------------------------
235
236/*! \section inserting / deleting characters
237*/
238
239/*! erase `n' characters starting from (including) the cursor position.
240
241 The line is filled in from the right with spaces.
242*/
243
244void TEScreen::eraseChars(int n)
245{
246 if (n == 0) n = 1; // Default
247 int p = QMAX(0,QMIN(cuX+n-1,columns-1));
248 clearImage(loc(cuX,cuY),loc(p,cuY),' ');
249}
250
251/*! delete `n' characters starting from (including) the cursor position.
252
253 The line is filled in from the right with spaces.
254*/
255
256void TEScreen::deleteChars(int n)
257{
258 if (n == 0) n = 1; // Default
259 int p = QMAX(0,QMIN(cuX+n,columns-1));
260 moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY));
261 clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' ');
262}
263
264/*! insert `n' spaces at the cursor position.
265
266 The cursor is not moved by the operation.
267*/
268
269void TEScreen::insertChars(int n)
270{
271 if (n == 0) n = 1; // Default
272 int p = QMAX(0,QMIN(columns-1-n,columns-1));
273 int q = QMAX(0,QMIN(cuX+n,columns-1));
274 moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY));
275 clearImage(loc(cuX,cuY),loc(q-1,cuY),' ');
276}
277
278/*! delete `n' lines starting from (including) the cursor position.
279
280 The cursor is not moved by the operation.
281*/
282
283void TEScreen::deleteLines(int n)
284{
285 if (n == 0) n = 1; // Default
286 scrollUp(cuY,n);
287}
288
289/*! insert `n' lines at the cursor position.
290
291 The cursor is not moved by the operation.
292*/
293
294void TEScreen::insertLines(int n)
295{
296 if (n == 0) n = 1; // Default
297 scrollDown(cuY,n);
298}
299
300// Mode Operations -----------------------------------------------------------
301
302/*! Set a specific mode. */
303
304void TEScreen::setMode(int m)
305{
306 currParm.mode[m] = TRUE;
307 switch(m)
308 {
309 case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home
310 }
311}
312
313/*! Reset a specific mode. */
314
315void TEScreen::resetMode(int m)
316{
317 currParm.mode[m] = FALSE;
318 switch(m)
319 {
320 case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home
321 }
322}
323
324/*! Save a specific mode. */
325
326void TEScreen::saveMode(int m)
327{
328 saveParm.mode[m] = currParm.mode[m];
329}
330
331/*! Restore a specific mode. */
332
333void TEScreen::restoreMode(int m)
334{
335 currParm.mode[m] = saveParm.mode[m];
336}
337
338//NOTE: this is a helper function
339/*! Return the setting a specific mode. */
340BOOL TEScreen::getMode(int m)
341{
342 return currParm.mode[m];
343}
344
345/*! Save the cursor position and the rendition attribute settings. */
346
347void TEScreen::saveCursor()
348{
349 sa_cuX = cuX;
350 sa_cuY = cuY;
351 sa_cu_re = cu_re;
352 sa_cu_fg = cu_fg;
353 sa_cu_bg = cu_bg;
354}
355
356/*! Restore the cursor position and the rendition attribute settings. */
357
358void TEScreen::restoreCursor()
359{
360 cuX = QMIN(sa_cuX,columns-1);
361 cuY = QMIN(sa_cuY,lines-1);
362 cu_re = sa_cu_re;
363 cu_fg = sa_cu_fg;
364 cu_bg = sa_cu_bg;
365 effectiveRendition();
366}
367
368/* ------------------------------------------------------------------------- */
369/* */
370/* Screen Operations */
371/* */
372/* ------------------------------------------------------------------------- */
373
374/*! Assing a new size to the screen.
375
376 The topmost left position is maintained, while lower lines
377 or right hand side columns might be removed or filled with
378 spaces to fit the new size.
379
380 The region setting is reset to the whole screen and the
381 tab positions reinitialized.
382*/
383
384void TEScreen::resizeImage(int new_lines, int new_columns)
385{
386
387 if (cuY > new_lines-1)
388 { // attempt to preserve focus and lines
389 bmargin = lines-1; //FIXME: margin lost
390 for (int i = 0; i < cuY-(new_lines-1); i++)
391 {
392 addHistLine(); scrollUp(0,1);
393 }
394 }
395
396 // make new image
397 ca* newimg = (ca*)malloc(new_lines*new_columns*sizeof(ca));
398
399 clearSelection();
400
401 // clear new image
402 for (int y = 0; y < new_lines; y++)
403 for (int x = 0; x < new_columns; x++)
404 {
405 newimg[y*new_columns+x].c = ' ';
406 newimg[y*new_columns+x].f = DEFAULT_FORE_COLOR;
407 newimg[y*new_columns+x].b = DEFAULT_BACK_COLOR;
408 newimg[y*new_columns+x].r = DEFAULT_RENDITION;
409 }
410 int cpy_lines = QMIN(new_lines, lines);
411 int cpy_columns = QMIN(new_columns,columns);
412 // copy to new image
413 for (int y = 0; y < cpy_lines; y++)
414 for (int x = 0; x < cpy_columns; x++)
415 {
416 newimg[y*new_columns+x].c = image[loc(x,y)].c;
417 newimg[y*new_columns+x].f = image[loc(x,y)].f;
418 newimg[y*new_columns+x].b = image[loc(x,y)].b;
419 newimg[y*new_columns+x].r = image[loc(x,y)].r;
420 }
421 free(image);
422 image = newimg;
423 lines = new_lines;
424 columns = new_columns;
425 cuX = QMIN(cuX,columns-1);
426 cuY = QMIN(cuY,lines-1);
427
428 // FIXME: try to keep values, evtl.
429 tmargin=0;
430 bmargin=lines-1;
431 initTabStops();
432 clearSelection();
433}
434
435/*
436 Clarifying rendition here and in TEWidget.
437
438 currently, TEWidget's color table is
439 0 1 2 .. 9 10 .. 17
440 dft_fg, dft_bg, dim 0..7, intensive 0..7
441
442 cu_fg, cu_bg contain values 0..8;
443 - 0 = default color
444 - 1..8 = ansi specified color
445
446 re_fg, re_bg contain values 0..17
447 due to the TEWidget's color table
448
449 rendition attributes are
450
451 attr widget screen
452 -------------- ------ ------
453 RE_UNDERLINE XX XX affects foreground only
454 RE_BLINK XX XX affects foreground only
455 RE_BOLD XX XX affects foreground only
456 RE_REVERSE -- XX
457 RE_TRANSPARENT XX -- affects background only
458 RE_INTENSIVE XX -- affects foreground only
459
460 Note that RE_BOLD is used in both widget
461 and screen rendition. Since xterm/vt102
462 is to poor to distinguish between bold
463 (which is a font attribute) and intensive
464 (which is a color attribute), we translate
465 this and RE_BOLD in falls eventually appart
466 into RE_BOLD and RE_INTENSIVE.
467*/
468
469void TEScreen::reverseRendition(ca* p)
470{ UINT8 f = p->f; UINT8 b = p->b;
471 p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT;
472}
473
474void TEScreen::effectiveRendition()
475// calculate rendition
476{
477 ef_re = cu_re & (RE_UNDERLINE | RE_BLINK);
478 if (cu_re & RE_REVERSE)
479 {
480 ef_fg = cu_bg;
481 ef_bg = cu_fg;
482 }
483 else
484 {
485 ef_fg = cu_fg;
486 ef_bg = cu_bg;
487 }
488 if (cu_re & RE_BOLD)
489 {
490 if (ef_fg < BASE_COLORS)
491 ef_fg += BASE_COLORS;
492 else
493 ef_fg -= BASE_COLORS;
494 }
495}
496
497/*!
498 returns the image.
499
500 Get the size of the image by \sa getLines and \sa getColumns.
501
502 NOTE that the image returned by this function must later be
503 freed.
504
505*/
506
507ca* TEScreen::getCookedImage()
508{ int x,y;
509 ca* merged = (ca*)malloc(lines*columns*sizeof(ca));
510 ca dft(' ',DEFAULT_FORE_COLOR,DEFAULT_BACK_COLOR,DEFAULT_RENDITION);
511
512 for (y = 0; (y < lines) && (y < (hist.getLines()-histCursor)); y++)
513 {
514 int len = QMIN(columns,hist.getLineLen(y+histCursor));
515 int yp = y*columns;
516 int yq = (y+histCursor)*columns;
517
518 hist.getCells(y+histCursor,0,len,merged+yp);
519 for (x = len; x < columns; x++) merged[yp+x] = dft;
520 for (x = 0; x < columns; x++)
521 { int p=x + yp; int q=x + yq;
522 if ( ( q >= sel_TL ) && ( q <= sel_BR ) )
523 reverseRendition(&merged[p]); // for selection
524 }
525 }
526 if (lines >= hist.getLines()-histCursor)
527 {
528 for (y = (hist.getLines()-histCursor); y < lines ; y++)
529 {
530 int yp = y*columns;
531 int yq = (y+histCursor)*columns;
532 int yr = (y-hist.getLines()+histCursor)*columns;
533 for (x = 0; x < columns; x++)
534 { int p = x + yp; int q = x + yq; int r = x + yr;
535 merged[p] = image[r];
536 if ( q >= sel_TL && q <= sel_BR )
537 reverseRendition(&merged[p]); // for selection
538 }
539
540 }
541 }
542 // evtl. inverse display
543 if (getMode(MODE_Screen))
544 { int i,n = lines*columns;
545 for (i = 0; i < n; i++)
546 reverseRendition(&merged[i]); // for reverse display
547 }
548 if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines)) // cursor visible
549 reverseRendition(&merged[loc(cuX,cuY+(hist.getLines()-histCursor))]);
550 return merged;
551}
552
553
554/*!
555*/
556
557void TEScreen::reset()
558{
559 setMode(MODE_Wrap ); saveMode(MODE_Wrap ); // wrap at end of margin
560 resetMode(MODE_Origin); saveMode(MODE_Origin); // position refere to [1,1]
561 resetMode(MODE_Insert); saveMode(MODE_Insert); // overstroke
562 setMode(MODE_Cursor); // cursor visible
563 resetMode(MODE_Screen); // screen not inverse
564 resetMode(MODE_NewLine);
565
566 tmargin=0;
567 bmargin=lines-1;
568
569 setDefaultRendition();
570 saveCursor();
571
572 clear();
573}
574
575/*! Clear the entire screen and home the cursor.
576*/
577
578void TEScreen::clear()
579{
580 clearEntireScreen();
581 home();
582}
583
584/*! Moves the cursor left one column.
585*/
586
587void TEScreen::BackSpace()
588{
589 cuX = QMAX(0,cuX-1);
590 if (BS_CLEARS) image[loc(cuX,cuY)].c = ' ';
591}
592
593/*!
594*/
595
596void TEScreen::Tabulate()
597{
598 // note that TAB is a format effector (does not write ' ');
599 cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1);
600}
601
602void TEScreen::clearTabStops()
603{
604 for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE;
605}
606
607void TEScreen::changeTabStop(bool set)
608{
609 if (cuX >= columns) return;
610 tabstops[cuX] = set;
611}
612
613void TEScreen::initTabStops()
614{
615 if (tabstops) free(tabstops);
616 tabstops = (bool*)malloc(columns*sizeof(bool));
617 // Arrg! The 1st tabstop has to be one longer than the other.
618 // i.e. the kids start counting from 0 instead of 1.
619 // Other programs might behave correctly. Be aware.
620 for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0);
621}
622
623/*!
624 This behaves either as IND (Screen::Index) or as NEL (Screen::NextLine)
625 depending on the NewLine Mode (LNM). This mode also
626 affects the key sequence returned for newline ([CR]LF).
627*/
628
629void TEScreen::NewLine()
630{
631 if (getMode(MODE_NewLine)) Return();
632 index();
633}
634
635/*! put `c' literally onto the screen at the current cursor position.
636
637 VT100 uses the convention to produce an automatic newline (am)
638 with the *first* character that would fall onto the next line (xenl).
639*/
640
641void TEScreen::checkSelection(int from, int to)
642{
643 if (sel_begin == -1) return;
644 int scr_TL = loc(0, hist.getLines());
645 //Clear entire selection if it overlaps region [from, to]
646 if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) )
647 {
648 clearSelection();
649 }
650}
651
652void TEScreen::ShowCharacter(unsigned short c)
653{
654 // Note that VT100 does wrapping BEFORE putting the character.
655 // This has impact on the assumption of valid cursor positions.
656 // We indicate the fact that a newline has to be triggered by
657 // putting the cursor one right to the last column of the screen.
658
659 if (cuX >= columns)
660 {
661 if (getMode(MODE_Wrap)) NextLine(); else cuX = columns-1;
662 }
663
664 if (getMode(MODE_Insert)) insertChars(1);
665
666 int i = loc(cuX,cuY);
667
668 checkSelection(i, i); // check if selection is still valid.
669
670 image[i].c = c;
671 image[i].f = ef_fg;
672 image[i].b = ef_bg;
673 image[i].r = ef_re;
674
675 cuX += 1;
676}
677
678// Region commands -------------------------------------------------------------
679
680
681/*! scroll up `n' lines within current region.
682 The `n' new lines are cleared.
683 \sa setRegion \sa scrollDown
684*/
685
686void TEScreen::scrollUp(int from, int n)
687{
688 if (n <= 0 || from + n > bmargin) return;
689 //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
690 moveImage(loc(0,from),loc(0,from+n),loc(columns-1,bmargin));
691 clearImage(loc(0,bmargin-n+1),loc(columns-1,bmargin),' ');
692}
693
694/*! scroll down `n' lines within current region.
695 The `n' new lines are cleared.
696 \sa setRegion \sa scrollUp
697*/
698
699void TEScreen::scrollDown(int from, int n)
700{
701//FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
702 if (n <= 0) return;
703 if (from > bmargin) return;
704 if (from + n > bmargin) n = bmargin - from;
705 moveImage(loc(0,from+n),loc(0,from),loc(columns-1,bmargin-n));
706 clearImage(loc(0,from),loc(columns-1,from+n-1),' ');
707}
708
709/*! position the cursor to a specific line and column. */
710void TEScreen::setCursorYX(int y, int x)
711{
712 setCursorY(y); setCursorX(x);
713}
714
715/*! Set the cursor to x-th line. */
716
717void TEScreen::setCursorX(int x)
718{
719 if (x == 0) x = 1; // Default
720 x -= 1; // Adjust
721 cuX = QMAX(0,QMIN(columns-1, x));
722}
723
724/*! Set the cursor to y-th line. */
725
726void TEScreen::setCursorY(int y)
727{
728 if (y == 0) y = 1; // Default
729 y -= 1; // Adjust
730 cuY = QMAX(0,QMIN(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) ));
731}
732
733/*! set cursor to the `left upper' corner of the screen (1,1).
734*/
735
736void TEScreen::home()
737{
738 cuX = 0;
739 cuY = 0;
740}
741
742/*! set cursor to the begin of the current line.
743*/
744
745void TEScreen::Return()
746{
747 cuX = 0;
748}
749
750/*! returns the current cursor columns.
751*/
752
753int TEScreen::getCursorX()
754{
755 return cuX;
756}
757
758/*! returns the current cursor line.
759*/
760
761int TEScreen::getCursorY()
762{
763 return cuY;
764}
765
766// Erasing ---------------------------------------------------------------------
767
768/*! \section Erasing
769
770 This group of operations erase parts of the screen contents by filling
771 it with spaces colored due to the current rendition settings.
772
773 Althought the cursor position is involved in most of these operations,
774 it is never modified by them.
775*/
776
777/*! fill screen between (including) `loca' and `loce' with spaces.
778
779 This is an internal helper functions. The parameter types are internal
780 addresses of within the screen image and make use of the way how the
781 screen matrix is mapped to the image vector.
782*/
783
784void TEScreen::clearImage(int loca, int loce, char c)
785{ int i;
786 int scr_TL=loc(0,hist.getLines());
787 //FIXME: check positions
788
789 //Clear entire selection if it overlaps region to be moved...
790 if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) )
791 {
792 clearSelection();
793 }
794 for (i = loca; i <= loce; i++)
795 {
796 image[i].c = c;
797 image[i].f = ef_fg; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi
798 image[i].b = ef_bg; //DEFAULT_BACK_COLOR; // many have different
799 image[i].r = ef_re; //DEFAULT_RENDITION; // ideas here.
800 }
801}
802
803/*! move image between (including) `loca' and `loce' to 'dst'.
804
805 This is an internal helper functions. The parameter types are internal
806 addresses of within the screen image and make use of the way how the
807 screen matrix is mapped to the image vector.
808*/
809
810void TEScreen::moveImage(int dst, int loca, int loce)
811{
812//FIXME: check positions
813 if (loce < loca) {
814 // kdDebug() << "WARNING!!! call to TEScreen:moveImage with loce < loca!" << endl;
815 return;
816 }
817 memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(ca));
818}
819
820/*! clear from (including) current cursor position to end of screen.
821*/
822
823void TEScreen::clearToEndOfScreen()
824{
825 clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
826}
827
828/*! clear from begin of screen to (including) current cursor position.
829*/
830
831void TEScreen::clearToBeginOfScreen()
832{
833 clearImage(loc(0,0),loc(cuX,cuY),' ');
834}
835
836/*! clear the entire screen.
837*/
838
839void TEScreen::clearEntireScreen()
840{
841 clearImage(loc(0,0),loc(columns-1,lines-1),' ');
842}
843
844/*! fill screen with 'E'
845 This is to aid screen alignment
846*/
847
848void TEScreen::helpAlign()
849{
850 clearImage(loc(0,0),loc(columns-1,lines-1),'E');
851}
852
853/*! clear from (including) current cursor position to end of current cursor line.
854*/
855
856void TEScreen::clearToEndOfLine()
857{
858 clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
859}
860
861/*! clear from begin of current cursor line to (including) current cursor position.
862*/
863
864void TEScreen::clearToBeginOfLine()
865{
866 clearImage(loc(0,cuY),loc(cuX,cuY),' ');
867}
868
869/*! clears entire current cursor line
870*/
871
872void TEScreen::clearEntireLine()
873{
874 clearImage(loc(0,cuY),loc(columns-1,cuY),' ');
875}
876
877// Rendition ------------------------------------------------------------------
878
879/*!
880 set rendition mode
881*/
882
883void TEScreen::setRendition(int re)
884{
885 cu_re |= re;
886 effectiveRendition();
887}
888
889/*!
890 reset rendition mode
891*/
892
893void TEScreen::resetRendition(int re)
894{
895 cu_re &= ~re;
896 effectiveRendition();
897}
898
899/*!
900*/
901
902void TEScreen::setDefaultRendition()
903{
904 setForeColorToDefault();
905 setBackColorToDefault();
906 cu_re = DEFAULT_RENDITION;
907 effectiveRendition();
908}
909
910/*!
911*/
912
913void TEScreen::setForeColor(int fgcolor)
914{
915 cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2);
916 effectiveRendition();
917}
918
919/*!
920*/
921
922void TEScreen::setBackColor(int bgcolor)
923{
924 cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2);
925 effectiveRendition();
926}
927
928/*!
929*/
930
931void TEScreen::setBackColorToDefault()
932{
933 cu_bg = DEFAULT_BACK_COLOR;
934 effectiveRendition();
935}
936
937/*!
938*/
939
940void TEScreen::setForeColorToDefault()
941{
942 cu_fg = DEFAULT_FORE_COLOR;
943 effectiveRendition();
944}
945
946/* ------------------------------------------------------------------------- */
947/* */
948/* Marking & Selection */
949/* */
950/* ------------------------------------------------------------------------- */
951
952void TEScreen::clearSelection()
953{
954 sel_BR = -1;
955 sel_TL = -1;
956 sel_begin = -1;
957}
958
959void TEScreen::setSelBeginXY(const int x, const int y)
960{
961 sel_begin = loc(x,y+histCursor) ;
962 sel_BR = sel_begin;
963 sel_TL = sel_begin;
964}
965
966void TEScreen::setSelExtentXY(const int x, const int y)
967{
968 if (sel_begin == -1) return;
969 int l = loc(x,y + histCursor);
970
971 if (l < sel_begin)
972 {
973 sel_TL = l;
974 sel_BR = sel_begin;
975 }
976 else
977 {
978 /* FIXME, HACK to correct for x too far to the right... */
979 if (( x == columns )|| (x == 0)) l--;
980
981 sel_TL = sel_begin;
982 sel_BR = l;
983 }
984}
985
986QString TEScreen::getSelText(const BOOL preserve_line_breaks)
987{
988 if (sel_begin == -1)
989 return QString::null; // Selection got clear while selecting.
990
991 int *m; // buffer to fill.
992 int s, d; // source index, dest. index.
993 int hist_BR = loc(0, hist.getLines());
994 int hY = sel_TL / columns;
995 int hX = sel_TL % columns;
996 int eol; // end of line
997
998 s = sel_TL; // tracks copy in source.
999
1000 // allocate buffer for maximum
1001 // possible size...
1002 d = (sel_BR - sel_TL) / columns + 1;
1003 m = new int[d * (columns + 1) + 2];
1004 d = 0;
1005
1006 while (s <= sel_BR)
1007 {
1008 if (s < hist_BR)
1009 { // get lines from hist.history
1010 // buffer.
1011 eol = hist.getLineLen(hY);
1012
1013 if ((hY == (sel_BR / columns)) &&
1014 (eol >= (sel_BR % columns)))
1015 {
1016 eol = sel_BR % columns + 1;
1017 }
1018
1019 while (hX < eol)
1020 {
1021 m[d++] = hist.getCell(hY, hX++).c;
1022 s++;
1023 }
1024
1025 if (s <= sel_BR)
1026 {
1027 // The line break handling
1028 // It's different from the screen
1029 // image case!
1030 if (eol % columns == 0)
1031 {
1032 // That's either a completely filled
1033 // line or an empty line
1034 if (eol == 0)
1035 {
1036 m[d++] = '\n';
1037 }
1038 else
1039 {
1040 // We have a full line.
1041 // FIXME: How can we handle newlines
1042 // at this position?!
1043 }
1044 }
1045 else if ((eol + 1) % columns == 0)
1046 {
1047 // FIXME: We don't know if this was a
1048 // space at the last position or a
1049 // short line!!
1050 m[d++] = ' ';
1051 }
1052 else
1053 {
1054 // We have a short line here. Put a
1055 // newline or a space into the
1056 // buffer.
1057 m[d++] = preserve_line_breaks ? '\n' : ' ';
1058 }
1059 }
1060
1061 hY++;
1062 hX = 0;
1063 s = hY * columns;
1064 }
1065 else
1066 { // or from screen image.
1067 eol = (s / columns + 1) * columns - 1;
1068
1069 if (eol < sel_BR)
1070 {
1071 while ((eol > s) &&
1072 isspace(image[eol - hist_BR].c))
1073 {
1074 eol--;
1075 }
1076 }
1077 else
1078 {
1079 eol = sel_BR;
1080 }
1081
1082 while (s <= eol)
1083 {
1084 m[d++] = image[s++ - hist_BR].c;
1085 }
1086
1087 if (eol < sel_BR)
1088 {
1089 // eol processing see below ...
1090 if ((eol + 1) % columns == 0)
1091 {
1092 if (image[eol - hist_BR].c == ' ')
1093 {
1094 m[d++] = ' ';
1095 }
1096 }
1097 else
1098 {
1099 m[d++] = ((preserve_line_breaks ||
1100 ((eol % columns) == 0)) ?
1101 '\n' : ' ');
1102 }
1103 }
1104
1105 s = (eol / columns + 1) * columns;
1106 }
1107 }
1108
1109 QChar* qc = new QChar[d];
1110
1111 for (int i = 0; i < d; i++)
1112 {
1113 qc[i] = m[i];
1114 }
1115
1116 QString res(qc, d);
1117
1118 delete m;
1119 delete qc;
1120
1121 return res;
1122}
1123/* above ... end of line processing for selection -- psilva
1124cases:
1125
11261) (eol+1)%columns == 0 --> the whole line is filled.
1127 If the last char is a space, insert (preserve) space. otherwise
1128 leave the text alone, so that words that are broken by linewrap
1129 are preserved.
1130
1131FIXME:
1132 * this suppresses \n for command output that is
1133 sized to the exact column width of the screen.
1134
11352) eol%columns == 0 --> blank line.
1136 insert a \n unconditionally.
1137 Do it either you would because you are in preserve_line_break mode,
1138 or because it's an ASCII paragraph delimiter, so even when
1139 not preserving line_breaks, you want to preserve paragraph breaks.
1140
1141 3) else --> partially filled line
1142 insert a \n in preserve line break mode, else a space
1143 The space prevents concatenation of the last word of one
1144 line with the first of the next.
1145
1146*/
1147
1148void TEScreen::addHistLine()
1149{
1150 assert(hasScroll() || histCursor == 0);
1151
1152 // add to hist buffer
1153 // we have to take care about scrolling, too...
1154
1155 if (hasScroll())
1156 { ca dft;
1157
1158 int end = columns-1;
1159 while (end >= 0 && image[end] == dft)
1160 end -= 1;
1161
1162 hist.addCells(image,end+1);
1163 hist.addLine();
1164
1165 // adjust history cursor
1166 histCursor += (hist.getLines()-1 == histCursor);
1167 }
1168
1169 if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround
1170}
1171
1172void TEScreen::setHistCursor(int cursor)
1173{
1174 histCursor = cursor; //FIXME:rangecheck
1175}
1176
1177int TEScreen::getHistCursor()
1178{
1179 return histCursor;
1180}
1181
1182int TEScreen::getHistLines()
1183{
1184 return hist.getLines();
1185}
1186
1187void TEScreen::setScroll(bool on)
1188{
1189 histCursor = 0;
1190 clearSelection();
1191 hist.setScroll(on);
1192}
1193
1194bool TEScreen::hasScroll()
1195{
1196 return hist.hasScroll();
1197}
diff --git a/noncore/apps/opie-console/TEScreen.h b/noncore/apps/opie-console/TEScreen.h
new file mode 100644
index 0000000..ba47ee5
--- a/dev/null
+++ b/noncore/apps/opie-console/TEScreen.h
@@ -0,0 +1,259 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [te_screen.h] Screen Data Type */
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#ifndef TESCREEN_H
20#define TESCREEN_H
21
22/*! \file
23*/
24
25#include "TECommon.h"
26#include "TEHistory.h"
27
28#define MODE_Origin 0
29#define MODE_Wrap 1
30#define MODE_Insert 2
31#define MODE_Screen 3
32#define MODE_Cursor 4
33#define MODE_NewLine 5
34#define MODES_SCREEN 6
35
36/*!
37*/
38struct ScreenParm
39{
40 int mode[MODES_SCREEN];
41};
42
43
44class TEScreen
45{
46public:
47 TEScreen(int lines, int columns);
48 ~TEScreen();
49
50public: // these are all `Screen' operations
51 //
52 // VT100/2 Operations ------------------
53 //
54 // Cursor Movement
55 //
56 void cursorUp (int n);
57 void cursorDown (int n);
58 void cursorLeft (int n);
59 void cursorRight (int n);
60 void setCursorY (int y);
61 void setCursorX (int x);
62 void setCursorYX (int y, int x);
63 void setMargins (int t, int b);
64 //
65 // Cursor Movement with Scrolling
66 //
67 void NewLine ();
68 void NextLine ();
69 void index ();
70 void reverseIndex();
71 //
72 void Return ();
73 void BackSpace ();
74 void Tabulate ();
75 //
76 // Editing
77 //
78 void eraseChars (int n);
79 void deleteChars (int n);
80 void insertChars (int n);
81 void deleteLines (int n);
82 void insertLines (int n);
83 //
84 // -------------------------------------
85 //
86 void clearTabStops();
87 void changeTabStop(bool set);
88 //
89 void resetMode (int n);
90 void setMode (int n);
91 void saveMode (int n);
92 void restoreMode (int n);
93 //
94 void saveCursor ();
95 void restoreCursor();
96 //
97 // -------------------------------------
98 //
99 void clearEntireScreen();
100 void clearToEndOfScreen();
101 void clearToBeginOfScreen();
102 //
103 void clearEntireLine();
104 void clearToEndOfLine();
105 void clearToBeginOfLine();
106 //
107 void helpAlign ();
108 //
109 // -------------------------------------
110 //
111 void setRendition (int rendition);
112 void resetRendition(int rendition);
113 void setForeColor (int fgcolor);
114 void setBackColor (int bgcolor);
115 //
116 void setDefaultRendition();
117 void setForeColorToDefault();
118 void setBackColorToDefault();
119 //
120 // -------------------------------------
121 //
122 BOOL getMode (int n);
123 //
124 // only for report cursor position
125 //
126 int getCursorX();
127 int getCursorY();
128 //
129 // -------------------------------------
130 //
131 void clear();
132 void home();
133 void reset();
134 //
135 void ShowCharacter(unsigned short c);
136 //
137 void resizeImage(int new_lines, int new_columns);
138 //
139 ca* getCookedImage();
140
141 /*! return the number of lines. */
142 int getLines() { return lines; }
143 /*! return the number of columns. */
144 int getColumns() { return columns; }
145
146 /*! set the position of the history cursor. */
147 void setHistCursor(int cursor);
148 /*! return the position of the history cursor. */
149 int getHistCursor();
150
151 int getHistLines ();
152 void setScroll(bool on);
153 bool hasScroll();
154
155 //
156 // Selection
157 //
158 void setSelBeginXY(const int x, const int y);
159 void setSelExtentXY(const int x, const int y);
160 void clearSelection();
161 QString getSelText(const BOOL preserve_line_breaks);
162
163 void checkSelection(int from, int to);
164
165private: // helper
166
167 void clearImage(int loca, int loce, char c);
168 void moveImage(int dst, int loca, int loce);
169
170 void scrollUp(int from, int i);
171 void scrollDown(int from, int i);
172
173 void addHistLine();
174
175 void initTabStops();
176
177 void effectiveRendition();
178 void reverseRendition(ca* p);
179
180private:
181
182 /*
183 The state of the screen is more complex as one would
184 expect first. The screem does really do part of the
185 emulation providing state informations in form of modes,
186 margins, tabulators, cursor etc.
187
188 Even more unexpected are variables to save and restore
189 parts of the state.
190 */
191
192 // screen image ----------------
193
194 int lines;
195 int columns;
196 ca *image; // [lines][columns]
197
198 // history buffer ---------------
199
200 int histCursor; // display position relative to start of the history buffer
201 HistoryScroll hist;
202
203 // cursor location
204
205 int cuX;
206 int cuY;
207
208 // cursor color and rendition info
209
210 UINT8 cu_fg; // foreground
211 UINT8 cu_bg; // background
212 UINT8 cu_re; // rendition
213
214 // margins ----------------
215
216 int tmargin; // top margin
217 int bmargin; // bottom margin
218
219 // states ----------------
220
221 ScreenParm currParm;
222
223 // ----------------------------
224
225 bool* tabstops;
226
227 // selection -------------------
228
229 int sel_begin; // The first location selected.
230 int sel_TL; // TopLeft Location.
231 int sel_BR; // Bottom Right Location.
232
233 // effective colors and rendition ------------
234
235 UINT8 ef_fg; // These are derived from
236 UINT8 ef_bg; // the cu_* variables above
237 UINT8 ef_re; // to speed up operation
238
239 //
240 // save cursor, rendition & states ------------
241 //
242
243 // cursor location
244
245 int sa_cuX;
246 int sa_cuY;
247
248 // rendition info
249
250 UINT8 sa_cu_re;
251 UINT8 sa_cu_fg;
252 UINT8 sa_cu_bg;
253
254 // modes
255
256 ScreenParm saveParm;
257};
258
259#endif // TESCREEN_H
diff --git a/noncore/apps/opie-console/TEWidget.cpp b/noncore/apps/opie-console/TEWidget.cpp
new file mode 100644
index 0000000..75c438c
--- a/dev/null
+++ b/noncore/apps/opie-console/TEWidget.cpp
@@ -0,0 +1,1264 @@
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/*! \class TEWidget
19
20 \brief Visible screen contents
21
22 This class is responsible to map the `image' of a terminal emulation to the
23 display. All the dependency of the emulation to a specific GUI or toolkit is
24 localized here. Further, this widget has no knowledge about being part of an
25 emulation, it simply work within the terminal emulation framework by exposing
26 size and key events and by being ordered to show a new image.
27
28 <ul>
29 <li> The internal image has the size of the widget (evtl. rounded up)
30 <li> The external image used in setImage can have any size.
31 <li> (internally) the external image is simply copied to the internal
32 when a setImage happens. During a resizeEvent no painting is done
33 a paintEvent is expected to follow anyway.
34 </ul>
35
36 \sa TEScreen \sa Emulation
37*/
38
39/* FIXME:
40 - 'image' may also be used uninitialized (it isn't in fact) in resizeEvent
41 - 'font_a' not used in mouse events
42 - add destructor
43*/
44
45/* TODO
46 - evtl. be sensitive to `paletteChange' while using default colors.
47 - set different 'rounding' styles? I.e. have a mode to show clipped chars?
48*/
49
50// #include "config.h"
51#include "TEWidget.h"
52#include "session.h"
53#include <qpe/config.h>
54
55#include <qapplication.h>
56#include <qcursor.h>
57#include <qregexp.h>
58#include <qpainter.h>
59#include <qclipboard.h>
60#include <qstyle.h>
61#include <qfile.h>
62#include <qdragobject.h>
63
64#include <stdio.h>
65#include <stdlib.h>
66#include <unistd.h>
67#include <ctype.h>
68#include <sys/stat.h>
69#include <sys/types.h>
70#include <signal.h>
71
72#include <assert.h>
73
74// #include "TEWidget.moc"
75//#include <kapp.h>
76//#include <kcursor.h>
77//#include <kurl.h>
78//#include <kdebug.h>
79//#include <klocale.h>
80
81#define HERE printf("%s(%d): %s\n",__FILE__,__LINE__,__FUNCTION__)
82#define HCNT(Name) // { static int cnt = 1; printf("%s(%d): %s %d\n",__FILE__,__LINE__,Name,cnt++); }
83
84#define loc(X,Y) ((Y)*columns+(X))
85
86//FIXME: the rim should normally be 1, 0 only when running in full screen mode.
87#define rimX 0 // left/right rim width
88#define rimY 0 // top/bottom rim high
89
90#define SCRWIDTH 16 // width of the scrollbar
91
92#define yMouseScroll 1
93// scroll increment used when dragging selection at top/bottom of window.
94
95/* ------------------------------------------------------------------------- */
96/* */
97/* Colors */
98/* */
99/* ------------------------------------------------------------------------- */
100
101//FIXME: the default color table is in session.C now.
102// We need a way to get rid of this one, here.
103static const ColorEntry base_color_table[TABLE_COLORS] =
104// The following are almost IBM standard color codes, with some slight
105// gamma correction for the dim colors to compensate for bright X screens.
106// It contains the 8 ansiterm/xterm colors in 2 intensities.
107{
108 // Fixme: could add faint colors here, also.
109 // normal
110 ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 1, 0 ), // Dfore, Dback
111 ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red
112 ColorEntry(QColor(0x18,0xB2,0x18), 0, 0 ), ColorEntry( QColor(0xB2,0x68,0x18), 0, 0 ), // Green, Yellow
113 ColorEntry(QColor(0x18,0x18,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), // Blue, Magenta
114 ColorEntry(QColor(0x18,0xB2,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 0, 0 ), // Cyan, White
115 // intensiv
116 ColorEntry(QColor(0x00,0x00,0x00), 0, 1 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 1, 0 ),
117 ColorEntry(QColor(0x68,0x68,0x68), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0x54), 0, 0 ),
118 ColorEntry(QColor(0x54,0xFF,0x54), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0x54), 0, 0 ),
119 ColorEntry(QColor(0x54,0x54,0xFF), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ),
120 ColorEntry(QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 )
121};
122
123/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb)
124
125 Code 0 1 2 3 4 5 6 7
126 ----------- ------- ------- ------- ------- ------- ------- ------- -------
127 ANSI (bgr) Black Red Green Yellow Blue Magenta Cyan White
128 IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White
129*/
130
131QColor TEWidget::getDefaultBackColor()
132{
133 return color_table[DEFAULT_BACK_COLOR].color;
134}
135
136const ColorEntry* TEWidget::getColorTable() const
137{
138 return color_table;
139}
140
141const ColorEntry* TEWidget::getdefaultColorTable() const
142{
143 return base_color_table;
144}
145
146
147const QPixmap *TEWidget::backgroundPixmap()
148{
149 static QPixmap *bg = new QPixmap("~/qpim/main/pics/faded_bg.xpm");
150 const QPixmap *pm = bg;
151 return pm;
152}
153
154void TEWidget::setColorTable(const ColorEntry table[])
155{
156 for (int i = 0; i < TABLE_COLORS; i++) color_table[i] = table[i];
157
158 const QPixmap* pm = backgroundPixmap();
159 if (!pm) setBackgroundColor(color_table[DEFAULT_BACK_COLOR].color);
160 update();
161}
162
163//FIXME: add backgroundPixmapChanged.
164
165/* ------------------------------------------------------------------------- */
166/* */
167/* Font */
168/* */
169/* ------------------------------------------------------------------------- */
170
171/*
172 The VT100 has 32 special graphical characters. The usual vt100 extended
173 xterm fonts have these at 0x00..0x1f.
174
175 QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals
176 come in here as proper unicode characters.
177
178 We treat non-iso10646 fonts as VT100 extended and do the requiered mapping
179 from unicode to 0x00..0x1f. The remaining translation is then left to the
180 QCodec.
181*/
182
183// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.
184
185unsigned short vt100_graphics[32] =
186{ // 0/8 1/9 2/10 3/11 4/12 5/13 6/14 7/15
187 0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0,
188 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,
189 0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534,
190 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7
191};
192
193static QChar vt100extended(QChar c)
194{
195 switch (c.unicode())
196 {
197 case 0x25c6 : return 1;
198 case 0x2592 : return 2;
199 case 0x2409 : return 3;
200 case 0x240c : return 4;
201 case 0x240d : return 5;
202 case 0x240a : return 6;
203 case 0x00b0 : return 7;
204 case 0x00b1 : return 8;
205 case 0x2424 : return 9;
206 case 0x240b : return 10;
207 case 0x2518 : return 11;
208 case 0x2510 : return 12;
209 case 0x250c : return 13;
210 case 0x2514 : return 14;
211 case 0x253c : return 15;
212 case 0xf800 : return 16;
213 case 0xf801 : return 17;
214 case 0x2500 : return 18;
215 case 0xf803 : return 19;
216 case 0xf804 : return 20;
217 case 0x251c : return 21;
218 case 0x2524 : return 22;
219 case 0x2534 : return 23;
220 case 0x252c : return 24;
221 case 0x2502 : return 25;
222 case 0x2264 : return 26;
223 case 0x2265 : return 27;
224 case 0x03c0 : return 28;
225 case 0x2260 : return 29;
226 case 0x00a3 : return 30;
227 case 0x00b7 : return 31;
228 }
229 return c;
230}
231
232static QChar identicalMap(QChar c)
233{
234 return c;
235}
236
237void TEWidget::fontChange(const QFont &)
238{
239 QFontMetrics fm(font());
240 font_h = fm.height();
241 font_w = fm.maxWidth();
242 font_a = fm.ascent();
243//printf("font_h: %d\n",font_h);
244//printf("font_w: %d\n",font_w);
245//printf("font_a: %d\n",font_a);
246//printf("charset: %s\n",QFont::encodingName(font().charSet()).ascii());
247//printf("rawname: %s\n",font().rawName().ascii());
248 fontMap =
249#if QT_VERSION < 300
250 strcmp(QFont::encodingName(font().charSet()).ascii(),"iso10646")
251 ? vt100extended
252 :
253#endif
254 identicalMap;
255 propagateSize();
256 update();
257}
258
259void TEWidget::setVTFont(const QFont& f)
260{
261 QFrame::setFont(f);
262}
263
264QFont TEWidget::getVTFont() {
265 return font();
266}
267
268void TEWidget::setFont(const QFont &)
269{
270 // ignore font change request if not coming from konsole itself
271}
272
273/* ------------------------------------------------------------------------- */
274/* */
275/* Constructor / Destructor */
276/* */
277/* ------------------------------------------------------------------------- */
278
279TEWidget::TEWidget(QWidget *parent, const char *name) : QFrame(parent,name)
280{
281#ifndef QT_NO_CLIPBOARD
282 cb = QApplication::clipboard();
283 QObject::connect( (QObject*)cb, SIGNAL(dataChanged()),
284 this, SLOT(onClearSelection()) );
285#endif
286
287 scrollbar = new QScrollBar(this);
288 scrollbar->setCursor( arrowCursor );
289 connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
290
291 Config cfg("Konsole");
292 cfg.setGroup("ScrollBar");
293 switch( cfg.readNumEntry("Position",2)){
294 case 0:
295 scrollLoc = SCRNONE;
296 break;
297 case 1:
298 scrollLoc = SCRLEFT;
299 break;
300 case 2:
301 scrollLoc = SCRRIGHT;
302 break;
303 };
304
305 blinkT = new QTimer(this);
306 connect(blinkT, SIGNAL(timeout()), this, SLOT(blinkEvent()));
307 // blinking = FALSE;
308 blinking = TRUE;
309
310 resizing = FALSE;
311 actSel = 0;
312 image = 0;
313 lines = 1;
314 columns = 1;
315 font_w = 1;
316 font_h = 1;
317 font_a = 1;
318 word_selection_mode = FALSE;
319
320 setMouseMarks(TRUE);
321 setVTFont( QFont("fixed") );
322 setColorTable(base_color_table); // init color table
323
324 qApp->installEventFilter( this ); //FIXME: see below
325// KCursor::setAutoHideCursor( this, true );
326
327 // Init DnD ////////////////////////////////////////////////////////////////
328 currentSession = NULL;
329// setAcceptDrops(true); // attempt
330// m_drop = new QPopupMenu(this);
331// m_drop->insertItem( QString("Paste"), 0);
332// m_drop->insertItem( QString("cd"), 1);
333// connect(m_drop, SIGNAL(activated(int)), SLOT(drop_menu_activated(int)));
334
335 // we need focus so that the auto-hide cursor feature works
336 setFocus();
337 setFocusPolicy( WheelFocus );
338}
339
340//FIXME: make proper destructor
341// Here's a start (David)
342TEWidget::~TEWidget()
343{
344 qApp->removeEventFilter( this );
345 if (image) free(image);
346}
347
348/* ------------------------------------------------------------------------- */
349/* */
350/* Display Operations */
351/* */
352/* ------------------------------------------------------------------------- */
353
354/*!
355 attributed string draw primitive
356*/
357
358void TEWidget::drawAttrStr(QPainter &paint, QRect rect,
359 QString& str, ca attr, BOOL pm, BOOL clear)
360{
361 if (pm && color_table[attr.b].transparent)
362 {
363 paint.setBackgroundMode( TransparentMode );
364 if (clear) erase(rect);
365 }
366 else
367 {
368 if (blinking)
369 paint.fillRect(rect, color_table[attr.b].color);
370 else
371 {
372 paint.setBackgroundMode( OpaqueMode );
373 paint.setBackgroundColor( color_table[attr.b].color );
374 }
375 }
376
377 if (color_table[attr.f].bold)
378 paint.setPen(QColor( 0x8F, 0x00, 0x00 ));
379 else
380 paint.setPen(color_table[attr.f].color);
381
382 paint.drawText(rect.x(),rect.y()+font_a, str);
383
384 if (attr.r & RE_UNDERLINE)
385 paint.drawLine(rect.left(), rect.y()+font_a+1, rect.right(),rect.y()+font_a+1 );
386}
387
388/*!
389 The image can only be set completely.
390
391 The size of the new image may or may not match the size of the widget.
392*/
393
394void TEWidget::setImage(const ca* const newimg, int lines, int columns)
395{ int y,x,len;
396 const QPixmap* pm = backgroundPixmap();
397 QPainter paint;
398 setUpdatesEnabled(FALSE);
399 paint.begin( this );
400HCNT("setImage");
401
402 QPoint tL = contentsRect().topLeft();
403 int tLx = tL.x();
404 int tLy = tL.y();
405 hasBlinker = FALSE;
406
407 int cf = -1; // undefined
408 int cb = -1; // undefined
409 int cr = -1; // undefined
410
411 int lins = QMIN(this->lines, QMAX(0,lines ));
412 int cols = QMIN(this->columns,QMAX(0,columns));
413 QChar *disstrU = new QChar[cols];
414
415//{ static int cnt = 0; printf("setImage %d\n",cnt++); }
416 for (y = 0; y < lins; y++)
417 {
418 const ca* lcl = &image[y*this->columns];
419 const ca* const ext = &newimg[y*columns];
420 if (!resizing) // not while resizing, we're expecting a paintEvent
421 for (x = 0; x < cols; x++)
422 {
423 hasBlinker |= (ext[x].r & RE_BLINK);
424 if (ext[x] != lcl[x])
425 {
426 cr = ext[x].r;
427 cb = ext[x].b;
428 if (ext[x].f != cf) cf = ext[x].f;
429 int lln = cols - x;
430 disstrU[0] = fontMap(ext[x+0].c);
431 for (len = 1; len < lln; len++)
432 {
433 if (ext[x+len].f != cf || ext[x+len].b != cb || ext[x+len].r != cr ||
434 ext[x+len] == lcl[x+len] )
435 break;
436 disstrU[len] = fontMap(ext[x+len].c);
437 }
438 QString unistr(disstrU,len);
439 drawAttrStr(paint,
440 QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
441 unistr, ext[x], pm != NULL, true);
442 x += len - 1;
443 }
444 }
445 // finally, make `image' become `newimg'.
446 memcpy((void*)lcl,(const void*)ext,cols*sizeof(ca));
447 }
448 drawFrame( &paint );
449 paint.end();
450 setUpdatesEnabled(TRUE);
451 if ( hasBlinker && !blinkT->isActive()) blinkT->start(1000); // 1000 ms
452 if (!hasBlinker && blinkT->isActive()) { blinkT->stop(); blinking = FALSE; }
453 delete [] disstrU;
454}
455
456// paint Event ////////////////////////////////////////////////////
457
458/*!
459 The difference of this routine vs. the `setImage' is,
460 that the drawing does not include a difference analysis
461 between the old and the new image. Instead, the internal
462 image is used and the painting bound by the PaintEvent box.
463*/
464
465void TEWidget::paintEvent( QPaintEvent* pe )
466{
467
468//{ static int cnt = 0; printf("paint %d\n",cnt++); }
469 const QPixmap* pm = backgroundPixmap();
470 QPainter paint;
471 setUpdatesEnabled(FALSE);
472 paint.begin( this );
473 paint.setBackgroundMode( TransparentMode );
474HCNT("paintEvent");
475
476 // Note that the actual widget size can be slightly larger
477 // that the image (the size is truncated towards the smaller
478 // number of characters in `resizeEvent'. The paint rectangle
479 // can thus be larger than the image, but less then the size
480 // of one character.
481
482 QRect rect = pe->rect().intersect(contentsRect());
483
484 QPoint tL = contentsRect().topLeft();
485 int tLx = tL.x();
486 int tLy = tL.y();
487
488 int lux = QMIN(columns-1, QMAX(0,(rect.left() - tLx - blX ) / font_w));
489 int luy = QMIN(lines-1, QMAX(0,(rect.top() - tLy - bY ) / font_h));
490 int rlx = QMIN(columns-1, QMAX(0,(rect.right() - tLx - blX ) / font_w));
491 int rly = QMIN(lines-1, QMAX(0,(rect.bottom() - tLy - bY ) / font_h));
492
493 /*
494 printf("paintEvent: %d..%d, %d..%d (%d..%d, %d..%d)\n",lux,rlx,luy,rly,
495 rect.left(), rect.right(), rect.top(), rect.bottom());
496 */
497
498 // if (pm != NULL && color_table[image->b].transparent)
499 // erase(rect);
500 // BL: I have no idea why we need this, and it breaks the refresh.
501
502 QChar *disstrU = new QChar[columns];
503 for (int y = luy; y <= rly; y++)
504 for (int x = lux; x <= rlx; x++)
505 {
506 int len = 1;
507 disstrU[0] = fontMap(image[loc(x,y)].c);
508 int cf = image[loc(x,y)].f;
509 int cb = image[loc(x,y)].b;
510 int cr = image[loc(x,y)].r;
511 while (x+len <= rlx &&
512 image[loc(x+len,y)].f == cf &&
513 image[loc(x+len,y)].b == cb &&
514 image[loc(x+len,y)].r == cr )
515 {
516 disstrU[len] = fontMap(image[loc(x+len,y)].c);
517 len += 1;
518 }
519 QString unistr(disstrU,len);
520 drawAttrStr(paint,
521 QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
522 unistr, image[loc(x,y)], pm != NULL, false);
523 x += len - 1;
524 }
525 delete [] disstrU;
526 drawFrame( &paint );
527 paint.end();
528 setUpdatesEnabled(TRUE);
529}
530
531void TEWidget::blinkEvent()
532{
533 blinking = !blinking;
534 repaint(FALSE);
535}
536
537/* ------------------------------------------------------------------------- */
538/* */
539/* Resizing */
540/* */
541/* ------------------------------------------------------------------------- */
542
543void TEWidget::resizeEvent(QResizeEvent* ev)
544{
545// printf("resize: %d,%d\n",ev->size().width(),ev->size().height());
546 //printf("approx: %d,%d\n",ev->size().width()/font_w,ev->size().height()/font_h);
547 //printf("leaves: %d,%d\n",ev->size().width()%font_w,ev->size().height()%font_h);
548 //printf("curren: %d,%d\n",width(),height());
549HCNT("resizeEvent");
550
551 // see comment in `paintEvent' concerning the rounding.
552 //FIXME: could make a routine here; check width(),height()
553 assert(ev->size().width() == width());
554 assert(ev->size().height() == height());
555
556 propagateSize();
557}
558
559void TEWidget::propagateSize()
560{
561 ca* oldimg = image;
562 int oldlin = lines;
563 int oldcol = columns;
564 makeImage();
565 // we copy the old image to reduce flicker
566 int lins = QMIN(oldlin,lines);
567 int cols = QMIN(oldcol,columns);
568 if (oldimg)
569 {
570 for (int lin = 0; lin < lins; lin++)
571 memcpy((void*)&image[columns*lin],
572 (void*)&oldimg[oldcol*lin],cols*sizeof(ca));
573 free(oldimg); //FIXME: try new,delete
574 }
575 else
576 clearImage();
577
578 //NOTE: control flows from the back through the chest right into the eye.
579 // `emu' will call back via `setImage'.
580
581 resizing = TRUE;
582 emit changedImageSizeSignal(lines, columns); // expose resizeEvent
583 resizing = FALSE;
584}
585
586/* ------------------------------------------------------------------------- */
587/* */
588/* Scrollbar */
589/* */
590/* ------------------------------------------------------------------------- */
591
592void TEWidget::scrollChanged(int)
593{
594 emit changedHistoryCursor(scrollbar->value()); //expose
595}
596
597void TEWidget::setScroll(int cursor, int slines)
598{
599 disconnect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
600 scrollbar->setRange(0,slines);
601 scrollbar->setSteps(1,lines);
602 scrollbar->setValue(cursor);
603 connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
604}
605
606void TEWidget::setScrollbarLocation(int loc)
607{
608 if (scrollLoc == loc) return; // quickly
609 scrollLoc = loc;
610 propagateSize();
611 update();
612}
613
614/* ------------------------------------------------------------------------- */
615/* */
616/* Mouse */
617/* */
618/* ------------------------------------------------------------------------- */
619
620/*!
621 Three different operations can be performed using the mouse, and the
622 routines in this section serve all of them:
623
624 1) The press/release events are exposed to the application
625 2) Marking (press and move left button) and Pasting (press middle button)
626 3) The right mouse button is used from the configuration menu
627
628 NOTE: During the marking process we attempt to keep the cursor within
629 the bounds of the text as being displayed by setting the mouse position
630 whenever the mouse has left the text area.
631
632 Two reasons to do so:
633 1) QT does not allow the `grabMouse' to confine-to the TEWidget.
634 Thus a `XGrapPointer' would have to be used instead.
635 2) Even if so, this would not help too much, since the text area
636 of the TEWidget is normally not identical with it's bounds.
637
638 The disadvantage of the current handling is, that the mouse can visibly
639 leave the bounds of the widget and is then moved back. Because of the
640 current construction, and the reasons mentioned above, we cannot do better
641 without changing the overall construction.
642*/
643
644/*!
645*/
646
647void TEWidget::mousePressEvent(QMouseEvent* ev)
648{
649//printf("press [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button());
650 if ( !contentsRect().contains(ev->pos()) ) return;
651 QPoint tL = contentsRect().topLeft();
652 int tLx = tL.x();
653 int tLy = tL.y();
654
655 word_selection_mode = FALSE;
656
657//printf("press top left [%d,%d] by=%d\n",tLx,tLy, bY);
658 if ( ev->button() == LeftButton)
659 {
660 QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
661
662 if ( ev->state() & ControlButton ) preserve_line_breaks = FALSE ;
663
664 if (mouse_marks || (ev->state() & ShiftButton))
665 {
666 emit clearSelectionSignal();
667 iPntSel = pntSel = pos;
668 actSel = 1; // left mouse button pressed but nothing selected yet.
669 grabMouse( /*crossCursor*/ ); // handle with care!
670 }
671 else
672 {
673 emit mouseSignal( 0, pos.x() + 1, pos.y() + 1 ); // left button
674 }
675 }
676 if ( ev->button() == MidButton )
677 {
678 emitSelection();
679 }
680 if ( ev->button() == RightButton ) // Configure
681 {
682 emit configureRequest( this, ev->state()&(ShiftButton|ControlButton), ev->x(), ev->y() );
683 }
684}
685
686void TEWidget::mouseMoveEvent(QMouseEvent* ev)
687{
688 // for auto-hiding the cursor, we need mouseTracking
689 if (ev->state() == NoButton ) return;
690
691 if (actSel == 0) return;
692
693 // don't extend selection while pasting
694 if (ev->state() & MidButton) return;
695
696 //if ( !contentsRect().contains(ev->pos()) ) return;
697 QPoint tL = contentsRect().topLeft();
698 int tLx = tL.x();
699 int tLy = tL.y();
700 int scroll = scrollbar->value();
701
702 // we're in the process of moving the mouse with the left button pressed
703 // the mouse cursor will kept catched within the bounds of the text in
704 // this widget.
705
706 // Adjust position within text area bounds. See FIXME above.
707 QPoint pos = ev->pos();
708 if ( pos.x() < tLx+blX ) pos.setX( tLx+blX );
709 if ( pos.x() > tLx+blX+columns*font_w-1 ) pos.setX( tLx+blX+columns*font_w );
710 if ( pos.y() < tLy+bY ) pos.setY( tLy+bY );
711 if ( pos.y() > tLy+bY+lines*font_h-1 ) pos.setY( tLy+bY+lines*font_h-1 );
712 // check if we produce a mouse move event by this
713 if ( pos != ev->pos() ) cursor().setPos(mapToGlobal(pos));
714
715 if ( pos.y() == tLy+bY+lines*font_h-1 )
716 {
717 scrollbar->setValue(scrollbar->value()+yMouseScroll); // scrollforward
718 }
719 if ( pos.y() == tLy+bY )
720 {
721 scrollbar->setValue(scrollbar->value()-yMouseScroll); // scrollback
722 }
723
724 QPoint here = QPoint((pos.x()-tLx-blX)/font_w,(pos.y()-tLy-bY)/font_h);
725 QPoint ohere;
726 bool swapping = FALSE;
727
728 if ( word_selection_mode )
729 {
730 // Extend to word boundaries
731 int i;
732 int selClass;
733
734 bool left_not_right = ( here.y() < iPntSel.y() ||
735 here.y() == iPntSel.y() && here.x() < iPntSel.x() );
736 bool old_left_not_right = ( pntSel.y() < iPntSel.y() ||
737 pntSel.y() == iPntSel.y() && pntSel.x() < iPntSel.x() );
738 swapping = left_not_right != old_left_not_right;
739
740 // Find left (left_not_right ? from here : from start)
741 QPoint left = left_not_right ? here : iPntSel;
742 i = loc(left.x(),left.y());
743 selClass = charClass(image[i].c);
744 while ( left.x() > 0 && charClass(image[i-1].c) == selClass )
745 { i--; left.rx()--; }
746
747 // Find left (left_not_right ? from start : from here)
748 QPoint right = left_not_right ? iPntSel : here;
749 i = loc(right.x(),right.y());
750 selClass = charClass(image[i].c);
751 while ( right.x() < columns-1 && charClass(image[i+1].c) == selClass )
752 { i++; right.rx()++; }
753
754 // Pick which is start (ohere) and which is extension (here)
755 if ( left_not_right )
756 {
757 here = left; ohere = right;
758 }
759 else
760 {
761 here = right; ohere = left;
762 }
763 }
764
765 if (here == pntSel && scroll == scrollbar->value()) return; // not moved
766
767 if ( word_selection_mode ) {
768 if ( actSel < 2 || swapping ) {
769 emit beginSelectionSignal( ohere.x(), ohere.y() );
770 }
771 } else if ( actSel < 2 ) {
772 emit beginSelectionSignal( pntSel.x(), pntSel.y() );
773 }
774
775 actSel = 2; // within selection
776 pntSel = here;
777 emit extendSelectionSignal( here.x(), here.y() );
778}
779
780void TEWidget::mouseReleaseEvent(QMouseEvent* ev)
781{
782//printf("release [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button());
783 if ( ev->button() == LeftButton)
784 {
785 if ( actSel > 1 ) emit endSelectionSignal(preserve_line_breaks);
786 preserve_line_breaks = TRUE;
787 actSel = 0;
788
789 //FIXME: emits a release event even if the mouse is
790 // outside the range. The procedure used in `mouseMoveEvent'
791 // applies here, too.
792
793 QPoint tL = contentsRect().topLeft();
794 int tLx = tL.x();
795 int tLy = tL.y();
796
797 if (!mouse_marks && !(ev->state() & ShiftButton))
798 emit mouseSignal( 3, // release
799 (ev->x()-tLx-blX)/font_w + 1,
800 (ev->y()-tLy-bY)/font_h + 1 );
801 releaseMouse();
802 }
803}
804
805void TEWidget::mouseDoubleClickEvent(QMouseEvent* ev)
806{
807 if ( ev->button() != LeftButton) return;
808
809 QPoint tL = contentsRect().topLeft();
810 int tLx = tL.x();
811 int tLy = tL.y();
812 QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
813
814 // pass on double click as two clicks.
815 if (!mouse_marks && !(ev->state() & ShiftButton))
816 {
817 emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button
818 emit mouseSignal( 3, pos.x()+1, pos.y()+1 ); // release
819 emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button
820 return;
821 }
822
823
824 emit clearSelectionSignal();
825 QPoint bgnSel = pos;
826 QPoint endSel = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
827 int i = loc(bgnSel.x(),bgnSel.y());
828 iPntSel = bgnSel;
829
830 word_selection_mode = TRUE;
831
832 // find word boundaries...
833 int selClass = charClass(image[i].c);
834 {
835 // set the start...
836 int x = bgnSel.x();
837 while ( x > 0 && charClass(image[i-1].c) == selClass )
838 { i--; x--; }
839 bgnSel.setX(x);
840 emit beginSelectionSignal( bgnSel.x(), bgnSel.y() );
841
842 // set the end...
843 i = loc( endSel.x(), endSel.y() );
844 x = endSel.x();
845 while( x < columns-1 && charClass(image[i+1].c) == selClass )
846 { i++; x++ ; }
847 endSel.setX(x);
848 actSel = 2; // within selection
849 emit extendSelectionSignal( endSel.x(), endSel.y() );
850 emit endSelectionSignal(preserve_line_breaks);
851 preserve_line_breaks = TRUE;
852 }
853}
854
855void TEWidget::focusInEvent( QFocusEvent * )
856{
857
858 // do nothing, to prevent repainting
859}
860
861
862void TEWidget::focusOutEvent( QFocusEvent * )
863{
864 // do nothing, to prevent repainting
865}
866
867bool TEWidget::focusNextPrevChild( bool next )
868{
869 if (next)
870 return false; // This disables changing the active part in konqueror
871 // when pressing Tab
872 return QFrame::focusNextPrevChild( next );
873}
874
875
876int TEWidget::charClass(char ch) const
877{
878 // This might seem like overkill, but imagine if ch was a Unicode
879 // character (Qt 2.0 QChar) - it might then be sensible to separate
880 // the different language ranges, etc.
881
882 if ( isspace(ch) ) return ' ';
883
884 static const char *word_characters = ":@-./_~";
885 if ( isalnum(ch) || strchr(word_characters, ch) )
886 return 'a';
887
888 // Everything else is weird
889 return 1;
890}
891
892void TEWidget::setMouseMarks(bool on)
893{
894 mouse_marks = on;
895 setCursor( mouse_marks ? ibeamCursor : arrowCursor );
896}
897
898/* ------------------------------------------------------------------------- */
899/* */
900/* Clipboard */
901/* */
902/* ------------------------------------------------------------------------- */
903
904#undef KeyPress
905
906void TEWidget::emitSelection()
907// Paste Clipboard by simulating keypress events
908{
909#ifndef QT_NO_CLIPBOARD
910 QString text = QApplication::clipboard()->text();
911 if ( ! text.isNull() )
912 {
913 text.replace(QRegExp("\n"), "\r");
914 QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text);
915 emit keyPressedSignal(&e); // expose as a big fat keypress event
916 emit clearSelectionSignal();
917 }
918#endif
919}
920
921void TEWidget::emitText(QString text)
922{
923 QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text);
924 emit keyPressedSignal(&e); // expose as a big fat keypress event
925}
926
927void TEWidget::pasteClipboard( )
928{
929 emitSelection();
930}
931
932void TEWidget::setSelection(const QString& t)
933{
934#ifndef QT_NO_CLIPBOARD
935 // Disconnect signal while WE set the clipboard
936 QObject *cb = QApplication::clipboard();
937 QObject::disconnect( cb, SIGNAL(dataChanged()),
938 this, SLOT(onClearSelection()) );
939
940 QApplication::clipboard()->setText(t);
941
942 QObject::connect( cb, SIGNAL(dataChanged()),
943 this, SLOT(onClearSelection()) );
944#endif
945}
946
947void TEWidget::onClearSelection()
948{
949 emit clearSelectionSignal();
950}
951
952/* ------------------------------------------------------------------------- */
953/* */
954/* Keyboard */
955/* */
956/* ------------------------------------------------------------------------- */
957
958//FIXME: an `eventFilter' has been installed instead of a `keyPressEvent'
959// due to a bug in `QT' or the ignorance of the author to prevent
960// repaint events being emitted to the screen whenever one leaves
961// or reenters the screen to/from another application.
962//
963// Troll says one needs to change focusInEvent() and focusOutEvent(),
964// which would also let you have an in-focus cursor and an out-focus
965// cursor like xterm does.
966
967// for the auto-hide cursor feature, I added empty focusInEvent() and
968// focusOutEvent() so that update() isn't called.
969// For auto-hide, we need to get keypress-events, but we only get them when
970// we have focus.
971
972void TEWidget::doScroll(int lines)
973{
974 scrollbar->setValue(scrollbar->value()+lines);
975}
976
977bool TEWidget::eventFilter( QObject *obj, QEvent *e )
978{
979 if ( (e->type() == QEvent::Accel ||
980 e->type() == QEvent::AccelAvailable ) && qApp->focusWidget() == this ) {
981 static_cast<QKeyEvent *>( e )->ignore();
982 return true;
983 }
984 if ( obj != this /* when embedded */ && obj != parent() /* when standalone */ )
985 return FALSE; // not us
986 if ( e->type() == QEvent::Wheel) {
987 QApplication::sendEvent(scrollbar, e);
988 }
989
990#ifdef FAKE_CTRL_AND_ALT
991 static bool control = FALSE;
992 static bool alt = FALSE;
993// qDebug(" Has a keyboard with no CTRL and ALT keys, but we fake it:");
994 bool dele=FALSE;
995 if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease ) {
996 QKeyEvent* ke = (QKeyEvent*)e;
997 bool keydown = e->type() == QEvent::KeyPress || ke->isAutoRepeat();
998 switch (ke->key()) {
999 case Key_F9: // let this be "Control"
1000 control = keydown;
1001 e = new QKeyEvent(QEvent::KeyPress, Key_Control, 0, ke->state());
1002 dele=TRUE;
1003 break;
1004 case Key_F13: // let this be "Alt"
1005 alt = keydown;
1006 e = new QKeyEvent(QEvent::KeyPress, Key_Alt, 0, ke->state());
1007 dele=TRUE;
1008 break;
1009 default:
1010 if ( control ) {
1011 int a = toupper(ke->ascii())-64;
1012 if ( a >= 0 && a < ' ' ) {
1013 e = new QKeyEvent(e->type(), ke->key(),
1014 a, ke->state()|ControlButton, QChar(a,0));
1015 dele=TRUE;
1016 }
1017 }
1018 if ( alt ) {
1019 e = new QKeyEvent(e->type(), ke->key(),
1020 ke->ascii(), ke->state()|AltButton, ke->text());
1021 dele=TRUE;
1022 }
1023 }
1024 }
1025#endif
1026
1027 if ( e->type() == QEvent::KeyPress ) {
1028 QKeyEvent* ke = (QKeyEvent*)e;
1029 actSel=0; // Key stroke implies a screen update, so TEWidget won't
1030 // know where the current selection is.
1031
1032// qDebug("key pressed is 0x%x",ke->key());
1033
1034 if( ke->state() == ShiftButton && ke->key() == Key_Tab) { //lets hardcode this sucker
1035
1036// qDebug("key pressed 2 is 0x%x",ke->key());
1037 emitText("\\"); // expose
1038 } else
1039 emit keyPressedSignal(ke); // expose
1040 ke->accept();
1041#ifdef FAKE_CTRL_AND_ALT
1042 if ( dele ) delete e;
1043#endif
1044 return true; // stop the event
1045 }
1046 if ( e->type() == QEvent::Enter ) {
1047 QObject::disconnect( (QObject*)cb, SIGNAL(dataChanged()),
1048 this, SLOT(onClearSelection()) );
1049 }
1050 if ( e->type() == QEvent::Leave ) {
1051 QObject::connect( (QObject*)cb, SIGNAL(dataChanged()),
1052 this, SLOT(onClearSelection()) );
1053 }
1054 return QFrame::eventFilter( obj, e );
1055}
1056
1057/* ------------------------------------------------------------------------- */
1058/* */
1059/* Frame */
1060/* */
1061/* ------------------------------------------------------------------------- */
1062
1063void TEWidget::frameChanged()
1064{
1065 propagateSize();
1066 update();
1067}
1068
1069/* ------------------------------------------------------------------------- */
1070/* */
1071/* Sound */
1072/* */
1073/* ------------------------------------------------------------------------- */
1074
1075void TEWidget::Bell()
1076{
1077 QApplication::beep();
1078}
1079
1080/* ------------------------------------------------------------------------- */
1081/* */
1082/* Auxiluary */
1083/* */
1084/* ------------------------------------------------------------------------- */
1085
1086void TEWidget::clearImage()
1087// initialize the image
1088// for internal use only
1089{
1090 for (int y = 0; y < lines; y++)
1091 for (int x = 0; x < columns; x++)
1092 {
1093 image[loc(x,y)].c = 0xff; //' ';
1094 image[loc(x,y)].f = 0xff; //DEFAULT_FORE_COLOR;
1095 image[loc(x,y)].b = 0xff; //DEFAULT_BACK_COLOR;
1096 image[loc(x,y)].r = 0xff; //DEFAULT_RENDITION;
1097 }
1098}
1099
1100// Create Image ///////////////////////////////////////////////////////
1101
1102void TEWidget::calcGeometry()
1103{
1104 //FIXME: set rimX == rimY == 0 when running in full screen mode.
1105
1106 scrollbar->resize(QApplication::style().scrollBarExtent().width(),
1107 contentsRect().height());
1108 switch(scrollLoc)
1109 {
1110 case SCRNONE :
1111 columns = ( contentsRect().width() - 2 * rimX ) / font_w;
1112 blX = (contentsRect().width() - (columns*font_w) ) / 2;
1113 brX = blX;
1114 scrollbar->hide();
1115 break;
1116 case SCRLEFT :
1117 columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w;
1118 brX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2;
1119 blX = brX + scrollbar->width();
1120 scrollbar->move(contentsRect().topLeft());
1121 scrollbar->show();
1122 break;
1123 case SCRRIGHT:
1124 columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w;
1125 blX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2;
1126 brX = blX;
1127 scrollbar->move(contentsRect().topRight() - QPoint(scrollbar->width()-1,0));
1128 scrollbar->show();
1129 break;
1130 }
1131 //FIXME: support 'rounding' styles
1132 lines = ( contentsRect().height() - 2 * rimY ) / font_h;
1133 bY = (contentsRect().height() - (lines *font_h)) / 2;
1134}
1135
1136void TEWidget::makeImage()
1137//FIXME: rename 'calcGeometry?
1138{
1139 calcGeometry();
1140 image = (ca*) malloc(lines*columns*sizeof(ca));
1141 clearImage();
1142}
1143
1144// calculate the needed size
1145QSize TEWidget::calcSize(int cols, int lins) const
1146{
1147 int frw = width() - contentsRect().width();
1148 int frh = height() - contentsRect().height();
1149 int scw = (scrollLoc==SCRNONE?0:scrollbar->width());
1150 return QSize( font_w*cols + 2*rimX + frw + scw, font_h*lins + 2*rimY + frh );
1151}
1152
1153QSize TEWidget::sizeHint() const
1154{
1155 return size();
1156}
1157
1158void TEWidget::styleChange(QStyle &)
1159{
1160 propagateSize();
1161}
1162
1163#ifndef QT_NO_DRAGANDDROP
1164
1165/* --------------------------------------------------------------------- */
1166/* */
1167/* Drag & Drop */
1168/* */
1169/* --------------------------------------------------------------------- */
1170
1171
1172void TEWidget::dragEnterEvent(QDragEnterEvent* e)
1173{
1174 e->accept(QTextDrag::canDecode(e) ||
1175 QUriDrag::canDecode(e));
1176}
1177
1178void TEWidget::dropEvent(QDropEvent* event)
1179{
1180 // The current behaviour when url(s) are dropped is
1181 // * if there is only ONE url and if it's a LOCAL one, ask for paste or cd
1182 // * in all other cases, just paste
1183 // (for non-local ones, or for a list of URLs, 'cd' is nonsense)
1184 QStrList strlist;
1185 int file_count = 0;
1186 dropText = "";
1187 bool bPopup = true;
1188
1189 if(QUriDrag::decode(event, strlist)) {
1190 if (strlist.count()) {
1191 for(const char* p = strlist.first(); p; p = strlist.next()) {
1192 if(file_count++ > 0) {
1193 dropText += " ";
1194 bPopup = false; // more than one file, don't popup
1195 }
1196
1197/*
1198 KURL url(p);
1199 if (url.isLocalFile()) {
1200 dropText += url.path(); // local URL : remove protocol
1201 }
1202 else {
1203 dropText += url.prettyURL();
1204 bPopup = false; // a non-local file, don't popup
1205 }
1206*/
1207
1208 }
1209
1210 if (bPopup)
1211 // m_drop->popup(pos() + event->pos());
1212 m_drop->popup(mapToGlobal(event->pos()));
1213 else
1214 {
1215 if (currentSession) {
1216 currentSession->getEmulation()->sendString(dropText.local8Bit());
1217 }
1218// kdDebug() << "Drop:" << dropText.local8Bit() << "\n";
1219 }
1220 }
1221 }
1222 else if(QTextDrag::decode(event, dropText)) {
1223// kdDebug() << "Drop:" << dropText.local8Bit() << "\n";
1224 if (currentSession) {
1225 currentSession->getEmulation()->sendString(dropText.local8Bit());
1226 }
1227 // Paste it
1228 }
1229}
1230#endif
1231
1232
1233void TEWidget::drop_menu_activated(int item)
1234{
1235#ifndef QT_NO_DRAGANDDROP
1236 switch (item)
1237 {
1238 case 0: // paste
1239 currentSession->getEmulation()->sendString(dropText.local8Bit());
1240// KWM::activate((Window)this->winId());
1241 break;
1242 case 1: // cd ...
1243 currentSession->getEmulation()->sendString("cd ");
1244 struct stat statbuf;
1245 if ( ::stat( QFile::encodeName( dropText ), &statbuf ) == 0 )
1246 {
1247 if ( !S_ISDIR(statbuf.st_mode) )
1248 {
1249/*
1250 KURL url;
1251 url.setPath( dropText );
1252 dropText = url.directory( true, false ); // remove filename
1253*/
1254 }
1255 }
1256 dropText.replace(QRegExp(" "), "\\ "); // escape spaces
1257 currentSession->getEmulation()->sendString(dropText.local8Bit());
1258 currentSession->getEmulation()->sendString("\n");
1259// KWM::activate((Window)this->winId());
1260 break;
1261 }
1262#endif
1263}
1264
diff --git a/noncore/apps/opie-console/TEWidget.h b/noncore/apps/opie-console/TEWidget.h
new file mode 100644
index 0000000..40e1aea
--- a/dev/null
+++ b/noncore/apps/opie-console/TEWidget.h
@@ -0,0 +1,202 @@
1/* ----------------------------------------------------------------------- */
2/* */
3/* [te_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 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#ifndef TE_WIDGET_H
19#define TE_WIDGET_H
20
21#include <qwidget.h>
22#include <qlabel.h>
23#include <qtimer.h>
24#include <qcolor.h>
25#include <qkeycode.h>
26#include <qscrollbar.h>
27
28#include <qpopupmenu.h>
29
30#include "TECommon.h"
31
32extern unsigned short vt100_graphics[32];
33
34class TESession;
35
36// class Konsole;
37
38class TEWidget : public QFrame
39// a widget representing attributed text
40{ Q_OBJECT
41
42// friend class Konsole;
43
44public:
45
46 TEWidget(QWidget *parent=0, const char *name=0);
47 virtual ~TEWidget();
48
49public:
50
51 QColor getDefaultBackColor();
52
53 const ColorEntry* getColorTable() const;
54 const ColorEntry* getdefaultColorTable() const;
55 void setColorTable(const ColorEntry table[]);
56
57 void setScrollbarLocation(int loc);
58 enum { SCRNONE=0, SCRLEFT=1, SCRRIGHT=2 };
59
60 void setScroll(int cursor, int lines);
61 void doScroll(int lines);
62
63 void emitSelection();
64
65public:
66
67 void setImage(const ca* const newimg, int lines, int columns);
68
69 int Lines() { return lines; }
70 int Columns() { return columns; }
71
72 void calcGeometry();
73 void propagateSize();
74 QSize calcSize(int cols, int lins) const;
75
76 QSize sizeHint() const;
77
78public:
79
80 void Bell();
81 void emitText(QString text);
82 void pasteClipboard();
83
84signals:
85
86 void keyPressedSignal(QKeyEvent *e);
87 void mouseSignal(int cb, int cx, int cy);
88 void changedImageSizeSignal(int lines, int columns);
89 void changedHistoryCursor(int value);
90 void configureRequest( TEWidget*, int state, int x, int y );
91
92 void clearSelectionSignal();
93 void beginSelectionSignal( const int x, const int y );
94 void extendSelectionSignal( const int x, const int y );
95 void endSelectionSignal(const BOOL preserve_line_breaks);
96
97
98protected:
99
100 virtual void styleChange( QStyle& );
101
102 bool eventFilter( QObject *, QEvent * );
103
104 void drawAttrStr(QPainter &paint, QRect rect,
105 QString& str, ca attr, BOOL pm, BOOL clear);
106 void paintEvent( QPaintEvent * );
107
108 void resizeEvent(QResizeEvent*);
109
110 void fontChange(const QFont &font);
111 void frameChanged();
112
113 void mouseDoubleClickEvent(QMouseEvent* ev);
114 void mousePressEvent( QMouseEvent* );
115 void mouseReleaseEvent( QMouseEvent* );
116 void mouseMoveEvent( QMouseEvent* );
117
118 void focusInEvent( QFocusEvent * );
119 void focusOutEvent( QFocusEvent * );
120 bool focusNextPrevChild( bool next );
121
122#ifndef QT_NO_DRAGANDDROP
123 // Dnd
124 void dragEnterEvent(QDragEnterEvent* event);
125 void dropEvent(QDropEvent* event);
126#endif
127
128 virtual int charClass(char) const;
129
130 void clearImage();
131
132public:
133 const QPixmap *backgroundPixmap();
134
135 void setSelection(const QString &t);
136
137 virtual void setFont(const QFont &);
138 void setVTFont(const QFont &);
139 QFont getVTFont();
140
141 void setMouseMarks(bool on);
142
143public slots:
144
145 void onClearSelection();
146
147protected slots:
148
149 void scrollChanged(int value);
150 void blinkEvent();
151
152private:
153
154 QChar (*fontMap)(QChar); // possible vt100 font extention
155
156 bool fixed_font; // has fixed pitch
157 int font_h; // height
158 int font_w; // width
159 int font_a; // ascend
160
161 int blX; // actual offset (left)
162 int brX; // actual offset (right)
163 int bY; // actual offset
164
165 int lines;
166 int columns;
167 ca *image; // [lines][columns]
168
169 ColorEntry color_table[TABLE_COLORS];
170
171 BOOL resizing;
172 bool mouse_marks;
173
174 void makeImage();
175
176 QPoint iPntSel; // initial selection point
177 QPoint pntSel; // current selection point
178 int actSel; // selection state
179 BOOL word_selection_mode;
180 BOOL preserve_line_breaks;
181
182 QClipboard* cb;
183 QScrollBar* scrollbar;
184 int scrollLoc;
185
186//#define SCRNONE 0
187//#define SCRLEFT 1
188//#define SCRRIGHT 2
189
190 BOOL blinking; // hide text in paintEvent
191 BOOL hasBlinker; // has characters to blink
192 QTimer* blinkT; // active when hasBlinker
193 QPopupMenu* m_drop;
194 QString dropText;
195 public:
196 // current session in this widget
197 TESession *currentSession;
198private slots:
199 void drop_menu_activated(int item);
200};
201
202#endif // TE_WIDGET_H
diff --git a/noncore/apps/opie-console/TEmuVt102.cpp b/noncore/apps/opie-console/TEmuVt102.cpp
new file mode 100644
index 0000000..275c18d
--- a/dev/null
+++ b/noncore/apps/opie-console/TEmuVt102.cpp
@@ -0,0 +1,1020 @@
1/* ------------------------------------------------------------------------- */
2/* */
3/* [TEmuVt102.C] VT102 Terminal Emulation */
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/*! \class TEmuVt102
20
21 \brief Actual Emulation for Konsole
22
23 \sa TEWidget \sa TEScreen
24*/
25
26#include "TEmuVt102.h"
27#include "TEWidget.h"
28#include "TEScreen.h"
29#include "keytrans.h"
30
31#include <stdio.h>
32#include <unistd.h>
33#include <qkeycode.h>
34#include <qtextcodec.h>
35
36
37/* VT102 Terminal Emulation
38
39 This class puts together the screens, the pty and the widget to a
40 complete terminal emulation. Beside combining it's componentes, it
41 handles the emulations's protocol.
42
43 This module consists of the following sections:
44
45 - Constructor/Destructor
46 - Incoming Bytes Event pipeline
47 - Outgoing Bytes
48 - Mouse Events
49 - Keyboard Events
50 - Modes and Charset State
51 - Diagnostics
52*/
53
54
55/* ------------------------------------------------------------------------- */
56/* */
57/* Constructor / Destructor */
58/* */
59/* ------------------------------------------------------------------------- */
60
61/*
62 Nothing really intesting happens here.
63*/
64
65/*!
66*/
67
68TEmuVt102::TEmuVt102(TEWidget* gui) : TEmulation(gui)
69{
70 QObject::connect(gui,SIGNAL(mouseSignal(int,int,int)),
71 this,SLOT(onMouse(int,int,int)));
72 initTokenizer();
73 reset();
74}
75
76/*!
77*/
78
79TEmuVt102::~TEmuVt102()
80{
81}
82
83/*!
84*/
85
86void TEmuVt102::reset()
87{
88 resetToken();
89 resetModes();
90 resetCharset(0); screen[0]->reset();
91 resetCharset(1); screen[0]->reset();
92 setCodec(0);
93 setKeytrans("linux.keytab");
94}
95
96/* ------------------------------------------------------------------------- */
97/* */
98/* Processing the incoming byte stream */
99/* */
100/* ------------------------------------------------------------------------- */
101
102/* Incoming Bytes Event pipeline
103
104 This section deals with decoding the incoming character stream.
105 Decoding means here, that the stream is first seperated into `tokens'
106 which are then mapped to a `meaning' provided as operations by the
107 `TEScreen' class or by the emulation class itself.
108
109 The pipeline proceeds as follows:
110
111 - Tokenizing the ESC codes (onRcvChar)
112 - VT100 code page translation of plain characters (applyCharset)
113 - Interpretation of ESC codes (tau)
114
115 The escape codes and their meaning are described in the
116 technical reference of this program.
117*/
118
119// Tokens ------------------------------------------------------------------ --
120
121/*
122 Since the tokens are the central notion if this section, we've put them
123 in front. They provide the syntactical elements used to represent the
124 terminals operations as byte sequences.
125
126 They are encodes here into a single machine word, so that we can later
127 switch over them easily. Depending on the token itself, additional
128 argument variables are filled with parameter values.
129
130 The tokens are defined below:
131
132 - CHR - Printable characters (32..255 but DEL (=127))
133 - CTL - Control characters (0..31 but ESC (= 27), DEL)
134 - ESC - Escape codes of the form <ESC><CHR but `[]()+*#'>
135 - ESC_DE - Escape codes of the form <ESC><any of `()+*#%'> C
136 - CSI_PN - Escape codes of the form <ESC>'[' {Pn} ';' {Pn} C
137 - CSI_PS - Escape codes of the form <ESC>'[' {Pn} ';' ... C
138 - CSI_PR - Escape codes of the form <ESC>'[' '?' {Pn} ';' ... C
139 - VT52 - VT52 escape codes
140 - <ESC><Chr>
141 - <ESC>'Y'{Pc}{Pc}
142 - XTE_HA - Xterm hacks <ESC>`]' {Pn} `;' {Text} <BEL>
143 note that this is handled differently
144
145 The last two forms allow list of arguments. Since the elements of
146 the lists are treated individually the same way, they are passed
147 as individual tokens to the interpretation. Further, because the
148 meaning of the parameters are names (althought represented as numbers),
149 they are includes within the token ('N').
150
151*/
152
153#define TY_CONSTR(T,A,N) ( ((((int)N) & 0xffff) << 16) | ((((int)A) & 0xff) << 8) | (((int)T) & 0xff) )
154
155#define TY_CHR___( ) TY_CONSTR(0,0,0)
156#define TY_CTL___(A ) TY_CONSTR(1,A,0)
157#define TY_ESC___(A ) TY_CONSTR(2,A,0)
158#define TY_ESC_CS(A,B) TY_CONSTR(3,A,B)
159#define TY_ESC_DE(A ) TY_CONSTR(4,A,0)
160#define TY_CSI_PS(A,N) TY_CONSTR(5,A,N)
161#define TY_CSI_PN(A ) TY_CONSTR(6,A,0)
162#define TY_CSI_PR(A,N) TY_CONSTR(7,A,N)
163
164#define TY_VT52__(A ) TY_CONSTR(8,A,0)
165
166// Tokenizer --------------------------------------------------------------- --
167
168/* The tokenizers state
169
170 The state is represented by the buffer (pbuf, ppos),
171 and accompanied by decoded arguments kept in (argv,argc).
172 Note that they are kept internal in the tokenizer.
173*/
174
175void TEmuVt102::resetToken()
176{
177 ppos = 0; argc = 0; argv[0] = 0; argv[1] = 0;
178}
179
180void TEmuVt102::addDigit(int dig)
181{
182 argv[argc] = 10*argv[argc] + dig;
183}
184
185void TEmuVt102::addArgument()
186{
187 argc = QMIN(argc+1,MAXARGS-1);
188 argv[argc] = 0;
189}
190
191void TEmuVt102::pushToToken(int cc)
192{
193 pbuf[ppos] = cc;
194 ppos = QMIN(ppos+1,MAXPBUF-1);
195}
196
197// Character Classes used while decoding
198
199#define CTL 1
200#define CHR 2
201#define CPN 4
202#define DIG 8
203#define SCS 16
204#define GRP 32
205
206void TEmuVt102::initTokenizer()
207{ int i; UINT8* s;
208 for(i = 0; i < 256; i++) tbl[ i] = 0;
209 for(i = 0; i < 32; i++) tbl[ i] |= CTL;
210 for(i = 32; i < 256; i++) tbl[ i] |= CHR;
211 for(s = (UINT8*)"@ABCDGHLMPXcdfry"; *s; s++) tbl[*s] |= CPN;
212 for(s = (UINT8*)"0123456789" ; *s; s++) tbl[*s] |= DIG;
213 for(s = (UINT8*)"()+*%" ; *s; s++) tbl[*s] |= SCS;
214 for(s = (UINT8*)"()+*#[]%" ; *s; s++) tbl[*s] |= GRP;
215 resetToken();
216}
217
218/* Ok, here comes the nasty part of the decoder.
219
220 Instead of keeping an explicit state, we deduce it from the
221 token scanned so far. It is then immediately combined with
222 the current character to form a scanning decision.
223
224 This is done by the following defines.
225
226 - P is the length of the token scanned so far.
227 - L (often P-1) is the position on which contents we base a decision.
228 - C is a character or a group of characters (taken from 'tbl').
229
230 Note that they need to applied in proper order.
231*/
232
233#define lec(P,L,C) (p == (P) && s[(L)] == (C))
234#define lun( ) (p == 1 && cc >= 32 )
235#define les(P,L,C) (p == (P) && s[L] < 256 && (tbl[s[(L)]] & (C)) == (C))
236#define eec(C) (p >= 3 && cc == (C))
237#define ees(C) (p >= 3 && cc < 256 && (tbl[ cc ] & (C)) == (C))
238#define eps(C) (p >= 3 && s[2] != '?' && cc < 256 && (tbl[ cc ] & (C)) == (C))
239#define epp( ) (p >= 3 && s[2] == '?' )
240#define egt( ) (p == 3 && s[2] == '>' )
241#define Xpe (ppos>=2 && pbuf[1] == ']' )
242#define Xte (Xpe && cc == 7 )
243#define ces(C) ( cc < 256 && (tbl[ cc ] & (C)) == (C) && !Xte)
244
245#define ESC 27
246#define CNTL(c) ((c)-'@')
247
248// process an incoming unicode character
249
250void TEmuVt102::onRcvChar(int cc)
251{ int i;
252
253 if (cc == 127) return; //VT100: ignore.
254
255 if (ces( CTL))
256 { // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100
257 // This means, they do neither a resetToken nor a pushToToken. Some of them, do
258 // of course. Guess this originates from a weakly layered handling of the X-on
259 // X-off protocol, which comes really below this level.
260 if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC) resetToken(); //VT100: CAN or SUB
261 if (cc != ESC) { tau( TY_CTL___(cc+'@' ), 0, 0); return; }
262 }
263
264 pushToToken(cc); // advance the state
265
266 int* s = pbuf;
267 int p = ppos;
268
269 if (getMode(MODE_Ansi)) // decide on proper action
270 {
271 if (lec(1,0,ESC)) { return; }
272 if (les(2,1,GRP)) { return; }
273 if (Xte ) { XtermHack(); resetToken(); return; }
274 if (Xpe ) { return; }
275 if (lec(3,2,'?')) { return; }
276 if (lec(3,2,'>')) { return; }
277 if (lun( )) { tau( TY_CHR___(), applyCharset(cc), 0); resetToken(); return; }
278 if (lec(2,0,ESC)) { tau( TY_ESC___(s[1]), 0, 0); resetToken(); return; }
279 if (les(3,1,SCS)) { tau( TY_ESC_CS(s[1],s[2]), 0, 0); resetToken(); return; }
280 if (lec(3,1,'#')) { tau( TY_ESC_DE(s[2]), 0, 0); resetToken(); return; }
281// if (egt( )) { tau( TY_CSI_PG(cc ), '>', 0); resetToken(); return; }
282 if (eps( CPN)) { tau( TY_CSI_PN(cc), argv[0],argv[1]); resetToken(); return; }
283 if (ees( DIG)) { addDigit(cc-'0'); return; }
284 if (eec( ';')) { addArgument(); return; }
285 for (i=0;i<=argc;i++)
286 if (epp( )) tau( TY_CSI_PR(cc,argv[i]), 0, 0); else
287 tau( TY_CSI_PS(cc,argv[i]), 0, 0);
288 resetToken();
289 }
290 else // mode VT52
291 {
292 if (lec(1,0,ESC)) return;
293 if (les(1,0,CHR)) { tau( TY_CHR___( ), s[0], 0); resetToken(); return; }
294 if (lec(2,1,'Y')) return;
295 if (lec(3,1,'Y')) return;
296 if (p < 4) { tau( TY_VT52__(s[1] ), 0, 0); resetToken(); return; }
297 tau( TY_VT52__(s[1] ), s[2],s[3]); resetToken(); return;
298 }
299}
300
301void TEmuVt102::XtermHack()
302{ int i,arg = 0;
303 for (i = 2; i < ppos && '0'<=pbuf[i] && pbuf[i]<'9' ; i++)
304 arg = 10*arg + (pbuf[i]-'0');
305 if (pbuf[i] != ';') { ReportErrorToken(); return; }
306 QChar *str = new QChar[ppos-i-2];
307 for (int j = 0; j < ppos-i-2; j++) str[j] = pbuf[i+1+j];
308 QString unistr(str,ppos-i-2);
309 // arg == 1 doesn't change the title. In XTerm it only changes the icon name
310 // (btw: arg=0 changes title and icon, arg=1 only icon, arg=2 only title
311 if (arg == 0 || arg == 2) emit changeTitle(arg,unistr);
312 delete [] str;
313}
314
315// Interpreting Codes ---------------------------------------------------------
316
317/*
318 Now that the incoming character stream is properly tokenized,
319 meaning is assigned to them. These are either operations of
320 the current screen, or of the emulation class itself.
321
322 The token to be interpreteted comes in as a machine word
323 possibly accompanied by two parameters.
324
325 Likewise, the operations assigned to, come with up to two
326 arguments. One could consider to make up a proper table
327 from the function below.
328
329 The technical reference manual provides more informations
330 about this mapping.
331*/
332
333void TEmuVt102::tau( int token, int p, int q )
334{
335//scan_buffer_report();
336//if (token == TY_CHR___()) printf("%c",p); else
337//printf("tau(%d,%d,%d, %d,%d)\n",(token>>0)&0xff,(token>>8)&0xff,(token>>16)&0xffff,p,q);
338 switch (token)
339 {
340
341 case TY_CHR___( ) : scr->ShowCharacter (p ); break; //UTF16
342
343 // 127 DEL : ignored on input
344
345 case TY_CTL___('@' ) : /* NUL: ignored */ break;
346 case TY_CTL___('A' ) : /* SOH: ignored */ break;
347 case TY_CTL___('B' ) : /* STX: ignored */ break;
348 case TY_CTL___('C' ) : /* ETX: ignored */ break;
349 case TY_CTL___('D' ) : /* EOT: ignored */ break;
350 case TY_CTL___('E' ) : reportAnswerBack ( ); break; //VT100
351 case TY_CTL___('F' ) : /* ACK: ignored */ break;
352 case TY_CTL___('G' ) : gui->Bell ( ); break; //VT100
353 case TY_CTL___('H' ) : scr->BackSpace ( ); break; //VT100
354 case TY_CTL___('I' ) : scr->Tabulate ( ); break; //VT100
355 case TY_CTL___('J' ) : scr->NewLine ( ); break; //VT100
356 case TY_CTL___('K' ) : scr->NewLine ( ); break; //VT100
357 case TY_CTL___('L' ) : scr->NewLine ( ); break; //VT100
358 case TY_CTL___('M' ) : scr->Return ( ); break; //VT100
359
360 case TY_CTL___('N' ) : useCharset ( 1); break; //VT100
361 case TY_CTL___('O' ) : useCharset ( 0); break; //VT100
362
363 case TY_CTL___('P' ) : /* DLE: ignored */ break;
364 case TY_CTL___('Q' ) : /* DC1: XON continue */ break; //VT100
365 case TY_CTL___('R' ) : /* DC2: ignored */ break;
366 case TY_CTL___('S' ) : /* DC3: XOFF halt */ break; //VT100
367 case TY_CTL___('T' ) : /* DC4: ignored */ break;
368 case TY_CTL___('U' ) : /* NAK: ignored */ break;
369 case TY_CTL___('V' ) : /* SYN: ignored */ break;
370 case TY_CTL___('W' ) : /* ETB: ignored */ break;
371 case TY_CTL___('X' ) : scr->ShowCharacter ( 0x2592); break; //VT100
372 case TY_CTL___('Y' ) : /* EM : ignored */ break;
373 case TY_CTL___('Z' ) : scr->ShowCharacter ( 0x2592); break; //VT100
374 case TY_CTL___('[' ) : /* ESC: cannot be seen here. */ break;
375 case TY_CTL___('\\' ) : /* FS : ignored */ break;
376 case TY_CTL___(']' ) : /* GS : ignored */ break;
377 case TY_CTL___('^' ) : /* RS : ignored */ break;
378 case TY_CTL___('_' ) : /* US : ignored */ break;
379
380 case TY_ESC___('D' ) : scr->index ( ); break; //VT100
381 case TY_ESC___('E' ) : scr->NextLine ( ); break; //VT100
382 case TY_ESC___('H' ) : scr->changeTabStop (TRUE ); break; //VT100
383 case TY_ESC___('M' ) : scr->reverseIndex ( ); break; //VT100
384 case TY_ESC___('Z' ) : reportTerminalType ( ); break;
385 case TY_ESC___('c' ) : reset ( ); break;
386
387 case TY_ESC___('n' ) : useCharset ( 2); break;
388 case TY_ESC___('o' ) : useCharset ( 3); break;
389 case TY_ESC___('7' ) : saveCursor ( ); break;
390 case TY_ESC___('8' ) : restoreCursor ( ); break;
391
392 case TY_ESC___('=' ) : setMode (MODE_AppKeyPad); break;
393 case TY_ESC___('>' ) : resetMode (MODE_AppKeyPad); break;
394 case TY_ESC___('<' ) : setMode (MODE_Ansi ); break; //VT100
395
396 case TY_ESC_CS('(', '0') : setCharset (0, '0'); break; //VT100
397 case TY_ESC_CS('(', 'A') : setCharset (0, 'A'); break; //VT100
398 case TY_ESC_CS('(', 'B') : setCharset (0, 'B'); break; //VT100
399
400 case TY_ESC_CS(')', '0') : setCharset (1, '0'); break; //VT100
401 case TY_ESC_CS(')', 'A') : setCharset (1, 'A'); break; //VT100
402 case TY_ESC_CS(')', 'B') : setCharset (1, 'B'); break; //VT100
403
404 case TY_ESC_CS('*', '0') : setCharset (2, '0'); break; //VT100
405 case TY_ESC_CS('*', 'A') : setCharset (2, 'A'); break; //VT100
406 case TY_ESC_CS('*', 'B') : setCharset (2, 'B'); break; //VT100
407
408 case TY_ESC_CS('+', '0') : setCharset (3, '0'); break; //VT100
409 case TY_ESC_CS('+', 'A') : setCharset (3, 'A'); break; //VT100
410 case TY_ESC_CS('+', 'B') : setCharset (3, 'B'); break; //VT100
411
412 case TY_ESC_CS('%', 'G') : setCodec (1 ); break; //LINUX
413 case TY_ESC_CS('%', '@') : setCodec (0 ); break; //LINUX
414
415 case TY_ESC_DE('3' ) : /* IGNORED: double high, top half */ break;
416 case TY_ESC_DE('4' ) : /* IGNORED: double high, bottom half */ break;
417 case TY_ESC_DE('5' ) : /* IGNORED: single width, single high*/ break;
418 case TY_ESC_DE('6' ) : /* IGNORED: double width, single high*/ break;
419 case TY_ESC_DE('8' ) : scr->helpAlign ( ); break;
420
421 case TY_CSI_PS('K', 0) : scr->clearToEndOfLine ( ); break;
422 case TY_CSI_PS('K', 1) : scr->clearToBeginOfLine ( ); break;
423 case TY_CSI_PS('K', 2) : scr->clearEntireLine ( ); break;
424 case TY_CSI_PS('J', 0) : scr->clearToEndOfScreen ( ); break;
425 case TY_CSI_PS('J', 1) : scr->clearToBeginOfScreen ( ); break;
426 case TY_CSI_PS('J', 2) : scr->clearEntireScreen ( ); break;
427 case TY_CSI_PS('g', 0) : scr->changeTabStop (FALSE ); break; //VT100
428 case TY_CSI_PS('g', 3) : scr->clearTabStops ( ); break; //VT100
429 case TY_CSI_PS('h', 4) : scr-> setMode (MODE_Insert ); break;
430 case TY_CSI_PS('h', 20) : setMode (MODE_NewLine ); break;
431 case TY_CSI_PS('i', 0) : /* IGNORE: attached printer */ break; //VT100
432 case TY_CSI_PS('l', 4) : scr-> resetMode (MODE_Insert ); break;
433 case TY_CSI_PS('l', 20) : resetMode (MODE_NewLine ); break;
434
435 case TY_CSI_PS('m', 0) : scr->setDefaultRendition ( ); break;
436 case TY_CSI_PS('m', 1) : scr-> setRendition (RE_BOLD ); break; //VT100
437 case TY_CSI_PS('m', 4) : scr-> setRendition (RE_UNDERLINE); break; //VT100
438 case TY_CSI_PS('m', 5) : scr-> setRendition (RE_BLINK ); break; //VT100
439 case TY_CSI_PS('m', 7) : scr-> setRendition (RE_REVERSE ); break;
440 case TY_CSI_PS('m', 10) : /* IGNORED: mapping related */ break; //LINUX
441 case TY_CSI_PS('m', 11) : /* IGNORED: mapping related */ break; //LINUX
442 case TY_CSI_PS('m', 12) : /* IGNORED: mapping related */ break; //LINUX
443 case TY_CSI_PS('m', 22) : scr->resetRendition (RE_BOLD ); break;
444 case TY_CSI_PS('m', 24) : scr->resetRendition (RE_UNDERLINE); break;
445 case TY_CSI_PS('m', 25) : scr->resetRendition (RE_BLINK ); break;
446 case TY_CSI_PS('m', 27) : scr->resetRendition (RE_REVERSE ); break;
447
448 case TY_CSI_PS('m', 30) : scr->setForeColor ( 0); break;
449 case TY_CSI_PS('m', 31) : scr->setForeColor ( 1); break;
450 case TY_CSI_PS('m', 32) : scr->setForeColor ( 2); break;
451 case TY_CSI_PS('m', 33) : scr->setForeColor ( 3); break;
452 case TY_CSI_PS('m', 34) : scr->setForeColor ( 4); break;
453 case TY_CSI_PS('m', 35) : scr->setForeColor ( 5); break;
454 case TY_CSI_PS('m', 36) : scr->setForeColor ( 6); break;
455 case TY_CSI_PS('m', 37) : scr->setForeColor ( 7); break;
456 case TY_CSI_PS('m', 39) : scr->setForeColorToDefault( ); break;
457
458 case TY_CSI_PS('m', 40) : scr->setBackColor ( 0); break;
459 case TY_CSI_PS('m', 41) : scr->setBackColor ( 1); break;
460 case TY_CSI_PS('m', 42) : scr->setBackColor ( 2); break;
461 case TY_CSI_PS('m', 43) : scr->setBackColor ( 3); break;
462 case TY_CSI_PS('m', 44) : scr->setBackColor ( 4); break;
463 case TY_CSI_PS('m', 45) : scr->setBackColor ( 5); break;
464 case TY_CSI_PS('m', 46) : scr->setBackColor ( 6); break;
465 case TY_CSI_PS('m', 47) : scr->setBackColor ( 7); break;
466 case TY_CSI_PS('m', 49) : scr->setBackColorToDefault( ); break;
467
468 case TY_CSI_PS('m', 90) : scr->setForeColor ( 8); break;
469 case TY_CSI_PS('m', 91) : scr->setForeColor ( 9); break;
470 case TY_CSI_PS('m', 92) : scr->setForeColor ( 10); break;
471 case TY_CSI_PS('m', 93) : scr->setForeColor ( 11); break;
472 case TY_CSI_PS('m', 94) : scr->setForeColor ( 12); break;
473 case TY_CSI_PS('m', 95) : scr->setForeColor ( 13); break;
474 case TY_CSI_PS('m', 96) : scr->setForeColor ( 14); break;
475 case TY_CSI_PS('m', 97) : scr->setForeColor ( 15); break;
476
477 case TY_CSI_PS('m', 100) : scr->setBackColor ( 8); break;
478 case TY_CSI_PS('m', 101) : scr->setBackColor ( 9); break;
479 case TY_CSI_PS('m', 102) : scr->setBackColor ( 10); break;
480 case TY_CSI_PS('m', 103) : scr->setBackColor ( 11); break;
481 case TY_CSI_PS('m', 104) : scr->setBackColor ( 12); break;
482 case TY_CSI_PS('m', 105) : scr->setBackColor ( 13); break;
483 case TY_CSI_PS('m', 106) : scr->setBackColor ( 14); break;
484 case TY_CSI_PS('m', 107) : scr->setBackColor ( 15); break;
485
486 case TY_CSI_PS('n', 5) : reportStatus ( ); break;
487 case TY_CSI_PS('n', 6) : reportCursorPosition ( ); break;
488 case TY_CSI_PS('q', 0) : /* IGNORED: LEDs off */ break; //VT100
489 case TY_CSI_PS('q', 1) : /* IGNORED: LED1 on */ break; //VT100
490 case TY_CSI_PS('q', 2) : /* IGNORED: LED2 on */ break; //VT100
491 case TY_CSI_PS('q', 3) : /* IGNORED: LED3 on */ break; //VT100
492 case TY_CSI_PS('q', 4) : /* IGNORED: LED4 on */ break; //VT100
493 case TY_CSI_PS('x', 0) : reportTerminalParms ( 2); break; //VT100
494 case TY_CSI_PS('x', 1) : reportTerminalParms ( 3); break; //VT100
495
496 case TY_CSI_PN('@' ) : scr->insertChars (p ); break;
497 case TY_CSI_PN('A' ) : scr->cursorUp (p ); break; //VT100
498 case TY_CSI_PN('B' ) : scr->cursorDown (p ); break; //VT100
499 case TY_CSI_PN('C' ) : scr->cursorRight (p ); break; //VT100
500 case TY_CSI_PN('D' ) : scr->cursorLeft (p ); break; //VT100
501 case TY_CSI_PN('G' ) : scr->setCursorX (p ); break; //LINUX
502 case TY_CSI_PN('H' ) : scr->setCursorYX (p, q); break; //VT100
503 case TY_CSI_PN('L' ) : scr->insertLines (p ); break;
504 case TY_CSI_PN('M' ) : scr->deleteLines (p ); break;
505 case TY_CSI_PN('P' ) : scr->deleteChars (p ); break;
506 case TY_CSI_PN('X' ) : scr->eraseChars (p ); break;
507 case TY_CSI_PN('c' ) : reportTerminalType ( ); break; //VT100
508 case TY_CSI_PN('d' ) : scr->setCursorY (p ); break; //LINUX
509 case TY_CSI_PN('f' ) : scr->setCursorYX (p, q); break; //VT100
510 case TY_CSI_PN('r' ) : scr->setMargins (p, q); break; //VT100
511 case TY_CSI_PN('y' ) : /* IGNORED: Confidence test */ break; //VT100
512
513 case TY_CSI_PR('h', 1) : setMode (MODE_AppCuKeys); break; //VT100
514 case TY_CSI_PR('l', 1) : resetMode (MODE_AppCuKeys); break; //VT100
515 case TY_CSI_PR('s', 1) : saveMode (MODE_AppCuKeys); break; //FIXME
516 case TY_CSI_PR('r', 1) : restoreMode (MODE_AppCuKeys); break; //FIXME
517
518 case TY_CSI_PR('l', 2) : resetMode (MODE_Ansi ); break; //VT100
519
520 case TY_CSI_PR('h', 3) : setColumns ( 132); break; //VT100
521 case TY_CSI_PR('l', 3) : setColumns ( 80); break; //VT100
522
523 case TY_CSI_PR('h', 4) : /* IGNORED: soft scrolling */ break; //VT100
524 case TY_CSI_PR('l', 4) : /* IGNORED: soft scrolling */ break; //VT100
525
526 case TY_CSI_PR('h', 5) : scr-> setMode (MODE_Screen ); break; //VT100
527 case TY_CSI_PR('l', 5) : scr-> resetMode (MODE_Screen ); break; //VT100
528
529 case TY_CSI_PR('h', 6) : scr-> setMode (MODE_Origin ); break; //VT100
530 case TY_CSI_PR('l', 6) : scr-> resetMode (MODE_Origin ); break; //VT100
531 case TY_CSI_PR('s', 6) : scr-> saveMode (MODE_Origin ); break; //FIXME
532 case TY_CSI_PR('r', 6) : scr->restoreMode (MODE_Origin ); break; //FIXME
533
534 case TY_CSI_PR('h', 7) : scr-> setMode (MODE_Wrap ); break; //VT100
535 case TY_CSI_PR('l', 7) : scr-> resetMode (MODE_Wrap ); break; //VT100
536 case TY_CSI_PR('s', 7) : scr-> saveMode (MODE_Wrap ); break; //FIXME
537 case TY_CSI_PR('r', 7) : scr->restoreMode (MODE_Wrap ); break; //FIXME
538
539 case TY_CSI_PR('h', 8) : /* IGNORED: autorepeat on */ break; //VT100
540 case TY_CSI_PR('l', 8) : /* IGNORED: autorepeat off */ break; //VT100
541
542 case TY_CSI_PR('h', 9) : /* IGNORED: interlace */ break; //VT100
543 case TY_CSI_PR('l', 9) : /* IGNORED: interlace */ break; //VT100
544
545 case TY_CSI_PR('h', 25) : setMode (MODE_Cursor ); break; //VT100
546 case TY_CSI_PR('l', 25) : resetMode (MODE_Cursor ); break; //VT100
547
548 case TY_CSI_PR('h', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
549 case TY_CSI_PR('l', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
550 case TY_CSI_PR('s', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
551 case TY_CSI_PR('r', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
552
553 case TY_CSI_PR('h', 47) : setMode (MODE_AppScreen); break; //VT100
554 case TY_CSI_PR('l', 47) : resetMode (MODE_AppScreen); break; //VT100
555
556 case TY_CSI_PR('h', 1000) : setMode (MODE_Mouse1000); break; //XTERM
557 case TY_CSI_PR('l', 1000) : resetMode (MODE_Mouse1000); break; //XTERM
558 case TY_CSI_PR('s', 1000) : saveMode (MODE_Mouse1000); break; //XTERM
559 case TY_CSI_PR('r', 1000) : restoreMode (MODE_Mouse1000); break; //XTERM
560
561 case TY_CSI_PR('h', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
562 case TY_CSI_PR('l', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
563 case TY_CSI_PR('s', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
564 case TY_CSI_PR('r', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
565
566 case TY_CSI_PR('h', 1047) : setMode (MODE_AppScreen); break; //XTERM
567 case TY_CSI_PR('l', 1047) : resetMode (MODE_AppScreen); break; //XTERM
568
569 //FIXME: Unitoken: save translations
570 case TY_CSI_PR('h', 1048) : saveCursor ( ); break; //XTERM
571 case TY_CSI_PR('l', 1048) : restoreCursor ( ); break; //XTERM
572
573 //FIXME: every once new sequences like this pop up in xterm.
574 // Here's a guess of what they could mean.
575 case TY_CSI_PR('h', 1049) : setMode (MODE_AppScreen); break; //XTERM
576 case TY_CSI_PR('l', 1049) : resetMode (MODE_AppScreen); break; //XTERM
577
578 //FIXME: when changing between vt52 and ansi mode evtl do some resetting.
579 case TY_VT52__('A' ) : scr->cursorUp ( 1); break; //VT52
580 case TY_VT52__('B' ) : scr->cursorDown ( 1); break; //VT52
581 case TY_VT52__('C' ) : scr->cursorRight ( 1); break; //VT52
582 case TY_VT52__('D' ) : scr->cursorLeft ( 1); break; //VT52
583
584 case TY_VT52__('F' ) : setAndUseCharset (0, '0'); break; //VT52
585 case TY_VT52__('G' ) : setAndUseCharset (0, 'B'); break; //VT52
586
587 case TY_VT52__('H' ) : scr->setCursorYX (1,1 ); break; //VT52
588 case TY_VT52__('I' ) : scr->reverseIndex ( ); break; //VT52
589 case TY_VT52__('J' ) : scr->clearToEndOfScreen ( ); break; //VT52
590 case TY_VT52__('K' ) : scr->clearToEndOfLine ( ); break; //VT52
591 case TY_VT52__('Y' ) : scr->setCursorYX (p-31,q-31 ); break; //VT52
592 case TY_VT52__('Z' ) : reportTerminalType ( ); break; //VT52
593 case TY_VT52__('<' ) : setMode (MODE_Ansi ); break; //VT52
594 case TY_VT52__('=' ) : setMode (MODE_AppKeyPad); break; //VT52
595 case TY_VT52__('>' ) : resetMode (MODE_AppKeyPad); break; //VT52
596
597 default : ReportErrorToken(); break;
598 };
599}
600
601/* ------------------------------------------------------------------------- */
602/* */
603/* Terminal to Host protocol */
604/* */
605/* ------------------------------------------------------------------------- */
606
607/*
608 Outgoing bytes originate from several sources:
609
610 - Replies to Enquieries.
611 - Mouse Events
612 - Keyboard Events
613*/
614
615/*!
616*/
617
618void TEmuVt102::sendString(const char* s)
619{
620 emit sndBlock(s,strlen(s));
621}
622
623// Replies ----------------------------------------------------------------- --
624
625// This section copes with replies send as response to an enquiery control code.
626
627/*!
628*/
629
630void TEmuVt102::reportCursorPosition()
631{ char tmp[20];
632 sprintf(tmp,"\033[%d;%dR",scr->getCursorY()+1,scr->getCursorX()+1);
633 sendString(tmp);
634}
635
636/*
637 What follows here is rather obsolete and faked stuff.
638 The correspondent enquieries are neverthenless issued.
639*/
640
641/*!
642*/
643
644void TEmuVt102::reportTerminalType()
645{
646//FIXME: should change?
647 if (getMode(MODE_Ansi))
648// sendString("\033[?1;2c"); // I'm a VT100 with AP0 //FIXME: send only in response to ^[[0c
649 sendString("\033[>0;115;0c"); // I'm a VT220 //FIXME: send only in response to ^[[>c
650 else
651 sendString("\033/Z"); // I'm a VT52
652}
653
654void TEmuVt102::reportTerminalParms(int p)
655// DECREPTPARM
656{ char tmp[100];
657 sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true.
658 sendString(tmp);
659}
660
661/*!
662*/
663
664void TEmuVt102::reportStatus()
665{
666 sendString("\033[0n"); //VT100. Device status report. 0 = Ready.
667}
668
669/*!
670*/
671
672#define ANSWER_BACK "" // This is really obsolete VT100 stuff.
673
674void TEmuVt102::reportAnswerBack()
675{
676 sendString(ANSWER_BACK);
677}
678
679// Mouse Handling ---------------------------------------------------------- --
680
681/*!
682 Mouse clicks are possibly reported to the client
683 application if it has issued interest in them.
684 They are normally consumed by the widget for copy
685 and paste, but may be propagated from the widget
686 when gui->setMouseMarks is set via setMode(MODE_Mouse1000).
687
688 `x',`y' are 1-based.
689 `ev' (event) indicates the button pressed (0-2)
690 or a general mouse release (3).
691*/
692
693void TEmuVt102::onMouse( int cb, int cx, int cy )
694{ char tmp[20];
695 if (!connected) return;
696 sprintf(tmp,"\033[M%c%c%c",cb+040,cx+040,cy+040);
697 sendString(tmp);
698}
699
700// Keyboard Handling ------------------------------------------------------- --
701
702#define encodeMode(M,B) BITS(B,getMode(M))
703#define encodeStat(M,B) BITS(B,((ev->state() & (M)) == (M)))
704
705/*
706 Keyboard event handling has been simplified somewhat by pushing
707 the complications towards a configuration file [see KeyTrans class].
708*/
709
710void TEmuVt102::onKeyPress( QKeyEvent* ev )
711{
712 if (!connected) return; // someone else gets the keys
713
714//printf("State/Key: 0x%04x 0x%04x (%d,%d)\n",ev->state(),ev->key(),ev->text().length(),ev->text().length()?ev->text().ascii()[0]:0);
715
716 // revert to non-history when typing
717 if (scr->getHistCursor() != scr->getHistLines());
718 scr->setHistCursor(scr->getHistLines());
719
720 // lookup in keyboard translation table ...
721 int cmd; const char* txt; int len;
722 if (keytrans->findEntry(ev->key(), encodeMode(MODE_NewLine , BITS_NewLine ) + // OLD,
723 encodeMode(MODE_Ansi , BITS_Ansi ) + // OBSOLETE,
724 encodeMode(MODE_AppCuKeys, BITS_AppCuKeys ) + // VT100 stuff
725 encodeStat(ControlButton , BITS_Control ) +
726 encodeStat(ShiftButton , BITS_Shift ) +
727 encodeStat(AltButton , BITS_Alt ),
728 &cmd, &txt, &len ))
729//printf("cmd: %d, %s, %d\n",cmd,txt,len);
730 switch(cmd) // ... and execute if found.
731 {
732 case CMD_emitSelection : gui->emitSelection(); return;
733 case CMD_scrollPageUp : gui->doScroll(-gui->Lines()/2); return;
734 case CMD_scrollPageDown : gui->doScroll(+gui->Lines()/2); return;
735 case CMD_scrollLineUp : gui->doScroll(-1 ); return;
736 case CMD_scrollLineDown : gui->doScroll(+1 ); return;
737 case CMD_send : emit sndBlock(txt,len); return;
738 case CMD_prevSession : emit prevSession(); return;
739 case CMD_nextSession : emit nextSession(); return;
740 }
741
742 // fall back handling
743 if (!ev->text().isEmpty())
744 {
745 if (ev->state() & AltButton) sendString("\033"); // ESC, this is the ALT prefix
746 /// very hacky
747 if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='A')) sendString("\01");
748 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='B')) sendString("\02");
749 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='C')) sendString("\03");
750 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='D')) sendString("\04");
751 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='E')) sendString("\05");
752 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='F')) sendString("\06");
753 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='G')) sendString("\07");
754 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='H')) sendString("\010");
755 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='I')) sendString("\011");
756 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='J')) sendString("\012");
757 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='K')) sendString("\013");
758 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='L')) sendString("\014");
759 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='M')) sendString("\015");
760 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='N')) sendString("\016");
761 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='O')) sendString("\017");
762 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='P')) sendString("\020");
763 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='Q')) sendString("\021");
764 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='R')) sendString("\022");
765 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='S')) sendString("\023");
766 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='T')) sendString("\024");
767 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='U')) sendString("\025");
768 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='V')) sendString("\026");
769 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='W')) sendString("\027");
770 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='X')) sendString("\030");
771 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='Y')) sendString("\031");
772 else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='Z')) sendString("\032");
773 else {
774 QCString s = codec->fromUnicode(ev->text()); // encode for application
775 emit sndBlock(s.data(),s.length()); // we may well have s.length() > 1
776 }
777 return;
778 }
779}
780
781/* ------------------------------------------------------------------------- */
782/* */
783/* VT100 Charsets */
784/* */
785/* ------------------------------------------------------------------------- */
786
787// Character Set Conversion ------------------------------------------------ --
788
789/*
790 The processing contains a VT100 specific code translation layer.
791 It's still in use and mainly responsible for the line drawing graphics.
792
793 These and some other glyphs are assigned to codes (0x5f-0xfe)
794 normally occupied by the latin letters. Since this codes also
795 appear within control sequences, the extra code conversion
796 does not permute with the tokenizer and is placed behind it
797 in the pipeline. It only applies to tokens, which represent
798 plain characters.
799
800 This conversion it eventually continued in TEWidget.C, since
801 it might involve VT100 enhanced fonts, which have these
802 particular glyphs allocated in (0x00-0x1f) in their code page.
803*/
804
805#define CHARSET charset[scr==screen[1]]
806
807// Apply current character map.
808
809unsigned short TEmuVt102::applyCharset(unsigned short c)
810{
811 if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f];
812 if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete
813 return c;
814}
815
816/*
817 "Charset" related part of the emulation state.
818 This configures the VT100 charset filter.
819
820 While most operation work on the current screen,
821 the following two are different.
822*/
823
824void TEmuVt102::resetCharset(int scrno)
825{
826 charset[scrno].cu_cs = 0;
827 strncpy(charset[scrno].charset,"BBBB",4);
828 charset[scrno].sa_graphic = FALSE;
829 charset[scrno].sa_pound = FALSE;
830 charset[scrno].graphic = FALSE;
831 charset[scrno].pound = FALSE;
832}
833
834/*!
835*/
836
837void TEmuVt102::setCharset(int n, int cs) // on both screens.
838{
839 charset[0].charset[n&3] = cs; useCharset(charset[0].cu_cs);
840 charset[1].charset[n&3] = cs; useCharset(charset[1].cu_cs);
841}
842
843/*!
844*/
845
846void TEmuVt102::setAndUseCharset(int n, int cs)
847{
848 CHARSET.charset[n&3] = cs;
849 useCharset(n&3);
850}
851
852/*!
853*/
854
855void TEmuVt102::useCharset(int n)
856{
857 CHARSET.cu_cs = n&3;
858 CHARSET.graphic = (CHARSET.charset[n&3] == '0');
859 CHARSET.pound = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete
860}
861
862/*! Save the cursor position and the rendition attribute settings. */
863
864void TEmuVt102::saveCursor()
865{
866 CHARSET.sa_graphic = CHARSET.graphic;
867 CHARSET.sa_pound = CHARSET.pound; //This mode is obsolete
868 // we are not clear about these
869 //sa_charset = charsets[cScreen->charset];
870 //sa_charset_num = cScreen->charset;
871 scr->saveCursor();
872}
873
874/*! Restore the cursor position and the rendition attribute settings. */
875
876void TEmuVt102::restoreCursor()
877{
878 CHARSET.graphic = CHARSET.sa_graphic;
879 CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete
880 scr->restoreCursor();
881}
882
883/* ------------------------------------------------------------------------- */
884/* */
885/* Mode Operations */
886/* */
887/* ------------------------------------------------------------------------- */
888
889/*
890 Some of the emulations state is either added to the state of the screens.
891
892 This causes some scoping problems, since different emulations choose to
893 located the mode either to the current screen or to both.
894
895 For strange reasons, the extend of the rendition attributes ranges over
896 all screens and not over the actual screen.
897
898 We decided on the precise precise extend, somehow.
899*/
900
901// "Mode" related part of the state. These are all booleans.
902
903void TEmuVt102::resetModes()
904{
905 resetMode(MODE_Mouse1000); saveMode(MODE_Mouse1000);
906 resetMode(MODE_AppScreen); saveMode(MODE_AppScreen);
907 // here come obsolete modes
908 resetMode(MODE_AppCuKeys); saveMode(MODE_AppCuKeys);
909 resetMode(MODE_NewLine );
910 setMode(MODE_Ansi );
911}
912
913void TEmuVt102::setMode(int m)
914{
915 currParm.mode[m] = TRUE;
916 switch (m)
917 {
918 case MODE_Mouse1000 : gui->setMouseMarks(FALSE);
919 break;
920 case MODE_AppScreen : screen[1]->clearSelection();
921 screen[1]->clearEntireScreen();
922 setScreen(1);
923 break;
924 }
925 if (m < MODES_SCREEN || m == MODE_NewLine)
926 {
927 screen[0]->setMode(m);
928 screen[1]->setMode(m);
929 }
930}
931
932void TEmuVt102::resetMode(int m)
933{
934 currParm.mode[m] = FALSE;
935 switch (m)
936 {
937 case MODE_Mouse1000 : gui->setMouseMarks(TRUE);
938 break;
939 case MODE_AppScreen : screen[0]->clearSelection();
940 setScreen(0);
941 break;
942 }
943 if (m < MODES_SCREEN || m == MODE_NewLine)
944 {
945 screen[0]->resetMode(m);
946 screen[1]->resetMode(m);
947 }
948}
949
950void TEmuVt102::saveMode(int m)
951{
952 saveParm.mode[m] = currParm.mode[m];
953}
954
955void TEmuVt102::restoreMode(int m)
956{
957 if(saveParm.mode[m]) setMode(m); else resetMode(m);
958}
959
960BOOL TEmuVt102::getMode(int m)
961{
962 return currParm.mode[m];
963}
964
965void TEmuVt102::setConnect(bool c)
966{
967 TEmulation::setConnect(c);
968 if (c)
969 { // refresh mouse mode
970 if (getMode(MODE_Mouse1000))
971 setMode(MODE_Mouse1000);
972 else
973 resetMode(MODE_Mouse1000);
974 }
975}
976
977/* ------------------------------------------------------------------------- */
978/* */
979/* Diagnostic */
980/* */
981/* ------------------------------------------------------------------------- */
982
983/*! shows the contents of the scan buffer.
984
985 This functions is used for diagnostics. It is called by \e ReportErrorToken
986 to inform about strings that cannot be decoded or handled by the emulation.
987
988 \sa ReportErrorToken
989*/
990
991/*!
992*/
993
994static void hexdump(int* s, int len)
995{ int i;
996 for (i = 0; i < len; i++)
997 {
998 if (s[i] == '\\')
999 printf("\\\\");
1000 else
1001 if ((s[i]) > 32 && s[i] < 127)
1002 printf("%c",s[i]);
1003 else
1004 printf("\\%04x(hex)",s[i]);
1005 }
1006}
1007
1008void TEmuVt102::scan_buffer_report()
1009{
1010 if (ppos == 0 || ppos == 1 && (pbuf[0] & 0xff) >= 32) return;
1011 printf("token: "); hexdump(pbuf,ppos); printf("\n");
1012}
1013
1014/*!
1015*/
1016
1017void TEmuVt102::ReportErrorToken()
1018{
1019 printf("undecodable "); scan_buffer_report();
1020}
diff --git a/noncore/apps/opie-console/TEmuVt102.h b/noncore/apps/opie-console/TEmuVt102.h
new file mode 100644
index 0000000..a448a71
--- a/dev/null
+++ b/noncore/apps/opie-console/TEmuVt102.h
@@ -0,0 +1,135 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [TEmuVt102.h] X Terminal Emulation */
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#ifndef VT102EMU_H
20#define VT102EMU_H
21
22#include "TEWidget.h"
23#include "TEScreen.h"
24#include "TEmulation.h"
25#include <qtimer.h>
26#include <stdio.h>
27
28//
29
30#define MODE_AppScreen (MODES_SCREEN+0)
31#define MODE_AppCuKeys (MODES_SCREEN+1)
32#define MODE_AppKeyPad (MODES_SCREEN+2)
33#define MODE_Mouse1000 (MODES_SCREEN+3)
34#define MODE_Ansi (MODES_SCREEN+4)
35#define MODE_total (MODES_SCREEN+5)
36
37struct DECpar
38{
39 BOOL mode[MODE_total];
40};
41
42struct CharCodes
43{
44 // coding info
45 char charset[4]; //
46 int cu_cs; // actual charset.
47 bool graphic; // Some VT100 tricks
48 bool pound ; // Some VT100 tricks
49 bool sa_graphic; // saved graphic
50 bool sa_pound; // saved pound
51};
52
53class TEmuVt102 : public TEmulation
54{ Q_OBJECT
55
56public:
57
58 TEmuVt102(TEWidget* gui);
59 ~TEmuVt102();
60
61public slots: // signals incoming from TEWidget
62
63 void onKeyPress(QKeyEvent*);
64 void onMouse(int cb, int cx, int cy);
65
66signals:
67
68 void changeTitle(int,const QString&);
69 void prevSession();
70 void nextSession();
71
72public:
73
74 void reset();
75
76 void onRcvChar(int cc);
77 void sendString(const char *);
78
79public:
80
81 BOOL getMode (int m);
82
83 void setMode (int m);
84 void resetMode (int m);
85 void saveMode (int m);
86 void restoreMode(int m);
87 void resetModes();
88
89 void setConnect(bool r);
90
91private:
92
93 void resetToken();
94#define MAXPBUF 80
95 void pushToToken(int cc);
96 int pbuf[MAXPBUF]; //FIXME: overflow?
97 int ppos;
98#define MAXARGS 15
99 void addDigit(int dig);
100 void addArgument();
101 int argv[MAXARGS];
102 int argc;
103 void initTokenizer();
104 int tbl[256];
105
106 void scan_buffer_report(); //FIXME: rename
107 void ReportErrorToken(); //FIXME: rename
108
109 void tau(int code, int p, int q);
110 void XtermHack();
111
112 //
113
114 void reportTerminalType();
115 void reportStatus();
116 void reportAnswerBack();
117 void reportCursorPosition();
118 void reportTerminalParms(int p);
119
120protected:
121
122 unsigned short applyCharset(unsigned short c);
123 void setCharset(int n, int cs);
124 void useCharset(int n);
125 void setAndUseCharset(int n, int cs);
126 void saveCursor();
127 void restoreCursor();
128 void resetCharset(int scrno);
129 CharCodes charset[2];
130
131 DECpar currParm;
132 DECpar saveParm;
133};
134
135#endif // ifndef ANSIEMU_H
diff --git a/noncore/apps/opie-console/TEmulation.cpp b/noncore/apps/opie-console/TEmulation.cpp
new file mode 100644
index 0000000..6f3ad32
--- a/dev/null
+++ b/noncore/apps/opie-console/TEmulation.cpp
@@ -0,0 +1,363 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [TEmulation.cpp] Terminal Emulation Decoder */
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/*! \class TEmulation
20
21 \brief Mediator between TEWidget and TEScreen.
22
23 This class is responsible to scan the escapes sequences of the terminal
24 emulation and to map it to their corresponding semantic complements.
25 Thus this module knows mainly about decoding escapes sequences and
26 is a stateless device w.r.t. the semantics.
27
28 It is also responsible to refresh the TEWidget by certain rules.
29
30 \sa TEWidget \sa TEScreen
31
32 \par A note on refreshing
33
34 Although the modifications to the current screen image could immediately
35 be propagated via `TEWidget' to the graphical surface, we have chosen
36 another way here.
37
38 The reason for doing so is twofold.
39
40 First, experiments show that directly displaying the operation results
41 in slowing down the overall performance of emulations. Displaying
42 individual characters using X11 creates a lot of overhead.
43
44 Second, by using the following refreshing method, the screen operations
45 can be completely separated from the displaying. This greatly simplifies
46 the programmer's task of coding and maintaining the screen operations,
47 since one need not worry about differential modifications on the
48 display affecting the operation of concern.
49
50 We use a refreshing algorithm here that has been adoped from rxvt/kvt.
51
52 By this, refreshing is driven by a timer, which is (re)started whenever
53 a new bunch of data to be interpreted by the emulation arives at `onRcvBlock'.
54 As soon as no more data arrive for `BULK_TIMEOUT' milliseconds, we trigger
55 refresh. This rule suits both bulk display operation as done by curses as
56 well as individual characters typed.
57 (BULK_TIMEOUT < 1000 / max characters received from keyboard per second).
58
59 Additionally, we trigger refreshing by newlines comming in to make visual
60 snapshots of lists as produced by `cat', `ls' and likely programs, thereby
61 producing the illusion of a permanent and immediate display operation.
62
63 As a sort of catch-all needed for cases where none of the above
64 conditions catch, the screen refresh is also triggered by a count
65 of incoming bulks (`bulk_incnt').
66*/
67
68/* FIXME
69 - evtl. the bulk operations could be made more transparent.
70*/
71
72#include "TEmulation.h"
73#include "TEWidget.h"
74#include "TEScreen.h"
75#include <stdio.h>
76#include <stdlib.h>
77#include <unistd.h>
78#include <qkeycode.h>
79
80
81/* ------------------------------------------------------------------------- */
82/* */
83/* TEmulation */
84/* */
85/* ------------------------------------------------------------------------- */
86
87#define CNTL(c) ((c)-'@')
88
89/*!
90*/
91
92TEmulation::TEmulation(TEWidget* gui)
93: decoder((QTextDecoder*)NULL)
94{
95 this->gui = gui;
96
97 screen[0] = new TEScreen(gui->Lines(),gui->Columns());
98 screen[1] = new TEScreen(gui->Lines(),gui->Columns());
99 scr = screen[0];
100
101 bulk_nlcnt = 0; // reset bulk newline counter
102 bulk_incnt = 0; // reset bulk counter
103 connected = FALSE;
104
105 QObject::connect(&bulk_timer, SIGNAL(timeout()), this, SLOT(showBulk()) );
106 QObject::connect(gui,SIGNAL(changedImageSizeSignal(int,int)),
107 this,SLOT(onImageSizeChange(int,int)));
108 QObject::connect(gui,SIGNAL(changedHistoryCursor(int)),
109 this,SLOT(onHistoryCursorChange(int)));
110 QObject::connect(gui,SIGNAL(keyPressedSignal(QKeyEvent*)),
111 this,SLOT(onKeyPress(QKeyEvent*)));
112 QObject::connect(gui,SIGNAL(beginSelectionSignal(const int,const int)),
113 this,SLOT(onSelectionBegin(const int,const int)) );
114 QObject::connect(gui,SIGNAL(extendSelectionSignal(const int,const int)),
115 this,SLOT(onSelectionExtend(const int,const int)) );
116 QObject::connect(gui,SIGNAL(endSelectionSignal(const BOOL)),
117 this,SLOT(setSelection(const BOOL)) );
118 QObject::connect(gui,SIGNAL(clearSelectionSignal()),
119 this,SLOT(clearSelection()) );
120}
121
122/*!
123*/
124
125TEmulation::~TEmulation()
126{
127 delete screen[0];
128 delete screen[1];
129 bulk_timer.stop();
130}
131
132/*! change between primary and alternate screen
133*/
134
135void TEmulation::setScreen(int n)
136{
137 scr = screen[n&1];
138}
139
140void TEmulation::setHistory(bool on)
141{
142 screen[0]->setScroll(on);
143 if (!connected) return;
144 showBulk();
145}
146
147bool TEmulation::history()
148{
149 return screen[0]->hasScroll();
150}
151
152void TEmulation::setCodec(int c)
153{
154 //FIXME: check whether we have to free codec
155 codec = c ? QTextCodec::codecForName("utf8")
156 : QTextCodec::codecForLocale();
157 if (decoder) delete decoder;
158 decoder = codec->makeDecoder();
159}
160
161void TEmulation::setKeytrans(int no)
162{
163 keytrans = KeyTrans::find(no);
164}
165
166void TEmulation::setKeytrans(const char * no)
167{
168 keytrans = KeyTrans::find(no);
169}
170
171// Interpreting Codes ---------------------------------------------------------
172
173/*
174 This section deals with decoding the incoming character stream.
175 Decoding means here, that the stream is first seperated into `tokens'
176 which are then mapped to a `meaning' provided as operations by the
177 `Screen' class.
178*/
179
180/*!
181*/
182
183void TEmulation::onRcvChar(int c)
184// process application unicode input to terminal
185// this is a trivial scanner
186{
187 c &= 0xff;
188 switch (c)
189 {
190 case '\b' : scr->BackSpace(); break;
191 case '\t' : scr->Tabulate(); break;
192 case '\n' : scr->NewLine(); break;
193 case '\r' : scr->Return(); break;
194 case 0x07 : gui->Bell(); break;
195 default : scr->ShowCharacter(c); break;
196 };
197}
198
199/* ------------------------------------------------------------------------- */
200/* */
201/* Keyboard Handling */
202/* */
203/* ------------------------------------------------------------------------- */
204
205/*!
206*/
207
208void TEmulation::onKeyPress( QKeyEvent* ev )
209{
210 if (!connected) return; // someone else gets the keys
211 if (scr->getHistCursor() != scr->getHistLines());
212 scr->setHistCursor(scr->getHistLines());
213 if (!ev->text().isEmpty())
214 { // A block of text
215 // Note that the text is proper unicode.
216 // We should do a conversion here, but since this
217 // routine will never be used, we simply emit plain ascii.
218 emit sndBlock(ev->text().ascii(),ev->text().length());
219 }
220 else if (ev->ascii()>0)
221 { unsigned char c[1];
222 c[0] = ev->ascii();
223 emit sndBlock((char*)c,1);
224 }
225}
226
227// Unblocking, Byte to Unicode translation --------------------------------- --
228
229/*
230 We are doing code conversion from locale to unicode first.
231*/
232
233void TEmulation::onRcvBlock(const char *s, int len)
234{
235 bulkStart();
236 bulk_incnt += 1;
237 for (int i = 0; i < len; i++)
238 {
239 QString result = decoder->toUnicode(&s[i],1);
240 int reslen = result.length();
241 for (int j = 0; j < reslen; j++)
242 onRcvChar(result[j].unicode());
243 if (s[i] == '\n') bulkNewline();
244 }
245 bulkEnd();
246}
247
248// Selection --------------------------------------------------------------- --
249
250void TEmulation::onSelectionBegin(const int x, const int y) {
251 if (!connected) return;
252 scr->setSelBeginXY(x,y);
253 showBulk();
254}
255
256void TEmulation::onSelectionExtend(const int x, const int y) {
257 if (!connected) return;
258 scr->setSelExtentXY(x,y);
259 showBulk();
260}
261
262void TEmulation::setSelection(const BOOL preserve_line_breaks) {
263 if (!connected) return;
264 QString t = scr->getSelText(preserve_line_breaks);
265 if (!t.isNull()) gui->setSelection(t);
266}
267
268void TEmulation::clearSelection() {
269 if (!connected) return;
270 scr->clearSelection();
271 showBulk();
272}
273
274// Refreshing -------------------------------------------------------------- --
275
276#define BULK_TIMEOUT 20
277
278/*!
279 called when \n comes in. Evtl. triggers showBulk at endBulk
280*/
281
282void TEmulation::bulkNewline()
283{
284 bulk_nlcnt += 1;
285 bulk_incnt = 0; // reset bulk counter since `nl' rule applies
286}
287
288/*!
289*/
290
291void TEmulation::showBulk()
292{
293 bulk_nlcnt = 0; // reset bulk newline counter
294 bulk_incnt = 0; // reset bulk counter
295 if (connected)
296 {
297 ca* image = scr->getCookedImage(); // get the image
298 gui->setImage(image,
299 scr->getLines(),
300 scr->getColumns()); // actual refresh
301 free(image);
302 //FIXME: check that we do not trigger other draw event here.
303 gui->setScroll(scr->getHistCursor(),scr->getHistLines());
304 }
305}
306
307void TEmulation::bulkStart()
308{
309 if (bulk_timer.isActive()) bulk_timer.stop();
310}
311
312void TEmulation::bulkEnd()
313{
314 if ( bulk_nlcnt > gui->Lines() || bulk_incnt > 20 )
315 showBulk(); // resets bulk_??cnt to 0, too.
316 else
317 bulk_timer.start(BULK_TIMEOUT,TRUE);
318}
319
320void TEmulation::setConnect(bool c)
321{
322 connected = c;
323 if ( connected)
324 {
325 onImageSizeChange(gui->Lines(), gui->Columns());
326 showBulk();
327 }
328 else
329 {
330 scr->clearSelection();
331 }
332}
333
334// ---------------------------------------------------------------------------
335
336/*! triggered by image size change of the TEWidget `gui'.
337
338 This event is simply propagated to the attached screens
339 and to the related serial line.
340*/
341
342void TEmulation::onImageSizeChange(int lines, int columns)
343{
344 if (!connected) return;
345 screen[0]->resizeImage(lines,columns);
346 screen[1]->resizeImage(lines,columns);
347 showBulk();
348 emit ImageSizeChanged(lines,columns); // propagate event to serial line
349}
350
351void TEmulation::onHistoryCursorChange(int cursor)
352{
353 if (!connected) return;
354 scr->setHistCursor(cursor);
355 showBulk();
356}
357
358void TEmulation::setColumns(int columns)
359{
360 //FIXME: this goes strange ways.
361 // Can we put this straight or explain it at least?
362 emit changeColumns(columns);
363}
diff --git a/noncore/apps/opie-console/TEmulation.h b/noncore/apps/opie-console/TEmulation.h
new file mode 100644
index 0000000..ec15e7a
--- a/dev/null
+++ b/noncore/apps/opie-console/TEmulation.h
@@ -0,0 +1,117 @@
1/* -------------------------------------------------------------------------- */
2/* */
3/* [emulation.h] Fundamental Terminal Emulation */
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#ifndef EMULATION_H
20#define EMULATION_H
21
22#include "TEWidget.h"
23#include "TEScreen.h"
24#include <qtimer.h>
25#include <stdio.h>
26#include <qtextcodec.h>
27#include "keytrans.h"
28
29class TEmulation : public QObject
30{ Q_OBJECT
31
32public:
33
34 TEmulation(TEWidget* gui);
35 ~TEmulation();
36
37public:
38 virtual void setHistory(bool on);
39 virtual bool history();
40
41public slots: // signals incoming from TEWidget
42
43 virtual void onImageSizeChange(int lines, int columns);
44 virtual void onHistoryCursorChange(int cursor);
45 virtual void onKeyPress(QKeyEvent*);
46
47 virtual void clearSelection();
48 virtual void onSelectionBegin(const int x, const int y);
49 virtual void onSelectionExtend(const int x, const int y);
50 virtual void setSelection(const BOOL preserve_line_breaks);
51
52public slots: // signals incoming from data source
53
54 void onRcvBlock(const char* txt,int len);
55
56signals:
57
58 void sndBlock(const char* txt,int len);
59 void ImageSizeChanged(int lines, int columns);
60 void changeColumns(int columns);
61 void changeTitle(int arg, const char* str);
62
63public:
64
65 virtual void onRcvChar(int);
66
67 virtual void setMode (int) = 0;
68 virtual void resetMode(int) = 0;
69
70 virtual void sendString(const char*) = 0;
71
72 virtual void setConnect(bool r);
73 void setColumns(int columns);
74
75 void setKeytrans(int no);
76 void setKeytrans(const char * no);
77
78protected:
79
80 TEWidget* gui;
81 TEScreen* scr; // referes to one `screen'
82 TEScreen* screen[2]; // 0 = primary, 1 = alternate
83 void setScreen(int n); // set `scr' to `screen[n]'
84
85 bool connected; // communicate with widget
86
87 void setCodec(int c); // codec number, 0 = locale, 1=utf8
88
89 QTextCodec* codec;
90 QTextCodec* localeCodec;
91 QTextDecoder* decoder;
92
93 KeyTrans* keytrans;
94
95// refreshing related material.
96// this is localized in the class.
97private slots: // triggered by timer
98
99 void showBulk();
100
101private:
102
103 void bulkNewline();
104 void bulkStart();
105 void bulkEnd();
106
107private:
108
109 QTimer bulk_timer;
110 int bulk_nlcnt; // bulk newline counter
111 char* SelectedText;
112 int bulk_incnt; // bulk counter
113
114
115};
116
117#endif // ifndef EMULATION_H
diff --git a/noncore/apps/opie-console/default.cpp b/noncore/apps/opie-console/default.cpp
index dd9681d..ce5c870 100644
--- a/noncore/apps/opie-console/default.cpp
+++ b/noncore/apps/opie-console/default.cpp
@@ -62,15 +62,15 @@ extern "C" {
62 62
63 63
64 // Terminal Widget(s) 64 // Terminal Widget(s)
65 ProfileDialogWidget* newTerminalWidget(const QString& na, QWidget* wid) { 65/* ProfileDialogWidget* newTerminalWidget(const QString& na, QWidget* wid) {
66 return new TerminalWidget(na, wid,0 ); 66 return new TerminalWidget(na, wid,0 );
67 } 67 }
68 68*/
69 // VT Emulations 69/* // VT Emulations
70 EmulationLayer* newVT102( WidgetLayer* wid ) { 70 EmulationLayer* newVT102( WidgetLayer* wid ) {
71 return new Vt102Emulation( wid ); 71 return new Vt102Emulation( wid );
72 } 72 }
73 73*/
74}; 74};
75 75
76Default::Default( MetaFactory* fact ) { 76Default::Default( MetaFactory* fact ) {
@@ -91,9 +91,9 @@ Default::Default( MetaFactory* fact ) {
91 fact->addConnectionWidgetFactory( "modem", QObject::tr("Modem"), newModemWidget ); 91 fact->addConnectionWidgetFactory( "modem", QObject::tr("Modem"), newModemWidget );
92 fact->addConnectionWidgetFactory( "bt", QObject::tr("Bluetooth"), newBTWidget ); 92 fact->addConnectionWidgetFactory( "bt", QObject::tr("Bluetooth"), newBTWidget );
93 93
94 fact->addTerminalWidgetFactory( "default", QObject::tr("Default Terminal"), newTerminalWidget ); 94// fact->addTerminalWidgetFactory( "default", QObject::tr("Default Terminal"), newTerminalWidget );
95 95
96 fact->addEmulationLayer( "default", QObject::tr("Default Terminal"), newVT102 ); 96// fact->addEmulationLayer( "default", QObject::tr("Default Terminal"), newVT102 );
97} 97}
98Default::~Default() { 98Default::~Default() {
99 99
diff --git a/noncore/apps/opie-console/default.h b/noncore/apps/opie-console/default.h
index 03616f3..288f370 100644
--- a/noncore/apps/opie-console/default.h
+++ b/noncore/apps/opie-console/default.h
@@ -22,9 +22,9 @@ extern "C" {
22 ProfileDialogWidget* newIrDaWidget (const QString&, QWidget* ); 22 ProfileDialogWidget* newIrDaWidget (const QString&, QWidget* );
23 ProfileDialogWidget* newBTWidget (const QString&, QWidget* ); 23 ProfileDialogWidget* newBTWidget (const QString&, QWidget* );
24 24
25 ProfileDialogWidget* newTerminalWidget(const QString&, QWidget* ); 25// ProfileDialogWidget* newTerminalWidget(const QString&, QWidget* );
26 26
27 EmulationLayer* newVT102( WidgetLayer* ); 27// EmulationLayer* newVT102( WidgetLayer* );
28}; 28};
29 29
30class MetaFactory; 30class MetaFactory;
diff --git a/noncore/apps/opie-console/history.cpp b/noncore/apps/opie-console/history.cpp
index 3b82d16..226a0a2 100644
--- a/noncore/apps/opie-console/history.cpp
+++ b/noncore/apps/opie-console/history.cpp
@@ -67,7 +67,7 @@ FIXME: There is noticable decrease in speed, also. Perhaps,
67// this is here one for debugging purpose. 67// this is here one for debugging purpose.
68 68
69//#define tmpfile xTmpFile 69//#define tmpfile xTmpFile
70 70/*
71FILE* xTmpFile() 71FILE* xTmpFile()
72{ 72{
73 static int fid = 0; 73 static int fid = 0;
@@ -75,7 +75,7 @@ FILE* xTmpFile()
75 sprintf(fname,"TmpFile.%d",fid++); 75 sprintf(fname,"TmpFile.%d",fid++);
76 return fopen(fname,"w"); 76 return fopen(fname,"w");
77} 77}
78 78*/
79 79
80// History Buffer /////////////////////////////////////////// 80// History Buffer ///////////////////////////////////////////
81 81
diff --git a/noncore/apps/opie-console/io_layer.cpp b/noncore/apps/opie-console/io_layer.cpp
index 9ba2f70..975ee60 100644
--- a/noncore/apps/opie-console/io_layer.cpp
+++ b/noncore/apps/opie-console/io_layer.cpp
@@ -18,3 +18,5 @@ int IOLayer::rawIO()const{
18void IOLayer::closeRawIO(int) { 18void IOLayer::closeRawIO(int) {
19 19
20} 20}
21void IOLayer::setSize(int, int ) {
22}
diff --git a/noncore/apps/opie-console/io_layer.h b/noncore/apps/opie-console/io_layer.h
index bf5a893..9c99222 100644
--- a/noncore/apps/opie-console/io_layer.h
+++ b/noncore/apps/opie-console/io_layer.h
@@ -64,6 +64,8 @@ public:
64 * and will listen to it's data again... 64 * and will listen to it's data again...
65 */ 65 */
66 virtual void closeRawIO(int); 66 virtual void closeRawIO(int);
67
68
67signals: 69signals:
68 /** 70 /**
69 * received input as QCString 71 * received input as QCString
@@ -97,6 +99,12 @@ public slots:
97 * closes and reloads the settings 99 * closes and reloads the settings
98 */ 100 */
99 virtual void reload( const Profile& ) = 0; 101 virtual void reload( const Profile& ) = 0;
102
103 /**
104 * set the size
105 * needed for pty
106 */
107 virtual void setSize(int rows, int cols );
100}; 108};
101 109
102#endif 110#endif
diff --git a/noncore/apps/opie-console/mainwindow.cpp b/noncore/apps/opie-console/mainwindow.cpp
index 1adb43d..1d7a4be 100644
--- a/noncore/apps/opie-console/mainwindow.cpp
+++ b/noncore/apps/opie-console/mainwindow.cpp
@@ -214,13 +214,14 @@ void MainWindow::slotNew() {
214} 214}
215 215
216void MainWindow::slotRecordScript() { 216void MainWindow::slotRecordScript() {
217 if (currentSession()) { 217/* if (currentSession()) {
218 currentSession()->emulationLayer()->startRecording(); 218 currentSession()->emulationLayer()->startRecording();
219 } 219 }
220 */
220} 221}
221 222
222void MainWindow::slotSaveScript() { 223void MainWindow::slotSaveScript() {
223 if (currentSession() && currentSession()->emulationLayer()->isRecording()) { 224/* if (currentSession() && currentSession()->emulationLayer()->isRecording()) {
224 MimeTypes types; 225 MimeTypes types;
225 QStringList script; 226 QStringList script;
226 script << "text/plain"; 227 script << "text/plain";
@@ -231,9 +232,11 @@ void MainWindow::slotSaveScript() {
231 currentSession()->emulationLayer()->clearScript(); 232 currentSession()->emulationLayer()->clearScript();
232 } 233 }
233 } 234 }
235 */
234} 236}
235 237
236void MainWindow::slotRunScript() { 238void MainWindow::slotRunScript() {
239/*
237 if (currentSession()) { 240 if (currentSession()) {
238 MimeTypes types; 241 MimeTypes types;
239 QStringList script; 242 QStringList script;
@@ -245,6 +248,7 @@ void MainWindow::slotRunScript() {
245 currentSession()->emulationLayer()->runScript(&script); 248 currentSession()->emulationLayer()->runScript(&script);
246 } 249 }
247 } 250 }
251 */
248} 252}
249 253
250void MainWindow::slotConnect() { 254void MainWindow::slotConnect() {
diff --git a/noncore/apps/opie-console/opie-console.pro b/noncore/apps/opie-console/opie-console.pro
index 26bce83..7990a64 100644
--- a/noncore/apps/opie-console/opie-console.pro
+++ b/noncore/apps/opie-console/opie-console.pro
@@ -13,27 +13,23 @@ HEADERS = io_layer.h io_serial.h io_irda.h io_bt.h io_modem.h \
13 configwidget.h \ 13 configwidget.h \
14 tabwidget.h \ 14 tabwidget.h \
15 configdialog.h \ 15 configdialog.h \
16 emulation_layer.h \
17 vt102emulation.h \
18 common.h \
19 history.h \
20 screen.h \
21 keytrans.h \ 16 keytrans.h \
22 widget_layer.h \
23 transferdialog.h \ 17 transferdialog.h \
24 profiledialogwidget.h \ 18 profiledialogwidget.h \
25 profileeditordialog.h \ 19 profileeditordialog.h \
26 default.h \ 20 default.h \
27 terminalwidget.h \
28 iolayerbase.h \ 21 iolayerbase.h \
29 serialconfigwidget.h irdaconfigwidget.h \ 22 serialconfigwidget.h irdaconfigwidget.h \
30 btconfigwidget.h modemconfigwidget.h \ 23 btconfigwidget.h modemconfigwidget.h \
31 atconfigdialog.h dialdialog.h \ 24 atconfigdialog.h dialdialog.h \
32 emulation_widget.h procctl.h \ 25 procctl.h \
33 function_keyboard.h \ 26 function_keyboard.h \
34 receive_layer.h filereceive.h \ 27 receive_layer.h filereceive.h \
35 script.h \ 28 script.h \
36 dialer.h 29 dialer.h \
30 emulation_handler.h TECommon.h \
31 TEHistroy.h TEScreen.h TEWidget.h \
32 TEmuVt102.h TEmulation.h
37 33
38SOURCES = io_layer.cpp io_serial.cpp io_irda.cpp io_bt.cpp io_modem.cpp \ 34SOURCES = io_layer.cpp io_serial.cpp io_irda.cpp io_bt.cpp io_modem.cpp \
39 file_layer.cpp filetransfer.cpp \ 35 file_layer.cpp filetransfer.cpp \
@@ -46,25 +42,23 @@ SOURCES = io_layer.cpp io_serial.cpp io_irda.cpp io_bt.cpp io_modem.cpp \
46 profilemanager.cpp \ 42 profilemanager.cpp \
47 tabwidget.cpp \ 43 tabwidget.cpp \
48 configdialog.cpp \ 44 configdialog.cpp \
49 emulation_layer.cpp \
50 vt102emulation.cpp \
51 history.cpp \
52 screen.cpp \
53 keytrans.cpp \ 45 keytrans.cpp \
54 widget_layer.cpp \
55 transferdialog.cpp \ 46 transferdialog.cpp \
56 profiledialogwidget.cpp \ 47 profiledialogwidget.cpp \
57 profileeditordialog.cpp \ 48 profileeditordialog.cpp \
58 terminalwidget.cpp \
59 iolayerbase.cpp \ 49 iolayerbase.cpp \
60 serialconfigwidget.cpp irdaconfigwidget.cpp \ 50 serialconfigwidget.cpp irdaconfigwidget.cpp \
61 btconfigwidget.cpp modemconfigwidget.cpp \ 51 btconfigwidget.cpp modemconfigwidget.cpp \
62 atconfigdialog.cpp dialdialog.cpp \ 52 atconfigdialog.cpp dialdialog.cpp \
63 emulation_widget.cpp default.cpp procctl.cpp \ 53 default.cpp procctl.cpp \
64 function_keyboard.cpp \ 54 function_keyboard.cpp \
65 receive_layer.cpp filereceive.cpp \ 55 receive_layer.cpp filereceive.cpp \
66 script.cpp \ 56 script.cpp \
67 dialer.cpp 57 dialer.cpp \
58 emulation_handler.cpp TEHistory.cpp \
59 TEScreen.cpp TEWidget.cpp \
60 TEmuVt102.cpp TEmulation.cpp
61
68 62
69INTERFACES = configurebase.ui editbase.ui 63INTERFACES = configurebase.ui editbase.ui
70INCLUDEPATH += $(OPIEDIR)/include 64INCLUDEPATH += $(OPIEDIR)/include
diff --git a/noncore/apps/opie-console/profilemanager.cpp b/noncore/apps/opie-console/profilemanager.cpp
index 4b88dec..113327c 100644
--- a/noncore/apps/opie-console/profilemanager.cpp
+++ b/noncore/apps/opie-console/profilemanager.cpp
@@ -7,6 +7,7 @@
7 7
8#include <qpe/config.h> 8#include <qpe/config.h>
9 9
10#include "emulation_handler.h"
10#include "widget_layer.h" 11#include "widget_layer.h"
11#include "emulation_widget.h" 12#include "emulation_widget.h"
12#include "metafactory.h" 13#include "metafactory.h"
@@ -83,12 +84,14 @@ Session* ProfileManager::fromProfile( const Profile& prof, QWidget* parent) {
83 QHBoxLayout* lay = new QHBoxLayout(dummy ); 84 QHBoxLayout* lay = new QHBoxLayout(dummy );
84 stack->addWidget( dummy, 0 ); 85 stack->addWidget( dummy, 0 );
85 stack->raiseWidget( 0 ); 86 stack->raiseWidget( 0 );
86 WidgetLayer* wid = new EmulationWidget( prof, dummy ); 87 EmulationHandler* handler = new EmulationHandler(prof,dummy );
87 lay->addWidget( wid ); 88 lay->addWidget( handler->widget() );
88 89// WidgetLayer* wid = new EmulationWidget( prof, dummy );
89 session->setEmulationWidget( wid ); 90// lay->addWidget( wid );
90 session->setEmulationLayer( m_fact->newEmulationLayer( m_fact->external( prof.terminalName() ), 91
91 wid ) ); 92// session->setEmulationWidget( wid );
93// session->setEmulationLayer( m_fact->newEmulationLayer( m_fact->external( prof.terminalName() ),
94// wid ) );
92 session->connect(); 95 session->connect();
93 96
94 return session; 97 return session;
diff --git a/noncore/apps/opie-console/session.cpp b/noncore/apps/opie-console/session.cpp
index ff2c3e2..7cae0df 100644
--- a/noncore/apps/opie-console/session.cpp
+++ b/noncore/apps/opie-console/session.cpp
@@ -10,18 +10,18 @@
10Session::Session() { 10Session::Session() {
11 m_widget = 0l; 11 m_widget = 0l;
12 m_layer = 0l; 12 m_layer = 0l;
13 m_widLay = 0l; 13// m_widLay = 0l;
14 m_emLay = 0l; 14// m_emLay = 0l;
15} 15}
16Session::Session( const QString& na, QWidgetStack* widget, IOLayer* lay) 16Session::Session( const QString& na, QWidgetStack* widget, IOLayer* lay)
17 : m_name( na ), m_widget( widget ), m_layer( lay ) 17 : m_name( na ), m_widget( widget ), m_layer( lay )
18{ 18{
19 m_widLay = 0l; 19// m_widLay = 0l;
20 m_emLay = 0l; 20// m_emLay = 0l;
21} 21}
22Session::~Session() { 22Session::~Session() {
23 delete m_layer; 23 delete m_layer;
24 delete m_emLay; 24// delete m_emLay;
25 delete m_widget; 25 delete m_widget;
26 /* the widget layer should be deleted by the m_widget */ 26 /* the widget layer should be deleted by the m_widget */
27} 27}
@@ -34,22 +34,25 @@ QWidgetStack* Session::widgetStack() {
34IOLayer* Session::layer() { 34IOLayer* Session::layer() {
35 return m_layer; 35 return m_layer;
36} 36}
37EmulationLayer* Session::emulationLayer() { 37/*EmulationLayer* Session::emulationLayer() {
38 return m_emLay; 38 return m_emLay;
39} 39}
40WidgetLayer* Session::emulationWidget() { 40WidgetLayer* Session::emulationWidget() {
41 return m_widLay; 41 return m_widLay;
42} 42}
43*/
43void Session::connect() { 44void Session::connect() {
44 if ( !m_layer || !m_emLay ) 45/* if ( !m_layer || !m_emLay )
45 return; 46 return;
46 47
47 QObject::connect(m_layer, SIGNAL(received(const QByteArray&) ), 48 QObject::connect(m_layer, SIGNAL(received(const QByteArray&) ),
48 m_emLay, SLOT(onRcvBlock(const QByteArray&) ) ); 49 m_emLay, SLOT(onRcvBlock(const QByteArray&) ) );
49 QObject::connect(m_emLay, SIGNAL(sndBlock(const QByteArray&) ), 50 QObject::connect(m_emLay, SIGNAL(sndBlock(const QByteArray&) ),
50 m_layer, SLOT(send(const QByteArray&) ) ); 51 m_layer, SLOT(send(const QByteArray&) ) );
52 */
51} 53}
52void Session::disconnect() { 54void Session::disconnect() {
55/*
53 if ( !m_layer || !m_emLay ) 56 if ( !m_layer || !m_emLay )
54 return; 57 return;
55 58
@@ -57,6 +60,7 @@ void Session::disconnect() {
57 m_emLay, SLOT(onRcvBlock(const QByteArray&) ) ); 60 m_emLay, SLOT(onRcvBlock(const QByteArray&) ) );
58 QObject::disconnect(m_emLay, SIGNAL(sndBlock(const QByteArray&) ), 61 QObject::disconnect(m_emLay, SIGNAL(sndBlock(const QByteArray&) ),
59 m_layer, SLOT(send(const QByteArray&) ) ); 62 m_layer, SLOT(send(const QByteArray&) ) );
63 */
60} 64}
61void Session::setName( const QString& na){ 65void Session::setName( const QString& na){
62 m_name = na; 66 m_name = na;
@@ -64,13 +68,14 @@ void Session::setName( const QString& na){
64void Session::setWidgetStack( QWidgetStack* wid ) { 68void Session::setWidgetStack( QWidgetStack* wid ) {
65 delete m_widget; 69 delete m_widget;
66 /* the EmulationLayer was destroyed... */ 70 /* the EmulationLayer was destroyed... */
67 delete m_emLay; 71 //delete m_emLay;
68 m_widget = wid; 72 m_widget = wid;
69} 73}
70void Session::setIOLayer( IOLayer* lay ) { 74void Session::setIOLayer( IOLayer* lay ) {
71 delete m_layer; 75 delete m_layer;
72 m_layer = lay; 76 m_layer = lay;
73} 77}
78/*
74void Session::setEmulationLayer( EmulationLayer* lay ) { 79void Session::setEmulationLayer( EmulationLayer* lay ) {
75 delete m_emLay; 80 delete m_emLay;
76 m_emLay = lay; 81 m_emLay = lay;
@@ -79,3 +84,4 @@ void Session::setEmulationWidget( WidgetLayer* lay ) {
79 delete m_widLay; 84 delete m_widLay;
80 m_widLay = lay; 85 m_widLay = lay;
81} 86}
87*/ \ No newline at end of file
diff --git a/noncore/apps/opie-console/session.h b/noncore/apps/opie-console/session.h
index 64c2cdb..04bf257 100644
--- a/noncore/apps/opie-console/session.h
+++ b/noncore/apps/opie-console/session.h
@@ -41,7 +41,7 @@ public:
41 */ 41 */
42 IOLayer* layer(); 42 IOLayer* layer();
43 43
44 EmulationLayer* emulationLayer(); 44// EmulationLayer* emulationLayer();
45 WidgetLayer* emulationWidget(); 45 WidgetLayer* emulationWidget();
46 46
47 /* 47 /*
@@ -57,8 +57,8 @@ public:
57 void disconnect(); 57 void disconnect();
58 58
59 void setWidgetStack( QWidgetStack* widget ); 59 void setWidgetStack( QWidgetStack* widget );
60 void setEmulationLayer( EmulationLayer* lay ); 60// void setEmulationLayer( EmulationLayer* lay );
61 void setEmulationWidget( WidgetLayer* lay ); 61// void setEmulationWidget( WidgetLayer* lay );
62 void setIOLayer( IOLayer* ); 62 void setIOLayer( IOLayer* );
63 void setName( const QString& ); 63 void setName( const QString& );
64 64
@@ -66,8 +66,8 @@ private:
66 QString m_name; 66 QString m_name;
67 QWidgetStack* m_widget; 67 QWidgetStack* m_widget;
68 IOLayer* m_layer; 68 IOLayer* m_layer;
69 EmulationLayer* m_emLay; 69// EmulationLayer* m_emLay;
70 WidgetLayer* m_widLay; 70// WidgetLayer* m_widLay;
71 71
72}; 72};
73 73