summaryrefslogtreecommitdiff
Side-by-side diff
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 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [TECommon.h] Common Definitions */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
+/* */
+/* This file is part of Konsole - an X terminal for KDE */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Ported Konsole to Qt/Embedded */
+/* */
+/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+/*! \file TECommon.h
+ \brief Definitions shared between TEScreen and TEWidget.
+*/
+
+#ifndef TECOMMON_H
+#define TECOMMON_H
+
+#include <qcolor.h>
+
+#ifndef BOOL
+typedef int BOOL;
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef UINT8
+typedef unsigned char UINT8;
+#endif
+
+#ifndef UINT16
+typedef unsigned short UINT16;
+#endif
+
+// Attributed Character Representations ///////////////////////////////
+
+// Colors
+
+#define BASE_COLORS (2+8)
+#define INTENSITIES 2
+#define TABLE_COLORS (INTENSITIES*BASE_COLORS)
+
+#define DEFAULT_FORE_COLOR 0
+#define DEFAULT_BACK_COLOR 1
+
+#define DEFAULT_RENDITION 0
+#define RE_BOLD (1 << 0)
+#define RE_BLINK (1 << 1)
+#define RE_UNDERLINE (1 << 2)
+#define RE_REVERSE (1 << 3) // Screen only
+#define RE_INTENSIVE (1 << 3) // Widget only
+
+/*! \class ca
+ * \brief a character with rendition attributes.
+*/
+
+class ca
+{
+public:
+ inline ca(UINT16 _c = ' ',
+ UINT8 _f = DEFAULT_FORE_COLOR,
+ UINT8 _b = DEFAULT_BACK_COLOR,
+ UINT8 _r = DEFAULT_RENDITION)
+ : c(_c), f(_f), b(_b), r(_r) {}
+public:
+ UINT16 c; // character
+ UINT8 f; // foreground color
+ UINT8 b; // background color
+ UINT8 r; // rendition
+public:
+ friend BOOL operator == (ca a, ca b);
+ friend BOOL operator != (ca a, ca b);
+};
+
+inline BOOL operator == (ca a, ca b)
+{
+ return a.c == b.c && a.f == b.f && a.b == b.b && a.r == b.r;
+}
+
+inline BOOL operator != (ca a, ca b)
+{
+ return a.c != b.c || a.f != b.f || a.b != b.b || a.r != b.r;
+}
+
+/*!
+*/
+struct ColorEntry
+{
+ ColorEntry(QColor c, bool tr, bool b) : color(c), transparent(tr), bold(b) {}
+ ColorEntry() : transparent(false), bold(false) {} // default constructors
+ void operator=(const ColorEntry& rhs) {
+ color = rhs.color;
+ transparent = rhs.transparent;
+ bold = rhs.bold;
+ }
+ QColor color;
+ bool transparent; // if used on bg
+ bool bold; // if used on fg
+};
+
+#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 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [TEHistory.C] History Buffer */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
+/* */
+/* This file is part of Konsole - an X terminal for KDE */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Ported Konsole to Qt/Embedded */
+/* */
+/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+#include "TEHistory.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
+
+/*
+ An arbitrary long scroll.
+
+ One can modify the scroll only by adding either cells
+ or newlines, but access it randomly.
+
+ The model is that of an arbitrary wide typewriter scroll
+ in that the scroll is a serie of lines and each line is
+ a serie of cells with no overwriting permitted.
+
+ The implementation provides arbitrary length and numbers
+ of cells and line/column indexed read access to the scroll
+ at constant costs.
+
+FIXME: some complain about the history buffer comsuming the
+ memory of their machines. This problem is critical
+ since the history does not behave gracefully in cases
+ where the memory is used up completely.
+
+ I put in a workaround that should handle it problem
+ now gracefully. I'm not satisfied with the solution.
+
+FIXME: Terminating the history is not properly indicated
+ in the menu. We should throw a signal.
+
+FIXME: There is noticable decrease in speed, also. Perhaps,
+ there whole feature needs to be revisited therefore.
+ Disadvantage of a more elaborated, say block-oriented
+ scheme with wrap around would be it's complexity.
+*/
+
+//FIXME: tempory replacement for tmpfile
+// this is here one for debugging purpose.
+
+//#define tmpfile xTmpFile
+
+FILE* xTmpFile()
+{
+ static int fid = 0;
+ char fname[80];
+ sprintf(fname,"TmpFile.%d",fid++);
+ return fopen(fname,"w");
+}
+
+
+// History Buffer ///////////////////////////////////////////
+
+/*
+ A Row(X) data type which allows adding elements to the end.
+*/
+
+HistoryBuffer::HistoryBuffer()
+{
+ ion = -1;
+ length = 0;
+}
+
+HistoryBuffer::~HistoryBuffer()
+{
+ setScroll(FALSE);
+}
+
+void HistoryBuffer::setScroll(bool on)
+{
+ if (on == hasScroll()) return;
+
+ if (on)
+ {
+ assert( ion < 0 );
+ assert( length == 0);
+ FILE* tmp = tmpfile(); if (!tmp) { perror("konsole: cannot open temp file.\n"); return; }
+ ion = dup(fileno(tmp)); if (ion<0) perror("konsole: cannot dup temp file.\n");
+ fclose(tmp);
+ }
+ else
+ {
+ assert( ion >= 0 );
+ close(ion);
+ ion = -1;
+ length = 0;
+ }
+}
+
+bool HistoryBuffer::hasScroll()
+{
+ return ion >= 0;
+}
+
+void HistoryBuffer::add(const unsigned char* bytes, int len)
+{ int rc;
+ assert(hasScroll());
+ rc = lseek(ion,length,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::add.seek"); setScroll(FALSE); return; }
+ rc = write(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::add.write"); setScroll(FALSE); return; }
+ length += rc;
+}
+
+void HistoryBuffer::get(unsigned char* bytes, int len, int loc)
+{ int rc;
+ assert(hasScroll());
+ if (loc < 0 || len < 0 || loc + len > length)
+ fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc);
+ rc = lseek(ion,loc,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::get.seek"); setScroll(FALSE); return; }
+ rc = read(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::get.read"); setScroll(FALSE); return; }
+}
+
+int HistoryBuffer::len()
+{
+ return length;
+}
+
+// History Scroll //////////////////////////////////////
+
+/*
+ The history scroll makes a Row(Row(Cell)) from
+ two history buffers. The index buffer contains
+ start of line positions which refere to the cells
+ buffer.
+
+ Note that index[0] addresses the second line
+ (line #1), while the first line (line #0) starts
+ at 0 in cells.
+*/
+
+HistoryScroll::HistoryScroll()
+{
+}
+
+HistoryScroll::~HistoryScroll()
+{
+}
+
+void HistoryScroll::setScroll(bool on)
+{
+ index.setScroll(on);
+ cells.setScroll(on);
+}
+
+bool HistoryScroll::hasScroll()
+{
+ return index.hasScroll() && cells.hasScroll();
+}
+
+int HistoryScroll::getLines()
+{
+ if (!hasScroll()) return 0;
+ return index.len() / sizeof(int);
+}
+
+int HistoryScroll::getLineLen(int lineno)
+{
+ if (!hasScroll()) return 0;
+ return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(ca);
+}
+
+int HistoryScroll::startOfLine(int lineno)
+{
+ if (lineno <= 0) return 0;
+ if (!hasScroll()) return 0;
+ if (lineno <= getLines())
+ { int res;
+ index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int));
+ return res;
+ }
+ return cells.len();
+}
+
+void HistoryScroll::getCells(int lineno, int colno, int count, ca res[])
+{
+ assert(hasScroll());
+ cells.get((unsigned char*)res,count*sizeof(ca),startOfLine(lineno)+colno*sizeof(ca));
+}
+
+void HistoryScroll::addCells(ca text[], int count)
+{
+ if (!hasScroll()) return;
+ cells.add((unsigned char*)text,count*sizeof(ca));
+}
+
+void HistoryScroll::addLine()
+{
+ if (!hasScroll()) return;
+ int locn = cells.len();
+ index.add((unsigned char*)&locn,sizeof(int));
+}
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 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [TEHistory.H] History Buffer */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
+/* */
+/* This file is part of Konsole - an X terminal for KDE */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Ported Konsole to Qt/Embedded */
+/* */
+/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+#ifndef TEHISTORY_H
+#define TEHISTORY_H
+
+#include "TECommon.h"
+
+/*
+ An extendable tmpfile(1) based buffer.
+*/
+class HistoryBuffer
+{
+public:
+ HistoryBuffer();
+ ~HistoryBuffer();
+
+public:
+ void setScroll(bool on);
+ bool hasScroll();
+
+public:
+ void add(const unsigned char* bytes, int len);
+ void get(unsigned char* bytes, int len, int loc);
+ int len();
+
+private:
+ int ion;
+ int length;
+};
+
+class HistoryScroll
+{
+public:
+ HistoryScroll();
+ ~HistoryScroll();
+
+public:
+ void setScroll(bool on);
+ bool hasScroll();
+
+public: // access to history
+ int getLines();
+ int getLineLen(int lineno);
+ void getCells(int lineno, int colno, int count, ca res[]);
+
+public: // backward compatibility (obsolete)
+ ca getCell(int lineno, int colno) { ca res; getCells(lineno,colno,1,&res); return res; }
+
+public: // adding lines.
+ void addCells(ca a[], int count);
+ void addLine();
+
+private:
+ int startOfLine(int lineno);
+ HistoryBuffer index; // lines Row(int)
+ HistoryBuffer cells; // text Row(ca)
+};
+
+#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 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [TEScreen.C] Screen Data Type */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
+/* */
+/* This file is part of Konsole - an X terminal for KDE */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Ported Konsole to Qt/Embedded */
+/* */
+/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+/*! \file
+*/
+
+/*! \class TEScreen
+
+ \brief The image manipulated by the emulation.
+
+ This class implements the operations of the terminal emulation framework.
+ It is a complete passive device, driven by the emulation decoder
+ (TEmuVT102). By this it forms in fact an ADT, that defines operations
+ on a rectangular image.
+
+ It does neither know how to display its image nor about escape sequences.
+ It is further independent of the underlying toolkit. By this, one can even
+ use this module for an ordinary text surface.
+
+ Since the operations are called by a specific emulation decoder, one may
+ collect their different operations here.
+
+ The state manipulated by the operations is mainly kept in `image', though
+ it is a little more complex bejond this. See the header file of the class.
+
+ \sa TEWidget \sa VT102Emulation
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+// #include <kdebug.h>
+
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "TEScreen.h"
+
+#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
+
+//FIXME: this is emulation specific. Use FALSE for xterm, TRUE for ANSI.
+//FIXME: see if we can get this from terminfo.
+#define BS_CLEARS FALSE
+
+#define loc(X,Y) ((Y)*columns+(X))
+
+/*! creates a `TEScreen' of `lines' lines and `columns' columns.
+*/
+
+TEScreen::TEScreen(int lines, int columns)
+{
+ this->lines = lines;
+ this->columns = columns;
+
+ image = (ca*) malloc(lines*columns*sizeof(ca));
+ tabstops = NULL; initTabStops();
+
+ histCursor = 0;
+
+ clearSelection();
+ reset();
+}
+
+/*! Destructor
+*/
+
+TEScreen::~TEScreen()
+{
+ free(image);
+ if (tabstops) free(tabstops);
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Normalized Screen Operations */
+/* */
+/* ------------------------------------------------------------------------- */
+
+// Cursor Setting --------------------------------------------------------------
+
+/*! \section Cursor
+
+ The `cursor' is a location within the screen that is implicitely used in
+ many operations. The operations within this section allow to manipulate
+ the cursor explicitly and to obtain it's value.
+
+ The position of the cursor is guarantied to be between (including) 0 and
+ `columns-1' and `lines-1'.
+*/
+
+/*!
+ Move the cursor up.
+
+ The cursor will not be moved beyond the top margin.
+*/
+
+void TEScreen::cursorUp(int n)
+//=CUU
+{
+ if (n == 0) n = 1; // Default
+ int stop = cuY < tmargin ? 0 : tmargin;
+ cuX = QMIN(columns-1,cuX); // nowrap!
+ cuY = QMAX(stop,cuY-n);
+}
+
+/*!
+ Move the cursor down.
+
+ The cursor will not be moved beyond the bottom margin.
+*/
+
+void TEScreen::cursorDown(int n)
+//=CUD
+{
+ if (n == 0) n = 1; // Default
+ int stop = cuY > bmargin ? lines-1 : bmargin;
+ cuX = QMIN(columns-1,cuX); // nowrap!
+ cuY = QMIN(stop,cuY+n);
+}
+
+/*!
+ Move the cursor left.
+
+ The cursor will not move beyond the first column.
+*/
+
+void TEScreen::cursorLeft(int n)
+//=CUB
+{
+ if (n == 0) n = 1; // Default
+ cuX = QMIN(columns-1,cuX); // nowrap!
+ cuX = QMAX(0,cuX-n);
+}
+
+/*!
+ Move the cursor left.
+
+ The cursor will not move beyond the rightmost column.
+*/
+
+void TEScreen::cursorRight(int n)
+//=CUF
+{
+ if (n == 0) n = 1; // Default
+ cuX = QMIN(columns-1,cuX+n);
+}
+
+/*!
+ Set top and bottom margin.
+*/
+
+void TEScreen::setMargins(int top, int bot)
+//=STBM
+{
+ if (top == 0) top = 1; // Default
+ if (bot == 0) bot = lines; // Default
+ top = top - 1; // Adjust to internal lineno
+ bot = bot - 1; // Adjust to internal lineno
+ if ( !( 0 <= top && top < bot && bot < lines ) )
+ { fprintf(stderr,"%s(%d) : setRegion(%d,%d) : bad range.\n",
+ __FILE__,__LINE__,top,bot);
+ return; // Default error action: ignore
+ }
+ tmargin = top;
+ bmargin = bot;
+ cuX = 0;
+ cuY = getMode(MODE_Origin) ? top : 0;
+}
+
+/*!
+ Move the cursor down one line.
+
+ If cursor is on bottom margin, the region between the
+ actual top and bottom margin is scrolled up instead.
+*/
+
+void TEScreen::index()
+//=IND
+{
+ if (cuY == bmargin)
+ {
+ if (tmargin == 0 && bmargin == lines-1) addHistLine(); // hist.history
+ scrollUp(tmargin,1);
+ }
+ else if (cuY < lines-1)
+ cuY += 1;
+}
+
+/*!
+ Move the cursor up one line.
+
+ If cursor is on the top margin, the region between the
+ actual top and bottom margin is scrolled down instead.
+*/
+
+void TEScreen::reverseIndex()
+//=RI
+{
+ if (cuY == tmargin)
+ scrollDown(tmargin,1);
+ else if (cuY > 0)
+ cuY -= 1;
+}
+
+/*!
+ Move the cursor to the begin of the next line.
+
+ If cursor is on bottom margin, the region between the
+ actual top and bottom margin is scrolled up.
+*/
+
+void TEScreen::NextLine()
+//=NEL
+{
+ Return(); index();
+}
+
+// Line Editing ----------------------------------------------------------------
+
+/*! \section inserting / deleting characters
+*/
+
+/*! erase `n' characters starting from (including) the cursor position.
+
+ The line is filled in from the right with spaces.
+*/
+
+void TEScreen::eraseChars(int n)
+{
+ if (n == 0) n = 1; // Default
+ int p = QMAX(0,QMIN(cuX+n-1,columns-1));
+ clearImage(loc(cuX,cuY),loc(p,cuY),' ');
+}
+
+/*! delete `n' characters starting from (including) the cursor position.
+
+ The line is filled in from the right with spaces.
+*/
+
+void TEScreen::deleteChars(int n)
+{
+ if (n == 0) n = 1; // Default
+ int p = QMAX(0,QMIN(cuX+n,columns-1));
+ moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY));
+ clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' ');
+}
+
+/*! insert `n' spaces at the cursor position.
+
+ The cursor is not moved by the operation.
+*/
+
+void TEScreen::insertChars(int n)
+{
+ if (n == 0) n = 1; // Default
+ int p = QMAX(0,QMIN(columns-1-n,columns-1));
+ int q = QMAX(0,QMIN(cuX+n,columns-1));
+ moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY));
+ clearImage(loc(cuX,cuY),loc(q-1,cuY),' ');
+}
+
+/*! delete `n' lines starting from (including) the cursor position.
+
+ The cursor is not moved by the operation.
+*/
+
+void TEScreen::deleteLines(int n)
+{
+ if (n == 0) n = 1; // Default
+ scrollUp(cuY,n);
+}
+
+/*! insert `n' lines at the cursor position.
+
+ The cursor is not moved by the operation.
+*/
+
+void TEScreen::insertLines(int n)
+{
+ if (n == 0) n = 1; // Default
+ scrollDown(cuY,n);
+}
+
+// Mode Operations -----------------------------------------------------------
+
+/*! Set a specific mode. */
+
+void TEScreen::setMode(int m)
+{
+ currParm.mode[m] = TRUE;
+ switch(m)
+ {
+ case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home
+ }
+}
+
+/*! Reset a specific mode. */
+
+void TEScreen::resetMode(int m)
+{
+ currParm.mode[m] = FALSE;
+ switch(m)
+ {
+ case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home
+ }
+}
+
+/*! Save a specific mode. */
+
+void TEScreen::saveMode(int m)
+{
+ saveParm.mode[m] = currParm.mode[m];
+}
+
+/*! Restore a specific mode. */
+
+void TEScreen::restoreMode(int m)
+{
+ currParm.mode[m] = saveParm.mode[m];
+}
+
+//NOTE: this is a helper function
+/*! Return the setting a specific mode. */
+BOOL TEScreen::getMode(int m)
+{
+ return currParm.mode[m];
+}
+
+/*! Save the cursor position and the rendition attribute settings. */
+
+void TEScreen::saveCursor()
+{
+ sa_cuX = cuX;
+ sa_cuY = cuY;
+ sa_cu_re = cu_re;
+ sa_cu_fg = cu_fg;
+ sa_cu_bg = cu_bg;
+}
+
+/*! Restore the cursor position and the rendition attribute settings. */
+
+void TEScreen::restoreCursor()
+{
+ cuX = QMIN(sa_cuX,columns-1);
+ cuY = QMIN(sa_cuY,lines-1);
+ cu_re = sa_cu_re;
+ cu_fg = sa_cu_fg;
+ cu_bg = sa_cu_bg;
+ effectiveRendition();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Screen Operations */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*! Assing a new size to the screen.
+
+ The topmost left position is maintained, while lower lines
+ or right hand side columns might be removed or filled with
+ spaces to fit the new size.
+
+ The region setting is reset to the whole screen and the
+ tab positions reinitialized.
+*/
+
+void TEScreen::resizeImage(int new_lines, int new_columns)
+{
+
+ if (cuY > new_lines-1)
+ { // attempt to preserve focus and lines
+ bmargin = lines-1; //FIXME: margin lost
+ for (int i = 0; i < cuY-(new_lines-1); i++)
+ {
+ addHistLine(); scrollUp(0,1);
+ }
+ }
+
+ // make new image
+ ca* newimg = (ca*)malloc(new_lines*new_columns*sizeof(ca));
+
+ clearSelection();
+
+ // clear new image
+ for (int y = 0; y < new_lines; y++)
+ for (int x = 0; x < new_columns; x++)
+ {
+ newimg[y*new_columns+x].c = ' ';
+ newimg[y*new_columns+x].f = DEFAULT_FORE_COLOR;
+ newimg[y*new_columns+x].b = DEFAULT_BACK_COLOR;
+ newimg[y*new_columns+x].r = DEFAULT_RENDITION;
+ }
+ int cpy_lines = QMIN(new_lines, lines);
+ int cpy_columns = QMIN(new_columns,columns);
+ // copy to new image
+ for (int y = 0; y < cpy_lines; y++)
+ for (int x = 0; x < cpy_columns; x++)
+ {
+ newimg[y*new_columns+x].c = image[loc(x,y)].c;
+ newimg[y*new_columns+x].f = image[loc(x,y)].f;
+ newimg[y*new_columns+x].b = image[loc(x,y)].b;
+ newimg[y*new_columns+x].r = image[loc(x,y)].r;
+ }
+ free(image);
+ image = newimg;
+ lines = new_lines;
+ columns = new_columns;
+ cuX = QMIN(cuX,columns-1);
+ cuY = QMIN(cuY,lines-1);
+
+ // FIXME: try to keep values, evtl.
+ tmargin=0;
+ bmargin=lines-1;
+ initTabStops();
+ clearSelection();
+}
+
+/*
+ Clarifying rendition here and in TEWidget.
+
+ currently, TEWidget's color table is
+ 0 1 2 .. 9 10 .. 17
+ dft_fg, dft_bg, dim 0..7, intensive 0..7
+
+ cu_fg, cu_bg contain values 0..8;
+ - 0 = default color
+ - 1..8 = ansi specified color
+
+ re_fg, re_bg contain values 0..17
+ due to the TEWidget's color table
+
+ rendition attributes are
+
+ attr widget screen
+ -------------- ------ ------
+ RE_UNDERLINE XX XX affects foreground only
+ RE_BLINK XX XX affects foreground only
+ RE_BOLD XX XX affects foreground only
+ RE_REVERSE -- XX
+ RE_TRANSPARENT XX -- affects background only
+ RE_INTENSIVE XX -- affects foreground only
+
+ Note that RE_BOLD is used in both widget
+ and screen rendition. Since xterm/vt102
+ is to poor to distinguish between bold
+ (which is a font attribute) and intensive
+ (which is a color attribute), we translate
+ this and RE_BOLD in falls eventually appart
+ into RE_BOLD and RE_INTENSIVE.
+*/
+
+void TEScreen::reverseRendition(ca* p)
+{ UINT8 f = p->f; UINT8 b = p->b;
+ p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT;
+}
+
+void TEScreen::effectiveRendition()
+// calculate rendition
+{
+ ef_re = cu_re & (RE_UNDERLINE | RE_BLINK);
+ if (cu_re & RE_REVERSE)
+ {
+ ef_fg = cu_bg;
+ ef_bg = cu_fg;
+ }
+ else
+ {
+ ef_fg = cu_fg;
+ ef_bg = cu_bg;
+ }
+ if (cu_re & RE_BOLD)
+ {
+ if (ef_fg < BASE_COLORS)
+ ef_fg += BASE_COLORS;
+ else
+ ef_fg -= BASE_COLORS;
+ }
+}
+
+/*!
+ returns the image.
+
+ Get the size of the image by \sa getLines and \sa getColumns.
+
+ NOTE that the image returned by this function must later be
+ freed.
+
+*/
+
+ca* TEScreen::getCookedImage()
+{ int x,y;
+ ca* merged = (ca*)malloc(lines*columns*sizeof(ca));
+ ca dft(' ',DEFAULT_FORE_COLOR,DEFAULT_BACK_COLOR,DEFAULT_RENDITION);
+
+ for (y = 0; (y < lines) && (y < (hist.getLines()-histCursor)); y++)
+ {
+ int len = QMIN(columns,hist.getLineLen(y+histCursor));
+ int yp = y*columns;
+ int yq = (y+histCursor)*columns;
+
+ hist.getCells(y+histCursor,0,len,merged+yp);
+ for (x = len; x < columns; x++) merged[yp+x] = dft;
+ for (x = 0; x < columns; x++)
+ { int p=x + yp; int q=x + yq;
+ if ( ( q >= sel_TL ) && ( q <= sel_BR ) )
+ reverseRendition(&merged[p]); // for selection
+ }
+ }
+ if (lines >= hist.getLines()-histCursor)
+ {
+ for (y = (hist.getLines()-histCursor); y < lines ; y++)
+ {
+ int yp = y*columns;
+ int yq = (y+histCursor)*columns;
+ int yr = (y-hist.getLines()+histCursor)*columns;
+ for (x = 0; x < columns; x++)
+ { int p = x + yp; int q = x + yq; int r = x + yr;
+ merged[p] = image[r];
+ if ( q >= sel_TL && q <= sel_BR )
+ reverseRendition(&merged[p]); // for selection
+ }
+
+ }
+ }
+ // evtl. inverse display
+ if (getMode(MODE_Screen))
+ { int i,n = lines*columns;
+ for (i = 0; i < n; i++)
+ reverseRendition(&merged[i]); // for reverse display
+ }
+ if (getMode(MODE_Cursor) && (cuY+(hist.getLines()-histCursor) < lines)) // cursor visible
+ reverseRendition(&merged[loc(cuX,cuY+(hist.getLines()-histCursor))]);
+ return merged;
+}
+
+
+/*!
+*/
+
+void TEScreen::reset()
+{
+ setMode(MODE_Wrap ); saveMode(MODE_Wrap ); // wrap at end of margin
+ resetMode(MODE_Origin); saveMode(MODE_Origin); // position refere to [1,1]
+ resetMode(MODE_Insert); saveMode(MODE_Insert); // overstroke
+ setMode(MODE_Cursor); // cursor visible
+ resetMode(MODE_Screen); // screen not inverse
+ resetMode(MODE_NewLine);
+
+ tmargin=0;
+ bmargin=lines-1;
+
+ setDefaultRendition();
+ saveCursor();
+
+ clear();
+}
+
+/*! Clear the entire screen and home the cursor.
+*/
+
+void TEScreen::clear()
+{
+ clearEntireScreen();
+ home();
+}
+
+/*! Moves the cursor left one column.
+*/
+
+void TEScreen::BackSpace()
+{
+ cuX = QMAX(0,cuX-1);
+ if (BS_CLEARS) image[loc(cuX,cuY)].c = ' ';
+}
+
+/*!
+*/
+
+void TEScreen::Tabulate()
+{
+ // note that TAB is a format effector (does not write ' ');
+ cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1);
+}
+
+void TEScreen::clearTabStops()
+{
+ for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE;
+}
+
+void TEScreen::changeTabStop(bool set)
+{
+ if (cuX >= columns) return;
+ tabstops[cuX] = set;
+}
+
+void TEScreen::initTabStops()
+{
+ if (tabstops) free(tabstops);
+ tabstops = (bool*)malloc(columns*sizeof(bool));
+ // Arrg! The 1st tabstop has to be one longer than the other.
+ // i.e. the kids start counting from 0 instead of 1.
+ // Other programs might behave correctly. Be aware.
+ for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0);
+}
+
+/*!
+ This behaves either as IND (Screen::Index) or as NEL (Screen::NextLine)
+ depending on the NewLine Mode (LNM). This mode also
+ affects the key sequence returned for newline ([CR]LF).
+*/
+
+void TEScreen::NewLine()
+{
+ if (getMode(MODE_NewLine)) Return();
+ index();
+}
+
+/*! put `c' literally onto the screen at the current cursor position.
+
+ VT100 uses the convention to produce an automatic newline (am)
+ with the *first* character that would fall onto the next line (xenl).
+*/
+
+void TEScreen::checkSelection(int from, int to)
+{
+ if (sel_begin == -1) return;
+ int scr_TL = loc(0, hist.getLines());
+ //Clear entire selection if it overlaps region [from, to]
+ if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) )
+ {
+ clearSelection();
+ }
+}
+
+void TEScreen::ShowCharacter(unsigned short c)
+{
+ // Note that VT100 does wrapping BEFORE putting the character.
+ // This has impact on the assumption of valid cursor positions.
+ // We indicate the fact that a newline has to be triggered by
+ // putting the cursor one right to the last column of the screen.
+
+ if (cuX >= columns)
+ {
+ if (getMode(MODE_Wrap)) NextLine(); else cuX = columns-1;
+ }
+
+ if (getMode(MODE_Insert)) insertChars(1);
+
+ int i = loc(cuX,cuY);
+
+ checkSelection(i, i); // check if selection is still valid.
+
+ image[i].c = c;
+ image[i].f = ef_fg;
+ image[i].b = ef_bg;
+ image[i].r = ef_re;
+
+ cuX += 1;
+}
+
+// Region commands -------------------------------------------------------------
+
+
+/*! scroll up `n' lines within current region.
+ The `n' new lines are cleared.
+ \sa setRegion \sa scrollDown
+*/
+
+void TEScreen::scrollUp(int from, int n)
+{
+ if (n <= 0 || from + n > bmargin) return;
+ //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
+ moveImage(loc(0,from),loc(0,from+n),loc(columns-1,bmargin));
+ clearImage(loc(0,bmargin-n+1),loc(columns-1,bmargin),' ');
+}
+
+/*! scroll down `n' lines within current region.
+ The `n' new lines are cleared.
+ \sa setRegion \sa scrollUp
+*/
+
+void TEScreen::scrollDown(int from, int n)
+{
+//FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
+ if (n <= 0) return;
+ if (from > bmargin) return;
+ if (from + n > bmargin) n = bmargin - from;
+ moveImage(loc(0,from+n),loc(0,from),loc(columns-1,bmargin-n));
+ clearImage(loc(0,from),loc(columns-1,from+n-1),' ');
+}
+
+/*! position the cursor to a specific line and column. */
+void TEScreen::setCursorYX(int y, int x)
+{
+ setCursorY(y); setCursorX(x);
+}
+
+/*! Set the cursor to x-th line. */
+
+void TEScreen::setCursorX(int x)
+{
+ if (x == 0) x = 1; // Default
+ x -= 1; // Adjust
+ cuX = QMAX(0,QMIN(columns-1, x));
+}
+
+/*! Set the cursor to y-th line. */
+
+void TEScreen::setCursorY(int y)
+{
+ if (y == 0) y = 1; // Default
+ y -= 1; // Adjust
+ cuY = QMAX(0,QMIN(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) ));
+}
+
+/*! set cursor to the `left upper' corner of the screen (1,1).
+*/
+
+void TEScreen::home()
+{
+ cuX = 0;
+ cuY = 0;
+}
+
+/*! set cursor to the begin of the current line.
+*/
+
+void TEScreen::Return()
+{
+ cuX = 0;
+}
+
+/*! returns the current cursor columns.
+*/
+
+int TEScreen::getCursorX()
+{
+ return cuX;
+}
+
+/*! returns the current cursor line.
+*/
+
+int TEScreen::getCursorY()
+{
+ return cuY;
+}
+
+// Erasing ---------------------------------------------------------------------
+
+/*! \section Erasing
+
+ This group of operations erase parts of the screen contents by filling
+ it with spaces colored due to the current rendition settings.
+
+ Althought the cursor position is involved in most of these operations,
+ it is never modified by them.
+*/
+
+/*! fill screen between (including) `loca' and `loce' with spaces.
+
+ This is an internal helper functions. The parameter types are internal
+ addresses of within the screen image and make use of the way how the
+ screen matrix is mapped to the image vector.
+*/
+
+void TEScreen::clearImage(int loca, int loce, char c)
+{ int i;
+ int scr_TL=loc(0,hist.getLines());
+ //FIXME: check positions
+
+ //Clear entire selection if it overlaps region to be moved...
+ if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) )
+ {
+ clearSelection();
+ }
+ for (i = loca; i <= loce; i++)
+ {
+ image[i].c = c;
+ image[i].f = ef_fg; //DEFAULT_FORE_COLOR; //FIXME: xterm and linux/ansi
+ image[i].b = ef_bg; //DEFAULT_BACK_COLOR; // many have different
+ image[i].r = ef_re; //DEFAULT_RENDITION; // ideas here.
+ }
+}
+
+/*! move image between (including) `loca' and `loce' to 'dst'.
+
+ This is an internal helper functions. The parameter types are internal
+ addresses of within the screen image and make use of the way how the
+ screen matrix is mapped to the image vector.
+*/
+
+void TEScreen::moveImage(int dst, int loca, int loce)
+{
+//FIXME: check positions
+ if (loce < loca) {
+ // kdDebug() << "WARNING!!! call to TEScreen:moveImage with loce < loca!" << endl;
+ return;
+ }
+ memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(ca));
+}
+
+/*! clear from (including) current cursor position to end of screen.
+*/
+
+void TEScreen::clearToEndOfScreen()
+{
+ clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
+}
+
+/*! clear from begin of screen to (including) current cursor position.
+*/
+
+void TEScreen::clearToBeginOfScreen()
+{
+ clearImage(loc(0,0),loc(cuX,cuY),' ');
+}
+
+/*! clear the entire screen.
+*/
+
+void TEScreen::clearEntireScreen()
+{
+ clearImage(loc(0,0),loc(columns-1,lines-1),' ');
+}
+
+/*! fill screen with 'E'
+ This is to aid screen alignment
+*/
+
+void TEScreen::helpAlign()
+{
+ clearImage(loc(0,0),loc(columns-1,lines-1),'E');
+}
+
+/*! clear from (including) current cursor position to end of current cursor line.
+*/
+
+void TEScreen::clearToEndOfLine()
+{
+ clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
+}
+
+/*! clear from begin of current cursor line to (including) current cursor position.
+*/
+
+void TEScreen::clearToBeginOfLine()
+{
+ clearImage(loc(0,cuY),loc(cuX,cuY),' ');
+}
+
+/*! clears entire current cursor line
+*/
+
+void TEScreen::clearEntireLine()
+{
+ clearImage(loc(0,cuY),loc(columns-1,cuY),' ');
+}
+
+// Rendition ------------------------------------------------------------------
+
+/*!
+ set rendition mode
+*/
+
+void TEScreen::setRendition(int re)
+{
+ cu_re |= re;
+ effectiveRendition();
+}
+
+/*!
+ reset rendition mode
+*/
+
+void TEScreen::resetRendition(int re)
+{
+ cu_re &= ~re;
+ effectiveRendition();
+}
+
+/*!
+*/
+
+void TEScreen::setDefaultRendition()
+{
+ setForeColorToDefault();
+ setBackColorToDefault();
+ cu_re = DEFAULT_RENDITION;
+ effectiveRendition();
+}
+
+/*!
+*/
+
+void TEScreen::setForeColor(int fgcolor)
+{
+ cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2);
+ effectiveRendition();
+}
+
+/*!
+*/
+
+void TEScreen::setBackColor(int bgcolor)
+{
+ cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2);
+ effectiveRendition();
+}
+
+/*!
+*/
+
+void TEScreen::setBackColorToDefault()
+{
+ cu_bg = DEFAULT_BACK_COLOR;
+ effectiveRendition();
+}
+
+/*!
+*/
+
+void TEScreen::setForeColorToDefault()
+{
+ cu_fg = DEFAULT_FORE_COLOR;
+ effectiveRendition();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Marking & Selection */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEScreen::clearSelection()
+{
+ sel_BR = -1;
+ sel_TL = -1;
+ sel_begin = -1;
+}
+
+void TEScreen::setSelBeginXY(const int x, const int y)
+{
+ sel_begin = loc(x,y+histCursor) ;
+ sel_BR = sel_begin;
+ sel_TL = sel_begin;
+}
+
+void TEScreen::setSelExtentXY(const int x, const int y)
+{
+ if (sel_begin == -1) return;
+ int l = loc(x,y + histCursor);
+
+ if (l < sel_begin)
+ {
+ sel_TL = l;
+ sel_BR = sel_begin;
+ }
+ else
+ {
+ /* FIXME, HACK to correct for x too far to the right... */
+ if (( x == columns )|| (x == 0)) l--;
+
+ sel_TL = sel_begin;
+ sel_BR = l;
+ }
+}
+
+QString TEScreen::getSelText(const BOOL preserve_line_breaks)
+{
+ if (sel_begin == -1)
+ return QString::null; // Selection got clear while selecting.
+
+ int *m; // buffer to fill.
+ int s, d; // source index, dest. index.
+ int hist_BR = loc(0, hist.getLines());
+ int hY = sel_TL / columns;
+ int hX = sel_TL % columns;
+ int eol; // end of line
+
+ s = sel_TL; // tracks copy in source.
+
+ // allocate buffer for maximum
+ // possible size...
+ d = (sel_BR - sel_TL) / columns + 1;
+ m = new int[d * (columns + 1) + 2];
+ d = 0;
+
+ while (s <= sel_BR)
+ {
+ if (s < hist_BR)
+ { // get lines from hist.history
+ // buffer.
+ eol = hist.getLineLen(hY);
+
+ if ((hY == (sel_BR / columns)) &&
+ (eol >= (sel_BR % columns)))
+ {
+ eol = sel_BR % columns + 1;
+ }
+
+ while (hX < eol)
+ {
+ m[d++] = hist.getCell(hY, hX++).c;
+ s++;
+ }
+
+ if (s <= sel_BR)
+ {
+ // The line break handling
+ // It's different from the screen
+ // image case!
+ if (eol % columns == 0)
+ {
+ // That's either a completely filled
+ // line or an empty line
+ if (eol == 0)
+ {
+ m[d++] = '\n';
+ }
+ else
+ {
+ // We have a full line.
+ // FIXME: How can we handle newlines
+ // at this position?!
+ }
+ }
+ else if ((eol + 1) % columns == 0)
+ {
+ // FIXME: We don't know if this was a
+ // space at the last position or a
+ // short line!!
+ m[d++] = ' ';
+ }
+ else
+ {
+ // We have a short line here. Put a
+ // newline or a space into the
+ // buffer.
+ m[d++] = preserve_line_breaks ? '\n' : ' ';
+ }
+ }
+
+ hY++;
+ hX = 0;
+ s = hY * columns;
+ }
+ else
+ { // or from screen image.
+ eol = (s / columns + 1) * columns - 1;
+
+ if (eol < sel_BR)
+ {
+ while ((eol > s) &&
+ isspace(image[eol - hist_BR].c))
+ {
+ eol--;
+ }
+ }
+ else
+ {
+ eol = sel_BR;
+ }
+
+ while (s <= eol)
+ {
+ m[d++] = image[s++ - hist_BR].c;
+ }
+
+ if (eol < sel_BR)
+ {
+ // eol processing see below ...
+ if ((eol + 1) % columns == 0)
+ {
+ if (image[eol - hist_BR].c == ' ')
+ {
+ m[d++] = ' ';
+ }
+ }
+ else
+ {
+ m[d++] = ((preserve_line_breaks ||
+ ((eol % columns) == 0)) ?
+ '\n' : ' ');
+ }
+ }
+
+ s = (eol / columns + 1) * columns;
+ }
+ }
+
+ QChar* qc = new QChar[d];
+
+ for (int i = 0; i < d; i++)
+ {
+ qc[i] = m[i];
+ }
+
+ QString res(qc, d);
+
+ delete m;
+ delete qc;
+
+ return res;
+}
+/* above ... end of line processing for selection -- psilva
+cases:
+
+1) (eol+1)%columns == 0 --> the whole line is filled.
+ If the last char is a space, insert (preserve) space. otherwise
+ leave the text alone, so that words that are broken by linewrap
+ are preserved.
+
+FIXME:
+ * this suppresses \n for command output that is
+ sized to the exact column width of the screen.
+
+2) eol%columns == 0 --> blank line.
+ insert a \n unconditionally.
+ Do it either you would because you are in preserve_line_break mode,
+ or because it's an ASCII paragraph delimiter, so even when
+ not preserving line_breaks, you want to preserve paragraph breaks.
+
+3) else --> partially filled line
+ insert a \n in preserve line break mode, else a space
+ The space prevents concatenation of the last word of one
+ line with the first of the next.
+
+*/
+
+void TEScreen::addHistLine()
+{
+ assert(hasScroll() || histCursor == 0);
+
+ // add to hist buffer
+ // we have to take care about scrolling, too...
+
+ if (hasScroll())
+ { ca dft;
+
+ int end = columns-1;
+ while (end >= 0 && image[end] == dft)
+ end -= 1;
+
+ hist.addCells(image,end+1);
+ hist.addLine();
+
+ // adjust history cursor
+ histCursor += (hist.getLines()-1 == histCursor);
+ }
+
+ if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround
+}
+
+void TEScreen::setHistCursor(int cursor)
+{
+ histCursor = cursor; //FIXME:rangecheck
+}
+
+int TEScreen::getHistCursor()
+{
+ return histCursor;
+}
+
+int TEScreen::getHistLines()
+{
+ return hist.getLines();
+}
+
+void TEScreen::setScroll(bool on)
+{
+ histCursor = 0;
+ clearSelection();
+ hist.setScroll(on);
+}
+
+bool TEScreen::hasScroll()
+{
+ return hist.hasScroll();
+}
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 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [te_screen.h] Screen Data Type */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
+/* */
+/* This file is part of Konsole - an X terminal for KDE */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Ported Konsole to Qt/Embedded */
+/* */
+/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+#ifndef TESCREEN_H
+#define TESCREEN_H
+
+/*! \file
+*/
+
+#include "TECommon.h"
+#include "TEHistory.h"
+
+#define MODE_Origin 0
+#define MODE_Wrap 1
+#define MODE_Insert 2
+#define MODE_Screen 3
+#define MODE_Cursor 4
+#define MODE_NewLine 5
+#define MODES_SCREEN 6
+
+/*!
+*/
+struct ScreenParm
+{
+ int mode[MODES_SCREEN];
+};
+
+
+class TEScreen
+{
+public:
+ TEScreen(int lines, int columns);
+ ~TEScreen();
+
+public: // these are all `Screen' operations
+ //
+ // VT100/2 Operations ------------------
+ //
+ // Cursor Movement
+ //
+ void cursorUp (int n);
+ void cursorDown (int n);
+ void cursorLeft (int n);
+ void cursorRight (int n);
+ void setCursorY (int y);
+ void setCursorX (int x);
+ void setCursorYX (int y, int x);
+ void setMargins (int t, int b);
+ //
+ // Cursor Movement with Scrolling
+ //
+ void NewLine ();
+ void NextLine ();
+ void index ();
+ void reverseIndex();
+ //
+ void Return ();
+ void BackSpace ();
+ void Tabulate ();
+ //
+ // Editing
+ //
+ void eraseChars (int n);
+ void deleteChars (int n);
+ void insertChars (int n);
+ void deleteLines (int n);
+ void insertLines (int n);
+ //
+ // -------------------------------------
+ //
+ void clearTabStops();
+ void changeTabStop(bool set);
+ //
+ void resetMode (int n);
+ void setMode (int n);
+ void saveMode (int n);
+ void restoreMode (int n);
+ //
+ void saveCursor ();
+ void restoreCursor();
+ //
+ // -------------------------------------
+ //
+ void clearEntireScreen();
+ void clearToEndOfScreen();
+ void clearToBeginOfScreen();
+ //
+ void clearEntireLine();
+ void clearToEndOfLine();
+ void clearToBeginOfLine();
+ //
+ void helpAlign ();
+ //
+ // -------------------------------------
+ //
+ void setRendition (int rendition);
+ void resetRendition(int rendition);
+ void setForeColor (int fgcolor);
+ void setBackColor (int bgcolor);
+ //
+ void setDefaultRendition();
+ void setForeColorToDefault();
+ void setBackColorToDefault();
+ //
+ // -------------------------------------
+ //
+ BOOL getMode (int n);
+ //
+ // only for report cursor position
+ //
+ int getCursorX();
+ int getCursorY();
+ //
+ // -------------------------------------
+ //
+ void clear();
+ void home();
+ void reset();
+ //
+ void ShowCharacter(unsigned short c);
+ //
+ void resizeImage(int new_lines, int new_columns);
+ //
+ ca* getCookedImage();
+
+ /*! return the number of lines. */
+ int getLines() { return lines; }
+ /*! return the number of columns. */
+ int getColumns() { return columns; }
+
+ /*! set the position of the history cursor. */
+ void setHistCursor(int cursor);
+ /*! return the position of the history cursor. */
+ int getHistCursor();
+
+ int getHistLines ();
+ void setScroll(bool on);
+ bool hasScroll();
+
+ //
+ // Selection
+ //
+ void setSelBeginXY(const int x, const int y);
+ void setSelExtentXY(const int x, const int y);
+ void clearSelection();
+ QString getSelText(const BOOL preserve_line_breaks);
+
+ void checkSelection(int from, int to);
+
+private: // helper
+
+ void clearImage(int loca, int loce, char c);
+ void moveImage(int dst, int loca, int loce);
+
+ void scrollUp(int from, int i);
+ void scrollDown(int from, int i);
+
+ void addHistLine();
+
+ void initTabStops();
+
+ void effectiveRendition();
+ void reverseRendition(ca* p);
+
+private:
+
+ /*
+ The state of the screen is more complex as one would
+ expect first. The screem does really do part of the
+ emulation providing state informations in form of modes,
+ margins, tabulators, cursor etc.
+
+ Even more unexpected are variables to save and restore
+ parts of the state.
+ */
+
+ // screen image ----------------
+
+ int lines;
+ int columns;
+ ca *image; // [lines][columns]
+
+ // history buffer ---------------
+
+ int histCursor; // display position relative to start of the history buffer
+ HistoryScroll hist;
+
+ // cursor location
+
+ int cuX;
+ int cuY;
+
+ // cursor color and rendition info
+
+ UINT8 cu_fg; // foreground
+ UINT8 cu_bg; // background
+ UINT8 cu_re; // rendition
+
+ // margins ----------------
+
+ int tmargin; // top margin
+ int bmargin; // bottom margin
+
+ // states ----------------
+
+ ScreenParm currParm;
+
+ // ----------------------------
+
+ bool* tabstops;
+
+ // selection -------------------
+
+ int sel_begin; // The first location selected.
+ int sel_TL; // TopLeft Location.
+ int sel_BR; // Bottom Right Location.
+
+ // effective colors and rendition ------------
+
+ UINT8 ef_fg; // These are derived from
+ UINT8 ef_bg; // the cu_* variables above
+ UINT8 ef_re; // to speed up operation
+
+ //
+ // save cursor, rendition & states ------------
+ //
+
+ // cursor location
+
+ int sa_cuX;
+ int sa_cuY;
+
+ // rendition info
+
+ UINT8 sa_cu_re;
+ UINT8 sa_cu_fg;
+ UINT8 sa_cu_bg;
+
+ // modes
+
+ ScreenParm saveParm;
+};
+
+#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 @@
+/* ------------------------------------------------------------------------ */
+/* */
+/* [TEWidget.C] Terminal Emulation Widget */
+/* */
+/* ------------------------------------------------------------------------ */
+/* */
+/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
+/* */
+/* This file is part of Konsole - an X terminal for KDE */
+/* */
+/* ------------------------------------------------------------------------ */
+/* */
+/* Ported Konsole to Qt/Embedded */
+/* */
+/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
+/* */
+/* -------------------------------------------------------------------------- */
+/*! \class TEWidget
+
+ \brief Visible screen contents
+
+ This class is responsible to map the `image' of a terminal emulation to the
+ display. All the dependency of the emulation to a specific GUI or toolkit is
+ localized here. Further, this widget has no knowledge about being part of an
+ emulation, it simply work within the terminal emulation framework by exposing
+ size and key events and by being ordered to show a new image.
+
+ <ul>
+ <li> The internal image has the size of the widget (evtl. rounded up)
+ <li> The external image used in setImage can have any size.
+ <li> (internally) the external image is simply copied to the internal
+ when a setImage happens. During a resizeEvent no painting is done
+ a paintEvent is expected to follow anyway.
+ </ul>
+
+ \sa TEScreen \sa Emulation
+*/
+
+/* FIXME:
+ - 'image' may also be used uninitialized (it isn't in fact) in resizeEvent
+ - 'font_a' not used in mouse events
+ - add destructor
+*/
+
+/* TODO
+ - evtl. be sensitive to `paletteChange' while using default colors.
+ - set different 'rounding' styles? I.e. have a mode to show clipped chars?
+*/
+
+// #include "config.h"
+#include "TEWidget.h"
+#include "session.h"
+#include <qpe/config.h>
+
+#include <qapplication.h>
+#include <qcursor.h>
+#include <qregexp.h>
+#include <qpainter.h>
+#include <qclipboard.h>
+#include <qstyle.h>
+#include <qfile.h>
+#include <qdragobject.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include <assert.h>
+
+// #include "TEWidget.moc"
+//#include <kapp.h>
+//#include <kcursor.h>
+//#include <kurl.h>
+//#include <kdebug.h>
+//#include <klocale.h>
+
+#define HERE printf("%s(%d): %s\n",__FILE__,__LINE__,__FUNCTION__)
+#define HCNT(Name) // { static int cnt = 1; printf("%s(%d): %s %d\n",__FILE__,__LINE__,Name,cnt++); }
+
+#define loc(X,Y) ((Y)*columns+(X))
+
+//FIXME: the rim should normally be 1, 0 only when running in full screen mode.
+#define rimX 0 // left/right rim width
+#define rimY 0 // top/bottom rim high
+
+#define SCRWIDTH 16 // width of the scrollbar
+
+#define yMouseScroll 1
+// scroll increment used when dragging selection at top/bottom of window.
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Colors */
+/* */
+/* ------------------------------------------------------------------------- */
+
+//FIXME: the default color table is in session.C now.
+// We need a way to get rid of this one, here.
+static const ColorEntry base_color_table[TABLE_COLORS] =
+// The following are almost IBM standard color codes, with some slight
+// gamma correction for the dim colors to compensate for bright X screens.
+// It contains the 8 ansiterm/xterm colors in 2 intensities.
+{
+ // Fixme: could add faint colors here, also.
+ // normal
+ ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 1, 0 ), // Dfore, Dback
+ ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red
+ ColorEntry(QColor(0x18,0xB2,0x18), 0, 0 ), ColorEntry( QColor(0xB2,0x68,0x18), 0, 0 ), // Green, Yellow
+ ColorEntry(QColor(0x18,0x18,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), // Blue, Magenta
+ ColorEntry(QColor(0x18,0xB2,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 0, 0 ), // Cyan, White
+ // intensiv
+ ColorEntry(QColor(0x00,0x00,0x00), 0, 1 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 1, 0 ),
+ ColorEntry(QColor(0x68,0x68,0x68), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0x54), 0, 0 ),
+ ColorEntry(QColor(0x54,0xFF,0x54), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0x54), 0, 0 ),
+ ColorEntry(QColor(0x54,0x54,0xFF), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ),
+ ColorEntry(QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 )
+};
+
+/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb)
+
+ Code 0 1 2 3 4 5 6 7
+ ----------- ------- ------- ------- ------- ------- ------- ------- -------
+ ANSI (bgr) Black Red Green Yellow Blue Magenta Cyan White
+ IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White
+*/
+
+QColor TEWidget::getDefaultBackColor()
+{
+ return color_table[DEFAULT_BACK_COLOR].color;
+}
+
+const ColorEntry* TEWidget::getColorTable() const
+{
+ return color_table;
+}
+
+const ColorEntry* TEWidget::getdefaultColorTable() const
+{
+ return base_color_table;
+}
+
+
+const QPixmap *TEWidget::backgroundPixmap()
+{
+ static QPixmap *bg = new QPixmap("~/qpim/main/pics/faded_bg.xpm");
+ const QPixmap *pm = bg;
+ return pm;
+}
+
+void TEWidget::setColorTable(const ColorEntry table[])
+{
+ for (int i = 0; i < TABLE_COLORS; i++) color_table[i] = table[i];
+
+ const QPixmap* pm = backgroundPixmap();
+ if (!pm) setBackgroundColor(color_table[DEFAULT_BACK_COLOR].color);
+ update();
+}
+
+//FIXME: add backgroundPixmapChanged.
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Font */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*
+ The VT100 has 32 special graphical characters. The usual vt100 extended
+ xterm fonts have these at 0x00..0x1f.
+
+ QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals
+ come in here as proper unicode characters.
+
+ We treat non-iso10646 fonts as VT100 extended and do the requiered mapping
+ from unicode to 0x00..0x1f. The remaining translation is then left to the
+ QCodec.
+*/
+
+// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.
+
+unsigned short vt100_graphics[32] =
+{ // 0/8 1/9 2/10 3/11 4/12 5/13 6/14 7/15
+ 0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0,
+ 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,
+ 0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534,
+ 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7
+};
+
+static QChar vt100extended(QChar c)
+{
+ switch (c.unicode())
+ {
+ case 0x25c6 : return 1;
+ case 0x2592 : return 2;
+ case 0x2409 : return 3;
+ case 0x240c : return 4;
+ case 0x240d : return 5;
+ case 0x240a : return 6;
+ case 0x00b0 : return 7;
+ case 0x00b1 : return 8;
+ case 0x2424 : return 9;
+ case 0x240b : return 10;
+ case 0x2518 : return 11;
+ case 0x2510 : return 12;
+ case 0x250c : return 13;
+ case 0x2514 : return 14;
+ case 0x253c : return 15;
+ case 0xf800 : return 16;
+ case 0xf801 : return 17;
+ case 0x2500 : return 18;
+ case 0xf803 : return 19;
+ case 0xf804 : return 20;
+ case 0x251c : return 21;
+ case 0x2524 : return 22;
+ case 0x2534 : return 23;
+ case 0x252c : return 24;
+ case 0x2502 : return 25;
+ case 0x2264 : return 26;
+ case 0x2265 : return 27;
+ case 0x03c0 : return 28;
+ case 0x2260 : return 29;
+ case 0x00a3 : return 30;
+ case 0x00b7 : return 31;
+ }
+ return c;
+}
+
+static QChar identicalMap(QChar c)
+{
+ return c;
+}
+
+void TEWidget::fontChange(const QFont &)
+{
+ QFontMetrics fm(font());
+ font_h = fm.height();
+ font_w = fm.maxWidth();
+ font_a = fm.ascent();
+//printf("font_h: %d\n",font_h);
+//printf("font_w: %d\n",font_w);
+//printf("font_a: %d\n",font_a);
+//printf("charset: %s\n",QFont::encodingName(font().charSet()).ascii());
+//printf("rawname: %s\n",font().rawName().ascii());
+ fontMap =
+#if QT_VERSION < 300
+ strcmp(QFont::encodingName(font().charSet()).ascii(),"iso10646")
+ ? vt100extended
+ :
+#endif
+ identicalMap;
+ propagateSize();
+ update();
+}
+
+void TEWidget::setVTFont(const QFont& f)
+{
+ QFrame::setFont(f);
+}
+
+QFont TEWidget::getVTFont() {
+ return font();
+}
+
+void TEWidget::setFont(const QFont &)
+{
+ // ignore font change request if not coming from konsole itself
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Constructor / Destructor */
+/* */
+/* ------------------------------------------------------------------------- */
+
+TEWidget::TEWidget(QWidget *parent, const char *name) : QFrame(parent,name)
+{
+#ifndef QT_NO_CLIPBOARD
+ cb = QApplication::clipboard();
+ QObject::connect( (QObject*)cb, SIGNAL(dataChanged()),
+ this, SLOT(onClearSelection()) );
+#endif
+
+ scrollbar = new QScrollBar(this);
+ scrollbar->setCursor( arrowCursor );
+ connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
+
+ Config cfg("Konsole");
+ cfg.setGroup("ScrollBar");
+ switch( cfg.readNumEntry("Position",2)){
+ case 0:
+ scrollLoc = SCRNONE;
+ break;
+ case 1:
+ scrollLoc = SCRLEFT;
+ break;
+ case 2:
+ scrollLoc = SCRRIGHT;
+ break;
+ };
+
+ blinkT = new QTimer(this);
+ connect(blinkT, SIGNAL(timeout()), this, SLOT(blinkEvent()));
+ // blinking = FALSE;
+ blinking = TRUE;
+
+ resizing = FALSE;
+ actSel = 0;
+ image = 0;
+ lines = 1;
+ columns = 1;
+ font_w = 1;
+ font_h = 1;
+ font_a = 1;
+ word_selection_mode = FALSE;
+
+ setMouseMarks(TRUE);
+ setVTFont( QFont("fixed") );
+ setColorTable(base_color_table); // init color table
+
+ qApp->installEventFilter( this ); //FIXME: see below
+// KCursor::setAutoHideCursor( this, true );
+
+ // Init DnD ////////////////////////////////////////////////////////////////
+ currentSession = NULL;
+// setAcceptDrops(true); // attempt
+// m_drop = new QPopupMenu(this);
+// m_drop->insertItem( QString("Paste"), 0);
+// m_drop->insertItem( QString("cd"), 1);
+// connect(m_drop, SIGNAL(activated(int)), SLOT(drop_menu_activated(int)));
+
+ // we need focus so that the auto-hide cursor feature works
+ setFocus();
+ setFocusPolicy( WheelFocus );
+}
+
+//FIXME: make proper destructor
+// Here's a start (David)
+TEWidget::~TEWidget()
+{
+ qApp->removeEventFilter( this );
+ if (image) free(image);
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Display Operations */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*!
+ attributed string draw primitive
+*/
+
+void TEWidget::drawAttrStr(QPainter &paint, QRect rect,
+ QString& str, ca attr, BOOL pm, BOOL clear)
+{
+ if (pm && color_table[attr.b].transparent)
+ {
+ paint.setBackgroundMode( TransparentMode );
+ if (clear) erase(rect);
+ }
+ else
+ {
+ if (blinking)
+ paint.fillRect(rect, color_table[attr.b].color);
+ else
+ {
+ paint.setBackgroundMode( OpaqueMode );
+ paint.setBackgroundColor( color_table[attr.b].color );
+ }
+ }
+
+ if (color_table[attr.f].bold)
+ paint.setPen(QColor( 0x8F, 0x00, 0x00 ));
+ else
+ paint.setPen(color_table[attr.f].color);
+
+ paint.drawText(rect.x(),rect.y()+font_a, str);
+
+ if (attr.r & RE_UNDERLINE)
+ paint.drawLine(rect.left(), rect.y()+font_a+1, rect.right(),rect.y()+font_a+1 );
+}
+
+/*!
+ The image can only be set completely.
+
+ The size of the new image may or may not match the size of the widget.
+*/
+
+void TEWidget::setImage(const ca* const newimg, int lines, int columns)
+{ int y,x,len;
+ const QPixmap* pm = backgroundPixmap();
+ QPainter paint;
+ setUpdatesEnabled(FALSE);
+ paint.begin( this );
+HCNT("setImage");
+
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+ hasBlinker = FALSE;
+
+ int cf = -1; // undefined
+ int cb = -1; // undefined
+ int cr = -1; // undefined
+
+ int lins = QMIN(this->lines, QMAX(0,lines ));
+ int cols = QMIN(this->columns,QMAX(0,columns));
+ QChar *disstrU = new QChar[cols];
+
+//{ static int cnt = 0; printf("setImage %d\n",cnt++); }
+ for (y = 0; y < lins; y++)
+ {
+ const ca* lcl = &image[y*this->columns];
+ const ca* const ext = &newimg[y*columns];
+ if (!resizing) // not while resizing, we're expecting a paintEvent
+ for (x = 0; x < cols; x++)
+ {
+ hasBlinker |= (ext[x].r & RE_BLINK);
+ if (ext[x] != lcl[x])
+ {
+ cr = ext[x].r;
+ cb = ext[x].b;
+ if (ext[x].f != cf) cf = ext[x].f;
+ int lln = cols - x;
+ disstrU[0] = fontMap(ext[x+0].c);
+ for (len = 1; len < lln; len++)
+ {
+ if (ext[x+len].f != cf || ext[x+len].b != cb || ext[x+len].r != cr ||
+ ext[x+len] == lcl[x+len] )
+ break;
+ disstrU[len] = fontMap(ext[x+len].c);
+ }
+ QString unistr(disstrU,len);
+ drawAttrStr(paint,
+ QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
+ unistr, ext[x], pm != NULL, true);
+ x += len - 1;
+ }
+ }
+ // finally, make `image' become `newimg'.
+ memcpy((void*)lcl,(const void*)ext,cols*sizeof(ca));
+ }
+ drawFrame( &paint );
+ paint.end();
+ setUpdatesEnabled(TRUE);
+ if ( hasBlinker && !blinkT->isActive()) blinkT->start(1000); // 1000 ms
+ if (!hasBlinker && blinkT->isActive()) { blinkT->stop(); blinking = FALSE; }
+ delete [] disstrU;
+}
+
+// paint Event ////////////////////////////////////////////////////
+
+/*!
+ The difference of this routine vs. the `setImage' is,
+ that the drawing does not include a difference analysis
+ between the old and the new image. Instead, the internal
+ image is used and the painting bound by the PaintEvent box.
+*/
+
+void TEWidget::paintEvent( QPaintEvent* pe )
+{
+
+//{ static int cnt = 0; printf("paint %d\n",cnt++); }
+ const QPixmap* pm = backgroundPixmap();
+ QPainter paint;
+ setUpdatesEnabled(FALSE);
+ paint.begin( this );
+ paint.setBackgroundMode( TransparentMode );
+HCNT("paintEvent");
+
+ // Note that the actual widget size can be slightly larger
+ // that the image (the size is truncated towards the smaller
+ // number of characters in `resizeEvent'. The paint rectangle
+ // can thus be larger than the image, but less then the size
+ // of one character.
+
+ QRect rect = pe->rect().intersect(contentsRect());
+
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+
+ int lux = QMIN(columns-1, QMAX(0,(rect.left() - tLx - blX ) / font_w));
+ int luy = QMIN(lines-1, QMAX(0,(rect.top() - tLy - bY ) / font_h));
+ int rlx = QMIN(columns-1, QMAX(0,(rect.right() - tLx - blX ) / font_w));
+ int rly = QMIN(lines-1, QMAX(0,(rect.bottom() - tLy - bY ) / font_h));
+
+ /*
+ printf("paintEvent: %d..%d, %d..%d (%d..%d, %d..%d)\n",lux,rlx,luy,rly,
+ rect.left(), rect.right(), rect.top(), rect.bottom());
+ */
+
+ // if (pm != NULL && color_table[image->b].transparent)
+ // erase(rect);
+ // BL: I have no idea why we need this, and it breaks the refresh.
+
+ QChar *disstrU = new QChar[columns];
+ for (int y = luy; y <= rly; y++)
+ for (int x = lux; x <= rlx; x++)
+ {
+ int len = 1;
+ disstrU[0] = fontMap(image[loc(x,y)].c);
+ int cf = image[loc(x,y)].f;
+ int cb = image[loc(x,y)].b;
+ int cr = image[loc(x,y)].r;
+ while (x+len <= rlx &&
+ image[loc(x+len,y)].f == cf &&
+ image[loc(x+len,y)].b == cb &&
+ image[loc(x+len,y)].r == cr )
+ {
+ disstrU[len] = fontMap(image[loc(x+len,y)].c);
+ len += 1;
+ }
+ QString unistr(disstrU,len);
+ drawAttrStr(paint,
+ QRect(blX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
+ unistr, image[loc(x,y)], pm != NULL, false);
+ x += len - 1;
+ }
+ delete [] disstrU;
+ drawFrame( &paint );
+ paint.end();
+ setUpdatesEnabled(TRUE);
+}
+
+void TEWidget::blinkEvent()
+{
+ blinking = !blinking;
+ repaint(FALSE);
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Resizing */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEWidget::resizeEvent(QResizeEvent* ev)
+{
+// printf("resize: %d,%d\n",ev->size().width(),ev->size().height());
+ //printf("approx: %d,%d\n",ev->size().width()/font_w,ev->size().height()/font_h);
+ //printf("leaves: %d,%d\n",ev->size().width()%font_w,ev->size().height()%font_h);
+ //printf("curren: %d,%d\n",width(),height());
+HCNT("resizeEvent");
+
+ // see comment in `paintEvent' concerning the rounding.
+ //FIXME: could make a routine here; check width(),height()
+ assert(ev->size().width() == width());
+ assert(ev->size().height() == height());
+
+ propagateSize();
+}
+
+void TEWidget::propagateSize()
+{
+ ca* oldimg = image;
+ int oldlin = lines;
+ int oldcol = columns;
+ makeImage();
+ // we copy the old image to reduce flicker
+ int lins = QMIN(oldlin,lines);
+ int cols = QMIN(oldcol,columns);
+ if (oldimg)
+ {
+ for (int lin = 0; lin < lins; lin++)
+ memcpy((void*)&image[columns*lin],
+ (void*)&oldimg[oldcol*lin],cols*sizeof(ca));
+ free(oldimg); //FIXME: try new,delete
+ }
+ else
+ clearImage();
+
+ //NOTE: control flows from the back through the chest right into the eye.
+ // `emu' will call back via `setImage'.
+
+ resizing = TRUE;
+ emit changedImageSizeSignal(lines, columns); // expose resizeEvent
+ resizing = FALSE;
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Scrollbar */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEWidget::scrollChanged(int)
+{
+ emit changedHistoryCursor(scrollbar->value()); //expose
+}
+
+void TEWidget::setScroll(int cursor, int slines)
+{
+ disconnect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
+ scrollbar->setRange(0,slines);
+ scrollbar->setSteps(1,lines);
+ scrollbar->setValue(cursor);
+ connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
+}
+
+void TEWidget::setScrollbarLocation(int loc)
+{
+ if (scrollLoc == loc) return; // quickly
+ scrollLoc = loc;
+ propagateSize();
+ update();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Mouse */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*!
+ Three different operations can be performed using the mouse, and the
+ routines in this section serve all of them:
+
+ 1) The press/release events are exposed to the application
+ 2) Marking (press and move left button) and Pasting (press middle button)
+ 3) The right mouse button is used from the configuration menu
+
+ NOTE: During the marking process we attempt to keep the cursor within
+ the bounds of the text as being displayed by setting the mouse position
+ whenever the mouse has left the text area.
+
+ Two reasons to do so:
+ 1) QT does not allow the `grabMouse' to confine-to the TEWidget.
+ Thus a `XGrapPointer' would have to be used instead.
+ 2) Even if so, this would not help too much, since the text area
+ of the TEWidget is normally not identical with it's bounds.
+
+ The disadvantage of the current handling is, that the mouse can visibly
+ leave the bounds of the widget and is then moved back. Because of the
+ current construction, and the reasons mentioned above, we cannot do better
+ without changing the overall construction.
+*/
+
+/*!
+*/
+
+void TEWidget::mousePressEvent(QMouseEvent* ev)
+{
+//printf("press [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button());
+ if ( !contentsRect().contains(ev->pos()) ) return;
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+
+ word_selection_mode = FALSE;
+
+//printf("press top left [%d,%d] by=%d\n",tLx,tLy, bY);
+ if ( ev->button() == LeftButton)
+ {
+ QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
+
+ if ( ev->state() & ControlButton ) preserve_line_breaks = FALSE ;
+
+ if (mouse_marks || (ev->state() & ShiftButton))
+ {
+ emit clearSelectionSignal();
+ iPntSel = pntSel = pos;
+ actSel = 1; // left mouse button pressed but nothing selected yet.
+ grabMouse( /*crossCursor*/ ); // handle with care!
+ }
+ else
+ {
+ emit mouseSignal( 0, pos.x() + 1, pos.y() + 1 ); // left button
+ }
+ }
+ if ( ev->button() == MidButton )
+ {
+ emitSelection();
+ }
+ if ( ev->button() == RightButton ) // Configure
+ {
+ emit configureRequest( this, ev->state()&(ShiftButton|ControlButton), ev->x(), ev->y() );
+ }
+}
+
+void TEWidget::mouseMoveEvent(QMouseEvent* ev)
+{
+ // for auto-hiding the cursor, we need mouseTracking
+ if (ev->state() == NoButton ) return;
+
+ if (actSel == 0) return;
+
+ // don't extend selection while pasting
+ if (ev->state() & MidButton) return;
+
+ //if ( !contentsRect().contains(ev->pos()) ) return;
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+ int scroll = scrollbar->value();
+
+ // we're in the process of moving the mouse with the left button pressed
+ // the mouse cursor will kept catched within the bounds of the text in
+ // this widget.
+
+ // Adjust position within text area bounds. See FIXME above.
+ QPoint pos = ev->pos();
+ if ( pos.x() < tLx+blX ) pos.setX( tLx+blX );
+ if ( pos.x() > tLx+blX+columns*font_w-1 ) pos.setX( tLx+blX+columns*font_w );
+ if ( pos.y() < tLy+bY ) pos.setY( tLy+bY );
+ if ( pos.y() > tLy+bY+lines*font_h-1 ) pos.setY( tLy+bY+lines*font_h-1 );
+ // check if we produce a mouse move event by this
+ if ( pos != ev->pos() ) cursor().setPos(mapToGlobal(pos));
+
+ if ( pos.y() == tLy+bY+lines*font_h-1 )
+ {
+ scrollbar->setValue(scrollbar->value()+yMouseScroll); // scrollforward
+ }
+ if ( pos.y() == tLy+bY )
+ {
+ scrollbar->setValue(scrollbar->value()-yMouseScroll); // scrollback
+ }
+
+ QPoint here = QPoint((pos.x()-tLx-blX)/font_w,(pos.y()-tLy-bY)/font_h);
+ QPoint ohere;
+ bool swapping = FALSE;
+
+ if ( word_selection_mode )
+ {
+ // Extend to word boundaries
+ int i;
+ int selClass;
+
+ bool left_not_right = ( here.y() < iPntSel.y() ||
+ here.y() == iPntSel.y() && here.x() < iPntSel.x() );
+ bool old_left_not_right = ( pntSel.y() < iPntSel.y() ||
+ pntSel.y() == iPntSel.y() && pntSel.x() < iPntSel.x() );
+ swapping = left_not_right != old_left_not_right;
+
+ // Find left (left_not_right ? from here : from start)
+ QPoint left = left_not_right ? here : iPntSel;
+ i = loc(left.x(),left.y());
+ selClass = charClass(image[i].c);
+ while ( left.x() > 0 && charClass(image[i-1].c) == selClass )
+ { i--; left.rx()--; }
+
+ // Find left (left_not_right ? from start : from here)
+ QPoint right = left_not_right ? iPntSel : here;
+ i = loc(right.x(),right.y());
+ selClass = charClass(image[i].c);
+ while ( right.x() < columns-1 && charClass(image[i+1].c) == selClass )
+ { i++; right.rx()++; }
+
+ // Pick which is start (ohere) and which is extension (here)
+ if ( left_not_right )
+ {
+ here = left; ohere = right;
+ }
+ else
+ {
+ here = right; ohere = left;
+ }
+ }
+
+ if (here == pntSel && scroll == scrollbar->value()) return; // not moved
+
+ if ( word_selection_mode ) {
+ if ( actSel < 2 || swapping ) {
+ emit beginSelectionSignal( ohere.x(), ohere.y() );
+ }
+ } else if ( actSel < 2 ) {
+ emit beginSelectionSignal( pntSel.x(), pntSel.y() );
+ }
+
+ actSel = 2; // within selection
+ pntSel = here;
+ emit extendSelectionSignal( here.x(), here.y() );
+}
+
+void TEWidget::mouseReleaseEvent(QMouseEvent* ev)
+{
+//printf("release [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button());
+ if ( ev->button() == LeftButton)
+ {
+ if ( actSel > 1 ) emit endSelectionSignal(preserve_line_breaks);
+ preserve_line_breaks = TRUE;
+ actSel = 0;
+
+ //FIXME: emits a release event even if the mouse is
+ // outside the range. The procedure used in `mouseMoveEvent'
+ // applies here, too.
+
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+
+ if (!mouse_marks && !(ev->state() & ShiftButton))
+ emit mouseSignal( 3, // release
+ (ev->x()-tLx-blX)/font_w + 1,
+ (ev->y()-tLy-bY)/font_h + 1 );
+ releaseMouse();
+ }
+}
+
+void TEWidget::mouseDoubleClickEvent(QMouseEvent* ev)
+{
+ if ( ev->button() != LeftButton) return;
+
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+ QPoint pos = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
+
+ // pass on double click as two clicks.
+ if (!mouse_marks && !(ev->state() & ShiftButton))
+ {
+ emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button
+ emit mouseSignal( 3, pos.x()+1, pos.y()+1 ); // release
+ emit mouseSignal( 0, pos.x()+1, pos.y()+1 ); // left button
+ return;
+ }
+
+
+ emit clearSelectionSignal();
+ QPoint bgnSel = pos;
+ QPoint endSel = QPoint((ev->x()-tLx-blX)/font_w,(ev->y()-tLy-bY)/font_h);
+ int i = loc(bgnSel.x(),bgnSel.y());
+ iPntSel = bgnSel;
+
+ word_selection_mode = TRUE;
+
+ // find word boundaries...
+ int selClass = charClass(image[i].c);
+ {
+ // set the start...
+ int x = bgnSel.x();
+ while ( x > 0 && charClass(image[i-1].c) == selClass )
+ { i--; x--; }
+ bgnSel.setX(x);
+ emit beginSelectionSignal( bgnSel.x(), bgnSel.y() );
+
+ // set the end...
+ i = loc( endSel.x(), endSel.y() );
+ x = endSel.x();
+ while( x < columns-1 && charClass(image[i+1].c) == selClass )
+ { i++; x++ ; }
+ endSel.setX(x);
+ actSel = 2; // within selection
+ emit extendSelectionSignal( endSel.x(), endSel.y() );
+ emit endSelectionSignal(preserve_line_breaks);
+ preserve_line_breaks = TRUE;
+ }
+}
+
+void TEWidget::focusInEvent( QFocusEvent * )
+{
+
+ // do nothing, to prevent repainting
+}
+
+
+void TEWidget::focusOutEvent( QFocusEvent * )
+{
+ // do nothing, to prevent repainting
+}
+
+bool TEWidget::focusNextPrevChild( bool next )
+{
+ if (next)
+ return false; // This disables changing the active part in konqueror
+ // when pressing Tab
+ return QFrame::focusNextPrevChild( next );
+}
+
+
+int TEWidget::charClass(char ch) const
+{
+ // This might seem like overkill, but imagine if ch was a Unicode
+ // character (Qt 2.0 QChar) - it might then be sensible to separate
+ // the different language ranges, etc.
+
+ if ( isspace(ch) ) return ' ';
+
+ static const char *word_characters = ":@-./_~";
+ if ( isalnum(ch) || strchr(word_characters, ch) )
+ return 'a';
+
+ // Everything else is weird
+ return 1;
+}
+
+void TEWidget::setMouseMarks(bool on)
+{
+ mouse_marks = on;
+ setCursor( mouse_marks ? ibeamCursor : arrowCursor );
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Clipboard */
+/* */
+/* ------------------------------------------------------------------------- */
+
+#undef KeyPress
+
+void TEWidget::emitSelection()
+// Paste Clipboard by simulating keypress events
+{
+#ifndef QT_NO_CLIPBOARD
+ QString text = QApplication::clipboard()->text();
+ if ( ! text.isNull() )
+ {
+ text.replace(QRegExp("\n"), "\r");
+ QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text);
+ emit keyPressedSignal(&e); // expose as a big fat keypress event
+ emit clearSelectionSignal();
+ }
+#endif
+}
+
+void TEWidget::emitText(QString text)
+{
+ QKeyEvent e(QEvent::KeyPress, 0, -1, 0, text);
+ emit keyPressedSignal(&e); // expose as a big fat keypress event
+}
+
+void TEWidget::pasteClipboard( )
+{
+ emitSelection();
+}
+
+void TEWidget::setSelection(const QString& t)
+{
+#ifndef QT_NO_CLIPBOARD
+ // Disconnect signal while WE set the clipboard
+ QObject *cb = QApplication::clipboard();
+ QObject::disconnect( cb, SIGNAL(dataChanged()),
+ this, SLOT(onClearSelection()) );
+
+ QApplication::clipboard()->setText(t);
+
+ QObject::connect( cb, SIGNAL(dataChanged()),
+ this, SLOT(onClearSelection()) );
+#endif
+}
+
+void TEWidget::onClearSelection()
+{
+ emit clearSelectionSignal();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Keyboard */
+/* */
+/* ------------------------------------------------------------------------- */
+
+//FIXME: an `eventFilter' has been installed instead of a `keyPressEvent'
+// due to a bug in `QT' or the ignorance of the author to prevent
+// repaint events being emitted to the screen whenever one leaves
+// or reenters the screen to/from another application.
+//
+// Troll says one needs to change focusInEvent() and focusOutEvent(),
+// which would also let you have an in-focus cursor and an out-focus
+// cursor like xterm does.
+
+// for the auto-hide cursor feature, I added empty focusInEvent() and
+// focusOutEvent() so that update() isn't called.
+// For auto-hide, we need to get keypress-events, but we only get them when
+// we have focus.
+
+void TEWidget::doScroll(int lines)
+{
+ scrollbar->setValue(scrollbar->value()+lines);
+}
+
+bool TEWidget::eventFilter( QObject *obj, QEvent *e )
+{
+ if ( (e->type() == QEvent::Accel ||
+ e->type() == QEvent::AccelAvailable ) && qApp->focusWidget() == this ) {
+ static_cast<QKeyEvent *>( e )->ignore();
+ return true;
+ }
+ if ( obj != this /* when embedded */ && obj != parent() /* when standalone */ )
+ return FALSE; // not us
+ if ( e->type() == QEvent::Wheel) {
+ QApplication::sendEvent(scrollbar, e);
+ }
+
+#ifdef FAKE_CTRL_AND_ALT
+ static bool control = FALSE;
+ static bool alt = FALSE;
+// qDebug(" Has a keyboard with no CTRL and ALT keys, but we fake it:");
+ bool dele=FALSE;
+ if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease ) {
+ QKeyEvent* ke = (QKeyEvent*)e;
+ bool keydown = e->type() == QEvent::KeyPress || ke->isAutoRepeat();
+ switch (ke->key()) {
+ case Key_F9: // let this be "Control"
+ control = keydown;
+ e = new QKeyEvent(QEvent::KeyPress, Key_Control, 0, ke->state());
+ dele=TRUE;
+ break;
+ case Key_F13: // let this be "Alt"
+ alt = keydown;
+ e = new QKeyEvent(QEvent::KeyPress, Key_Alt, 0, ke->state());
+ dele=TRUE;
+ break;
+ default:
+ if ( control ) {
+ int a = toupper(ke->ascii())-64;
+ if ( a >= 0 && a < ' ' ) {
+ e = new QKeyEvent(e->type(), ke->key(),
+ a, ke->state()|ControlButton, QChar(a,0));
+ dele=TRUE;
+ }
+ }
+ if ( alt ) {
+ e = new QKeyEvent(e->type(), ke->key(),
+ ke->ascii(), ke->state()|AltButton, ke->text());
+ dele=TRUE;
+ }
+ }
+ }
+#endif
+
+ if ( e->type() == QEvent::KeyPress ) {
+ QKeyEvent* ke = (QKeyEvent*)e;
+ actSel=0; // Key stroke implies a screen update, so TEWidget won't
+ // know where the current selection is.
+
+// qDebug("key pressed is 0x%x",ke->key());
+
+ if( ke->state() == ShiftButton && ke->key() == Key_Tab) { //lets hardcode this sucker
+
+// qDebug("key pressed 2 is 0x%x",ke->key());
+ emitText("\\"); // expose
+ } else
+ emit keyPressedSignal(ke); // expose
+ ke->accept();
+#ifdef FAKE_CTRL_AND_ALT
+ if ( dele ) delete e;
+#endif
+ return true; // stop the event
+ }
+ if ( e->type() == QEvent::Enter ) {
+ QObject::disconnect( (QObject*)cb, SIGNAL(dataChanged()),
+ this, SLOT(onClearSelection()) );
+ }
+ if ( e->type() == QEvent::Leave ) {
+ QObject::connect( (QObject*)cb, SIGNAL(dataChanged()),
+ this, SLOT(onClearSelection()) );
+ }
+ return QFrame::eventFilter( obj, e );
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Frame */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEWidget::frameChanged()
+{
+ propagateSize();
+ update();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Sound */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEWidget::Bell()
+{
+ QApplication::beep();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Auxiluary */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEWidget::clearImage()
+// initialize the image
+// for internal use only
+{
+ for (int y = 0; y < lines; y++)
+ for (int x = 0; x < columns; x++)
+ {
+ image[loc(x,y)].c = 0xff; //' ';
+ image[loc(x,y)].f = 0xff; //DEFAULT_FORE_COLOR;
+ image[loc(x,y)].b = 0xff; //DEFAULT_BACK_COLOR;
+ image[loc(x,y)].r = 0xff; //DEFAULT_RENDITION;
+ }
+}
+
+// Create Image ///////////////////////////////////////////////////////
+
+void TEWidget::calcGeometry()
+{
+ //FIXME: set rimX == rimY == 0 when running in full screen mode.
+
+ scrollbar->resize(QApplication::style().scrollBarExtent().width(),
+ contentsRect().height());
+ switch(scrollLoc)
+ {
+ case SCRNONE :
+ columns = ( contentsRect().width() - 2 * rimX ) / font_w;
+ blX = (contentsRect().width() - (columns*font_w) ) / 2;
+ brX = blX;
+ scrollbar->hide();
+ break;
+ case SCRLEFT :
+ columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w;
+ brX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2;
+ blX = brX + scrollbar->width();
+ scrollbar->move(contentsRect().topLeft());
+ scrollbar->show();
+ break;
+ case SCRRIGHT:
+ columns = ( contentsRect().width() - 2 * rimX - scrollbar->width()) / font_w;
+ blX = (contentsRect().width() - (columns*font_w) - scrollbar->width() ) / 2;
+ brX = blX;
+ scrollbar->move(contentsRect().topRight() - QPoint(scrollbar->width()-1,0));
+ scrollbar->show();
+ break;
+ }
+ //FIXME: support 'rounding' styles
+ lines = ( contentsRect().height() - 2 * rimY ) / font_h;
+ bY = (contentsRect().height() - (lines *font_h)) / 2;
+}
+
+void TEWidget::makeImage()
+//FIXME: rename 'calcGeometry?
+{
+ calcGeometry();
+ image = (ca*) malloc(lines*columns*sizeof(ca));
+ clearImage();
+}
+
+// calculate the needed size
+QSize TEWidget::calcSize(int cols, int lins) const
+{
+ int frw = width() - contentsRect().width();
+ int frh = height() - contentsRect().height();
+ int scw = (scrollLoc==SCRNONE?0:scrollbar->width());
+ return QSize( font_w*cols + 2*rimX + frw + scw, font_h*lins + 2*rimY + frh );
+}
+
+QSize TEWidget::sizeHint() const
+{
+ return size();
+}
+
+void TEWidget::styleChange(QStyle &)
+{
+ propagateSize();
+}
+
+#ifndef QT_NO_DRAGANDDROP
+
+/* --------------------------------------------------------------------- */
+/* */
+/* Drag & Drop */
+/* */
+/* --------------------------------------------------------------------- */
+
+
+void TEWidget::dragEnterEvent(QDragEnterEvent* e)
+{
+ e->accept(QTextDrag::canDecode(e) ||
+ QUriDrag::canDecode(e));
+}
+
+void TEWidget::dropEvent(QDropEvent* event)
+{
+ // The current behaviour when url(s) are dropped is
+ // * if there is only ONE url and if it's a LOCAL one, ask for paste or cd
+ // * in all other cases, just paste
+ // (for non-local ones, or for a list of URLs, 'cd' is nonsense)
+ QStrList strlist;
+ int file_count = 0;
+ dropText = "";
+ bool bPopup = true;
+
+ if(QUriDrag::decode(event, strlist)) {
+ if (strlist.count()) {
+ for(const char* p = strlist.first(); p; p = strlist.next()) {
+ if(file_count++ > 0) {
+ dropText += " ";
+ bPopup = false; // more than one file, don't popup
+ }
+
+/*
+ KURL url(p);
+ if (url.isLocalFile()) {
+ dropText += url.path(); // local URL : remove protocol
+ }
+ else {
+ dropText += url.prettyURL();
+ bPopup = false; // a non-local file, don't popup
+ }
+*/
+
+ }
+
+ if (bPopup)
+ // m_drop->popup(pos() + event->pos());
+ m_drop->popup(mapToGlobal(event->pos()));
+ else
+ {
+ if (currentSession) {
+ currentSession->getEmulation()->sendString(dropText.local8Bit());
+ }
+// kdDebug() << "Drop:" << dropText.local8Bit() << "\n";
+ }
+ }
+ }
+ else if(QTextDrag::decode(event, dropText)) {
+// kdDebug() << "Drop:" << dropText.local8Bit() << "\n";
+ if (currentSession) {
+ currentSession->getEmulation()->sendString(dropText.local8Bit());
+ }
+ // Paste it
+ }
+}
+#endif
+
+
+void TEWidget::drop_menu_activated(int item)
+{
+#ifndef QT_NO_DRAGANDDROP
+ switch (item)
+ {
+ case 0: // paste
+ currentSession->getEmulation()->sendString(dropText.local8Bit());
+// KWM::activate((Window)this->winId());
+ break;
+ case 1: // cd ...
+ currentSession->getEmulation()->sendString("cd ");
+ struct stat statbuf;
+ if ( ::stat( QFile::encodeName( dropText ), &statbuf ) == 0 )
+ {
+ if ( !S_ISDIR(statbuf.st_mode) )
+ {
+/*
+ KURL url;
+ url.setPath( dropText );
+ dropText = url.directory( true, false ); // remove filename
+*/
+ }
+ }
+ dropText.replace(QRegExp(" "), "\\ "); // escape spaces
+ currentSession->getEmulation()->sendString(dropText.local8Bit());
+ currentSession->getEmulation()->sendString("\n");
+// KWM::activate((Window)this->winId());
+ break;
+ }
+#endif
+}
+
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 @@
+/* ----------------------------------------------------------------------- */
+/* */
+/* [te_widget.h] Terminal Emulation Widget */
+/* */
+/* ----------------------------------------------------------------------- */
+/* */
+/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
+/* */
+/* This file is part of Konsole - an X terminal for KDE */
+/* */
+/* ----------------------------------------------------------------------- */
+/* */
+/* Ported Konsole to Qt/Embedded */
+/* */
+/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
+/* */
+/* -------------------------------------------------------------------------- */
+#ifndef TE_WIDGET_H
+#define TE_WIDGET_H
+
+#include <qwidget.h>
+#include <qlabel.h>
+#include <qtimer.h>
+#include <qcolor.h>
+#include <qkeycode.h>
+#include <qscrollbar.h>
+
+#include <qpopupmenu.h>
+
+#include "TECommon.h"
+
+extern unsigned short vt100_graphics[32];
+
+class TESession;
+
+// class Konsole;
+
+class TEWidget : public QFrame
+// a widget representing attributed text
+{ Q_OBJECT
+
+// friend class Konsole;
+
+public:
+
+ TEWidget(QWidget *parent=0, const char *name=0);
+ virtual ~TEWidget();
+
+public:
+
+ QColor getDefaultBackColor();
+
+ const ColorEntry* getColorTable() const;
+ const ColorEntry* getdefaultColorTable() const;
+ void setColorTable(const ColorEntry table[]);
+
+ void setScrollbarLocation(int loc);
+ enum { SCRNONE=0, SCRLEFT=1, SCRRIGHT=2 };
+
+ void setScroll(int cursor, int lines);
+ void doScroll(int lines);
+
+ void emitSelection();
+
+public:
+
+ void setImage(const ca* const newimg, int lines, int columns);
+
+ int Lines() { return lines; }
+ int Columns() { return columns; }
+
+ void calcGeometry();
+ void propagateSize();
+ QSize calcSize(int cols, int lins) const;
+
+ QSize sizeHint() const;
+
+public:
+
+ void Bell();
+ void emitText(QString text);
+ void pasteClipboard();
+
+signals:
+
+ void keyPressedSignal(QKeyEvent *e);
+ void mouseSignal(int cb, int cx, int cy);
+ void changedImageSizeSignal(int lines, int columns);
+ void changedHistoryCursor(int value);
+ void configureRequest( TEWidget*, int state, int x, int y );
+
+ void clearSelectionSignal();
+ void beginSelectionSignal( const int x, const int y );
+ void extendSelectionSignal( const int x, const int y );
+ void endSelectionSignal(const BOOL preserve_line_breaks);
+
+
+protected:
+
+ virtual void styleChange( QStyle& );
+
+ bool eventFilter( QObject *, QEvent * );
+
+ void drawAttrStr(QPainter &paint, QRect rect,
+ QString& str, ca attr, BOOL pm, BOOL clear);
+ void paintEvent( QPaintEvent * );
+
+ void resizeEvent(QResizeEvent*);
+
+ void fontChange(const QFont &font);
+ void frameChanged();
+
+ void mouseDoubleClickEvent(QMouseEvent* ev);
+ void mousePressEvent( QMouseEvent* );
+ void mouseReleaseEvent( QMouseEvent* );
+ void mouseMoveEvent( QMouseEvent* );
+
+ void focusInEvent( QFocusEvent * );
+ void focusOutEvent( QFocusEvent * );
+ bool focusNextPrevChild( bool next );
+
+#ifndef QT_NO_DRAGANDDROP
+ // Dnd
+ void dragEnterEvent(QDragEnterEvent* event);
+ void dropEvent(QDropEvent* event);
+#endif
+
+ virtual int charClass(char) const;
+
+ void clearImage();
+
+public:
+ const QPixmap *backgroundPixmap();
+
+ void setSelection(const QString &t);
+
+ virtual void setFont(const QFont &);
+ void setVTFont(const QFont &);
+ QFont getVTFont();
+
+ void setMouseMarks(bool on);
+
+public slots:
+
+ void onClearSelection();
+
+protected slots:
+
+ void scrollChanged(int value);
+ void blinkEvent();
+
+private:
+
+ QChar (*fontMap)(QChar); // possible vt100 font extention
+
+ bool fixed_font; // has fixed pitch
+ int font_h; // height
+ int font_w; // width
+ int font_a; // ascend
+
+ int blX; // actual offset (left)
+ int brX; // actual offset (right)
+ int bY; // actual offset
+
+ int lines;
+ int columns;
+ ca *image; // [lines][columns]
+
+ ColorEntry color_table[TABLE_COLORS];
+
+ BOOL resizing;
+ bool mouse_marks;
+
+ void makeImage();
+
+ QPoint iPntSel; // initial selection point
+ QPoint pntSel; // current selection point
+ int actSel; // selection state
+ BOOL word_selection_mode;
+ BOOL preserve_line_breaks;
+
+ QClipboard* cb;
+ QScrollBar* scrollbar;
+ int scrollLoc;
+
+//#define SCRNONE 0
+//#define SCRLEFT 1
+//#define SCRRIGHT 2
+
+ BOOL blinking; // hide text in paintEvent
+ BOOL hasBlinker; // has characters to blink
+ QTimer* blinkT; // active when hasBlinker
+ QPopupMenu* m_drop;
+ QString dropText;
+ public:
+ // current session in this widget
+ TESession *currentSession;
+private slots:
+ void drop_menu_activated(int item);
+};
+
+#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 @@
+/* ------------------------------------------------------------------------- */
+/* */
+/* [TEmuVt102.C] VT102 Terminal Emulation */
+/* */
+/* ------------------------------------------------------------------------- */
+/* */
+/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
+/* */
+/* This file is part of Konsole - an X terminal for KDE */
+/* */
+/* ------------------------------------------------------------------------- */
+/* */
+/* Ported Konsole to Qt/Embedded */
+/* */
+/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+/*! \class TEmuVt102
+
+ \brief Actual Emulation for Konsole
+
+ \sa TEWidget \sa TEScreen
+*/
+
+#include "TEmuVt102.h"
+#include "TEWidget.h"
+#include "TEScreen.h"
+#include "keytrans.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <qkeycode.h>
+#include <qtextcodec.h>
+
+
+/* VT102 Terminal Emulation
+
+ This class puts together the screens, the pty and the widget to a
+ complete terminal emulation. Beside combining it's componentes, it
+ handles the emulations's protocol.
+
+ This module consists of the following sections:
+
+ - Constructor/Destructor
+ - Incoming Bytes Event pipeline
+ - Outgoing Bytes
+ - Mouse Events
+ - Keyboard Events
+ - Modes and Charset State
+ - Diagnostics
+*/
+
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Constructor / Destructor */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*
+ Nothing really intesting happens here.
+*/
+
+/*!
+*/
+
+TEmuVt102::TEmuVt102(TEWidget* gui) : TEmulation(gui)
+{
+ QObject::connect(gui,SIGNAL(mouseSignal(int,int,int)),
+ this,SLOT(onMouse(int,int,int)));
+ initTokenizer();
+ reset();
+}
+
+/*!
+*/
+
+TEmuVt102::~TEmuVt102()
+{
+}
+
+/*!
+*/
+
+void TEmuVt102::reset()
+{
+ resetToken();
+ resetModes();
+ resetCharset(0); screen[0]->reset();
+ resetCharset(1); screen[0]->reset();
+ setCodec(0);
+ setKeytrans("linux.keytab");
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Processing the incoming byte stream */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/* Incoming Bytes Event pipeline
+
+ This section deals with decoding the incoming character stream.
+ Decoding means here, that the stream is first seperated into `tokens'
+ which are then mapped to a `meaning' provided as operations by the
+ `TEScreen' class or by the emulation class itself.
+
+ The pipeline proceeds as follows:
+
+ - Tokenizing the ESC codes (onRcvChar)
+ - VT100 code page translation of plain characters (applyCharset)
+ - Interpretation of ESC codes (tau)
+
+ The escape codes and their meaning are described in the
+ technical reference of this program.
+*/
+
+// Tokens ------------------------------------------------------------------ --
+
+/*
+ Since the tokens are the central notion if this section, we've put them
+ in front. They provide the syntactical elements used to represent the
+ terminals operations as byte sequences.
+
+ They are encodes here into a single machine word, so that we can later
+ switch over them easily. Depending on the token itself, additional
+ argument variables are filled with parameter values.
+
+ The tokens are defined below:
+
+ - CHR - Printable characters (32..255 but DEL (=127))
+ - CTL - Control characters (0..31 but ESC (= 27), DEL)
+ - ESC - Escape codes of the form <ESC><CHR but `[]()+*#'>
+ - ESC_DE - Escape codes of the form <ESC><any of `()+*#%'> C
+ - CSI_PN - Escape codes of the form <ESC>'[' {Pn} ';' {Pn} C
+ - CSI_PS - Escape codes of the form <ESC>'[' {Pn} ';' ... C
+ - CSI_PR - Escape codes of the form <ESC>'[' '?' {Pn} ';' ... C
+ - VT52 - VT52 escape codes
+ - <ESC><Chr>
+ - <ESC>'Y'{Pc}{Pc}
+ - XTE_HA - Xterm hacks <ESC>`]' {Pn} `;' {Text} <BEL>
+ note that this is handled differently
+
+ The last two forms allow list of arguments. Since the elements of
+ the lists are treated individually the same way, they are passed
+ as individual tokens to the interpretation. Further, because the
+ meaning of the parameters are names (althought represented as numbers),
+ they are includes within the token ('N').
+
+*/
+
+#define TY_CONSTR(T,A,N) ( ((((int)N) & 0xffff) << 16) | ((((int)A) & 0xff) << 8) | (((int)T) & 0xff) )
+
+#define TY_CHR___( ) TY_CONSTR(0,0,0)
+#define TY_CTL___(A ) TY_CONSTR(1,A,0)
+#define TY_ESC___(A ) TY_CONSTR(2,A,0)
+#define TY_ESC_CS(A,B) TY_CONSTR(3,A,B)
+#define TY_ESC_DE(A ) TY_CONSTR(4,A,0)
+#define TY_CSI_PS(A,N) TY_CONSTR(5,A,N)
+#define TY_CSI_PN(A ) TY_CONSTR(6,A,0)
+#define TY_CSI_PR(A,N) TY_CONSTR(7,A,N)
+
+#define TY_VT52__(A ) TY_CONSTR(8,A,0)
+
+// Tokenizer --------------------------------------------------------------- --
+
+/* The tokenizers state
+
+ The state is represented by the buffer (pbuf, ppos),
+ and accompanied by decoded arguments kept in (argv,argc).
+ Note that they are kept internal in the tokenizer.
+*/
+
+void TEmuVt102::resetToken()
+{
+ ppos = 0; argc = 0; argv[0] = 0; argv[1] = 0;
+}
+
+void TEmuVt102::addDigit(int dig)
+{
+ argv[argc] = 10*argv[argc] + dig;
+}
+
+void TEmuVt102::addArgument()
+{
+ argc = QMIN(argc+1,MAXARGS-1);
+ argv[argc] = 0;
+}
+
+void TEmuVt102::pushToToken(int cc)
+{
+ pbuf[ppos] = cc;
+ ppos = QMIN(ppos+1,MAXPBUF-1);
+}
+
+// Character Classes used while decoding
+
+#define CTL 1
+#define CHR 2
+#define CPN 4
+#define DIG 8
+#define SCS 16
+#define GRP 32
+
+void TEmuVt102::initTokenizer()
+{ int i; UINT8* s;
+ for(i = 0; i < 256; i++) tbl[ i] = 0;
+ for(i = 0; i < 32; i++) tbl[ i] |= CTL;
+ for(i = 32; i < 256; i++) tbl[ i] |= CHR;
+ for(s = (UINT8*)"@ABCDGHLMPXcdfry"; *s; s++) tbl[*s] |= CPN;
+ for(s = (UINT8*)"0123456789" ; *s; s++) tbl[*s] |= DIG;
+ for(s = (UINT8*)"()+*%" ; *s; s++) tbl[*s] |= SCS;
+ for(s = (UINT8*)"()+*#[]%" ; *s; s++) tbl[*s] |= GRP;
+ resetToken();
+}
+
+/* Ok, here comes the nasty part of the decoder.
+
+ Instead of keeping an explicit state, we deduce it from the
+ token scanned so far. It is then immediately combined with
+ the current character to form a scanning decision.
+
+ This is done by the following defines.
+
+ - P is the length of the token scanned so far.
+ - L (often P-1) is the position on which contents we base a decision.
+ - C is a character or a group of characters (taken from 'tbl').
+
+ Note that they need to applied in proper order.
+*/
+
+#define lec(P,L,C) (p == (P) && s[(L)] == (C))
+#define lun( ) (p == 1 && cc >= 32 )
+#define les(P,L,C) (p == (P) && s[L] < 256 && (tbl[s[(L)]] & (C)) == (C))
+#define eec(C) (p >= 3 && cc == (C))
+#define ees(C) (p >= 3 && cc < 256 && (tbl[ cc ] & (C)) == (C))
+#define eps(C) (p >= 3 && s[2] != '?' && cc < 256 && (tbl[ cc ] & (C)) == (C))
+#define epp( ) (p >= 3 && s[2] == '?' )
+#define egt( ) (p == 3 && s[2] == '>' )
+#define Xpe (ppos>=2 && pbuf[1] == ']' )
+#define Xte (Xpe && cc == 7 )
+#define ces(C) ( cc < 256 && (tbl[ cc ] & (C)) == (C) && !Xte)
+
+#define ESC 27
+#define CNTL(c) ((c)-'@')
+
+// process an incoming unicode character
+
+void TEmuVt102::onRcvChar(int cc)
+{ int i;
+
+ if (cc == 127) return; //VT100: ignore.
+
+ if (ces( CTL))
+ { // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100
+ // This means, they do neither a resetToken nor a pushToToken. Some of them, do
+ // of course. Guess this originates from a weakly layered handling of the X-on
+ // X-off protocol, which comes really below this level.
+ if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC) resetToken(); //VT100: CAN or SUB
+ if (cc != ESC) { tau( TY_CTL___(cc+'@' ), 0, 0); return; }
+ }
+
+ pushToToken(cc); // advance the state
+
+ int* s = pbuf;
+ int p = ppos;
+
+ if (getMode(MODE_Ansi)) // decide on proper action
+ {
+ if (lec(1,0,ESC)) { return; }
+ if (les(2,1,GRP)) { return; }
+ if (Xte ) { XtermHack(); resetToken(); return; }
+ if (Xpe ) { return; }
+ if (lec(3,2,'?')) { return; }
+ if (lec(3,2,'>')) { return; }
+ if (lun( )) { tau( TY_CHR___(), applyCharset(cc), 0); resetToken(); return; }
+ if (lec(2,0,ESC)) { tau( TY_ESC___(s[1]), 0, 0); resetToken(); return; }
+ if (les(3,1,SCS)) { tau( TY_ESC_CS(s[1],s[2]), 0, 0); resetToken(); return; }
+ if (lec(3,1,'#')) { tau( TY_ESC_DE(s[2]), 0, 0); resetToken(); return; }
+// if (egt( )) { tau( TY_CSI_PG(cc ), '>', 0); resetToken(); return; }
+ if (eps( CPN)) { tau( TY_CSI_PN(cc), argv[0],argv[1]); resetToken(); return; }
+ if (ees( DIG)) { addDigit(cc-'0'); return; }
+ if (eec( ';')) { addArgument(); return; }
+ for (i=0;i<=argc;i++)
+ if (epp( )) tau( TY_CSI_PR(cc,argv[i]), 0, 0); else
+ tau( TY_CSI_PS(cc,argv[i]), 0, 0);
+ resetToken();
+ }
+ else // mode VT52
+ {
+ if (lec(1,0,ESC)) return;
+ if (les(1,0,CHR)) { tau( TY_CHR___( ), s[0], 0); resetToken(); return; }
+ if (lec(2,1,'Y')) return;
+ if (lec(3,1,'Y')) return;
+ if (p < 4) { tau( TY_VT52__(s[1] ), 0, 0); resetToken(); return; }
+ tau( TY_VT52__(s[1] ), s[2],s[3]); resetToken(); return;
+ }
+}
+
+void TEmuVt102::XtermHack()
+{ int i,arg = 0;
+ for (i = 2; i < ppos && '0'<=pbuf[i] && pbuf[i]<'9' ; i++)
+ arg = 10*arg + (pbuf[i]-'0');
+ if (pbuf[i] != ';') { ReportErrorToken(); return; }
+ QChar *str = new QChar[ppos-i-2];
+ for (int j = 0; j < ppos-i-2; j++) str[j] = pbuf[i+1+j];
+ QString unistr(str,ppos-i-2);
+ // arg == 1 doesn't change the title. In XTerm it only changes the icon name
+ // (btw: arg=0 changes title and icon, arg=1 only icon, arg=2 only title
+ if (arg == 0 || arg == 2) emit changeTitle(arg,unistr);
+ delete [] str;
+}
+
+// Interpreting Codes ---------------------------------------------------------
+
+/*
+ Now that the incoming character stream is properly tokenized,
+ meaning is assigned to them. These are either operations of
+ the current screen, or of the emulation class itself.
+
+ The token to be interpreteted comes in as a machine word
+ possibly accompanied by two parameters.
+
+ Likewise, the operations assigned to, come with up to two
+ arguments. One could consider to make up a proper table
+ from the function below.
+
+ The technical reference manual provides more informations
+ about this mapping.
+*/
+
+void TEmuVt102::tau( int token, int p, int q )
+{
+//scan_buffer_report();
+//if (token == TY_CHR___()) printf("%c",p); else
+//printf("tau(%d,%d,%d, %d,%d)\n",(token>>0)&0xff,(token>>8)&0xff,(token>>16)&0xffff,p,q);
+ switch (token)
+ {
+
+ case TY_CHR___( ) : scr->ShowCharacter (p ); break; //UTF16
+
+ // 127 DEL : ignored on input
+
+ case TY_CTL___('@' ) : /* NUL: ignored */ break;
+ case TY_CTL___('A' ) : /* SOH: ignored */ break;
+ case TY_CTL___('B' ) : /* STX: ignored */ break;
+ case TY_CTL___('C' ) : /* ETX: ignored */ break;
+ case TY_CTL___('D' ) : /* EOT: ignored */ break;
+ case TY_CTL___('E' ) : reportAnswerBack ( ); break; //VT100
+ case TY_CTL___('F' ) : /* ACK: ignored */ break;
+ case TY_CTL___('G' ) : gui->Bell ( ); break; //VT100
+ case TY_CTL___('H' ) : scr->BackSpace ( ); break; //VT100
+ case TY_CTL___('I' ) : scr->Tabulate ( ); break; //VT100
+ case TY_CTL___('J' ) : scr->NewLine ( ); break; //VT100
+ case TY_CTL___('K' ) : scr->NewLine ( ); break; //VT100
+ case TY_CTL___('L' ) : scr->NewLine ( ); break; //VT100
+ case TY_CTL___('M' ) : scr->Return ( ); break; //VT100
+
+ case TY_CTL___('N' ) : useCharset ( 1); break; //VT100
+ case TY_CTL___('O' ) : useCharset ( 0); break; //VT100
+
+ case TY_CTL___('P' ) : /* DLE: ignored */ break;
+ case TY_CTL___('Q' ) : /* DC1: XON continue */ break; //VT100
+ case TY_CTL___('R' ) : /* DC2: ignored */ break;
+ case TY_CTL___('S' ) : /* DC3: XOFF halt */ break; //VT100
+ case TY_CTL___('T' ) : /* DC4: ignored */ break;
+ case TY_CTL___('U' ) : /* NAK: ignored */ break;
+ case TY_CTL___('V' ) : /* SYN: ignored */ break;
+ case TY_CTL___('W' ) : /* ETB: ignored */ break;
+ case TY_CTL___('X' ) : scr->ShowCharacter ( 0x2592); break; //VT100
+ case TY_CTL___('Y' ) : /* EM : ignored */ break;
+ case TY_CTL___('Z' ) : scr->ShowCharacter ( 0x2592); break; //VT100
+ case TY_CTL___('[' ) : /* ESC: cannot be seen here. */ break;
+ case TY_CTL___('\\' ) : /* FS : ignored */ break;
+ case TY_CTL___(']' ) : /* GS : ignored */ break;
+ case TY_CTL___('^' ) : /* RS : ignored */ break;
+ case TY_CTL___('_' ) : /* US : ignored */ break;
+
+ case TY_ESC___('D' ) : scr->index ( ); break; //VT100
+ case TY_ESC___('E' ) : scr->NextLine ( ); break; //VT100
+ case TY_ESC___('H' ) : scr->changeTabStop (TRUE ); break; //VT100
+ case TY_ESC___('M' ) : scr->reverseIndex ( ); break; //VT100
+ case TY_ESC___('Z' ) : reportTerminalType ( ); break;
+ case TY_ESC___('c' ) : reset ( ); break;
+
+ case TY_ESC___('n' ) : useCharset ( 2); break;
+ case TY_ESC___('o' ) : useCharset ( 3); break;
+ case TY_ESC___('7' ) : saveCursor ( ); break;
+ case TY_ESC___('8' ) : restoreCursor ( ); break;
+
+ case TY_ESC___('=' ) : setMode (MODE_AppKeyPad); break;
+ case TY_ESC___('>' ) : resetMode (MODE_AppKeyPad); break;
+ case TY_ESC___('<' ) : setMode (MODE_Ansi ); break; //VT100
+
+ case TY_ESC_CS('(', '0') : setCharset (0, '0'); break; //VT100
+ case TY_ESC_CS('(', 'A') : setCharset (0, 'A'); break; //VT100
+ case TY_ESC_CS('(', 'B') : setCharset (0, 'B'); break; //VT100
+
+ case TY_ESC_CS(')', '0') : setCharset (1, '0'); break; //VT100
+ case TY_ESC_CS(')', 'A') : setCharset (1, 'A'); break; //VT100
+ case TY_ESC_CS(')', 'B') : setCharset (1, 'B'); break; //VT100
+
+ case TY_ESC_CS('*', '0') : setCharset (2, '0'); break; //VT100
+ case TY_ESC_CS('*', 'A') : setCharset (2, 'A'); break; //VT100
+ case TY_ESC_CS('*', 'B') : setCharset (2, 'B'); break; //VT100
+
+ case TY_ESC_CS('+', '0') : setCharset (3, '0'); break; //VT100
+ case TY_ESC_CS('+', 'A') : setCharset (3, 'A'); break; //VT100
+ case TY_ESC_CS('+', 'B') : setCharset (3, 'B'); break; //VT100
+
+ case TY_ESC_CS('%', 'G') : setCodec (1 ); break; //LINUX
+ case TY_ESC_CS('%', '@') : setCodec (0 ); break; //LINUX
+
+ case TY_ESC_DE('3' ) : /* IGNORED: double high, top half */ break;
+ case TY_ESC_DE('4' ) : /* IGNORED: double high, bottom half */ break;
+ case TY_ESC_DE('5' ) : /* IGNORED: single width, single high*/ break;
+ case TY_ESC_DE('6' ) : /* IGNORED: double width, single high*/ break;
+ case TY_ESC_DE('8' ) : scr->helpAlign ( ); break;
+
+ case TY_CSI_PS('K', 0) : scr->clearToEndOfLine ( ); break;
+ case TY_CSI_PS('K', 1) : scr->clearToBeginOfLine ( ); break;
+ case TY_CSI_PS('K', 2) : scr->clearEntireLine ( ); break;
+ case TY_CSI_PS('J', 0) : scr->clearToEndOfScreen ( ); break;
+ case TY_CSI_PS('J', 1) : scr->clearToBeginOfScreen ( ); break;
+ case TY_CSI_PS('J', 2) : scr->clearEntireScreen ( ); break;
+ case TY_CSI_PS('g', 0) : scr->changeTabStop (FALSE ); break; //VT100
+ case TY_CSI_PS('g', 3) : scr->clearTabStops ( ); break; //VT100
+ case TY_CSI_PS('h', 4) : scr-> setMode (MODE_Insert ); break;
+ case TY_CSI_PS('h', 20) : setMode (MODE_NewLine ); break;
+ case TY_CSI_PS('i', 0) : /* IGNORE: attached printer */ break; //VT100
+ case TY_CSI_PS('l', 4) : scr-> resetMode (MODE_Insert ); break;
+ case TY_CSI_PS('l', 20) : resetMode (MODE_NewLine ); break;
+
+ case TY_CSI_PS('m', 0) : scr->setDefaultRendition ( ); break;
+ case TY_CSI_PS('m', 1) : scr-> setRendition (RE_BOLD ); break; //VT100
+ case TY_CSI_PS('m', 4) : scr-> setRendition (RE_UNDERLINE); break; //VT100
+ case TY_CSI_PS('m', 5) : scr-> setRendition (RE_BLINK ); break; //VT100
+ case TY_CSI_PS('m', 7) : scr-> setRendition (RE_REVERSE ); break;
+ case TY_CSI_PS('m', 10) : /* IGNORED: mapping related */ break; //LINUX
+ case TY_CSI_PS('m', 11) : /* IGNORED: mapping related */ break; //LINUX
+ case TY_CSI_PS('m', 12) : /* IGNORED: mapping related */ break; //LINUX
+ case TY_CSI_PS('m', 22) : scr->resetRendition (RE_BOLD ); break;
+ case TY_CSI_PS('m', 24) : scr->resetRendition (RE_UNDERLINE); break;
+ case TY_CSI_PS('m', 25) : scr->resetRendition (RE_BLINK ); break;
+ case TY_CSI_PS('m', 27) : scr->resetRendition (RE_REVERSE ); break;
+
+ case TY_CSI_PS('m', 30) : scr->setForeColor ( 0); break;
+ case TY_CSI_PS('m', 31) : scr->setForeColor ( 1); break;
+ case TY_CSI_PS('m', 32) : scr->setForeColor ( 2); break;
+ case TY_CSI_PS('m', 33) : scr->setForeColor ( 3); break;
+ case TY_CSI_PS('m', 34) : scr->setForeColor ( 4); break;
+ case TY_CSI_PS('m', 35) : scr->setForeColor ( 5); break;
+ case TY_CSI_PS('m', 36) : scr->setForeColor ( 6); break;
+ case TY_CSI_PS('m', 37) : scr->setForeColor ( 7); break;
+ case TY_CSI_PS('m', 39) : scr->setForeColorToDefault( ); break;
+
+ case TY_CSI_PS('m', 40) : scr->setBackColor ( 0); break;
+ case TY_CSI_PS('m', 41) : scr->setBackColor ( 1); break;
+ case TY_CSI_PS('m', 42) : scr->setBackColor ( 2); break;
+ case TY_CSI_PS('m', 43) : scr->setBackColor ( 3); break;
+ case TY_CSI_PS('m', 44) : scr->setBackColor ( 4); break;
+ case TY_CSI_PS('m', 45) : scr->setBackColor ( 5); break;
+ case TY_CSI_PS('m', 46) : scr->setBackColor ( 6); break;
+ case TY_CSI_PS('m', 47) : scr->setBackColor ( 7); break;
+ case TY_CSI_PS('m', 49) : scr->setBackColorToDefault( ); break;
+
+ case TY_CSI_PS('m', 90) : scr->setForeColor ( 8); break;
+ case TY_CSI_PS('m', 91) : scr->setForeColor ( 9); break;
+ case TY_CSI_PS('m', 92) : scr->setForeColor ( 10); break;
+ case TY_CSI_PS('m', 93) : scr->setForeColor ( 11); break;
+ case TY_CSI_PS('m', 94) : scr->setForeColor ( 12); break;
+ case TY_CSI_PS('m', 95) : scr->setForeColor ( 13); break;
+ case TY_CSI_PS('m', 96) : scr->setForeColor ( 14); break;
+ case TY_CSI_PS('m', 97) : scr->setForeColor ( 15); break;
+
+ case TY_CSI_PS('m', 100) : scr->setBackColor ( 8); break;
+ case TY_CSI_PS('m', 101) : scr->setBackColor ( 9); break;
+ case TY_CSI_PS('m', 102) : scr->setBackColor ( 10); break;
+ case TY_CSI_PS('m', 103) : scr->setBackColor ( 11); break;
+ case TY_CSI_PS('m', 104) : scr->setBackColor ( 12); break;
+ case TY_CSI_PS('m', 105) : scr->setBackColor ( 13); break;
+ case TY_CSI_PS('m', 106) : scr->setBackColor ( 14); break;
+ case TY_CSI_PS('m', 107) : scr->setBackColor ( 15); break;
+
+ case TY_CSI_PS('n', 5) : reportStatus ( ); break;
+ case TY_CSI_PS('n', 6) : reportCursorPosition ( ); break;
+ case TY_CSI_PS('q', 0) : /* IGNORED: LEDs off */ break; //VT100
+ case TY_CSI_PS('q', 1) : /* IGNORED: LED1 on */ break; //VT100
+ case TY_CSI_PS('q', 2) : /* IGNORED: LED2 on */ break; //VT100
+ case TY_CSI_PS('q', 3) : /* IGNORED: LED3 on */ break; //VT100
+ case TY_CSI_PS('q', 4) : /* IGNORED: LED4 on */ break; //VT100
+ case TY_CSI_PS('x', 0) : reportTerminalParms ( 2); break; //VT100
+ case TY_CSI_PS('x', 1) : reportTerminalParms ( 3); break; //VT100
+
+ case TY_CSI_PN('@' ) : scr->insertChars (p ); break;
+ case TY_CSI_PN('A' ) : scr->cursorUp (p ); break; //VT100
+ case TY_CSI_PN('B' ) : scr->cursorDown (p ); break; //VT100
+ case TY_CSI_PN('C' ) : scr->cursorRight (p ); break; //VT100
+ case TY_CSI_PN('D' ) : scr->cursorLeft (p ); break; //VT100
+ case TY_CSI_PN('G' ) : scr->setCursorX (p ); break; //LINUX
+ case TY_CSI_PN('H' ) : scr->setCursorYX (p, q); break; //VT100
+ case TY_CSI_PN('L' ) : scr->insertLines (p ); break;
+ case TY_CSI_PN('M' ) : scr->deleteLines (p ); break;
+ case TY_CSI_PN('P' ) : scr->deleteChars (p ); break;
+ case TY_CSI_PN('X' ) : scr->eraseChars (p ); break;
+ case TY_CSI_PN('c' ) : reportTerminalType ( ); break; //VT100
+ case TY_CSI_PN('d' ) : scr->setCursorY (p ); break; //LINUX
+ case TY_CSI_PN('f' ) : scr->setCursorYX (p, q); break; //VT100
+ case TY_CSI_PN('r' ) : scr->setMargins (p, q); break; //VT100
+ case TY_CSI_PN('y' ) : /* IGNORED: Confidence test */ break; //VT100
+
+ case TY_CSI_PR('h', 1) : setMode (MODE_AppCuKeys); break; //VT100
+ case TY_CSI_PR('l', 1) : resetMode (MODE_AppCuKeys); break; //VT100
+ case TY_CSI_PR('s', 1) : saveMode (MODE_AppCuKeys); break; //FIXME
+ case TY_CSI_PR('r', 1) : restoreMode (MODE_AppCuKeys); break; //FIXME
+
+ case TY_CSI_PR('l', 2) : resetMode (MODE_Ansi ); break; //VT100
+
+ case TY_CSI_PR('h', 3) : setColumns ( 132); break; //VT100
+ case TY_CSI_PR('l', 3) : setColumns ( 80); break; //VT100
+
+ case TY_CSI_PR('h', 4) : /* IGNORED: soft scrolling */ break; //VT100
+ case TY_CSI_PR('l', 4) : /* IGNORED: soft scrolling */ break; //VT100
+
+ case TY_CSI_PR('h', 5) : scr-> setMode (MODE_Screen ); break; //VT100
+ case TY_CSI_PR('l', 5) : scr-> resetMode (MODE_Screen ); break; //VT100
+
+ case TY_CSI_PR('h', 6) : scr-> setMode (MODE_Origin ); break; //VT100
+ case TY_CSI_PR('l', 6) : scr-> resetMode (MODE_Origin ); break; //VT100
+ case TY_CSI_PR('s', 6) : scr-> saveMode (MODE_Origin ); break; //FIXME
+ case TY_CSI_PR('r', 6) : scr->restoreMode (MODE_Origin ); break; //FIXME
+
+ case TY_CSI_PR('h', 7) : scr-> setMode (MODE_Wrap ); break; //VT100
+ case TY_CSI_PR('l', 7) : scr-> resetMode (MODE_Wrap ); break; //VT100
+ case TY_CSI_PR('s', 7) : scr-> saveMode (MODE_Wrap ); break; //FIXME
+ case TY_CSI_PR('r', 7) : scr->restoreMode (MODE_Wrap ); break; //FIXME
+
+ case TY_CSI_PR('h', 8) : /* IGNORED: autorepeat on */ break; //VT100
+ case TY_CSI_PR('l', 8) : /* IGNORED: autorepeat off */ break; //VT100
+
+ case TY_CSI_PR('h', 9) : /* IGNORED: interlace */ break; //VT100
+ case TY_CSI_PR('l', 9) : /* IGNORED: interlace */ break; //VT100
+
+ case TY_CSI_PR('h', 25) : setMode (MODE_Cursor ); break; //VT100
+ case TY_CSI_PR('l', 25) : resetMode (MODE_Cursor ); break; //VT100
+
+ case TY_CSI_PR('h', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
+ case TY_CSI_PR('l', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
+ case TY_CSI_PR('s', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
+ case TY_CSI_PR('r', 41) : /* IGNORED: obsolete more(1) fix */ break; //XTERM
+
+ case TY_CSI_PR('h', 47) : setMode (MODE_AppScreen); break; //VT100
+ case TY_CSI_PR('l', 47) : resetMode (MODE_AppScreen); break; //VT100
+
+ case TY_CSI_PR('h', 1000) : setMode (MODE_Mouse1000); break; //XTERM
+ case TY_CSI_PR('l', 1000) : resetMode (MODE_Mouse1000); break; //XTERM
+ case TY_CSI_PR('s', 1000) : saveMode (MODE_Mouse1000); break; //XTERM
+ case TY_CSI_PR('r', 1000) : restoreMode (MODE_Mouse1000); break; //XTERM
+
+ case TY_CSI_PR('h', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
+ case TY_CSI_PR('l', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
+ case TY_CSI_PR('s', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
+ case TY_CSI_PR('r', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM
+
+ case TY_CSI_PR('h', 1047) : setMode (MODE_AppScreen); break; //XTERM
+ case TY_CSI_PR('l', 1047) : resetMode (MODE_AppScreen); break; //XTERM
+
+ //FIXME: Unitoken: save translations
+ case TY_CSI_PR('h', 1048) : saveCursor ( ); break; //XTERM
+ case TY_CSI_PR('l', 1048) : restoreCursor ( ); break; //XTERM
+
+ //FIXME: every once new sequences like this pop up in xterm.
+ // Here's a guess of what they could mean.
+ case TY_CSI_PR('h', 1049) : setMode (MODE_AppScreen); break; //XTERM
+ case TY_CSI_PR('l', 1049) : resetMode (MODE_AppScreen); break; //XTERM
+
+ //FIXME: when changing between vt52 and ansi mode evtl do some resetting.
+ case TY_VT52__('A' ) : scr->cursorUp ( 1); break; //VT52
+ case TY_VT52__('B' ) : scr->cursorDown ( 1); break; //VT52
+ case TY_VT52__('C' ) : scr->cursorRight ( 1); break; //VT52
+ case TY_VT52__('D' ) : scr->cursorLeft ( 1); break; //VT52
+
+ case TY_VT52__('F' ) : setAndUseCharset (0, '0'); break; //VT52
+ case TY_VT52__('G' ) : setAndUseCharset (0, 'B'); break; //VT52
+
+ case TY_VT52__('H' ) : scr->setCursorYX (1,1 ); break; //VT52
+ case TY_VT52__('I' ) : scr->reverseIndex ( ); break; //VT52
+ case TY_VT52__('J' ) : scr->clearToEndOfScreen ( ); break; //VT52
+ case TY_VT52__('K' ) : scr->clearToEndOfLine ( ); break; //VT52
+ case TY_VT52__('Y' ) : scr->setCursorYX (p-31,q-31 ); break; //VT52
+ case TY_VT52__('Z' ) : reportTerminalType ( ); break; //VT52
+ case TY_VT52__('<' ) : setMode (MODE_Ansi ); break; //VT52
+ case TY_VT52__('=' ) : setMode (MODE_AppKeyPad); break; //VT52
+ case TY_VT52__('>' ) : resetMode (MODE_AppKeyPad); break; //VT52
+
+ default : ReportErrorToken(); break;
+ };
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Terminal to Host protocol */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*
+ Outgoing bytes originate from several sources:
+
+ - Replies to Enquieries.
+ - Mouse Events
+ - Keyboard Events
+*/
+
+/*!
+*/
+
+void TEmuVt102::sendString(const char* s)
+{
+ emit sndBlock(s,strlen(s));
+}
+
+// Replies ----------------------------------------------------------------- --
+
+// This section copes with replies send as response to an enquiery control code.
+
+/*!
+*/
+
+void TEmuVt102::reportCursorPosition()
+{ char tmp[20];
+ sprintf(tmp,"\033[%d;%dR",scr->getCursorY()+1,scr->getCursorX()+1);
+ sendString(tmp);
+}
+
+/*
+ What follows here is rather obsolete and faked stuff.
+ The correspondent enquieries are neverthenless issued.
+*/
+
+/*!
+*/
+
+void TEmuVt102::reportTerminalType()
+{
+//FIXME: should change?
+ if (getMode(MODE_Ansi))
+// sendString("\033[?1;2c"); // I'm a VT100 with AP0 //FIXME: send only in response to ^[[0c
+ sendString("\033[>0;115;0c"); // I'm a VT220 //FIXME: send only in response to ^[[>c
+ else
+ sendString("\033/Z"); // I'm a VT52
+}
+
+void TEmuVt102::reportTerminalParms(int p)
+// DECREPTPARM
+{ char tmp[100];
+ sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true.
+ sendString(tmp);
+}
+
+/*!
+*/
+
+void TEmuVt102::reportStatus()
+{
+ sendString("\033[0n"); //VT100. Device status report. 0 = Ready.
+}
+
+/*!
+*/
+
+#define ANSWER_BACK "" // This is really obsolete VT100 stuff.
+
+void TEmuVt102::reportAnswerBack()
+{
+ sendString(ANSWER_BACK);
+}
+
+// Mouse Handling ---------------------------------------------------------- --
+
+/*!
+ Mouse clicks are possibly reported to the client
+ application if it has issued interest in them.
+ They are normally consumed by the widget for copy
+ and paste, but may be propagated from the widget
+ when gui->setMouseMarks is set via setMode(MODE_Mouse1000).
+
+ `x',`y' are 1-based.
+ `ev' (event) indicates the button pressed (0-2)
+ or a general mouse release (3).
+*/
+
+void TEmuVt102::onMouse( int cb, int cx, int cy )
+{ char tmp[20];
+ if (!connected) return;
+ sprintf(tmp,"\033[M%c%c%c",cb+040,cx+040,cy+040);
+ sendString(tmp);
+}
+
+// Keyboard Handling ------------------------------------------------------- --
+
+#define encodeMode(M,B) BITS(B,getMode(M))
+#define encodeStat(M,B) BITS(B,((ev->state() & (M)) == (M)))
+
+/*
+ Keyboard event handling has been simplified somewhat by pushing
+ the complications towards a configuration file [see KeyTrans class].
+*/
+
+void TEmuVt102::onKeyPress( QKeyEvent* ev )
+{
+ if (!connected) return; // someone else gets the keys
+
+//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);
+
+ // revert to non-history when typing
+ if (scr->getHistCursor() != scr->getHistLines());
+ scr->setHistCursor(scr->getHistLines());
+
+ // lookup in keyboard translation table ...
+ int cmd; const char* txt; int len;
+ if (keytrans->findEntry(ev->key(), encodeMode(MODE_NewLine , BITS_NewLine ) + // OLD,
+ encodeMode(MODE_Ansi , BITS_Ansi ) + // OBSOLETE,
+ encodeMode(MODE_AppCuKeys, BITS_AppCuKeys ) + // VT100 stuff
+ encodeStat(ControlButton , BITS_Control ) +
+ encodeStat(ShiftButton , BITS_Shift ) +
+ encodeStat(AltButton , BITS_Alt ),
+ &cmd, &txt, &len ))
+//printf("cmd: %d, %s, %d\n",cmd,txt,len);
+ switch(cmd) // ... and execute if found.
+ {
+ case CMD_emitSelection : gui->emitSelection(); return;
+ case CMD_scrollPageUp : gui->doScroll(-gui->Lines()/2); return;
+ case CMD_scrollPageDown : gui->doScroll(+gui->Lines()/2); return;
+ case CMD_scrollLineUp : gui->doScroll(-1 ); return;
+ case CMD_scrollLineDown : gui->doScroll(+1 ); return;
+ case CMD_send : emit sndBlock(txt,len); return;
+ case CMD_prevSession : emit prevSession(); return;
+ case CMD_nextSession : emit nextSession(); return;
+ }
+
+ // fall back handling
+ if (!ev->text().isEmpty())
+ {
+ if (ev->state() & AltButton) sendString("\033"); // ESC, this is the ALT prefix
+ /// very hacky
+ if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='A')) sendString("\01");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='B')) sendString("\02");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='C')) sendString("\03");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='D')) sendString("\04");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='E')) sendString("\05");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='F')) sendString("\06");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='G')) sendString("\07");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='H')) sendString("\010");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='I')) sendString("\011");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='J')) sendString("\012");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='K')) sendString("\013");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='L')) sendString("\014");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='M')) sendString("\015");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='N')) sendString("\016");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='O')) sendString("\017");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='P')) sendString("\020");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='Q')) sendString("\021");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='R')) sendString("\022");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='S')) sendString("\023");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='T')) sendString("\024");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='U')) sendString("\025");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='V')) sendString("\026");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='W')) sendString("\027");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='X')) sendString("\030");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='Y')) sendString("\031");
+ else if ((ev->state() & ControlButton) && (ev->text().upper().ascii()[0]=='Z')) sendString("\032");
+ else {
+ QCString s = codec->fromUnicode(ev->text()); // encode for application
+ emit sndBlock(s.data(),s.length()); // we may well have s.length() > 1
+ }
+ return;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* VT100 Charsets */
+/* */
+/* ------------------------------------------------------------------------- */
+
+// Character Set Conversion ------------------------------------------------ --
+
+/*
+ The processing contains a VT100 specific code translation layer.
+ It's still in use and mainly responsible for the line drawing graphics.
+
+ These and some other glyphs are assigned to codes (0x5f-0xfe)
+ normally occupied by the latin letters. Since this codes also
+ appear within control sequences, the extra code conversion
+ does not permute with the tokenizer and is placed behind it
+ in the pipeline. It only applies to tokens, which represent
+ plain characters.
+
+ This conversion it eventually continued in TEWidget.C, since
+ it might involve VT100 enhanced fonts, which have these
+ particular glyphs allocated in (0x00-0x1f) in their code page.
+*/
+
+#define CHARSET charset[scr==screen[1]]
+
+// Apply current character map.
+
+unsigned short TEmuVt102::applyCharset(unsigned short c)
+{
+ if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f];
+ if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete
+ return c;
+}
+
+/*
+ "Charset" related part of the emulation state.
+ This configures the VT100 charset filter.
+
+ While most operation work on the current screen,
+ the following two are different.
+*/
+
+void TEmuVt102::resetCharset(int scrno)
+{
+ charset[scrno].cu_cs = 0;
+ strncpy(charset[scrno].charset,"BBBB",4);
+ charset[scrno].sa_graphic = FALSE;
+ charset[scrno].sa_pound = FALSE;
+ charset[scrno].graphic = FALSE;
+ charset[scrno].pound = FALSE;
+}
+
+/*!
+*/
+
+void TEmuVt102::setCharset(int n, int cs) // on both screens.
+{
+ charset[0].charset[n&3] = cs; useCharset(charset[0].cu_cs);
+ charset[1].charset[n&3] = cs; useCharset(charset[1].cu_cs);
+}
+
+/*!
+*/
+
+void TEmuVt102::setAndUseCharset(int n, int cs)
+{
+ CHARSET.charset[n&3] = cs;
+ useCharset(n&3);
+}
+
+/*!
+*/
+
+void TEmuVt102::useCharset(int n)
+{
+ CHARSET.cu_cs = n&3;
+ CHARSET.graphic = (CHARSET.charset[n&3] == '0');
+ CHARSET.pound = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete
+}
+
+/*! Save the cursor position and the rendition attribute settings. */
+
+void TEmuVt102::saveCursor()
+{
+ CHARSET.sa_graphic = CHARSET.graphic;
+ CHARSET.sa_pound = CHARSET.pound; //This mode is obsolete
+ // we are not clear about these
+ //sa_charset = charsets[cScreen->charset];
+ //sa_charset_num = cScreen->charset;
+ scr->saveCursor();
+}
+
+/*! Restore the cursor position and the rendition attribute settings. */
+
+void TEmuVt102::restoreCursor()
+{
+ CHARSET.graphic = CHARSET.sa_graphic;
+ CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete
+ scr->restoreCursor();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Mode Operations */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*
+ Some of the emulations state is either added to the state of the screens.
+
+ This causes some scoping problems, since different emulations choose to
+ located the mode either to the current screen or to both.
+
+ For strange reasons, the extend of the rendition attributes ranges over
+ all screens and not over the actual screen.
+
+ We decided on the precise precise extend, somehow.
+*/
+
+// "Mode" related part of the state. These are all booleans.
+
+void TEmuVt102::resetModes()
+{
+ resetMode(MODE_Mouse1000); saveMode(MODE_Mouse1000);
+ resetMode(MODE_AppScreen); saveMode(MODE_AppScreen);
+ // here come obsolete modes
+ resetMode(MODE_AppCuKeys); saveMode(MODE_AppCuKeys);
+ resetMode(MODE_NewLine );
+ setMode(MODE_Ansi );
+}
+
+void TEmuVt102::setMode(int m)
+{
+ currParm.mode[m] = TRUE;
+ switch (m)
+ {
+ case MODE_Mouse1000 : gui->setMouseMarks(FALSE);
+ break;
+ case MODE_AppScreen : screen[1]->clearSelection();
+ screen[1]->clearEntireScreen();
+ setScreen(1);
+ break;
+ }
+ if (m < MODES_SCREEN || m == MODE_NewLine)
+ {
+ screen[0]->setMode(m);
+ screen[1]->setMode(m);
+ }
+}
+
+void TEmuVt102::resetMode(int m)
+{
+ currParm.mode[m] = FALSE;
+ switch (m)
+ {
+ case MODE_Mouse1000 : gui->setMouseMarks(TRUE);
+ break;
+ case MODE_AppScreen : screen[0]->clearSelection();
+ setScreen(0);
+ break;
+ }
+ if (m < MODES_SCREEN || m == MODE_NewLine)
+ {
+ screen[0]->resetMode(m);
+ screen[1]->resetMode(m);
+ }
+}
+
+void TEmuVt102::saveMode(int m)
+{
+ saveParm.mode[m] = currParm.mode[m];
+}
+
+void TEmuVt102::restoreMode(int m)
+{
+ if(saveParm.mode[m]) setMode(m); else resetMode(m);
+}
+
+BOOL TEmuVt102::getMode(int m)
+{
+ return currParm.mode[m];
+}
+
+void TEmuVt102::setConnect(bool c)
+{
+ TEmulation::setConnect(c);
+ if (c)
+ { // refresh mouse mode
+ if (getMode(MODE_Mouse1000))
+ setMode(MODE_Mouse1000);
+ else
+ resetMode(MODE_Mouse1000);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Diagnostic */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*! shows the contents of the scan buffer.
+
+ This functions is used for diagnostics. It is called by \e ReportErrorToken
+ to inform about strings that cannot be decoded or handled by the emulation.
+
+ \sa ReportErrorToken
+*/
+
+/*!
+*/
+
+static void hexdump(int* s, int len)
+{ int i;
+ for (i = 0; i < len; i++)
+ {
+ if (s[i] == '\\')
+ printf("\\\\");
+ else
+ if ((s[i]) > 32 && s[i] < 127)
+ printf("%c",s[i]);
+ else
+ printf("\\%04x(hex)",s[i]);
+ }
+}
+
+void TEmuVt102::scan_buffer_report()
+{
+ if (ppos == 0 || ppos == 1 && (pbuf[0] & 0xff) >= 32) return;
+ printf("token: "); hexdump(pbuf,ppos); printf("\n");
+}
+
+/*!
+*/
+
+void TEmuVt102::ReportErrorToken()
+{
+ printf("undecodable "); scan_buffer_report();
+}
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 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [TEmuVt102.h] X Terminal Emulation */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
+/* */
+/* This file is part of Konsole - an X terminal for KDE */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Ported Konsole to Qt/Embedded */
+/* */
+/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+#ifndef VT102EMU_H
+#define VT102EMU_H
+
+#include "TEWidget.h"
+#include "TEScreen.h"
+#include "TEmulation.h"
+#include <qtimer.h>
+#include <stdio.h>
+
+//
+
+#define MODE_AppScreen (MODES_SCREEN+0)
+#define MODE_AppCuKeys (MODES_SCREEN+1)
+#define MODE_AppKeyPad (MODES_SCREEN+2)
+#define MODE_Mouse1000 (MODES_SCREEN+3)
+#define MODE_Ansi (MODES_SCREEN+4)
+#define MODE_total (MODES_SCREEN+5)
+
+struct DECpar
+{
+ BOOL mode[MODE_total];
+};
+
+struct CharCodes
+{
+ // coding info
+ char charset[4]; //
+ int cu_cs; // actual charset.
+ bool graphic; // Some VT100 tricks
+ bool pound ; // Some VT100 tricks
+ bool sa_graphic; // saved graphic
+ bool sa_pound; // saved pound
+};
+
+class TEmuVt102 : public TEmulation
+{ Q_OBJECT
+
+public:
+
+ TEmuVt102(TEWidget* gui);
+ ~TEmuVt102();
+
+public slots: // signals incoming from TEWidget
+
+ void onKeyPress(QKeyEvent*);
+ void onMouse(int cb, int cx, int cy);
+
+signals:
+
+ void changeTitle(int,const QString&);
+ void prevSession();
+ void nextSession();
+
+public:
+
+ void reset();
+
+ void onRcvChar(int cc);
+ void sendString(const char *);
+
+public:
+
+ BOOL getMode (int m);
+
+ void setMode (int m);
+ void resetMode (int m);
+ void saveMode (int m);
+ void restoreMode(int m);
+ void resetModes();
+
+ void setConnect(bool r);
+
+private:
+
+ void resetToken();
+#define MAXPBUF 80
+ void pushToToken(int cc);
+ int pbuf[MAXPBUF]; //FIXME: overflow?
+ int ppos;
+#define MAXARGS 15
+ void addDigit(int dig);
+ void addArgument();
+ int argv[MAXARGS];
+ int argc;
+ void initTokenizer();
+ int tbl[256];
+
+ void scan_buffer_report(); //FIXME: rename
+ void ReportErrorToken(); //FIXME: rename
+
+ void tau(int code, int p, int q);
+ void XtermHack();
+
+ //
+
+ void reportTerminalType();
+ void reportStatus();
+ void reportAnswerBack();
+ void reportCursorPosition();
+ void reportTerminalParms(int p);
+
+protected:
+
+ unsigned short applyCharset(unsigned short c);
+ void setCharset(int n, int cs);
+ void useCharset(int n);
+ void setAndUseCharset(int n, int cs);
+ void saveCursor();
+ void restoreCursor();
+ void resetCharset(int scrno);
+ CharCodes charset[2];
+
+ DECpar currParm;
+ DECpar saveParm;
+};
+
+#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 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [TEmulation.cpp] Terminal Emulation Decoder */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
+/* */
+/* This file is part of Konsole - an X terminal for KDE */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Ported Konsole to Qt/Embedded */
+/* */
+/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+/*! \class TEmulation
+
+ \brief Mediator between TEWidget and TEScreen.
+
+ This class is responsible to scan the escapes sequences of the terminal
+ emulation and to map it to their corresponding semantic complements.
+ Thus this module knows mainly about decoding escapes sequences and
+ is a stateless device w.r.t. the semantics.
+
+ It is also responsible to refresh the TEWidget by certain rules.
+
+ \sa TEWidget \sa TEScreen
+
+ \par A note on refreshing
+
+ Although the modifications to the current screen image could immediately
+ be propagated via `TEWidget' to the graphical surface, we have chosen
+ another way here.
+
+ The reason for doing so is twofold.
+
+ First, experiments show that directly displaying the operation results
+ in slowing down the overall performance of emulations. Displaying
+ individual characters using X11 creates a lot of overhead.
+
+ Second, by using the following refreshing method, the screen operations
+ can be completely separated from the displaying. This greatly simplifies
+ the programmer's task of coding and maintaining the screen operations,
+ since one need not worry about differential modifications on the
+ display affecting the operation of concern.
+
+ We use a refreshing algorithm here that has been adoped from rxvt/kvt.
+
+ By this, refreshing is driven by a timer, which is (re)started whenever
+ a new bunch of data to be interpreted by the emulation arives at `onRcvBlock'.
+ As soon as no more data arrive for `BULK_TIMEOUT' milliseconds, we trigger
+ refresh. This rule suits both bulk display operation as done by curses as
+ well as individual characters typed.
+ (BULK_TIMEOUT < 1000 / max characters received from keyboard per second).
+
+ Additionally, we trigger refreshing by newlines comming in to make visual
+ snapshots of lists as produced by `cat', `ls' and likely programs, thereby
+ producing the illusion of a permanent and immediate display operation.
+
+ As a sort of catch-all needed for cases where none of the above
+ conditions catch, the screen refresh is also triggered by a count
+ of incoming bulks (`bulk_incnt').
+*/
+
+/* FIXME
+ - evtl. the bulk operations could be made more transparent.
+*/
+
+#include "TEmulation.h"
+#include "TEWidget.h"
+#include "TEScreen.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <qkeycode.h>
+
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* TEmulation */
+/* */
+/* ------------------------------------------------------------------------- */
+
+#define CNTL(c) ((c)-'@')
+
+/*!
+*/
+
+TEmulation::TEmulation(TEWidget* gui)
+: decoder((QTextDecoder*)NULL)
+{
+ this->gui = gui;
+
+ screen[0] = new TEScreen(gui->Lines(),gui->Columns());
+ screen[1] = new TEScreen(gui->Lines(),gui->Columns());
+ scr = screen[0];
+
+ bulk_nlcnt = 0; // reset bulk newline counter
+ bulk_incnt = 0; // reset bulk counter
+ connected = FALSE;
+
+ QObject::connect(&bulk_timer, SIGNAL(timeout()), this, SLOT(showBulk()) );
+ QObject::connect(gui,SIGNAL(changedImageSizeSignal(int,int)),
+ this,SLOT(onImageSizeChange(int,int)));
+ QObject::connect(gui,SIGNAL(changedHistoryCursor(int)),
+ this,SLOT(onHistoryCursorChange(int)));
+ QObject::connect(gui,SIGNAL(keyPressedSignal(QKeyEvent*)),
+ this,SLOT(onKeyPress(QKeyEvent*)));
+ QObject::connect(gui,SIGNAL(beginSelectionSignal(const int,const int)),
+ this,SLOT(onSelectionBegin(const int,const int)) );
+ QObject::connect(gui,SIGNAL(extendSelectionSignal(const int,const int)),
+ this,SLOT(onSelectionExtend(const int,const int)) );
+ QObject::connect(gui,SIGNAL(endSelectionSignal(const BOOL)),
+ this,SLOT(setSelection(const BOOL)) );
+ QObject::connect(gui,SIGNAL(clearSelectionSignal()),
+ this,SLOT(clearSelection()) );
+}
+
+/*!
+*/
+
+TEmulation::~TEmulation()
+{
+ delete screen[0];
+ delete screen[1];
+ bulk_timer.stop();
+}
+
+/*! change between primary and alternate screen
+*/
+
+void TEmulation::setScreen(int n)
+{
+ scr = screen[n&1];
+}
+
+void TEmulation::setHistory(bool on)
+{
+ screen[0]->setScroll(on);
+ if (!connected) return;
+ showBulk();
+}
+
+bool TEmulation::history()
+{
+ return screen[0]->hasScroll();
+}
+
+void TEmulation::setCodec(int c)
+{
+ //FIXME: check whether we have to free codec
+ codec = c ? QTextCodec::codecForName("utf8")
+ : QTextCodec::codecForLocale();
+ if (decoder) delete decoder;
+ decoder = codec->makeDecoder();
+}
+
+void TEmulation::setKeytrans(int no)
+{
+ keytrans = KeyTrans::find(no);
+}
+
+void TEmulation::setKeytrans(const char * no)
+{
+ keytrans = KeyTrans::find(no);
+}
+
+// Interpreting Codes ---------------------------------------------------------
+
+/*
+ This section deals with decoding the incoming character stream.
+ Decoding means here, that the stream is first seperated into `tokens'
+ which are then mapped to a `meaning' provided as operations by the
+ `Screen' class.
+*/
+
+/*!
+*/
+
+void TEmulation::onRcvChar(int c)
+// process application unicode input to terminal
+// this is a trivial scanner
+{
+ c &= 0xff;
+ switch (c)
+ {
+ case '\b' : scr->BackSpace(); break;
+ case '\t' : scr->Tabulate(); break;
+ case '\n' : scr->NewLine(); break;
+ case '\r' : scr->Return(); break;
+ case 0x07 : gui->Bell(); break;
+ default : scr->ShowCharacter(c); break;
+ };
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Keyboard Handling */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*!
+*/
+
+void TEmulation::onKeyPress( QKeyEvent* ev )
+{
+ if (!connected) return; // someone else gets the keys
+ if (scr->getHistCursor() != scr->getHistLines());
+ scr->setHistCursor(scr->getHistLines());
+ if (!ev->text().isEmpty())
+ { // A block of text
+ // Note that the text is proper unicode.
+ // We should do a conversion here, but since this
+ // routine will never be used, we simply emit plain ascii.
+ emit sndBlock(ev->text().ascii(),ev->text().length());
+ }
+ else if (ev->ascii()>0)
+ { unsigned char c[1];
+ c[0] = ev->ascii();
+ emit sndBlock((char*)c,1);
+ }
+}
+
+// Unblocking, Byte to Unicode translation --------------------------------- --
+
+/*
+ We are doing code conversion from locale to unicode first.
+*/
+
+void TEmulation::onRcvBlock(const char *s, int len)
+{
+ bulkStart();
+ bulk_incnt += 1;
+ for (int i = 0; i < len; i++)
+ {
+ QString result = decoder->toUnicode(&s[i],1);
+ int reslen = result.length();
+ for (int j = 0; j < reslen; j++)
+ onRcvChar(result[j].unicode());
+ if (s[i] == '\n') bulkNewline();
+ }
+ bulkEnd();
+}
+
+// Selection --------------------------------------------------------------- --
+
+void TEmulation::onSelectionBegin(const int x, const int y) {
+ if (!connected) return;
+ scr->setSelBeginXY(x,y);
+ showBulk();
+}
+
+void TEmulation::onSelectionExtend(const int x, const int y) {
+ if (!connected) return;
+ scr->setSelExtentXY(x,y);
+ showBulk();
+}
+
+void TEmulation::setSelection(const BOOL preserve_line_breaks) {
+ if (!connected) return;
+ QString t = scr->getSelText(preserve_line_breaks);
+ if (!t.isNull()) gui->setSelection(t);
+}
+
+void TEmulation::clearSelection() {
+ if (!connected) return;
+ scr->clearSelection();
+ showBulk();
+}
+
+// Refreshing -------------------------------------------------------------- --
+
+#define BULK_TIMEOUT 20
+
+/*!
+ called when \n comes in. Evtl. triggers showBulk at endBulk
+*/
+
+void TEmulation::bulkNewline()
+{
+ bulk_nlcnt += 1;
+ bulk_incnt = 0; // reset bulk counter since `nl' rule applies
+}
+
+/*!
+*/
+
+void TEmulation::showBulk()
+{
+ bulk_nlcnt = 0; // reset bulk newline counter
+ bulk_incnt = 0; // reset bulk counter
+ if (connected)
+ {
+ ca* image = scr->getCookedImage(); // get the image
+ gui->setImage(image,
+ scr->getLines(),
+ scr->getColumns()); // actual refresh
+ free(image);
+ //FIXME: check that we do not trigger other draw event here.
+ gui->setScroll(scr->getHistCursor(),scr->getHistLines());
+ }
+}
+
+void TEmulation::bulkStart()
+{
+ if (bulk_timer.isActive()) bulk_timer.stop();
+}
+
+void TEmulation::bulkEnd()
+{
+ if ( bulk_nlcnt > gui->Lines() || bulk_incnt > 20 )
+ showBulk(); // resets bulk_??cnt to 0, too.
+ else
+ bulk_timer.start(BULK_TIMEOUT,TRUE);
+}
+
+void TEmulation::setConnect(bool c)
+{
+ connected = c;
+ if ( connected)
+ {
+ onImageSizeChange(gui->Lines(), gui->Columns());
+ showBulk();
+ }
+ else
+ {
+ scr->clearSelection();
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+/*! triggered by image size change of the TEWidget `gui'.
+
+ This event is simply propagated to the attached screens
+ and to the related serial line.
+*/
+
+void TEmulation::onImageSizeChange(int lines, int columns)
+{
+ if (!connected) return;
+ screen[0]->resizeImage(lines,columns);
+ screen[1]->resizeImage(lines,columns);
+ showBulk();
+ emit ImageSizeChanged(lines,columns); // propagate event to serial line
+}
+
+void TEmulation::onHistoryCursorChange(int cursor)
+{
+ if (!connected) return;
+ scr->setHistCursor(cursor);
+ showBulk();
+}
+
+void TEmulation::setColumns(int columns)
+{
+ //FIXME: this goes strange ways.
+ // Can we put this straight or explain it at least?
+ emit changeColumns(columns);
+}
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 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [emulation.h] Fundamental Terminal Emulation */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */
+/* */
+/* This file is part of Konsole - an X terminal for KDE */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Ported Konsole to Qt/Embedded */
+/* */
+/* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+#ifndef EMULATION_H
+#define EMULATION_H
+
+#include "TEWidget.h"
+#include "TEScreen.h"
+#include <qtimer.h>
+#include <stdio.h>
+#include <qtextcodec.h>
+#include "keytrans.h"
+
+class TEmulation : public QObject
+{ Q_OBJECT
+
+public:
+
+ TEmulation(TEWidget* gui);
+ ~TEmulation();
+
+public:
+ virtual void setHistory(bool on);
+ virtual bool history();
+
+public slots: // signals incoming from TEWidget
+
+ virtual void onImageSizeChange(int lines, int columns);
+ virtual void onHistoryCursorChange(int cursor);
+ virtual void onKeyPress(QKeyEvent*);
+
+ virtual void clearSelection();
+ virtual void onSelectionBegin(const int x, const int y);
+ virtual void onSelectionExtend(const int x, const int y);
+ virtual void setSelection(const BOOL preserve_line_breaks);
+
+public slots: // signals incoming from data source
+
+ void onRcvBlock(const char* txt,int len);
+
+signals:
+
+ void sndBlock(const char* txt,int len);
+ void ImageSizeChanged(int lines, int columns);
+ void changeColumns(int columns);
+ void changeTitle(int arg, const char* str);
+
+public:
+
+ virtual void onRcvChar(int);
+
+ virtual void setMode (int) = 0;
+ virtual void resetMode(int) = 0;
+
+ virtual void sendString(const char*) = 0;
+
+ virtual void setConnect(bool r);
+ void setColumns(int columns);
+
+ void setKeytrans(int no);
+ void setKeytrans(const char * no);
+
+protected:
+
+ TEWidget* gui;
+ TEScreen* scr; // referes to one `screen'
+ TEScreen* screen[2]; // 0 = primary, 1 = alternate
+ void setScreen(int n); // set `scr' to `screen[n]'
+
+ bool connected; // communicate with widget
+
+ void setCodec(int c); // codec number, 0 = locale, 1=utf8
+
+ QTextCodec* codec;
+ QTextCodec* localeCodec;
+ QTextDecoder* decoder;
+
+ KeyTrans* keytrans;
+
+// refreshing related material.
+// this is localized in the class.
+private slots: // triggered by timer
+
+ void showBulk();
+
+private:
+
+ void bulkNewline();
+ void bulkStart();
+ void bulkEnd();
+
+private:
+
+ QTimer bulk_timer;
+ int bulk_nlcnt; // bulk newline counter
+ char* SelectedText;
+ int bulk_incnt; // bulk counter
+
+
+};
+
+#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
@@ -53,48 +53,48 @@ extern "C" {
ProfileDialogWidget* newIrDaWidget( const QString& str, QWidget* wid ) {
return new IrdaConfigWidget( str, wid );
}
ProfileDialogWidget* newModemWidget( const QString& str, QWidget* wid ) {
return new ModemConfigWidget(str, wid );
}
ProfileDialogWidget* newBTWidget( const QString& str, QWidget* wid ) {
return new BTConfigWidget(str, wid );
}
// Terminal Widget(s)
- ProfileDialogWidget* newTerminalWidget(const QString& na, QWidget* wid) {
+/* ProfileDialogWidget* newTerminalWidget(const QString& na, QWidget* wid) {
return new TerminalWidget(na, wid,0 );
}
-
- // VT Emulations
+*/
+/* // VT Emulations
EmulationLayer* newVT102( WidgetLayer* wid ) {
return new Vt102Emulation( wid );
}
-
+*/
};
Default::Default( MetaFactory* fact ) {
fact->addFileTransferLayer( "SZ", QObject::tr("Z-Modem"), newSZTransfer );
fact->addFileTransferLayer( "SY", QObject::tr("Y-Modem"), newSYTransfer );
fact->addFileTransferLayer( "SX", QObject::tr("X-Modem"), newSXTransfer );
fact->addReceiveLayer( "SZ", QObject::tr("Z-Modem"), newSZReceive );
fact->addReceiveLayer( "SY", QObject::tr("Y-Modem"), newSYReceive );
fact->addReceiveLayer( "SX", QObject::tr("X-Modem"), newSXReceive );
fact->addIOLayerFactory( "serial", QObject::tr("Serial"), newSerialLayer );
fact->addIOLayerFactory( "irda", QObject::tr("Infrared"), newIrDaLayer );
fact->addIOLayerFactory( "bt", QObject::tr("Bluetooth"), newBTLayer );
fact->addConnectionWidgetFactory( "serial", QObject::tr("Serial"), newSerialWidget );
fact->addConnectionWidgetFactory( "irda", QObject::tr("Infrared"), newIrDaWidget );
fact->addConnectionWidgetFactory( "modem", QObject::tr("Modem"), newModemWidget );
fact->addConnectionWidgetFactory( "bt", QObject::tr("Bluetooth"), newBTWidget );
- fact->addTerminalWidgetFactory( "default", QObject::tr("Default Terminal"), newTerminalWidget );
+// fact->addTerminalWidgetFactory( "default", QObject::tr("Default Terminal"), newTerminalWidget );
- fact->addEmulationLayer( "default", QObject::tr("Default Terminal"), newVT102 );
+// fact->addEmulationLayer( "default", QObject::tr("Default Terminal"), newVT102 );
}
Default::~Default() {
}
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
@@ -13,26 +13,26 @@ extern "C" {
ReceiveLayer* newSZReceive(IOLayer*);
ReceiveLayer* newSYReceive(IOLayer*);
ReceiveLayer* newSXReceive(IOLayer*);
IOLayer* newSerialLayer(const Profile&);
IOLayer* newBTLayer(const Profile& );
IOLayer* newIrDaLayer(const Profile& );
ProfileDialogWidget* newSerialWidget(const QString&, QWidget* );
ProfileDialogWidget* newIrDaWidget (const QString&, QWidget* );
ProfileDialogWidget* newBTWidget (const QString&, QWidget* );
- ProfileDialogWidget* newTerminalWidget(const QString&, QWidget* );
+// ProfileDialogWidget* newTerminalWidget(const QString&, QWidget* );
- EmulationLayer* newVT102( WidgetLayer* );
+// EmulationLayer* newVT102( WidgetLayer* );
};
class MetaFactory;
struct Default {
public:
Default(MetaFactory* );
~Default();
};
#endif
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
@@ -58,33 +58,33 @@ FIXME: Terminating the history is not properly indicated
in the menu. We should throw a signal.
FIXME: There is noticable decrease in speed, also. Perhaps,
there whole feature needs to be revisited therefore.
Disadvantage of a more elaborated, say block-oriented
scheme with wrap around would be it's complexity.
*/
//FIXME: tempory replacement for tmpfile
// this is here one for debugging purpose.
//#define tmpfile xTmpFile
-
+/*
FILE* xTmpFile()
{
static int fid = 0;
char fname[80];
sprintf(fname,"TmpFile.%d",fid++);
return fopen(fname,"w");
}
-
+*/
// History Buffer ///////////////////////////////////////////
/*
A Row(X) data type which allows adding elements to the end.
*/
HistoryBuffer::HistoryBuffer()
{
ion = -1;
length = 0;
}
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
@@ -9,12 +9,14 @@ IOLayer::IOLayer(const Profile &)
: QObject()
{
}
IOLayer::~IOLayer() {
}
int IOLayer::rawIO()const{
return -1;
}
void IOLayer::closeRawIO(int) {
}
+void IOLayer::setSize(int, int ) {
+}
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
@@ -55,24 +55,26 @@ public:
* the device for io but does not
* do any ioctling on it...
* and it'll stop listening to the before opened
* device
*/
virtual int rawIO()const;
/**
* will close the rawIO stuff
* and will listen to it's data again...
*/
virtual void closeRawIO(int);
+
+
signals:
/**
* received input as QCString
*/
virtual void received( const QByteArray& ) = 0;
/**
* an error occured
* int for the error number
* and QString for a text
*/
virtual void error( int, const QString& ) = 0;
@@ -88,15 +90,21 @@ public slots:
*/
virtual bool open() = 0;
/**
* close the io
*/
virtual void close() = 0;
/**
* closes and reloads the settings
*/
virtual void reload( const Profile& ) = 0;
+
+ /**
+ * set the size
+ * needed for pty
+ */
+ virtual void setSize(int rows, int cols );
};
#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
@@ -205,55 +205,59 @@ QList<Session> MainWindow::sessions() {
void MainWindow::slotNew() {
qWarning("New Connection");
ProfileEditorDialog dlg(factory() );
dlg.showMaximized();
int ret = dlg.exec();
if ( ret == QDialog::Accepted ) {
create( dlg.profile() );
}
}
void MainWindow::slotRecordScript() {
- if (currentSession()) {
+/* if (currentSession()) {
currentSession()->emulationLayer()->startRecording();
}
+ */
}
void MainWindow::slotSaveScript() {
- if (currentSession() && currentSession()->emulationLayer()->isRecording()) {
+/* if (currentSession() && currentSession()->emulationLayer()->isRecording()) {
MimeTypes types;
QStringList script;
script << "text/plain";
types.insert("Script", script);
QString filename = OFileDialog::getSaveFileName(2, "/", QString::null, types);
if (!filename.isEmpty()) {
currentSession()->emulationLayer()->script()->saveTo(filename);
currentSession()->emulationLayer()->clearScript();
}
}
+ */
}
void MainWindow::slotRunScript() {
+/*
if (currentSession()) {
MimeTypes types;
QStringList script;
script << "text/plain";
types.insert("Script", script);
QString filename = OFileDialog::getOpenFileName(2, "/", QString::null, types);
if (!filename.isEmpty()) {
Script script(DocLnk(filename).file());
currentSession()->emulationLayer()->runScript(&script);
}
}
+ */
}
void MainWindow::slotConnect() {
if ( currentSession() )
currentSession()->layer()->open();
}
void MainWindow::slotDisconnect() {
if ( currentSession() )
currentSession()->layer()->close();
}
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
@@ -4,71 +4,65 @@ CONFIG = qt debug
DESTDIR = $(OPIEDIR)/bin
HEADERS = io_layer.h io_serial.h io_irda.h io_bt.h io_modem.h \
file_layer.h filetransfer.h \
metafactory.h \
session.h \
mainwindow.h \
profile.h \
profileconfig.h \
profilemanager.h \
configwidget.h \
tabwidget.h \
configdialog.h \
- emulation_layer.h \
- vt102emulation.h \
- common.h \
- history.h \
- screen.h \
keytrans.h \
- widget_layer.h \
transferdialog.h \
profiledialogwidget.h \
profileeditordialog.h \
default.h \
- terminalwidget.h \
iolayerbase.h \
serialconfigwidget.h irdaconfigwidget.h \
btconfigwidget.h modemconfigwidget.h \
atconfigdialog.h dialdialog.h \
- emulation_widget.h procctl.h \
+ procctl.h \
function_keyboard.h \
receive_layer.h filereceive.h \
script.h \
- dialer.h
+ dialer.h \
+ emulation_handler.h TECommon.h \
+ TEHistroy.h TEScreen.h TEWidget.h \
+ TEmuVt102.h TEmulation.h
SOURCES = io_layer.cpp io_serial.cpp io_irda.cpp io_bt.cpp io_modem.cpp \
file_layer.cpp filetransfer.cpp \
main.cpp \
metafactory.cpp \
session.cpp \
mainwindow.cpp \
profile.cpp \
profileconfig.cpp \
profilemanager.cpp \
tabwidget.cpp \
configdialog.cpp \
- emulation_layer.cpp \
- vt102emulation.cpp \
- history.cpp \
- screen.cpp \
keytrans.cpp \
- widget_layer.cpp \
transferdialog.cpp \
profiledialogwidget.cpp \
profileeditordialog.cpp \
- terminalwidget.cpp \
iolayerbase.cpp \
serialconfigwidget.cpp irdaconfigwidget.cpp \
btconfigwidget.cpp modemconfigwidget.cpp \
atconfigdialog.cpp dialdialog.cpp \
- emulation_widget.cpp default.cpp procctl.cpp \
+ default.cpp procctl.cpp \
function_keyboard.cpp \
receive_layer.cpp filereceive.cpp \
script.cpp \
- dialer.cpp
+ dialer.cpp \
+ emulation_handler.cpp TEHistory.cpp \
+ TEScreen.cpp TEWidget.cpp \
+ TEmuVt102.cpp TEmulation.cpp
+
INTERFACES = configurebase.ui editbase.ui
INCLUDEPATH += $(OPIEDIR)/include
DEPENDPATH += $(OPIEDIR)/include
LIBS += -lqpe -lopie
TARGET = opie-console
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
@@ -1,21 +1,22 @@
#include <stdio.h>
#include <stdlib.h>
#include <qfile.h>
#include <qlayout.h>
#include <qwidgetstack.h>
#include <qpe/config.h>
+#include "emulation_handler.h"
#include "widget_layer.h"
#include "emulation_widget.h"
#include "metafactory.h"
#include "profileconfig.h"
#include "profilemanager.h"
ProfileManager::ProfileManager( MetaFactory* fact )
: m_fact( fact )
{
}
ProfileManager::~ProfileManager() {
@@ -74,30 +75,32 @@ Session* ProfileManager::fromProfile( const Profile& prof, QWidget* parent) {
Session* session = new Session();
session->setName( prof.name() );
/* translate the internal name to the external */
session->setIOLayer(m_fact->newIOLayer( m_fact->external(prof.ioLayerName()) ,
prof) );
QWidgetStack *stack = new QWidgetStack(parent);
session->setWidgetStack( stack );
QWidget* dummy = new QWidget( stack );
QHBoxLayout* lay = new QHBoxLayout(dummy );
stack->addWidget( dummy, 0 );
stack->raiseWidget( 0 );
- WidgetLayer* wid = new EmulationWidget( prof, dummy );
- lay->addWidget( wid );
-
- session->setEmulationWidget( wid );
- session->setEmulationLayer( m_fact->newEmulationLayer( m_fact->external( prof.terminalName() ),
- wid ) );
+ EmulationHandler* handler = new EmulationHandler(prof,dummy );
+ lay->addWidget( handler->widget() );
+// WidgetLayer* wid = new EmulationWidget( prof, dummy );
+// lay->addWidget( wid );
+
+// session->setEmulationWidget( wid );
+// session->setEmulationLayer( m_fact->newEmulationLayer( m_fact->external( prof.terminalName() ),
+// wid ) );
session->connect();
return session;
}
void ProfileManager::save( ) {
QFile::remove( (QString(getenv("HOME") )+ "/Settings/opie-console-profiles.conf" ) );
ProfileConfig conf("opie-console-profiles");
Profile::ValueList::Iterator it2;
for (it2 = m_list.begin(); it2 != m_list.end(); ++it2 ) {
conf.setGroup( (*it2).name() );
/* now the config stuff */
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
@@ -1,81 +1,87 @@
#include "io_layer.h"
#include "file_layer.h"
#include "widget_layer.h"
#include "emulation_layer.h"
#include "session.h"
Session::Session() {
m_widget = 0l;
m_layer = 0l;
- m_widLay = 0l;
- m_emLay = 0l;
+// m_widLay = 0l;
+// m_emLay = 0l;
}
Session::Session( const QString& na, QWidgetStack* widget, IOLayer* lay)
: m_name( na ), m_widget( widget ), m_layer( lay )
{
- m_widLay = 0l;
- m_emLay = 0l;
+// m_widLay = 0l;
+// m_emLay = 0l;
}
Session::~Session() {
delete m_layer;
- delete m_emLay;
+// delete m_emLay;
delete m_widget;
/* the widget layer should be deleted by the m_widget */
}
QString Session::name()const {
return m_name;
}
QWidgetStack* Session::widgetStack() {
return m_widget;
}
IOLayer* Session::layer() {
return m_layer;
}
-EmulationLayer* Session::emulationLayer() {
+/*EmulationLayer* Session::emulationLayer() {
return m_emLay;
}
WidgetLayer* Session::emulationWidget() {
return m_widLay;
}
+*/
void Session::connect() {
- if ( !m_layer || !m_emLay )
+/* if ( !m_layer || !m_emLay )
return;
QObject::connect(m_layer, SIGNAL(received(const QByteArray&) ),
m_emLay, SLOT(onRcvBlock(const QByteArray&) ) );
QObject::connect(m_emLay, SIGNAL(sndBlock(const QByteArray&) ),
m_layer, SLOT(send(const QByteArray&) ) );
+ */
}
void Session::disconnect() {
+/*
if ( !m_layer || !m_emLay )
return;
QObject::disconnect(m_layer, SIGNAL(received(const QByteArray&) ),
m_emLay, SLOT(onRcvBlock(const QByteArray&) ) );
QObject::disconnect(m_emLay, SIGNAL(sndBlock(const QByteArray&) ),
m_layer, SLOT(send(const QByteArray&) ) );
+ */
}
void Session::setName( const QString& na){
m_name = na;
}
void Session::setWidgetStack( QWidgetStack* wid ) {
delete m_widget;
/* the EmulationLayer was destroyed... */
- delete m_emLay;
+ //delete m_emLay;
m_widget = wid;
}
void Session::setIOLayer( IOLayer* lay ) {
delete m_layer;
m_layer = lay;
}
+/*
void Session::setEmulationLayer( EmulationLayer* lay ) {
delete m_emLay;
m_emLay = lay;
}
void Session::setEmulationWidget( WidgetLayer* lay ) {
delete m_widLay;
m_widLay = lay;
}
+*/ \ 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
@@ -32,43 +32,43 @@ public:
* this is used to be semi modal
* for FileTransfer
*
* semi modal == SessionModal
*/
QWidgetStack* widgetStack();
/**
* return the layer
*/
IOLayer* layer();
- EmulationLayer* emulationLayer();
+// EmulationLayer* emulationLayer();
WidgetLayer* emulationWidget();
/*
* connects the data flow from
* the IOLayer to the EmulationLayer
*/
void connect();
/*
* disconnect the dataflow
* this will be done for ft
*/
void disconnect();
void setWidgetStack( QWidgetStack* widget );
- void setEmulationLayer( EmulationLayer* lay );
- void setEmulationWidget( WidgetLayer* lay );
+// void setEmulationLayer( EmulationLayer* lay );
+// void setEmulationWidget( WidgetLayer* lay );
void setIOLayer( IOLayer* );
void setName( const QString& );
private:
QString m_name;
QWidgetStack* m_widget;
IOLayer* m_layer;
- EmulationLayer* m_emLay;
- WidgetLayer* m_widLay;
+// EmulationLayer* m_emLay;
+// WidgetLayer* m_widLay;
};
#endif