summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-console/emulation_layer.cpp372
-rw-r--r--noncore/apps/opie-console/emulation_layer.cpp~373
-rw-r--r--noncore/apps/opie-console/emulation_layer.h146
-rw-r--r--noncore/apps/opie-console/emulation_layer.obin0 -> 13224 bytes
-rw-r--r--noncore/apps/opie-console/history.cpp218
-rw-r--r--noncore/apps/opie-console/history.h82
-rw-r--r--noncore/apps/opie-console/history.obin0 -> 6468 bytes
-rw-r--r--noncore/apps/opie-console/keytrans.cpp706
-rw-r--r--noncore/apps/opie-console/keytrans.h93
-rw-r--r--noncore/apps/opie-console/keytrans.obin0 -> 34264 bytes
-rw-r--r--noncore/apps/opie-console/screen.cpp1197
-rw-r--r--noncore/apps/opie-console/screen.h259
-rw-r--r--noncore/apps/opie-console/screen.obin0 -> 15864 bytes
-rw-r--r--noncore/apps/opie-console/vt102emulation.cpp1029
-rw-r--r--noncore/apps/opie-console/vt102emulation.h153
-rw-r--r--noncore/apps/opie-console/vt102emulation.obin0 -> 33320 bytes
16 files changed, 4628 insertions, 0 deletions
diff --git a/noncore/apps/opie-console/emulation_layer.cpp b/noncore/apps/opie-console/emulation_layer.cpp
new file mode 100644
index 0000000..6c420e0
--- a/dev/null
+++ b/noncore/apps/opie-console/emulation_layer.cpp
@@ -0,0 +1,372 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [emulation_layer.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> */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Modified to suit opie-console */
+/* */
+/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+/*! \class EmulationLayer
+
+ \brief Mediator between Widget and Screen.
+
+ 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 Widget by certain rules.
+
+ \sa Widget \sa Screen
+
+ \par A note on refreshing
+
+ Although the modifications to the current screen image could immediately
+ be propagated via `Widget' 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 "emulation_layer.h"
+#include "widget.h"
+#include "screen.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <qkeycode.h>
+
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* EmulationLayer */
+/* */
+/* ------------------------------------------------------------------------- */
+
+#define CNTL(c) ((c)-'@')
+
+/*!
+*/
+
+EmulationLayer::EmulationLayer(Widget* gui)
+: decoder((QTextDecoder*)NULL)
+{
+ this->gui = gui;
+
+ screen[0] = new Screen(gui->Lines(),gui->Columns());
+ screen[1] = new Screen(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()) );
+}
+
+/*!
+*/
+
+EmulationLayer::~EmulationLayer()
+{
+ delete screen[0];
+ delete screen[1];
+ bulk_timer.stop();
+}
+
+/*! change between primary and alternate screen
+*/
+
+void EmulationLayer::setScreen(int n)
+{
+ scr = screen[n&1];
+}
+
+void EmulationLayer::setHistory(bool on)
+{
+ screen[0]->setScroll(on);
+ if (!connected) return;
+ showBulk();
+}
+
+bool EmulationLayer::history()
+{
+ return screen[0]->hasScroll();
+}
+
+void EmulationLayer::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 EmulationLayer::setKeytrans(int no)
+{
+ keytrans = KeyTrans::find(no);
+}
+
+void EmulationLayer::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 EmulationLayer::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 EmulationLayer::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.
+ sendString( ev->text().ascii() ); //,ev->text().length());
+ }
+ else if (ev->ascii()>0)
+ {
+ QByteArray c = QByteArray( 1 );
+ c.at( 0 ) = ev->ascii();
+ // ibot: qbytearray is emited not char*
+ emit sndBlock( (QByteArray) c );
+ }
+}
+
+// Unblocking, Byte to Unicode translation --------------------------------- --
+
+/*
+ We are doing code conversion from locale to unicode first.
+*/
+
+void EmulationLayer::onRcvBlock(const QByteArray &s )
+{
+ bulkStart();
+ bulk_incnt += 1;
+ for (int i = 0; i < s.size(); i++)
+ {
+ //TODO: ibot: maybe decoding qbytearray to unicode in io_layer?
+ 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 EmulationLayer::onSelectionBegin(const int x, const int y) {
+ if (!connected) return;
+ scr->setSelBeginXY(x,y);
+ showBulk();
+}
+
+void EmulationLayer::onSelectionExtend(const int x, const int y) {
+ if (!connected) return;
+ scr->setSelExtentXY(x,y);
+ showBulk();
+}
+
+void EmulationLayer::setSelection(const BOOL preserve_line_breaks) {
+ if (!connected) return;
+ QString t = scr->getSelText(preserve_line_breaks);
+ if (!t.isNull()) gui->setSelection(t);
+}
+
+void EmulationLayer::clearSelection() {
+ if (!connected) return;
+ scr->clearSelection();
+ showBulk();
+}
+
+// Refreshing -------------------------------------------------------------- --
+
+#define BULK_TIMEOUT 20
+
+/*!
+ called when \n comes in. Evtl. triggers showBulk at endBulk
+*/
+
+void EmulationLayer::bulkNewline()
+{
+ bulk_nlcnt += 1;
+ bulk_incnt = 0; // reset bulk counter since `nl' rule applies
+}
+
+/*!
+*/
+
+void EmulationLayer::showBulk()
+{
+ bulk_nlcnt = 0; // reset bulk newline counter
+ bulk_incnt = 0; // reset bulk counter
+ if (connected)
+ {
+ Character* 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 EmulationLayer::bulkStart()
+{
+ if (bulk_timer.isActive()) bulk_timer.stop();
+}
+
+void EmulationLayer::bulkEnd()
+{
+ if ( bulk_nlcnt > gui->Lines() || bulk_incnt > 20 )
+ showBulk(); // resets bulk_??cnt to 0, too.
+ else
+ bulk_timer.start(BULK_TIMEOUT,TRUE);
+}
+
+void EmulationLayer::setConnect(bool c)
+{
+ connected = c;
+ if ( connected)
+ {
+ onImageSizeChange(gui->Lines(), gui->Columns());
+ showBulk();
+ }
+ else
+ {
+ scr->clearSelection();
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+/*! triggered by image size change of the Widget `gui'.
+
+ This event is simply propagated to the attached screens
+ and to the related serial line.
+*/
+
+void EmulationLayer::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 EmulationLayer::onHistoryCursorChange(int cursor)
+{
+ if (!connected) return;
+ scr->setHistCursor(cursor);
+ showBulk();
+}
+
+void EmulationLayer::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/emulation_layer.cpp~ b/noncore/apps/opie-console/emulation_layer.cpp~
new file mode 100644
index 0000000..e65fd4b
--- a/dev/null
+++ b/noncore/apps/opie-console/emulation_layer.cpp~
@@ -0,0 +1,373 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [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> */
+/* */
+/* -------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------- */
+/* */
+/* Modified to suit opie-console */
+/* */
+/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*! \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 "emulation_layer.h"
+#include "widget.h"
+#include "TEScreen.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <qkeycode.h>
+
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* EmulationLayer */
+/* */
+/* ------------------------------------------------------------------------- */
+
+#define CNTL(c) ((c)-'@')
+
+/*!
+*/
+
+EmulationLayer::EmulationLayer(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()) );
+}
+
+/*!
+*/
+
+EmulationLayer::~EmulationLayer()
+{
+ delete screen[0];
+ delete screen[1];
+ bulk_timer.stop();
+}
+
+/*! change between primary and alternate screen
+*/
+
+void EmulationLayer::setScreen(int n)
+{
+ scr = screen[n&1];
+}
+
+void EmulationLayer::setHistory(bool on)
+{
+ screen[0]->setScroll(on);
+ if (!connected) return;
+ showBulk();
+}
+
+bool EmulationLayer::history()
+{
+ return screen[0]->hasScroll();
+}
+
+void EmulationLayer::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 EmulationLayer::setKeytrans(int no)
+{
+ keytrans = KeyTrans::find(no);
+}
+
+void EmulationLayer::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 EmulationLayer::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 EmulationLayer::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.
+ sendString( ev->text().ascii() ); //,ev->text().length());
+ }
+ else if (ev->ascii()>0)
+ {
+ QByteArray c = QByteArray( 1 );
+ c.at( 0 ) = ev->ascii();
+ // ibot: qbytearray is emited not char*
+ emit sndBlock( (QByteArray) c );
+ }
+}
+
+// Unblocking, Byte to Unicode translation --------------------------------- --
+
+/*
+ We are doing code conversion from locale to unicode first.
+*/
+
+void EmulationLayer::onRcvBlock(const QByteArray &s )
+{
+ bulkStart();
+ bulk_incnt += 1;
+ for (int i = 0; i < s.size(); i++)
+ {
+ //TODO: ibot: maybe decoding qbytearray to unicode in io_layer?
+ 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 EmulationLayer::onSelectionBegin(const int x, const int y) {
+ if (!connected) return;
+ scr->setSelBeginXY(x,y);
+ showBulk();
+}
+
+void EmulationLayer::onSelectionExtend(const int x, const int y) {
+ if (!connected) return;
+ scr->setSelExtentXY(x,y);
+ showBulk();
+}
+
+void EmulationLayer::setSelection(const BOOL preserve_line_breaks) {
+ if (!connected) return;
+ QString t = scr->getSelText(preserve_line_breaks);
+ if (!t.isNull()) gui->setSelection(t);
+}
+
+void EmulationLayer::clearSelection() {
+ if (!connected) return;
+ scr->clearSelection();
+ showBulk();
+}
+
+// Refreshing -------------------------------------------------------------- --
+
+#define BULK_TIMEOUT 20
+
+/*!
+ called when \n comes in. Evtl. triggers showBulk at endBulk
+*/
+
+void EmulationLayer::bulkNewline()
+{
+ bulk_nlcnt += 1;
+ bulk_incnt = 0; // reset bulk counter since `nl' rule applies
+}
+
+/*!
+*/
+
+void EmulationLayer::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 EmulationLayer::bulkStart()
+{
+ if (bulk_timer.isActive()) bulk_timer.stop();
+}
+
+void EmulationLayer::bulkEnd()
+{
+ if ( bulk_nlcnt > gui->Lines() || bulk_incnt > 20 )
+ showBulk(); // resets bulk_??cnt to 0, too.
+ else
+ bulk_timer.start(BULK_TIMEOUT,TRUE);
+}
+
+void EmulationLayer::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 EmulationLayer::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 EmulationLayer::onHistoryCursorChange(int cursor)
+{
+ if (!connected) return;
+ scr->setHistCursor(cursor);
+ showBulk();
+}
+
+void EmulationLayer::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/emulation_layer.h b/noncore/apps/opie-console/emulation_layer.h
new file mode 100644
index 0000000..0f54331
--- a/dev/null
+++ b/noncore/apps/opie-console/emulation_layer.h
@@ -0,0 +1,146 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [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> */
+/* */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* */
+/* made to a layer between io_layer and widget */
+/* */
+/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+#ifndef EMULATION_LAYER_H
+#define EMULATION_LAYER_H
+
+#include "widget.h"
+#include "screen.h"
+#include <qtimer.h>
+#include <stdio.h>
+#include <qtextcodec.h>
+#include "keytrans.h"
+
+class EmulationLayer : public QObject
+{ Q_OBJECT
+
+public:
+
+ EmulationLayer(Widget* gui);
+ ~EmulationLayer();
+
+public:
+ virtual void setHistory(bool on);
+ virtual bool history();
+
+public slots: // signals incoming from Widget
+
+ 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
+
+ /**
+ * to be called, when new data arrives
+ */
+ void onRcvBlock(const QByteArray&);
+
+signals:
+
+ /**
+ * will send data, encoded to suit emulation
+ */
+ void sndBlock(const QByteArray&);
+
+ void ImageSizeChanged(int lines, int columns);
+
+ void changeColumns(int columns);
+
+ void changeTitle(int arg, const char* str);
+
+
+public:
+
+ /**
+ * process single char (decode)
+ */
+ virtual void onRcvChar(int);
+
+ virtual void setMode (int) = 0;
+ virtual void resetMode(int) = 0;
+
+ /**
+ * @deprecated use qbytearray instead
+ */
+ virtual void sendString(const char*) = 0;
+
+ /**
+ * sends a string to IOLayer
+ * encodes to suit emulation before
+ */
+ virtual void sendString(const QByteArray&) = 0;
+
+ virtual void setConnect(bool r);
+ void setColumns(int columns);
+
+ void setKeytrans(int no);
+ void setKeytrans(const char * no);
+
+protected:
+
+ Widget* gui;
+ Screen* scr; // referes to one `screen'
+ Screen* 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/emulation_layer.o b/noncore/apps/opie-console/emulation_layer.o
new file mode 100644
index 0000000..fe80bcb
--- a/dev/null
+++ b/noncore/apps/opie-console/emulation_layer.o
Binary files differ
diff --git a/noncore/apps/opie-console/history.cpp b/noncore/apps/opie-console/history.cpp
new file mode 100644
index 0000000..3b82d16
--- a/dev/null
+++ b/noncore/apps/opie-console/history.cpp
@@ -0,0 +1,218 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [history.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> */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* Ported embedded-Konsole to opie-console */
+/* */
+/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+#include "history.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(Character);
+}
+
+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, Character res[])
+{
+ assert(hasScroll());
+ cells.get((unsigned char*)res,count*sizeof(Character),startOfLine(lineno)+colno*sizeof(Character));
+}
+
+void HistoryScroll::addCells(Character text[], int count)
+{
+ if (!hasScroll()) return;
+ cells.add((unsigned char*)text,count*sizeof(Character));
+}
+
+void HistoryScroll::addLine()
+{
+ if (!hasScroll()) return;
+ int locn = cells.len();
+ index.add((unsigned char*)&locn,sizeof(int));
+}
diff --git a/noncore/apps/opie-console/history.h b/noncore/apps/opie-console/history.h
new file mode 100644
index 0000000..aa77ebb
--- a/dev/null
+++ b/noncore/apps/opie-console/history.h
@@ -0,0 +1,82 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [history.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> */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* ported embedded_konsole to opie-console */
+/* */
+/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+#ifndef HISTORY_H
+#define HISTORY_H
+
+#include "common.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, Character res[]);
+
+public: // backward compatibility (obsolete)
+ Character getCell(int lineno, int colno) { Character res; getCells(lineno,colno,1,&res); return res; }
+
+public: // adding lines.
+ void addCells(Character a[], int count);
+ void addLine();
+
+private:
+ int startOfLine(int lineno);
+ HistoryBuffer index; // lines Row(int)
+ HistoryBuffer cells; // text Row(Character)
+};
+
+#endif // HISTORY_H
diff --git a/noncore/apps/opie-console/history.o b/noncore/apps/opie-console/history.o
new file mode 100644
index 0000000..256d3a5
--- a/dev/null
+++ b/noncore/apps/opie-console/history.o
Binary files differ
diff --git a/noncore/apps/opie-console/keytrans.cpp b/noncore/apps/opie-console/keytrans.cpp
new file mode 100644
index 0000000..d569ae0
--- a/dev/null
+++ b/noncore/apps/opie-console/keytrans.cpp
@@ -0,0 +1,706 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [keytrans.C] Keyboard Translation */
+/* */
+/* -------------------------------------------------------------------------- */
+/* */
+/* 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> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+/*
+ The keyboard translation table allows to configure konsoles behavior
+ on key strokes.
+
+ FIXME: some bug crept in, disallowing '\0' to be emitted.
+*/
+
+#include "keytrans.h"
+
+#include <qpe/qpeapplication.h>
+
+#include <qnamespace.h>
+#include <qbuffer.h>
+#include <qobject.h>
+#include <qdict.h>
+#include <qintdict.h>
+#include <qfile.h>
+#include <qglobal.h>
+#include <qdir.h>
+
+//#include <kstddirs.h>
+//nclude <klocale.h>
+
+#include <stdio.h>
+
+
+#undef USE_APPDATA_DIR
+
+
+#define HERE printf("%s(%d): here\n",__FILE__,__LINE__)
+
+/* KeyEntry
+
+ instances represent the individual assignments
+*/
+
+KeyTrans::KeyEntry::KeyEntry(int _ref, int _key, int _bits, int _mask, int _cmd, QString _txt)
+: ref(_ref), key(_key), bits(_bits), mask(_mask), cmd(_cmd), txt(_txt)
+{
+}
+
+KeyTrans::KeyEntry::~KeyEntry()
+{
+}
+
+bool KeyTrans::KeyEntry::matches(int _key, int _bits, int _mask)
+{ int m = mask & _mask;
+ return _key == key && (bits & m) == (_bits & m);
+}
+
+QString KeyTrans::KeyEntry::text()
+{
+ return txt;
+}
+
+/* KeyTrans
+
+ combines the individual assignments to a proper map
+ Takes part in a collection themself.
+*/
+
+KeyTrans::KeyTrans()
+{
+ path = "";
+ numb = 0;
+}
+
+KeyTrans::~KeyTrans()
+{
+}
+
+KeyTrans::KeyEntry* KeyTrans::addEntry(int ref, int key, int bits, int mask, int cmd, QString txt)
+// returns conflicting entry
+{
+ for (QListIterator<KeyEntry> it(table); it.current(); ++it)
+ {
+ if (it.current()->matches(key,bits,mask))
+ {
+ return it.current();
+ }
+ }
+ table.append(new KeyEntry(ref,key,bits,mask,cmd,txt));
+ return (KeyEntry*)NULL;
+}
+
+bool KeyTrans::findEntry(int key, int bits, int* cmd, const char** txt, int* len)
+{
+ for (QListIterator<KeyEntry> it(table); it.current(); ++it)
+ if (it.current()->matches(key,bits,0xffff))
+ {
+ *cmd = it.current()->cmd;
+ *txt = it.current()->txt.ascii();
+ *len = it.current()->txt.length();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Scanner for keyboard configuration */
+/* */
+/* ------------------------------------------------------------------------- */
+
+// regular tokenizer
+/* Tokens
+ - Spaces
+ - Name (A-Za-z0-9)+
+ - String
+ - Opr on of +-:
+*/
+
+#define SYMName 0
+#define SYMString 1
+#define SYMEol 2
+#define SYMEof 3
+#define SYMOpr 4
+#define SYMError 5
+
+#define inRange(L,X,H) ((L <= X) && (X <= H))
+#define isNibble(X) (inRange('A',X,'F')||inRange('a',X,'f')||inRange('0',X,'9'))
+#define convNibble(X) (inRange('0',X,'9')?X-'0':X+10-(inRange('A',X,'F')?'A':'a'))
+
+class KeytabReader
+{
+public:
+ KeytabReader(QString p, QIODevice &d);
+public:
+ void getCc();
+ void getSymbol();
+ void parseTo(KeyTrans* kt);
+ void ReportError(const char* msg);
+ void ReportToken(); // diagnostic
+private:
+ int sym;
+ QString res;
+ int len;
+ int slinno;
+ int scolno;
+private:
+ int cc;
+ int linno;
+ int colno;
+ QIODevice* buf;
+ QString path;
+};
+
+
+KeytabReader::KeytabReader(QString p, QIODevice &d)
+{
+ path = p;
+ buf = &d;
+ cc = 0;
+}
+
+void KeytabReader::getCc()
+{
+ if (cc == '\n') { linno += 1; colno = 0; }
+ if (cc < 0) return;
+ cc = buf->getch();
+ colno += 1;
+}
+
+void KeytabReader::getSymbol()
+{
+ res = ""; len = 0; sym = SYMError;
+ while (cc == ' ') getCc(); // skip spaces
+ if (cc == '#') // skip comment
+ {
+ while (cc != '\n' && cc > 0) getCc();
+ }
+ slinno = linno;
+ scolno = colno;
+ if (cc <= 0)
+ {
+ sym = SYMEof; return; // eos
+ }
+ if (cc == '\n')
+ {
+ getCc();
+ sym = SYMEol; return; // eol
+ }
+ if (inRange('A',cc,'Z')||inRange('a',cc,'z')||inRange('0',cc,'9'))
+ {
+ while (inRange('A',cc,'Z') || inRange('a',cc,'z') || inRange('0',cc,'9'))
+ {
+ res = res + (char)cc;
+ getCc();
+ }
+ sym = SYMName;
+ return;
+ }
+ if (strchr("+-:",cc))
+ {
+ res = "";
+ res = res + (char)cc;
+ getCc();
+ sym = SYMOpr; return;
+ }
+ if (cc == '"')
+ {
+ getCc();
+ while (cc >= ' ' && cc != '"')
+ { int sc;
+ if (cc == '\\') // handle quotation
+ {
+ getCc();
+ switch (cc)
+ {
+ case 'E' : sc = 27; getCc(); break;
+ case 'b' : sc = 8; getCc(); break;
+ case 'f' : sc = 12; getCc(); break;
+ case 't' : sc = 9; getCc(); break;
+ case 'r' : sc = 13; getCc(); break;
+ case 'n' : sc = 10; getCc(); break;
+ case '\\' : // fall thru
+ case '"' : sc = cc; getCc(); break;
+ case 'x' : getCc();
+ sc = 0;
+ if (!isNibble(cc)) return; sc = 16*sc + convNibble(cc); getCc();
+ if (!isNibble(cc)) return; sc = 16*sc + convNibble(cc); getCc();
+ break;
+ default : return;
+ }
+ }
+ else
+ {
+ // regular char
+ sc = cc; getCc();
+ }
+ res = res + (char)sc;
+ len = len + 1;
+ }
+ if (cc != '"') return;
+ getCc();
+ sym = SYMString; return;
+ }
+}
+
+void KeytabReader::ReportToken() // diagnostic
+{
+ printf("sym(%d): ",slinno);
+ switch(sym)
+ {
+ case SYMEol : printf("End of line"); break;
+ case SYMEof : printf("End of file"); break;
+ case SYMName : printf("Name: %s",res.latin1()); break;
+ case SYMOpr : printf("Opr : %s",res.latin1()); break;
+ case SYMString : printf("String len %d,%d ",res.length(),len);
+ for (unsigned i = 0; i < res.length(); i++)
+ printf(" %02x(%c)",res.latin1()[i],res.latin1()[i]>=' '?res.latin1()[i]:'?');
+ break;
+ }
+ printf("\n");
+}
+
+void KeytabReader::ReportError(const char* msg) // diagnostic
+{
+ fprintf(stderr,"%s(%d,%d):error: %s.\n",path.ascii(),slinno,scolno,msg);
+}
+
+// local symbol tables ---------------------------------------------------------------------
+
+class KeyTransSymbols
+{
+public:
+ KeyTransSymbols();
+protected:
+ void defOprSyms();
+ void defModSyms();
+ void defKeySyms();
+ void defKeySym(const char* key, int val);
+ void defOprSym(const char* key, int val);
+ void defModSym(const char* key, int val);
+public:
+ QDict<QObject> keysyms;
+ QDict<QObject> modsyms;
+ QDict<QObject> oprsyms;
+};
+
+static KeyTransSymbols * syms = 0L;
+
+// parser ----------------------------------------------------------------------------------
+/* Syntax
+ - Line :: [KeyName { ("+" | "-") ModeName } ":" (String|CommandName)] "\n"
+ - Comment :: '#' (any but \n)*
+*/
+
+KeyTrans* KeyTrans::fromDevice(QString path, QIODevice &buf)
+{
+ KeyTrans* kt = new KeyTrans;
+ kt->path = path;
+ KeytabReader ktr(path,buf); ktr.parseTo(kt);
+ return kt;
+}
+
+
+#define assertSyntax(Cond,Message) if (!(Cond)) { ReportError(Message); goto ERROR; }
+
+void KeytabReader::parseTo(KeyTrans* kt)
+{
+ // Opening sequence
+
+ buf->open(IO_ReadOnly);
+ getCc();
+ linno = 1;
+ colno = 1;
+ getSymbol();
+
+Loop:
+ // syntax: ["key" KeyName { ("+" | "-") ModeName } ":" String/CommandName] ["#" Comment]
+ if (sym == SYMName && !strcmp(res.latin1(),"keyboard"))
+ {
+ getSymbol(); assertSyntax(sym == SYMString, "Header expected")
+ kt->hdr = res.latin1();
+ getSymbol(); assertSyntax(sym == SYMEol, "Text unexpected")
+ getSymbol(); // eoln
+ goto Loop;
+ }
+ if (sym == SYMName && !strcmp(res.latin1(),"key"))
+ {
+//printf("line %3d: ",startofsym);
+ getSymbol(); assertSyntax(sym == SYMName, "Name expected")
+ assertSyntax(syms->keysyms[res], "Unknown key name")
+ int key = (int)syms->keysyms[res]-1;
+//printf(" key %s (%04x)",res.latin1(),(int)syms->keysyms[res]-1);
+ getSymbol(); // + - :
+ int mode = 0;
+ int mask = 0;
+ while (sym == SYMOpr && (!strcmp(res.latin1(),"+") || !strcmp(res.latin1(),"-")))
+ {
+ bool on = !strcmp(res.latin1(),"+");
+ getSymbol();
+ // mode name
+ assertSyntax(sym == SYMName, "Name expected")
+ assertSyntax(syms->modsyms[res], "Unknown mode name")
+ int bits = (int)syms->modsyms[res]-1;
+ if (mask & (1 << bits))
+ {
+ fprintf(stderr,"%s(%d,%d): mode name used multible times.\n",path.ascii(),slinno,scolno);
+ }
+ else
+ {
+ mode |= (on << bits);
+ mask |= (1 << bits);
+ }
+//printf(", mode %s(%d) %s",res.latin1(),(int)syms->modsyms[res]-1,on?"on":"off");
+ getSymbol();
+ }
+ assertSyntax(sym == SYMOpr && !strcmp(res.latin1(),":"), "':' expected")
+ getSymbol();
+ // string or command
+ assertSyntax(sym == SYMName || sym == SYMString,"Command or string expected")
+ int cmd = 0;
+ if (sym == SYMName)
+ {
+ assertSyntax(syms->oprsyms[res], "Unknown operator name")
+ cmd = (int)syms->oprsyms[res]-1;
+//printf(": do %s(%d)",res.latin1(),(int)syms->oprsyms[res]-1);
+ }
+ if (sym == SYMString)
+ {
+ cmd = CMD_send;
+//printf(": send");
+//for (unsigned i = 0; i < res.length(); i++)
+//printf(" %02x(%c)",res.latin1()[i],res.latin1()[i]>=' '?res.latin1()[i]:'?');
+ }
+//printf(". summary %04x,%02x,%02x,%d\n",key,mode,mask,cmd);
+ KeyTrans::KeyEntry* ke = kt->addEntry(slinno,key,mode,mask,cmd,res);
+ if (ke)
+ {
+ fprintf(stderr,"%s(%d): keystroke already assigned in line %d.\n",path.ascii(),slinno,ke->ref);
+ }
+ getSymbol();
+ assertSyntax(sym == SYMEol, "Unexpected text")
+ goto Loop;
+ }
+ if (sym == SYMEol)
+ {
+ getSymbol();
+ goto Loop;
+ }
+
+ assertSyntax(sym == SYMEof, "Undecodable Line")
+
+ buf->close();
+ return;
+
+ERROR:
+ while (sym != SYMEol && sym != SYMEof) getSymbol(); // eoln
+ goto Loop;
+}
+
+
+KeyTrans* KeyTrans::defaultKeyTrans()
+{
+ QCString txt =
+#include "default.keytab.h"
+ ;
+ QBuffer buf(txt);
+ return fromDevice("[buildin]",buf);
+}
+
+KeyTrans* KeyTrans::fromFile(const char* path)
+{
+ QFile file(path);
+ return fromDevice(path,file);
+}
+
+// local symbol tables ---------------------------------------------------------------------
+// material needed for parsing the config file.
+// This is incomplete work.
+
+void KeyTransSymbols::defKeySym(const char* key, int val)
+{
+ keysyms.insert(key,(QObject*)(val+1));
+}
+
+void KeyTransSymbols::defOprSym(const char* key, int val)
+{
+ oprsyms.insert(key,(QObject*)(val+1));
+}
+
+void KeyTransSymbols::defModSym(const char* key, int val)
+{
+ modsyms.insert(key,(QObject*)(val+1));
+}
+
+void KeyTransSymbols::defOprSyms()
+{
+ // Modifier
+ defOprSym("scrollLineUp", CMD_scrollLineUp );
+ defOprSym("scrollLineDown",CMD_scrollLineDown);
+ defOprSym("scrollPageUp", CMD_scrollPageUp );
+ defOprSym("scrollPageDown",CMD_scrollPageDown);
+ defOprSym("emitSelection", CMD_emitSelection );
+ defOprSym("prevSession", CMD_prevSession );
+ defOprSym("nextSession", CMD_nextSession );
+}
+
+void KeyTransSymbols::defModSyms()
+{
+ // Modifier
+ defModSym("Shift", BITS_Shift );
+ defModSym("Control", BITS_Control );
+ defModSym("Alt", BITS_Alt );
+ // Modes
+ defModSym("BsHack", BITS_BsHack ); // deprecated
+ defModSym("Ansi", BITS_Ansi );
+ defModSym("NewLine", BITS_NewLine );
+ defModSym("AppCuKeys", BITS_AppCuKeys );
+}
+
+void KeyTransSymbols::defKeySyms()
+{
+ // Grey keys
+ defKeySym("Escape", Qt::Key_Escape );
+ defKeySym("Tab", Qt::Key_Tab );
+ defKeySym("Backtab", Qt::Key_Backtab );
+ defKeySym("Backspace", Qt::Key_Backspace );
+ defKeySym("Return", Qt::Key_Return );
+ defKeySym("Enter", Qt::Key_Enter );
+ defKeySym("Insert", Qt::Key_Insert );
+ defKeySym("Delete", Qt::Key_Delete );
+ defKeySym("Pause", Qt::Key_Pause );
+ defKeySym("Print", Qt::Key_Print );
+ defKeySym("SysReq", Qt::Key_SysReq );
+ defKeySym("Home", Qt::Key_Home );
+ defKeySym("End", Qt::Key_End );
+ defKeySym("Left", Qt::Key_Left );
+ defKeySym("Up", Qt::Key_Up );
+ defKeySym("Right", Qt::Key_Right );
+ defKeySym("Down", Qt::Key_Down );
+ defKeySym("Prior", Qt::Key_Prior );
+ defKeySym("Next", Qt::Key_Next );
+ defKeySym("Shift", Qt::Key_Shift );
+ defKeySym("Control", Qt::Key_Control );
+ defKeySym("Meta", Qt::Key_Meta );
+ defKeySym("Alt", Qt::Key_Alt );
+ defKeySym("CapsLock", Qt::Key_CapsLock );
+ defKeySym("NumLock", Qt::Key_NumLock );
+ defKeySym("ScrollLock", Qt::Key_ScrollLock );
+ defKeySym("F1", Qt::Key_F1 );
+ defKeySym("F2", Qt::Key_F2 );
+ defKeySym("F3", Qt::Key_F3 );
+ defKeySym("F4", Qt::Key_F4 );
+ defKeySym("F5", Qt::Key_F5 );
+ defKeySym("F6", Qt::Key_F6 );
+ defKeySym("F7", Qt::Key_F7 );
+ defKeySym("F8", Qt::Key_F8 );
+ defKeySym("F9", Qt::Key_F9 );
+ defKeySym("F10", Qt::Key_F10 );
+ defKeySym("F11", Qt::Key_F11 );
+ defKeySym("F12", Qt::Key_F12 );
+ defKeySym("F13", Qt::Key_F13 );
+ defKeySym("F14", Qt::Key_F14 );
+ defKeySym("F15", Qt::Key_F15 );
+ defKeySym("F16", Qt::Key_F16 );
+ defKeySym("F17", Qt::Key_F17 );
+ defKeySym("F18", Qt::Key_F18 );
+ defKeySym("F19", Qt::Key_F19 );
+ defKeySym("F20", Qt::Key_F20 );
+ defKeySym("F21", Qt::Key_F21 );
+ defKeySym("F22", Qt::Key_F22 );
+ defKeySym("F23", Qt::Key_F23 );
+ defKeySym("F24", Qt::Key_F24 );
+ defKeySym("F25", Qt::Key_F25 );
+ defKeySym("F26", Qt::Key_F26 );
+ defKeySym("F27", Qt::Key_F27 );
+ defKeySym("F28", Qt::Key_F28 );
+ defKeySym("F29", Qt::Key_F29 );
+ defKeySym("F30", Qt::Key_F30 );
+ defKeySym("F31", Qt::Key_F31 );
+ defKeySym("F32", Qt::Key_F32 );
+ defKeySym("F33", Qt::Key_F33 );
+ defKeySym("F34", Qt::Key_F34 );
+ defKeySym("F35", Qt::Key_F35 );
+ defKeySym("Super_L", Qt::Key_Super_L );
+ defKeySym("Super_R", Qt::Key_Super_R );
+ defKeySym("Menu", Qt::Key_Menu );
+ defKeySym("Hyper_L", Qt::Key_Hyper_L );
+ defKeySym("Hyper_R", Qt::Key_Hyper_R );
+
+ // Regular keys
+ defKeySym("Space", Qt::Key_Space );
+ defKeySym("Exclam", Qt::Key_Exclam );
+ defKeySym("QuoteDbl", Qt::Key_QuoteDbl );
+ defKeySym("NumberSign", Qt::Key_NumberSign );
+ defKeySym("Dollar", Qt::Key_Dollar );
+ defKeySym("Percent", Qt::Key_Percent );
+ defKeySym("Ampersand", Qt::Key_Ampersand );
+ defKeySym("Apostrophe", Qt::Key_Apostrophe );
+ defKeySym("ParenLeft", Qt::Key_ParenLeft );
+ defKeySym("ParenRight", Qt::Key_ParenRight );
+ defKeySym("Asterisk", Qt::Key_Asterisk );
+ defKeySym("Plus", Qt::Key_Plus );
+ defKeySym("Comma", Qt::Key_Comma );
+ defKeySym("Minus", Qt::Key_Minus );
+ defKeySym("Period", Qt::Key_Period );
+ defKeySym("Slash", Qt::Key_Slash );
+ defKeySym("0", Qt::Key_0 );
+ defKeySym("1", Qt::Key_1 );
+ defKeySym("2", Qt::Key_2 );
+ defKeySym("3", Qt::Key_3 );
+ defKeySym("4", Qt::Key_4 );
+ defKeySym("5", Qt::Key_5 );
+ defKeySym("6", Qt::Key_6 );
+ defKeySym("7", Qt::Key_7 );
+ defKeySym("8", Qt::Key_8 );
+ defKeySym("9", Qt::Key_9 );
+ defKeySym("Colon", Qt::Key_Colon );
+ defKeySym("Semicolon", Qt::Key_Semicolon );
+ defKeySym("Less", Qt::Key_Less );
+ defKeySym("Equal", Qt::Key_Equal );
+ defKeySym("Greater", Qt::Key_Greater );
+ defKeySym("Question", Qt::Key_Question );
+ defKeySym("At", Qt::Key_At );
+ defKeySym("A", Qt::Key_A );
+ defKeySym("B", Qt::Key_B );
+ defKeySym("C", Qt::Key_C );
+ defKeySym("D", Qt::Key_D );
+ defKeySym("E", Qt::Key_E );
+ defKeySym("F", Qt::Key_F );
+ defKeySym("G", Qt::Key_G );
+ defKeySym("H", Qt::Key_H );
+ defKeySym("I", Qt::Key_I );
+ defKeySym("J", Qt::Key_J );
+ defKeySym("K", Qt::Key_K );
+ defKeySym("L", Qt::Key_L );
+ defKeySym("M", Qt::Key_M );
+ defKeySym("N", Qt::Key_N );
+ defKeySym("O", Qt::Key_O );
+ defKeySym("P", Qt::Key_P );
+ defKeySym("Q", Qt::Key_Q );
+ defKeySym("R", Qt::Key_R );
+ defKeySym("S", Qt::Key_S );
+ defKeySym("T", Qt::Key_T );
+ defKeySym("U", Qt::Key_U );
+ defKeySym("V", Qt::Key_V );
+ defKeySym("W", Qt::Key_W );
+ defKeySym("X", Qt::Key_X );
+ defKeySym("Y", Qt::Key_Y );
+ defKeySym("Z", Qt::Key_Z );
+ defKeySym("BracketLeft", Qt::Key_BracketLeft );
+ defKeySym("Backslash", Qt::Key_Backslash );
+ defKeySym("BracketRight", Qt::Key_BracketRight);
+ defKeySym("AsciiCircum", Qt::Key_AsciiCircum );
+ defKeySym("Underscore", Qt::Key_Underscore );
+ defKeySym("QuoteLeft", Qt::Key_QuoteLeft );
+ defKeySym("BraceLeft", Qt::Key_BraceLeft );
+ defKeySym("Bar", Qt::Key_Bar );
+ defKeySym("BraceRight", Qt::Key_BraceRight );
+ defKeySym("AsciiTilde", Qt::Key_AsciiTilde );
+}
+
+KeyTransSymbols::KeyTransSymbols()
+{
+ defModSyms();
+ defOprSyms();
+ defKeySyms();
+}
+
+// Global material -----------------------------------------------------------
+
+static int keytab_serial = 0; //FIXME: remove,localize
+
+static QIntDict<KeyTrans> * numb2keymap = 0L;
+static QDict<KeyTrans> * path2keymap = 0L;
+
+KeyTrans* KeyTrans::find(int numb)
+{
+ KeyTrans* res = numb2keymap->find(numb);
+ return res ? res : numb2keymap->find(0);
+}
+
+KeyTrans* KeyTrans::find(const char* path)
+{
+ KeyTrans* res = path2keymap->find(path);
+ return res ? res : numb2keymap->find(0);
+}
+
+int KeyTrans::count()
+{
+ return numb2keymap->count();
+}
+
+void KeyTrans::addKeyTrans()
+{
+ this->numb = keytab_serial ++;
+ numb2keymap->insert(numb,this);
+ path2keymap->insert(path,this);
+}
+
+void KeyTrans::loadAll()
+{
+ if (!numb2keymap)
+ numb2keymap = new QIntDict<KeyTrans>;
+ if (!path2keymap)
+ path2keymap = new QDict<KeyTrans>;
+ if (!syms)
+ syms = new KeyTransSymbols;
+
+ defaultKeyTrans()->addKeyTrans();
+
+
+ QString path = QPEApplication::qpeDir() + "etc/keytabs";
+ QDir dir(path);
+ QStringList lst = dir.entryList("*.keytab");
+
+ for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
+ QFile file(path + "/" + *it);
+ KeyTrans* sc = KeyTrans::fromDevice(*it, file);
+ if (sc) {
+ sc->addKeyTrans();
+ }
+ }
+
+}
+
+// Debugging material -----------------------------------------------------------
+/*
+void TestTokenizer(QBuffer &buf)
+{
+ // opening sequence
+
+ buf.open(IO_ReadOnly);
+ cc = buf.getch();
+ lineno = 1;
+
+ // Test tokenizer
+
+ while (getSymbol(buf)) ReportToken();
+
+ buf.close();
+}
+
+void test()
+{
+ // Opening sequence
+
+ QCString txt =
+#include "default.keytab.h"
+ ;
+ QBuffer buf(txt);
+ if (0) TestTokenizer(buf);
+ if (1) { KeyTrans kt; kt.scanTable(buf); }
+}
+*/
diff --git a/noncore/apps/opie-console/keytrans.h b/noncore/apps/opie-console/keytrans.h
new file mode 100644
index 0000000..ef6ed15
--- a/dev/null
+++ b/noncore/apps/opie-console/keytrans.h
@@ -0,0 +1,93 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [keytrans.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 KEYTRANS_H
+#define KEYTRANS_H
+
+#include <qstring.h>
+#include <qlist.h>
+#include <qiodevice.h>
+
+#define BITS_NewLine 0
+#define BITS_BsHack 1
+#define BITS_Ansi 2
+#define BITS_AppCuKeys 3
+#define BITS_Control 4
+#define BITS_Shift 5
+#define BITS_Alt 6
+#define BITS_COUNT 7
+
+#define CMD_send 0
+#define CMD_emitSelection 1
+#define CMD_scrollPageUp 2
+#define CMD_scrollPageDown 3
+#define CMD_scrollLineUp 4
+#define CMD_scrollLineDown 5
+#define CMD_prevSession 6
+#define CMD_nextSession 7
+
+#define BITS(x,v) ((((v)!=0)<<(x)))
+
+
+class KeyTrans
+{
+public:
+ KeyTrans();
+ ~KeyTrans();
+ static KeyTrans* defaultKeyTrans();
+ static KeyTrans* fromFile(const char* path);
+ static KeyTrans* find(int numb);
+ static KeyTrans* find(const char* path);
+public:
+ static int count();
+ static void loadAll();
+public:
+ bool findEntry(int key, int bits, int* cmd, const char** txt, int* len);
+private:
+ void addKeyTrans();
+ static KeyTrans* fromDevice(QString path, QIODevice &buf);
+public:
+ class KeyEntry
+ {
+ public:
+ KeyEntry(int ref, int key, int bits, int mask, int cmd, QString txt);
+ ~KeyEntry();
+ public:
+ bool matches(int key, int bits, int mask);
+ QString text();
+ public:
+ int ref;
+ private:
+ int key;
+ int bits;
+ int mask;
+ public:
+ int cmd;
+ QString txt;
+ };
+public:
+ KeyEntry* addEntry(int ref, int key, int bits, int mask, int cmd, QString txt);
+private:
+ QList<KeyEntry> table;
+public: //FIXME: we'd do better
+ QString hdr;
+ int numb;
+ QString path;
+};
+
+#endif
diff --git a/noncore/apps/opie-console/keytrans.o b/noncore/apps/opie-console/keytrans.o
new file mode 100644
index 0000000..2557f8a
--- a/dev/null
+++ b/noncore/apps/opie-console/keytrans.o
Binary files differ
diff --git a/noncore/apps/opie-console/screen.cpp b/noncore/apps/opie-console/screen.cpp
new file mode 100644
index 0000000..8ebc47d
--- a/dev/null
+++ b/noncore/apps/opie-console/screen.cpp
@@ -0,0 +1,1197 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [screen.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 Screen
+
+ \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 "screen.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 `Screen' of `lines' lines and `columns' columns.
+*/
+
+Screen::Screen(int lines, int columns)
+{
+ this->lines = lines;
+ this->columns = columns;
+
+ image = (Character*) malloc(lines*columns*sizeof(Character));
+ tabstops = NULL; initTabStops();
+
+ histCursor = 0;
+
+ clearSelection();
+ reset();
+}
+
+/*! Destructor
+*/
+
+Screen::~Screen()
+{
+ 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 Screen::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 Screen::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 Screen::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 Screen::cursorRight(int n)
+//=CUF
+{
+ if (n == 0) n = 1; // Default
+ cuX = QMIN(columns-1,cuX+n);
+}
+
+/*!
+ Set top and bottom margin.
+*/
+
+void Screen::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 Screen::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 Screen::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 Screen::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 Screen::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 Screen::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 Screen::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 Screen::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 Screen::insertLines(int n)
+{
+ if (n == 0) n = 1; // Default
+ scrollDown(cuY,n);
+}
+
+// Mode Operations -----------------------------------------------------------
+
+/*! Set a specific mode. */
+
+void Screen::setMode(int m)
+{
+ currParm.mode[m] = TRUE;
+ switch(m)
+ {
+ case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home
+ }
+}
+
+/*! Reset a specific mode. */
+
+void Screen::resetMode(int m)
+{
+ currParm.mode[m] = FALSE;
+ switch(m)
+ {
+ case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home
+ }
+}
+
+/*! Save a specific mode. */
+
+void Screen::saveMode(int m)
+{
+ saveParm.mode[m] = currParm.mode[m];
+}
+
+/*! Restore a specific mode. */
+
+void Screen::restoreMode(int m)
+{
+ currParm.mode[m] = saveParm.mode[m];
+}
+
+//NOTE: this is a helper function
+/*! Return the setting a specific mode. */
+BOOL Screen::getMode(int m)
+{
+ return currParm.mode[m];
+}
+
+/*! Save the cursor position and the rendition attribute settings. */
+
+void Screen::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 Screen::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 Screen::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
+ Character* newimg = (Character*) malloc(new_lines*new_columns*sizeof(Character));
+
+ 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 Screen::reverseRendition(Character* p)
+{ UINT8 f = p->f; UINT8 b = p->b;
+ p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT;
+}
+
+void Screen::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.
+
+*/
+
+Character* Screen::getCookedImage()
+{ int x,y;
+ Character* merged = (Character*) malloc(lines*columns*sizeof(Character));
+ Character 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 Screen::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 Screen::clear()
+{
+ clearEntireScreen();
+ home();
+}
+
+/*! Moves the cursor left one column.
+*/
+
+void Screen::BackSpace()
+{
+ cuX = QMAX(0,cuX-1);
+ if (BS_CLEARS) image[loc(cuX,cuY)].c = ' ';
+}
+
+/*!
+*/
+
+void Screen::Tabulate()
+{
+ // note that TAB is a format effector (does not write ' ');
+ cursorRight(1); while(cuX < columns-1 && !tabstops[cuX]) cursorRight(1);
+}
+
+void Screen::clearTabStops()
+{
+ for (int i = 0; i < columns; i++) tabstops[i-1] = FALSE;
+}
+
+void Screen::changeTabStop(bool set)
+{
+ if (cuX >= columns) return;
+ tabstops[cuX] = set;
+}
+
+void Screen::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 Screen::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 Screen::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 Screen::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 Screen::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 Screen::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 Screen::setCursorYX(int y, int x)
+{
+ setCursorY(y); setCursorX(x);
+}
+
+/*! Set the cursor to x-th line. */
+
+void Screen::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 Screen::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 Screen::home()
+{
+ cuX = 0;
+ cuY = 0;
+}
+
+/*! set cursor to the begin of the current line.
+*/
+
+void Screen::Return()
+{
+ cuX = 0;
+}
+
+/*! returns the current cursor columns.
+*/
+
+int Screen::getCursorX()
+{
+ return cuX;
+}
+
+/*! returns the current cursor line.
+*/
+
+int Screen::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 Screen::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 Screen::moveImage(int dst, int loca, int loce)
+{
+//FIXME: check positions
+ if (loce < loca) {
+ // kdDebug() << "WARNING!!! call to Screen:moveImage with loce < loca!" << endl;
+ return;
+ }
+ memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(Character));
+}
+
+/*! clear from (including) current cursor position to end of screen.
+*/
+
+void Screen::clearToEndOfScreen()
+{
+ clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
+}
+
+/*! clear from begin of screen to (including) current cursor position.
+*/
+
+void Screen::clearToBeginOfScreen()
+{
+ clearImage(loc(0,0),loc(cuX,cuY),' ');
+}
+
+/*! clear the entire screen.
+*/
+
+void Screen::clearEntireScreen()
+{
+ clearImage(loc(0,0),loc(columns-1,lines-1),' ');
+}
+
+/*! fill screen with 'E'
+ This is to aid screen alignment
+*/
+
+void Screen::helpAlign()
+{
+ clearImage(loc(0,0),loc(columns-1,lines-1),'E');
+}
+
+/*! clear from (including) current cursor position to end of current cursor line.
+*/
+
+void Screen::clearToEndOfLine()
+{
+ clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
+}
+
+/*! clear from begin of current cursor line to (including) current cursor position.
+*/
+
+void Screen::clearToBeginOfLine()
+{
+ clearImage(loc(0,cuY),loc(cuX,cuY),' ');
+}
+
+/*! clears entire current cursor line
+*/
+
+void Screen::clearEntireLine()
+{
+ clearImage(loc(0,cuY),loc(columns-1,cuY),' ');
+}
+
+// Rendition ------------------------------------------------------------------
+
+/*!
+ set rendition mode
+*/
+
+void Screen::setRendition(int re)
+{
+ cu_re |= re;
+ effectiveRendition();
+}
+
+/*!
+ reset rendition mode
+*/
+
+void Screen::resetRendition(int re)
+{
+ cu_re &= ~re;
+ effectiveRendition();
+}
+
+/*!
+*/
+
+void Screen::setDefaultRendition()
+{
+ setForeColorToDefault();
+ setBackColorToDefault();
+ cu_re = DEFAULT_RENDITION;
+ effectiveRendition();
+}
+
+/*!
+*/
+
+void Screen::setForeColor(int fgcolor)
+{
+ cu_fg = (fgcolor&7)+((fgcolor&8) ? 4+8 : 2);
+ effectiveRendition();
+}
+
+/*!
+*/
+
+void Screen::setBackColor(int bgcolor)
+{
+ cu_bg = (bgcolor&7)+((bgcolor&8) ? 4+8 : 2);
+ effectiveRendition();
+}
+
+/*!
+*/
+
+void Screen::setBackColorToDefault()
+{
+ cu_bg = DEFAULT_BACK_COLOR;
+ effectiveRendition();
+}
+
+/*!
+*/
+
+void Screen::setForeColorToDefault()
+{
+ cu_fg = DEFAULT_FORE_COLOR;
+ effectiveRendition();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Marking & Selection */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void Screen::clearSelection()
+{
+ sel_BR = -1;
+ sel_TL = -1;
+ sel_begin = -1;
+}
+
+void Screen::setSelBeginXY(const int x, const int y)
+{
+ sel_begin = loc(x,y+histCursor) ;
+ sel_BR = sel_begin;
+ sel_TL = sel_begin;
+}
+
+void Screen::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 Screen::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 Screen::addHistLine()
+{
+ assert(hasScroll() || histCursor == 0);
+
+ // add to hist buffer
+ // we have to take care about scrolling, too...
+
+ if (hasScroll())
+ { Character 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 Screen::setHistCursor(int cursor)
+{
+ histCursor = cursor; //FIXME:rangecheck
+}
+
+int Screen::getHistCursor()
+{
+ return histCursor;
+}
+
+int Screen::getHistLines()
+{
+ return hist.getLines();
+}
+
+void Screen::setScroll(bool on)
+{
+ histCursor = 0;
+ clearSelection();
+ hist.setScroll(on);
+}
+
+bool Screen::hasScroll()
+{
+ return hist.hasScroll();
+}
diff --git a/noncore/apps/opie-console/screen.h b/noncore/apps/opie-console/screen.h
new file mode 100644
index 0000000..cd7422a
--- a/dev/null
+++ b/noncore/apps/opie-console/screen.h
@@ -0,0 +1,259 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [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 SCREEN_H
+#define SCREEN_H
+
+/*! \file
+*/
+
+#include "common.h"
+#include "history.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 Screen
+{
+public:
+ Screen(int lines, int columns);
+ ~Screen();
+
+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);
+ //
+ Character* 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(Character* 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;
+ Character *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/screen.o b/noncore/apps/opie-console/screen.o
new file mode 100644
index 0000000..b2d0420
--- a/dev/null
+++ b/noncore/apps/opie-console/screen.o
Binary files differ
diff --git a/noncore/apps/opie-console/vt102emulation.cpp b/noncore/apps/opie-console/vt102emulation.cpp
new file mode 100644
index 0000000..dc977f5
--- a/dev/null
+++ b/noncore/apps/opie-console/vt102emulation.cpp
@@ -0,0 +1,1029 @@
+/* ------------------------------------------------------------------------- */
+/* */
+/* [vt102emulation.cpp] 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 Vt102Emulation
+
+ \brief Actual Emulation for Konsole
+
+ \sa Widget \sa Screen \sa EmulationLayer
+*/
+
+#include "vt102emulation.h"
+#include "widget.h"
+#include "screen.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.
+*/
+
+/*!
+*/
+
+Vt102Emulation::Vt102Emulation(Widget* gui) : EmulationLayer(gui)
+{
+ QObject::connect(gui,SIGNAL(mouseSignal(int,int,int)),
+ this,SLOT(onMouse(int,int,int)));
+ initTokenizer();
+ reset();
+}
+
+/*!
+*/
+
+Vt102Emulation::~Vt102Emulation()
+{
+}
+
+/*!
+*/
+
+void Vt102Emulation::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 Vt102Emulation::resetToken()
+{
+ ppos = 0; argc = 0; argv[0] = 0; argv[1] = 0;
+}
+
+void Vt102Emulation::addDigit(int dig)
+{
+ argv[argc] = 10*argv[argc] + dig;
+}
+
+void Vt102Emulation::addArgument()
+{
+ argc = QMIN(argc+1,MAXARGS-1);
+ argv[argc] = 0;
+}
+
+void Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::sendString(const char* s)
+{
+ QByteArray tmp;
+ tmp.setRawData( s, strlen( s ));
+ emit sndBlock( tmp);
+}
+
+void Vt102Emulation::sendString(const QByteArray s)
+{
+ emit sndBlock( s );
+}
+
+// Replies ----------------------------------------------------------------- --
+
+// This section copes with replies send as response to an enquiery control code.
+
+/*!
+*/
+
+void Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::reportTerminalParms(int p)
+// DECREPTPARM
+{ char tmp[100];
+ sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true.
+ sendString(tmp);
+}
+
+/*!
+*/
+
+void Vt102Emulation::reportStatus()
+{
+ sendString("\033[0n"); //VT100. Device status report. 0 = Ready.
+}
+
+/*!
+*/
+
+#define ANSWER_BACK "" // This is really obsolete VT100 stuff.
+
+void Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::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 : sendString( txt ); 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
+ sendString( s ); // 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 Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::setAndUseCharset(int n, int cs)
+{
+ CHARSET.charset[n&3] = cs;
+ useCharset(n&3);
+}
+
+/*!
+*/
+
+void Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::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 Vt102Emulation::saveMode(int m)
+{
+ saveParm.mode[m] = currParm.mode[m];
+}
+
+void Vt102Emulation::restoreMode(int m)
+{
+ if(saveParm.mode[m]) setMode(m); else resetMode(m);
+}
+
+BOOL Vt102Emulation::getMode(int m)
+{
+ return currParm.mode[m];
+}
+
+void Vt102Emulation::setConnect(bool c)
+{
+ EmulationLayer::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 Vt102Emulation::scan_buffer_report()
+{
+ if (ppos == 0 || ppos == 1 && (pbuf[0] & 0xff) >= 32) return;
+ printf("token: "); hexdump(pbuf,ppos); printf("\n");
+}
+
+/*!
+*/
+
+void Vt102Emulation::ReportErrorToken()
+{
+ printf("undecodable "); scan_buffer_report();
+}
diff --git a/noncore/apps/opie-console/vt102emulation.h b/noncore/apps/opie-console/vt102emulation.h
new file mode 100644
index 0000000..018835e
--- a/dev/null
+++ b/noncore/apps/opie-console/vt102emulation.h
@@ -0,0 +1,153 @@
+/* -------------------------------------------------------------------------- */
+/* */
+/* [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> */
+/* */
+/* -------------------------------------------------------------------------- */
+/* Ported embedded-konsole to opie-terminal */
+/* */
+/* Copyright (C) 2002 by opie developers <opie@handhelds.org> */
+/* */
+/* -------------------------------------------------------------------------- */
+
+#ifndef VT102EMU_H
+#define VT102EMU_H
+
+#include "widget.h"
+#include "screen.h"
+#include "emulation_layer.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 Vt102Emulation: public EmulationLayer
+{ Q_OBJECT
+
+public:
+
+ Vt102Emulation(Widget* gui);
+ ~Vt102Emulation();
+
+public slots: // signals incoming from Widget
+
+ void onKeyPress(QKeyEvent*);
+ void onMouse(int cb, int cx, int cy);
+
+signals:
+
+ void changeTitle(int,const QString&);
+ void prevSession();
+ void nextSession();
+
+public:
+
+ void reset();
+
+ /**
+ * receive a char from IOLayer
+ */
+ void onRcvChar(int cc);
+
+ /**
+ * sends a list of bytes to the IOLayer
+ */
+ void sendString(const QByteArray);
+
+ /**
+ * @deprecated use QByteArray instead
+ * see sendString() above
+ */
+ 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/vt102emulation.o b/noncore/apps/opie-console/vt102emulation.o
new file mode 100644
index 0000000..009a4fa
--- a/dev/null
+++ b/noncore/apps/opie-console/vt102emulation.o
Binary files differ