summaryrefslogtreecommitdiffstats
path: root/konsole/konsole
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit4aed2c8219774f5d797760606b8489a92ddc5163 (patch)
tree3f8c130f7d269626bf6a9447407ef6c35954426a /konsole/konsole
downloadtdebase-4aed2c8219774f5d797760606b8489a92ddc5163.tar.gz
tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'konsole/konsole')
-rw-r--r--konsole/konsole/BlockArray.cpp327
-rw-r--r--konsole/konsole/BlockArray.h119
-rwxr-xr-xkonsole/konsole/MakeDefaults7
-rw-r--r--konsole/konsole/Makefile.am80
-rw-r--r--konsole/konsole/TECommon.h234
-rw-r--r--konsole/konsole/TEHistory.cpp626
-rw-r--r--konsole/konsole/TEHistory.h273
-rw-r--r--konsole/konsole/TEPty.cpp262
-rw-r--r--konsole/konsole/TEPty.h123
-rw-r--r--konsole/konsole/TEScreen.cpp1570
-rw-r--r--konsole/konsole/TEScreen.h279
-rw-r--r--konsole/konsole/TEWidget.cpp2326
-rw-r--r--konsole/konsole/TEWidget.h335
-rw-r--r--konsole/konsole/TEmuVt102.cpp1430
-rw-r--r--konsole/konsole/TEmuVt102.h146
-rw-r--r--konsole/konsole/TEmulation.cpp550
-rw-r--r--konsole/konsole/TEmulation.h149
-rw-r--r--konsole/konsole/default.keytab.h76
-rw-r--r--konsole/konsole/fontembedder.cpp119
-rw-r--r--konsole/konsole/keytrans.cpp755
-rw-r--r--konsole/konsole/keytrans.h100
-rw-r--r--konsole/konsole/konsole.cpp4341
-rw-r--r--konsole/konsole/konsole.h501
-rw-r--r--konsole/konsole/konsole_part.cpp1133
-rw-r--r--konsole/konsole/konsole_part.h241
-rw-r--r--konsole/konsole/konsole_wcwidth.cpp216
-rw-r--r--konsole/konsole/konsole_wcwidth.h19
-rw-r--r--konsole/konsole/konsolebookmarkhandler.cpp104
-rw-r--r--konsole/konsole/konsolebookmarkhandler.h62
-rw-r--r--konsole/konsole/konsolebookmarkmenu.cpp156
-rw-r--r--konsole/konsole/konsolebookmarkmenu.h72
-rw-r--r--konsole/konsole/konsoleiface.h49
-rw-r--r--konsole/konsole/kwrited.cpp143
-rw-r--r--konsole/konsole/kwrited.h56
-rw-r--r--konsole/konsole/linefont.h21
-rw-r--r--konsole/konsole/linefont.src786
-rw-r--r--konsole/konsole/main.cpp671
-rw-r--r--konsole/konsole/printsettings.cpp66
-rw-r--r--konsole/konsole/printsettings.h44
-rw-r--r--konsole/konsole/schema.cpp634
-rw-r--r--konsole/konsole/schema.h243
-rw-r--r--konsole/konsole/session.cpp838
-rw-r--r--konsole/konsole/session.h232
-rw-r--r--konsole/konsole/sessioniface.h51
-rw-r--r--konsole/konsole/x-konsole.desktop74
-rw-r--r--konsole/konsole/zmodem_dialog.cpp56
-rw-r--r--konsole/konsole/zmodem_dialog.h49
47 files changed, 20744 insertions, 0 deletions
diff --git a/konsole/konsole/BlockArray.cpp b/konsole/konsole/BlockArray.cpp
new file mode 100644
index 000000000..5a978bc5e
--- /dev/null
+++ b/konsole/konsole/BlockArray.cpp
@@ -0,0 +1,327 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 2000 by Stephan Kulow <coolo@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#include "BlockArray.h"
+#include <assert.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <kdebug.h>
+
+static int blocksize = 0;
+
+BlockArray::BlockArray()
+ : size(0),
+ current(size_t(-1)),
+ index(size_t(-1)),
+ lastmap(0),
+ lastmap_index(size_t(-1)),
+ lastblock(0), ion(-1),
+ length(0)
+{
+ // lastmap_index = index = current = size_t(-1);
+ if (blocksize == 0)
+ blocksize = ((sizeof(Block) / getpagesize()) + 1) * getpagesize();
+
+}
+
+BlockArray::~BlockArray()
+{
+ setHistorySize(0);
+ assert(!lastblock);
+}
+
+size_t BlockArray::append(Block *block)
+{
+ if (!size)
+ return size_t(-1);
+
+ ++current;
+ if (current >= size) current = 0;
+
+ int rc;
+ rc = lseek(ion, current * blocksize, SEEK_SET); if (rc < 0) { perror("HistoryBuffer::add.seek"); setHistorySize(0); return size_t(-1); }
+ rc = write(ion, block, blocksize); if (rc < 0) { perror("HistoryBuffer::add.write"); setHistorySize(0); return size_t(-1); }
+
+ length++;
+ if (length > size) length = size;
+
+ ++index;
+
+ delete block;
+ return current;
+}
+
+size_t BlockArray::newBlock()
+{
+ if (!size)
+ return size_t(-1);
+ append(lastblock);
+
+ lastblock = new Block();
+ return index + 1;
+}
+
+Block *BlockArray::lastBlock() const
+{
+ return lastblock;
+}
+
+bool BlockArray::has(size_t i) const
+{
+ if (i == index + 1)
+ return true;
+
+ if (i > index)
+ return false;
+ if (index - i >= length)
+ return false;
+ return true;
+}
+
+const Block* BlockArray::at(size_t i)
+{
+ if (i == index + 1)
+ return lastblock;
+
+ if (i == lastmap_index)
+ return lastmap;
+
+ if (i > index) {
+ kdDebug(1211) << "BlockArray::at() i > index\n";
+ return 0;
+ }
+
+// if (index - i >= length) {
+// kdDebug(1211) << "BlockArray::at() index - i >= length\n";
+// return 0;
+// }
+
+ size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ;
+
+ assert(j < size);
+ unmap();
+
+ Block *block = (Block*)mmap(0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize);
+
+ if (block == (Block*)-1) { perror("mmap"); return 0; }
+
+ lastmap = block;
+ lastmap_index = i;
+
+ return block;
+}
+
+void BlockArray::unmap()
+{
+ if (lastmap) {
+ int res = munmap((char*)lastmap, blocksize);
+ if (res < 0) perror("munmap");
+ }
+ lastmap = 0;
+ lastmap_index = size_t(-1);
+}
+
+bool BlockArray::setSize(size_t newsize)
+{
+ return setHistorySize(newsize * 1024 / blocksize);
+}
+
+bool BlockArray::setHistorySize(size_t newsize)
+{
+// kdDebug(1211) << "setHistorySize " << size << " " << newsize << endl;
+
+ if (size == newsize)
+ return false;
+
+ unmap();
+
+ if (!newsize) {
+ delete lastblock;
+ lastblock = 0;
+ if (ion >= 0) close(ion);
+ ion = -1;
+ current = size_t(-1);
+ return true;
+ }
+
+ if (!size) {
+ FILE* tmp = tmpfile();
+ if (!tmp) {
+ perror("konsole: cannot open temp file.\n");
+ } else {
+ ion = dup(fileno(tmp));
+ if (ion<0) {
+ perror("konsole: cannot dup temp file.\n");
+ fclose(tmp);
+ }
+ }
+ if (ion < 0)
+ return false;
+
+ assert(!lastblock);
+
+ lastblock = new Block();
+ size = newsize;
+ return false;
+ }
+
+ if (newsize > size) {
+ increaseBuffer();
+ size = newsize;
+ return false;
+ } else {
+ decreaseBuffer(newsize);
+ ftruncate(ion, length*blocksize);
+ size = newsize;
+
+ return true;
+ }
+}
+
+void moveBlock(FILE *fion, int cursor, int newpos, char *buffer2)
+{
+ int res = fseek(fion, cursor * blocksize, SEEK_SET);
+ if (res)
+ perror("fseek");
+ res = fread(buffer2, blocksize, 1, fion);
+ if (res != 1)
+ perror("fread");
+
+ res = fseek(fion, newpos * blocksize, SEEK_SET);
+ if (res)
+ perror("fseek");
+ res = fwrite(buffer2, blocksize, 1, fion);
+ if (res != 1)
+ perror("fwrite");
+ // printf("moving block %d to %d\n", cursor, newpos);
+}
+
+void BlockArray::decreaseBuffer(size_t newsize)
+{
+ if (index < newsize) // still fits in whole
+ return;
+
+ int offset = (current - (newsize - 1) + size) % size;
+
+ if (!offset)
+ return;
+
+ // The Block constructor could do somthing in future...
+ char *buffer1 = new char[blocksize];
+
+ FILE *fion = fdopen(dup(ion), "w+b");
+ if (!fion) {
+ delete [] buffer1;
+ perror("fdopen/dup");
+ return;
+ }
+
+ int firstblock;
+ if (current <= newsize) {
+ firstblock = current + 1;
+ } else {
+ firstblock = 0;
+ }
+
+ size_t oldpos;
+ for (size_t i = 0, cursor=firstblock; i < newsize; i++) {
+ oldpos = (size + cursor + offset) % size;
+ moveBlock(fion, oldpos, cursor, buffer1);
+ if (oldpos < newsize) {
+ cursor = oldpos;
+ } else
+ cursor++;
+ }
+
+ current = newsize - 1;
+ length = newsize;
+
+ delete [] buffer1;
+
+ fclose(fion);
+
+}
+
+void BlockArray::increaseBuffer()
+{
+ if (index < size) // not even wrapped once
+ return;
+
+ int offset = (current + size + 1) % size;
+ if (!offset) // no moving needed
+ return;
+
+ // The Block constructor could do somthing in future...
+ char *buffer1 = new char[blocksize];
+ char *buffer2 = new char[blocksize];
+
+ int runs = 1;
+ int bpr = size; // blocks per run
+
+ if (size % offset == 0) {
+ bpr = size / offset;
+ runs = offset;
+ }
+
+ FILE *fion = fdopen(dup(ion), "w+b");
+ if (!fion) {
+ perror("fdopen/dup");
+ delete [] buffer1;
+ delete [] buffer2;
+ return;
+ }
+
+ int res;
+ for (int i = 0; i < runs; i++)
+ {
+ // free one block in chain
+ int firstblock = (offset + i) % size;
+ res = fseek(fion, firstblock * blocksize, SEEK_SET);
+ if (res)
+ perror("fseek");
+ res = fread(buffer1, blocksize, 1, fion);
+ if (res != 1)
+ perror("fread");
+ int newpos = 0;
+ for (int j = 1, cursor=firstblock; j < bpr; j++)
+ {
+ cursor = (cursor + offset) % size;
+ newpos = (cursor - offset + size) % size;
+ moveBlock(fion, cursor, newpos, buffer2);
+ }
+ res = fseek(fion, i * blocksize, SEEK_SET);
+ if (res)
+ perror("fseek");
+ res = fwrite(buffer1, blocksize, 1, fion);
+ if (res != 1)
+ perror("fwrite");
+ }
+ current = size - 1;
+ length = size;
+
+ delete [] buffer1;
+ delete [] buffer2;
+
+ fclose(fion);
+
+}
+
diff --git a/konsole/konsole/BlockArray.h b/konsole/konsole/BlockArray.h
new file mode 100644
index 000000000..3b977babb
--- /dev/null
+++ b/konsole/konsole/BlockArray.h
@@ -0,0 +1,119 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 2000 by Stephan Kulow <coolo@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef BLOCKARRAY_H
+#define BLOCKARRAY_H
+
+#include <unistd.h>
+
+//#error Dont use in KDE 2.1
+
+#define BlockSize (1 << 12)
+#define ENTRIES ((BlockSize - sizeof(size_t) ) / sizeof(unsigned char))
+
+struct Block {
+ Block() { size = 0; }
+ unsigned char data[ENTRIES];
+ size_t size;
+};
+
+// ///////////////////////////////////////////////////////
+
+class BlockArray {
+public:
+ /**
+ * Creates a history file for holding
+ * maximal size blocks. If more blocks
+ * are requested, then it drops earlier
+ * added ones.
+ */
+ BlockArray();
+
+ /// destructor
+ ~BlockArray();
+
+ /**
+ * adds the Block at the end of history.
+ * This may drop other blocks.
+ *
+ * The ownership on the block is transfered.
+ * An unique index number is returned for accessing
+ * it later (if not yet droped then)
+ *
+ * Note, that the block may be dropped completely
+ * if history is turned off.
+ */
+ size_t append(Block *block);
+
+ /**
+ * gets the block at the index. Function may return
+ * 0 if the block isn't available any more.
+ *
+ * The returned block is strictly readonly as only
+ * maped in memory - and will be invalid on the next
+ * operation on this class.
+ */
+ const Block *at(size_t index);
+
+ /**
+ * reorders blocks as needed. If newsize is null,
+ * the history is emptied completely. The indices
+ * returned on append won't change their semantic,
+ * but they may not be valid after this call.
+ */
+ bool setHistorySize(size_t newsize);
+
+ size_t newBlock();
+
+ Block *lastBlock() const;
+
+ /**
+ * Convenient function to set the size in KBytes
+ * instead of blocks
+ */
+ bool setSize(size_t newsize);
+
+ size_t len() const { return length; }
+
+ bool has(size_t index) const;
+
+ size_t getCurrent() const { return current; }
+
+private:
+ void unmap();
+ void increaseBuffer();
+ void decreaseBuffer(size_t newsize);
+
+ size_t size;
+ // current always shows to the last inserted block
+ size_t current;
+ size_t index;
+
+ Block *lastmap;
+ size_t lastmap_index;
+ Block *lastblock;
+
+ int ion;
+ size_t length;
+
+};
+
+
+#endif
diff --git a/konsole/konsole/MakeDefaults b/konsole/konsole/MakeDefaults
new file mode 100755
index 000000000..1026e374f
--- /dev/null
+++ b/konsole/konsole/MakeDefaults
@@ -0,0 +1,7 @@
+#!/bin/sh
+# [MakeDefaults] Quote default configuration files
+
+# TODO. We should convert both schema and sessions
+# to the method demonstrated for keytrans.
+
+../tests/quote ../other/README.default.Keytab > default.keytab.h
diff --git a/konsole/konsole/Makefile.am b/konsole/konsole/Makefile.am
new file mode 100644
index 000000000..5b4876384
--- /dev/null
+++ b/konsole/konsole/Makefile.am
@@ -0,0 +1,80 @@
+# This file is part of Konsole - an X terminal for KDE
+
+# set the include path for X, qt and KDE
+INCLUDES = -I. $(all_includes)
+
+# you can add here more. This one gets installed
+# bin_PROGRAMS = kcmkonsole
+bin_PROGRAMS =
+noinst_PROGRAMS = fontembedder
+lib_LTLIBRARIES =
+kdeinit_LTLIBRARIES = konsole.la
+kde_module_LTLIBRARIES = libkonsolepart.la kded_kwrited.la
+
+libkonsolepart_la_SOURCES = TEPty.cpp BlockArray.cpp konsole_part.cpp \
+ schema.cpp \
+ session.cpp \
+ zmodem_dialog.cpp \
+ TEWidget.cpp \
+ TEmuVt102.cpp \
+ TEScreen.cpp konsole_wcwidth.cpp \
+ TEmulation.cpp \
+ TEHistory.cpp \
+ keytrans.cpp \
+ konsoleiface.skel \
+ sessioniface.skel
+
+libkonsolepart_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkonsolepart_la_LIBADD = $(XTESTLIB) $(LIB_KPARTS)
+
+fontembedder_SOURCES = fontembedder.cpp
+fontembedder_LDFLAGS = $(all_libraries)
+fontembedder_LDADD = $(LIB_QT)
+
+# kwrited kded module
+kded_kwrited_la_SOURCES = kwrited.cpp TEPty.cpp kwrited.skel
+kded_kwrited_la_LIBADD = $(LIB_KDECORE)
+kded_kwrited_la_LDFLAGS = $(all_libraries) -module -avoid-version
+
+# konsole kdeinit module
+konsole_la_SOURCES = TEPty.cpp BlockArray.cpp main.cpp konsole.cpp schema.cpp session.cpp TEWidget.cpp TEmuVt102.cpp \
+ TEScreen.cpp TEmulation.cpp TEHistory.cpp keytrans.cpp konsoleiface.skel sessioniface.skel \
+ konsole_wcwidth.cpp konsolebookmarkhandler.cpp konsolebookmarkmenu.cpp \
+ zmodem_dialog.cpp printsettings.cpp
+konsole_la_LDFLAGS = $(all_libraries) -module -avoid-version
+konsole_la_LIBADD = $(LIB_KDEUI) $(LIB_KIO) $(LIB_KDEPRINT) $(LIBUTIL) $(XTESTLIB) $(LIB_XRENDER)
+
+# kcmkonsole_SOURCES = kcmkonsole.cpp schema.cpp
+# kcmkonsole_LDADD = $(LIB_KDEUI)
+# kcmkonsole_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+noinst_HEADERS = TEWidget.h TEPty.h TEmulation.h TEmuVt102.h \
+ TECommon.h TEScreen.h konsole.h schema.h session.h konsole_wcwidth.h \
+ kwrited.h TEHistory.h keytrans.h default.keytab.h BlockArray.h \
+ konsolebookmarkhandler.h konsolebookmarkmenu.h zmodem_dialog.h \
+ printsettings.h linefont.h
+
+METASOURCES = AUTO
+
+messages: rc.cpp
+ rm -f schemas.cpp
+ rm -f tips.cpp
+ (cd .. && $(PREPARETIPS) > konsole/tips.cpp)
+ for i in ../other/*.schema; do \
+ grep "^title" $$i | cut -d':' -f2- | sed -e 's#^title \(.*\)$$#i18n(\"\1\")#' >> schemas.cpp ;\
+ done
+ for i in ../other/*.Keytab ../other/*.keytab; do \
+ grep "^keyboard" $$i | sed -e 's#^keyboard \"\(.*\)\"$$#i18n(\"\1\")#' >> schemas.cpp ;\
+ done
+ $(XGETTEXT) *.cpp -o $(podir)/konsole.pot
+ rm -f schemas.cpp
+ rm -f tips.cpp
+
+# setting up x-application/konsole as a special mimetype
+mimedir = $(kde_mimedir)/application
+mime_DATA = x-konsole.desktop
+
+EXTRA_DIST = $(mime_DATA)
+
+fonts: fontembedder
+ ./fontembedder $(srcdir)/linefont.src > linefont.h
diff --git a/konsole/konsole/TECommon.h b/konsole/konsole/TECommon.h
new file mode 100644
index 000000000..c541fe0f1
--- /dev/null
+++ b/konsole/konsole/TECommon.h
@@ -0,0 +1,234 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+/*! \file TECommon.h
+ \brief Definitions shared between TEScreen and TEWidget.
+*/
+
+#ifndef TECOMMON_H
+#define TECOMMON_H
+
+#include <qcolor.h>
+
+#ifndef UINT8
+typedef unsigned char UINT8;
+#endif
+
+#ifndef UINT16
+typedef unsigned short UINT16;
+#endif
+
+// Color Table Elements ///////////////////////////////////////////////
+
+/*!
+*/
+struct ColorEntry
+{
+ ColorEntry(QColor c, bool tr, bool b) : color(c), transparent(tr), bold(b) {}
+ ColorEntry() : transparent(false), bold(false) {} // default constructors
+ void operator=(const ColorEntry& rhs) {
+ color = rhs.color;
+ transparent = rhs.transparent;
+ bold = rhs.bold;
+ }
+ QColor color;
+ bool transparent; // if used on bg
+ bool bold; // if used on fg
+};
+
+// Attributed Character Representations ///////////////////////////////
+
+// Colors
+
+#define BASE_COLORS (2+8)
+#define INTENSITIES 2
+#define TABLE_COLORS (INTENSITIES*BASE_COLORS)
+
+#define DEFAULT_FORE_COLOR 0
+#define DEFAULT_BACK_COLOR 1
+
+#define DEFAULT_RENDITION 0
+#define RE_BOLD (1 << 0)
+#define RE_BLINK (1 << 1)
+#define RE_UNDERLINE (1 << 2)
+#define RE_REVERSE (1 << 3) // Screen only
+#define RE_INTENSIVE (1 << 3) // Widget only
+#define RE_CURSOR (1 << 4)
+
+
+/* cacol is a union of the various color spaces.
+
+ Assignment is as follows:
+
+ Type - Space - Values
+
+ 0 - Undefined - u: 0, v:0 w:0
+ 1 - Default - u: 0..1 v:intense w:0
+ 2 - System - u: 0..7 v:intense w:0
+ 3 - Index(256) - u: 16..255 v:0 w:0
+ 4 - RGB - u: 0..255 v:0..256 w:0..256
+
+ Default colour space has two separate colours, namely
+ default foreground and default background colour.
+*/
+
+#define CO_UND 0
+#define CO_DFT 1
+#define CO_SYS 2
+#define CO_256 3
+#define CO_RGB 4
+
+class cacol
+{
+public:
+ cacol();
+ cacol(UINT8 space, int color);
+ UINT8 t; // color space indicator
+ UINT8 u; // various bytes representing the data in the respective ...
+ UINT8 v; // ... color space. C++ does not do unions, so we cannot ...
+ UINT8 w; // ... express ourselfs here, properly.
+ void toggleIntensive(); // Hack or helper?
+ QColor color(const ColorEntry* base) const;
+ friend bool operator == (cacol a, cacol b);
+ friend bool operator != (cacol a, cacol b);
+};
+
+#if 0
+inline cacol::cacol(UINT8 _t, UINT8 _u, UINT8 _v, UINT8 _w)
+: t(_t), u(_u), v(_v), w(_w)
+{
+}
+#else
+inline cacol::cacol(UINT8 ty, int co)
+: t(ty), u(0), v(0), w(0)
+{
+ switch (t)
+ {
+ case CO_UND: break;
+ case CO_DFT: u = co& 1; break;
+ case CO_SYS: u = co& 7; v = (co>>3)&1; break;
+ case CO_256: u = co&255; break;
+ case CO_RGB: u = co>>16; v = co>>8; w = co; break;
+ default : t = 0; break;
+ }
+}
+#endif
+
+inline cacol::cacol() // undefined, really
+: t(CO_UND), u(0), v(0), w(0)
+{
+}
+
+inline bool operator == (cacol a, cacol b)
+{
+ return a.t == b.t && a.u == b.u && a.v == b.v && a.w == b.w;
+}
+
+inline bool operator != (cacol a, cacol b)
+{
+ return a.t != b.t || a.u != b.u || a.v != b.v || a.w != b.w;
+}
+
+inline const QColor color256(UINT8 u, const ColorEntry* base)
+{
+ // 0.. 16: system colors
+ if (u < 8) return base[u+2 ].color; u -= 8;
+ if (u < 8) return base[u+2+BASE_COLORS].color; u -= 8;
+
+ // 16..231: 6x6x6 rgb color cube
+ if (u < 216) return QColor(255*((u/36)%6)/5,
+ 255*((u/ 6)%6)/5,
+ 255*((u/ 1)%6)/5); u -= 216;
+
+ // 232..255: gray, leaving out black and white
+ int gray = u*10+8; return QColor(gray,gray,gray);
+}
+
+inline QColor cacol::color(const ColorEntry* base) const
+{
+ switch (t)
+ {
+ case CO_DFT: return base[u+0+(v?BASE_COLORS:0)].color;
+ case CO_SYS: return base[u+2+(v?BASE_COLORS:0)].color;
+ case CO_256: return color256(u,base);
+ case CO_RGB: return QColor(u,v,w);
+ default : return QColor(255,0,0); // diagnostic catch all
+ }
+}
+
+inline void cacol::toggleIntensive()
+{
+ if (t == CO_SYS || t == CO_DFT)
+ {
+ v = !v;
+ }
+}
+
+/*! \class ca
+ * \brief a character with rendition attributes.
+*/
+
+class ca
+{
+public:
+ inline ca(UINT16 _c = ' ',
+ cacol _f = cacol(CO_DFT,DEFAULT_FORE_COLOR),
+ cacol _b = cacol(CO_DFT,DEFAULT_BACK_COLOR),
+ UINT8 _r = DEFAULT_RENDITION)
+ : c(_c), r(_r), f(_f), b(_b) {}
+public:
+ UINT16 c; // character
+ UINT8 r; // rendition
+ cacol f; // foreground color
+ cacol b; // background color
+public:
+ //FIXME: following a hack to cope with various color spaces
+ // it brings the rendition pipeline further out of balance,
+ // which it was anyway as the result of various additions.
+ bool isTransparent(const ColorEntry* base) const;
+ bool isBold(const ColorEntry* base) const;
+public:
+ friend bool operator == (ca a, ca b);
+ friend bool operator != (ca a, ca b);
+};
+
+inline bool operator == (ca a, ca b)
+{
+ return a.c == b.c && a.f == b.f && a.b == b.b && a.r == b.r;
+}
+
+inline bool operator != (ca a, ca b)
+{
+ return a.c != b.c || a.f != b.f || a.b != b.b || a.r != b.r;
+}
+
+inline bool ca::isTransparent(const ColorEntry* base) const
+{
+ return (b.t == CO_DFT) && base[b.u+0+(b.v?BASE_COLORS:0)].transparent
+ || (b.t == CO_SYS) && base[b.u+2+(b.v?BASE_COLORS:0)].transparent;
+}
+
+inline bool ca::isBold(const ColorEntry* base) const
+{
+ return (f.t == CO_DFT) && base[f.u+0+(f.v?BASE_COLORS:0)].bold
+ || (f.t == CO_SYS) && base[f.u+2+(f.v?BASE_COLORS:0)].bold;
+}
+
+#endif // TECOMMON_H
diff --git a/konsole/konsole/TEHistory.cpp b/konsole/konsole/TEHistory.cpp
new file mode 100644
index 000000000..5a0ee5477
--- /dev/null
+++ b/konsole/konsole/TEHistory.cpp
@@ -0,0 +1,626 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#include <iostream>
+#include "TEHistory.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <kdebug.h>
+
+// Reasonable line size
+#define LINE_SIZE 1024
+
+/*
+ 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 noticeable 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
+
+// History File ///////////////////////////////////////////
+
+/*
+ A Row(X) data type which allows adding elements to the end.
+*/
+
+HistoryFile::HistoryFile()
+ : ion(-1),
+ length(0)
+{
+ if (tmpFile.status() == 0)
+ {
+ tmpFile.unlink();
+ ion = tmpFile.handle();
+ }
+}
+
+HistoryFile::~HistoryFile()
+{
+}
+
+void HistoryFile::add(const unsigned char* bytes, int len)
+{
+ int rc = 0;
+
+ rc = lseek(ion,length,SEEK_SET); if (rc < 0) { perror("HistoryFile::add.seek"); return; }
+ rc = write(ion,bytes,len); if (rc < 0) { perror("HistoryFile::add.write"); return; }
+ length += rc;
+}
+
+void HistoryFile::get(unsigned char* bytes, int len, int loc)
+{
+ int rc = 0;
+
+ 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("HistoryFile::get.seek"); return; }
+ rc = read(ion,bytes,len); if (rc < 0) { perror("HistoryFile::get.read"); return; }
+}
+
+int HistoryFile::len()
+{
+ return length;
+}
+
+
+// History Scroll abstract base class //////////////////////////////////////
+
+
+HistoryScroll::HistoryScroll(HistoryType* t)
+ : m_histType(t)
+{
+}
+
+HistoryScroll::~HistoryScroll()
+{
+ delete m_histType;
+}
+
+bool HistoryScroll::hasScroll()
+{
+ return true;
+}
+
+// History Scroll File //////////////////////////////////////
+
+/*
+ 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.
+*/
+
+HistoryScrollFile::HistoryScrollFile(const QString &logFileName)
+ : HistoryScroll(new HistoryTypeFile(logFileName)),
+ m_logFileName(logFileName)
+{
+}
+
+HistoryScrollFile::~HistoryScrollFile()
+{
+}
+
+int HistoryScrollFile::getLines()
+{
+ return index.len() / sizeof(int);
+}
+
+int HistoryScrollFile::getLineLen(int lineno)
+{
+ return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(ca);
+}
+
+bool HistoryScrollFile::isWrappedLine(int lineno)
+{
+ if (lineno>=0 && lineno <= getLines()) {
+ unsigned char flag;
+ lineflags.get((unsigned char*)&flag,sizeof(unsigned char),(lineno)*sizeof(unsigned char));
+ return flag;
+ }
+ return false;
+}
+
+int HistoryScrollFile::startOfLine(int lineno)
+{
+ if (lineno <= 0) return 0;
+ if (lineno <= getLines())
+ { int res;
+ index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int));
+ return res;
+ }
+ return cells.len();
+}
+
+void HistoryScrollFile::getCells(int lineno, int colno, int count, ca res[])
+{
+ cells.get((unsigned char*)res,count*sizeof(ca),startOfLine(lineno)+colno*sizeof(ca));
+}
+
+void HistoryScrollFile::addCells(ca text[], int count)
+{
+ cells.add((unsigned char*)text,count*sizeof(ca));
+}
+
+void HistoryScrollFile::addLine(bool previousWrapped)
+{
+ int locn = cells.len();
+ index.add((unsigned char*)&locn,sizeof(int));
+ unsigned char flags = previousWrapped ? 0x01 : 0x00;
+ lineflags.add((unsigned char*)&flags,sizeof(unsigned char));
+}
+
+
+// History Scroll Buffer //////////////////////////////////////
+HistoryScrollBuffer::HistoryScrollBuffer(unsigned int maxNbLines)
+ : HistoryScroll(new HistoryTypeBuffer(maxNbLines)),
+ m_histBuffer(maxNbLines),
+ m_wrappedLine(maxNbLines),
+ m_maxNbLines(maxNbLines),
+ m_nbLines(0),
+ m_arrayIndex(maxNbLines - 1)
+{
+}
+
+HistoryScrollBuffer::~HistoryScrollBuffer()
+{
+ for(size_t line = 0; line < m_nbLines; ++line) {
+ delete m_histBuffer[adjustLineNb(line)];
+ }
+}
+
+void HistoryScrollBuffer::addCells(ca a[], int count)
+{
+ histline* newLine = new histline;
+
+ newLine->duplicate(a, count);
+
+ ++m_arrayIndex;
+ if (m_arrayIndex >= m_maxNbLines) {
+ m_arrayIndex = 0;
+ }
+
+ if (m_nbLines < m_maxNbLines) ++m_nbLines;
+
+ delete m_histBuffer[m_arrayIndex];
+ m_histBuffer.insert(m_arrayIndex, newLine);
+ m_wrappedLine.clearBit(m_arrayIndex);
+}
+
+void HistoryScrollBuffer::addLine(bool previousWrapped)
+{
+ m_wrappedLine.setBit(m_arrayIndex,previousWrapped);
+}
+
+int HistoryScrollBuffer::getLines()
+{
+ return m_nbLines; // m_histBuffer.size();
+}
+
+int HistoryScrollBuffer::getLineLen(int lineno)
+{
+ if (lineno >= (int) m_maxNbLines) return 0;
+
+ lineno = adjustLineNb(lineno);
+
+ histline *l = m_histBuffer[lineno];
+
+ return l ? l->size() : 0;
+}
+
+bool HistoryScrollBuffer::isWrappedLine(int lineno)
+{
+ if (lineno >= (int) m_maxNbLines)
+ return 0;
+
+ return m_wrappedLine[adjustLineNb(lineno)];
+}
+
+void HistoryScrollBuffer::getCells(int lineno, int colno, int count, ca res[])
+{
+ if (!count) return;
+
+ assert (lineno < (int) m_maxNbLines);
+
+ lineno = adjustLineNb(lineno);
+
+ histline *l = m_histBuffer[lineno];
+
+ if (!l) {
+ memset(res, 0, count * sizeof(ca));
+ return;
+ }
+
+ assert(colno <= (int) l->size() - count);
+
+ memcpy(res, l->data() + colno, count * sizeof(ca));
+}
+
+void HistoryScrollBuffer::setMaxNbLines(unsigned int nbLines)
+{
+ QPtrVector<histline> newHistBuffer(nbLines);
+ QBitArray newWrappedLine(nbLines);
+
+ size_t preservedLines = (nbLines > m_nbLines ? m_nbLines : nbLines); //min
+
+ // delete any lines that will be lost
+ size_t lineOld;
+ for(lineOld = 0; lineOld < m_nbLines - preservedLines; ++lineOld) {
+ delete m_histBuffer[adjustLineNb(lineOld)];
+ }
+
+ // copy the lines to new arrays
+ size_t indexNew = 0;
+ while(indexNew < preservedLines) {
+ newHistBuffer.insert(indexNew, m_histBuffer[adjustLineNb(lineOld)]);
+ newWrappedLine.setBit(indexNew, m_wrappedLine[adjustLineNb(lineOld)]);
+ ++lineOld;
+ ++indexNew;
+ }
+ m_arrayIndex = preservedLines - 1;
+
+ m_histBuffer = newHistBuffer;
+ m_wrappedLine = newWrappedLine;
+
+ m_maxNbLines = nbLines;
+ if (m_nbLines > m_maxNbLines)
+ m_nbLines = m_maxNbLines;
+
+ delete m_histType;
+ m_histType = new HistoryTypeBuffer(nbLines);
+}
+
+int HistoryScrollBuffer::adjustLineNb(int lineno)
+{
+ // lineno = 0: oldest line
+ // lineno = getLines() - 1: newest line
+
+ return (m_arrayIndex + lineno - (m_nbLines - 1) + m_maxNbLines) % m_maxNbLines;
+}
+
+
+// History Scroll None //////////////////////////////////////
+
+HistoryScrollNone::HistoryScrollNone()
+ : HistoryScroll(new HistoryTypeNone())
+{
+}
+
+HistoryScrollNone::~HistoryScrollNone()
+{
+}
+
+bool HistoryScrollNone::hasScroll()
+{
+ return false;
+}
+
+int HistoryScrollNone::getLines()
+{
+ return 0;
+}
+
+int HistoryScrollNone::getLineLen(int)
+{
+ return 0;
+}
+
+bool HistoryScrollNone::isWrappedLine(int /*lineno*/)
+{
+ return false;
+}
+
+void HistoryScrollNone::getCells(int, int, int, ca [])
+{
+}
+
+void HistoryScrollNone::addCells(ca [], int)
+{
+}
+
+void HistoryScrollNone::addLine(bool)
+{
+}
+
+// History Scroll BlockArray //////////////////////////////////////
+
+HistoryScrollBlockArray::HistoryScrollBlockArray(size_t size)
+ : HistoryScroll(new HistoryTypeBlockArray(size))
+{
+ m_lineLengths.setAutoDelete(true);
+ m_blockArray.setHistorySize(size); // nb. of lines.
+}
+
+HistoryScrollBlockArray::~HistoryScrollBlockArray()
+{
+}
+
+int HistoryScrollBlockArray::getLines()
+{
+// kdDebug(1211) << "HistoryScrollBlockArray::getLines() : "
+// << m_lineLengths.count() << endl;
+
+ return m_lineLengths.count();
+}
+
+int HistoryScrollBlockArray::getLineLen(int lineno)
+{
+ size_t *pLen = m_lineLengths[lineno];
+ size_t res = pLen ? *pLen : 0;
+
+ return res;
+}
+
+bool HistoryScrollBlockArray::isWrappedLine(int /*lineno*/)
+{
+ return false;
+}
+
+void HistoryScrollBlockArray::getCells(int lineno, int colno,
+ int count, ca res[])
+{
+ if (!count) return;
+
+ const Block *b = m_blockArray.at(lineno);
+
+ if (!b) {
+ memset(res, 0, count * sizeof(ca)); // still better than random data
+ return;
+ }
+
+ assert(((colno + count) * sizeof(ca)) < ENTRIES);
+ memcpy(res, b->data + (colno * sizeof(ca)), count * sizeof(ca));
+}
+
+void HistoryScrollBlockArray::addCells(ca a[], int count)
+{
+ Block *b = m_blockArray.lastBlock();
+
+ if (!b) return;
+
+ // put cells in block's data
+ assert((count * sizeof(ca)) < ENTRIES);
+
+ memset(b->data, 0, ENTRIES);
+
+ memcpy(b->data, a, count * sizeof(ca));
+ b->size = count * sizeof(ca);
+
+ size_t res = m_blockArray.newBlock();
+ assert (res > 0);
+ Q_UNUSED( res );
+
+ // store line length
+ size_t *pLen = new size_t;
+ *pLen = count;
+
+ m_lineLengths.replace(m_blockArray.getCurrent(), pLen);
+}
+
+void HistoryScrollBlockArray::addLine(bool)
+{
+}
+
+//////////////////////////////////////////////////////////////////////
+// History Types
+//////////////////////////////////////////////////////////////////////
+
+HistoryType::HistoryType()
+{
+}
+
+HistoryType::~HistoryType()
+{
+}
+
+//////////////////////////////
+
+HistoryTypeNone::HistoryTypeNone()
+{
+}
+
+bool HistoryTypeNone::isOn() const
+{
+ return false;
+}
+
+HistoryScroll* HistoryTypeNone::getScroll(HistoryScroll *old) const
+{
+ delete old;
+ return new HistoryScrollNone();
+}
+
+unsigned int HistoryTypeNone::getSize() const
+{
+ return 0;
+}
+
+//////////////////////////////
+
+HistoryTypeBlockArray::HistoryTypeBlockArray(size_t size)
+ : m_size(size)
+{
+}
+
+bool HistoryTypeBlockArray::isOn() const
+{
+ return true;
+}
+
+unsigned int HistoryTypeBlockArray::getSize() const
+{
+ return m_size;
+}
+
+HistoryScroll* HistoryTypeBlockArray::getScroll(HistoryScroll *old) const
+{
+ delete old;
+ return new HistoryScrollBlockArray(m_size);
+}
+
+
+//////////////////////////////
+
+HistoryTypeBuffer::HistoryTypeBuffer(unsigned int nbLines)
+ : m_nbLines(nbLines)
+{
+}
+
+bool HistoryTypeBuffer::isOn() const
+{
+ return true;
+}
+
+unsigned int HistoryTypeBuffer::getSize() const
+{
+ return m_nbLines;
+}
+
+HistoryScroll* HistoryTypeBuffer::getScroll(HistoryScroll *old) const
+{
+ if (old)
+ {
+ HistoryScrollBuffer *oldBuffer = dynamic_cast<HistoryScrollBuffer*>(old);
+ if (oldBuffer)
+ {
+ oldBuffer->setMaxNbLines(m_nbLines);
+ return oldBuffer;
+ }
+
+ HistoryScroll *newScroll = new HistoryScrollBuffer(m_nbLines);
+ int lines = old->getLines();
+ int startLine = 0;
+ if (lines > (int) m_nbLines)
+ startLine = lines - m_nbLines;
+
+ ca line[LINE_SIZE];
+ for(int i = startLine; i < lines; i++)
+ {
+ int size = old->getLineLen(i);
+ if (size > LINE_SIZE)
+ {
+ ca *tmp_line = new ca[size];
+ old->getCells(i, 0, size, tmp_line);
+ newScroll->addCells(tmp_line, size);
+ newScroll->addLine(old->isWrappedLine(i));
+ delete tmp_line;
+ }
+ else
+ {
+ old->getCells(i, 0, size, line);
+ newScroll->addCells(line, size);
+ newScroll->addLine(old->isWrappedLine(i));
+ }
+ }
+ delete old;
+ return newScroll;
+ }
+ return new HistoryScrollBuffer(m_nbLines);
+}
+
+//////////////////////////////
+
+HistoryTypeFile::HistoryTypeFile(const QString& fileName)
+ : m_fileName(fileName)
+{
+}
+
+bool HistoryTypeFile::isOn() const
+{
+ return true;
+}
+
+const QString& HistoryTypeFile::getFileName() const
+{
+ return m_fileName;
+}
+
+HistoryScroll* HistoryTypeFile::getScroll(HistoryScroll *old) const
+{
+ if (dynamic_cast<HistoryFile *>(old))
+ return old; // Unchanged.
+
+ HistoryScroll *newScroll = new HistoryScrollFile(m_fileName);
+
+ ca line[LINE_SIZE];
+ int lines = old->getLines();
+ for(int i = 0; i < lines; i++)
+ {
+ int size = old->getLineLen(i);
+ if (size > LINE_SIZE)
+ {
+ ca *tmp_line = new ca[size];
+ old->getCells(i, 0, size, tmp_line);
+ newScroll->addCells(tmp_line, size);
+ newScroll->addLine(old->isWrappedLine(i));
+ delete tmp_line;
+ }
+ else
+ {
+ old->getCells(i, 0, size, line);
+ newScroll->addCells(line, size);
+ newScroll->addLine(old->isWrappedLine(i));
+ }
+ }
+
+ delete old;
+ return newScroll;
+}
+
+unsigned int HistoryTypeFile::getSize() const
+{
+ return 0;
+}
diff --git a/konsole/konsole/TEHistory.h b/konsole/konsole/TEHistory.h
new file mode 100644
index 000000000..c8fa2f379
--- /dev/null
+++ b/konsole/konsole/TEHistory.h
@@ -0,0 +1,273 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef TEHISTORY_H
+#define TEHISTORY_H
+
+#include <qcstring.h>
+#include <qptrvector.h>
+#include <qbitarray.h>
+
+#include <ktempfile.h>
+
+#include "TECommon.h"
+
+#if 1
+/*
+ An extendable tmpfile(1) based buffer.
+*/
+
+class HistoryFile
+{
+public:
+ HistoryFile();
+ virtual ~HistoryFile();
+
+ virtual void add(const unsigned char* bytes, int len);
+ virtual void get(unsigned char* bytes, int len, int loc);
+ virtual int len();
+
+private:
+ int ion;
+ int length;
+ KTempFile tmpFile;
+};
+#endif
+
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+// Abstract base class for file and buffer versions
+//////////////////////////////////////////////////////////////////////
+class HistoryType;
+
+class HistoryScroll
+{
+public:
+ HistoryScroll(HistoryType*);
+ virtual ~HistoryScroll();
+
+ virtual bool hasScroll();
+
+ // access to history
+ virtual int getLines() = 0;
+ virtual int getLineLen(int lineno) = 0;
+ virtual void getCells(int lineno, int colno, int count, ca res[]) = 0;
+ virtual bool isWrappedLine(int lineno) = 0;
+
+ // backward compatibility (obsolete)
+ ca getCell(int lineno, int colno) { ca res; getCells(lineno,colno,1,&res); return res; }
+
+ // adding lines.
+ virtual void addCells(ca a[], int count) = 0;
+ virtual void addLine(bool previousWrapped=false) = 0;
+
+ const HistoryType& getType() { return *m_histType; }
+
+protected:
+ HistoryType* m_histType;
+
+};
+
+#if 1
+
+//////////////////////////////////////////////////////////////////////
+// File-based history (e.g. file log, no limitation in length)
+//////////////////////////////////////////////////////////////////////
+
+class HistoryScrollFile : public HistoryScroll
+{
+public:
+ HistoryScrollFile(const QString &logFileName);
+ virtual ~HistoryScrollFile();
+
+ virtual int getLines();
+ virtual int getLineLen(int lineno);
+ virtual void getCells(int lineno, int colno, int count, ca res[]);
+ virtual bool isWrappedLine(int lineno);
+
+ virtual void addCells(ca a[], int count);
+ virtual void addLine(bool previousWrapped=false);
+
+private:
+ int startOfLine(int lineno);
+
+ QString m_logFileName;
+ HistoryFile index; // lines Row(int)
+ HistoryFile cells; // text Row(ca)
+ HistoryFile lineflags; // flags Row(unsigned char)
+};
+
+
+//////////////////////////////////////////////////////////////////////
+// Buffer-based history (limited to a fixed nb of lines)
+//////////////////////////////////////////////////////////////////////
+class HistoryScrollBuffer : public HistoryScroll
+{
+public:
+ typedef QMemArray<ca> histline;
+
+ HistoryScrollBuffer(unsigned int maxNbLines = 1000);
+ virtual ~HistoryScrollBuffer();
+
+ virtual int getLines();
+ virtual int getLineLen(int lineno);
+ virtual void getCells(int lineno, int colno, int count, ca res[]);
+ virtual bool isWrappedLine(int lineno);
+
+ virtual void addCells(ca a[], int count);
+ virtual void addLine(bool previousWrapped=false);
+
+ void setMaxNbLines(unsigned int nbLines);
+ unsigned int maxNbLines() { return m_maxNbLines; }
+
+
+private:
+ int adjustLineNb(int lineno);
+
+ QPtrVector<histline> m_histBuffer;
+ QBitArray m_wrappedLine;
+ unsigned int m_maxNbLines;
+ unsigned int m_nbLines;
+ unsigned int m_arrayIndex;
+
+};
+
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Nothing-based history (no history :-)
+//////////////////////////////////////////////////////////////////////
+class HistoryScrollNone : public HistoryScroll
+{
+public:
+ HistoryScrollNone();
+ virtual ~HistoryScrollNone();
+
+ virtual bool hasScroll();
+
+ virtual int getLines();
+ virtual int getLineLen(int lineno);
+ virtual void getCells(int lineno, int colno, int count, ca res[]);
+ virtual bool isWrappedLine(int lineno);
+
+ virtual void addCells(ca a[], int count);
+ virtual void addLine(bool previousWrapped=false);
+};
+
+//////////////////////////////////////////////////////////////////////
+// BlockArray-based history
+//////////////////////////////////////////////////////////////////////
+#include "BlockArray.h"
+#include <qintdict.h>
+class HistoryScrollBlockArray : public HistoryScroll
+{
+public:
+ HistoryScrollBlockArray(size_t size);
+ virtual ~HistoryScrollBlockArray();
+
+ virtual int getLines();
+ virtual int getLineLen(int lineno);
+ virtual void getCells(int lineno, int colno, int count, ca res[]);
+ virtual bool isWrappedLine(int lineno);
+
+ virtual void addCells(ca a[], int count);
+ virtual void addLine(bool previousWrapped=false);
+
+protected:
+ BlockArray m_blockArray;
+ QIntDict<size_t> m_lineLengths;
+};
+
+//////////////////////////////////////////////////////////////////////
+// History type
+//////////////////////////////////////////////////////////////////////
+
+class HistoryType
+{
+public:
+ HistoryType();
+ virtual ~HistoryType();
+
+ virtual bool isOn() const = 0;
+ virtual unsigned int getSize() const = 0;
+
+ virtual HistoryScroll* getScroll(HistoryScroll *) const = 0;
+};
+
+class HistoryTypeNone : public HistoryType
+{
+public:
+ HistoryTypeNone();
+
+ virtual bool isOn() const;
+ virtual unsigned int getSize() const;
+
+ virtual HistoryScroll* getScroll(HistoryScroll *) const;
+};
+
+class HistoryTypeBlockArray : public HistoryType
+{
+public:
+ HistoryTypeBlockArray(size_t size);
+
+ virtual bool isOn() const;
+ virtual unsigned int getSize() const;
+
+ virtual HistoryScroll* getScroll(HistoryScroll *) const;
+
+protected:
+ size_t m_size;
+};
+
+#if 1 // Disabled for now
+class HistoryTypeFile : public HistoryType
+{
+public:
+ HistoryTypeFile(const QString& fileName=QString::null);
+
+ virtual bool isOn() const;
+ virtual const QString& getFileName() const;
+ virtual unsigned int getSize() const;
+
+ virtual HistoryScroll* getScroll(HistoryScroll *) const;
+
+protected:
+ QString m_fileName;
+};
+
+
+class HistoryTypeBuffer : public HistoryType
+{
+public:
+ HistoryTypeBuffer(unsigned int nbLines);
+
+ virtual bool isOn() const;
+ virtual unsigned int getSize() const;
+
+ virtual HistoryScroll* getScroll(HistoryScroll *) const;
+
+protected:
+ unsigned int m_nbLines;
+};
+
+#endif
+
+#endif // TEHISTORY_H
diff --git a/konsole/konsole/TEPty.cpp b/konsole/konsole/TEPty.cpp
new file mode 100644
index 000000000..e68ea8ff5
--- /dev/null
+++ b/konsole/konsole/TEPty.cpp
@@ -0,0 +1,262 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+/* If you're compiling konsole on non-Linux platforms and find
+ problems that you can track down to this file, please have
+ a look into ../README.ports, too.
+*/
+
+/*! \file
+*/
+
+
+/*! \class TEPty
+
+ \brief Ptys provide a pseudo terminal connection to a program.
+
+ Although closely related to pipes, these pseudo terminal connections have
+ some ability, that makes it nessesary to uses them. Most importent, they
+ know about changing screen sizes and UNIX job control.
+
+ Within the terminal emulation framework, this class represents the
+ host side of the terminal together with the connecting serial line.
+
+ One can create many instances of this class within a program.
+ As a side effect of using this class, a signal(2) handler is
+ installed on SIGCHLD.
+
+ \par FIXME
+
+ [NOTE: much of the technical stuff below will be replaced by forkpty.]
+
+ publish the SIGCHLD signal if not related to an instance.
+
+ clearify TEPty::done vs. TEPty::~TEPty semantics.
+ check if pty is restartable via run after done.
+
+ \par Pseudo terminals
+
+ Pseudo terminals are a unique feature of UNIX, and always come in form of
+ pairs of devices (/dev/ptyXX and /dev/ttyXX), which are connected to each
+ other by the operating system. One may think of them as two serial devices
+ linked by a null-modem cable. Being based on devices the number of
+ simultanous instances of this class is (globally) limited by the number of
+ those device pairs, which is 256.
+
+ Another technic are UNIX 98 PTY's. These are supported also, and preferred
+ over the (obsolete) predecessor.
+
+ There's a sinister ioctl(2), signal(2) and job control stuff
+ nessesary to make everything work as it should.
+
+ Much of the stuff can be simplified by using openpty from glibc2.
+ Compatibility issues with obsolete installations and other unixes
+ my prevent this.
+*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <termios.h>
+
+#include <kstandarddirs.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kpty.h>
+
+#include "TEPty.h"
+
+
+void TEPty::donePty()
+{
+ emit done(exitStatus());
+}
+
+void TEPty::setSize(int lines, int cols)
+{
+ pty()->setWinSize(lines, cols);
+}
+
+void TEPty::setXonXoff(bool on)
+{
+ pty()->setXonXoff(on);
+}
+
+void TEPty::useUtf8(bool on)
+{
+ pty()->setUtf8Mode(on);
+}
+
+void TEPty::setErase(char erase)
+{
+ struct termios tios;
+ int fd = pty()->slaveFd();
+
+ if(tcgetattr(fd, &tios))
+ {
+ qWarning("Uh oh.. can't get terminal attributes..");
+ return;
+ }
+ tios.c_cc[VERASE] = erase;
+ if(tcsetattr(fd, TCSANOW, &tios))
+ qWarning("Uh oh.. can't set terminal attributes..");
+}
+
+/*!
+ start the client program.
+*/
+int TEPty::run(const char* _pgm, QStrList & _args, const char* _term, ulong winid, bool _addutmp,
+ const char* _konsole_dcop, const char* _konsole_dcop_session)
+{
+ clearArguments();
+
+ setBinaryExecutable(_pgm);
+
+ QStrListIterator it( _args );
+ for (; it.current(); ++it )
+ arguments.append(it.current());
+
+ if (_term && _term[0])
+ setEnvironment("TERM",_term);
+ if (_konsole_dcop && _konsole_dcop[0])
+ setEnvironment("KONSOLE_DCOP",_konsole_dcop);
+ if (_konsole_dcop_session && _konsole_dcop_session[0])
+ setEnvironment("KONSOLE_DCOP_SESSION", _konsole_dcop_session);
+ setEnvironment("WINDOWID", QString::number(winid));
+
+ setUsePty(All, _addutmp);
+
+ if ( start(NotifyOnExit, (Communication) (Stdin | Stdout)) == false )
+ return -1;
+
+ resume(); // Start...
+ return 0;
+
+}
+
+void TEPty::setWriteable(bool writeable)
+{
+ struct stat sbuf;
+ stat(pty()->ttyName(), &sbuf);
+ if (writeable)
+ chmod(pty()->ttyName(), sbuf.st_mode | S_IWGRP);
+ else
+ chmod(pty()->ttyName(), sbuf.st_mode & ~(S_IWGRP|S_IWOTH));
+}
+
+/*!
+ Create an instance.
+*/
+TEPty::TEPty()
+{
+ m_bufferFull = false;
+ connect(this, SIGNAL(receivedStdout(KProcess *, char *, int )),
+ this, SLOT(dataReceived(KProcess *,char *, int)));
+ connect(this, SIGNAL(processExited(KProcess *)),
+ this, SLOT(donePty()));
+ connect(this, SIGNAL(wroteStdin(KProcess *)),
+ this, SLOT(writeReady()));
+
+ setUsePty(All, false); // utmp will be overridden later
+}
+
+/*!
+ Destructor.
+*/
+TEPty::~TEPty()
+{
+}
+
+/*! sends a character through the line */
+void TEPty::send_byte(char c)
+{
+ send_bytes(&c,1);
+}
+
+/*! sends a 0 terminated string through the line */
+void TEPty::send_string(const char* s)
+{
+ send_bytes(s,strlen(s));
+}
+
+void TEPty::writeReady()
+{
+ pendingSendJobs.remove(pendingSendJobs.begin());
+ m_bufferFull = false;
+ doSendJobs();
+}
+
+void TEPty::doSendJobs() {
+ if(pendingSendJobs.isEmpty())
+ {
+ emit buffer_empty();
+ return;
+ }
+
+ SendJob& job = pendingSendJobs.first();
+ if (!writeStdin(job.buffer.data(), job.length))
+ {
+ qWarning("Uh oh.. can't write data..");
+ return;
+ }
+ m_bufferFull = true;
+}
+
+void TEPty::appendSendJob(const char* s, int len)
+{
+ pendingSendJobs.append(SendJob(s,len));
+}
+
+/*! sends len bytes through the line */
+void TEPty::send_bytes(const char* s, int len)
+{
+ appendSendJob(s,len);
+ if (!m_bufferFull)
+ doSendJobs();
+}
+
+/*! indicates that a block of data is received */
+void TEPty::dataReceived(KProcess *,char *buf, int len)
+{
+ emit block_in(buf,len);
+}
+
+void TEPty::lockPty(bool lock)
+{
+ if (lock)
+ suspend();
+ else
+ resume();
+}
+
+int TEPty::commSetupDoneC ()
+{
+ int ok = KProcess::commSetupDoneC ();
+ if ( ok ) {
+ emit forkedChild();
+ }
+ return ok;
+}
+
+#include "TEPty.moc"
diff --git a/konsole/konsole/TEPty.h b/konsole/konsole/TEPty.h
new file mode 100644
index 000000000..294fde8c7
--- /dev/null
+++ b/konsole/konsole/TEPty.h
@@ -0,0 +1,123 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef TE_PTY_H
+#define TE_PTY_H
+
+#include <config.h>
+
+#include <kprocess.h>
+#include <qsocketnotifier.h>
+#include <qstrlist.h>
+#include <qvaluelist.h>
+#include <qmemarray.h>
+
+class TEPty: public KProcess
+{
+Q_OBJECT
+
+ public:
+
+ TEPty();
+ ~TEPty();
+
+ public:
+
+ /*!
+ * having a `run' separate from the constructor allows to make
+ * the necessary connections to the signals and slots of the
+ * instance before starting the execution of the client.
+ */
+ int run( const char* pgm, QStrList & args, const char* term, ulong winid, bool _addutmp,
+ const char* konsole_dcop = "", const char* konsole_dcop_session = "" );
+ void setWriteable(bool writeable);
+ QString error() { return m_strError; }
+ void setXonXoff(bool on);
+ void setSize(int lines, int cols);
+ void setErase(char erase);
+
+ public slots:
+ void useUtf8(bool on);
+ void lockPty(bool lock);
+ void send_bytes(const char* s, int len);
+
+ signals:
+
+ /*!
+ emitted when the client program terminates.
+ */
+ void done(int returnCode);
+
+ /*!
+ emitted when a new block of data comes in.
+ \param s - the data
+ \param len - the length of the block
+ */
+ void block_in(const char* s, int len);
+
+ /*!
+ emitted when buffer_full becomes false
+ */
+ void buffer_empty();
+
+ // this will be emitted in the child process
+ // after forking (and, obviously, before exec())
+ void forkedChild();
+
+ public:
+
+ void send_byte(char s);
+ void send_string(const char* s);
+ bool buffer_full() { return m_bufferFull; }
+
+ // override from KProcess to allow the client of konsolePart
+ // to set up things after fork() but before exec()
+ virtual int commSetupDoneC();
+
+ protected slots:
+ void dataReceived(KProcess *, char *buf, int len);
+ public slots:
+ void donePty();
+
+ private:
+ void appendSendJob(const char* s, int len);
+
+ private slots:
+ void doSendJobs();
+ void writeReady();
+
+ private:
+
+ QString m_strError;
+
+ struct SendJob {
+ SendJob() {}
+ SendJob(const char* b, int len) {
+ buffer.duplicate(b,len);
+ length = len;
+ }
+ QMemArray<char> buffer;
+ int length;
+ };
+ QValueList<SendJob> pendingSendJobs;
+ bool m_bufferFull;
+};
+
+#endif
diff --git a/konsole/konsole/TEScreen.cpp b/konsole/konsole/TEScreen.cpp
new file mode 100644
index 000000000..dba8ebd22
--- /dev/null
+++ b/konsole/konsole/TEScreen.cpp
@@ -0,0 +1,1570 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+/*! \class TEScreen
+
+ \brief The image manipulated by the emulation.
+
+ This class implements the operations of the terminal emulation framework.
+ It is a complete passive device, driven by the emulation decoder
+ (TEmuVT102). By this it forms in fact an ADT, that defines operations
+ on a rectangular image.
+
+ It does neither know how to display its image nor about escape sequences.
+ It is further independent of the underlying toolkit. By this, one can even
+ use this module for an ordinary text surface.
+
+ Since the operations are called by a specific emulation decoder, one may
+ collect their different operations here.
+
+ The state manipulated by the operations is mainly kept in `image', though
+ it is a little more complex bejond this. See the header file of the class.
+
+ \sa TEWidget \sa VT102Emulation
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <kdebug.h>
+
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "konsole_wcwidth.h"
+#include "TEScreen.h"
+
+//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
+
+#ifndef loc
+#define loc(X,Y) ((Y)*columns+(X))
+#endif
+
+//#define REVERSE_WRAPPED_LINES // for wrapped line debug
+
+/*! creates a `TEScreen' of `lines' lines and `columns' columns.
+*/
+
+TEScreen::TEScreen(int l, int c)
+ : lines(l),
+ columns(c),
+ image(new ca[(lines+1)*columns]),
+ histCursor(0),
+ hist(new HistoryScrollNone()),
+ cuX(0), cuY(0),
+ cu_fg(cacol()), cu_bg(cacol()), cu_re(0),
+ tmargin(0), bmargin(0),
+ tabstops(0),
+ sel_begin(0), sel_TL(0), sel_BR(0),
+ sel_busy(false),
+ columnmode(false),
+ ef_fg(cacol()), ef_bg(cacol()), ef_re(0),
+ sa_cuX(0), sa_cuY(0),
+ sa_cu_re(0), sa_cu_fg(cacol()), sa_cu_bg(cacol()),
+ lastPos(-1)
+{
+ /*
+ this->lines = lines;
+ this->columns = columns;
+
+ // we add +1 here as under some weired circumstances konsole crashes
+ // reading out of bound. As a crash is worse, we afford the minimum
+ // of added memory
+ image = (ca*) malloc((lines+1)*columns*sizeof(ca));
+ tabstops = NULL; initTabStops();
+ cuX = cuY = sa_cu_re = cu_re = sa_cu_fg = cu_fg = sa_cu_bg = cu_bg = 0;
+
+ histCursor = 0;
+ */
+ line_wrapped.resize(lines+1);
+ initTabStops();
+ clearSelection();
+ reset();
+}
+
+/*! Destructor
+*/
+
+TEScreen::~TEScreen()
+{
+ delete[] image;
+ delete[] tabstops;
+ delete hist;
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Normalized Screen Operations */
+/* */
+/* ------------------------------------------------------------------------- */
+
+// Cursor Setting --------------------------------------------------------------
+
+/*! \section Cursor
+
+ The `cursor' is a location within the screen that is implicitely used in
+ many operations. The operations within this section allow to manipulate
+ the cursor explicitly and to obtain it's value.
+
+ The position of the cursor is guarantied to be between (including) 0 and
+ `columns-1' and `lines-1'.
+*/
+
+/*!
+ Move the cursor up.
+
+ The cursor will not be moved beyond the top margin.
+*/
+
+void TEScreen::cursorUp(int n)
+//=CUU
+{
+ if (n == 0) n = 1; // Default
+ int stop = cuY < tmargin ? 0 : tmargin;
+ cuX = QMIN(columns-1,cuX); // nowrap!
+ cuY = QMAX(stop,cuY-n);
+}
+
+/*!
+ Move the cursor down.
+
+ The cursor will not be moved beyond the bottom margin.
+*/
+
+void TEScreen::cursorDown(int n)
+//=CUD
+{
+ if (n == 0) n = 1; // Default
+ int stop = cuY > bmargin ? lines-1 : bmargin;
+ cuX = QMIN(columns-1,cuX); // nowrap!
+ cuY = QMIN(stop,cuY+n);
+}
+
+/*!
+ Move the cursor left.
+
+ The cursor will not move beyond the first column.
+*/
+
+void TEScreen::cursorLeft(int n)
+//=CUB
+{
+ if (n == 0) n = 1; // Default
+ cuX = QMIN(columns-1,cuX); // nowrap!
+ cuX = QMAX(0,cuX-n);
+}
+
+/*!
+ Move the cursor left.
+
+ The cursor will not move beyond the rightmost column.
+*/
+
+void TEScreen::cursorRight(int n)
+//=CUF
+{
+ if (n == 0) n = 1; // Default
+ cuX = QMIN(columns-1,cuX+n);
+}
+
+/*!
+ Set top and bottom margin.
+*/
+
+void TEScreen::setMargins(int top, int bot)
+//=STBM
+{
+ if (top == 0) top = 1; // Default
+ if (bot == 0) bot = lines; // Default
+ top = top - 1; // Adjust to internal lineno
+ bot = bot - 1; // Adjust to internal lineno
+ if ( !( 0 <= top && top < bot && bot < lines ) )
+ { kdDebug()<<" setRegion("<<top<<","<<bot<<") : bad range."<<endl;
+ return; // Default error action: ignore
+ }
+ tmargin = top;
+ bmargin = bot;
+ cuX = 0;
+ cuY = getMode(MODE_Origin) ? top : 0;
+}
+
+/*!
+ Move the cursor down one line.
+
+ If cursor is on bottom margin, the region between the
+ actual top and bottom margin is scrolled up instead.
+*/
+
+void TEScreen::index()
+//=IND
+{
+ if (cuY == bmargin)
+ {
+ scrollUp(1);
+ }
+ else if (cuY < lines-1)
+ cuY += 1;
+}
+
+/*!
+ Move the cursor up one line.
+
+ If cursor is on the top margin, the region between the
+ actual top and bottom margin is scrolled down instead.
+*/
+
+void TEScreen::reverseIndex()
+//=RI
+{
+ if (cuY == tmargin)
+ scrollDown(tmargin,1);
+ else if (cuY > 0)
+ cuY -= 1;
+}
+
+/*!
+ Move the cursor to the begin of the next line.
+
+ If cursor is on bottom margin, the region between the
+ actual top and bottom margin is scrolled up.
+*/
+
+void TEScreen::NextLine()
+//=NEL
+{
+ Return(); index();
+}
+
+// Line Editing ----------------------------------------------------------------
+
+/*! \section inserting / deleting characters
+*/
+
+/*! erase `n' characters starting from (including) the cursor position.
+
+ The line is filled in from the right with spaces.
+*/
+
+void TEScreen::eraseChars(int n)
+{
+ if (n == 0) n = 1; // Default
+ int p = QMAX(0,QMIN(cuX+n-1,columns-1));
+ clearImage(loc(cuX,cuY),loc(p,cuY),' ');
+}
+
+/*! delete `n' characters starting from (including) the cursor position.
+
+ The line is filled in from the right with spaces.
+*/
+
+void TEScreen::deleteChars(int n)
+{
+ if (n == 0) n = 1; // Default
+ if (n > columns) n = columns - 1;
+ int p = QMAX(0,QMIN(cuX+n,columns-1));
+ moveImage(loc(cuX,cuY),loc(p,cuY),loc(columns-1,cuY));
+ clearImage(loc(columns-n,cuY),loc(columns-1,cuY),' ');
+}
+
+/*! insert `n' spaces at the cursor position.
+
+ The cursor is not moved by the operation.
+*/
+
+void TEScreen::insertChars(int n)
+{
+ if (n == 0) n = 1; // Default
+ int p = QMAX(0,QMIN(columns-1-n,columns-1));
+ int q = QMAX(0,QMIN(cuX+n,columns-1));
+ moveImage(loc(q,cuY),loc(cuX,cuY),loc(p,cuY));
+ clearImage(loc(cuX,cuY),loc(q-1,cuY),' ');
+}
+
+/*! delete `n' lines starting from (including) the cursor position.
+
+ The cursor is not moved by the operation.
+*/
+
+void TEScreen::deleteLines(int n)
+{
+ if (n == 0) n = 1; // Default
+ scrollUp(cuY,n);
+}
+
+/*! insert `n' lines at the cursor position.
+
+ The cursor is not moved by the operation.
+*/
+
+void TEScreen::insertLines(int n)
+{
+ if (n == 0) n = 1; // Default
+ scrollDown(cuY,n);
+}
+
+// Mode Operations -----------------------------------------------------------
+
+/*! Set a specific mode. */
+
+void TEScreen::setMode(int m)
+{
+ currParm.mode[m] = true;
+ switch(m)
+ {
+ case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home
+ }
+}
+
+/*! Reset a specific mode. */
+
+void TEScreen::resetMode(int m)
+{
+ currParm.mode[m] = false;
+ switch(m)
+ {
+ case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home
+ }
+}
+
+/*! Save a specific mode. */
+
+void TEScreen::saveMode(int m)
+{
+ saveParm.mode[m] = currParm.mode[m];
+}
+
+/*! Restore a specific mode. */
+
+void TEScreen::restoreMode(int m)
+{
+ currParm.mode[m] = saveParm.mode[m];
+}
+
+//NOTE: this is a helper function
+/*! Return the setting a specific mode. */
+bool TEScreen::getMode(int m)
+{
+ return currParm.mode[m];
+}
+
+/*! Save the cursor position and the rendition attribute settings. */
+
+void TEScreen::saveCursor()
+{
+ sa_cuX = cuX;
+ sa_cuY = cuY;
+ sa_cu_re = cu_re;
+ sa_cu_fg = cu_fg;
+ sa_cu_bg = cu_bg;
+}
+
+/*! Restore the cursor position and the rendition attribute settings. */
+
+void TEScreen::restoreCursor()
+{
+ cuX = QMIN(sa_cuX,columns-1);
+ cuY = QMIN(sa_cuY,lines-1);
+ cu_re = sa_cu_re;
+ cu_fg = sa_cu_fg;
+ cu_bg = sa_cu_bg;
+ effectiveRendition();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Screen Operations */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*! Assing a new size to the screen.
+
+ The topmost left position is maintained, while lower lines
+ or right hand side columns might be removed or filled with
+ spaces to fit the new size.
+
+ The region setting is reset to the whole screen and the
+ tab positions reinitialized.
+*/
+
+void TEScreen::resizeImage(int new_lines, int new_columns)
+{
+ if ((new_lines==lines) && (new_columns==columns)) return;
+
+ if (cuY > new_lines-1)
+ { // attempt to preserve focus and lines
+ bmargin = lines-1; //FIXME: margin lost
+ for (int i = 0; i < cuY-(new_lines-1); i++)
+ {
+ addHistLine(); scrollUp(0,1);
+ }
+ }
+
+ // make new image
+
+ ca* newimg = new ca[(new_lines+1)*new_columns];
+ QBitArray newwrapped(new_lines+1);
+ 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 = cacol(CO_DFT,DEFAULT_FORE_COLOR);
+ newimg[y*new_columns+x].b = cacol(CO_DFT,DEFAULT_BACK_COLOR);
+ newimg[y*new_columns+x].r = DEFAULT_RENDITION;
+ }
+ newwrapped[y]=false;
+ }
+ 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;
+ }
+ newwrapped[y]=line_wrapped[y];
+ }
+ delete[] image;
+ image = newimg;
+ line_wrapped = newwrapped;
+ lines = new_lines;
+ columns = new_columns;
+ cuX = QMIN(cuX,columns-1);
+ cuY = QMIN(cuY,lines-1);
+
+ // FIXME: try to keep values, evtl.
+ tmargin=0;
+ bmargin=lines-1;
+ initTabStops();
+ clearSelection();
+}
+
+/*
+ Clarifying rendition here and in TEWidget.
+
+ currently, TEWidget's color table is
+ 0 1 2 .. 9 10 .. 17
+ dft_fg, dft_bg, dim 0..7, intensive 0..7
+
+ cu_fg, cu_bg contain values 0..8;
+ - 0 = default color
+ - 1..8 = ansi specified color
+
+ re_fg, re_bg contain values 0..17
+ due to the TEWidget's color table
+
+ rendition attributes are
+
+ attr widget screen
+ -------------- ------ ------
+ RE_UNDERLINE XX XX affects foreground only
+ RE_BLINK XX XX affects foreground only
+ RE_BOLD XX XX affects foreground only
+ RE_REVERSE -- XX
+ RE_TRANSPARENT XX -- affects background only
+ RE_INTENSIVE XX -- affects foreground only
+
+ Note that RE_BOLD is used in both widget
+ and screen rendition. Since xterm/vt102
+ is to poor to distinguish between bold
+ (which is a font attribute) and intensive
+ (which is a color attribute), we translate
+ this and RE_BOLD in falls eventually appart
+ into RE_BOLD and RE_INTENSIVE.
+*/
+
+void TEScreen::reverseRendition(ca* p)
+{ cacol f = p->f; cacol b = p->b;
+ p->f = b; p->b = f; //p->r &= ~RE_TRANSPARENT;
+}
+
+void TEScreen::effectiveRendition()
+// calculate rendition
+{
+ ef_re = cu_re & (RE_UNDERLINE | RE_BLINK);
+ if (cu_re & RE_REVERSE)
+ {
+ ef_fg = cu_bg;
+ ef_bg = cu_fg;
+ }
+ else
+ {
+ ef_fg = cu_fg;
+ ef_bg = cu_bg;
+ }
+ if (cu_re & RE_BOLD)
+ ef_fg.toggleIntensive();
+}
+
+/*!
+ returns the image.
+
+ Get the size of the image by \sa getLines and \sa getColumns.
+
+ NOTE that the image returned by this function must later be
+ freed.
+
+*/
+
+ca* TEScreen::getCookedImage()
+{
+/*kdDebug() << "sel_begin=" << sel_begin << "(" << sel_begin/columns << "," << sel_begin%columns << ")"
+ << " sel_TL=" << sel_TL << "(" << sel_TL/columns << "," << sel_TL%columns << ")"
+ << " sel_BR=" << sel_BR << "(" << sel_BR/columns << "," << sel_BR%columns << ")"
+ << " histcursor=" << histCursor << endl;*/
+
+ int x,y;
+ ca* merged = (ca*)malloc((lines*columns+1)*sizeof(ca));
+ ca dft(' ',cacol(CO_DFT,DEFAULT_FORE_COLOR),cacol(CO_DFT,DEFAULT_BACK_COLOR),DEFAULT_RENDITION);
+ merged[lines*columns] = dft;
+
+// kdDebug(1211) << "InGetCookedImage" << endl;
+ for (y = 0; (y < lines) && (y < (hist->getLines()-histCursor)); y++)
+ {
+ int len = QMIN(columns,hist->getLineLen(y+histCursor));
+ int yp = y*columns;
+
+// kdDebug(1211) << "InGetCookedImage - In first For. Y =" << y << "histCursor = " << histCursor << endl;
+ hist->getCells(y+histCursor,0,len,merged+yp);
+ for (x = len; x < columns; x++) merged[yp+x] = dft;
+ if (sel_begin !=-1)
+ for (x = 0; x < columns; x++)
+ {
+#ifdef REVERSE_WRAPPED_LINES
+ if (hist->isWrappedLine(y+histCursor))
+ reverseRendition(&merged[p]);
+#endif
+ if (testIsSelected(x,y)) {
+ int p=x + yp;
+ reverseRendition(&merged[p]); // for selection
+ }
+ }
+ }
+ if (lines >= hist->getLines()-histCursor)
+ {
+ for (y = (hist->getLines()-histCursor); y < lines ; y++)
+ {
+ int yp = y*columns;
+ int yr = (y-hist->getLines()+histCursor)*columns;
+// kdDebug(1211) << "InGetCookedImage - In second For. Y =" << y << endl;
+ for (x = 0; x < columns; x++)
+ { int p = x + yp; int r = x + yr;
+ merged[p] = image[r];
+#ifdef REVERSE_WRAPPED_LINES
+ if (line_wrapped[y- hist->getLines() +histCursor])
+ reverseRendition(&merged[p]);
+#endif
+ if (sel_begin != -1 && testIsSelected(x,y))
+ reverseRendition(&merged[p]); // for selection
+ }
+
+ }
+ }
+ // evtl. inverse display
+ if (getMode(MODE_Screen))
+ {
+ for (int i = 0; i < lines*columns; i++)
+ reverseRendition(&merged[i]); // for reverse display
+ }
+// if (getMode(MODE_Cursor) && (cuY+(hist->getLines()-histCursor) < lines)) // cursor visible
+
+ int loc_ = loc(cuX, cuY+hist->getLines()-histCursor);
+ if(getMode(MODE_Cursor) && loc_ < columns*lines)
+ merged[loc(cuX,cuY+(hist->getLines()-histCursor))].r|=RE_CURSOR;
+ return merged;
+}
+
+QBitArray TEScreen::getCookedLineWrapped()
+{
+ QBitArray result(lines);
+
+ for (int y = 0; (y < lines) && (y < (hist->getLines()-histCursor)); y++)
+ result[y]=hist->isWrappedLine(y+histCursor);
+
+ if (lines >= hist->getLines()-histCursor)
+ for (int y = (hist->getLines()-histCursor); y < lines ; y++)
+ result[y]=line_wrapped[y- hist->getLines() +histCursor];
+
+ return result;
+}
+
+/*!
+*/
+
+void TEScreen::reset()
+{
+ setMode(MODE_Wrap ); saveMode(MODE_Wrap ); // wrap at end of margin
+ resetMode(MODE_Origin); saveMode(MODE_Origin); // position refere to [1,1]
+ resetMode(MODE_Insert); saveMode(MODE_Insert); // overstroke
+ setMode(MODE_Cursor); // cursor visible
+ resetMode(MODE_Screen); // screen not inverse
+ resetMode(MODE_NewLine);
+
+ tmargin=0;
+ bmargin=lines-1;
+
+ setDefaultRendition();
+ saveCursor();
+
+ clear();
+}
+
+/*! Clear the entire screen and home the cursor.
+*/
+
+void TEScreen::clear()
+{
+ clearEntireScreen();
+ home();
+}
+
+/*! Moves the cursor left one column.
+*/
+
+void TEScreen::BackSpace()
+{
+ cuX = QMAX(0,cuX-1);
+ if (BS_CLEARS) image[loc(cuX,cuY)].c = ' ';
+}
+
+/*!
+*/
+
+void TEScreen::Tabulate(int n)
+{
+ // note that TAB is a format effector (does not write ' ');
+ if (n == 0) n = 1;
+ while((n > 0) && (cuX < columns-1))
+ {
+ cursorRight(1); while((cuX < columns-1) && !tabstops[cuX]) cursorRight(1);
+ n--;
+ }
+}
+
+void TEScreen::backTabulate(int n)
+{
+ // note that TAB is a format effector (does not write ' ');
+ if (n == 0) n = 1;
+ while((n > 0) && (cuX > 0))
+ {
+ cursorLeft(1); while((cuX > 0) && !tabstops[cuX]) cursorLeft(1);
+ n--;
+ }
+}
+
+void TEScreen::clearTabStops()
+{
+ for (int i = 0; i < columns; i++) tabstops[i] = false;
+}
+
+void TEScreen::changeTabStop(bool set)
+{
+ if (cuX >= columns) return;
+ tabstops[cuX] = set;
+}
+
+void TEScreen::initTabStops()
+{
+ delete[] tabstops;
+ tabstops = new bool[columns];
+
+ // Arrg! The 1st tabstop has to be one longer than the other.
+ // i.e. the kids start counting from 0 instead of 1.
+ // Other programs might behave correctly. Be aware.
+ for (int i = 0; i < columns; i++) tabstops[i] = (i%8 == 0 && i != 0);
+}
+
+/*!
+ This behaves either as IND (Screen::Index) or as NEL (Screen::NextLine)
+ depending on the NewLine Mode (LNM). This mode also
+ affects the key sequence returned for newline ([CR]LF).
+*/
+
+void TEScreen::NewLine()
+{
+ if (getMode(MODE_NewLine)) Return();
+ index();
+}
+
+/*! put `c' literally onto the screen at the current cursor position.
+
+ VT100 uses the convention to produce an automatic newline (am)
+ with the *first* character that would fall onto the next line (xenl).
+*/
+
+void TEScreen::checkSelection(int from, int to)
+{
+ if (sel_begin == -1) return;
+ int scr_TL = loc(0, hist->getLines());
+ //Clear entire selection if it overlaps region [from, to]
+ if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) )
+ {
+ clearSelection();
+ }
+}
+
+void TEScreen::ShowCharacter(unsigned short c)
+{
+ // Note that VT100 does wrapping BEFORE putting the character.
+ // This has impact on the assumption of valid cursor positions.
+ // We indicate the fact that a newline has to be triggered by
+ // putting the cursor one right to the last column of the screen.
+
+ int w = konsole_wcwidth(c);
+
+ if (w <= 0)
+ return;
+
+ if (cuX+w > columns) {
+ if (getMode(MODE_Wrap)) {
+ line_wrapped[cuY]=true;
+ NextLine();
+ }
+ else
+ cuX = columns-w;
+ }
+
+ if (getMode(MODE_Insert)) insertChars(w);
+
+ 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;
+
+ lastPos = i;
+
+ cuX += w--;
+
+ while(w)
+ {
+ i++;
+ image[i].c = 0;
+ image[i].f = ef_fg;
+ image[i].b = ef_bg;
+ image[i].r = ef_re;
+ w--;
+ }
+}
+
+void TEScreen::compose(QString compose)
+{
+ if (lastPos == -1)
+ return;
+
+ QChar c(image[lastPos].c);
+ compose.prepend(c);
+ compose.compose();
+ image[lastPos].c = compose[0].unicode();
+}
+
+// Region commands -------------------------------------------------------------
+
+void TEScreen::scrollUp(int n)
+{
+ if (n == 0) n = 1; // Default
+ if (tmargin == 0) addHistLine(); // hist.history
+ scrollUp(tmargin, n);
+}
+
+/*! scroll up `n' lines within current region.
+ The `n' new lines are cleared.
+ \sa setRegion \sa scrollDown
+*/
+
+void TEScreen::scrollUp(int from, int n)
+{
+ if (n <= 0 || from + n > bmargin) return;
+ //FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
+ moveImage(loc(0,from),loc(0,from+n),loc(columns-1,bmargin));
+ clearImage(loc(0,bmargin-n+1),loc(columns-1,bmargin),' ');
+}
+
+void TEScreen::scrollDown(int n)
+{
+ if (n == 0) n = 1; // Default
+ scrollDown(tmargin, n);
+}
+
+/*! scroll down `n' lines within current region.
+ The `n' new lines are cleared.
+ \sa setRegion \sa scrollUp
+*/
+
+void TEScreen::scrollDown(int from, int n)
+{
+//FIXME: make sure `tmargin', `bmargin', `from', `n' is in bounds.
+ if (n <= 0) return;
+ if (from > bmargin) return;
+ if (from + n > bmargin) n = bmargin - from;
+ moveImage(loc(0,from+n),loc(0,from),loc(columns-1,bmargin-n));
+ clearImage(loc(0,from),loc(columns-1,from+n-1),' ');
+}
+
+/*! position the cursor to a specific line and column. */
+void TEScreen::setCursorYX(int y, int x)
+{
+ setCursorY(y); setCursorX(x);
+}
+
+/*! Set the cursor to x-th line. */
+
+void TEScreen::setCursorX(int x)
+{
+ if (x == 0) x = 1; // Default
+ x -= 1; // Adjust
+ cuX = QMAX(0,QMIN(columns-1, x));
+}
+
+/*! Set the cursor to y-th line. */
+
+void TEScreen::setCursorY(int y)
+{
+ if (y == 0) y = 1; // Default
+ y -= 1; // Adjust
+ cuY = QMAX(0,QMIN(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) ));
+}
+
+/*! set cursor to the `left upper' corner of the screen (1,1).
+*/
+
+void TEScreen::home()
+{
+ cuX = 0;
+ cuY = 0;
+}
+
+/*! set cursor to the begin of the current line.
+*/
+
+void TEScreen::Return()
+{
+ cuX = 0;
+}
+
+/*! returns the current cursor columns.
+*/
+
+int TEScreen::getCursorX()
+{
+ return cuX;
+}
+
+/*! returns the current cursor line.
+*/
+
+int TEScreen::getCursorY()
+{
+ return cuY;
+}
+
+// Erasing ---------------------------------------------------------------------
+
+/*! \section Erasing
+
+ This group of operations erase parts of the screen contents by filling
+ it with spaces colored due to the current rendition settings.
+
+ Althought the cursor position is involved in most of these operations,
+ it is never modified by them.
+*/
+
+/*! fill screen between (including) `loca' and `loce' with spaces.
+
+ This is an internal helper functions. The parameter types are internal
+ addresses of within the screen image and make use of the way how the
+ screen matrix is mapped to the image vector.
+*/
+
+void TEScreen::clearImage(int loca, int loce, char c)
+{ int i;
+ int scr_TL=loc(0,hist->getLines());
+ //FIXME: check positions
+
+ //Clear entire selection if it overlaps region to be moved...
+ if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) )
+ {
+ clearSelection();
+ }
+
+ for (i = loca; i <= loce; i++)
+ {
+ // Use the current colors but the default rendition
+ // Check with: echo -e '\033[41;33;07m\033[2Khello world\033[00m'
+ image[i].c = c;
+ image[i].f = cu_fg;
+ image[i].b = cu_bg;
+ image[i].r = DEFAULT_RENDITION;
+ }
+
+ for (i = loca/columns; i<=loce/columns; i++)
+ line_wrapped[i]=false;
+}
+
+/*! move image between (including) `loca' and `loce' to 'dst'.
+
+ This is an internal helper functions. The parameter types are internal
+ addresses of within the screen image and make use of the way how the
+ screen matrix is mapped to the image vector.
+*/
+
+void TEScreen::moveImage(int dst, int loca, int loce)
+{
+//FIXME: check positions
+ if (loce < loca) {
+ kdDebug(1211) << "WARNING!!! call to TEScreen:moveImage with loce < loca!" << endl;
+ return;
+ }
+ //kdDebug(1211) << "Using memmove to scroll up" << endl;
+ memmove(&image[dst],&image[loca],(loce-loca+1)*sizeof(ca));
+ for (int i=0;i<=(loce-loca+1)/columns;i++)
+ line_wrapped[(dst/columns)+i]=line_wrapped[(loca/columns)+i];
+ if (lastPos != -1)
+ {
+ int diff = dst - loca; // Scroll by this amount
+ lastPos += diff;
+ if ((lastPos < 0) || (lastPos >= (lines*columns)))
+ lastPos = -1;
+ }
+ if (sel_begin != -1)
+ {
+ // Adjust selection to follow scroll.
+ bool beginIsTL = (sel_begin == sel_TL);
+ int diff = dst - loca; // Scroll by this amount
+ int scr_TL=loc(0,hist->getLines());
+ int srca = loca+scr_TL; // Translate index from screen to global
+ int srce = loce+scr_TL; // Translate index from screen to global
+ int desta = srca+diff;
+ int deste = srce+diff;
+
+ if ((sel_TL >= srca) && (sel_TL <= srce))
+ sel_TL += diff;
+ else if ((sel_TL >= desta) && (sel_TL <= deste))
+ sel_BR = -1; // Clear selection (see below)
+
+ if ((sel_BR >= srca) && (sel_BR <= srce))
+ sel_BR += diff;
+ else if ((sel_BR >= desta) && (sel_BR <= deste))
+ sel_BR = -1; // Clear selection (see below)
+
+ if (sel_BR < 0)
+ {
+ clearSelection();
+ }
+ else
+ {
+ if (sel_TL < 0)
+ sel_TL = 0;
+ }
+
+ if (beginIsTL)
+ sel_begin = sel_TL;
+ else
+ sel_begin = sel_BR;
+ }
+}
+
+/*! clear from (including) current cursor position to end of screen.
+*/
+
+void TEScreen::clearToEndOfScreen()
+{
+ clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' ');
+}
+
+/*! clear from begin of screen to (including) current cursor position.
+*/
+
+void TEScreen::clearToBeginOfScreen()
+{
+ clearImage(loc(0,0),loc(cuX,cuY),' ');
+}
+
+/*! clear the entire screen.
+*/
+
+void TEScreen::clearEntireScreen()
+{
+ // Add entire screen to history
+ for (int i = 0; i < (lines-1); i++)
+ {
+ addHistLine(); scrollUp(0,1);
+ }
+
+ clearImage(loc(0,0),loc(columns-1,lines-1),' ');
+}
+
+/*! fill screen with 'E'
+ This is to aid screen alignment
+*/
+
+void TEScreen::helpAlign()
+{
+ clearImage(loc(0,0),loc(columns-1,lines-1),'E');
+}
+
+/*! clear from (including) current cursor position to end of current cursor line.
+*/
+
+void TEScreen::clearToEndOfLine()
+{
+ clearImage(loc(cuX,cuY),loc(columns-1,cuY),' ');
+}
+
+/*! clear from begin of current cursor line to (including) current cursor position.
+*/
+
+void TEScreen::clearToBeginOfLine()
+{
+ clearImage(loc(0,cuY),loc(cuX,cuY),' ');
+}
+
+/*! clears entire current cursor line
+*/
+
+void TEScreen::clearEntireLine()
+{
+ clearImage(loc(0,cuY),loc(columns-1,cuY),' ');
+}
+
+// Rendition ------------------------------------------------------------------
+
+/*!
+ set rendition mode
+*/
+
+void TEScreen::setRendition(int re)
+{
+ cu_re |= re;
+ effectiveRendition();
+}
+
+/*!
+ reset rendition mode
+*/
+
+void TEScreen::resetRendition(int re)
+{
+ cu_re &= ~re;
+ effectiveRendition();
+}
+
+/*!
+*/
+
+void TEScreen::setDefaultRendition()
+{
+ setForeColor(CO_DFT,DEFAULT_FORE_COLOR);
+ setBackColor(CO_DFT,DEFAULT_BACK_COLOR);
+ cu_re = DEFAULT_RENDITION;
+ effectiveRendition();
+}
+
+/*!
+*/
+void TEScreen::setForeColor(int space, int color)
+{
+ cu_fg = cacol(space, color);
+ effectiveRendition();
+}
+
+/*!
+*/
+void TEScreen::setBackColor(int space, int color)
+{
+ cu_bg = cacol(space, color);
+ effectiveRendition();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Marking & Selection */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEScreen::clearSelection()
+{
+ sel_BR = -1;
+ sel_TL = -1;
+ sel_begin = -1;
+}
+
+void TEScreen::setSelBeginXY(const int x, const int y, const bool mode)
+{
+// kdDebug(1211) << "setSelBeginXY(" << x << "," << y << ")" << endl;
+ sel_begin = loc(x,y+histCursor) ;
+
+ /* FIXME, HACK to correct for x too far to the right... */
+ if (x == columns) sel_begin--;
+
+ sel_BR = sel_begin;
+ sel_TL = sel_begin;
+ columnmode = mode;
+}
+
+void TEScreen::setSelExtentXY(const int x, const int y)
+{
+// kdDebug(1211) << "setSelExtentXY(" << x << "," << y << ")" << endl;
+ 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) l--;
+
+ sel_TL = sel_begin;
+ sel_BR = l;
+ }
+}
+
+bool TEScreen::testIsSelected(const int x,const int y)
+{
+ if (columnmode) {
+ int sel_Left,sel_Right;
+ if ( sel_TL % columns < sel_BR % columns ) {
+ sel_Left = sel_TL; sel_Right = sel_BR;
+ } else {
+ sel_Left = sel_BR; sel_Right = sel_TL;
+ }
+ return ( x >= sel_Left % columns ) && ( x <= sel_Right % columns ) &&
+ ( y+histCursor >= sel_TL / columns ) && ( y+histCursor <= sel_BR / columns );
+ }
+ else {
+ int pos = loc(x,y+histCursor);
+ return ( pos >= sel_TL && pos <= sel_BR );
+ }
+}
+
+static bool isSpace(UINT16 c)
+{
+ if ((c > 32) && (c < 127))
+ return false;
+ if ((c == 32) || (c == 0))
+ return true;
+ QChar qc(c);
+ return qc.isSpace();
+}
+
+QString TEScreen::getSelText(bool preserve_line_breaks)
+{
+ QString result;
+ QTextOStream stream(&result);
+ getSelText(preserve_line_breaks, &stream);
+ return result;
+}
+
+
+static QString makeString(int *m, int d, bool stripTrailingSpaces)
+{
+ QChar* qc = new QChar[d];
+
+ int last_space = -1;
+ int j = 0;
+
+ for (int i = 0; i < d; i++, j++)
+ {
+ if (m[i] == ' ')
+ {
+ if (last_space == -1)
+ last_space = j;
+ }
+ else
+ {
+ last_space = -1;
+ }
+ qc[j] = m[i];
+ }
+
+ if ((last_space != -1) && stripTrailingSpaces)
+ {
+ // Strip trailing spaces
+ j = last_space;
+ }
+
+ QString res(qc, j);
+ delete [] qc;
+ return res;
+}
+
+void TEScreen::getSelText(bool preserve_line_breaks, QTextStream *stream)
+{
+ if (sel_begin == -1)
+ return; // 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[columns + 3];
+ d = 0;
+
+#define LINE_END do { \
+ assert(d <= columns); \
+ *stream << makeString(m, d, true) << (preserve_line_breaks ? "\n" : " "); \
+ d = 0; \
+ } while(false)
+#define LINE_WRAP do { \
+ assert(d <= columns); \
+ *stream << makeString(m, d, false); \
+ d = 0; \
+ } while(false)
+#define LINE_FLUSH do { \
+ assert(d <= columns); \
+ *stream << makeString(m, d, false); \
+ d = 0; \
+ } while(false)
+
+ if (columnmode) {
+ bool newlineneeded=false;
+ preserve_line_breaks = true; // Just in case
+
+ int sel_Left, sel_Right;
+ if ( sel_TL % columns < sel_BR % columns ) {
+ sel_Left = sel_TL; sel_Right = sel_BR;
+ } else {
+ sel_Left = sel_BR; sel_Right = sel_TL;
+ }
+
+ while (s <= sel_BR) {
+ if (s < hist_BR) { // get lines from hist->history buffer.
+ hX = sel_Left % columns;
+ eol = hist->getLineLen(hY);
+ if (eol > columns)
+ eol = columns;
+ if ((hY == (sel_BR / columns)) &&
+ (eol > (sel_BR % columns)))
+ {
+ eol = sel_BR % columns + 1;
+ }
+
+ while (hX < eol && hX <= sel_Right % columns)
+ {
+ Q_UINT16 c = hist->getCell(hY, hX++).c;
+ if (c)
+ m[d++] = c;
+ s++;
+ }
+ LINE_END;
+
+ hY++;
+ s = hY * columns;
+ }
+ else { // or from screen image.
+ if (testIsSelected((s - hist_BR) % columns, (s - hist_BR) / columns)) {
+ Q_UINT16 c = image[s++ - hist_BR].c;
+ if (c) {
+ m[d++] = c;
+ newlineneeded = true;
+ }
+ if (((s - hist_BR) % columns == 0) && newlineneeded)
+ {
+ LINE_END;
+ newlineneeded = false;
+ }
+ }
+ else {
+ s++;
+ if (newlineneeded) {
+ LINE_END;
+ newlineneeded = false;
+ }
+ }
+ }
+ }
+ if (newlineneeded)
+ LINE_END;
+ }
+ else
+ {
+ while (s <= sel_BR)
+ {
+ if (s < hist_BR)
+ { // get lines from hist->history buffer.
+ eol = hist->getLineLen(hY);
+ if (eol > columns)
+ eol = columns;
+
+ if ((hY == (sel_BR / columns)) &&
+ (eol > (sel_BR % columns)))
+ {
+ eol = sel_BR % columns + 1;
+ }
+
+ while (hX < eol)
+ {
+ Q_UINT16 c = hist->getCell(hY, hX++).c;
+ if (c)
+ m[d++] = c;
+ s++;
+ }
+
+ if (s <= sel_BR)
+ { // The line break handling
+ bool wrap = false;
+ if (eol % columns == 0)
+ { // That's either a full or empty line
+ if ((eol != 0) && hist->isWrappedLine(hY))
+ wrap = true;
+ }
+ else if ((eol + 1) % columns == 0)
+ {
+ if (hist->isWrappedLine(hY))
+ wrap = true;
+ }
+
+ if (wrap)
+ {
+ LINE_WRAP;
+ }
+ else
+ {
+ LINE_END;
+ }
+
+ }
+ else
+ {
+ // Flush trailing stuff
+ LINE_FLUSH;
+ }
+
+ hY++;
+ hX = 0;
+ s = hY * columns;
+ }
+ else
+ { // or from screen image.
+ eol = (s / columns + 1) * columns - 1;
+
+ bool addNewLine = false;
+
+ if (eol < sel_BR)
+ {
+ while ((eol > s) &&
+ (!image[eol - hist_BR].c || isSpace(image[eol - hist_BR].c)) &&
+ !line_wrapped[(eol-hist_BR)/columns])
+ {
+ eol--;
+ }
+ }
+ else if (eol == sel_BR)
+ {
+ if (!line_wrapped[(eol - hist_BR)/columns])
+ addNewLine = true;
+ }
+ else
+ {
+ eol = sel_BR;
+ }
+
+ while (s <= eol)
+ {
+ Q_UINT16 c = image[s++ - hist_BR].c;
+ if (c)
+ m[d++] = c;
+ }
+
+ if (eol < sel_BR)
+ { // eol processing
+ bool wrap = false;
+ if ((eol + 1) % columns == 0)
+ { // the whole line is filled
+ if (line_wrapped[(eol - hist_BR)/columns])
+ wrap = true;
+ }
+ if (wrap)
+ {
+ LINE_WRAP;
+ }
+ else
+ {
+ LINE_END;
+ }
+ }
+ else
+ {
+ // Flush trailing stuff
+ if (addNewLine && preserve_line_breaks)
+ {
+ LINE_END;
+ }
+ else
+ {
+ LINE_FLUSH;
+ }
+ }
+
+ s = (eol / columns + 1) * columns;
+ }
+ }
+ }
+
+ assert(d == 0);
+
+ delete [] m;
+}
+
+void TEScreen::streamHistory(QTextStream* stream) {
+ sel_begin = 0;
+ sel_BR = sel_begin;
+ sel_TL = sel_begin;
+ setSelExtentXY(columns-1,lines-1+hist->getLines()-histCursor);
+ getSelText(true, stream);
+ clearSelection();
+}
+
+QString TEScreen::getHistoryLine(int no)
+{
+ sel_begin = loc(0,no);
+ sel_TL = sel_begin;
+ sel_BR = loc(columns-1,no);
+ return getSelText(false);
+}
+
+void TEScreen::addHistLine()
+{
+ assert(hasScroll() || histCursor == 0);
+
+ // add to hist buffer
+ // we have to take care about scrolling, too...
+
+ if (hasScroll())
+ { ca dft;
+
+ int end = columns-1;
+ while (end >= 0 && image[end] == dft && !line_wrapped[0])
+ end -= 1;
+
+ int oldHistLines = hist->getLines();
+
+ hist->addCells(image,end+1);
+ hist->addLine(line_wrapped[0]);
+
+ int newHistLines = hist->getLines();
+
+ bool beginIsTL = (sel_begin == sel_TL);
+
+ // adjust history cursor
+ if (newHistLines > oldHistLines)
+ {
+ histCursor++;
+ // Adjust selection for the new point of reference
+ if (sel_begin != -1)
+ {
+ sel_TL += columns;
+ sel_BR += columns;
+ }
+ }
+
+ // Scroll up if user is looking at the history and we can scroll up
+ if ((histCursor > 0) && // We can scroll up and...
+ ((histCursor != newHistLines) || // User is looking at history...
+ sel_busy)) // or user is selecting text.
+ {
+ histCursor--;
+ }
+
+ if (sel_begin != -1)
+ {
+ // Scroll selection in history up
+ int top_BR = loc(0, 1+newHistLines);
+
+ if (sel_TL < top_BR)
+ sel_TL -= columns;
+
+ if (sel_BR < top_BR)
+ sel_BR -= columns;
+
+ if (sel_BR < 0)
+ {
+ clearSelection();
+ }
+ else
+ {
+ if (sel_TL < 0)
+ sel_TL = 0;
+ }
+
+ if (beginIsTL)
+ sel_begin = sel_TL;
+ else
+ sel_begin = sel_BR;
+ }
+ }
+
+ if (!hasScroll()) histCursor = 0; //FIXME: a poor workaround
+}
+
+void TEScreen::setHistCursor(int cursor)
+{
+ histCursor = cursor; //FIXME:rangecheck
+}
+
+int TEScreen::getHistCursor()
+{
+ return histCursor;
+}
+
+int TEScreen::getHistLines()
+{
+ return hist->getLines();
+}
+
+void TEScreen::setScroll(const HistoryType& t)
+{
+ clearSelection();
+ hist = t.getScroll(hist);
+ histCursor = hist->getLines();
+}
+
+bool TEScreen::hasScroll()
+{
+ return hist->hasScroll();
+}
+
+const HistoryType& TEScreen::getScroll()
+{
+ return hist->getType();
+}
diff --git a/konsole/konsole/TEScreen.h b/konsole/konsole/TEScreen.h
new file mode 100644
index 000000000..55cbcb07c
--- /dev/null
+++ b/konsole/konsole/TEScreen.h
@@ -0,0 +1,279 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef TESCREEN_H
+#define TESCREEN_H
+
+#include "TECommon.h"
+#include "TEHistory.h"
+
+#define MODE_Origin 0
+#define MODE_Wrap 1
+#define MODE_Insert 2
+#define MODE_Screen 3
+#define MODE_Cursor 4
+#define MODE_NewLine 5
+#define MODES_SCREEN 6
+
+/*!
+*/
+struct ScreenParm
+{
+ int mode[MODES_SCREEN];
+};
+
+
+class TEScreen
+{
+public:
+ TEScreen(int lines, int columns);
+ ~TEScreen();
+
+public: // these are all `Screen' operations
+ //
+ // VT100/2 Operations ------------------
+ //
+ // Cursor Movement
+ //
+ void cursorUp (int n);
+ void cursorDown (int n);
+ void cursorLeft (int n);
+ void cursorRight (int n);
+ void setCursorY (int y);
+ void setCursorX (int x);
+ void setCursorYX (int y, int x);
+ void setMargins (int t, int b);
+ //
+ // Cursor Movement with Scrolling
+ //
+ void NewLine ();
+ void NextLine ();
+ void index ();
+ void reverseIndex();
+ //
+ // Scrolling
+ //
+ void scrollUp(int n);
+ void scrollDown(int n);
+ //
+ void Return ();
+ void BackSpace ();
+ void Tabulate (int n = 1);
+ void backTabulate(int n);
+ //
+ // 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 space, int color);
+ void setBackColor (int space, int color);
+ //
+ void setDefaultRendition();
+ //
+ // -------------------------------------
+ //
+ bool getMode (int n);
+ //
+ // only for report cursor position
+ //
+ int getCursorX();
+ int getCursorY();
+ //
+ // -------------------------------------
+ //
+ void clear();
+ void home();
+ void reset();
+ // Show character
+ void ShowCharacter(unsigned short c);
+
+ // Do composition with last shown character
+ void compose(QString compose);
+
+ //
+ void resizeImage(int new_lines, int new_columns);
+ //
+ ca* getCookedImage();
+ QBitArray getCookedLineWrapped();
+
+ /*! 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(const HistoryType&);
+ const HistoryType& getScroll();
+ bool hasScroll();
+
+ //
+ // Selection
+ //
+ void setSelBeginXY(const int x, const int y, const bool columnmode);
+ void setSelExtentXY(const int x, const int y);
+ void clearSelection();
+ void setBusySelecting(bool busy) { sel_busy = busy; }
+ bool testIsSelected(const int x,const int y);
+
+ QString getSelText(bool preserve_line_breaks);
+ void getSelText(bool preserve_line_breaks, QTextStream* stream);
+ void streamHistory(QTextStream* stream);
+ QString getHistoryLine(int no);
+
+ void checkSelection(int from, int to);
+
+private: // helper
+
+ void clearImage(int loca, int loce, char c);
+ void moveImage(int dst, int loca, int loce);
+
+ void scrollUp(int from, int i);
+ void scrollDown(int from, int i);
+
+ void addHistLine();
+
+ void initTabStops();
+
+ void effectiveRendition();
+ void reverseRendition(ca* p);
+
+ /*
+ The state of the screen is more complex as one would
+ expect first. The screem does really do part of the
+ emulation providing state informations in form of modes,
+ margins, tabulators, cursor etc.
+
+ Even more unexpected are variables to save and restore
+ parts of the state.
+ */
+
+ // screen image ----------------
+
+ int lines;
+ int columns;
+ ca *image; // [lines][columns]
+ QBitArray line_wrapped; // [lines]
+
+ // 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
+
+ cacol cu_fg; // foreground
+ cacol 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.
+ bool sel_busy; // Busy making a selection.
+ bool columnmode; // Column selection mode
+
+ // effective colors and rendition ------------
+
+ cacol ef_fg; // These are derived from
+ cacol 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;
+ cacol sa_cu_fg;
+ cacol sa_cu_bg;
+
+ // last position where we added a character
+ int lastPos;
+
+ // modes
+
+ ScreenParm saveParm;
+};
+
+#endif // TESCREEN_H
diff --git a/konsole/konsole/TEWidget.cpp b/konsole/konsole/TEWidget.cpp
new file mode 100644
index 000000000..03020a767
--- /dev/null
+++ b/konsole/konsole/TEWidget.cpp
@@ -0,0 +1,2326 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+/*! \class TEWidget
+
+ \brief Visible screen contents
+
+ This class is responsible to map the `image' of a terminal emulation to the
+ display. All the dependency of the emulation to a specific GUI or toolkit is
+ localized here. Further, this widget has no knowledge about being part of an
+ emulation, it simply work within the terminal emulation framework by exposing
+ size and key events and by being ordered to show a new image.
+
+ <ul>
+ <li> The internal image has the size of the widget (evtl. rounded up)
+ <li> The external image used in setImage can have any size.
+ <li> (internally) the external image is simply copied to the internal
+ when a setImage happens. During a resizeEvent no painting is done
+ a paintEvent is expected to follow anyway.
+ </ul>
+
+ \sa TEScreen \sa Emulation
+*/
+
+/* FIXME:
+ - 'image' may also be used uninitialized (it isn't in fact) in resizeEvent
+ - 'font_a' not used in mouse events
+ - add destructor
+*/
+
+/* TODO
+ - evtl. be sensitive to `paletteChange' while using default colors.
+ - set different 'rounding' styles? I.e. have a mode to show clipped
+ chars?
+*/
+
+#include "config.h"
+#include "TEWidget.h"
+#include "konsole_wcwidth.h"
+
+#include <qapplication.h>
+#include <qpainter.h>
+#include <qclipboard.h>
+#include <qstyle.h>
+#include <qfile.h>
+#include <qdragobject.h>
+#include <qlayout.h>
+#include <qregexp.h>
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+
+#include <krun.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <knotifyclient.h>
+#include <kglobalsettings.h>
+#include <kshortcut.h>
+#include <kurldrag.h>
+#include <kio/netaccess.h>
+#include <qlabel.h>
+#include <qtimer.h>
+
+#ifndef loc
+#define loc(X,Y) ((Y)*columns+(X))
+#endif
+
+#define SCRWIDTH 16 // width of the scrollbar
+
+#define yMouseScroll 1
+
+#define REPCHAR "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+ "abcdefgjijklmnopqrstuvwxyz" \
+ "0123456789./+@"
+
+extern bool argb_visual; // declared in main.cpp and konsole_part.cpp
+
+// scroll increment used when dragging selection at top/bottom of window.
+
+// static
+bool TEWidget::s_antialias = true;
+bool TEWidget::s_standalone = false;
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Colors */
+/* */
+/* ------------------------------------------------------------------------- */
+
+//FIXME: the default color table is in session.C now.
+// We need a way to get rid of this one, here.
+static const ColorEntry base_color_table[TABLE_COLORS] =
+// The following are almost IBM standard color codes, with some slight
+// gamma correction for the dim colors to compensate for bright X screens.
+// It contains the 8 ansiterm/xterm colors in 2 intensities.
+{
+ // Fixme: could add faint colors here, also.
+ // normal
+ ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 1, 0 ), // Dfore, Dback
+ ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red
+ ColorEntry(QColor(0x18,0xB2,0x18), 0, 0 ), ColorEntry( QColor(0xB2,0x68,0x18), 0, 0 ), // Green, Yellow
+ ColorEntry(QColor(0x18,0x18,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0xB2), 0, 0 ), // Blue, Magenta
+ ColorEntry(QColor(0x18,0xB2,0xB2), 0, 0 ), ColorEntry( QColor(0xB2,0xB2,0xB2), 0, 0 ), // Cyan, White
+ // intensiv
+ ColorEntry(QColor(0x00,0x00,0x00), 0, 1 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 1, 0 ),
+ ColorEntry(QColor(0x68,0x68,0x68), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0x54), 0, 0 ),
+ ColorEntry(QColor(0x54,0xFF,0x54), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0x54), 0, 0 ),
+ ColorEntry(QColor(0x54,0x54,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0x54,0xFF), 0, 0 ),
+ ColorEntry(QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 )
+};
+
+/* Note that we use ANSI color order (bgr), while IBMPC color order is (rgb)
+
+ Code 0 1 2 3 4 5 6 7
+ ----------- ------- ------- ------- ------- ------- ------- ------- -------
+ ANSI (bgr) Black Red Green Yellow Blue Magenta Cyan White
+ IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White
+*/
+
+void TEWidget::setDefaultBackColor(const QColor& color)
+{
+ defaultBgColor = color;
+ if (qAlpha(blend_color) != 0xff && !backgroundPixmap())
+ setBackgroundColor(getDefaultBackColor());
+}
+
+QColor TEWidget::getDefaultBackColor()
+{
+ if (defaultBgColor.isValid())
+ return defaultBgColor;
+ return color_table[DEFAULT_BACK_COLOR].color;
+}
+
+const ColorEntry* TEWidget::getColorTable() const
+{
+ return color_table;
+}
+
+void TEWidget::setColorTable(const ColorEntry table[])
+{
+ for (int i = 0; i < TABLE_COLORS; i++) color_table[i] = table[i];
+ const QPixmap* pm = backgroundPixmap();
+ if (!pm)
+ if (!argb_visual || (qAlpha(blend_color) == 0xff))
+ setBackgroundColor(getDefaultBackColor());
+ else {
+ float alpha = qAlpha(blend_color) / 255.;
+ int pixel = qAlpha(blend_color) << 24 |
+ int(qRed(blend_color) * alpha) << 16 |
+ int(qGreen(blend_color) * alpha) << 8 |
+ int(qBlue(blend_color) * alpha);
+ setBackgroundColor(QColor(blend_color, pixel));
+ }
+ update();
+}
+
+//FIXME: add backgroundPixmapChanged.
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Font */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*
+ The VT100 has 32 special graphical characters. The usual vt100 extended
+ xterm fonts have these at 0x00..0x1f.
+
+ QT's iso mapping leaves 0x00..0x7f without any changes. But the graphicals
+ come in here as proper unicode characters.
+
+ We treat non-iso10646 fonts as VT100 extended and do the requiered mapping
+ from unicode to 0x00..0x1f. The remaining translation is then left to the
+ QCodec.
+*/
+
+static inline bool isLineChar(Q_UINT16 c) { return ((c & 0xFF80) == 0x2500);}
+
+// assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i.
+
+unsigned short vt100_graphics[32] =
+{ // 0/8 1/9 2/10 3/11 4/12 5/13 6/14 7/15
+ 0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0,
+ 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,
+ 0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534,
+ 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7
+};
+
+/*
+static QChar vt100extended(QChar c)
+{
+ switch (c.unicode())
+ {
+ case 0x25c6 : return 1;
+ case 0x2592 : return 2;
+ case 0x2409 : return 3;
+ case 0x240c : return 4;
+ case 0x240d : return 5;
+ case 0x240a : return 6;
+ case 0x00b0 : return 7;
+ case 0x00b1 : return 8;
+ case 0x2424 : return 9;
+ case 0x240b : return 10;
+ case 0x2518 : return 11;
+ case 0x2510 : return 12;
+ case 0x250c : return 13;
+ case 0x2514 : return 14;
+ case 0x253c : return 15;
+ case 0xf800 : return 16;
+ case 0xf801 : return 17;
+ case 0x2500 : return 18;
+ case 0xf803 : return 19;
+ case 0xf804 : return 20;
+ case 0x251c : return 21;
+ case 0x2524 : return 22;
+ case 0x2534 : return 23;
+ case 0x252c : return 24;
+ case 0x2502 : return 25;
+ case 0x2264 : return 26;
+ case 0x2265 : return 27;
+ case 0x03c0 : return 28;
+ case 0x2260 : return 29;
+ case 0x00a3 : return 30;
+ case 0x00b7 : return 31;
+ }
+ return c;
+}
+
+static QChar identicalMap(QChar c)
+{
+ return c;
+}
+*/
+
+void TEWidget::fontChange(const QFont &)
+{
+ QFontMetrics fm(font());
+ font_h = fm.height() + m_lineSpacing;
+
+ // waba TEWidget 1.123:
+ // "Base character width on widest ASCII character. This prevents too wide
+ // characters in the presence of double wide (e.g. Japanese) characters."
+ // Get the width from representative normal width characters
+ font_w = qRound((double)fm.width(REPCHAR)/(double)strlen(REPCHAR));
+
+ fixed_font = true;
+ int fw = fm.width(REPCHAR[0]);
+ for(unsigned int i=1; i< strlen(REPCHAR); i++){
+ if (fw != fm.width(REPCHAR[i])){
+ fixed_font = false;
+ break;
+ }
+ }
+
+ if (font_w>200) // don't trust unrealistic value, fallback to QFontMetrics::maxWidth()
+ font_w=fm.maxWidth();
+ if (font_w<1)
+ font_w=1;
+
+ font_a = fm.ascent();
+//printf("font: %s\n", font().toString().latin1());
+//printf("fixed: %s\n", font().fixedPitch() ? "yes" : "no");
+//printf("fixed_font: %d\n", fixed_font);
+//printf("font_h: %d\n",font_h);
+//printf("font_w: %d\n",font_w);
+//printf("fw: %d\n",fw);
+//printf("font_a: %d\n",font_a);
+//printf("rawname: %s\n",font().rawName().ascii());
+
+/*
+#if defined(Q_CC_GNU)
+#warning TODO: Review/fix vt100 extended font-mapping
+#endif
+*/
+
+// fontMap = identicalMap;
+ emit changedFontMetricSignal( font_h, font_w );
+ propagateSize();
+ update();
+}
+
+void TEWidget::setVTFont(const QFont& f)
+{
+ QFont font = f;
+
+ // the font must be small enough to allow at least one line and one character of text to fit
+ // on screen
+ QFontMetrics metrics(f);
+ if ( metrics.height() < height() && metrics.maxWidth() < width() )
+ {
+ if (!s_antialias)
+ font.setStyleStrategy( QFont::NoAntialias );
+ QFrame::setFont(font);
+ fontChange(font);
+ }
+}
+
+void TEWidget::setFont(const QFont &)
+{
+ // ignore font change request if not coming from konsole itself
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Constructor / Destructor */
+/* */
+/* ------------------------------------------------------------------------- */
+
+TEWidget::TEWidget(QWidget *parent, const char *name)
+:QFrame(parent,name,WNoAutoErase)
+,font_h(1)
+,font_w(1)
+,font_a(1)
+,lines(1)
+,columns(1)
+,contentHeight(1)
+,contentWidth(1)
+,image(0)
+,resizing(false)
+,terminalSizeHint(false)
+,terminalSizeStartup(true)
+,bidiEnabled(false)
+,actSel(0)
+,word_selection_mode(false)
+,line_selection_mode(false)
+,preserve_line_breaks(true)
+,column_selection_mode(false)
+,scrollLoc(SCRNONE)
+,word_characters(":@-./_~")
+,m_bellMode(BELLSYSTEM)
+,blinking(false)
+,cursorBlinking(false)
+,hasBlinkingCursor(false)
+,ctrldrag(false)
+,cuttobeginningofline(false)
+,isBlinkEvent(false)
+,isPrinting(false)
+,printerFriendly(false)
+,printerBold(false)
+,isFixedSize(false)
+,m_drop(0)
+,possibleTripleClick(false)
+,mResizeWidget(0)
+,mResizeLabel(0)
+,mResizeTimer(0)
+,m_lineSpacing(0)
+,colorsSwapped(false)
+,rimX(1)
+,rimY(1)
+,m_imPreeditText(QString::null)
+,m_imPreeditLength(0)
+,m_imStart(0)
+,m_imStartLine(0)
+,m_imEnd(0)
+,m_imSelStart(0)
+,m_imSelEnd(0)
+,m_cursorLine(0)
+,m_cursorCol(0)
+,m_isIMEdit(false)
+,m_isIMSel(false)
+,blend_color(qRgba(0,0,0,0xff))
+{
+ // The offsets are not yet calculated.
+ // Do not calculate these too often to be more smoothly when resizing
+ // konsole in opaque mode.
+ bY = bX = 1;
+
+ cb = QApplication::clipboard();
+ QObject::connect( (QObject*)cb, SIGNAL(selectionChanged()),
+ this, SLOT(onClearSelection()) );
+
+ scrollbar = new QScrollBar(this);
+ scrollbar->setCursor( arrowCursor );
+ connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
+
+ blinkT = new QTimer(this);
+ connect(blinkT, SIGNAL(timeout()), this, SLOT(blinkEvent()));
+ blinkCursorT = new QTimer(this);
+ connect(blinkCursorT, SIGNAL(timeout()), this, SLOT(blinkCursorEvent()));
+
+ setMouseMarks(true);
+ setColorTable(base_color_table); // init color table
+
+ qApp->installEventFilter( this ); //FIXME: see below
+ KCursor::setAutoHideCursor( this, true );
+
+ // Init DnD ////////////////////////////////////////////////////////////////
+ setAcceptDrops(true); // attempt
+ dragInfo.state = diNone;
+
+ setFocusPolicy( WheelFocus );
+
+ // im
+ setInputMethodEnabled(true);
+
+ if (!argb_visual)
+ {
+ // Looks better at startup with KRootPixmap based pseudo-transparancy
+ setBackgroundMode(NoBackground);
+ }
+}
+
+//FIXME: make proper destructor
+// Here's a start (David)
+TEWidget::~TEWidget()
+{
+ qApp->removeEventFilter( this );
+ if (image) free(image);
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Display Operations */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/**
+ A table for emulating the simple (single width) unicode drawing chars.
+ It represents the 250x - 257x glyphs. If it's zero, we can't use it.
+ if it's not, it's encoded as follows: imagine a 5x5 grid where the points are numbered
+ 0 to 24 left to top, top to bottom. Each point is represented by the corresponding bit.
+
+ Then, the pixels basically have the following interpretation:
+ _|||_
+ -...-
+ -...-
+ -...-
+ _|||_
+
+where _ = none
+ | = vertical line.
+ - = horizontal line.
+ */
+
+
+enum LineEncode
+{
+ TopL = (1<<1),
+ TopC = (1<<2),
+ TopR = (1<<3),
+
+ LeftT = (1<<5),
+ Int11 = (1<<6),
+ Int12 = (1<<7),
+ Int13 = (1<<8),
+ RightT = (1<<9),
+
+ LeftC = (1<<10),
+ Int21 = (1<<11),
+ Int22 = (1<<12),
+ Int23 = (1<<13),
+ RightC = (1<<14),
+
+ LeftB = (1<<15),
+ Int31 = (1<<16),
+ Int32 = (1<<17),
+ Int33 = (1<<18),
+ RightB = (1<<19),
+
+ BotL = (1<<21),
+ BotC = (1<<22),
+ BotR = (1<<23)
+};
+
+#include "linefont.h"
+
+static void drawLineChar(QPainter& paint, int x, int y, int w, int h, uchar code)
+{
+ //Calculate cell midpoints, end points.
+ int cx = x + w/2;
+ int cy = y + h/2;
+ int ex = x + w - 1;
+ int ey = y + h - 1;
+
+ Q_UINT32 toDraw = LineChars[code];
+
+ //Top lines:
+ if (toDraw & TopL)
+ paint.drawLine(cx-1, y, cx-1, cy-2);
+ if (toDraw & TopC)
+ paint.drawLine(cx, y, cx, cy-2);
+ if (toDraw & TopR)
+ paint.drawLine(cx+1, y, cx+1, cy-2);
+
+ //Bot lines:
+ if (toDraw & BotL)
+ paint.drawLine(cx-1, cy+2, cx-1, ey);
+ if (toDraw & BotC)
+ paint.drawLine(cx, cy+2, cx, ey);
+ if (toDraw & BotR)
+ paint.drawLine(cx+1, cy+2, cx+1, ey);
+
+ //Left lines:
+ if (toDraw & LeftT)
+ paint.drawLine(x, cy-1, cx-2, cy-1);
+ if (toDraw & LeftC)
+ paint.drawLine(x, cy, cx-2, cy);
+ if (toDraw & LeftB)
+ paint.drawLine(x, cy+1, cx-2, cy+1);
+
+ //Right lines:
+ if (toDraw & RightT)
+ paint.drawLine(cx+2, cy-1, ex, cy-1);
+ if (toDraw & RightC)
+ paint.drawLine(cx+2, cy, ex, cy);
+ if (toDraw & RightB)
+ paint.drawLine(cx+2, cy+1, ex, cy+1);
+
+ //Intersection points.
+ if (toDraw & Int11)
+ paint.drawPoint(cx-1, cy-1);
+ if (toDraw & Int12)
+ paint.drawPoint(cx, cy-1);
+ if (toDraw & Int13)
+ paint.drawPoint(cx+1, cy-1);
+
+ if (toDraw & Int21)
+ paint.drawPoint(cx-1, cy);
+ if (toDraw & Int22)
+ paint.drawPoint(cx, cy);
+ if (toDraw & Int23)
+ paint.drawPoint(cx+1, cy);
+
+ if (toDraw & Int31)
+ paint.drawPoint(cx-1, cy+1);
+ if (toDraw & Int32)
+ paint.drawPoint(cx, cy+1);
+ if (toDraw & Int33)
+ paint.drawPoint(cx+1, cy+1);
+
+}
+
+void TEWidget::drawTextFixed(QPainter &paint, int x, int y,
+ QString& str, const ca *attr)
+{
+ QString drawstr;
+ unsigned int nc=0;
+ int w;
+ for(unsigned int i=0;i<str.length();i++)
+ {
+ drawstr = str.at(i);
+ // Add double of the width if next c is 0;
+ if ((attr+nc+1)->c) // This may access image[image_size] See makeImage()
+ {
+ w = font_w;
+ nc++;
+ }
+ else
+ {
+ w = font_w*2;
+ nc+=2;
+ }
+
+ //Check for line-drawing char
+ if (isLineChar(drawstr[0].unicode()))
+ {
+ uchar code = drawstr[0].cell();
+ if (LineChars[code])
+ {
+ drawLineChar(paint, x, y, w, font_h, code);
+ x += w;
+ continue;
+ }
+ }
+
+ paint.drawText(x,y, w, font_h, Qt::AlignHCenter | Qt::DontClip, drawstr, -1);
+ x += w;
+ }
+}
+
+
+/*!
+ attributed string draw primitive
+*/
+
+void TEWidget::drawAttrStr(QPainter &paint, QRect rect,
+ QString& str, const ca *attr, bool pm, bool clear)
+{
+ int a = font_a + m_lineSpacing / 2;
+ QColor fColor = printerFriendly ? Qt::black : attr->f.color(color_table);
+ QColor bColor = attr->b.color(color_table);
+ QString drawstr;
+
+ if ((attr->r & RE_CURSOR) && !isPrinting)
+ cursorRect = rect;
+
+ // Paint background
+ if (!printerFriendly)
+ {
+ if (attr->isTransparent(color_table))
+ {
+ if (pm)
+ paint.setBackgroundMode( TransparentMode );
+ if (clear || (blinking && (attr->r & RE_BLINK)))
+ erase(rect);
+ }
+ else
+ {
+ if (pm || clear || (blinking && (attr->r & RE_BLINK)) ||
+ attr->b == cacol(CO_DFT, colorsSwapped ? DEFAULT_FORE_COLOR : DEFAULT_BACK_COLOR) )
+
+ // draw background colors with 75% opacity
+ if ( argb_visual && qAlpha(blend_color) < 0xff ) {
+ QRgb col = bColor.rgb();
+
+ Q_UINT8 salpha = 192;
+ Q_UINT8 dalpha = 255 - salpha;
+
+ int a, r, g, b;
+ a = QMIN( (qAlpha (col) * salpha) / 255 + (qAlpha (blend_color) * dalpha) / 255, 255 );
+ r = QMIN( (qRed (col) * salpha) / 255 + (qRed (blend_color) * dalpha) / 255, 255 );
+ g = QMIN( (qGreen (col) * salpha) / 255 + (qGreen (blend_color) * dalpha) / 255, 255 );
+ b = QMIN( (qBlue (col) * salpha) / 255 + (qBlue (blend_color) * dalpha) / 255, 255 );
+
+ col = a << 24 | r << 16 | g << 8 | b;
+ int pixel = a << 24 | (r * a / 255) << 16 | (g * a / 255) << 8 | (b * a / 255);
+
+ paint.fillRect(rect, QColor(col, pixel));
+ } else
+ paint.fillRect(rect, bColor);
+ }
+
+ QString tmpStr = str.simplifyWhiteSpace();
+ if ( m_isIMEdit && !tmpStr.isEmpty() ) { // imput method edit area background color
+ QRect tmpRect = rect;
+ if ( str != m_imPreeditText ) { // ugly hack
+ tmpRect.setLeft( tmpRect.left() + font_w );
+ tmpRect.setWidth( tmpRect.width() + font_w );
+ }
+
+ paint.fillRect( tmpRect, Qt::darkCyan ); // currently use hard code color
+ }
+
+ if ( m_isIMSel && !tmpStr.isEmpty() ) { // imput method selection background color
+ int x = rect.left() + ( font_w * (m_imSelStart - m_imStart) );
+ int y = rect.top();
+ int w = font_w * (m_imSelEnd - m_imSelStart);
+ int h = font_h;
+
+ QRect tmpRect = QRect( x, y, w, h );
+ if ( str != m_imPreeditText ) { // ugly hack
+ tmpRect.setLeft( tmpRect.left() + font_w );
+ tmpRect.setWidth( tmpRect.width() + font_w );
+ }
+
+ paint.fillRect( tmpRect, Qt::darkGray ); // currently use hard code color
+ }
+ }
+
+ // Paint cursor
+ if ((attr->r & RE_CURSOR) && !isPrinting) {
+ paint.setBackgroundMode( TransparentMode );
+ int h = font_h - m_lineSpacing;
+ QRect r(rect.x(),rect.y()+m_lineSpacing/2,rect.width(),h);
+ if (hasFocus())
+ {
+ if (!cursorBlinking)
+ {
+ paint.fillRect(r, fColor);
+ fColor = bColor;
+ }
+ }
+ else
+ {
+ paint.setPen(fColor);
+ paint.drawRect(r);
+ }
+ }
+
+ if (!(blinking && (attr->r & RE_BLINK)))
+ {
+ // ### Disabled for now, since it causes problems with characters
+ // that use the full width and/or height of the character cells.
+ //bool shadow = ( !isPrinting && qAlpha(blend_color) < 0xff
+ // && qGray( fColor.rgb() ) > 64 );
+ bool shadow = false;
+ paint.setPen(fColor);
+ int x = rect.x();
+
+ if (attr->isBold(color_table) && printerBold)
+ {
+ // When printing we use a bold font for bold
+ paint.save();
+ QFont f = font();
+ f.setBold(true);
+ paint.setFont(f);
+ }
+
+ if(!fixed_font)
+ {
+ // The meaning of y differs between different versions of QPainter::drawText!!
+ int y = rect.y(); // top of rect
+
+ if ( shadow ) {
+ paint.setPen( Qt::black );
+ drawTextFixed(paint, x+1, y+1, str, attr);
+ paint.setPen(fColor);
+ }
+
+ drawTextFixed(paint, x, y, str, attr);
+ }
+ else
+ {
+ // The meaning of y differs between different versions of QPainter::drawText!!
+ int y = rect.y()+a; // baseline
+
+ if ( shadow ) {
+ paint.setPen( Qt::black );
+ paint.drawText(x+1,y+1, str, -1, bidiEnabled ? QPainter::Auto : QPainter::LTR );
+ paint.setPen(fColor);
+ }
+
+ paint.drawText(x,y, str, -1, bidiEnabled ? QPainter::Auto : QPainter::LTR );
+ }
+
+ if (attr->isBold(color_table) && isPrinting)
+ {
+ // When printing we use a bold font for bold
+ paint.restore();
+ }
+
+ if ( attr->isBold(color_table) && !printerBold)
+ {
+ paint.setClipRect(rect);
+ // On screen we use overstrike for bold
+ paint.setBackgroundMode( TransparentMode );
+ int x = rect.x()+1;
+ if(!fixed_font)
+ {
+ // The meaning of y differs between different versions of QPainter::drawText!!
+ int y = rect.y(); // top of rect
+ drawTextFixed(paint, x, y, str, attr);
+ }
+ else
+ {
+ // The meaning of y differs between different versions of QPainter::drawText!!
+ int y = rect.y()+a; // baseline
+ if (bidiEnabled)
+ paint.drawText(x,y, str, -1);
+ else
+ paint.drawText(x,y, str, -1, QPainter::LTR);
+ }
+ paint.setClipping(false);
+ }
+ if (attr->r & RE_UNDERLINE)
+ paint.drawLine(rect.left(), rect.y()+a+1,
+ rect.right(),rect.y()+a+1 );
+ }
+}
+
+/*!
+ Set XIM Position
+*/
+void TEWidget::setCursorPos(const int curx, const int cury)
+{
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+
+ int xpos, ypos;
+ ypos = bY + tLy + font_h*(cury-1) + font_a;
+ xpos = bX + tLx + font_w*curx;
+ /* The hasFocus() check is to avoid crashes in QXIMInputContext on some systems.
+ See http://lists.kde.org/?l=kde-core-devel&m=115770546313922&w=2 . */
+ if (hasFocus())
+ setMicroFocusHint(xpos, ypos, 0, font_h);
+ // fprintf(stderr, "x/y = %d/%d\txpos/ypos = %d/%d\n", curx, cury, xpos, ypos);
+ m_cursorLine = cury;
+ m_cursorCol = curx;
+}
+
+/*!
+ The image can only be set completely.
+
+ The size of the new image may or may not match the size of the widget.
+*/
+
+void TEWidget::setImage(const ca* const newimg, int lines, int columns)
+{
+ if (!image)
+ updateImageSize(); // Create image
+
+ int y,x,len;
+ const QPixmap* pm = backgroundPixmap();
+ QPainter paint;
+ setUpdatesEnabled(false);
+ paint.begin( this );
+
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+ hasBlinker = false;
+
+ cacol cf; // undefined
+ cacol cb; // undefined
+ int cr = -1; // undefined
+
+ int lins = QMIN(this->lines, QMAX(0,lines ));
+ int cols = QMIN(this->columns,QMAX(0,columns));
+ QChar *disstrU = new QChar[cols];
+ char *dirtyMask = (char *) malloc(cols+2);
+
+//{ static int cnt = 0; printf("setImage %d\n",cnt++); }
+ for (y = 0; y < lins; y++)
+ {
+ const ca* lcl = &image[y*this->columns];
+ const ca* const ext = &newimg[y*columns];
+
+ // The dirty mask indicates which characters need repainting. We also
+ // mark surrounding neighbours dirty, in case the character exceeds
+ // its cell boundaries
+ memset(dirtyMask, 0, cols+2);
+ // Two extra so that we don't have to have to care about start and end conditions
+ for (x = 0; x < cols; x++)
+ {
+ if ( ( (m_imPreeditLength > 0) && ( ( m_imStartLine == y )
+ && ( ( m_imStart < m_imEnd ) && ( ( x > m_imStart ) ) && ( x < m_imEnd ) )
+ || ( ( m_imSelStart < m_imSelEnd ) && ( ( x > m_imSelStart ) ) ) ) )
+ || ext[x] != lcl[x])
+ {
+ dirtyMask[x] = dirtyMask[x+1] = dirtyMask[x+2] = 1;
+ }
+ }
+ dirtyMask++; // Position correctly
+
+ if (!resizing) // not while resizing, we're expecting a paintEvent
+ for (x = 0; x < cols; x++)
+ {
+ hasBlinker |= (ext[x].r & RE_BLINK);
+ // Start drawing if this character or the next one differs.
+ // We also take the next one into account to handle the situation
+ // where characters exceed their cell width.
+ if (dirtyMask[x])
+ {
+ Q_UINT16 c = ext[x+0].c;
+ if ( !c )
+ continue;
+ int p = 0;
+ disstrU[p++] = c; //fontMap(c);
+ bool lineDraw = isLineChar(c);
+ bool doubleWidth = (ext[x+1].c == 0);
+ cr = ext[x].r;
+ cb = ext[x].b;
+ if (ext[x].f != cf) cf = ext[x].f;
+ int lln = cols - x;
+ for (len = 1; len < lln; len++)
+ {
+ c = ext[x+len].c;
+ if (!c)
+ continue; // Skip trailing part of multi-col chars.
+
+ if (ext[x+len].f != cf || ext[x+len].b != cb || ext[x+len].r != cr ||
+ !dirtyMask[x+len] || isLineChar(c) != lineDraw || (ext[x+len+1].c == 0) != doubleWidth)
+ break;
+
+ disstrU[p++] = c; //fontMap(c);
+ }
+
+ QString unistr(disstrU, p);
+
+ // for XIM on the spot input style
+ m_isIMEdit = m_isIMSel = false;
+ if ( m_imStartLine == y ) {
+ if ( ( m_imStart < m_imEnd ) && ( x >= m_imStart-1 ) && ( x + int( unistr.length() ) <= m_imEnd ) )
+ m_isIMEdit = true;
+
+ if ( ( m_imSelStart < m_imSelEnd ) && ( x >= m_imStart-1 ) && ( x + int( unistr.length() ) <= m_imEnd ) )
+ m_isIMSel = true;
+ }
+ else if ( m_imStartLine < y ) { // for word worp
+ if ( ( m_imStart < m_imEnd ) )
+ m_isIMEdit = true;
+
+ if ( ( m_imSelStart < m_imSelEnd ) )
+ m_isIMSel = true;
+ }
+
+ bool save_fixed_font = fixed_font;
+ if (lineDraw)
+ fixed_font = false;
+ if (doubleWidth)
+ fixed_font = false;
+ drawAttrStr(paint,
+ QRect(bX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
+ unistr, &ext[x], pm != NULL, true);
+ fixed_font = save_fixed_font;
+ x += len - 1;
+ }
+ }
+
+ dirtyMask--; // Set back
+
+ // finally, make `image' become `newimg'.
+ memcpy((void*)lcl,(const void*)ext,cols*sizeof(ca));
+ }
+ drawFrame( &paint );
+ paint.end();
+ setUpdatesEnabled(true);
+ if ( hasBlinker && !blinkT->isActive()) blinkT->start(1000); // 1000 ms
+ if (!hasBlinker && blinkT->isActive()) { blinkT->stop(); blinking = false; }
+ free(dirtyMask);
+ delete [] disstrU;
+
+ if (resizing && terminalSizeHint)
+ {
+ if (terminalSizeStartup) {
+ terminalSizeStartup=false;
+ return;
+ }
+ if (!mResizeWidget)
+ {
+ mResizeWidget = new QFrame(this);
+ QFont f = KGlobalSettings::generalFont();
+ int fs = f.pointSize();
+ if (fs == -1)
+ fs = QFontInfo(f).pointSize();
+ f.setPointSize((fs*3)/2);
+ f.setBold(true);
+ mResizeWidget->setFont(f);
+ mResizeWidget->setFrameShape((QFrame::Shape) (QFrame::Box|QFrame::Raised));
+ mResizeWidget->setMidLineWidth(4);
+ QBoxLayout *l = new QVBoxLayout( mResizeWidget, 10);
+ mResizeLabel = new QLabel(i18n("Size: XXX x XXX"), mResizeWidget);
+ l->addWidget(mResizeLabel, 1, AlignCenter);
+ mResizeWidget->setMinimumWidth(mResizeLabel->fontMetrics().width(i18n("Size: XXX x XXX"))+20);
+ mResizeWidget->setMinimumHeight(mResizeLabel->sizeHint().height()+20);
+ mResizeTimer = new QTimer(this);
+ connect(mResizeTimer, SIGNAL(timeout()), mResizeWidget, SLOT(hide()));
+ }
+ QString sizeStr = i18n("Size: %1 x %2").arg(columns).arg(lines);
+ mResizeLabel->setText(sizeStr);
+ mResizeWidget->move((width()-mResizeWidget->width())/2,
+ (height()-mResizeWidget->height())/2+20);
+ mResizeWidget->show();
+ mResizeTimer->start(1000, true);
+ }
+}
+
+void TEWidget::setBlinkingCursor(bool blink)
+{
+ hasBlinkingCursor=blink;
+ if (blink && !blinkCursorT->isActive()) blinkCursorT->start(1000);
+ if (!blink && blinkCursorT->isActive()) {
+ blinkCursorT->stop();
+ if (cursorBlinking)
+ blinkCursorEvent();
+ else
+ cursorBlinking = false;
+ }
+}
+
+// paint Event ////////////////////////////////////////////////////
+
+/*!
+ The difference of this routine vs. the `setImage' is,
+ that the drawing does not include a difference analysis
+ between the old and the new image. Instead, the internal
+ image is used and the painting bound by the PaintEvent box.
+*/
+
+void TEWidget::paintEvent( QPaintEvent* pe )
+{
+ const QPixmap* pm = backgroundPixmap();
+ QPainter paint;
+ setUpdatesEnabled(false);
+ paint.begin( this );
+ paint.setBackgroundMode( TransparentMode );
+
+ // Note that the actual widget size can be slightly larger
+ // that the image (the size is truncated towards the smaller
+ // number of characters in `resizeEvent'. The paint rectangle
+ // can thus be larger than the image, but less then the size
+ // of one character.
+
+ QRect rect = pe->rect().intersect(contentsRect());
+
+ paintContents(paint, rect, pm != 0);
+
+ drawFrame( &paint );
+
+ // Since we're using WNoAutoErase, we have to make sure that
+ // every single pixel is painted by the paint event.
+ // To do this, we must figure out which pixels are left in the
+ // area between the terminal image and the frame border.
+
+ // Calculate the contents rect excluding scroll bar.
+ QRect innerRect = contentsRect();
+ if( scrollLoc != SCRNONE )
+ innerRect.setWidth( innerRect.width() - scrollbar->width() );
+
+ innerRect.setWidth( innerRect.width() + 3 );
+ innerRect.setHeight( innerRect.height() );
+
+ // Calculate the emulation rect (area needed for actual terminal contents)
+ QRect emurect( contentsRect().topLeft(), QSize( columns * font_w + 2 * rimX, lines * font_h + 2 * rimY ));
+
+ // Now erase() the remaining pixels on all sides of the emulation
+
+ // Top
+ QRect er( innerRect );
+ er.setBottom( emurect.top() );
+ erase( er );
+
+ // Bottom
+ er.setBottom( innerRect.bottom() );
+ er.setTop( emurect.bottom() );
+ erase( er );
+
+ // Left
+ er.setTop( emurect.top() );
+ er.setBottom( emurect.bottom() - 1 );
+ er.setRight( emurect.left() );
+ erase( er );
+
+ // Right
+ er.setRight( innerRect.right() );
+ er.setTop( emurect.top() );
+ er.setBottom( emurect.bottom() - 1 );
+ er.setLeft( emurect.right() );
+ erase( er );
+
+ paint.end();
+ setUpdatesEnabled(true);
+}
+
+void TEWidget::print(QPainter &paint, bool friendly, bool exact)
+{
+ bool save_fixed_font = fixed_font;
+ bool save_blinking = blinking;
+ fixed_font = false;
+ blinking = false;
+ paint.setFont(font());
+
+ isPrinting = true;
+ printerFriendly = friendly;
+ printerBold = !exact;
+
+ if (exact)
+ {
+ QPixmap pm(contentsRect().right(), contentsRect().bottom());
+ pm.fill();
+
+ QPainter pm_paint;
+ pm_paint.begin(&pm, this);
+ paintContents(pm_paint, contentsRect(), true);
+ pm_paint.end();
+ paint.drawPixmap(0, 0, pm);
+ }
+ else
+ {
+ paintContents(paint, contentsRect(), true);
+ }
+
+ printerFriendly = false;
+ isPrinting = false;
+ printerBold = false;
+
+ fixed_font = save_fixed_font;
+ blinking = save_blinking;
+}
+
+void TEWidget::paintContents(QPainter &paint, const QRect &rect, bool pm)
+{
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+
+ int lux = QMIN(columns-1, QMAX(0,(rect.left() - tLx - bX ) / font_w));
+ int luy = QMIN(lines-1, QMAX(0,(rect.top() - tLy - bY ) / font_h));
+ int rlx = QMIN(columns-1, QMAX(0,(rect.right() - tLx - bX ) / font_w));
+ int rly = QMIN(lines-1, QMAX(0,(rect.bottom() - tLy - bY ) / font_h));
+
+ QChar *disstrU = new QChar[columns];
+ for (int y = luy; y <= rly; y++)
+ {
+ Q_UINT16 c = image[loc(lux,y)].c;
+ int x = lux;
+ if(!c && x)
+ x--; // Search for start of multi-col char
+ for (; x <= rlx; x++)
+ {
+ int len = 1;
+ int p = 0;
+ c = image[loc(x,y)].c;
+ if (c)
+ disstrU[p++] = c; //fontMap(c);
+ bool lineDraw = isLineChar(c);
+ bool doubleWidth = (image[loc(x,y)+1].c == 0);
+ cacol cf = image[loc(x,y)].f;
+ cacol cb = image[loc(x,y)].b;
+ int cr = image[loc(x,y)].r;
+ while (x+len <= rlx &&
+ image[loc(x+len,y)].f == cf &&
+ image[loc(x+len,y)].b == cb &&
+ image[loc(x+len,y)].r == cr &&
+ (image[loc(x+len,y)+1].c == 0) == doubleWidth &&
+ isLineChar( c = image[loc(x+len,y)].c) == lineDraw) // Assignment!
+ {
+ if (c)
+ disstrU[p++] = c; //fontMap(c);
+ if (doubleWidth) // assert((image[loc(x+len,y)+1].c == 0)), see above if condition
+ len++; // Skip trailing part of multi-column char
+ len++;
+ }
+ if ((x+len < columns) && (!image[loc(x+len,y)].c))
+ len++; // Adjust for trailing part of multi-column char
+
+ if (!isBlinkEvent || (cr & RE_BLINK))
+ {
+ bool save_fixed_font = fixed_font;
+ if (lineDraw)
+ fixed_font = false;
+ if (doubleWidth)
+ fixed_font = false;
+ QString unistr(disstrU,p);
+ drawAttrStr(paint,
+ QRect(bX+tLx+font_w*x,bY+tLy+font_h*y,font_w*len,font_h),
+ unistr, &image[loc(x,y)], pm, !(isBlinkEvent || isPrinting));
+ fixed_font = save_fixed_font;
+ }
+ x += len - 1;
+ }
+ }
+ delete [] disstrU;
+}
+
+void TEWidget::blinkEvent()
+{
+ blinking = !blinking;
+ isBlinkEvent = true;
+ repaint(false);
+ isBlinkEvent = false;
+}
+
+void TEWidget::blinkCursorEvent()
+{
+ cursorBlinking = !cursorBlinking;
+ repaint(cursorRect, true);
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Resizing */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEWidget::resizeEvent(QResizeEvent*)
+{
+ updateImageSize();
+}
+
+void TEWidget::propagateSize()
+{
+ if (isFixedSize)
+ {
+ setSize(columns, lines);
+ QFrame::setFixedSize(sizeHint());
+ parentWidget()->adjustSize();
+ parentWidget()->setFixedSize(parentWidget()->sizeHint());
+ return;
+ }
+ if (image)
+ updateImageSize();
+}
+
+void TEWidget::updateImageSize()
+{
+ ca* oldimg = image;
+ int oldlin = lines;
+ int oldcol = columns;
+ makeImage();
+ // we copy the old image to reduce flicker
+ int lins = QMIN(oldlin,lines);
+ int cols = QMIN(oldcol,columns);
+ if (oldimg)
+ {
+ for (int lin = 0; lin < lins; lin++)
+ memcpy((void*)&image[columns*lin],
+ (void*)&oldimg[oldcol*lin],cols*sizeof(ca));
+ free(oldimg); //FIXME: try new,delete
+ }
+
+ //NOTE: control flows from the back through the chest right into the eye.
+ // `emu' will call back via `setImage'.
+
+ resizing = (oldlin!=lines) || (oldcol!=columns);
+ emit changedContentSizeSignal(contentHeight, contentWidth); // expose resizeEvent
+ resizing = false;
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Scrollbar */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEWidget::scrollChanged(int)
+{
+ emit changedHistoryCursor(scrollbar->value()); //expose
+}
+
+void TEWidget::setScroll(int cursor, int slines)
+{
+ //kdDebug(1211)<<"TEWidget::setScroll() disconnect()"<<endl;
+ disconnect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
+ //kdDebug(1211)<<"TEWidget::setScroll() setRange()"<<endl;
+ scrollbar->setRange(0,slines);
+ //kdDebug(1211)<<"TEWidget::setScroll() setSteps()"<<endl;
+ scrollbar->setSteps(1,lines);
+ scrollbar->setValue(cursor);
+ connect(scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scrollChanged(int)));
+ //kdDebug(1211)<<"TEWidget::setScroll() done"<<endl;
+}
+
+void TEWidget::setScrollbarLocation(int loc)
+{
+ if (scrollLoc == loc) return; // quickly
+ bY = bX = 1;
+ scrollLoc = loc;
+ calcGeometry();
+ propagateSize();
+ update();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Mouse */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*!
+ Three different operations can be performed using the mouse, and the
+ routines in this section serve all of them:
+
+ 1) The press/release events are exposed to the application
+ 2) Marking (press and move left button) and Pasting (press middle button)
+ 3) The right mouse button is used from the configuration menu
+
+ NOTE: During the marking process we attempt to keep the cursor within
+ the bounds of the text as being displayed by setting the mouse position
+ whenever the mouse has left the text area.
+
+ Two reasons to do so:
+ 1) QT does not allow the `grabMouse' to confine-to the TEWidget.
+ Thus a `XGrapPointer' would have to be used instead.
+ 2) Even if so, this would not help too much, since the text area
+ of the TEWidget is normally not identical with it's bounds.
+
+ The disadvantage of the current handling is, that the mouse can visibly
+ leave the bounds of the widget and is then moved back. Because of the
+ current construction, and the reasons mentioned above, we cannot do better
+ without changing the overall construction.
+*/
+
+/*!
+*/
+
+void TEWidget::mousePressEvent(QMouseEvent* ev)
+{
+//printf("press [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button());
+
+ if ( possibleTripleClick && (ev->button()==LeftButton) ) {
+ mouseTripleClickEvent(ev);
+ return;
+ }
+
+ if ( !contentsRect().contains(ev->pos()) ) return;
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+
+ QPoint pos = QPoint((ev->x()-tLx-bX+(font_w/2))/font_w,(ev->y()-tLy-bY)/font_h);
+
+//printf("press top left [%d,%d] by=%d\n",tLx,tLy, bY);
+ if ( ev->button() == LeftButton)
+ {
+ line_selection_mode = false;
+ word_selection_mode = false;
+
+ emit isBusySelecting(true); // Keep it steady...
+ // Drag only when the Control key is hold
+ bool selected = false;
+ // The receiver of the testIsSelected() signal will adjust
+ // 'selected' accordingly.
+ emit testIsSelected(pos.x(), pos.y(), selected);
+ if ((!ctrldrag || ev->state() & ControlButton) && selected ) {
+ // The user clicked inside selected text
+ dragInfo.state = diPending;
+ dragInfo.start = ev->pos();
+ }
+ else {
+ // No reason to ever start a drag event
+ dragInfo.state = diNone;
+
+ preserve_line_breaks = !( ( ev->state() & ControlButton ) && !(ev->state() & AltButton) );
+ column_selection_mode = (ev->state() & AltButton) && (ev->state() & ControlButton);
+
+ if (mouse_marks || (ev->state() & ShiftButton))
+ {
+ emit clearSelectionSignal();
+ pos.ry() += scrollbar->value();
+ iPntSel = pntSel = pos;
+ actSel = 1; // left mouse button pressed but nothing selected yet.
+ grabMouse( /*crossCursor*/ ); // handle with care!
+ }
+ else
+ {
+ emit mouseSignal( 0, (ev->x()-tLx-bX)/font_w +1, (ev->y()-tLy-bY)/font_h +1 +scrollbar->value() -scrollbar->maxValue() );
+ }
+ }
+ }
+ else if ( ev->button() == MidButton )
+ {
+ if ( mouse_marks || (!mouse_marks && (ev->state() & ShiftButton)) )
+ emitSelection(true,ev->state() & ControlButton);
+ else
+ emit mouseSignal( 1, (ev->x()-tLx-bX)/font_w +1, (ev->y()-tLy-bY)/font_h +1 +scrollbar->value() -scrollbar->maxValue() );
+ }
+ else if ( ev->button() == RightButton )
+ {
+ if (mouse_marks || (ev->state() & ShiftButton)) {
+ configureRequestPoint = QPoint( ev->x(), ev->y() );
+ emit configureRequest( this, ev->state()&(ShiftButton|ControlButton), ev->x(), ev->y() );
+ }
+ else
+ emit mouseSignal( 2, (ev->x()-tLx-bX)/font_w +1, (ev->y()-tLy-bY)/font_h +1 +scrollbar->value() -scrollbar->maxValue() );
+ }
+}
+
+void TEWidget::mouseMoveEvent(QMouseEvent* ev)
+{
+ // for auto-hiding the cursor, we need mouseTracking
+ if (ev->state() == NoButton ) return;
+
+ if (dragInfo.state == diPending) {
+ // we had a mouse down, but haven't confirmed a drag yet
+ // if the mouse has moved sufficiently, we will confirm
+
+ int distance = KGlobalSettings::dndEventDelay();
+ if ( ev->x() > dragInfo.start.x() + distance || ev->x() < dragInfo.start.x() - distance ||
+ ev->y() > dragInfo.start.y() + distance || ev->y() < dragInfo.start.y() - distance) {
+ // we've left the drag square, we can start a real drag operation now
+ emit isBusySelecting(false); // Ok.. we can breath again.
+ emit clearSelectionSignal();
+ doDrag();
+ }
+ return;
+ } else if (dragInfo.state == diDragging) {
+ // this isn't technically needed because mouseMoveEvent is suppressed during
+ // Qt drag operations, replaced by dragMoveEvent
+ return;
+ }
+
+ if (actSel == 0) return;
+
+ // don't extend selection while pasting
+ if (ev->state() & MidButton) return;
+
+ extendSelection( ev->pos() );
+}
+
+void TEWidget::setSelectionEnd()
+{
+ extendSelection( configureRequestPoint );
+}
+
+void TEWidget::extendSelection( QPoint pos )
+{
+ //if ( !contentsRect().contains(ev->pos()) ) return;
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+ int scroll = scrollbar->value();
+
+ // we're in the process of moving the mouse with the left button pressed
+ // the mouse cursor will kept caught within the bounds of the text in
+ // this widget.
+
+ // Adjust position within text area bounds. See FIXME above.
+ QPoint oldpos = pos;
+ if ( pos.x() < tLx+bX ) pos.setX( tLx+bX );
+ if ( pos.x() > tLx+bX+columns*font_w-1 ) pos.setX( tLx+bX+columns*font_w );
+ if ( pos.y() < tLy+bY ) pos.setY( tLy+bY );
+ if ( pos.y() > tLy+bY+lines*font_h-1 ) pos.setY( tLy+bY+lines*font_h-1 );
+
+ // check if we produce a mouse move event by this
+ if ( pos != oldpos ) cursor().setPos(mapToGlobal(pos));
+
+ if ( pos.y() == tLy+bY+lines*font_h-1 )
+ {
+ scrollbar->setValue(scrollbar->value()+yMouseScroll); // scrollforward
+ }
+ if ( pos.y() == tLy+bY )
+ {
+ scrollbar->setValue(scrollbar->value()-yMouseScroll); // scrollback
+ }
+
+ QPoint here = QPoint((pos.x()-tLx-bX+(font_w/2))/font_w,(pos.y()-tLy-bY)/font_h);
+ QPoint ohere;
+ QPoint iPntSelCorr = iPntSel;
+ iPntSelCorr.ry() -= scrollbar->value();
+ QPoint pntSelCorr = pntSel;
+ pntSelCorr.ry() -= scrollbar->value();
+ bool swapping = false;
+
+ if ( word_selection_mode )
+ {
+ // Extend to word boundaries
+ int i;
+ int selClass;
+
+ bool left_not_right = ( here.y() < iPntSelCorr.y() ||
+ here.y() == iPntSelCorr.y() && here.x() < iPntSelCorr.x() );
+ bool old_left_not_right = ( pntSelCorr.y() < iPntSelCorr.y() ||
+ pntSelCorr.y() == iPntSelCorr.y() && pntSelCorr.x() < iPntSelCorr.x() );
+ swapping = left_not_right != old_left_not_right;
+
+ // Find left (left_not_right ? from here : from start)
+ QPoint left = left_not_right ? here : iPntSelCorr;
+ i = loc(left.x(),left.y());
+ if (i>=0 && i<=image_size) {
+ selClass = charClass(image[i].c);
+ while ( ((left.x()>0) || (left.y()>0 && m_line_wrapped[left.y()-1])) && charClass(image[i-1].c) == selClass )
+ { i--; if (left.x()>0) left.rx()--; else {left.rx()=columns-1; left.ry()--;} }
+ }
+
+ // Find left (left_not_right ? from start : from here)
+ QPoint right = left_not_right ? iPntSelCorr : here;
+ i = loc(right.x(),right.y());
+ if (i>=0 && i<=image_size) {
+ selClass = charClass(image[i].c);
+ while( ((right.x()<columns-1) || (right.y()<lines-1 && m_line_wrapped[right.y()])) && charClass(image[i+1].c) == selClass )
+ { i++; if (right.x()<columns-1) right.rx()++; else {right.rx()=0; right.ry()++; } }
+ }
+
+ // Pick which is start (ohere) and which is extension (here)
+ if ( left_not_right )
+ {
+ here = left; ohere = right;
+ }
+ else
+ {
+ here = right; ohere = left;
+ }
+ ohere.rx()++;
+ }
+
+ if ( line_selection_mode )
+ {
+ // Extend to complete line
+ bool above_not_below = ( here.y() < iPntSelCorr.y() );
+
+ QPoint above = above_not_below ? here : iPntSelCorr;
+ QPoint below = above_not_below ? iPntSelCorr : here;
+
+ while (above.y()>0 && m_line_wrapped[above.y()-1])
+ above.ry()--;
+ while (below.y()<lines-1 && m_line_wrapped[below.y()])
+ below.ry()++;
+
+ above.setX(0);
+ below.setX(columns-1);
+
+ // Pick which is start (ohere) and which is extension (here)
+ if ( above_not_below )
+ {
+ here = above; ohere = below;
+ }
+ else
+ {
+ here = below; ohere = above;
+ }
+
+ QPoint newSelBegin = QPoint( ohere.x(), ohere.y() );
+ swapping = !(tripleSelBegin==newSelBegin);
+ tripleSelBegin = newSelBegin;
+
+ ohere.rx()++;
+ }
+
+ int offset = 0;
+ if ( !word_selection_mode && !line_selection_mode )
+ {
+ int i;
+ int selClass;
+
+ bool left_not_right = ( here.y() < iPntSelCorr.y() ||
+ here.y() == iPntSelCorr.y() && here.x() < iPntSelCorr.x() );
+ bool old_left_not_right = ( pntSelCorr.y() < iPntSelCorr.y() ||
+ pntSelCorr.y() == iPntSelCorr.y() && pntSelCorr.x() < iPntSelCorr.x() );
+ swapping = left_not_right != old_left_not_right;
+
+ // Find left (left_not_right ? from here : from start)
+ QPoint left = left_not_right ? here : iPntSelCorr;
+
+ // Find left (left_not_right ? from start : from here)
+ QPoint right = left_not_right ? iPntSelCorr : here;
+ if ( right.x() > 0 && !column_selection_mode )
+ {
+ i = loc(right.x(),right.y());
+ if (i>=0 && i<=image_size) {
+ selClass = charClass(image[i-1].c);
+ if (selClass == ' ')
+ {
+ while ( right.x() < columns-1 && charClass(image[i+1].c) == selClass && (right.y()<lines-1) && !m_line_wrapped[right.y()])
+ { i++; right.rx()++; }
+ if (right.x() < columns-1)
+ right = left_not_right ? iPntSelCorr : here;
+ else
+ right.rx()++; // will be balanced later because of offset=-1;
+ }
+ }
+ }
+
+ // Pick which is start (ohere) and which is extension (here)
+ if ( left_not_right )
+ {
+ here = left; ohere = right; offset = 0;
+ }
+ else
+ {
+ here = right; ohere = left; offset = -1;
+ }
+ }
+
+ if ((here == pntSelCorr) && (scroll == scrollbar->value())) return; // not moved
+
+ if (here == ohere) return; // It's not left, it's not right.
+
+ if ( actSel < 2 || swapping )
+ if ( column_selection_mode && !line_selection_mode && !word_selection_mode )
+ emit beginSelectionSignal( ohere.x(), ohere.y(), true );
+ else
+ emit beginSelectionSignal( ohere.x()-1-offset, ohere.y(), false );
+
+ actSel = 2; // within selection
+ pntSel = here;
+ pntSel.ry() += scrollbar->value();
+
+ if ( column_selection_mode && !line_selection_mode && !word_selection_mode )
+ emit extendSelectionSignal( here.x(), here.y() );
+ else
+ emit extendSelectionSignal( here.x()+offset, here.y() );
+}
+
+void TEWidget::mouseReleaseEvent(QMouseEvent* ev)
+{
+//printf("release [%d,%d] %d\n",ev->x()/font_w,ev->y()/font_h,ev->button());
+ if ( ev->button() == LeftButton)
+ {
+ emit isBusySelecting(false); // Ok.. we can breath again.
+ if(dragInfo.state == diPending)
+ {
+ // We had a drag event pending but never confirmed. Kill selection
+ emit clearSelectionSignal();
+ }
+ else
+ {
+ if ( actSel > 1 )
+ emit endSelectionSignal(preserve_line_breaks);
+ actSel = 0;
+
+ //FIXME: emits a release event even if the mouse is
+ // outside the range. The procedure used in `mouseMoveEvent'
+ // applies here, too.
+
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+
+ if (!mouse_marks && !(ev->state() & ShiftButton))
+ emit mouseSignal( 3, // release
+ (ev->x()-tLx-bX)/font_w + 1,
+ (ev->y()-tLy-bY)/font_h + 1 +scrollbar->value() -scrollbar->maxValue());
+ releaseMouse();
+ }
+ dragInfo.state = diNone;
+ }
+ if ( !mouse_marks && ((ev->button() == RightButton && !(ev->state() & ShiftButton))
+ || ev->button() == MidButton) ) {
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+
+ emit mouseSignal( 3, (ev->x()-tLx-bX)/font_w +1, (ev->y()-tLy-bY)/font_h +1 +scrollbar->value() -scrollbar->maxValue() );
+ releaseMouse();
+ }
+}
+
+void TEWidget::mouseDoubleClickEvent(QMouseEvent* ev)
+{
+ if ( ev->button() != LeftButton) return;
+
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+ QPoint pos = QPoint((ev->x()-tLx-bX)/font_w,(ev->y()-tLy-bY)/font_h);
+
+ // pass on double click as two clicks.
+ if (!mouse_marks && !(ev->state() & ShiftButton))
+ {
+ // Send just _ONE_ click event, since the first click of the double click
+ // was already sent by the click handler!
+ emit mouseSignal( 0, pos.x()+1, pos.y()+1 +scrollbar->value() -scrollbar->maxValue() ); // left button
+ return;
+ }
+
+
+ emit clearSelectionSignal();
+ QPoint bgnSel = pos;
+ QPoint endSel = pos;
+ int i = loc(bgnSel.x(),bgnSel.y());
+ iPntSel = bgnSel;
+ iPntSel.ry() += scrollbar->value();
+
+ word_selection_mode = true;
+
+ // find word boundaries...
+ int selClass = charClass(image[i].c);
+ {
+ // set the start...
+ int x = bgnSel.x();
+ while ( ((x>0) || (bgnSel.y()>0 && m_line_wrapped[bgnSel.y()-1])) && charClass(image[i-1].c) == selClass )
+ { i--; if (x>0) x--; else {x=columns-1; bgnSel.ry()--;} }
+ bgnSel.setX(x);
+ emit beginSelectionSignal( bgnSel.x(), bgnSel.y(), false );
+
+ // set the end...
+ i = loc( endSel.x(), endSel.y() );
+ x = endSel.x();
+ while( ((x<columns-1) || (endSel.y()<lines-1 && m_line_wrapped[endSel.y()])) && charClass(image[i+1].c) == selClass )
+ { i++; if (x<columns-1) x++; else {x=0; endSel.ry()++; } }
+ endSel.setX(x);
+
+ // In word selection mode don't select @ (64) if at end of word.
+ if ( ( QChar( image[i].c ) == '@' ) && ( ( endSel.x() - bgnSel.x() ) > 0 ) )
+ endSel.setX( x - 1 );
+
+ actSel = 2; // within selection
+ emit extendSelectionSignal( endSel.x(), endSel.y() );
+ emit endSelectionSignal(preserve_line_breaks);
+ }
+
+ possibleTripleClick=true;
+ QTimer::singleShot(QApplication::doubleClickInterval(),this,SLOT(tripleClickTimeout()));
+}
+
+void TEWidget::wheelEvent( QWheelEvent* ev )
+{
+ if (ev->orientation() != Qt::Vertical)
+ return;
+
+ if ( mouse_marks )
+ QApplication::sendEvent(scrollbar, ev);
+ else
+ {
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+ QPoint pos = QPoint((ev->x()-tLx-bX)/font_w,(ev->y()-tLy-bY)/font_h);
+ emit mouseSignal( ev->delta() > 0 ? 4 : 5, pos.x() + 1, pos.y() + 1 +scrollbar->value() -scrollbar->maxValue() );
+ }
+}
+
+void TEWidget::tripleClickTimeout()
+{
+ possibleTripleClick=false;
+}
+
+void TEWidget::mouseTripleClickEvent(QMouseEvent* ev)
+{
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+ iPntSel = QPoint((ev->x()-tLx-bX)/font_w,(ev->y()-tLy-bY)/font_h);
+
+ emit clearSelectionSignal();
+
+ line_selection_mode = true;
+ word_selection_mode = false;
+
+ actSel = 2; // within selection
+ emit isBusySelecting(true); // Keep it steady...
+
+ while (iPntSel.y()>0 && m_line_wrapped[iPntSel.y()-1])
+ iPntSel.ry()--;
+ if (cuttobeginningofline) {
+ // find word boundary start
+ int i = loc(iPntSel.x(),iPntSel.y());
+ int selClass = charClass(image[i].c);
+ int x = iPntSel.x();
+ while ( ((x>0) || (iPntSel.y()>0 && m_line_wrapped[iPntSel.y()-1])) && charClass(image[i-1].c) == selClass )
+ { i--; if (x>0) x--; else {x=columns-1; iPntSel.ry()--;} }
+
+ emit beginSelectionSignal( x, iPntSel.y(), false );
+ tripleSelBegin = QPoint( x, iPntSel.y() );
+ }
+ else {
+ emit beginSelectionSignal( 0, iPntSel.y(), false );
+ tripleSelBegin = QPoint( 0, iPntSel.y() );
+ }
+
+ while (iPntSel.y()<lines-1 && m_line_wrapped[iPntSel.y()])
+ iPntSel.ry()++;
+ emit extendSelectionSignal( columns-1, iPntSel.y() );
+
+ emit endSelectionSignal(preserve_line_breaks);
+
+ iPntSel.ry() += scrollbar->value();
+}
+
+void TEWidget::focusInEvent( QFocusEvent * )
+{
+ repaint(cursorRect, true); // *do* erase area, to get rid of the
+ // hollow cursor rectangle.
+}
+
+
+void TEWidget::focusOutEvent( QFocusEvent * )
+{
+ repaint(cursorRect, true); // don't erase area
+}
+
+bool TEWidget::focusNextPrevChild( bool next )
+{
+ if (next)
+ return false; // This disables changing the active part in konqueror
+ // when pressing Tab
+ return QFrame::focusNextPrevChild( next );
+}
+
+
+int TEWidget::charClass(UINT16 ch) const
+{
+ QChar qch=QChar(ch);
+ if ( qch.isSpace() ) return ' ';
+
+ if ( qch.isLetterOrNumber() || word_characters.contains(qch, false) )
+ return 'a';
+
+ // Everything else is weird
+ return 1;
+}
+
+void TEWidget::setWordCharacters(QString wc)
+{
+ word_characters = wc;
+}
+
+void TEWidget::setMouseMarks(bool on)
+{
+ mouse_marks = on;
+ setCursor( mouse_marks ? ibeamCursor : arrowCursor );
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Clipboard */
+/* */
+/* ------------------------------------------------------------------------- */
+
+#undef KeyPress
+
+void TEWidget::emitText(QString text)
+{
+ if (!text.isEmpty()) {
+ QKeyEvent e(QEvent::KeyPress, 0,-1,0, text);
+ emit keyPressedSignal(&e); // expose as a big fat keypress event
+ }
+}
+
+void TEWidget::emitSelection(bool useXselection,bool appendReturn)
+// Paste Clipboard by simulating keypress events
+{
+ QApplication::clipboard()->setSelectionMode( useXselection );
+ QString text = QApplication::clipboard()->text();
+ if(appendReturn)
+ text.append("\r");
+ if ( ! text.isEmpty() )
+ {
+ text.replace("\n", "\r");
+ QKeyEvent e(QEvent::KeyPress, 0,-1,0, text);
+ emit keyPressedSignal(&e); // expose as a big fat keypress event
+ emit clearSelectionSignal();
+ }
+ QApplication::clipboard()->setSelectionMode( false );
+}
+
+void TEWidget::setSelection(const QString& t)
+{
+ // Disconnect signal while WE set the clipboard
+ QClipboard *cb = QApplication::clipboard();
+ QObject::disconnect( cb, SIGNAL(selectionChanged()),
+ this, SLOT(onClearSelection()) );
+
+ cb->setSelectionMode( true );
+ cb->setText(t);
+ cb->setSelectionMode( false );
+
+ QObject::connect( cb, SIGNAL(selectionChanged()),
+ this, SLOT(onClearSelection()) );
+}
+
+void TEWidget::copyClipboard()
+{
+ emit copySelectionSignal();
+}
+
+void TEWidget::pasteClipboard()
+{
+ emitSelection(false,false);
+}
+
+void TEWidget::pasteSelection()
+{
+ emitSelection(true,false);
+}
+
+void TEWidget::onClearSelection()
+{
+ emit clearSelectionSignal();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Keyboard */
+/* */
+/* ------------------------------------------------------------------------- */
+
+//FIXME: an `eventFilter' has been installed instead of a `keyPressEvent'
+// due to a bug in `QT' or the ignorance of the author to prevent
+// repaint events being emitted to the screen whenever one leaves
+// or reenters the screen to/from another application.
+//
+// Troll says one needs to change focusInEvent() and focusOutEvent(),
+// which would also let you have an in-focus cursor and an out-focus
+// cursor like xterm does.
+
+// for the auto-hide cursor feature, I added empty focusInEvent() and
+// focusOutEvent() so that update() isn't called.
+// For auto-hide, we need to get keypress-events, but we only get them when
+// we have focus.
+
+void TEWidget::doScroll(int lines)
+{
+ scrollbar->setValue(scrollbar->value()+lines);
+}
+
+bool TEWidget::eventFilter( QObject *obj, QEvent *e )
+{
+ if ( (e->type() == QEvent::Accel ||
+ e->type() == QEvent::AccelAvailable ) && qApp->focusWidget() == this )
+ {
+ static_cast<QKeyEvent *>( e )->ignore();
+ return false;
+ }
+ if ( obj != this /* when embedded */ && obj != parent() /* when standalone */ )
+ return false; // not us
+ if ( e->type() == QEvent::KeyPress )
+ {
+ QKeyEvent* ke = (QKeyEvent*)e;
+
+ actSel=0; // Key stroke implies a screen update, so TEWidget won't
+ // know where the current selection is.
+
+ if (hasBlinkingCursor) {
+ blinkCursorT->start(1000);
+ if (cursorBlinking)
+ blinkCursorEvent();
+ else
+ cursorBlinking = false;
+ }
+
+ emit keyPressedSignal(ke); // expose
+
+ // in Qt2 when key events were propagated up the tree
+ // (unhandled? -> parent widget) they passed the event filter only once at
+ // the beginning. in qt3 this has changed, that is, the event filter is
+ // called each time the event is sent (see loop in QApplication::notify,
+ // when internalNotify() is called for KeyPress, whereas internalNotify
+ // activates also the global event filter) . That's why we stop propagation
+ // here.
+ return true;
+ }
+ if ( e->type() == QEvent::Enter )
+ {
+ QObject::disconnect( (QObject*)cb, SIGNAL(dataChanged()),
+ this, SLOT(onClearSelection()) );
+ }
+ if ( e->type() == QEvent::Leave )
+ {
+ QObject::connect( (QObject*)cb, SIGNAL(dataChanged()),
+ this, SLOT(onClearSelection()) );
+ }
+ return QFrame::eventFilter( obj, e );
+}
+
+void TEWidget::imStartEvent( QIMEvent */*e*/ )
+{
+ m_imStart = m_cursorCol;
+ m_imStartLine = m_cursorLine;
+ m_imPreeditLength = 0;
+
+ m_imEnd = m_imSelStart = m_imSelEnd = 0;
+ m_isIMEdit = m_isIMSel = false;
+}
+
+void TEWidget::imComposeEvent( QIMEvent *e )
+{
+ QString text = QString::null;
+ if ( m_imPreeditLength > 0 ) {
+ text.fill( '\010', m_imPreeditLength );
+ }
+
+ m_imEnd = m_imStart + string_width( e->text() );
+
+ QString tmpStr = e->text().left( e->cursorPos() );
+ m_imSelStart = m_imStart + string_width( tmpStr );
+
+ tmpStr = e->text().mid( e->cursorPos(), e->selectionLength() );
+ m_imSelEnd = m_imSelStart + string_width( tmpStr );
+ m_imPreeditLength = e->text().length();
+ m_imPreeditText = e->text();
+ text += e->text();
+
+ if ( text.length() > 0 ) {
+ QKeyEvent ke( QEvent::KeyPress, 0, -1, 0, text );
+ emit keyPressedSignal( &ke );
+ }
+}
+
+void TEWidget::imEndEvent( QIMEvent *e )
+{
+ QString text = QString::null;
+ if ( m_imPreeditLength > 0 ) {
+ text.fill( '\010', m_imPreeditLength );
+ }
+
+ m_imEnd = m_imSelStart = m_imSelEnd = 0;
+ text += e->text();
+ if ( text.length() > 0 ) {
+ QKeyEvent ke( QEvent::KeyPress, 0, -1, 0, text );
+ emit keyPressedSignal( &ke );
+ }
+
+ QPoint tL = contentsRect().topLeft();
+ int tLx = tL.x();
+ int tLy = tL.y();
+
+ QRect repaintRect = QRect( bX+tLx, bY+tLy+font_h*m_imStartLine,
+ contentsRect().width(), contentsRect().height() );
+ m_imStart = 0;
+ m_imPreeditLength = 0;
+
+ m_isIMEdit = m_isIMSel = false;
+ repaint( repaintRect, true );
+}
+
+// Override any Ctrl+<key> accelerator when pressed with the keyboard
+// focus in TEWidget, so that the key will be passed to the terminal instead.
+bool TEWidget::event( QEvent *e )
+{
+ if ( e->type() == QEvent::AccelOverride )
+ {
+ QKeyEvent *ke = static_cast<QKeyEvent *>( e );
+ KKey key( ke );
+ int keyCodeQt = key.keyCodeQt();
+
+ if ( !standalone() && (ke->state() == Qt::ControlButton) )
+ {
+ ke->accept();
+ return true;
+ }
+
+ // Override any of the following accelerators:
+ switch ( keyCodeQt )
+ {
+ case Key_Tab:
+ case Key_Delete:
+ ke->accept();
+ return true;
+ }
+ }
+ return QFrame::event( e );
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Frame */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEWidget::frameChanged()
+{
+ propagateSize();
+ update();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Sound */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEWidget::setBellMode(int mode)
+{
+ m_bellMode=mode;
+}
+
+void TEWidget::Bell(bool visibleSession, QString message)
+{
+ if (bellTimer.isActive())
+ return;
+
+ //minimum delay in milliseconds between each bell event
+ //for the 3 different types of bells.
+ const int BELLSYSTEM_DELAY = 100;
+ const int BELLNOTIFY_DELAY = 500; //longer to avoid horrible noise with several audible system
+ //notifications in close succession
+ const int BELLVISUAL_DELAY = 500; //longer to avoid ugly flickering with several flashes in close
+ //succession
+
+ if (m_bellMode==BELLNONE) return;
+
+ if (m_bellMode==BELLSYSTEM) {
+ bellTimer.start(BELLSYSTEM_DELAY,true);
+ KNotifyClient::beep();
+ } else if (m_bellMode==BELLNOTIFY) {
+ bellTimer.start(BELLNOTIFY_DELAY,true);
+
+ if (visibleSession)
+ KNotifyClient::event(winId(), "BellVisible", message);
+ else
+ KNotifyClient::event(winId(), "BellInvisible", message);
+ } else if (m_bellMode==BELLVISUAL) {
+ bellTimer.start(BELLVISUAL_DELAY,true);
+
+ swapColorTable();
+ QTimer::singleShot(200,this,SLOT(swapColorTable()));
+ }
+}
+
+void TEWidget::swapColorTable()
+{
+ ColorEntry color = color_table[1];
+ color_table[1]=color_table[0];
+ color_table[0]= color;
+ colorsSwapped = !colorsSwapped;
+ update();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Auxiluary */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void TEWidget::clearImage()
+// initialize the image
+// for internal use only
+{
+ // We initialize image[image_size] too. See makeImage()
+ for (int i = 0; i <= image_size; i++)
+ {
+ image[i].c = ' ';
+ image[i].f = cacol(CO_DFT,DEFAULT_FORE_COLOR);
+ image[i].b = cacol(CO_DFT,DEFAULT_BACK_COLOR);
+ image[i].r = DEFAULT_RENDITION;
+ }
+}
+
+// Create Image ///////////////////////////////////////////////////////
+
+void TEWidget::calcGeometry()
+{
+ scrollbar->resize(QApplication::style().pixelMetric(QStyle::PM_ScrollBarExtent),
+ contentsRect().height());
+ switch(scrollLoc)
+ {
+ case SCRNONE :
+ bX = rimX;
+ contentWidth = contentsRect().width() - 2 * rimX;
+ scrollbar->hide();
+ break;
+ case SCRLEFT :
+ bX = rimX+scrollbar->width();
+ contentWidth = contentsRect().width() - 2 * rimX - scrollbar->width();
+ scrollbar->move(contentsRect().topLeft());
+ scrollbar->show();
+ break;
+ case SCRRIGHT:
+ bX = rimX;
+ contentWidth = contentsRect().width() - 2 * rimX - scrollbar->width();
+ scrollbar->move(contentsRect().topRight() - QPoint(scrollbar->width()-1,0));
+ scrollbar->show();
+ break;
+ }
+
+ //FIXME: support 'rounding' styles
+ bY = rimY;
+ contentHeight = contentsRect().height() - 2 * rimY + /* mysterious */ 1;
+
+ if (!isFixedSize)
+ {
+ columns = contentWidth / font_w;
+
+ if (columns<1) {
+ kdDebug(1211) << "TEWidget::calcGeometry: columns=" << columns << endl;
+ columns=1;
+ }
+ lines = contentHeight / font_h;
+ }
+}
+
+void TEWidget::makeImage()
+{
+ calcGeometry();
+ image_size=lines*columns;
+ // We over-commit 1 character so that we can be more relaxed in dealing with
+ // certain boundary conditions: image[image_size] is a valid but unused position
+ image = (ca*) malloc((image_size+1)*sizeof(ca));
+ clearImage();
+}
+
+// calculate the needed size
+void TEWidget::setSize(int cols, int lins)
+{
+ int frw = width() - contentsRect().width();
+ int frh = height() - contentsRect().height();
+ int scw = (scrollLoc==SCRNONE?0:scrollbar->width());
+ m_size = QSize(font_w*cols + 2*rimX + frw + scw, font_h*lins + 2*rimY + frh + /* mysterious */ 1);
+ updateGeometry();
+}
+
+void TEWidget::setFixedSize(int cols, int lins)
+{
+ isFixedSize = true;
+ columns = cols;
+ lines = lins;
+ if (image)
+ {
+ free(image);
+ makeImage();
+ }
+ setSize(cols, lins);
+ QFrame::setFixedSize(m_size);
+}
+
+QSize TEWidget::sizeHint() const
+{
+ return m_size;
+}
+
+void TEWidget::styleChange(QStyle &)
+{
+ propagateSize();
+}
+
+
+/* --------------------------------------------------------------------- */
+/* */
+/* Drag & Drop */
+/* */
+/* --------------------------------------------------------------------- */
+
+void TEWidget::dragEnterEvent(QDragEnterEvent* e)
+{
+ e->accept(QTextDrag::canDecode(e) ||
+ KURLDrag::canDecode(e));
+}
+
+enum dropPopupOptions { paste, cd, cp, ln, mv };
+
+void TEWidget::dropEvent(QDropEvent* event)
+{
+ if (m_drop==0)
+ {
+ m_drop = new KPopupMenu(this);
+ m_drop->insertItem( i18n("Paste"), paste );
+ m_drop->insertSeparator();
+ m_drop->insertItem( "cd", cd );
+ m_drop->insertItem( "cp", cp );
+ m_drop->insertItem( "ln", ln );
+ m_drop->insertItem( "mv", mv );
+ connect(m_drop, SIGNAL(activated(int)), SLOT(drop_menu_activated(int)));
+ };
+ // The current behaviour when url(s) are dropped is
+ // * if there is only ONE url and if it's a LOCAL one, ask for paste or cd/cp/ln/mv
+ // * if there are only LOCAL urls, ask for paste or cp/ln/mv
+ // * in all other cases, just paste
+ // (for non-local ones, or for a list of URLs, 'cd' is nonsense)
+ KURL::List urllist;
+ m_dnd_file_count = 0;
+ dropText = "";
+ bool justPaste = true;
+
+ if(KURLDrag::decode(event, urllist)) {
+ justPaste =false;
+ if (!urllist.isEmpty()) {
+ KURL::List::Iterator it;
+
+ m_drop->setItemEnabled( cd, true );
+ m_drop->setItemEnabled( ln, true );
+
+ for ( it = urllist.begin(); it != urllist.end(); ++it ) {
+ if(m_dnd_file_count++ > 0) {
+ dropText += " ";
+ m_drop->setItemEnabled(cd,false);
+ }
+ KURL url = KIO::NetAccess::mostLocalURL( *it, 0 );
+ QString tmp;
+ if (url.isLocalFile()) {
+ tmp = url.path(); // local URL : remove protocol. This helps "ln" & "cd" and doesn't harm the others
+ } else if ( url.protocol() == QString::fromLatin1( "mailto" ) ) {
+ justPaste = true;
+ break;
+ } else {
+ tmp = url.url();
+ m_drop->setItemEnabled( cd, false );
+ m_drop->setItemEnabled( ln, false );
+ }
+ if (urllist.count()>1)
+ KRun::shellQuote(tmp);
+ dropText += tmp;
+ }
+
+ if (!justPaste) m_drop->popup(mapToGlobal(event->pos()));
+ }
+ }
+ if(justPaste && QTextDrag::decode(event, dropText)) {
+ kdDebug(1211) << "Drop:" << dropText.local8Bit() << "\n";
+ emit sendStringToEmu(dropText.local8Bit());
+ // Paste it
+ }
+}
+
+void TEWidget::doDrag()
+{
+ dragInfo.state = diDragging;
+ dragInfo.dragObject = new QTextDrag(QApplication::clipboard()->text(QClipboard::Selection), this);
+ dragInfo.dragObject->dragCopy();
+ // Don't delete the QTextDrag object. Qt will delete it when it's done with it.
+}
+
+void TEWidget::drop_menu_activated(int item)
+{
+ switch (item)
+ {
+ case paste:
+ if (m_dnd_file_count==1)
+ KRun::shellQuote(dropText);
+ emit sendStringToEmu(dropText.local8Bit());
+ setActiveWindow();
+ break;
+ case cd:
+ emit sendStringToEmu("cd ");
+ struct stat statbuf;
+ if ( ::stat( QFile::encodeName( dropText ), &statbuf ) == 0 )
+ {
+ if ( !S_ISDIR(statbuf.st_mode) )
+ {
+ KURL url;
+ url.setPath( dropText );
+ dropText = url.directory( true, false ); // remove filename
+ }
+ }
+ KRun::shellQuote(dropText);
+ emit sendStringToEmu(dropText.local8Bit());
+ emit sendStringToEmu("\n");
+ setActiveWindow();
+ break;
+ case cp:
+ emit sendStringToEmu("kfmclient copy " );
+ break;
+ case ln:
+ emit sendStringToEmu("ln -s ");
+ break;
+ case mv:
+ emit sendStringToEmu("kfmclient move " );
+ break;
+ }
+ if (item>cd && item<=mv) {
+ if (m_dnd_file_count==1)
+ KRun::shellQuote(dropText);
+ emit sendStringToEmu(dropText.local8Bit());
+ emit sendStringToEmu(" .\n");
+ setActiveWindow();
+ }
+}
+
+uint TEWidget::lineSpacing() const
+{
+ return m_lineSpacing;
+}
+
+void TEWidget::setLineSpacing(uint i)
+{
+ m_lineSpacing = i;
+ setVTFont(font()); // Trigger an update.
+}
+
+#include "TEWidget.moc"
diff --git a/konsole/konsole/TEWidget.h b/konsole/konsole/TEWidget.h
new file mode 100644
index 000000000..bb4d2c610
--- /dev/null
+++ b/konsole/konsole/TEWidget.h
@@ -0,0 +1,335 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef TE_WIDGET_H
+#define TE_WIDGET_H
+
+#include <qbitarray.h>
+#include <qwidget.h>
+#include <qcolor.h>
+#include <qkeycode.h>
+#include <qtimer.h>
+#include <qscrollbar.h>
+
+#include <kpopupmenu.h>
+
+#include "TECommon.h"
+
+
+extern unsigned short vt100_graphics[32];
+
+class Konsole;
+class QLabel;
+class QTimer;
+
+class TEWidget : public QFrame
+// a widget representing attributed text
+{
+ Q_OBJECT
+
+ friend class Konsole;
+public:
+
+ TEWidget(QWidget *parent=0, const char *name=0);
+ virtual ~TEWidget();
+
+ void setBlendColor(const QRgb color) { blend_color = color; }
+
+ void setDefaultBackColor(const QColor& color);
+ QColor getDefaultBackColor();
+
+ const ColorEntry* getColorTable() const;
+ void setColorTable(const ColorEntry table[]);
+
+ void setScrollbarLocation(int loc);
+ int getScrollbarLocation() { return scrollLoc; }
+ enum { SCRNONE=0, SCRLEFT=1, SCRRIGHT=2 };
+
+ void setScroll(int cursor, int lines);
+ void doScroll(int lines);
+
+ bool blinkingCursor() { return hasBlinkingCursor; }
+ void setBlinkingCursor(bool blink);
+
+ void setCtrlDrag(bool enable) { ctrldrag=enable; }
+ bool ctrlDrag() { return ctrldrag; }
+
+ void setCutToBeginningOfLine(bool enable) { cuttobeginningofline=enable; }
+ bool cutToBeginningOfLine() { return cuttobeginningofline; }
+
+ void setLineSpacing(uint);
+ uint lineSpacing() const;
+
+ void emitSelection(bool useXselection,bool appendReturn);
+ void emitText(QString text);
+
+ void setImage(const ca* const newimg, int lines, int columns);
+ void setLineWrapped(QBitArray line_wrapped) { m_line_wrapped=line_wrapped; }
+
+ void setCursorPos(const int curx, const int cury);
+
+ int Lines() { return lines; }
+ int Columns() { return columns; }
+
+ int fontHeight() { return font_h; }
+ int fontWidth() { return font_w; }
+
+ void calcGeometry();
+ void propagateSize();
+ void updateImageSize();
+ void setSize(int cols, int lins);
+ void setFixedSize(int cols, int lins);
+ QSize sizeHint() const;
+
+ void setWordCharacters(QString wc);
+ QString wordCharacters() { return word_characters; }
+
+ void setBellMode(int mode);
+ int bellMode() { return m_bellMode; }
+ enum { BELLSYSTEM=0, BELLNOTIFY=1, BELLVISUAL=2, BELLNONE=3 };
+ void Bell(bool visibleSession, QString message);
+
+ void setSelection(const QString &t);
+
+ /**
+ * Reimplemented. Has no effect. Use setVTFont() to change the font
+ * used to draw characters in the display.
+ */
+ virtual void setFont(const QFont &);
+
+ /** Returns the font used to draw characters in the display */
+ QFont getVTFont() { return font(); }
+
+ /**
+ * Sets the font used to draw the display. Has no effect if @p font
+ * is larger than the size of the display itself.
+ */
+ void setVTFont(const QFont& font);
+
+ void setMouseMarks(bool on);
+ static void setAntialias( bool enable ) { s_antialias = enable; }
+ static bool antialias() { return s_antialias; }
+ static void setStandalone( bool standalone ) { s_standalone = standalone; }
+ static bool standalone() { return s_standalone; }
+
+ void setTerminalSizeHint(bool on) { terminalSizeHint=on; }
+ bool isTerminalSizeHint() { return terminalSizeHint; }
+ void setTerminalSizeStartup(bool on) { terminalSizeStartup=on; }
+
+ void setBidiEnabled(bool set) { bidiEnabled=set; }
+ bool isBidiEnabled() { return bidiEnabled; }
+
+ void print(QPainter &paint, bool friendly, bool exact);
+
+ void setRim(int rim) { rimX=rim; rimY=rim; }
+
+public slots:
+
+ void setSelectionEnd();
+ void copyClipboard();
+ void pasteClipboard();
+ void pasteSelection();
+ void onClearSelection();
+
+signals:
+
+ void keyPressedSignal(QKeyEvent *e);
+ void mouseSignal(int cb, int cx, int cy);
+ void changedFontMetricSignal(int height, int width);
+ void changedContentSizeSignal(int height, int width);
+ void changedHistoryCursor(int value);
+ void configureRequest( TEWidget*, int state, int x, int y );
+
+ void copySelectionSignal();
+ void clearSelectionSignal();
+ void beginSelectionSignal( const int x, const int y, const bool columnmode );
+ void extendSelectionSignal( const int x, const int y );
+ void endSelectionSignal(const bool preserve_line_breaks);
+ void isBusySelecting(bool);
+ void testIsSelected(const int x, const int y, bool &selected /* result */);
+ void sendStringToEmu(const char*);
+
+protected:
+
+ virtual void styleChange( QStyle& );
+
+ bool eventFilter( QObject *, QEvent * );
+ bool event( QEvent * );
+
+ void drawTextFixed(QPainter &paint, int x, int y,
+ QString& str, const ca *attr);
+
+ void drawAttrStr(QPainter &paint, QRect rect,
+ QString& str, const ca *attr, bool pm, bool clear);
+ void paintEvent( QPaintEvent * );
+
+ void paintContents(QPainter &paint, const QRect &rect, bool pm=false);
+
+ void resizeEvent(QResizeEvent*);
+
+ void fontChange(const QFont &font);
+ void frameChanged();
+
+ void mouseDoubleClickEvent(QMouseEvent* ev);
+ void mousePressEvent( QMouseEvent* );
+ void mouseReleaseEvent( QMouseEvent* );
+ void mouseMoveEvent( QMouseEvent* );
+ void extendSelection( QPoint pos );
+ void wheelEvent( QWheelEvent* );
+
+ void focusInEvent( QFocusEvent * );
+ void focusOutEvent( QFocusEvent * );
+ bool focusNextPrevChild( bool next );
+ // Dnd
+ void dragEnterEvent(QDragEnterEvent* event);
+ void dropEvent(QDropEvent* event);
+ void doDrag();
+ enum DragState { diNone, diPending, diDragging };
+
+ struct _dragInfo {
+ DragState state;
+ QPoint start;
+ QTextDrag *dragObject;
+ } dragInfo;
+
+ virtual int charClass(UINT16) const;
+
+ void clearImage();
+
+ void mouseTripleClickEvent(QMouseEvent* ev);
+
+ void imStartEvent( QIMEvent *e );
+ void imComposeEvent( QIMEvent *e );
+ void imEndEvent( QIMEvent *e );
+
+protected slots:
+
+ void scrollChanged(int value);
+ void blinkEvent();
+ void blinkCursorEvent();
+
+private:
+
+// QChar (*fontMap)(QChar); // possible vt100 font extension
+
+ bool fixed_font; // has fixed pitch
+ int font_h; // height
+ int font_w; // width
+ int font_a; // ascend
+
+ int bX; // offset
+ int bY; // offset
+
+ int lines;
+ int columns;
+ int contentHeight;
+ int contentWidth;
+ ca *image; // [lines][columns]
+ int image_size;
+ QBitArray m_line_wrapped;
+
+ ColorEntry color_table[TABLE_COLORS];
+ QColor defaultBgColor;
+
+ bool resizing;
+ bool terminalSizeHint,terminalSizeStartup;
+ bool bidiEnabled;
+ bool mouse_marks;
+
+ void makeImage();
+
+ QPoint iPntSel; // initial selection point
+ QPoint pntSel; // current selection point
+ QPoint tripleSelBegin; // help avoid flicker
+ int actSel; // selection state
+ bool word_selection_mode;
+ bool line_selection_mode;
+ bool preserve_line_breaks;
+ bool column_selection_mode;
+
+ QClipboard* cb;
+ QScrollBar* scrollbar;
+ int scrollLoc;
+ QString word_characters;
+ QTimer bellTimer; //used to rate-limit bell events. started when a bell event occurs,
+ //and prevents further bell events until it stops
+ int m_bellMode;
+
+ bool blinking; // hide text in paintEvent
+ bool hasBlinker; // has characters to blink
+ bool cursorBlinking; // hide cursor in paintEvent
+ bool hasBlinkingCursor; // has blinking cursor enabled
+ bool ctrldrag; // require Ctrl key for drag
+ bool cuttobeginningofline; // triple click only selects forward
+ bool isBlinkEvent; // paintEvent due to blinking.
+ bool isPrinting; // Paint job is intended for printer
+ bool printerFriendly; // paint printer friendly, save ink
+ bool printerBold; // Use a bold font instead of overstrike for bold
+ bool isFixedSize; //Columns / lines are locked.
+ QTimer* blinkT; // active when hasBlinker
+ QTimer* blinkCursorT; // active when hasBlinkingCursor
+
+ KPopupMenu* m_drop;
+ QString dropText;
+ int m_dnd_file_count;
+
+ bool possibleTripleClick; // is set in mouseDoubleClickEvent and deleted
+ // after QApplication::doubleClickInterval() delay
+
+ static bool s_antialias; // do we antialias or not
+ static bool s_standalone; // are we part of a standalone konsole?
+
+ QFrame *mResizeWidget;
+ QLabel *mResizeLabel;
+ QTimer *mResizeTimer;
+
+ uint m_lineSpacing;
+
+ QRect cursorRect; //for quick changing of cursor
+
+ QPoint configureRequestPoint; // remember right mouse button click position
+ bool colorsSwapped; // true during visual bell
+
+ // the rim should normally be 1, 0 only when running in full screen mode.
+ int rimX; // left/right rim width
+ int rimY; // top/bottom rim high
+ QSize m_size;
+
+ QString m_imPreeditText;
+ int m_imPreeditLength;
+ int m_imStart;
+ int m_imStartLine;
+ int m_imEnd;
+ int m_imSelStart;
+ int m_imSelEnd;
+ int m_cursorLine;
+ int m_cursorCol;
+ bool m_isIMEdit;
+ bool m_isIMSel;
+
+ QRgb blend_color;
+
+private slots:
+ void drop_menu_activated(int item);
+ void swapColorTable();
+ void tripleClickTimeout(); // resets possibleTripleClick
+};
+
+#endif // TE_WIDGET_H
diff --git a/konsole/konsole/TEmuVt102.cpp b/konsole/konsole/TEmuVt102.cpp
new file mode 100644
index 000000000..47207de34
--- /dev/null
+++ b/konsole/konsole/TEmuVt102.cpp
@@ -0,0 +1,1430 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+/*! \class TEmuVt102
+
+ \brief Actual Emulation for Konsole
+
+ \sa TEWidget \sa TEScreen
+*/
+#include "config.h"
+
+// this allows konsole to be compiled without XKB and XTEST extensions
+// even though it might be available on a particular system.
+#if defined(AVOID_XKB)
+#undef HAVE_XKB
+#endif
+
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include "TEmuVt102.h"
+#include "TEWidget.h"
+#include "TEScreen.h"
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <assert.h>
+
+#include "TEmuVt102.moc"
+
+#include <kdebug.h>
+
+/* VT102 Terminal Emulation
+
+ This class puts together the screens, the pty and the widget to a
+ complete terminal emulation. Beside combining it's componentes, it
+ handles the emulations's protocol.
+
+ This module consists of the following sections:
+
+ - Constructor/Destructor
+ - Incoming Bytes Event pipeline
+ - Outgoing Bytes
+ - Mouse Events
+ - Keyboard Events
+ - Modes and Charset State
+ - Diagnostics
+*/
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Constructor / Destructor */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*
+ Nothing really intesting happens here.
+*/
+
+/*!
+*/
+
+TEmuVt102::TEmuVt102(TEWidget* gui) : TEmulation(gui)
+{
+ //kdDebug(1211)<<"TEmuVt102 ctor() connecting"<<endl;
+ QObject::connect(gui,SIGNAL(mouseSignal(int,int,int)),
+ this,SLOT(onMouse(int,int,int)));
+ QObject::connect(gui, SIGNAL(sendStringToEmu(const char*)),
+ this, SLOT(sendString(const char*)));
+ //kdDebug(1211)<<"TEmuVt102 ctor() initToken..."<<endl;
+ initTokenizer();
+ //kdDebug(1211)<<"TEmuVt102 ctor() reset()"<<endl;
+ reset();
+ //kdDebug(1211)<<"TEmuVt102 ctor() ctor done"<<endl;
+}
+
+/*!
+*/
+
+void TEmuVt102::changeGUI(TEWidget* newgui)
+{
+ if (static_cast<TEWidget *>( gui )==newgui) return;
+
+ if ( gui ) {
+ QObject::disconnect(gui,SIGNAL(mouseSignal(int,int,int)),
+ this,SLOT(onMouse(int,int,int)));
+ QObject::disconnect(gui, SIGNAL(sendStringToEmu(const char*)),
+ this, SLOT(sendString(const char*)));
+ }
+ TEmulation::changeGUI(newgui);
+ QObject::connect(gui,SIGNAL(mouseSignal(int,int,int)),
+ this,SLOT(onMouse(int,int,int)));
+ QObject::connect(gui, SIGNAL(sendStringToEmu(const char*)),
+ this, SLOT(sendString(const char*)));
+}
+
+/*!
+*/
+
+TEmuVt102::~TEmuVt102()
+{
+}
+
+/*!
+*/
+
+void TEmuVt102::clearEntireScreen()
+{
+ scr->clearEntireScreen();
+}
+
+void TEmuVt102::reset()
+{
+ //kdDebug(1211)<<"TEmuVt102::reset() resetToken()"<<endl;
+ resetToken();
+ //kdDebug(1211)<<"TEmuVt102::reset() resetModes()"<<endl;
+ resetModes();
+ //kdDebug(1211)<<"TEmuVt102::reset() resetCharSet()"<<endl;
+ resetCharset(0);
+ //kdDebug(1211)<<"TEmuVt102::reset() reset screen0()"<<endl;
+ screen[0]->reset();
+ //kdDebug(1211)<<"TEmuVt102::reset() resetCharSet()"<<endl;
+ resetCharset(1);
+ //kdDebug(1211)<<"TEmuVt102::reset() reset screen 1"<<endl;
+ screen[1]->reset();
+ //kdDebug(1211)<<"TEmuVt102::reset() setCodec()"<<endl;
+ setCodec(0);
+ //kdDebug(1211)<<"TEmuVt102::reset() done"<<endl;
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* 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
+ - CSI_PE - 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)
+
+#define TY_CSI_PG(A ) TY_CONSTR(9,A,0)
+
+#define TY_CSI_PE(A ) TY_CONSTR(10,A,0)
+
+// Tokenizer --------------------------------------------------------------- --
+
+/* The tokenizers state
+
+ The state is represented by the buffer (pbuf, ppos),
+ and accompanied by decoded arguments kept in (argv,argc).
+ Note that they are kept internal in the tokenizer.
+*/
+
+void TEmuVt102::resetToken()
+{
+ ppos = 0; argc = 0; argv[0] = 0; argv[1] = 0;
+}
+
+void TEmuVt102::addDigit(int dig)
+{
+ argv[argc] = 10*argv[argc] + dig;
+}
+
+void TEmuVt102::addArgument()
+{
+ argc = QMIN(argc+1,MAXARGS-1);
+ argv[argc] = 0;
+}
+
+void TEmuVt102::pushToToken(int cc)
+{
+ pbuf[ppos] = cc;
+ ppos = QMIN(ppos+1,MAXPBUF-1);
+}
+
+// Character Classes used while decoding
+
+#define CTL 1
+#define CHR 2
+#define CPN 4
+#define DIG 8
+#define SCS 16
+#define GRP 32
+#define CPS 64
+
+void TEmuVt102::initTokenizer()
+{ int i; UINT8* s;
+ for(i = 0; i < 256; i++) tbl[ i] = 0;
+ for(i = 0; i < 32; i++) tbl[ i] |= CTL;
+ for(i = 32; i < 256; i++) tbl[ i] |= CHR;
+ for(s = (UINT8*)"@ABCDGHILMPSTXZcdfry"; *s; s++) tbl[*s] |= CPN;
+// resize = \e[8;<row>;<col>t
+ for(s = (UINT8*)"t"; *s; s++) tbl[*s] |= CPS;
+ 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] != '?' && s[2] != '!' && s[2] != '>' && cc < 256 && (tbl[ cc ] & (C)) == (C))
+#define epp( ) (p >= 3 && s[2] == '?' )
+#define epe( ) (p >= 3 && s[2] == '!' )
+#define egt( ) (p >= 3 && s[2] == '>' )
+#define Xpe (ppos>=2 && pbuf[1] == ']' )
+#define Xte (Xpe && cc == 7 )
+#define ces(C) ( cc < 256 && (tbl[ cc ] & (C)) == (C) && !Xte)
+
+#define ESC 27
+#define CNTL(c) ((c)-'@')
+
+// process an incoming unicode character
+
+void TEmuVt102::onRcvChar(int cc)
+{ int i;
+ if (cc == 127) return; //VT100: ignore.
+
+ if (ces( CTL))
+ { // DEC HACK ALERT! Control Characters are allowed *within* esc sequences in VT100
+ // This means, they do neither a resetToken nor a pushToToken. Some of them, do
+ // of course. Guess this originates from a weakly layered handling of the X-on
+ // X-off protocol, which comes really below this level.
+ if (cc == CNTL('X') || cc == CNTL('Z') || cc == ESC) resetToken(); //VT100: CAN or SUB
+ if (cc != ESC) { tau( TY_CTL(cc+'@' ), 0, 0); return; }
+ }
+
+ pushToToken(cc); // advance the state
+
+ int* s = pbuf;
+ int p = ppos;
+
+ if (getMode(MODE_Ansi)) // decide on proper action
+ {
+ if (lec(1,0,ESC)) { return; }
+ if (lec(1,0,ESC+128)) { s[0] = ESC; onRcvChar('['); 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 (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 (eps( CPN)) { tau( TY_CSI_PN(cc), argv[0],argv[1]); resetToken(); return; }
+
+// resize = \e[8;<row>;<col>t
+ if (eps( CPS)) { tau( TY_CSI_PS(cc, argv[0]), argv[1], argv[2]); resetToken(); return; }
+
+ if (epe( )) { tau( TY_CSI_PE(cc), 0, 0); 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 if(egt( )) { tau( TY_CSI_PG(cc ), 0, 0); } // spec. case for ESC]>0c or ESC]>c
+ else if (cc == 'm' && argc - i >= 4 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 2)
+ { // ESC[ ... 48;2;<red>;<green>;<blue> ... m -or- ESC[ ... 38;2;<red>;<green>;<blue> ... m
+ i += 2;
+ tau( TY_CSI_PS(cc, argv[i-2]), CO_RGB, (argv[i] << 16) | (argv[i+1] << 8) | argv[i+2]);
+ i += 2;
+ }
+ else if (cc == 'm' && argc - i >= 2 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 5)
+ { // ESC[ ... 48;5;<index> ... m -or- ESC[ ... 38;5;<index> ... m
+ i += 2;
+ tau( TY_CSI_PS(cc, argv[i-2]), CO_256, argv[i]);
+ }
+ else { tau( TY_CSI_PS(cc,argv[i]), 0, 0); }
+ resetToken();
+ }
+ else // mode VT52
+ {
+ if (lec(1,0,ESC)) return;
+ if (les(1,0,CHR)) { tau( TY_CHR( ), s[0], 0); resetToken(); return; }
+ if (lec(2,1,'Y')) return;
+ if (lec(3,1,'Y')) return;
+ if (p < 4) { tau( TY_VT52(s[1] ), 0, 0); resetToken(); return; }
+ tau( TY_VT52(s[1] ), s[2],s[3]); resetToken(); return;
+ }
+}
+
+void TEmuVt102::XtermHack()
+{ int i,arg = 0;
+ for (i = 2; i < ppos && '0'<=pbuf[i] && pbuf[i]<'9' ; i++)
+ arg = 10*arg + (pbuf[i]-'0');
+ if (pbuf[i] != ';') { ReportErrorToken(); return; }
+ QChar *str = new QChar[ppos-i-2];
+ for (int j = 0; j < ppos-i-2; j++) str[j] = pbuf[i+1+j];
+ QString unistr(str,ppos-i-2);
+ // arg == 1 doesn't change the title. In XTerm it only changes the icon name
+ // (btw: arg=0 changes title and icon, arg=1 only icon, arg=2 only title
+ emit changeTitle(arg,unistr);
+ delete [] str;
+}
+
+// Interpreting Codes ---------------------------------------------------------
+
+/*
+ Now that the incoming character stream is properly tokenized,
+ meaning is assigned to them. These are either operations of
+ the current screen, or of the emulation class itself.
+
+ The token to be interpreteted comes in as a machine word
+ possibly accompanied by two parameters.
+
+ Likewise, the operations assigned to, come with up to two
+ arguments. One could consider to make up a proper table
+ from the function below.
+
+ The technical reference manual provides more informations
+ about this mapping.
+*/
+
+void TEmuVt102::tau( int token, int p, int q )
+{
+#if 0
+int N = (token>>0)&0xff;
+int A = (token>>8)&0xff;
+switch( N )
+{
+ case 0: printf("%c", (p < 128) ? p : '?');
+ break;
+ case 1: if (A == 'J') printf("\r");
+ else if (A == 'M') printf("\n");
+ else printf("CTL-%c ", (token>>8)&0xff);
+ break;
+ case 2: printf("ESC-%c ", (token>>8)&0xff);
+ break;
+ case 3: printf("ESC_CS-%c-%c ", (token>>8)&0xff, (token>>16)&0xff);
+ break;
+ case 4: printf("ESC_DE-%c ", (token>>8)&0xff);
+ break;
+ case 5: printf("CSI-PS-%c-%d", (token>>8)&0xff, (token>>16)&0xff );
+ break;
+ case 6: printf("CSI-PN-%c [%d]", (token>>8)&0xff, p);
+ break;
+ case 7: printf("CSI-PR-%c-%d", (token>>8)&0xff, (token>>16)&0xff );
+ break;
+ case 8: printf("VT52-%c", (token>>8)&0xff);
+ break;
+ case 9: printf("CSI-PG-%c", (token>>8)&0xff);
+ break;
+ case 10: printf("CSI-PE-%c", (token>>8)&0xff);
+ break;
+}
+#endif
+
+ 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' ) : emit notifySessionState(NOTIFYBELL);
+ 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;
+
+// resize = \e[8;<row>;<col>t
+ case TY_CSI_PS('t', 8) : changeColLin( q /* col */, p /* lin */ ); break;
+
+// change tab text color : \e[28;<color>t color: 0-16,777,215
+ case TY_CSI_PS('t', 28) : emit changeTabTextColor ( p ); 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('s', 0) : saveCursor ( ); break;
+ case TY_CSI_PS('u', 0) : restoreCursor ( ); 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 (CO_SYS, 0); break;
+ case TY_CSI_PS('m', 31) : scr->setForeColor (CO_SYS, 1); break;
+ case TY_CSI_PS('m', 32) : scr->setForeColor (CO_SYS, 2); break;
+ case TY_CSI_PS('m', 33) : scr->setForeColor (CO_SYS, 3); break;
+ case TY_CSI_PS('m', 34) : scr->setForeColor (CO_SYS, 4); break;
+ case TY_CSI_PS('m', 35) : scr->setForeColor (CO_SYS, 5); break;
+ case TY_CSI_PS('m', 36) : scr->setForeColor (CO_SYS, 6); break;
+ case TY_CSI_PS('m', 37) : scr->setForeColor (CO_SYS, 7); break;
+
+ case TY_CSI_PS('m', 38) : scr->setForeColor (p, q); break;
+
+ case TY_CSI_PS('m', 39) : scr->setForeColor (CO_DFT, 0); break;
+
+ case TY_CSI_PS('m', 40) : scr->setBackColor (CO_SYS, 0); break;
+ case TY_CSI_PS('m', 41) : scr->setBackColor (CO_SYS, 1); break;
+ case TY_CSI_PS('m', 42) : scr->setBackColor (CO_SYS, 2); break;
+ case TY_CSI_PS('m', 43) : scr->setBackColor (CO_SYS, 3); break;
+ case TY_CSI_PS('m', 44) : scr->setBackColor (CO_SYS, 4); break;
+ case TY_CSI_PS('m', 45) : scr->setBackColor (CO_SYS, 5); break;
+ case TY_CSI_PS('m', 46) : scr->setBackColor (CO_SYS, 6); break;
+ case TY_CSI_PS('m', 47) : scr->setBackColor (CO_SYS, 7); break;
+
+ case TY_CSI_PS('m', 48) : scr->setBackColor (p, q); break;
+
+ case TY_CSI_PS('m', 49) : scr->setBackColor (CO_DFT, 1); break;
+
+ case TY_CSI_PS('m', 90) : scr->setForeColor (CO_SYS, 8); break;
+ case TY_CSI_PS('m', 91) : scr->setForeColor (CO_SYS, 9); break;
+ case TY_CSI_PS('m', 92) : scr->setForeColor (CO_SYS, 10); break;
+ case TY_CSI_PS('m', 93) : scr->setForeColor (CO_SYS, 11); break;
+ case TY_CSI_PS('m', 94) : scr->setForeColor (CO_SYS, 12); break;
+ case TY_CSI_PS('m', 95) : scr->setForeColor (CO_SYS, 13); break;
+ case TY_CSI_PS('m', 96) : scr->setForeColor (CO_SYS, 14); break;
+ case TY_CSI_PS('m', 97) : scr->setForeColor (CO_SYS, 15); break;
+
+ case TY_CSI_PS('m', 100) : scr->setBackColor (CO_SYS, 8); break;
+ case TY_CSI_PS('m', 101) : scr->setBackColor (CO_SYS, 9); break;
+ case TY_CSI_PS('m', 102) : scr->setBackColor (CO_SYS, 10); break;
+ case TY_CSI_PS('m', 103) : scr->setBackColor (CO_SYS, 11); break;
+ case TY_CSI_PS('m', 104) : scr->setBackColor (CO_SYS, 12); break;
+ case TY_CSI_PS('m', 105) : scr->setBackColor (CO_SYS, 13); break;
+ case TY_CSI_PS('m', 106) : scr->setBackColor (CO_SYS, 14); break;
+ case TY_CSI_PS('m', 107) : scr->setBackColor (CO_SYS, 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('I' ) : scr->Tabulate (p ); break;
+ 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('S' ) : scr->scrollUp (p ); break;
+ case TY_CSI_PN('T' ) : scr->scrollDown (p ); break;
+ case TY_CSI_PN('X' ) : scr->eraseChars (p ); break;
+ case TY_CSI_PN('Z' ) : scr->backTabulate (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' ) : 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('s', 8) : /* IGNORED: autorepeat on */ break; //VT100
+ case TY_CSI_PR('r', 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('s', 9) : /* IGNORED: interlace */ break; //VT100
+ case TY_CSI_PR('r', 9) : /* IGNORED: interlace */ break; //VT100
+
+ case TY_CSI_PR('h', 12) : /* IGNORED: Cursor blink */ break; //att610
+ case TY_CSI_PR('l', 12) : /* IGNORED: Cursor blink */ break; //att610
+ case TY_CSI_PR('s', 12) : /* IGNORED: Cursor blink */ break; //att610
+ case TY_CSI_PR('r', 12) : /* IGNORED: Cursor blink */ break; //att610
+
+ 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('s', 25) : saveMode (MODE_Cursor ); break; //VT100
+ case TY_CSI_PR('r', 25) : restoreMode (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('s', 47) : saveMode (MODE_AppScreen); break; //XTERM
+ case TY_CSI_PR('r', 47) : restoreMode (MODE_AppScreen); break; //XTERM
+
+ case TY_CSI_PR('h', 67) : /* IGNORED: DECBKM */ break; //XTERM
+ case TY_CSI_PR('l', 67) : /* IGNORED: DECBKM */ break; //XTERM
+ case TY_CSI_PR('s', 67) : /* IGNORED: DECBKM */ break; //XTERM
+ case TY_CSI_PR('r', 67) : /* IGNORED: DECBKM */ break; //XTERM
+
+ // XTerm defines the following modes:
+ // SET_VT200_MOUSE 1000
+ // SET_VT200_HIGHLIGHT_MOUSE 1001
+ // SET_BTN_EVENT_MOUSE 1002
+ // SET_ANY_EVENT_MOUSE 1003
+ //
+ // FIXME: Modes 1000,1002 and 1003 have subtle differences which we don't
+ // support yet, we treat them all the same.
+
+ 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) : resetMode (MODE_Mouse1000); 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', 1002) : setMode (MODE_Mouse1000); break; //XTERM
+ case TY_CSI_PR('l', 1002) : resetMode (MODE_Mouse1000); break; //XTERM
+ case TY_CSI_PR('s', 1002) : saveMode (MODE_Mouse1000); break; //XTERM
+ case TY_CSI_PR('r', 1002) : restoreMode (MODE_Mouse1000); break; //XTERM
+
+ case TY_CSI_PR('h', 1003) : setMode (MODE_Mouse1000); break; //XTERM
+ case TY_CSI_PR('l', 1003) : resetMode (MODE_Mouse1000); break; //XTERM
+ case TY_CSI_PR('s', 1003) : saveMode (MODE_Mouse1000); break; //XTERM
+ case TY_CSI_PR('r', 1003) : restoreMode (MODE_Mouse1000); break; //XTERM
+
+ case TY_CSI_PR('h', 1047) : setMode (MODE_AppScreen); break; //XTERM
+ case TY_CSI_PR('l', 1047) : screen[1]->clearEntireScreen(); resetMode(MODE_AppScreen); break; //XTERM
+ case TY_CSI_PR('s', 1047) : saveMode (MODE_AppScreen); break; //XTERM
+ case TY_CSI_PR('r', 1047) : restoreMode (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
+ case TY_CSI_PR('s', 1048) : saveCursor ( ); break; //XTERM
+ case TY_CSI_PR('r', 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) : saveCursor(); screen[1]->clearEntireScreen(); setMode(MODE_AppScreen); break; //XTERM
+ case TY_CSI_PR('l', 1049) : resetMode(MODE_AppScreen); restoreCursor(); break; //XTERM
+
+ //FIXME: weird DEC reset sequence
+ case TY_CSI_PE('p' ) : /* IGNORED: reset ( ) */ break;
+
+ //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
+
+ case TY_CSI_PG('c' ) : reportSecondaryAttributes( ); break; //VT100
+
+ default : ReportErrorToken(); break;
+ };
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Terminal to Host protocol */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*
+ Outgoing bytes originate from several sources:
+
+ - Replies to Enquieries.
+ - Mouse Events
+ - Keyboard Events
+*/
+
+/*!
+*/
+
+void TEmuVt102::sendString(const char* s)
+{
+ emit sndBlock(s,strlen(s));
+}
+
+// Replies ----------------------------------------------------------------- --
+
+// This section copes with replies send as response to an enquiery control code.
+
+/*!
+*/
+
+void TEmuVt102::reportCursorPosition()
+{ char tmp[20];
+ sprintf(tmp,"\033[%d;%dR",scr->getCursorY()+1,scr->getCursorX()+1);
+ sendString(tmp);
+}
+
+/*
+ What follows here is rather obsolete and faked stuff.
+ The correspondent enquieries are neverthenless issued.
+*/
+
+/*!
+*/
+
+void TEmuVt102::reportTerminalType()
+{
+ // Primary device attribute response (Request was: ^[[0c or ^[[c (from TT321 Users Guide))
+ // VT220: ^[[?63;1;2;3;6;7;8c (list deps on emul. capabilities)
+ // VT100: ^[[?1;2c
+ // VT101: ^[[?1;0c
+ // VT102: ^[[?6v
+ if (getMode(MODE_Ansi))
+ sendString("\033[?1;2c"); // I'm a VT100
+ else
+ sendString("\033/Z"); // I'm a VT52
+}
+
+void TEmuVt102::reportSecondaryAttributes()
+{
+ // Seconday device attribute response (Request was: ^[[>0c or ^[[>c)
+ if (getMode(MODE_Ansi))
+ sendString("\033[>0;115;0c"); // Why 115? ;)
+ else
+ sendString("\033/Z"); // FIXME I don't think VT52 knows about it but kept for
+ // konsoles backward compatibility.
+}
+
+void TEmuVt102::reportTerminalParms(int p)
+// DECREPTPARM
+{ char tmp[100];
+ sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true.
+ sendString(tmp);
+}
+
+/*!
+*/
+
+void TEmuVt102::reportStatus()
+{
+ sendString("\033[0n"); //VT100. Device status report. 0 = Ready.
+}
+
+/*!
+*/
+
+#define ANSWER_BACK "" // This is really obsolete VT100 stuff.
+
+void TEmuVt102::reportAnswerBack()
+{
+ sendString(ANSWER_BACK);
+}
+
+// Mouse Handling ---------------------------------------------------------- --
+
+/*!
+ Mouse clicks are possibly reported to the client
+ application if it has issued interest in them.
+ They are normally consumed by the widget for copy
+ and paste, but may be propagated from the widget
+ when gui->setMouseMarks is set via setMode(MODE_Mouse1000).
+
+ `x',`y' are 1-based.
+ `ev' (event) indicates the button pressed (0-2)
+ or a general mouse release (3).
+*/
+
+void TEmuVt102::onMouse( int cb, int cx, int cy )
+{ char tmp[20];
+ if (!connected || cx<1 || cy<1) return;
+ // normal buttons are passed as 0x20 + button,
+ // mouse wheel (buttons 4,5) as 0x5c + button
+ if (cb >= 4) cb += 0x3c;
+ sprintf(tmp,"\033[M%c%c%c",cb+0x20,cx+0x20,cy+0x20);
+ sendString(tmp);
+}
+
+// Keyboard Handling ------------------------------------------------------- --
+
+#if defined(HAVE_XKB)
+static void scrolllock_set_off();
+static void scrolllock_set_on();
+#endif
+
+void TEmuVt102::scrollLock(const bool lock)
+{
+ if (lock)
+ {
+ holdScreen = true;
+ emit lockPty(true);
+ }
+ else
+ {
+ holdScreen = false;
+ emit lockPty(false);
+ }
+#if defined(HAVE_XKB)
+ if (holdScreen)
+ scrolllock_set_on();
+ else
+ scrolllock_set_off();
+#endif
+}
+
+void TEmuVt102::onScrollLock()
+{
+ bool switchlock = !holdScreen;
+ scrollLock(switchlock);
+}
+
+#define encodeMode(M,B) BITS(B,getMode(M))
+#define encodeStat(M,B) BITS(B,((ev->state() & (M)) == (M)))
+
+/*
+ Keyboard event handling has been simplified somewhat by pushing
+ the complications towards a configuration file [see KeyTrans class].
+*/
+
+void TEmuVt102::onKeyPress( QKeyEvent* ev )
+{
+ if (!listenToKeyPress) return; // someone else gets the keys
+ emit notifySessionState(NOTIFYNORMAL);
+
+//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);
+
+ // lookup in keyboard translation table ...
+ int cmd = CMD_none;
+ const char* txt;
+ int len;
+ bool metaspecified;
+ if (keytrans->findEntry(ev->key(), encodeMode(MODE_NewLine , BITS_NewLine ) + // OLD,
+ encodeMode(MODE_Ansi , BITS_Ansi ) + // OBSOLETE,
+ encodeMode(MODE_AppCuKeys, BITS_AppCuKeys ) + // VT100 stuff
+ encodeMode(MODE_AppScreen, BITS_AppScreen ) + // VT100 stuff
+ encodeStat(ControlButton , BITS_Control ) +
+ encodeStat(ShiftButton , BITS_Shift ) +
+ encodeStat(AltButton , BITS_Alt ),
+ &cmd, &txt, &len, &metaspecified ))
+//printf("cmd: %d, %s, %d\n",cmd,txt,len);
+ if (connected)
+ {
+ switch(cmd) // ... and execute if found.
+ {
+ 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_scrollLock : onScrollLock( ); return;
+ }
+ }
+ if (holdScreen)
+ {
+ switch(ev->key())
+ {
+ case Key_Down : gui->doScroll(+1); return;
+ case Key_Up : gui->doScroll(-1); return;
+ case Key_PageUp : gui->doScroll(-gui->Lines()/2); return;
+ case Key_PageDown : gui->doScroll(gui->Lines()/2); return;
+ }
+ }
+
+ // revert to non-history when typing
+ if (scr->getHistCursor() != scr->getHistLines() && (!ev->text().isEmpty()
+ || ev->key()==Key_Down || ev->key()==Key_Up || ev->key()==Key_Left || ev->key()==Key_Right
+ || ev->key()==Key_PageUp || ev->key()==Key_PageDown))
+ scr->setHistCursor(scr->getHistLines());
+
+ if (cmd==CMD_send) {
+ if ((ev->state() & AltButton) && !metaspecified ) sendString("\033");
+ emit sndBlock(txt,len);
+ return;
+ }
+
+ // fall back handling
+ if (!ev->text().isEmpty())
+ {
+ if (ev->state() & AltButton) sendString("\033"); // ESC, this is the ALT prefix
+ QCString s = m_codec->fromUnicode(ev->text()); // encode for application
+ // FIXME: In Qt 2, QKeyEvent::text() would return "\003" for Ctrl-C etc.
+ // while in Qt 3 it returns the actual key ("c" or "C") which caused
+ // the ControlButton to be ignored. This hack seems to work for
+ // latin1 locales at least. Please anyone find a clean solution (malte)
+ if (ev->state() & ControlButton)
+ s.fill(ev->ascii(), 1);
+ emit sndBlock(s.data(),s.length()); // we may well have s.length() > 1
+ return;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* VT100 Charsets */
+/* */
+/* ------------------------------------------------------------------------- */
+
+// Character Set Conversion ------------------------------------------------ --
+
+/*
+ The processing contains a VT100 specific code translation layer.
+ It's still in use and mainly responsible for the line drawing graphics.
+
+ These and some other glyphs are assigned to codes (0x5f-0xfe)
+ normally occupied by the latin letters. Since this codes also
+ appear within control sequences, the extra code conversion
+ does not permute with the tokenizer and is placed behind it
+ in the pipeline. It only applies to tokens, which represent
+ plain characters.
+
+ This conversion it eventually continued in TEWidget.C, since
+ it might involve VT100 enhanced fonts, which have these
+ particular glyphs allocated in (0x00-0x1f) in their code page.
+*/
+
+#define CHARSET charset[scr==screen[1]]
+
+// Apply current character map.
+
+unsigned short TEmuVt102::applyCharset(unsigned short c)
+{
+ if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f];
+ if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete
+ return c;
+}
+
+/*
+ "Charset" related part of the emulation state.
+ This configures the VT100 charset filter.
+
+ While most operation work on the current screen,
+ the following two are different.
+*/
+
+void TEmuVt102::resetCharset(int scrno)
+{
+ charset[scrno].cu_cs = 0;
+ strncpy(charset[scrno].charset,"BBBB",4);
+ charset[scrno].sa_graphic = false;
+ charset[scrno].sa_pound = false;
+ charset[scrno].graphic = false;
+ charset[scrno].pound = false;
+}
+
+/*!
+*/
+
+void TEmuVt102::setCharset(int n, int cs) // on both screens.
+{
+ charset[0].charset[n&3] = cs; useCharset(charset[0].cu_cs);
+ charset[1].charset[n&3] = cs; useCharset(charset[1].cu_cs);
+}
+
+/*!
+*/
+
+void TEmuVt102::setAndUseCharset(int n, int cs)
+{
+ CHARSET.charset[n&3] = cs;
+ useCharset(n&3);
+}
+
+/*!
+*/
+
+void TEmuVt102::useCharset(int n)
+{
+ CHARSET.cu_cs = n&3;
+ CHARSET.graphic = (CHARSET.charset[n&3] == '0');
+ CHARSET.pound = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete
+}
+
+void TEmuVt102::setMargins(int t, int b)
+{
+ screen[0]->setMargins(t, b);
+ screen[1]->setMargins(t, b);
+}
+
+/*! Save the cursor position and the rendition attribute settings. */
+
+void TEmuVt102::saveCursor()
+{
+ CHARSET.sa_graphic = CHARSET.graphic;
+ CHARSET.sa_pound = CHARSET.pound; //This mode is obsolete
+ // we are not clear about these
+ //sa_charset = charsets[cScreen->charset];
+ //sa_charset_num = cScreen->charset;
+ scr->saveCursor();
+}
+
+/*! Restore the cursor position and the rendition attribute settings. */
+
+void TEmuVt102::restoreCursor()
+{
+ CHARSET.graphic = CHARSET.sa_graphic;
+ CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete
+ scr->restoreCursor();
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Mode Operations */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*
+ Some of the emulations state is either added to the state of the screens.
+
+ This causes some scoping problems, since different emulations choose to
+ located the mode either to the current screen or to both.
+
+ For strange reasons, the extend of the rendition attributes ranges over
+ all screens and not over the actual screen.
+
+ We decided on the precise precise extend, somehow.
+*/
+
+// "Mode" related part of the state. These are all booleans.
+
+void TEmuVt102::resetModes()
+{
+ resetMode(MODE_Mouse1000); saveMode(MODE_Mouse1000);
+ resetMode(MODE_AppScreen); saveMode(MODE_AppScreen);
+ // here come obsolete modes
+ resetMode(MODE_AppCuKeys); saveMode(MODE_AppCuKeys);
+ resetMode(MODE_NewLine );
+ setMode(MODE_Ansi );
+ holdScreen = false;
+}
+
+void TEmuVt102::setMode(int m)
+{
+ currParm.mode[m] = true;
+ switch (m)
+ {
+ case MODE_Mouse1000 : if (connected) gui->setMouseMarks(false);
+ break;
+
+ case MODE_AppScreen : screen[1]->clearSelection();
+ setScreen(1);
+ break;
+ }
+ if (m < MODES_SCREEN || m == MODE_NewLine)
+ {
+ screen[0]->setMode(m);
+ screen[1]->setMode(m);
+ }
+}
+
+void TEmuVt102::resetMode(int m)
+{
+ currParm.mode[m] = false;
+ switch (m)
+ {
+ case MODE_Mouse1000 : if (connected) gui->setMouseMarks(true);
+ break;
+
+ case MODE_AppScreen : screen[0]->clearSelection();
+ setScreen(0);
+ break;
+ }
+ if (m < MODES_SCREEN || m == MODE_NewLine)
+ {
+ screen[0]->resetMode(m);
+ screen[1]->resetMode(m);
+ }
+}
+
+void TEmuVt102::saveMode(int m)
+{
+ saveParm.mode[m] = currParm.mode[m];
+}
+
+void TEmuVt102::restoreMode(int m)
+{
+ if(saveParm.mode[m]) setMode(m); else resetMode(m);
+}
+
+bool TEmuVt102::getMode(int m)
+{
+ return currParm.mode[m];
+}
+
+void TEmuVt102::setConnect(bool c)
+{
+ TEmulation::setConnect(c);
+ if (gui)
+ {
+ QObject::disconnect(gui, SIGNAL(sendStringToEmu(const char*)),
+ this, SLOT(sendString(const char*)));
+ }
+ if (c)
+ { // refresh mouse mode
+ if (getMode(MODE_Mouse1000))
+ setMode(MODE_Mouse1000);
+ else
+ resetMode(MODE_Mouse1000);
+#if defined(HAVE_XKB)
+ if (holdScreen)
+ scrolllock_set_on();
+ else
+ scrolllock_set_off();
+#endif
+ QObject::connect(gui, SIGNAL(sendStringToEmu(const char*)),
+ this, SLOT(sendString(const char*)));
+ }
+}
+
+char TEmuVt102::getErase()
+{
+ int cmd = CMD_none;
+ const char* txt;
+ int len;
+ bool metaspecified;
+
+ if (keytrans->findEntry(Qt::Key_Backspace, 0, &cmd, &txt, &len,
+ &metaspecified) && (cmd==CMD_send) && (len == 1))
+ return txt[0];
+
+ return '\b';
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Diagnostic */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*! shows the contents of the scan buffer.
+
+ This functions is used for diagnostics. It is called by \e ReportErrorToken
+ to inform about strings that cannot be decoded or handled by the emulation.
+
+ \sa ReportErrorToken
+*/
+
+/*!
+*/
+
+static void hexdump(int* s, int len)
+{ int i;
+ for (i = 0; i < len; i++)
+ {
+ if (s[i] == '\\')
+ printf("\\\\");
+ else
+ if ((s[i]) > 32 && s[i] < 127)
+ printf("%c",s[i]);
+ else
+ printf("\\%04x(hex)",s[i]);
+ }
+}
+
+void TEmuVt102::scan_buffer_report()
+{
+ if (ppos == 0 || ppos == 1 && (pbuf[0] & 0xff) >= 32) return;
+ printf("token: "); hexdump(pbuf,ppos); printf("\n");
+}
+
+/*!
+*/
+
+void TEmuVt102::ReportErrorToken()
+{
+#ifndef NDEBUG
+ printf("undecodable "); scan_buffer_report();
+#endif
+}
+
+/*
+ Originally comes from NumLockX http://dforce.sh.cvut.cz/~seli/en/numlockx
+
+ NumLockX
+
+ Copyright (C) 2000-2001 Lubos Lunak <l.lunak@kde.org>
+ Copyright (C) 2001 Oswald Buddenhagen <ossi@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+****************************************************************************/
+
+#if defined(HAVE_XKB)
+
+#include <X11/Xlib.h>
+
+#define explicit myexplicit
+#include <X11/XKBlib.h>
+#undef explicit
+
+#include <X11/keysym.h>
+
+/* the XKB stuff is based on code created by Oswald Buddenhagen <ossi@kde.org> */
+static int xkb_init()
+{
+ int xkb_opcode, xkb_event, xkb_error;
+ int xkb_lmaj = XkbMajorVersion;
+ int xkb_lmin = XkbMinorVersion;
+ return XkbLibraryVersion( &xkb_lmaj, &xkb_lmin )
+ && XkbQueryExtension( qt_xdisplay(), &xkb_opcode, &xkb_event, &xkb_error,
+ &xkb_lmaj, &xkb_lmin );
+}
+
+#if 0
+// This method doesn't work in all cases. The atom "ScrollLock" doesn't seem
+// to exist on all XFree versions (at least it's not here with my 3.3.6) - DF
+static unsigned int xkb_mask_modifier( XkbDescPtr xkb, const char *name )
+{
+ int i;
+ if( !xkb || !xkb->names )
+ return 0;
+
+ Atom atom = XInternAtom( xkb->dpy, name, true );
+ if (atom == None)
+ return 0;
+
+ for( i = 0;
+ i < XkbNumVirtualMods;
+ i++ )
+ {
+ if (atom == xkb->names->vmods[i] )
+ {
+ unsigned int mask;
+ XkbVirtualModsToReal( xkb, 1 << i, &mask );
+ return mask;
+ }
+ }
+ return 0;
+}
+
+static unsigned int xkb_scrolllock_mask()
+{
+ XkbDescPtr xkb;
+ if(( xkb = XkbGetKeyboard( qt_xdisplay(), XkbAllComponentsMask, XkbUseCoreKbd )) != NULL )
+ {
+ unsigned int mask = xkb_mask_modifier( xkb, "ScrollLock" );
+ XkbFreeKeyboard( xkb, 0, True );
+ return mask;
+ }
+ return 0;
+}
+
+#else
+static unsigned int xkb_scrolllock_mask()
+{
+ int scrolllock_mask = 0;
+ XModifierKeymap* map = XGetModifierMapping( qt_xdisplay() );
+ KeyCode scrolllock_keycode = XKeysymToKeycode( qt_xdisplay(), XK_Scroll_Lock );
+ if( scrolllock_keycode == NoSymbol ) {
+ XFreeModifiermap(map);
+ return 0;
+ }
+ for( int i = 0;
+ i < 8;
+ ++i )
+ {
+ if( map->modifiermap[ map->max_keypermod * i ] == scrolllock_keycode )
+ scrolllock_mask += 1 << i;
+ }
+
+ XFreeModifiermap(map);
+ return scrolllock_mask;
+}
+#endif
+
+
+static unsigned int scrolllock_mask = 0;
+
+static int xkb_set_on()
+{
+ if (!scrolllock_mask)
+ {
+ if( !xkb_init())
+ return 0;
+ scrolllock_mask = xkb_scrolllock_mask();
+ if( scrolllock_mask == 0 )
+ return 0;
+ }
+ XkbLockModifiers ( qt_xdisplay(), XkbUseCoreKbd, scrolllock_mask, scrolllock_mask);
+ return 1;
+}
+
+static int xkb_set_off()
+{
+ if (!scrolllock_mask)
+ {
+ if( !xkb_init())
+ return 0;
+ scrolllock_mask = xkb_scrolllock_mask();
+ if( scrolllock_mask == 0 )
+ return 0;
+ }
+ XkbLockModifiers ( qt_xdisplay(), XkbUseCoreKbd, scrolllock_mask, 0);
+ return 1;
+}
+
+static void scrolllock_set_on()
+{
+ xkb_set_on();
+}
+
+static void scrolllock_set_off()
+{
+ xkb_set_off();
+}
+#endif // defined(HAVE_XKB)
diff --git a/konsole/konsole/TEmuVt102.h b/konsole/konsole/TEmuVt102.h
new file mode 100644
index 000000000..cd49cc089
--- /dev/null
+++ b/konsole/konsole/TEmuVt102.h
@@ -0,0 +1,146 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef VT102EMU_H
+#define VT102EMU_H
+
+#include "TEWidget.h"
+#include "TEScreen.h"
+#include "TEmulation.h"
+#include <stdio.h>
+
+//
+
+#define MODE_AppScreen (MODES_SCREEN+0)
+#define MODE_AppCuKeys (MODES_SCREEN+1)
+#define MODE_AppKeyPad (MODES_SCREEN+2)
+#define MODE_Mouse1000 (MODES_SCREEN+3)
+#define MODE_Ansi (MODES_SCREEN+4)
+#define MODE_total (MODES_SCREEN+5)
+
+struct DECpar
+{
+ bool mode[MODE_total];
+};
+
+struct CharCodes
+{
+ // coding info
+ char charset[4]; //
+ int cu_cs; // actual charset.
+ bool graphic; // Some VT100 tricks
+ bool pound ; // Some VT100 tricks
+ bool sa_graphic; // saved graphic
+ bool sa_pound; // saved pound
+};
+
+class TEmuVt102 : public TEmulation
+{ Q_OBJECT
+
+public:
+
+ TEmuVt102(TEWidget* gui);
+ void changeGUI(TEWidget* newgui);
+ ~TEmuVt102();
+
+ virtual void onKeyPress(QKeyEvent*);
+public slots: // signals incoming from TEWidget
+
+ void onMouse(int cb, int cx, int cy);
+
+signals:
+
+ void changeTitle(int,const QString&);
+
+public:
+
+ void clearEntireScreen();
+ void reset();
+
+ void onRcvChar(int cc);
+public slots:
+ 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);
+
+ char getErase();
+
+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 reportSecondaryAttributes();
+ void reportStatus();
+ void reportAnswerBack();
+ void reportCursorPosition();
+ void reportTerminalParms(int p);
+
+ void onScrollLock();
+ void scrollLock(const bool lock);
+
+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);
+ void setMargins(int t, int b);
+
+ CharCodes charset[2];
+
+ DECpar currParm;
+ DECpar saveParm;
+ bool holdScreen;
+};
+
+#endif // ifndef ANSIEMU_H
diff --git a/konsole/konsole/TEmulation.cpp b/konsole/konsole/TEmulation.cpp
new file mode 100644
index 000000000..0ff2a5163
--- /dev/null
+++ b/konsole/konsole/TEmulation.cpp
@@ -0,0 +1,550 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1996 by Matthias Ettrich <ettrich@kde.org>
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+/*! \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.
+
+ We start also a second time which is never restarted. If repeatedly
+ restarting of the first timer could delay continuous output indefinitly,
+ the second timer guarantees that the output is refreshed with at least
+ a fixed rate.
+*/
+
+/* FIXME
+ - evtl. the bulk operations could be made more transparent.
+*/
+
+#include "TEmulation.h"
+#include "TEWidget.h"
+#include "TEScreen.h"
+#include <kdebug.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <qregexp.h>
+#include <qclipboard.h>
+
+#include <assert.h>
+
+#include "TEmulation.moc"
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* TEmulation */
+/* */
+/* ------------------------------------------------------------------------- */
+
+#define CNTL(c) ((c)-'@')
+
+/*!
+*/
+
+TEmulation::TEmulation(TEWidget* w)
+: gui(w),
+ scr(0),
+ connected(false),
+ listenToKeyPress(false),
+ m_codec(0),
+ decoder(0),
+ keytrans(0),
+ m_findPos(-1)
+{
+
+ screen[0] = new TEScreen(gui->Lines(),gui->Columns());
+ screen[1] = new TEScreen(gui->Lines(),gui->Columns());
+ scr = screen[0];
+
+ QObject::connect(&bulk_timer1, SIGNAL(timeout()), this, SLOT(showBulk()) );
+ QObject::connect(&bulk_timer2, SIGNAL(timeout()), this, SLOT(showBulk()) );
+ connectGUI();
+ setKeymap(0); // Default keymap
+}
+
+/*!
+*/
+
+void TEmulation::connectGUI()
+{
+ 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,const bool)),
+ this,SLOT(onSelectionBegin(const int,const int,const bool)) );
+ 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(copySelectionSignal()),
+ this,SLOT(copySelection()) );
+ QObject::connect(gui,SIGNAL(clearSelectionSignal()),
+ this,SLOT(clearSelection()) );
+ QObject::connect(gui,SIGNAL(isBusySelecting(bool)),
+ this,SLOT(isBusySelecting(bool)) );
+ QObject::connect(gui,SIGNAL(testIsSelected(const int, const int, bool &)),
+ this,SLOT(testIsSelected(const int, const int, bool &)) );
+}
+
+/*!
+*/
+
+void TEmulation::changeGUI(TEWidget* newgui)
+{
+ if (static_cast<TEWidget *>( gui )==newgui) return;
+
+ if ( gui ) {
+ QObject::disconnect(gui,SIGNAL(changedHistoryCursor(int)),
+ this,SLOT(onHistoryCursorChange(int)));
+ QObject::disconnect(gui,SIGNAL(keyPressedSignal(QKeyEvent*)),
+ this,SLOT(onKeyPress(QKeyEvent*)));
+ QObject::disconnect(gui,SIGNAL(beginSelectionSignal(const int,const int,const bool)),
+ this,SLOT(onSelectionBegin(const int,const int,const bool)) );
+ QObject::disconnect(gui,SIGNAL(extendSelectionSignal(const int,const int)),
+ this,SLOT(onSelectionExtend(const int,const int)) );
+ QObject::disconnect(gui,SIGNAL(endSelectionSignal(const bool)),
+ this,SLOT(setSelection(const bool)) );
+ QObject::disconnect(gui,SIGNAL(copySelectionSignal()),
+ this,SLOT(copySelection()) );
+ QObject::disconnect(gui,SIGNAL(clearSelectionSignal()),
+ this,SLOT(clearSelection()) );
+ QObject::disconnect(gui,SIGNAL(isBusySelecting(bool)),
+ this,SLOT(isBusySelecting(bool)) );
+ QObject::disconnect(gui,SIGNAL(testIsSelected(const int, const int, bool &)),
+ this,SLOT(testIsSelected(const int, const int, bool &)) );
+ }
+ gui=newgui;
+ connectGUI();
+}
+
+/*!
+*/
+
+TEmulation::~TEmulation()
+{
+ delete screen[0];
+ delete screen[1];
+ delete decoder;
+}
+
+/*! change between primary and alternate screen
+*/
+
+void TEmulation::setScreen(int n)
+{
+ TEScreen *old = scr;
+ scr = screen[n&1];
+ if (scr != old)
+ old->setBusySelecting(false);
+}
+
+void TEmulation::setHistory(const HistoryType& t)
+{
+ screen[0]->setScroll(t);
+
+ if (!connected) return;
+ showBulk();
+}
+
+const HistoryType& TEmulation::history()
+{
+ return screen[0]->getScroll();
+}
+
+void TEmulation::setCodec(const QTextCodec * qtc)
+{
+ m_codec = qtc;
+ delete decoder;
+ decoder = m_codec->makeDecoder();
+ emit useUtf8(utf8());
+}
+
+void TEmulation::setCodec(int c)
+{
+ setCodec(c ? QTextCodec::codecForName("utf8")
+ : QTextCodec::codecForLocale());
+}
+
+void TEmulation::setKeymap(int no)
+{
+ keytrans = KeyTrans::find(no);
+}
+
+void TEmulation::setKeymap(const QString &id)
+{
+ keytrans = KeyTrans::find(id);
+}
+
+QString TEmulation::keymap()
+{
+ return keytrans->id();
+}
+
+int TEmulation::keymapNo()
+{
+ return keytrans->numb();
+}
+
+// Interpreting Codes ---------------------------------------------------------
+
+/*
+ This section deals with decoding the incoming character stream.
+ Decoding means here, that the stream is first seperated into `tokens'
+ which are then mapped to a `meaning' provided as operations by the
+ `Screen' class.
+*/
+
+/*!
+*/
+
+void TEmulation::onRcvChar(int c)
+// process application unicode input to terminal
+// this is a trivial scanner
+{
+ c &= 0xff;
+ switch (c)
+ {
+ case '\b' : scr->BackSpace(); break;
+ case '\t' : scr->Tabulate(); break;
+ case '\n' : scr->NewLine(); break;
+ case '\r' : scr->Return(); break;
+ case 0x07 : emit notifySessionState(NOTIFYBELL);
+ break;
+ default : scr->ShowCharacter(c); break;
+ };
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Keyboard Handling */
+/* */
+/* ------------------------------------------------------------------------- */
+
+/*!
+*/
+
+void TEmulation::onKeyPress( QKeyEvent* ev )
+{
+ if (!listenToKeyPress) return; // someone else gets the keys
+ emit notifySessionState(NOTIFYNORMAL);
+ if (scr->getHistCursor() != scr->getHistLines() && !ev->text().isEmpty())
+ scr->setHistCursor(scr->getHistLines());
+ if (!ev->text().isEmpty())
+ { // A block of text
+ // Note that the text is proper unicode.
+ // We should do a conversion here, but since this
+ // routine will never be used, we simply emit plain ascii.
+ emit sndBlock(ev->text().ascii(),ev->text().length());
+ }
+ else if (ev->ascii()>0)
+ { unsigned char c[1];
+ c[0] = ev->ascii();
+ emit sndBlock((char*)c,1);
+ }
+}
+
+// Unblocking, Byte to Unicode translation --------------------------------- --
+
+/*
+ We are doing code conversion from locale to unicode first.
+*/
+
+void TEmulation::onRcvBlock(const char *s, int len)
+{
+ emit notifySessionState(NOTIFYACTIVITY);
+
+ bulkStart();
+
+ QString r;
+ int i, l;
+
+ for (i = 0; i < len; i++)
+ {
+ // If we get a control code halfway a multi-byte sequence
+ // we flush the decoder and continue with the control code.
+ if ((unsigned char) s[i] < 32)
+ {
+ if (!r.length()) {
+ QString tmp;
+ // Flush decoder
+ while(!tmp.length())
+ tmp = decoder->toUnicode(" ",1);
+ }
+
+ onRcvChar((unsigned char) s[i]);
+
+ if (s[i] == '\030' && (len-i-1 > 3) && (strncmp(s+i+1, "B00", 3) == 0))
+ emit zmodemDetected();
+
+ continue;
+ }
+
+ // Otherwise, bulk decode until the next control code
+ for(l = i; l < len; l++)
+ if ((unsigned char) s[l+1] < 32)
+ break;
+
+ r = decoder->toUnicode(&s[i],l-i+1);
+ int reslen = r.length();
+
+ for (int j = 0; j < reslen; j++)
+ {
+ if (r[j].category() == QChar::Mark_NonSpacing)
+ scr->compose(r.mid(j,1));
+ else
+ onRcvChar(r[j].unicode());
+ }
+ i = l;
+ }
+}
+
+// Selection --------------------------------------------------------------- --
+
+void TEmulation::onSelectionBegin(const int x, const int y, const bool columnmode) {
+ if (!connected) return;
+ scr->setSelBeginXY(x,y,columnmode);
+ showBulk();
+}
+
+void TEmulation::onSelectionExtend(const int x, const int y) {
+ if (!connected) return;
+ scr->setSelExtentXY(x,y);
+ showBulk();
+}
+
+void TEmulation::setSelection(const bool preserve_line_breaks) {
+ if (!connected) return;
+ QString t = scr->getSelText(preserve_line_breaks);
+ if (!t.isNull()) gui->setSelection(t);
+}
+
+void TEmulation::isBusySelecting(bool busy)
+{
+ if (!connected) return;
+ scr->setBusySelecting(busy);
+}
+
+void TEmulation::testIsSelected(const int x, const int y, bool &selected)
+{
+ if (!connected) return;
+ selected=scr->testIsSelected(x,y);
+}
+
+void TEmulation::clearSelection() {
+ if (!connected) return;
+ scr->clearSelection();
+ showBulk();
+}
+
+void TEmulation::copySelection() {
+ if (!connected) return;
+ QString t = scr->getSelText(true);
+ QApplication::clipboard()->setText(t);
+}
+
+void TEmulation::streamHistory(QTextStream* stream) {
+ scr->streamHistory(stream);
+}
+
+void TEmulation::findTextBegin()
+{
+ m_findPos = -1;
+}
+
+bool TEmulation::findTextNext( const QString &str, bool forward, bool caseSensitive, bool regExp )
+{
+ int pos = -1;
+ QString string;
+
+ if (forward) {
+ for (int i = (m_findPos==-1?0:m_findPos+1); i<(scr->getHistLines()+scr->getLines()); i++) {
+ string = scr->getHistoryLine(i);
+ if (regExp)
+ pos = string.find( QRegExp(str,caseSensitive) );
+ else
+ pos = string.find(str, 0, caseSensitive);
+ if(pos!=-1) {
+ m_findPos=i;
+ if(i>scr->getHistLines())
+ scr->setHistCursor(scr->getHistLines());
+ else
+ scr->setHistCursor(i);
+ showBulk();
+ return true;
+ }
+ }
+ }
+ else { // searching backwards
+ for(int i = (m_findPos==-1?(scr->getHistLines()+scr->getLines()):m_findPos-1); i>=0; i--) {
+ string = scr->getHistoryLine(i);
+ if (regExp)
+ pos = string.find( QRegExp(str,caseSensitive) );
+ else
+ pos = string.find(str, 0, caseSensitive);
+ if(pos!=-1) {
+ m_findPos=i;
+ if(i>scr->getHistLines())
+ scr->setHistCursor(scr->getHistLines());
+ else
+ scr->setHistCursor(i);
+ showBulk();
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+// Refreshing -------------------------------------------------------------- --
+
+#define BULK_TIMEOUT1 10
+#define BULK_TIMEOUT2 40
+
+/*!
+*/
+
+void TEmulation::showBulk()
+{
+ bulk_timer1.stop();
+ bulk_timer2.stop();
+
+ if (connected)
+ {
+ ca* image = scr->getCookedImage(); // get the image
+ gui->setImage(image,
+ scr->getLines(),
+ scr->getColumns()); // actual refresh
+ gui->setCursorPos(scr->getCursorX(), scr->getCursorY()); // set XIM position
+ free(image);
+ //FIXME: check that we do not trigger other draw event here.
+ gui->setLineWrapped( scr->getCookedLineWrapped() );
+ //kdDebug(1211)<<"TEmulation::showBulk(): setScroll()"<<endl;
+ gui->setScroll(scr->getHistCursor(),scr->getHistLines());
+ //kdDebug(1211)<<"TEmulation::showBulk(): setScroll() done"<<endl;
+ }
+}
+
+void TEmulation::bulkStart()
+{
+ bulk_timer1.start(BULK_TIMEOUT1,true);
+ if (!bulk_timer2.isActive())
+ bulk_timer2.start(BULK_TIMEOUT2, true);
+}
+
+void TEmulation::setConnect(bool c)
+{
+ //kdDebug(1211)<<"TEmulation::setConnect()"<<endl;
+ connected = c;
+ if ( connected)
+ {
+ showBulk();
+ }
+}
+
+char TEmulation::getErase()
+{
+ return '\b';
+}
+
+void TEmulation::setListenToKeyPress(bool l)
+{
+ listenToKeyPress=l;
+}
+
+// ---------------------------------------------------------------------------
+
+/*! triggered by image size change of the TEWidget `gui'.
+
+ This event is simply propagated to the attached screens
+ and to the related serial line.
+*/
+
+void TEmulation::onImageSizeChange(int lines, int columns)
+{
+ assert( lines > 0 && columns > 0 );
+
+ //kdDebug(1211)<<"TEmulation::onImageSizeChange()"<<endl;
+ screen[0]->resizeImage(lines,columns);
+ screen[1]->resizeImage(lines,columns);
+
+ if (!connected) return;
+ //kdDebug(1211)<<"TEmulation::onImageSizeChange() showBulk()"<<endl;
+ showBulk();
+ //kdDebug(1211)<<"TEmulation::onImageSizeChange() showBulk() done"<<endl;
+ emit ImageSizeChanged(columns, lines); // propagate event
+ //kdDebug(1211)<<"TEmulation::onImageSizeChange() done"<<endl;
+}
+
+QSize TEmulation::imageSize()
+{
+ return QSize(scr->getColumns(), scr->getLines());
+}
+
+void TEmulation::onHistoryCursorChange(int cursor)
+{
+ if (!connected) return;
+ scr->setHistCursor(cursor);
+
+ bulkStart();
+}
+
+void TEmulation::setColumns(int columns)
+{
+ //FIXME: this goes strange ways.
+ // Can we put this straight or explain it at least?
+ emit changeColumns(columns);
+}
diff --git a/konsole/konsole/TEmulation.h b/konsole/konsole/TEmulation.h
new file mode 100644
index 000000000..53f05c6e7
--- /dev/null
+++ b/konsole/konsole/TEmulation.h
@@ -0,0 +1,149 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef EMULATION_H
+#define EMULATION_H
+
+#include "TEWidget.h"
+#include "TEScreen.h"
+#include <qtimer.h>
+#include <stdio.h>
+#include <qtextcodec.h>
+#include <qguardedptr.h>
+#include <keytrans.h>
+
+enum { NOTIFYNORMAL=0, NOTIFYBELL=1, NOTIFYACTIVITY=2, NOTIFYSILENCE=3 };
+
+class TEmulation : public QObject
+{ Q_OBJECT
+
+public:
+
+ TEmulation(TEWidget* gui);
+ virtual void changeGUI(TEWidget* newgui);
+ ~TEmulation();
+
+public:
+ QSize imageSize();
+ virtual void setHistory(const HistoryType&);
+ const QTextCodec *codec() { return m_codec; }
+ void setCodec(const QTextCodec *);
+ virtual const HistoryType& history();
+ virtual void streamHistory(QTextStream*);
+
+ virtual void findTextBegin();
+ virtual bool findTextNext( const QString &str, bool forward, bool caseSensitive, bool regExp );
+
+public slots: // signals incoming from TEWidget
+
+ virtual void onImageSizeChange(int lines, int columns);
+ virtual void onHistoryCursorChange(int cursor);
+ virtual void onKeyPress(QKeyEvent*);
+
+ virtual void clearSelection();
+ virtual void copySelection();
+ virtual void onSelectionBegin(const int x, const int y, const bool columnmode);
+ virtual void onSelectionExtend(const int x, const int y);
+ virtual void setSelection(const bool preserve_line_breaks);
+ virtual void isBusySelecting(bool busy);
+ virtual void testIsSelected(const int x, const int y, bool &selected);
+
+public slots: // signals incoming from data source
+
+ void onRcvBlock(const char* txt,int len);
+
+signals:
+
+ void lockPty(bool);
+ void useUtf8(bool);
+ void sndBlock(const char* txt,int len);
+ void ImageSizeChanged(int lines, int columns);
+ void changeColumns(int columns);
+ void changeColLin(int columns, int lines);
+ void changeTitle(int arg, const char* str);
+ void notifySessionState(int state);
+ void zmodemDetected();
+ void changeTabTextColor(int color);
+
+public:
+
+ virtual void onRcvChar(int);
+
+ virtual void setMode (int) = 0;
+ virtual void resetMode(int) = 0;
+
+ virtual void sendString(const char*) = 0;
+
+ virtual void setConnect(bool r);
+ bool isConnected() { return connected; }
+
+ bool utf8() { return m_codec->mibEnum() == 106; }
+
+ virtual char getErase();
+
+ virtual void setListenToKeyPress(bool l);
+ void setColumns(int columns);
+
+ void setKeymap(int no);
+ void setKeymap(const QString &id);
+ int keymapNo();
+ QString keymap();
+
+ virtual void clearEntireScreen() =0;
+ virtual void reset() =0;
+
+protected:
+
+ QGuardedPtr<TEWidget> gui;
+ TEScreen* scr; // referes to one `screen'
+ TEScreen* screen[2]; // 0 = primary, 1 = alternate
+ void setScreen(int n); // set `scr' to `screen[n]'
+
+ bool connected; // communicate with widget
+ bool listenToKeyPress; // listen to input
+
+ void setCodec(int c); // codec number, 0 = locale, 1=utf8
+
+ const QTextCodec* m_codec;
+ QTextDecoder* decoder;
+
+ KeyTrans* keytrans;
+
+// refreshing related material.
+// this is localized in the class.
+private slots: // triggered by timer
+
+ void showBulk();
+
+private:
+
+ void connectGUI();
+
+ void bulkStart();
+
+private:
+
+ QTimer bulk_timer1;
+ QTimer bulk_timer2;
+
+ int m_findPos;
+};
+
+#endif // ifndef EMULATION_H
diff --git a/konsole/konsole/default.keytab.h b/konsole/konsole/default.keytab.h
new file mode 100644
index 000000000..855b4d320
--- /dev/null
+++ b/konsole/konsole/default.keytab.h
@@ -0,0 +1,76 @@
+ /* generated by '../tests/quote ../other/README.default.Keytab' */
+
+ "keyboard \"XTerm (XFree 4.x.x)\"\n"
+ "key Escape : \"\\E\"\n"
+ "key Tab -Shift : \"\\t\"\n"
+ "key Tab +Shift+Ansi : \"\\E[Z\"\n"
+ "key Tab +Shift-Ansi : \"\\t\"\n"
+ "key Backtab +Ansi : \"\\E[Z\"\n"
+ "key Backtab -Ansi : \"\\t\"\n"
+ "key Return-Shift-NewLine : \"\\r\"\n"
+ "key Return-Shift+NewLine : \"\\r\\n\"\n"
+ "key Return+Shift : \"\\EOM\"\n"
+ "key Backspace : \"\\x7f\"\n"
+ "key Up -Shift-Ansi : \"\\EA\"\n"
+ "key Down -Shift-Ansi : \"\\EB\"\n"
+ "key Right-Shift-Ansi : \"\\EC\"\n"
+ "key Left -Shift-Ansi : \"\\ED\"\n"
+ "key Up -Shift-AnyMod+Ansi+AppCuKeys : \"\\EOA\"\n"
+ "key Down -Shift-AnyMod+Ansi+AppCuKeys : \"\\EOB\"\n"
+ "key Right -Shift-AnyMod+Ansi+AppCuKeys : \"\\EOC\"\n"
+ "key Left -Shift-AnyMod+Ansi+AppCuKeys : \"\\EOD\"\n"
+ "key Up -Shift-AnyMod+Ansi-AppCuKeys : \"\\E[A\"\n"
+ "key Down -Shift-AnyMod+Ansi-AppCuKeys : \"\\E[B\"\n"
+ "key Right -Shift-AnyMod+Ansi-AppCuKeys : \"\\E[C\"\n"
+ "key Left -Shift-AnyMod+Ansi-AppCuKeys : \"\\E[D\"\n"
+ "key Up -Shift+AnyMod+Ansi : \"\\E[1;*A\"\n"
+ "key Down -Shift+AnyMod+Ansi : \"\\E[1;*B\"\n"
+ "key Right -Shift+AnyMod+Ansi : \"\\E[1;*C\"\n"
+ "key Left -Shift+AnyMod+Ansi : \"\\E[1;*D\"\n"
+ "key Enter+NewLine : \"\\r\\n\"\n"
+ "key Enter-NewLine : \"\\r\"\n"
+ "key Home -AnyMod -AppCuKeys : \"\\E[H\" \n"
+ "key End -AnyMod -AppCuKeys : \"\\E[F\" \n"
+ "key Home -AnyMod +AppCuKeys : \"\\EOH\" \n"
+ "key End -AnyMod +AppCuKeys : \"\\EOF\" \n"
+ "key Home +AnyMod : \"\\E[1;*H\"\n"
+ "key End +AnyMod : \"\\E[1;*F\"\n"
+ "key Insert -AnyMod : \"\\E[2~\"\n"
+ "key Delete -AnyMod : \"\\E[3~\"\n"
+ "key Insert +AnyMod : \"\\E[2;*~\"\n"
+ "key Delete +AnyMod : \"\\E[3;*~\"\n"
+ "key Prior -Shift-AnyMod : \"\\E[5~\"\n"
+ "key Next -Shift-AnyMod : \"\\E[6~\"\n"
+ "key Prior -Shift+AnyMod : \"\\E[5;*~\"\n"
+ "key Next -Shift+AnyMod : \"\\E[6;*~\"\n"
+ "key F1 -AnyMod : \"\\EOP\"\n"
+ "key F2 -AnyMod : \"\\EOQ\"\n"
+ "key F3 -AnyMod : \"\\EOR\"\n"
+ "key F4 -AnyMod : \"\\EOS\"\n"
+ "key F5 -AnyMod : \"\\E[15~\"\n"
+ "key F6 -AnyMod : \"\\E[17~\"\n"
+ "key F7 -AnyMod : \"\\E[18~\"\n"
+ "key F8 -AnyMod : \"\\E[19~\"\n"
+ "key F9 -AnyMod : \"\\E[20~\"\n"
+ "key F10 -AnyMod : \"\\E[21~\"\n"
+ "key F11 -AnyMod : \"\\E[23~\"\n"
+ "key F12 -AnyMod : \"\\E[24~\"\n"
+ "key F1 +AnyMod : \"\\EO*P\"\n"
+ "key F2 +AnyMod : \"\\EO*Q\"\n"
+ "key F3 +AnyMod : \"\\EO*R\"\n"
+ "key F4 +AnyMod : \"\\EO*S\"\n"
+ "key F5 +AnyMod : \"\\E[15;*~\"\n"
+ "key F6 +AnyMod : \"\\E[17;*~\"\n"
+ "key F7 +AnyMod : \"\\E[18;*~\"\n"
+ "key F8 +AnyMod : \"\\E[19;*~\"\n"
+ "key F9 +AnyMod : \"\\E[20;*~\"\n"
+ "key F10 +AnyMod : \"\\E[21;*~\"\n"
+ "key F11 +AnyMod : \"\\E[23;*~\"\n"
+ "key F12 +AnyMod : \"\\E[24;*~\"\n"
+ "key Space +Control : \"\\x00\"\n"
+ "key Up +Shift-AppScreen : scrollLineUp\n"
+ "key Prior +Shift-AppScreen : scrollPageUp\n"
+ "key Down +Shift-AppScreen : scrollLineDown\n"
+ "key Next +Shift-AppScreen : scrollPageDown\n"
+ "key ScrollLock : scrollLock\n"
+ ""
diff --git a/konsole/konsole/fontembedder.cpp b/konsole/konsole/fontembedder.cpp
new file mode 100644
index 000000000..f2a189598
--- /dev/null
+++ b/konsole/konsole/fontembedder.cpp
@@ -0,0 +1,119 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 2005 by Maksim Orlovich <maksim@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#include <qfile.h>
+#include <qtextstream.h>
+#include <stdlib.h>
+#include <iostream>
+#include <iomanip>
+
+using namespace std;
+
+static Q_UINT32 charVal(QChar val)
+{
+ if (val == ' ')
+ return 0;
+ else
+ return 1;
+}
+
+static Q_UINT32 readGlyphLine(QTextStream& input)
+{
+ QString line = input.readLine();
+ while (line.length() < 5)
+ line += ' ';
+
+ Q_UINT32 val = charVal(line[0]) |
+ (charVal(line[1]) << 1) |
+ (charVal(line[2]) << 2) |
+ (charVal(line[3]) << 3) |
+ (charVal(line[4]) << 4);
+ return val;
+}
+
+static Q_UINT32 readGlyph(QTextStream& input)
+{
+ return readGlyphLine(input) |
+ (readGlyphLine(input) << 5) |
+ (readGlyphLine(input) << 10) |
+ (readGlyphLine(input) << 15) |
+ (readGlyphLine(input) << 20);
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 1)
+ {
+ qWarning("usage: fontembedder font.src > font.h");
+ exit(1);
+ }
+ QFile inFile(argv[1]);
+ if (!inFile.open(IO_ReadOnly))
+ {
+ qFatal("Can not open %s", argv[1]);
+ }
+
+ QTextStream input(&inFile);
+
+ Q_UINT32 glyphStates[128];
+ for (int i = 0; i < 128; ++i)
+ glyphStates[i] = 0; //nothing..
+
+ while (!input.atEnd())
+ {
+ QString line = input.readLine();
+ line = line.stripWhiteSpace();
+ if (line.isEmpty())
+ continue; //Skip empty lines
+ if (line[0] == '#')
+ continue; //Skip comments
+
+ //Must be a glyph ID.
+ int glyph = line.toInt(0, 16);
+ if ((glyph < 0x2500) || (glyph > 0x257f))
+ qFatal("Invalid glyph number");
+
+ glyph = glyph - 0x2500;
+
+ glyphStates[glyph] = readGlyph(input);
+ }
+
+ //Output.
+ cout<<"// WARNING: Autogenerated by \"fontembedder " << argv[1] << "\".\n";
+ cout<<"// You probably do not want to hand-edit this!\n\n";
+ cout<<"static const Q_UINT32 LineChars[] = {\n";
+
+ //Nicely formatted: 8 per line, 16 lines
+ for (int line = 0; line < 128; line += 8)
+ {
+ cout<<"\t";
+ for (int col = line; col < line + 8; ++col)
+ {
+ cout<<"0x"<<hex<<setw(8)<<setfill('0')<<glyphStates[col];
+ if (col != 127)
+ cout<<", ";
+ }
+ cout<<"\n";
+ }
+ cout<<"};\n";
+ return 0;
+}
+
+//kate: indent-width 4; tab-width 4; space-indent on;
diff --git a/konsole/konsole/keytrans.cpp b/konsole/konsole/keytrans.cpp
new file mode 100644
index 000000000..7632520ba
--- /dev/null
+++ b/konsole/konsole/keytrans.cpp
@@ -0,0 +1,755 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+/*
+ 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 <qbuffer.h>
+#include <qobject.h>
+#include <qintdict.h>
+#include <qfile.h>
+#include <kstandarddirs.h>
+#include <klocale.h>
+
+#include <stdio.h>
+#include <stddef.h>
+
+/* 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);
+}
+
+bool KeyTrans::KeyEntry::metaspecified(void)
+{
+ return ((mask & (1 << BITS_Alt)) && (bits & (1 << BITS_Alt))) ||
+ ((mask & (1 << BITS_AnyMod)) && (bits & (1 << BITS_AnyMod)));
+}
+
+bool KeyTrans::KeyEntry::anymodspecified(void)
+{
+ return (mask & (1 << BITS_AnyMod)) && (bits & (1 << BITS_AnyMod));
+}
+
+QString KeyTrans::KeyEntry::text()
+{
+ return txt;
+}
+
+/* KeyTrans
+
+ combines the individual assignments to a proper map
+ Takes part in a collection themself.
+*/
+
+KeyTrans::KeyTrans(const QString& path)
+:m_path(path)
+,m_numb(0)
+,m_fileRead(false)
+{
+ tableX.setAutoDelete(true);
+ if (m_path=="[buildin]")
+ {
+ m_id = "default";
+ }
+ else
+ {
+ m_id = m_path;
+ int i = m_id.findRev('/');
+ if (i > -1)
+ m_id = m_id.mid(i+1);
+ i = m_id.findRev('.');
+ if (i > -1)
+ m_id = m_id.left(i);
+ }
+}
+
+KeyTrans::KeyTrans()
+{
+/* table.setAutoDelete(true);
+ 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 (QPtrListIterator<KeyEntry> it(tableX); it.current(); ++it)
+ {
+ if (it.current()->matches(key,bits,mask))
+ {
+ return it.current();
+ }
+ }
+ tableX.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,
+ bool* metaspecified)
+{
+ if (!m_fileRead) readConfig();
+
+ if (bits & ((1<<BITS_Shift)|(1<<BITS_Alt)|(1<<BITS_Control)))
+ bits |= (1<<BITS_AnyMod);
+
+ for (QPtrListIterator<KeyEntry> it(tableX); it.current(); ++it)
+ if (it.current()->matches(key,bits,0xffff))
+ {
+ *cmd = it.current()->cmd;
+ *len = it.current()->txt.length();
+ if ((*cmd==CMD_send) && it.current()->anymodspecified() && (*len < 16))
+ {
+ static char buf[16];
+ char *c, mask = '1' + BITS(0, bits&(1<<BITS_Shift)) +
+ BITS(1, bits&(1<<BITS_Alt)) + BITS(2, bits&(1<<BITS_Control));
+ strcpy(buf, it.current()->txt.ascii());
+ c = strchr(buf, '*');
+ if (c) *c = mask;
+ *txt = buf;
+ }
+ else
+ *txt = it.current()->txt.ascii();
+ *metaspecified = it.current()->metaspecified();
+ 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;
+ colno = 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; // eos
+ }
+ else if (cc == '\n')
+ {
+ getCc();
+ sym = SYMEol; // eol
+ }
+ else if (inRange('A',cc,'Z')||inRange('a',cc,'z')||inRange('0',cc,'9')||(cc=='_'))
+ {
+ while (inRange('A',cc,'Z') || inRange('a',cc,'z') || inRange('0',cc,'9') || (cc=='_'))
+ {
+ res = res + (char)cc;
+ getCc();
+ }
+ sym = SYMName;
+ }
+ else if (strchr("+-:",cc))
+ {
+ res = "";
+ res = res + (char)cc;
+ getCc();
+ sym = SYMOpr;
+ }
+ else 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;
+ }
+ else
+ {
+ // cc was an invalid char. Get next cc or we will loop forever.
+ getCc();
+ }
+}
+
+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)*
+*/
+
+void KeyTrans::readConfig()
+{
+ if (m_fileRead) return;
+ m_fileRead=true;
+ QIODevice* buf(0);
+ if (m_path=="[buildin]")
+ {
+ QCString txt =
+#include "default.keytab.h"
+;
+ buf=new QBuffer(txt);
+ }
+ else
+ {
+ buf=new QFile(m_path);
+ };
+ KeytabReader ktr(m_path,*buf);
+ ktr.parseTo(this);
+ delete buf;
+}
+
+#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->m_hdr = i18n(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")
+ ptrdiff_t key = (ptrdiff_t)(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")
+ ptrdiff_t bits = (ptrdiff_t)(syms->modsyms[res]) - 1;
+ if (mask & (1 << bits))
+ {
+ fprintf(stderr,"%s(%d,%d): mode name used multiple 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")
+ ptrdiff_t cmd = 0;
+ if (sym == SYMName)
+ {
+ assertSyntax(syms->oprsyms[res], "Unknown operator name")
+ cmd = (ptrdiff_t)(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;
+}
+
+
+// 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("scrollLock", CMD_scrollLock);
+}
+
+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 );
+ defModSym("AppScreen", BITS_AppScreen );
+ // Special (Any Modifier)
+ defModSym("AnyMod", BITS_AnyMod );
+}
+
+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;
+
+KeyTrans* KeyTrans::find(int numb)
+{
+ KeyTrans* res = numb2keymap->find(numb);
+ return res ? res : numb2keymap->find(0);
+}
+
+KeyTrans* KeyTrans::find(const QString &id)
+{
+ QIntDictIterator<KeyTrans> it(*numb2keymap);
+ while(it.current())
+ {
+ if (it.current()->id() == id)
+ return it.current();
+ ++it;
+ }
+ return numb2keymap->find(0);
+}
+
+int KeyTrans::count()
+{
+ return numb2keymap->count();
+}
+
+void KeyTrans::addKeyTrans()
+{
+ m_numb = keytab_serial ++;
+ numb2keymap->insert(m_numb,this);
+}
+
+void KeyTrans::loadAll()
+{
+ if (!numb2keymap)
+ numb2keymap = new QIntDict<KeyTrans>;
+ else { // Needed for konsole_part.
+ numb2keymap->clear();
+ keytab_serial = 0;
+ }
+
+ if (!syms)
+ syms = new KeyTransSymbols;
+
+ //defaultKeyTrans()->addKeyTrans();
+ KeyTrans* sc = new KeyTrans("[buildin]");
+ sc->addKeyTrans();
+
+ QStringList lst = KGlobal::dirs()->findAllResources("data", "konsole/*.keytab");
+
+ for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it )
+ {
+ //QFile file(QFile::encodeName(*it));
+ sc = new KeyTrans(QFile::encodeName(*it));
+ //KeyTrans* sc = KeyTrans::fromDevice(QFile::encodeName(*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/konsole/konsole/keytrans.h b/konsole/konsole/keytrans.h
new file mode 100644
index 000000000..62ccc9c72
--- /dev/null
+++ b/konsole/konsole/keytrans.h
@@ -0,0 +1,100 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef KEYTRANS_H
+#define KEYTRANS_H
+
+#include <qstring.h>
+#include <qptrlist.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_AppScreen 7
+#define BITS_COUNT 8
+#define BITS_AnyMod 9
+
+#define CMD_none -1
+#define CMD_send 0
+#define CMD_scrollPageUp 2
+#define CMD_scrollPageDown 3
+#define CMD_scrollLineUp 4
+#define CMD_scrollLineDown 5
+#define CMD_scrollLock 6
+
+#define BITS(x,v) ((((v)!=0)<<(x)))
+
+class KeytabReader;
+
+class KeyTrans
+{
+ friend class KeytabReader;
+ public:
+ static KeyTrans* find(int numb);
+ static KeyTrans* find(const QString &id);
+ static int count();
+ static void loadAll();
+
+ KeyTrans(const QString& p);
+ ~KeyTrans();
+ bool findEntry(int key, int bits, int* cmd, const char** txt, int* len,
+ bool* metaspecified);
+ const QString& hdr() {if (!m_fileRead) readConfig(); return m_hdr;}
+ int numb() {return m_numb;}
+ const QString& id() { return m_id;}
+
+ class KeyEntry
+ {
+ public:
+ KeyEntry(int ref, int key, int bits, int mask, int cmd, QString txt);
+ ~KeyEntry();
+ bool matches(int key, int bits, int mask);
+ bool metaspecified(void);
+ bool anymodspecified(void);
+ QString text();
+ int ref;
+ private:
+ int key;
+ int bits;
+ int mask;
+ public:
+ int cmd;
+ QString txt;
+ };
+
+ private:
+ KeyEntry* addEntry(int ref, int key, int bits, int mask, int cmd, QString txt);
+ void addKeyTrans();
+ void readConfig();
+ QPtrList<KeyEntry> tableX;
+ QString m_hdr;
+ QString m_path;
+ QString m_id;
+ int m_numb;
+ bool m_fileRead;
+ KeyTrans();
+};
+
+#endif
diff --git a/konsole/konsole/konsole.cpp b/konsole/konsole/konsole.cpp
new file mode 100644
index 000000000..2f9abdf52
--- /dev/null
+++ b/konsole/konsole/konsole.cpp
@@ -0,0 +1,4341 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1996 by Matthias Ettrich <ettrich@kde.org>
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+/* The material contained in here more or less directly orginates from */
+/* kvt, which is copyright (c) 1996 by Matthias Ettrich <ettrich@kde.org> */
+/* */
+
+/*! \class Konsole
+
+ \brief Konsole's main class and program
+
+ The class Konsole handles the application level. Mainly, it is responsible
+ for the configuration, taken from several files, from the command line
+ and from the user. It hardly does anything interesting.
+ Everything is created as late as possible to make it startup fast.
+*/
+
+/*TODO:
+ - allow to set codec
+ - officially declare this file to be hacked to death. ;^)
+ - merge into konsole_part.
+*/
+
+/*STATE:
+
+ konsole/kwin session management, parts stuff, config, menues
+ are all in bad need for a complete rewrite.
+
+ While the emulation core (TEmulation, TEVt102, TEScreen, TEWidget)
+ are pretty stable, the upper level material has certainly drifted.
+
+ Everything related to Sessions, Configuration has to be redesigned.
+ It seems that the konsole now falls apart into individual sessions
+ and a session manager.
+
+Time to start a requirement list.
+
+ - Rework the Emulation::setConnect logic.
+ Together with session changing (Shift-Left/Right, Ctrl-D) it allows
+ key events to propagate to other sessions.
+
+ - Get rid of the unconfigurable, uncallable initial "Konsole" session.
+ Leads to code replication in konsole_part and other issues. Related
+ to the booting of konsole, thus matter of redesign.
+*/
+
+/*FIXME:
+ - All the material in here badly sufferes from the fact that the
+ configuration can originate from many places, so all is duplicated
+ and falls out of service. Especially the command line is badly broken.
+ The sources are:
+ - command line
+ - menu
+ - configuration files
+ - other events (e.g. resizing)
+ We have to find a single-place method to better maintain this.
+ - In general, the material contained in here and in session.C
+ should be rebalanced. Much more material now comes from configuration
+ files and the overall routines should better respect this.
+ - Font+Size list should go to a configuration file, too.
+ - Controlling the widget is currently done by individual attributes.
+ This lead to quite some amount of flicker when a whole bunch of
+ attributes has to be set, e.g. in session swapping.
+*/
+
+#include <config.h>
+
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qimage.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qhbox.h>
+#include <qtoolbutton.h>
+#include <qtooltip.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <kfiledialog.h>
+#include <kurlrequesterdlg.h>
+
+#include <kfontdialog.h>
+#include <kkeydialog.h>
+#include <kstandarddirs.h>
+#include <qpainter.h>
+#include <kmenubar.h>
+#include <kmessagebox.h>
+#include <krootpixmap.h>
+#include <krun.h>
+#include <kstdaction.h>
+#include <kinputdialog.h>
+#include <kdebug.h>
+#include <kipc.h>
+#include <dcopclient.h>
+#include <kglobalsettings.h>
+#include <knotifydialog.h>
+#include <kprinter.h>
+#include <kaccelmanager.h>
+
+#include <kaction.h>
+#include <kshell.h>
+#include <qlabel.h>
+#include <kpopupmenu.h>
+#include <klocale.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include <kiconloader.h>
+#include <kstringhandler.h>
+#include <ktip.h>
+#include <kprocctrl.h>
+#include <ktabwidget.h>
+#include <kregexpeditorinterface.h>
+#include <kparts/componentfactory.h>
+#include <kcharsets.h>
+#include <kcolordialog.h>
+#include <kio/netaccess.h>
+
+#include "konsole.h"
+#include <netwm.h>
+#include "printsettings.h"
+
+#define KONSOLEDEBUG kdDebug(1211)
+
+#define POPUP_NEW_SESSION_ID 121
+#define POPUP_SETTINGS_ID 212
+
+#define SESSION_NEW_WINDOW_ID 1
+#define SESSION_NEW_SHELL_ID 100
+
+extern bool argb_visual; // declared in main.cpp and konsole_part.cpp
+
+// KonsoleFontSelectAction is now also used for selectSize!
+class KonsoleFontSelectAction : public KSelectAction {
+public:
+ KonsoleFontSelectAction(const QString &text, int accel,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name = 0 )
+ : KSelectAction(text, accel, receiver, slot, parent, name) {}
+ KonsoleFontSelectAction( const QString &text, const QIconSet& pix,
+ int accel, const QObject* receiver,
+ const char* slot, QObject* parent,
+ const char* name = 0 )
+ : KSelectAction(text, pix, accel, receiver, slot, parent, name) {}
+
+ virtual void slotActivated( int index );
+};
+
+void KonsoleFontSelectAction::slotActivated(int index) {
+ // emit even if it's already activated
+ if (currentItem() == index) {
+ KSelectAction::slotActivated();
+ return;
+ } else {
+ KSelectAction::slotActivated(index);
+ }
+}
+
+template class QPtrDict<TESession>;
+template class QIntDict<KSimpleConfig>;
+template class QPtrDict<KRadioAction>;
+
+#define DEFAULT_HISTORY_SIZE 1000
+
+Konsole::Konsole(const char* name, int histon, bool menubaron, bool tabbaron, bool frameon, bool scrollbaron,
+ QCString type, bool b_inRestore, const int wanted_tabbar, const QString &workdir )
+:DCOPObject( "konsole" )
+,KMainWindow(0, name)
+,m_defaultSession(0)
+,m_defaultSessionFilename("")
+,tabwidget(0)
+,te(0)
+,se(0)
+,se_previous(0)
+,m_initialSession(0)
+,colors(0)
+,kWinModule(0)
+,menubar(0)
+,statusbar(0)
+,m_session(0)
+,m_edit(0)
+,m_view(0)
+,m_bookmarks(0)
+,m_bookmarksSession(0)
+,m_options(0)
+,m_schema(0)
+,m_keytab(0)
+,m_tabbarSessionsCommands(0)
+,m_signals(0)
+,m_help(0)
+,m_rightButton(0)
+,m_zmodemUpload(0)
+,monitorActivity(0)
+,monitorSilence(0)
+,masterMode(0)
+,showMenubar(0)
+,m_fullscreen(0)
+,selectSize(0)
+,selectFont(0)
+,selectScrollbar(0)
+,selectTabbar(0)
+,selectBell(0)
+,selectSetEncoding(0)
+,m_clearHistory(0)
+,m_findHistory(0)
+,m_saveHistory(0)
+,m_detachSession(0)
+,m_moveSessionLeft(0)
+,m_moveSessionRight(0)
+,bookmarkHandler(0)
+,bookmarkHandlerSession(0)
+,m_finddialog(0)
+,m_find_pattern("")
+,cmd_serial(0)
+,cmd_first_screen(-1)
+,n_keytab(0)
+,n_defaultKeytab(0)
+,n_render(0)
+,curr_schema(0)
+,wallpaperSource(0)
+,sessionIdCounter(0)
+,monitorSilenceSeconds(10)
+,s_kconfigSchema("")
+,m_tabViewMode(ShowIconAndText)
+,b_dynamicTabHide(false)
+,b_autoResizeTabs(false)
+,b_installBitmapFonts(false)
+,b_framevis(true)
+,b_fullscreen(false)
+,m_menuCreated(false)
+,b_warnQuit(false)
+,b_allowResize(true) // Whether application may resize
+,b_fixedSize(false) // Whether user may resize
+,b_addToUtmp(true)
+,b_xonXoff(false)
+,b_bidiEnabled(false)
+,b_fullScripting(false)
+,b_showstartuptip(true)
+,b_sessionShortcutsEnabled(false)
+,b_sessionShortcutsMapped(false)
+,b_matchTabWinTitle(false)
+,m_histSize(DEFAULT_HISTORY_SIZE)
+,m_separator_id(-1)
+,m_newSessionButton(0)
+,m_removeSessionButton(0)
+,sessionNumberMapper(0)
+,sl_sessionShortCuts(0)
+,s_workDir(workdir)
+{
+ isRestored = b_inRestore;
+ connect( &m_closeTimeout, SIGNAL(timeout()), this, SLOT(slotCouldNotClose()));
+
+ no2command.setAutoDelete(true);
+ menubar = menuBar();
+
+ KAcceleratorManager::setNoAccel( menubar );
+
+ sessionNumberMapper = new QSignalMapper( this );
+ connect( sessionNumberMapper, SIGNAL( mapped( int ) ),
+ this, SLOT( newSessionTabbar( int ) ) );
+
+ colors = new ColorSchemaList();
+ colors->checkSchemas();
+ colors->sort();
+
+ KeyTrans::loadAll();
+
+ // create applications /////////////////////////////////////////////////////
+ // read and apply default values ///////////////////////////////////////////
+ resize(321, 321); // Dummy.
+ QSize currentSize = size();
+ KConfig * config = KGlobal::config();
+ config->setDesktopGroup();
+ applyMainWindowSettings(config);
+ if (currentSize != size())
+ defaultSize = size();
+
+ KSimpleConfig *co;
+ if (!type.isEmpty())
+ setDefaultSession(type+".desktop");
+ co = defaultSession();
+
+ co->setDesktopGroup();
+ QString schema = co->readEntry("Schema");
+ readProperties(config, schema, false);
+
+ makeBasicGUI();
+
+ if (isRestored) {
+ n_tabbar = wanted_tabbar;
+ KConfig *c = KApplication::kApplication()->sessionConfig();
+// c->setDesktopGroup(); // Reads from wrong group
+ b_dynamicTabHide = c->readBoolEntry("DynamicTabHide", false);
+ }
+
+ if (!tabbaron)
+ n_tabbar = TabNone;
+
+ makeTabWidget();
+ setCentralWidget(tabwidget);
+
+ if (b_dynamicTabHide || n_tabbar==TabNone)
+ tabwidget->setTabBarHidden(true);
+
+ if (!histon)
+ b_histEnabled=false;
+
+ if (!menubaron)
+ menubar->hide();
+ if (!frameon) {
+ b_framevis=false;
+ if (te) te->setFrameStyle( QFrame::NoFrame );
+ }
+ if (!scrollbaron) {
+ n_scroll = TEWidget::SCRNONE;
+ if (te) te->setScrollbarLocation(TEWidget::SCRNONE);
+ }
+
+// connect(kapp, SIGNAL(kdisplayFontChanged()), this, SLOT(slotFontChanged()));
+
+ kapp->dcopClient()->setDefaultObject( "konsole" );
+}
+
+
+Konsole::~Konsole()
+{
+ sessions.first();
+ while(sessions.current())
+ {
+ sessions.current()->closeSession();
+ sessions.next();
+ }
+
+ // Wait a bit for all childs to clean themselves up.
+ while(sessions.count() && KProcessController::theKProcessController->waitForProcessExit(1))
+ ;
+
+ sessions.setAutoDelete(true);
+
+ resetScreenSessions();
+ if (no2command.isEmpty())
+ delete m_defaultSession;
+
+ delete colors;
+ colors=0;
+
+ delete kWinModule;
+ kWinModule = 0;
+}
+
+void Konsole::setAutoClose(bool on)
+{
+ if (sessions.first())
+ sessions.first()->setAutoClose(on);
+}
+
+void Konsole::showTip()
+{
+ KTipDialog::showTip(this,QString::null,true);
+}
+
+void Konsole::showTipOnStart()
+{
+ if (b_showstartuptip)
+ KTipDialog::showTip(this);
+}
+
+/* ------------------------------------------------------------------------- */
+/* Make menu */
+/* ------------------------------------------------------------------------- */
+
+void Konsole::updateRMBMenu()
+{
+ if (!m_rightButton) return;
+ int index = 0;
+ if (!showMenubar->isChecked() && m_options)
+ {
+ // Only show when menubar is hidden
+ if (!showMenubar->isPlugged( m_rightButton ))
+ {
+ showMenubar->plug ( m_rightButton, index );
+ m_rightButton->insertSeparator( index+1 );
+ }
+ index = 2;
+ m_rightButton->setItemVisible(POPUP_NEW_SESSION_ID,true);
+ if (m_separator_id != -1)
+ m_rightButton->setItemVisible(m_separator_id,true);
+ m_rightButton->setItemVisible(POPUP_SETTINGS_ID,true);
+ }
+ else
+ {
+ if (showMenubar->isPlugged( m_rightButton ))
+ {
+ showMenubar->unplug ( m_rightButton );
+ m_rightButton->removeItemAt(index);
+ }
+ index = 0;
+ m_rightButton->setItemVisible(POPUP_NEW_SESSION_ID,false);
+ m_rightButton->setItemVisible(m_separator_id,false);
+ m_rightButton->setItemVisible(POPUP_SETTINGS_ID,false);
+ }
+
+ if (!m_fullscreen)
+ return;
+ if (b_fullscreen)
+ {
+ if (!m_fullscreen->isPlugged( m_rightButton ))
+ {
+ m_fullscreen->plug ( m_rightButton, index );
+ m_rightButton->insertSeparator( index+1 );
+ }
+ }
+ else
+ {
+ if (m_fullscreen->isPlugged( m_rightButton ))
+ {
+ m_fullscreen->unplug ( m_rightButton );
+ m_rightButton->removeItemAt(index);
+ }
+ }
+}
+
+// Be carefull !!
+// This function consumes a lot of time, that's why it is called delayed on demand.
+// Be careful not to introduce function calls which lead to the execution of this
+// function when starting konsole
+// Be careful not to access stuff which is created in this function before this
+// function was called ! you can check this using m_menuCreated, aleXXX
+void Konsole::makeGUI()
+{
+ if (m_menuCreated) return;
+
+ if (m_tabbarSessionsCommands)
+ disconnect(m_tabbarSessionsCommands,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ disconnect(m_session,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ if (m_options)
+ disconnect(m_options,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ if (m_help)
+ disconnect(m_help,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ if (m_rightButton)
+ disconnect(m_rightButton,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ disconnect(m_edit,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ disconnect(m_view,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ if (m_bookmarks)
+ disconnect(m_bookmarks,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ if (m_bookmarksSession)
+ disconnect(m_bookmarksSession,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ if (m_tabbarSessionsCommands)
+ connect(m_tabbarSessionsCommands,SIGNAL(aboutToShow()),this,SLOT(loadScreenSessions()));
+ connect(m_session,SIGNAL(aboutToShow()),this,SLOT(loadScreenSessions()));
+ m_menuCreated=true;
+
+ // Remove the empty separator Qt inserts if the menu is empty on popup,
+ // not sure if this will be "fixed" in Qt, for now use this hack (malte)
+ if(!(isRestored)) {
+ if (sender() && sender()->inherits("QPopupMenu") &&
+ static_cast<const QPopupMenu *>(sender())->count() == 1)
+ const_cast<QPopupMenu *>(static_cast<const QPopupMenu *>(sender()))->removeItemAt(0);
+ }
+
+ KActionCollection* actions = actionCollection();
+
+ // Send Signal Menu -------------------------------------------------------------
+ if (kapp->authorizeKAction("send_signal"))
+ {
+ m_signals = new KPopupMenu(this);
+ m_signals->insertItem( i18n( "&Suspend Task" ) + " (STOP)", SIGSTOP);
+ m_signals->insertItem( i18n( "&Continue Task" ) + " (CONT)", SIGCONT);
+ m_signals->insertItem( i18n( "&Hangup" ) + " (HUP)", SIGHUP);
+ m_signals->insertItem( i18n( "&Interrupt Task" ) + " (INT)", SIGINT);
+ m_signals->insertItem( i18n( "&Terminate Task" ) + " (TERM)", SIGTERM);
+ m_signals->insertItem( i18n( "&Kill Task" ) + " (KILL)", SIGKILL);
+ m_signals->insertItem( i18n( "User Signal &1") + " (USR1)", SIGUSR1);
+ m_signals->insertItem( i18n( "User Signal &2") + " (USR2)", SIGUSR2);
+ connect(m_signals, SIGNAL(activated(int)), SLOT(sendSignal(int)));
+ KAcceleratorManager::manage( m_signals );
+ }
+
+ // Edit Menu ----------------------------------------------------------------
+ m_copyClipboard->plug(m_edit);
+ m_pasteClipboard->plug(m_edit);
+
+ m_edit->setCheckable(true);
+ if (m_signals)
+ m_edit->insertItem( i18n("&Send Signal"), m_signals );
+
+ if ( m_zmodemUpload ) {
+ m_edit->insertSeparator();
+ m_zmodemUpload->plug( m_edit );
+ }
+
+ m_edit->insertSeparator();
+ m_clearTerminal->plug(m_edit);
+
+ m_resetClearTerminal->plug(m_edit);
+
+ m_edit->insertSeparator();
+ m_findHistory->plug(m_edit);
+ m_findNext->plug(m_edit);
+ m_findPrevious->plug(m_edit);
+ m_saveHistory->plug(m_edit);
+ m_edit->insertSeparator();
+ m_clearHistory->plug(m_edit);
+ m_clearAllSessionHistories->plug(m_edit);
+
+ // View Menu
+ m_detachSession->plug(m_view);
+ m_renameSession->plug(m_view);
+
+ m_view->insertSeparator();
+ monitorActivity->plug ( m_view );
+ monitorSilence->plug ( m_view );
+
+ masterMode->plug ( m_view );
+
+ m_view->insertSeparator();
+ m_moveSessionLeft->setEnabled( false );
+ m_moveSessionLeft->plug(m_view);
+
+ m_moveSessionRight->setEnabled( false );
+ m_moveSessionRight->plug(m_view);
+
+ m_view->insertSeparator();
+ KRadioAction *ra = session2action.find(se);
+ if (ra!=0) ra->plug(m_view);
+
+ //bookmarks menu
+ if (bookmarkHandler)
+ connect( bookmarkHandler, SIGNAL( openURL( const QString&, const QString& )),
+ SLOT( enterURL( const QString&, const QString& )));
+ if (bookmarkHandlerSession)
+ connect( bookmarkHandlerSession, SIGNAL( openURL( const QString&, const QString& )),
+ SLOT( newSession( const QString&, const QString& )));
+ if (m_bookmarks)
+ connect(m_bookmarks, SIGNAL(aboutToShow()), SLOT(bookmarks_menu_check()));
+ if (m_bookmarksSession)
+ connect(m_bookmarksSession, SIGNAL(aboutToShow()), SLOT(bookmarks_menu_check()));
+
+ // Schema Options Menu -----------------------------------------------------
+ m_schema = new KPopupMenu(this);
+ m_schema->setCheckable(true);
+ KAcceleratorManager::manage( m_schema );
+ connect(m_schema, SIGNAL(activated(int)), SLOT(schema_menu_activated(int)));
+ connect(m_schema, SIGNAL(aboutToShow()), SLOT(schema_menu_check()));
+
+ // Keyboard Options Menu ---------------------------------------------------
+ m_keytab = new KPopupMenu(this);
+ m_keytab->setCheckable(true);
+ KAcceleratorManager::manage( m_keytab );
+ connect(m_keytab, SIGNAL(activated(int)), SLOT(keytab_menu_activated(int)));
+
+ //options menu
+ if (m_options)
+ {
+ // Menubar on/off
+ showMenubar->plug ( m_options );
+
+ // Tabbar
+ selectTabbar = new KSelectAction(i18n("&Tab Bar"), 0, this,
+ SLOT(slotSelectTabbar()), actions, "tabbar" );
+ QStringList tabbaritems;
+ tabbaritems << i18n("&Hide") << i18n("&Top") << i18n("&Bottom");
+ selectTabbar->setItems(tabbaritems);
+ selectTabbar->plug(m_options);
+
+ // Scrollbar
+ selectScrollbar = new KSelectAction(i18n("Sc&rollbar"), 0, this,
+ SLOT(slotSelectScrollbar()), actions, "scrollbar" );
+ QStringList scrollitems;
+ scrollitems << i18n("&Hide") << i18n("&Left") << i18n("&Right");
+ selectScrollbar->setItems(scrollitems);
+ selectScrollbar->plug(m_options);
+
+ // Fullscreen
+ m_options->insertSeparator();
+ if (m_fullscreen)
+ {
+ m_fullscreen->plug(m_options);
+ m_options->insertSeparator();
+ }
+
+ // Select Bell
+ selectBell = new KSelectAction(i18n("&Bell"), SmallIconSet( "bell"), 0 , this,
+ SLOT(slotSelectBell()), actions, "bell");
+ QStringList bellitems;
+ bellitems << i18n("System &Bell")
+ << i18n("System &Notification")
+ << i18n("&Visible Bell")
+ << i18n("N&one");
+ selectBell->setItems(bellitems);
+ selectBell->plug(m_options);
+
+ checkBitmapFonts();
+ KActionMenu* m_fontsizes = new KActionMenu( i18n( "Font" ),
+ SmallIconSet( "text" ),
+ actions, 0L );
+ m_fontsizes->insert( new KAction( i18n( "&Enlarge Font" ),
+ SmallIconSet( "fontsizeup" ), 0, this,
+ SLOT( biggerFont() ), actions,
+ "enlarge_font" ) );
+ m_fontsizes->insert( new KAction( i18n( "&Shrink Font" ),
+ SmallIconSet( "fontsizedown" ), 0, this,
+ SLOT( smallerFont() ), actions,
+ "shrink_font" ) );
+ m_fontsizes->insert( new KAction( i18n( "Se&lect..." ),
+ SmallIconSet( "font" ), 0, this,
+ SLOT( slotSelectFont() ), actions,
+ "select_font" ) );
+ if ( b_installBitmapFonts )
+ {
+ m_fontsizes->insert( new KAction( i18n( "&Install Bitmap..." ),
+ SmallIconSet( "font" ), 0, this,
+ SLOT( slotInstallBitmapFonts() ), actions,
+ "install_fonts" ) );
+ }
+ m_fontsizes->plug(m_options);
+
+ // encoding menu, start with default checked !
+ selectSetEncoding = new KSelectAction( i18n( "&Encoding" ), SmallIconSet( "charset" ), 0, this, SLOT(slotSetEncoding()), actions, "set_encoding" );
+ QStringList list = KGlobal::charsets()->descriptiveEncodingNames();
+ list.prepend( i18n( "Default" ) );
+ selectSetEncoding->setItems(list);
+ selectSetEncoding->setCurrentItem (0);
+ selectSetEncoding->plug(m_options);
+
+ if (kapp->authorizeKAction("keyboard"))
+ m_options->insertItem( SmallIconSet( "key_bindings" ), i18n( "&Keyboard" ), m_keytab );
+
+ // Schema
+ if (kapp->authorizeKAction("schema"))
+ m_options->insertItem( SmallIconSet( "colorize" ), i18n( "Sch&ema" ), m_schema);
+
+ // Select size
+ if (!b_fixedSize)
+ {
+ selectSize = new KonsoleFontSelectAction(i18n("S&ize"), 0, this,
+ SLOT(slotSelectSize()), actions, "size");
+ QStringList sizeitems;
+ sizeitems << i18n("40x15 (&Small)")
+ << i18n("80x24 (&VT100)")
+ << i18n("80x25 (&IBM PC)")
+ << i18n("80x40 (&XTerm)")
+ << i18n("80x52 (IBM V&GA)")
+ << ""
+ << i18n("&Custom...");
+ selectSize->setItems(sizeitems);
+ selectSize->plug(m_options);
+ }
+
+ KAction *historyType = new KAction(i18n("Hist&ory..."), "history", 0, this,
+ SLOT(slotHistoryType()), actions, "history");
+ historyType->plug(m_options);
+
+ m_options->insertSeparator();
+
+ KAction *save_settings = new KAction(i18n("&Save as Default"), "filesave", 0, this,
+ SLOT(slotSaveSettings()), actions, "save_default");
+ save_settings->plug(m_options);
+
+ m_options->insertSeparator();
+
+ m_saveProfile->plug(m_options);
+
+ m_options->insertSeparator();
+
+ KStdAction::configureNotifications(this, SLOT(slotConfigureNotifications()), actionCollection())->plug(m_options);
+ KStdAction::keyBindings(this, SLOT(slotConfigureKeys()), actionCollection())->plug(m_options);
+ KAction *configure = KStdAction::preferences(this, SLOT(slotConfigure()), actions);
+ configure->plug(m_options);
+
+ if (KGlobalSettings::insertTearOffHandle())
+ m_options->insertTearOffHandle();
+ }
+
+ //help menu
+ if (m_help)
+ {
+ m_help->insertSeparator(1);
+ m_help->insertItem(SmallIcon( "idea" ), i18n("&Tip of the Day"),
+ this, SLOT(showTip()), 0, -1, 2);
+ }
+
+ //the different session menus
+ buildSessionMenus();
+
+ connect(m_session, SIGNAL(activated(int)), SLOT(newSession(int)));
+
+ // Right mouse button menu
+ if (m_rightButton)
+ {
+ updateRMBMenu(); // show menubar / exit fullscreen
+
+ KAction* selectionEnd = new KAction(i18n("Set Selection End"), 0, this,
+ SLOT(slotSetSelectionEnd()), actions, "selection_end");
+ selectionEnd->plug(m_rightButton);
+
+ m_copyClipboard->plug(m_rightButton);
+ m_pasteClipboard->plug(m_rightButton);
+ if (m_signals)
+ m_rightButton->insertItem(i18n("&Send Signal"), m_signals);
+
+ m_rightButton->insertSeparator();
+ if (m_tabbarSessionsCommands)
+ m_rightButton->insertItem( i18n("New Sess&ion"), m_tabbarSessionsCommands, POPUP_NEW_SESSION_ID );
+ m_detachSession->plug(m_rightButton);
+ m_renameSession->plug(m_rightButton);
+
+ if (m_bookmarks)
+ {
+ m_rightButton->insertSeparator();
+ m_rightButton->insertItem(i18n("&Bookmarks"), m_bookmarks);
+ }
+
+ if (m_options)
+ {
+ m_separator_id=m_rightButton->insertSeparator();
+ m_rightButton->insertItem(i18n("S&ettings"), m_options, POPUP_SETTINGS_ID);
+ }
+ m_rightButton->insertSeparator();
+ m_closeSession->plug(m_rightButton );
+ if (KGlobalSettings::insertTearOffHandle())
+ m_rightButton->insertTearOffHandle();
+ }
+
+ delete colors;
+ colors = new ColorSchemaList();
+ colors->checkSchemas();
+ colors->sort();
+ updateSchemaMenu();
+ ColorSchema *sch=colors->find(s_schema);
+ if (sch)
+ curr_schema=sch->numb();
+ else
+ curr_schema = 0;
+ for (uint i=0; i<m_schema->count(); i++)
+ m_schema->setItemChecked(i,false);
+
+ m_schema->setItemChecked(curr_schema,true);
+ while (se == NULL) {}
+ se->setSchemaNo(curr_schema);
+
+ // insert keymaps into menu
+ // This sorting seems a bit cumbersome; but it is not called often.
+ QStringList kt_titles;
+ typedef QMap<QString,KeyTrans*> QStringKeyTransMap;
+ QStringKeyTransMap kt_map;
+
+ for (int i = 0; i < KeyTrans::count(); i++)
+ {
+ KeyTrans* ktr = KeyTrans::find(i);
+ assert( ktr );
+ QString title=ktr->hdr().lower();
+ kt_titles << title;
+ kt_map[title] = ktr;
+ }
+ kt_titles.sort();
+ for ( QStringList::Iterator it = kt_titles.begin(); it != kt_titles.end(); ++it ) {
+ KeyTrans* ktr = kt_map[*it];
+ assert( ktr );
+ QString title=ktr->hdr();
+ m_keytab->insertItem(title.replace('&',"&&"),ktr->numb());
+ }
+
+ applySettingsToGUI();
+ isRestored = false;
+
+
+ // Fill tab context menu
+ m_tabPopupMenu = new KPopupMenu( this );
+ KAcceleratorManager::manage( m_tabPopupMenu );
+
+ m_tabDetachSession= new KAction( i18n("&Detach Session"), SmallIconSet("tab_breakoff"), 0, this, SLOT(slotTabDetachSession()), this );
+ m_tabDetachSession->plug(m_tabPopupMenu);
+
+ m_tabPopupMenu->insertItem( i18n("&Rename Session..."), this,
+ SLOT(slotTabRenameSession()) );
+ m_tabPopupMenu->insertSeparator();
+
+ m_tabMonitorActivity = new KToggleAction ( i18n( "Monitor for &Activity" ),
+ SmallIconSet("activity"), 0, this, SLOT( slotTabToggleMonitor() ), this );
+ m_tabMonitorActivity->setCheckedState( KGuiItem( i18n( "Stop Monitoring for &Activity" ) ) );
+ m_tabMonitorActivity->plug(m_tabPopupMenu);
+
+ m_tabMonitorSilence = new KToggleAction ( i18n( "Monitor for &Silence" ),
+ SmallIconSet("silence"), 0, this, SLOT( slotTabToggleMonitor() ), this );
+ m_tabMonitorSilence->setCheckedState( KGuiItem( i18n( "Stop Monitoring for &Silence" ) ) );
+ m_tabMonitorSilence->plug(m_tabPopupMenu);
+
+ m_tabMasterMode = new KToggleAction ( i18n( "Send &Input to All Sessions" ), "remote", 0, this,
+ SLOT( slotTabToggleMasterMode() ), this);
+ m_tabMasterMode->plug(m_tabPopupMenu);
+
+ m_tabPopupMenu->insertSeparator();
+ m_tabPopupMenu->insertItem( SmallIconSet("colors"), i18n("Select &Tab Color..."), this, SLOT(slotTabSelectColor()) );
+
+ m_tabPopupMenu->insertSeparator();
+ m_tabPopupTabsMenu = new KPopupMenu( m_tabPopupMenu );
+ m_tabPopupMenu->insertItem( i18n("Switch to Tab" ), m_tabPopupTabsMenu );
+ connect( m_tabPopupTabsMenu, SIGNAL( activated ( int ) ),
+ SLOT( activateSession( int ) ) );
+
+ m_tabPopupMenu->insertSeparator();
+ m_tabPopupMenu->insertItem( SmallIcon("fileclose"), i18n("C&lose Session"), this,
+ SLOT(slotTabCloseSession()) );
+
+ if (m_options) {
+ // Fill tab bar context menu
+ m_tabbarPopupMenu = new KPopupMenu( this );
+ KAcceleratorManager::manage( m_tabbarPopupMenu );
+ selectTabbar->plug(m_tabbarPopupMenu);
+
+ KSelectAction *viewOptions = new KSelectAction(this);
+ viewOptions->setText(i18n("Tab &Options"));
+ QStringList options;
+ options << i18n("&Text && Icons") << i18n("Text &Only") << i18n("&Icons Only");
+ viewOptions->setItems(options);
+ viewOptions->setCurrentItem(m_tabViewMode);
+ viewOptions->plug(m_tabbarPopupMenu);
+ connect(viewOptions, SIGNAL(activated(int)), this, SLOT(slotTabSetViewOptions(int)));
+ slotTabSetViewOptions(m_tabViewMode);
+
+ KToggleAction *dynamicTabHideOption = new KToggleAction ( i18n( "&Dynamic Hide" ), 0, this,
+ SLOT( slotTabbarToggleDynamicHide() ), this);
+ dynamicTabHideOption->setChecked(b_dynamicTabHide);
+ dynamicTabHideOption->plug(m_tabbarPopupMenu);
+
+ KToggleAction *m_autoResizeTabs = new KToggleAction( i18n("&Auto Resize Tabs"),
+ 0, this, SLOT( slotToggleAutoResizeTabs() ), this);
+ m_autoResizeTabs->setChecked(b_autoResizeTabs);
+ m_autoResizeTabs->plug(m_tabbarPopupMenu);
+ }
+}
+
+// Called via menu
+void Konsole::slotSetEncoding()
+{
+ if (!se) return;
+
+ QTextCodec * qtc;
+ if (selectSetEncoding->currentItem() == 0)
+ {
+ qtc = QTextCodec::codecForLocale();
+ }
+ else
+ {
+ bool found;
+ QString enc = KGlobal::charsets()->encodingForName(selectSetEncoding->currentText());
+ qtc = KGlobal::charsets()->codecForName(enc, found);
+
+ // BR114535 : Remove jis7 due to infinite loop.
+ if ( enc == "jis7" ) {
+ kdWarning()<<"Encoding Japanese (jis7) currently does not work! BR114535"<<endl;
+ qtc = QTextCodec::codecForLocale();
+ selectSetEncoding->setCurrentItem( 0 );
+ }
+
+ if(!found)
+ {
+ kdWarning() << "Codec " << selectSetEncoding->currentText() << " not found! Using default..." << endl;
+ qtc = QTextCodec::codecForLocale();
+ selectSetEncoding->setCurrentItem( 0 );
+ }
+ }
+
+ se->setEncodingNo(selectSetEncoding->currentItem());
+ se->getEmulation()->setCodec(qtc);
+}
+
+void Konsole::makeTabWidget()
+{
+ tabwidget = new KTabWidget(this);
+ tabwidget->setTabReorderingEnabled(true);
+ tabwidget->setAutomaticResizeTabs( b_autoResizeTabs );
+ tabwidget->setTabCloseActivatePrevious( true );
+
+ if (n_tabbar==TabTop)
+ tabwidget->setTabPosition(QTabWidget::Top);
+ else
+ tabwidget->setTabPosition(QTabWidget::Bottom);
+
+ KAcceleratorManager::setNoAccel( tabwidget );
+
+ connect(tabwidget, SIGNAL(movedTab(int,int)), SLOT(slotMovedTab(int,int)));
+ connect(tabwidget, SIGNAL(mouseDoubleClick(QWidget*)), SLOT(slotRenameSession()));
+ connect(tabwidget, SIGNAL(currentChanged(QWidget*)), SLOT(activateSession(QWidget*)));
+ connect( tabwidget, SIGNAL(contextMenu(QWidget*, const QPoint &)),
+ SLOT(slotTabContextMenu(QWidget*, const QPoint &)));
+ connect( tabwidget, SIGNAL(contextMenu(const QPoint &)),
+ SLOT(slotTabbarContextMenu(const QPoint &)));
+
+ if (kapp->authorize("shell_access")) {
+ connect(tabwidget, SIGNAL(mouseDoubleClick()), SLOT(newSession()));
+
+ m_newSessionButton = new QToolButton( tabwidget );
+ QToolTip::add(m_newSessionButton,i18n("Click for new standard session\nClick and hold for session menu"));
+ m_newSessionButton->setIconSet( SmallIcon( "tab_new" ) );
+ m_newSessionButton->adjustSize();
+ m_newSessionButton->setPopup( m_tabbarSessionsCommands );
+ connect(m_newSessionButton, SIGNAL(clicked()), SLOT(newSession()));
+ tabwidget->setCornerWidget( m_newSessionButton, BottomLeft );
+ m_newSessionButton->installEventFilter(this);
+
+ m_removeSessionButton = new QToolButton( tabwidget );
+ QToolTip::add(m_removeSessionButton,i18n("Close the current session"));
+ m_removeSessionButton->setIconSet( SmallIconSet( "tab_remove" ) );
+ m_removeSessionButton->adjustSize();
+ m_removeSessionButton->setEnabled(false);
+ connect(m_removeSessionButton, SIGNAL(clicked()), SLOT(confirmCloseCurrentSession()));
+ tabwidget->setCornerWidget( m_removeSessionButton, BottomRight );
+
+ }
+}
+
+bool Konsole::eventFilter( QObject *o, QEvent *ev )
+{
+ if (o == m_newSessionButton)
+ {
+ // Popup the menu when the left mousebutton is pressed and the mouse
+ // is moved by a small distance.
+ if (ev->type() == QEvent::MouseButtonPress)
+ {
+ QMouseEvent* mev = static_cast<QMouseEvent*>(ev);
+ m_newSessionButtonMousePressPos = mev->pos();
+ }
+ else if (ev->type() == QEvent::MouseMove)
+ {
+ QMouseEvent* mev = static_cast<QMouseEvent*>(ev);
+ if ((mev->pos() - m_newSessionButtonMousePressPos).manhattanLength()
+ > KGlobalSettings::dndEventDelay())
+ {
+ m_newSessionButton->openPopup();
+ return true;
+ }
+ }
+ else if (ev->type() == QEvent::ContextMenu)
+ {
+ QMouseEvent* mev = static_cast<QMouseEvent*>(ev);
+ slotTabbarContextMenu(mev->globalPos());
+ return true;
+ }
+ }
+ return KMainWindow::eventFilter(o, ev);
+}
+
+void Konsole::makeBasicGUI()
+{
+ if (kapp->authorize("shell_access")) {
+ m_tabbarSessionsCommands = new KPopupMenu( this );
+ KAcceleratorManager::manage( m_tabbarSessionsCommands );
+ connect(m_tabbarSessionsCommands, SIGNAL(activated(int)), SLOT(newSessionTabbar(int)));
+ }
+
+ m_session = new KPopupMenu(this);
+ KAcceleratorManager::manage( m_session );
+ m_edit = new KPopupMenu(this);
+ KAcceleratorManager::manage( m_edit );
+ m_view = new KPopupMenu(this);
+ KAcceleratorManager::manage( m_view );
+ if (kapp->authorizeKAction("bookmarks"))
+ {
+ bookmarkHandler = new KonsoleBookmarkHandler( this, true );
+ m_bookmarks = bookmarkHandler->menu();
+ // call manually to disable accelerator c-b for add-bookmark initially.
+ bookmarks_menu_check();
+ }
+
+ if (kapp->authorizeKAction("settings")) {
+ m_options = new KPopupMenu(this);
+ KAcceleratorManager::manage( m_options );
+ }
+
+ if (kapp->authorizeKAction("help"))
+ m_help = helpMenu(0, false);
+
+ if (kapp->authorizeKAction("konsole_rmb")) {
+ m_rightButton = new KPopupMenu(this);
+ KAcceleratorManager::manage( m_rightButton );
+ }
+
+ if (kapp->authorizeKAction("bookmarks"))
+ {
+ // Bookmarks that open new sessions.
+ bookmarkHandlerSession = new KonsoleBookmarkHandler( this, false );
+ m_bookmarksSession = bookmarkHandlerSession->menu();
+ }
+
+ // For those who would like to add shortcuts here, be aware that
+ // ALT-key combinations are heavily used by many programs. Thus,
+ // activating shortcuts here means deactivating them in the other
+ // programs.
+
+ if (m_tabbarSessionsCommands)
+ connect(m_tabbarSessionsCommands,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ connect(m_session,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ if (m_options)
+ connect(m_options,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ if (m_help)
+ connect(m_help,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ if (m_rightButton)
+ connect(m_rightButton,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ connect(m_edit,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ connect(m_view,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ if (m_bookmarks)
+ connect(m_bookmarks,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+ if (m_bookmarksSession)
+ connect(m_bookmarksSession,SIGNAL(aboutToShow()),this,SLOT(makeGUI()));
+
+ menubar->insertItem(i18n("Session") , m_session);
+ menubar->insertItem(i18n("Edit"), m_edit);
+ menubar->insertItem(i18n("View"), m_view);
+ if (m_bookmarks)
+ menubar->insertItem(i18n("Bookmarks"), m_bookmarks);
+ if (m_options)
+ menubar->insertItem(i18n("Settings"), m_options);
+ if (m_help)
+ menubar->insertItem(i18n("Help"), m_help);
+
+ m_shortcuts = new KActionCollection(this);
+
+ m_copyClipboard = new KAction(i18n("&Copy"), "editcopy", 0, this,
+ SLOT(slotCopyClipboard()), m_shortcuts, "edit_copy");
+ m_pasteClipboard = new KAction(i18n("&Paste"), "editpaste", Qt::SHIFT+Qt::Key_Insert, this,
+ SLOT(slotPasteClipboard()), m_shortcuts, "edit_paste");
+ m_pasteSelection = new KAction(i18n("Paste Selection"), Qt::CTRL+Qt::SHIFT+Qt::Key_Insert, this,
+ SLOT(slotPasteSelection()), m_shortcuts, "pasteselection");
+
+ m_clearTerminal = new KAction(i18n("C&lear Terminal"), 0, this,
+ SLOT(slotClearTerminal()), m_shortcuts, "clear_terminal");
+ m_resetClearTerminal = new KAction(i18n("&Reset && Clear Terminal"), 0, this,
+ SLOT(slotResetClearTerminal()), m_shortcuts, "reset_clear_terminal");
+ m_findHistory = new KAction(i18n("&Find in History..."), "find", 0, this,
+ SLOT(slotFindHistory()), m_shortcuts, "find_history");
+ m_findHistory->setEnabled(b_histEnabled);
+
+ m_findNext = new KAction(i18n("Find &Next"), "next", 0, this,
+ SLOT(slotFindNext()), m_shortcuts, "find_next");
+ m_findNext->setEnabled(b_histEnabled);
+
+ m_findPrevious = new KAction(i18n("Find Pre&vious"), "previous", 0, this,
+ SLOT(slotFindPrevious()), m_shortcuts, "find_previous");
+ m_findPrevious->setEnabled( b_histEnabled );
+
+ m_saveHistory = new KAction(i18n("S&ave History As..."), "filesaveas", 0, this,
+ SLOT(slotSaveHistory()), m_shortcuts, "save_history");
+ m_saveHistory->setEnabled(b_histEnabled );
+
+ m_clearHistory = new KAction(i18n("Clear &History"), "history_clear", 0, this,
+ SLOT(slotClearHistory()), m_shortcuts, "clear_history");
+ m_clearHistory->setEnabled(b_histEnabled);
+
+ m_clearAllSessionHistories = new KAction(i18n("Clear All H&istories"), "history_clear", 0,
+ this, SLOT(slotClearAllSessionHistories()), m_shortcuts, "clear_all_histories");
+
+ m_detachSession = new KAction(i18n("&Detach Session"), SmallIconSet("tab_breakoff"), 0, this,
+ SLOT(slotDetachSession()), m_shortcuts, "detach_session");
+ m_detachSession->setEnabled(false);
+
+ m_renameSession = new KAction(i18n("&Rename Session..."), Qt::CTRL+Qt::ALT+Qt::Key_S, this,
+ SLOT(slotRenameSession()), m_shortcuts, "rename_session");
+
+ if (kapp->authorizeKAction("zmodem_upload"))
+ m_zmodemUpload = new KAction( i18n( "&ZModem Upload..." ),
+ Qt::CTRL+Qt::ALT+Qt::Key_U, this,
+ SLOT( slotZModemUpload() ),
+ m_shortcuts, "zmodem_upload" );
+
+ monitorActivity = new KToggleAction ( i18n( "Monitor for &Activity" ),
+ SmallIconSet("activity"), 0, this,
+ SLOT( slotToggleMonitor() ), m_shortcuts, "monitor_activity" );
+ monitorActivity->setCheckedState( KGuiItem( i18n( "Stop Monitoring for &Activity" ) ) );
+
+ monitorSilence = new KToggleAction ( i18n( "Monitor for &Silence" ),
+ SmallIconSet("silence"), 0, this,
+ SLOT( slotToggleMonitor() ), m_shortcuts, "monitor_silence" );
+ monitorSilence->setCheckedState( KGuiItem( i18n( "Stop Monitoring for &Silence" ) ) );
+
+ masterMode = new KToggleAction ( i18n( "Send &Input to All Sessions" ), "remote", 0, this,
+ SLOT( slotToggleMasterMode() ), m_shortcuts, "send_input_to_all_sessions" );
+
+ showMenubar = new KToggleAction ( i18n( "Show &Menubar" ), "showmenu", 0, this,
+ SLOT( slotToggleMenubar() ), m_shortcuts, "show_menubar" );
+ showMenubar->setCheckedState( KGuiItem( i18n("Hide &Menubar"), "showmenu", QString::null, QString::null ) );
+
+ m_fullscreen = KStdAction::fullScreen(0, 0, m_shortcuts, this );
+ connect( m_fullscreen,SIGNAL(toggled(bool)), this,SLOT(updateFullScreen(bool)));
+ m_fullscreen->setChecked(b_fullscreen);
+
+ m_saveProfile = new KAction( i18n( "Save Sessions &Profile..." ), SmallIconSet("filesaveas"), 0, this,
+ SLOT( slotSaveSessionsProfile() ), m_shortcuts, "save_sessions_profile" );
+
+ //help menu
+ if (m_help)
+ m_help->setAccel(QKeySequence(),m_help->idAt(0));
+ // Don't steal F1 (handbook) accel (esp. since it not visible in
+ // "Configure Shortcuts").
+
+ m_closeSession = new KAction(i18n("C&lose Session"), "fileclose", 0, this,
+ SLOT(confirmCloseCurrentSession()), m_shortcuts, "close_session");
+ m_print = new KAction(i18n("&Print Screen..."), "fileprint", 0, this, SLOT( slotPrint() ), m_shortcuts, "file_print");
+ m_quit = new KAction(i18n("&Quit"), "exit", 0, this, SLOT( close() ), m_shortcuts, "file_quit");
+
+ KShortcut shortcut(Qt::CTRL+Qt::ALT+Qt::Key_N);
+ shortcut.append(KShortcut(Qt::CTRL+Qt::SHIFT+Qt::Key_N));
+ new KAction(i18n("New Session"), shortcut, this, SLOT(newSession()), m_shortcuts, "new_session");
+ new KAction(i18n("Activate Menu"), Qt::CTRL+Qt::ALT+Qt::Key_M, this, SLOT(activateMenu()), m_shortcuts, "activate_menu");
+ new KAction(i18n("List Sessions"), 0, this, SLOT(listSessions()), m_shortcuts, "list_sessions");
+
+ m_moveSessionLeft = new KAction(i18n("&Move Session Left"), QApplication::reverseLayout() ? "forward" : "back",
+ QApplication::reverseLayout() ? Qt::CTRL+Qt::SHIFT+Qt::Key_Right : Qt::CTRL+Qt::SHIFT+Qt::Key_Left, this,
+ SLOT(moveSessionLeft()), m_shortcuts, "move_session_left");
+ m_moveSessionRight = new KAction(i18n("M&ove Session Right"), QApplication::reverseLayout() ? "back" : "forward",
+ QApplication::reverseLayout() ? Qt::CTRL+Qt::SHIFT+Qt::Key_Left : Qt::CTRL+Qt::SHIFT+Qt::Key_Right, this,
+ SLOT(moveSessionRight()), m_shortcuts, "move_session_right");
+
+ new KAction(i18n("Go to Previous Session"), QApplication::reverseLayout() ? Qt::SHIFT+Qt::Key_Right : Qt::SHIFT+Qt::Key_Left,
+ this, SLOT(prevSession()), m_shortcuts, "previous_session");
+ new KAction(i18n("Go to Next Session"), QApplication::reverseLayout() ? Qt::SHIFT+Qt::Key_Left : Qt::SHIFT+Qt::Key_Right,
+ this, SLOT(nextSession()), m_shortcuts, "next_session");
+
+ for (int i=1;i<13;i++) { // Due to 12 function keys?
+ new KAction(i18n("Switch to Session %1").arg(i), 0, this, SLOT(switchToSession()), m_shortcuts, QString().sprintf("switch_to_session_%02d", i).latin1());
+ }
+
+ new KAction(i18n("Enlarge Font"), 0, this, SLOT(biggerFont()), m_shortcuts, "bigger_font");
+ new KAction(i18n("Shrink Font"), 0, this, SLOT(smallerFont()), m_shortcuts, "smaller_font");
+
+ new KAction(i18n("Toggle Bidi"), Qt::CTRL+Qt::ALT+Qt::Key_B, this, SLOT(toggleBidi()), m_shortcuts, "toggle_bidi");
+
+ // Should we load all *.desktop files now? Required for Session shortcuts.
+ if ( KConfigGroup(KGlobal::config(), "General").readBoolEntry("SessionShortcutsEnabled", false) ) {
+ b_sessionShortcutsEnabled = true;
+ loadSessionCommands();
+ loadScreenSessions();
+ }
+ m_shortcuts->readShortcutSettings();
+
+ m_sessionList = new KPopupMenu(this);
+ KAcceleratorManager::manage( m_sessionList );
+ connect(m_sessionList, SIGNAL(activated(int)), SLOT(activateSession(int)));
+}
+
+/**
+ Make menubar available via escape sequence (Default: Ctrl+Alt+m)
+ */
+void Konsole::activateMenu()
+{
+ menubar->activateItemAt(0);
+ if ( !showMenubar->isChecked() ) {
+ menubar->show();
+ showMenubar->setChecked(true);
+ }
+}
+
+/**
+ Ask for Quit confirmation - Martijn Klingens
+ Asks for confirmation if there are still open shells when the 'Warn on
+ Quit' option is set.
+ */
+bool Konsole::queryClose()
+{
+ if(kapp->sessionSaving())
+ // saving session - do not even think about doing any kind of cleanup here
+ return true;
+
+ if (sessions.count() == 0)
+ return true;
+
+ if ( b_warnQuit)
+ {
+ if(sessions.count()>1) {
+ switch (
+ KMessageBox::warningYesNoCancel(
+ this,
+ i18n( "You have open sessions (besides the current one). "
+ "These will be killed if you continue.\n"
+ "Are you sure you want to quit?" ),
+ i18n("Really Quit?"),
+ KStdGuiItem::quit(),
+ KGuiItem(i18n("C&lose Session"),"fileclose")
+ )
+ ) {
+ case KMessageBox::Yes :
+ break;
+ case KMessageBox::No :
+ { closeCurrentSession();
+ return false;
+ }
+ break;
+ case KMessageBox::Cancel : return false;
+ }
+ }
+ }
+
+ // WABA: Don't close if there are any sessions left.
+ // Tell them to go away.
+ sessions.first();
+ while(sessions.current())
+ {
+ sessions.current()->closeSession();
+ sessions.next();
+ }
+
+ m_closeTimeout.start(1500, true);
+ return false;
+}
+
+void Konsole::slotCouldNotClose()
+{
+ int result = KMessageBox::warningContinueCancel(this,
+ i18n("The application running in Konsole does not respond to the close request. "
+ "Do you want Konsole to close anyway?"),
+ i18n("Application Does Not Respond"),
+ KStdGuiItem::close());
+ if (result == KMessageBox::Continue)
+ {
+ while(sessions.first())
+ {
+ doneSession(sessions.current());
+ }
+ }
+}
+
+/**
+ sets application window to a size based on columns X lines of the te
+ guest widget. Call with (0,0) for setting default size.
+*/
+
+void Konsole::setColLin(int columns, int lines)
+{
+ if ((columns==0) || (lines==0))
+ {
+ if (b_fixedSize || defaultSize.isEmpty())
+ {
+ // not in config file : set default value
+ columns = 80;
+ lines = 24;
+ }
+ }
+
+ if ((columns==0) || (lines==0))
+ {
+ resize(defaultSize);
+ }
+ else
+ {
+ if (b_fixedSize)
+ te->setFixedSize(columns, lines);
+ else
+ te->setSize(columns, lines);
+ adjustSize();
+ if (b_fixedSize)
+ setFixedSize(sizeHint());
+ notifySize(columns, lines); // set menu items
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void Konsole::configureRequest(TEWidget* _te, int state, int x, int y)
+{
+ if (!m_menuCreated)
+ makeGUI();
+ KPopupMenu *menu = (state & ControlButton) ? m_session : m_rightButton;
+ if (menu)
+ menu->popup(_te->mapToGlobal(QPoint(x,y)));
+}
+
+void Konsole::slotTabContextMenu(QWidget* _te, const QPoint & pos)
+{
+ if (!m_menuCreated)
+ makeGUI();
+
+ m_contextMenuSession = sessions.at( tabwidget->indexOf( _te ) );
+
+ m_tabDetachSession->setEnabled( tabwidget->count()>1 );
+
+ m_tabMonitorActivity->setChecked( m_contextMenuSession->isMonitorActivity() );
+ m_tabMonitorSilence->setChecked( m_contextMenuSession->isMonitorSilence() );
+ m_tabMasterMode->setChecked( m_contextMenuSession->isMasterMode() );
+
+ m_tabPopupTabsMenu->clear();
+ int counter=0;
+ for (TESession *ses = sessions.first(); ses; ses = sessions.next()) {
+ QString title=ses->Title();
+ m_tabPopupTabsMenu->insertItem(SmallIcon(ses->IconName()),title.replace('&',"&&"),counter++);
+ }
+
+ m_tabPopupMenu->popup( pos );
+}
+
+void Konsole::slotTabDetachSession() {
+ detachSession( m_contextMenuSession );
+}
+
+void Konsole::slotTabRenameSession() {
+ renameSession(m_contextMenuSession);
+}
+
+void Konsole::slotTabSelectColor()
+{
+ QColor color = tabwidget->tabColor( m_contextMenuSession->widget() );
+ int result = KColorDialog::getColor( color );
+
+ if ( result == KColorDialog::Accepted )
+ tabwidget->setTabColor(m_contextMenuSession->widget(), color);
+}
+
+void Konsole::slotTabToggleMonitor()
+{
+ m_contextMenuSession->setMonitorActivity( m_tabMonitorActivity->isChecked() );
+ m_contextMenuSession->setMonitorSilence( m_tabMonitorSilence->isChecked() );
+ notifySessionState( m_contextMenuSession, NOTIFYNORMAL );
+ if (m_contextMenuSession==se) {
+ monitorActivity->setChecked( m_tabMonitorActivity->isChecked() );
+ monitorSilence->setChecked( m_tabMonitorSilence->isChecked() );
+ }
+}
+
+void Konsole::slotTabToggleMasterMode()
+{
+ setMasterMode( m_tabMasterMode->isChecked(), m_contextMenuSession );
+}
+
+void Konsole::slotTabCloseSession()
+{
+ confirmCloseCurrentSession(m_contextMenuSession);
+}
+
+void Konsole::slotTabbarContextMenu(const QPoint & pos)
+{
+ if (!m_menuCreated)
+ makeGUI();
+
+ if ( m_tabbarPopupMenu ) m_tabbarPopupMenu->popup( pos );
+}
+
+void Konsole::slotTabSetViewOptions(int mode)
+{
+ m_tabViewMode = TabViewModes(mode);
+
+ for(int i = 0; i < tabwidget->count(); i++) {
+
+ QWidget *page = tabwidget->page(i);
+ QIconSet icon = iconSetForSession(sessions.at(i));
+ QString title;
+ if (b_matchTabWinTitle)
+ title = sessions.at(i)->fullTitle();
+ else
+ title = sessions.at(i)->Title();
+
+ title=title.replace('&',"&&");
+ switch(mode) {
+ case ShowIconAndText:
+ tabwidget->changeTab(page, icon, title);
+ break;
+ case ShowTextOnly:
+ tabwidget->changeTab(page, QIconSet(), title);
+ break;
+ case ShowIconOnly:
+ tabwidget->changeTab(page, icon, QString::null);
+ break;
+ }
+ }
+}
+
+void Konsole::slotToggleAutoResizeTabs()
+{
+ b_autoResizeTabs = !b_autoResizeTabs;
+
+ tabwidget->setAutomaticResizeTabs( b_autoResizeTabs );
+}
+
+void Konsole::slotTabbarToggleDynamicHide()
+{
+ b_dynamicTabHide=!b_dynamicTabHide;
+ if (b_dynamicTabHide && tabwidget->count()==1)
+ tabwidget->setTabBarHidden(true);
+ else
+ tabwidget->setTabBarHidden(false);
+}
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* Configuration */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void Konsole::slotSaveSessionsProfile()
+{
+ bool ok;
+
+ QString prof = KInputDialog::getText( i18n( "Save Sessions Profile" ),
+ i18n( "Enter name under which the profile should be saved:" ),
+ QString::null, &ok, this );
+ if ( ok ) {
+ QString path = locateLocal( "data",
+ QString::fromLatin1( "konsole/profiles/" ) + prof,
+ KGlobal::instance() );
+
+ if ( QFile::exists( path ) )
+ QFile::remove( path );
+
+ KSimpleConfig cfg( path );
+ savePropertiesInternal(&cfg,1);
+ saveMainWindowSettings(&cfg);
+ }
+}
+
+void Konsole::saveProperties(KConfig* config) {
+ uint counter=0;
+ uint active=0;
+ QString key;
+
+ if (config != KGlobal::config())
+ {
+ // called by the session manager
+ config->writeEntry("numSes",sessions.count());
+ sessions.first();
+ while(counter < sessions.count())
+ {
+ key = QString("Title%1").arg(counter);
+
+ config->writeEntry(key, sessions.current()->Title());
+ key = QString("Schema%1").arg(counter);
+ config->writeEntry(key, colors->find( sessions.current()->schemaNo() )->relPath());
+ key = QString("Encoding%1").arg(counter);
+ config->writeEntry(key, sessions.current()->encodingNo());
+ key = QString("Args%1").arg(counter);
+ config->writeEntry(key, sessions.current()->getArgs());
+ key = QString("Pgm%1").arg(counter);
+ config->writeEntry(key, sessions.current()->getPgm());
+ key = QString("SessionFont%1").arg(counter);
+ config->writeEntry(key, (sessions.current()->widget())->getVTFont());
+ key = QString("Term%1").arg(counter);
+ config->writeEntry(key, sessions.current()->Term());
+ key = QString("KeyTab%1").arg(counter);
+ config->writeEntry(key, sessions.current()->keymap());
+ key = QString("Icon%1").arg(counter);
+ config->writeEntry(key, sessions.current()->IconName());
+ key = QString("MonitorActivity%1").arg(counter);
+ config->writeEntry(key, sessions.current()->isMonitorActivity());
+ key = QString("MonitorSilence%1").arg(counter);
+ config->writeEntry(key, sessions.current()->isMonitorSilence());
+ key = QString("MasterMode%1").arg(counter);
+ config->writeEntry(key, sessions.current()->isMasterMode());
+ key = QString("TabColor%1").arg(counter);
+ config->writeEntry(key, tabwidget->tabColor((sessions.current())->widget()));
+ key = QString("History%1").arg(counter);
+ config->writeEntry(key, sessions.current()->history().getSize());
+ key = QString("HistoryEnabled%1").arg(counter);
+ config->writeEntry(key, sessions.current()->history().isOn());
+
+ QString cwd=sessions.current()->getCwd();
+ if (cwd.isEmpty())
+ cwd=sessions.current()->getInitial_cwd();
+ key = QString("Cwd%1").arg(counter);
+ config->writePathEntry(key, cwd);
+
+ if (sessions.current()==se)
+ active=counter;
+ sessions.next();
+ counter++;
+ }
+ }
+ else
+ {
+ config->setDesktopGroup();
+ config->writeEntry("TabColor", tabwidget->tabColor(se->widget()));
+ }
+ config->writeEntry("Fullscreen",b_fullscreen);
+ config->writeEntry("defaultfont", (se->widget())->getVTFont());
+ s_kconfigSchema = colors->find( se->schemaNo() )->relPath();
+ config->writeEntry("schema",s_kconfigSchema);
+ config->writeEntry("scrollbar",n_scroll);
+ config->writeEntry("tabbar",n_tabbar);
+ config->writeEntry("bellmode",n_bell);
+ config->writeEntry("keytab",KeyTrans::find(n_defaultKeytab)->id());
+ config->writeEntry("ActiveSession", active);
+ config->writeEntry("DefaultSession", m_defaultSessionFilename);
+ config->writeEntry("TabViewMode", int(m_tabViewMode));
+ config->writeEntry("DynamicTabHide", b_dynamicTabHide);
+ config->writeEntry("AutoResizeTabs", b_autoResizeTabs);
+
+ if (selectSetEncoding)
+ {
+ QString encoding = KGlobal::charsets()->encodingForName(selectSetEncoding->currentText());
+ config->writeEntry("EncodingName", encoding);
+ } else { // This will not always work (ie 'winsami' saves as 'ws2')
+ if (se) config->writeEntry("EncodingName", se->encoding());
+ }
+
+ if (se) {
+ config->writeEntry("history", se->history().getSize());
+ config->writeEntry("historyenabled", b_histEnabled);
+ }
+
+ config->writeEntry("class",name());
+ if (config != KGlobal::config())
+ {
+ saveMainWindowSettings(config);
+ }
+
+ if (!s_workDir.isEmpty())
+ config->writePathEntry("workdir", s_workDir);
+
+ // Set the new default font
+ defaultFont = se->widget()->getVTFont();
+}
+
+
+// Called by constructor (with config = KGlobal::config())
+// and by session-management (with config = sessionconfig).
+// So it has to apply the settings when reading them.
+void Konsole::readProperties(KConfig* config)
+{
+ readProperties(config, QString::null, false);
+}
+
+// If --type option was given, load the corresponding schema instead of
+// default
+//
+// When globalConfigOnly is true only the options that are shared among all
+// konsoles are being read.
+void Konsole::readProperties(KConfig* config, const QString &schema, bool globalConfigOnly)
+{
+
+ if (config==KGlobal::config())
+ {
+ config->setDesktopGroup();
+ b_warnQuit=config->readBoolEntry( "WarnQuit", true );
+ b_allowResize=config->readBoolEntry( "AllowResize", false);
+ b_bidiEnabled = config->readBoolEntry("EnableBidi",false);
+ s_word_seps= config->readEntry("wordseps",":@-./_~");
+ b_framevis = config->readBoolEntry("has frame",true);
+ QPtrList<TEWidget> tes = activeTEs();
+ for (TEWidget *_te = tes.first(); _te; _te = tes.next()) {
+ _te->setWordCharacters(s_word_seps);
+ _te->setTerminalSizeHint( config->readBoolEntry("TerminalSizeHint",false) );
+ _te->setFrameStyle( b_framevis?(QFrame::WinPanel|QFrame::Sunken):QFrame::NoFrame );
+ _te->setBlinkingCursor(config->readBoolEntry("BlinkingCursor",false));
+ _te->setCtrlDrag(config->readBoolEntry("CtrlDrag",true));
+ _te->setCutToBeginningOfLine(config->readBoolEntry("CutToBeginningOfLine",false));
+ _te->setLineSpacing( config->readUnsignedNumEntry( "LineSpacing", 0 ) );
+ _te->setBidiEnabled(b_bidiEnabled);
+ }
+
+ monitorSilenceSeconds=config->readUnsignedNumEntry("SilenceSeconds", 10);
+ for (TESession *ses = sessions.first(); ses; ses = sessions.next())
+ ses->setMonitorSilenceSeconds(monitorSilenceSeconds);
+
+ b_xonXoff = config->readBoolEntry("XonXoff",false);
+ b_matchTabWinTitle = config->readBoolEntry("MatchTabWinTitle",false);
+ config->setGroup("UTMP");
+ b_addToUtmp = config->readBoolEntry("AddToUtmp",true);
+ config->setDesktopGroup();
+
+ // Do not set a default value; this allows the System-wide Scheme
+ // to set the tab text color.
+ m_tabColor = config->readColorEntry("TabColor");
+ }
+
+ if (!globalConfigOnly)
+ {
+ n_defaultKeytab=KeyTrans::find(config->readEntry("keytab","default"))->numb(); // act. the keytab for this session
+ b_fullscreen = config->readBoolEntry("Fullscreen",false);
+ n_scroll = QMIN(config->readUnsignedNumEntry("scrollbar",TEWidget::SCRRIGHT),2);
+ n_tabbar = QMIN(config->readUnsignedNumEntry("tabbar",TabBottom),2);
+ n_bell = QMIN(config->readUnsignedNumEntry("bellmode",TEWidget::BELLSYSTEM),3);
+
+ // Options that should be applied to all sessions /////////////
+
+ // (1) set menu items and Konsole members
+
+ QFont tmpFont = KGlobalSettings::fixedFont();
+ defaultFont = config->readFontEntry("defaultfont", &tmpFont);
+
+ //set the schema
+ s_kconfigSchema=config->readEntry("schema");
+ ColorSchema* sch = colors->find(schema.isEmpty() ? s_kconfigSchema : schema);
+ if (!sch)
+ {
+ sch = (ColorSchema*)colors->at(0); //the default one
+ kdWarning() << "Could not find schema named " <<s_kconfigSchema<<"; using "<<sch->relPath()<<endl;
+ s_kconfigSchema = sch->relPath();
+ }
+ if (sch->hasSchemaFileChanged()) sch->rereadSchemaFile();
+ s_schema = sch->relPath();
+ curr_schema = sch->numb();
+ pmPath = sch->imagePath();
+
+ if (te) {
+ if (sch->useTransparency())
+ {
+ if (!rootxpms[te])
+ rootxpms.insert( te, new KRootPixmap(te) );
+ rootxpms[te]->setFadeEffect(sch->tr_x(), QColor(sch->tr_r(), sch->tr_g(), sch->tr_b()));
+ }
+ else
+ {
+ if (rootxpms[te]) {
+ delete rootxpms[te];
+ rootxpms.remove(te);
+ }
+ pixmap_menu_activated(sch->alignment());
+ }
+
+ te->setColorTable(sch->table()); //FIXME: set twice here to work around a bug
+ te->setColorTable(sch->table());
+ te->setScrollbarLocation(n_scroll);
+ te->setBellMode(n_bell);
+ }
+
+ // History
+ m_histSize = config->readNumEntry("history",DEFAULT_HISTORY_SIZE);
+ b_histEnabled = config->readBoolEntry("historyenabled",true);
+
+ // Tab View Mode
+ m_tabViewMode = TabViewModes(config->readNumEntry("TabViewMode", ShowIconAndText));
+ b_dynamicTabHide = config->readBoolEntry("DynamicTabHide", false);
+ b_autoResizeTabs = config->readBoolEntry("AutoResizeTabs", false);
+
+ s_encodingName = config->readEntry( "EncodingName", "" ).lower();
+
+ // The scrollbar location only needs to be changed when the given
+ // profile scrollbar entry differs from the konsolerc scrollbar entry.
+ QPtrList<TEWidget> tes = activeTEs();
+ for (TEWidget *_te = tes.first(); _te; _te = tes.next()) {
+ if (_te->getScrollbarLocation() != n_scroll)
+ _te->setScrollbarLocation(n_scroll);
+ }
+ }
+
+ if (m_menuCreated)
+ {
+ applySettingsToGUI();
+ activateSession();
+ };
+}
+
+void Konsole::applySettingsToGUI()
+{
+ if (!m_menuCreated) return;
+ if (m_options)
+ {
+// setFont();
+ notifySize(te->Columns(), te->Lines());
+ selectTabbar->setCurrentItem(n_tabbar);
+ showMenubar->setChecked(!menuBar()->isHidden());
+ selectScrollbar->setCurrentItem(n_scroll);
+ selectBell->setCurrentItem(n_bell);
+ selectSetEncoding->setCurrentItem( se->encodingNo() );
+ updateRMBMenu();
+ }
+ updateKeytabMenu();
+ tabwidget->setAutomaticResizeTabs( b_autoResizeTabs );
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* */
+/* */
+/* ------------------------------------------------------------------------- */
+
+void Konsole::bookmarks_menu_check()
+{
+ bool state = false;
+ if ( se )
+ state = !(se->getCwd().isEmpty());
+
+ KAction *addBookmark = actionCollection()->action( "add_bookmark" );
+ if ( !addBookmark )
+ {
+ return;
+ }
+ addBookmark->setEnabled( state );
+}
+
+void Konsole::pixmap_menu_activated(int item, TEWidget* tewidget)
+{
+ if (!tewidget)
+ tewidget=te;
+ if (item <= 1) pmPath = "";
+ QPixmap pm(pmPath);
+ if (pm.isNull()) {
+ pmPath = "";
+ item = 1;
+ tewidget->setBackgroundColor(tewidget->getDefaultBackColor());
+ return;
+ }
+ // FIXME: respect scrollbar (instead of te->size)
+ n_render= item;
+ switch (item)
+ {
+ case 1: // none
+ case 2: // tile
+ tewidget->setBackgroundPixmap(pm);
+ break;
+ case 3: // center
+ { QPixmap bgPixmap;
+ bgPixmap.resize(tewidget->size());
+ bgPixmap.fill(tewidget->getDefaultBackColor());
+ bitBlt( &bgPixmap, ( tewidget->size().width() - pm.width() ) / 2,
+ ( tewidget->size().height() - pm.height() ) / 2,
+ &pm, 0, 0,
+ pm.width(), pm.height() );
+
+ tewidget->setBackgroundPixmap(bgPixmap);
+ }
+ break;
+ case 4: // full
+ {
+ float sx = (float)tewidget->size().width() / pm.width();
+ float sy = (float)tewidget->size().height() / pm.height();
+ QWMatrix matrix;
+ matrix.scale( sx, sy );
+ tewidget->setBackgroundPixmap(pm.xForm( matrix ));
+ }
+ break;
+ default: // oops
+ n_render = 1;
+ }
+}
+
+void Konsole::slotSelectBell() {
+ n_bell = selectBell->currentItem();
+ te->setBellMode(n_bell);
+}
+
+void Konsole::slotSelectScrollbar() {
+ if (m_menuCreated)
+ n_scroll = selectScrollbar->currentItem();
+
+ QPtrList<TEWidget> tes = activeTEs();
+ for (TEWidget *_te = tes.first(); _te; _te = tes.next())
+ _te->setScrollbarLocation(n_scroll);
+ activateSession(); // maybe helps in bg
+}
+
+void Konsole::checkBitmapFonts()
+{
+ {
+ QFont f;
+ f.setRawName("-misc-console-medium-r-normal--16-160-72-72-c-80-iso10646-1");
+ QFontInfo fi( f );
+ if ( !fi.exactMatch() )
+ b_installBitmapFonts = true;
+ }
+ {
+ QFont f;
+ f.setRawName("-misc-fixed-medium-r-normal--15-140-75-75-c-90-iso10646-1");
+ QFontInfo fi( f );
+ if ( !fi.exactMatch() )
+ b_installBitmapFonts = true;
+ }
+}
+
+// In KDE 3.5, Konsole only allows the user to pick a font via
+// KFontDialog. This causes problems with the bdf/pcf files
+// distributed with Konsole (console8x16 and 9x15).
+void Konsole::slotInstallBitmapFonts()
+{
+ if ( !b_installBitmapFonts )
+ return;
+
+ QStringList sl_installFonts;
+ {
+ QFont f;
+ f.setRawName("-misc-console-medium-r-normal--16-160-72-72-c-80-iso10646-1");
+ QFontInfo fi( f );
+ if ( !fi.exactMatch() )
+ sl_installFonts << "console8x16.pcf.gz";
+ }
+ {
+ QFont f;
+ f.setRawName("-misc-fixed-medium-r-normal--15-140-75-75-c-90-iso10646-1");
+ QFontInfo fi( f );
+ if ( !fi.exactMatch() )
+ sl_installFonts << "9x15.pcf.gz";
+ }
+
+ if ( !sl_installFonts.isEmpty() )
+ {
+ if ( KMessageBox::questionYesNoList( this,
+ i18n( "If you want to use the bitmap fonts distributed with Konsole, they must be installed. After installation, you must restart Konsole to use them. Do you want to install the fonts listed below into fonts:/Personal?" ),
+ sl_installFonts,
+ i18n( "Install Bitmap Fonts?" ),
+ KGuiItem( i18n("&Install" ) ),
+ i18n("Do Not Install") ) == KMessageBox::Yes )
+ {
+ for ( QStringList::iterator it = sl_installFonts.begin();
+ it != sl_installFonts.end(); ++it )
+ {
+ QString sf = "fonts/" + *it;
+ if ( KIO::NetAccess::copy( locate( "appdata", sf ),
+ "fonts:/Personal/", 0 ) )
+ {
+ b_installBitmapFonts = false;
+ // TODO: Remove the Install from the Fonts sub-menu.
+ } else {
+ KMessageBox::error( this, i18n( "Could not install %1 into fonts:/Personal/" ).arg( *it ), i18n( "Error" ) );
+ }
+ }
+ }
+ }
+
+}
+
+void Konsole::slotSelectFont() {
+ if ( !se ) return;
+
+ QFont font = se->widget()->getVTFont();
+ if ( KFontDialog::getFont( font, true ) != QDialog::Accepted )
+ return;
+
+ se->widget()->setVTFont( font );
+// activateSession(); // activates the current
+}
+
+void Konsole::schema_menu_activated(int item)
+{
+ if (!se) return;
+ setSchema(item);
+ activateSession(); // activates the current
+}
+
+/* slot */ void Konsole::schema_menu_check()
+{
+ if (colors->checkSchemas())
+ {
+ colors->sort();
+ updateSchemaMenu();
+ }
+}
+
+void Konsole::updateSchemaMenu()
+{
+ m_schema->clear();
+ for (int i = 0; i < (int) colors->count(); i++)
+ {
+ ColorSchema* s = (ColorSchema*)colors->at(i);
+ assert( s );
+ QString title=s->title();
+ m_schema->insertItem(title.replace('&',"&&"),s->numb(),0);
+ }
+
+ if (te && se)
+ {
+ m_schema->setItemChecked(se->schemaNo(),true);
+ }
+
+}
+
+void Konsole::updateKeytabMenu()
+{
+ if (m_menuCreated)
+ {
+ m_keytab->setItemChecked(n_keytab,false);
+ m_keytab->setItemChecked(se->keymapNo(),true);
+ };
+ n_keytab = se->keymapNo();
+}
+
+void Konsole::keytab_menu_activated(int item)
+{
+ se->setKeymapNo(item);
+ n_defaultKeytab = item;
+ updateKeytabMenu();
+}
+
+/**
+ Toggle the Menubar visibility
+ */
+void Konsole::slotToggleMenubar() {
+ if ( showMenubar->isChecked() )
+ menubar->show();
+ else
+ menubar->hide();
+ if (b_fixedSize)
+ {
+ adjustSize();
+ setFixedSize(sizeHint());
+ }
+ if (!showMenubar->isChecked()) {
+ setCaption(i18n("Use the right mouse button to bring back the menu"));
+ QTimer::singleShot(5000,this,SLOT(updateTitle()));
+ }
+ updateRMBMenu();
+}
+
+void Konsole::initTEWidget(TEWidget* new_te, TEWidget* default_te)
+{
+ new_te->setWordCharacters(default_te->wordCharacters());
+ new_te->setTerminalSizeHint(default_te->isTerminalSizeHint());
+ new_te->setTerminalSizeStartup(false);
+ new_te->setFrameStyle(b_framevis?(QFrame::WinPanel|QFrame::Sunken):QFrame::NoFrame);
+ new_te->setBlinkingCursor(default_te->blinkingCursor());
+ new_te->setCtrlDrag(default_te->ctrlDrag());
+ new_te->setCutToBeginningOfLine(default_te->cutToBeginningOfLine());
+ new_te->setLineSpacing(default_te->lineSpacing());
+ new_te->setBidiEnabled(b_bidiEnabled);
+
+ new_te->setVTFont(default_te->font());
+ new_te->setScrollbarLocation(n_scroll);
+ new_te->setBellMode(default_te->bellMode());
+
+ new_te->setMinimumSize(150,70);
+}
+
+void Konsole::createSessionTab(TEWidget *widget, const QIconSet &iconSet,
+ const QString &text, int index)
+{
+ switch(m_tabViewMode) {
+ case ShowIconAndText:
+ tabwidget->insertTab(widget, iconSet, text, index);
+ break;
+ case ShowTextOnly:
+ tabwidget->insertTab(widget, QIconSet(), text, index);
+ break;
+ case ShowIconOnly:
+ tabwidget->insertTab(widget, iconSet, QString::null, index);
+ break;
+ }
+ if ( m_tabColor.isValid() )
+ tabwidget->setTabColor(widget, m_tabColor);
+}
+
+QIconSet Konsole::iconSetForSession(TESession *session) const
+{
+ if (m_tabViewMode == ShowTextOnly)
+ return QIconSet();
+ return SmallIconSet(session->isMasterMode() ? "remote" : session->IconName());
+}
+
+
+/**
+ Toggle the Tabbar visibility
+ */
+void Konsole::slotSelectTabbar() {
+ if (m_menuCreated)
+ n_tabbar = selectTabbar->currentItem();
+
+ if ( n_tabbar == TabNone ) { // Hide tabbar
+ tabwidget->setTabBarHidden( true );
+ } else {
+ if ( tabwidget->isTabBarHidden() )
+ tabwidget->setTabBarHidden( false );
+ if ( n_tabbar == TabTop )
+ tabwidget->setTabPosition( QTabWidget::Top );
+ else
+ tabwidget->setTabPosition( QTabWidget::Bottom );
+ }
+
+/* FIXME: Still necessary ? */
+ QPtrDictIterator<KRootPixmap> it(rootxpms);
+ for (;it.current();++it)
+ it.current()->repaint(true);
+
+ if (b_fixedSize)
+ {
+ adjustSize();
+ setFixedSize(sizeHint());
+ }
+}
+
+void Konsole::slotSaveSettings()
+{
+ KConfig *config = KGlobal::config();
+ config->setDesktopGroup();
+ saveProperties(config);
+ saveMainWindowSettings(config);
+ config->sync();
+}
+
+void Konsole::slotConfigureNotifications()
+{
+ KNotifyDialog::configure(this, "Notification Configuration Dialog");
+}
+
+void Konsole::slotConfigureKeys()
+{
+ KKeyDialog::configure(m_shortcuts);
+ m_shortcuts->writeShortcutSettings();
+
+ QStringList ctrlKeys;
+
+ for ( uint i = 0; i < m_shortcuts->count(); i++ )
+ {
+ KShortcut shortcut = (m_shortcuts->action( i ))->shortcut();
+ for( uint j = 0; j < shortcut.count(); j++)
+ {
+ const KKey &key = shortcut.seq(j).key(0); // First Key of KeySequence
+ if (key.modFlags() == KKey::CTRL)
+ ctrlKeys += key.toString();
+ }
+
+ // Are there any shortcuts for Session Menu entries?
+ if ( !b_sessionShortcutsEnabled &&
+ m_shortcuts->action( i )->shortcut().count() &&
+ QString(m_shortcuts->action( i )->name()).startsWith("SSC_") ) {
+ b_sessionShortcutsEnabled = true;
+ KConfigGroup group(KGlobal::config(), "General");
+ group.writeEntry("SessionShortcutsEnabled", true);
+ }
+ }
+
+ if (!ctrlKeys.isEmpty())
+ {
+ ctrlKeys.sort();
+ KMessageBox::informationList( this, i18n( "You have chosen one or more Ctrl+<key> combinations to be used as shortcuts. "
+ "As a result these key combinations will no longer be passed to the command shell "
+ "or to applications that run inside Konsole. "
+ "This can have the unintended consequence that functionality that would otherwise be "
+ "bound to these key combinations is no longer accessible."
+ "\n\n"
+ "You may wish to reconsider your choice of keys and use Alt+Ctrl+<key> or Ctrl+Shift+<key> instead."
+ "\n\n"
+ "You are currently using the following Ctrl+<key> combinations:" ),
+ ctrlKeys,
+ i18n( "Choice of Shortcut Keys" ), 0);
+ }
+}
+
+void Konsole::slotConfigure()
+{
+ QStringList args;
+ args << "kcmkonsole";
+ KApplication::kdeinitExec( "kcmshell", args );
+}
+
+void Konsole::reparseConfiguration()
+{
+ KGlobal::config()->reparseConfiguration();
+ readProperties(KGlobal::config(), QString::null, true);
+
+ // The .desktop files may have been changed by user...
+ b_sessionShortcutsMapped = false;
+
+ // Mappings may have to be changed...get a fresh mapper.
+ disconnect( sessionNumberMapper, SIGNAL( mapped( int ) ),
+ this, SLOT( newSessionTabbar( int ) ) );
+ delete sessionNumberMapper;
+ sessionNumberMapper = new QSignalMapper( this );
+ connect( sessionNumberMapper, SIGNAL( mapped( int ) ),
+ this, SLOT( newSessionTabbar( int ) ) );
+
+ sl_sessionShortCuts.clear();
+ buildSessionMenus();
+
+ // FIXME: Should be a better way to traverse KActionCollection
+ uint count = m_shortcuts->count();
+ for ( uint i = 0; i < count; i++ )
+ {
+ KAction* action = m_shortcuts->action( i );
+ bool b_foundSession = false;
+ if ( QString(action->name()).startsWith("SSC_") ) {
+ QString name = QString(action->name());
+
+ // Check to see if shortcut's session has been loaded.
+ for ( QStringList::Iterator it = sl_sessionShortCuts.begin(); it != sl_sessionShortCuts.end(); ++it ) {
+ if ( QString::compare( *it, name ) == 0 ) {
+ b_foundSession = true;
+ break;
+ }
+ }
+ if ( ! b_foundSession ) {
+ action->setShortcut( KShortcut() ); // Clear shortcut
+ m_shortcuts->writeShortcutSettings();
+ delete action; // Remove Action and Accel
+ if ( i == 0 ) i = 0; // Reset index
+ else i--;
+ count--; // = m_shortcuts->count();
+ }
+ }
+ }
+
+ m_shortcuts->readShortcutSettings();
+
+ // User may have changed Schema->Set as default schema
+ s_kconfigSchema = KGlobal::config()->readEntry("schema");
+ ColorSchema* sch = colors->find(s_kconfigSchema);
+ if (!sch)
+ {
+ sch = (ColorSchema*)colors->at(0); //the default one
+ kdWarning() << "Could not find schema named " <<s_kconfigSchema<<"; using "<<sch->relPath()<<endl;
+ s_kconfigSchema = sch->relPath();
+ }
+ if (sch->hasSchemaFileChanged()) sch->rereadSchemaFile();
+ s_schema = sch->relPath();
+ curr_schema = sch->numb();
+ pmPath = sch->imagePath();
+
+ for (TESession *_se = sessions.first(); _se; _se = sessions.next()) {
+ ColorSchema* s = colors->find( _se->schemaNo() );
+ if (s) {
+ if (s->hasSchemaFileChanged())
+ s->rereadSchemaFile();
+ setSchema(s,_se->widget());
+ }
+ }
+}
+
+// Called via emulation via session
+void Konsole::changeTabTextColor( TESession* ses, int rgb )
+{
+ if ( !ses ) return;
+ QColor color;
+ color.setRgb( rgb );
+ if ( !color.isValid() ) {
+ kdWarning()<<" Invalid RGB color "<<rgb<<endl;
+ return;
+ }
+ tabwidget->setTabColor( ses->widget(), color );
+}
+
+// Called from emulation
+void Konsole::changeColLin(int columns, int lines)
+{
+ if (b_allowResize && !b_fixedSize) {
+ setColLin(columns, lines);
+ te->update();
+ }
+}
+
+// Called from emulation
+void Konsole::changeColumns(int columns)
+{
+ if (b_allowResize) {
+ setColLin(columns,te->Lines());
+ te->update();
+ }
+}
+
+void Konsole::slotSelectSize() {
+ int item = selectSize->currentItem();
+ if (b_fullscreen)
+ setFullScreen( false );
+
+ switch (item) {
+ case 0: setColLin(40,15); break;
+ case 1: setColLin(80,24); break;
+ case 2: setColLin(80,25); break;
+ case 3: setColLin(80,40); break;
+ case 4: setColLin(80,52); break;
+ case 6: SizeDialog dlg(te->Columns(), te->Lines(), this);
+ if (dlg.exec())
+ setColLin(dlg.columns(),dlg.lines());
+ break;
+ }
+}
+
+void Konsole::notifySize(int columns, int lines)
+{
+ if (selectSize)
+ {
+ selectSize->blockSignals(true);
+ selectSize->setCurrentItem(-1);
+ if (columns==40&&lines==15)
+ selectSize->setCurrentItem(0);
+ else if (columns==80&&lines==24)
+ selectSize->setCurrentItem(1);
+ else if (columns==80&&lines==25)
+ selectSize->setCurrentItem(2);
+ else if (columns==80&&lines==40)
+ selectSize->setCurrentItem(3);
+ else if (columns==80&&lines==52)
+ selectSize->setCurrentItem(4);
+ else
+ selectSize->setCurrentItem(5);
+ selectSize->blockSignals(false);
+ }
+
+ if (n_render >= 3) pixmap_menu_activated(n_render);
+}
+
+void Konsole::updateTitle(TESession* _se)
+{
+ if ( !_se )
+ _se = se;
+
+ if (_se == se)
+ {
+ setCaption( _se->fullTitle() );
+ setIconText( _se->IconText() );
+ }
+ tabwidget->setTabIconSet(_se->widget(), iconSetForSession(_se));
+ QString icon = _se->IconName();
+ KRadioAction *ra = session2action.find(_se);
+ if (ra && (ra->icon() != icon))
+ ra->setIcon(icon);
+ if (m_tabViewMode == ShowIconOnly)
+ tabwidget->changeTab( _se->widget(), QString::null );
+ else if (b_matchTabWinTitle)
+ tabwidget->setTabLabel( _se->widget(), _se->fullTitle().replace('&',"&&"));
+}
+
+void Konsole::initSessionFont(QFont font) {
+ te->setVTFont( font );
+}
+
+void Konsole::initSessionKeyTab(const QString &keyTab) {
+ se->setKeymap(keyTab);
+ updateKeytabMenu();
+}
+
+void Konsole::initFullScreen()
+{
+ //This function is to be called from main.C to initialize the state of the Konsole (fullscreen or not). It doesn't appear to work
+ //from inside the Konsole constructor
+ if (b_fullscreen) {
+ setColLin(0,0);
+ }
+ setFullScreen(b_fullscreen);
+}
+
+void Konsole::toggleFullScreen()
+{
+ setFullScreen(!b_fullscreen);
+}
+
+bool Konsole::fullScreen()
+{
+ return b_fullscreen;
+}
+
+void Konsole::setFullScreen(bool on)
+{
+ if( on )
+ showFullScreen();
+ else {
+ if( isFullScreen()) // showNormal() may also do unminimize, unmaximize etc. :(
+ showNormal();
+ }
+}
+
+// don't call this directly
+void Konsole::updateFullScreen( bool on )
+{
+ b_fullscreen = on;
+ if( on )
+ showFullScreen();
+ else {
+ if( isFullScreen()) // showNormal() may also do unminimize, unmaximize etc. :(
+ showNormal();
+ updateTitle(); // restore caption of window
+ }
+ updateRMBMenu();
+ te->setFrameStyle( b_framevis && !b_fullscreen ?(QFrame::WinPanel|QFrame::Sunken):QFrame::NoFrame );
+}
+
+/* --| sessions |------------------------------------------------------------ */
+
+//FIXME: activating sessions creates a lot flicker in the moment.
+// it comes from setting the attributes of a session individually.
+// ONE setImage call should actually be enough to match all cases.
+// These can be quite different:
+// - The screen size might have changed while the session was
+// detached. A propagation of the resize should in this case
+// make the drawEvent.
+// - font, background image and color palette should be set in one go.
+
+void Konsole::disableMasterModeConnections()
+{
+ QPtrListIterator<TESession> from_it(sessions);
+ for (; from_it.current(); ++from_it) {
+ TESession *from = from_it.current();
+ if (from->isMasterMode()) {
+ QPtrListIterator<TESession> to_it(sessions);
+ for (; to_it.current(); ++to_it) {
+ TESession *to = to_it.current();
+ if (to!=from)
+ disconnect(from->widget(),SIGNAL(keyPressedSignal(QKeyEvent*)),
+ to->getEmulation(),SLOT(onKeyPress(QKeyEvent*)));
+ }
+ }
+ }
+}
+
+void Konsole::enableMasterModeConnections()
+{
+ QPtrListIterator<TESession> from_it(sessions);
+ for (; from_it.current(); ++from_it) {
+ TESession *from = from_it.current();
+ if (from->isMasterMode()) {
+ QPtrListIterator<TESession> to_it(sessions);
+ for (; to_it.current(); ++to_it) {
+ TESession *to = to_it.current();
+ if (to!=from) {
+ connect(from->widget(),SIGNAL(keyPressedSignal(QKeyEvent*)),
+ to->getEmulation(),SLOT(onKeyPress(QKeyEvent*)));
+ }
+ }
+ }
+ from->setListenToKeyPress(true);
+ }
+}
+
+void Konsole::feedAllSessions(const QString &text)
+{
+ if (!te) return;
+ bool oldMasterMode = se->isMasterMode();
+ setMasterMode(true);
+ te->emitText(text);
+ if (!oldMasterMode)
+ setMasterMode(false);
+}
+
+void Konsole::sendAllSessions(const QString &text)
+{
+ QString newtext=text;
+ newtext.append("\r");
+ feedAllSessions(newtext);
+}
+
+KURL Konsole::baseURL() const
+{
+ KURL url;
+ url.setPath(se->getCwd()+"/");
+ return url;
+}
+
+void Konsole::enterURL(const QString& URL, const QString&)
+{
+ QString path, login, host, newtext;
+
+ if (URL.startsWith("file:")) {
+ KURL uglyurl(URL);
+ newtext=uglyurl.path();
+ KRun::shellQuote(newtext);
+ te->emitText("cd "+newtext+"\r");
+ }
+ else if (URL.contains("://", true)) {
+ KURL u(URL);
+ newtext = u.protocol();
+ bool isSSH = (newtext == "ssh");
+ if (u.port() && isSSH)
+ newtext += " -p " + QString().setNum(u.port());
+ if (u.hasUser())
+ newtext += " -l " + u.user();
+
+ /*
+ * If we have a host, connect.
+ */
+ if (u.hasHost()) {
+ newtext = newtext + " " + u.host();
+ if (u.port() && !isSSH)
+ newtext += QString(" %1").arg(u.port());
+ se->setUserTitle(31,""); // we don't know remote cwd
+ te->emitText(newtext + "\r");
+ }
+ }
+ else
+ te->emitText(URL);
+}
+
+void Konsole::slotClearTerminal()
+{
+ if (se) {
+ se->getEmulation()->clearEntireScreen();
+ se->getEmulation()->clearSelection();
+ }
+}
+
+void Konsole::slotResetClearTerminal()
+{
+ if (se) {
+ se->getEmulation()->reset();
+ se->getEmulation()->clearSelection();
+ }
+}
+
+void Konsole::sendSignal(int sn)
+{
+ if (se) se->sendSignal(sn);
+}
+
+void Konsole::runSession(TESession* s)
+{
+ KRadioAction *ra = session2action.find(s);
+ ra->setChecked(true);
+ activateSession(s);
+
+ // give some time to get through the
+ // resize events before starting up.
+ QTimer::singleShot(100,s,SLOT(run()));
+}
+
+void Konsole::addSession(TESession* s)
+{
+ QString newTitle = s->Title();
+
+ bool nameOk;
+ int count = 1;
+ do {
+ nameOk = true;
+ for (TESession *ses = sessions.first(); ses; ses = sessions.next())
+ {
+ if (newTitle == ses->Title())
+ {
+ nameOk = false;
+ break;
+ }
+ }
+ if (!nameOk)
+ {
+ count++;
+ newTitle = i18n("abbreviation of number","%1 No. %2").arg(s->Title()).arg(count);
+ }
+ }
+ while (!nameOk);
+
+ s->setTitle(newTitle);
+
+ // create an action for the session
+ KRadioAction *ra = new KRadioAction(newTitle.replace('&',"&&"),
+ s->IconName(),
+ 0,
+ this,
+ SLOT(activateSession()),
+ m_shortcuts);
+ ra->setExclusiveGroup("sessions");
+ ra->setChecked(true);
+
+ action2session.insert(ra, s);
+ session2action.insert(s,ra);
+ sessions.append(s);
+ if (sessions.count()>1) {
+ if (!m_menuCreated)
+ makeGUI();
+ m_detachSession->setEnabled(true);
+ }
+
+ if (m_menuCreated)
+ ra->plug(m_view);
+
+ createSessionTab(te, SmallIconSet(s->IconName()), newTitle);
+ setSchema(s->schemaNo());
+ tabwidget->setCurrentPage(tabwidget->count()-1);
+ disableMasterModeConnections(); // no duplicate connections, remove old
+ enableMasterModeConnections();
+ if( m_removeSessionButton )
+ m_removeSessionButton->setEnabled(tabwidget->count()>1);
+}
+
+QString Konsole::currentSession()
+{
+ return se->SessionId();
+}
+
+QString Konsole::sessionId(const int position)
+{
+ if (position<=0 || position>(int)sessions.count())
+ return "";
+
+ return sessions.at(position-1)->SessionId();
+}
+
+void Konsole::listSessions()
+{
+ int counter=0;
+ m_sessionList->clear();
+ m_sessionList->insertTitle(i18n("Session List"));
+ m_sessionList->setKeyboardShortcutsEnabled(true);
+ for (TESession *ses = sessions.first(); ses; ses = sessions.next()) {
+ QString title=ses->Title();
+ m_sessionList->insertItem(SmallIcon(ses->IconName()),title.replace('&',"&&"),counter++);
+ }
+ m_sessionList->adjustSize();
+ m_sessionList->popup(mapToGlobal(QPoint((width()/2)-(m_sessionList->width()/2),(height()/2)-(m_sessionList->height()/2))));
+}
+
+void Konsole::switchToSession()
+{
+ activateSession( QString( sender()->name() ).right( 2 ).toInt() -1 );
+}
+
+void Konsole::activateSession(int position)
+{
+ if (position<0 || position>=(int)sessions.count())
+ return;
+ activateSession( sessions.at(position) );
+}
+
+void Konsole::activateSession(QWidget* w)
+{
+ activateSession(tabwidget->indexOf(w));
+ w->setFocus();
+}
+
+void Konsole::activateSession(const QString &sessionId)
+{
+ TESession* activate=NULL;
+
+ sessions.first();
+ while(sessions.current())
+ {
+ if (sessions.current()->SessionId()==sessionId)
+ activate=sessions.current();
+ sessions.next();
+ }
+
+ if (activate)
+ activateSession( activate );
+}
+
+/**
+ Activates a session from the menu
+ */
+void Konsole::activateSession()
+{
+ TESession* s = NULL;
+ // finds the session based on which button was activated
+ QPtrDictIterator<TESession> it( action2session ); // iterator for dict
+ while ( it.current() )
+ {
+ KRadioAction *ra = (KRadioAction*)it.currentKey();
+ if (ra->isChecked()) { s = it.current(); break; }
+ ++it;
+ }
+ if (s!=NULL) activateSession(s);
+}
+
+void Konsole::activateSession(TESession *s)
+{
+ if (se)
+ {
+ se->setConnect(false);
+ se->setListenToKeyPress(true);
+ notifySessionState(se,NOTIFYNORMAL);
+ // Delete the session if isn't in the session list any longer.
+ if (sessions.find(se) == -1)
+ delete se;
+ }
+ if (se != s)
+ se_previous = se;
+ se = s;
+
+ // Set the required schema variables for the current session
+ ColorSchema* cs = colors->find( se->schemaNo() );
+ if (!cs)
+ cs = (ColorSchema*)colors->at(0); //the default one
+ s_schema = cs->relPath();
+ curr_schema = cs->numb();
+ pmPath = cs->imagePath();
+ n_render = cs->alignment();
+
+// BR 106464 temporary fix...
+// only 2 sessions opened, 2nd session viewable, right-click on 1st tab and
+// select 'Detach', close original Konsole window... crash
+// s is not set properly on original Konsole window
+ KRadioAction *ra = session2action.find(se);
+ if (!ra) {
+ se=sessions.first(); // Get new/correct TESession
+ ra = session2action.find(se);
+ }
+ ra->setChecked(true);
+
+ QTimer::singleShot(1,this,SLOT(allowPrevNext())); // hack, hack, hack
+
+ tabwidget->showPage( se->widget() );
+ te = se->widget();
+ if (m_menuCreated) {
+ if (selectBell) selectBell->setCurrentItem(te->bellMode());
+ updateSchemaMenu();
+ }
+
+ if (rootxpms[te])
+ rootxpms[te]->start();
+ notifySize(te->Columns(), te->Lines()); // set menu items
+ se->setConnect(true);
+ updateTitle();
+ if (!m_menuCreated)
+ return;
+
+ if (selectSetEncoding) selectSetEncoding->setCurrentItem(se->encodingNo());
+ updateKeytabMenu(); // act. the keytab for this session
+ if (m_clearHistory) m_clearHistory->setEnabled( se->history().isOn() );
+ if (m_findHistory) m_findHistory->setEnabled( se->history().isOn() );
+ if (m_findNext) m_findNext->setEnabled( se->history().isOn() );
+ if (m_findPrevious) m_findPrevious->setEnabled( se->history().isOn() );
+ se->getEmulation()->findTextBegin();
+ if (m_saveHistory) m_saveHistory->setEnabled( se->history().isOn() );
+ if (monitorActivity) monitorActivity->setChecked( se->isMonitorActivity() );
+ if (monitorSilence) monitorSilence->setChecked( se->isMonitorSilence() );
+ masterMode->setChecked( se->isMasterMode() );
+ sessions.find(se);
+ uint position=sessions.at();
+ if (m_moveSessionLeft) m_moveSessionLeft->setEnabled(position>0);
+ if (m_moveSessionRight) m_moveSessionRight->setEnabled(position<sessions.count()-1);
+}
+
+void Konsole::slotUpdateSessionConfig(TESession *session)
+{
+ if (session == se)
+ activateSession(se);
+}
+
+void Konsole::slotResizeSession(TESession *session, QSize size)
+{
+ TESession *oldSession = se;
+ if (se != session)
+ activateSession(session);
+ setColLin(size.width(), size.height());
+ activateSession(oldSession);
+}
+
+// Called by newSession and DCOP function below
+void Konsole::setSessionEncoding( const QString &encoding, TESession *session )
+{
+ if ( encoding.isEmpty() )
+ return;
+
+ if ( !session )
+ session = se;
+
+ bool found = false;
+ QString enc = KGlobal::charsets()->encodingForName(encoding);
+ QTextCodec * qtc = KGlobal::charsets()->codecForName(enc, found);
+ if ( !found || !qtc )
+ return;
+
+ // Encoding was found; now try to figure out which Encoding menu item
+ // it corresponds to.
+ int i = 0;
+ bool found_encoding = false;
+ QStringList encodingNames = KGlobal::charsets()->descriptiveEncodingNames();
+ QStringList::ConstIterator it = encodingNames.begin();
+ QString t_encoding = encoding.lower();
+
+ while ( it != encodingNames.end() && !found_encoding )
+ {
+ if ( QString::compare( KGlobal::charsets()->encodingForName(*it),
+ t_encoding ) == 0 ) {
+ found_encoding = true;
+ }
+ i++; it++;
+ }
+
+ // BR114535 : Remove jis7 due to infinite loop.
+ if ( enc == "jis7" ) {
+ kdWarning()<<"Encoding Japanese (jis7) currently does not work! BR114535"<<endl;
+ return;
+ }
+
+ if ( found_encoding )
+ {
+ session->setEncodingNo( i );
+ session->getEmulation()->setCodec(qtc);
+ if (se == session)
+ activateSession(se);
+ }
+}
+
+// Called via DCOP only
+void Konsole::slotSetSessionEncoding(TESession *session, const QString &encoding)
+{
+ setSessionEncoding( encoding, session );
+}
+
+void Konsole::slotGetSessionSchema(TESession *session, QString &schema)
+{
+ int no = session->schemaNo();
+ ColorSchema* s = colors->find( no );
+ schema = s->relPath();
+}
+
+void Konsole::slotSetSessionSchema(TESession *session, const QString &schema)
+{
+ ColorSchema* s = colors->find( schema );
+ setSchema(s, session->widget());
+}
+
+void Konsole::allowPrevNext()
+{
+ if (!se) return;
+ notifySessionState(se,NOTIFYNORMAL);
+}
+
+KSimpleConfig *Konsole::defaultSession()
+{
+ if (!m_defaultSession) {
+ KConfig * config = KGlobal::config();
+ config->setDesktopGroup();
+ setDefaultSession(config->readEntry("DefaultSession","shell.desktop"));
+ }
+ return m_defaultSession;
+}
+
+void Konsole::setDefaultSession(const QString &filename)
+{
+ delete m_defaultSession;
+ m_defaultSession = new KSimpleConfig(locate("appdata", filename), true /* read only */);
+ m_defaultSession->setDesktopGroup();
+ b_showstartuptip = m_defaultSession->readBoolEntry("Tips", true);
+
+ m_defaultSessionFilename=filename;
+}
+
+void Konsole::newSession(const QString &pgm, const QStrList &args, const QString &term, const QString &icon, const QString &title, const QString &cwd)
+{
+ KSimpleConfig *co = defaultSession();
+ newSession(co, pgm, args, term, icon, title, cwd);
+}
+
+QString Konsole::newSession()
+{
+ KSimpleConfig *co = defaultSession();
+ return newSession(co, QString::null, QStrList());
+}
+
+void Konsole::newSession(int i)
+{
+ if (i == SESSION_NEW_WINDOW_ID)
+ {
+ // TODO: "type" isn't passed properly
+ Konsole* konsole = new Konsole(name(), b_histEnabled, !menubar->isHidden(), n_tabbar != TabNone, b_framevis,
+ n_scroll != TEWidget::SCRNONE, 0, false, 0);
+ konsole->newSession();
+ konsole->enableFullScripting(b_fullScripting);
+ konsole->enableFixedSize(b_fixedSize);
+ konsole->setColLin(0,0); // Use defaults
+ konsole->initFullScreen();
+ konsole->show();
+ return;
+ }
+
+ KSimpleConfig* co = no2command.find(i);
+ if (co) {
+ newSession(co);
+ resetScreenSessions();
+ }
+}
+
+void Konsole::newSessionTabbar(int i)
+{
+ if (i == SESSION_NEW_WINDOW_ID)
+ {
+ // TODO: "type" isn't passed properly
+ Konsole* konsole = new Konsole(name(), b_histEnabled, !menubar->isHidden(), n_tabbar != TabNone, b_framevis,
+ n_scroll != TEWidget::SCRNONE, 0, false, 0);
+ konsole->newSession();
+ konsole->enableFullScripting(b_fullScripting);
+ konsole->enableFixedSize(b_fixedSize);
+ konsole->setColLin(0,0); // Use defaults
+ konsole->initFullScreen();
+ konsole->show();
+ return;
+ }
+
+ KSimpleConfig* co = no2command.find(i);
+ if (co) {
+ newSession(co);
+ resetScreenSessions();
+ }
+}
+
+QString Konsole::newSession(const QString &type)
+{
+ KSimpleConfig *co;
+ if (type.isEmpty())
+ co = defaultSession();
+ else
+ co = new KSimpleConfig(locate("appdata", type + ".desktop"), true /* read only */);
+ return newSession(co);
+}
+
+QString Konsole::newSession(KSimpleConfig *co, QString program, const QStrList &args,
+ const QString &_term,const QString &_icon,
+ const QString &_title, const QString &_cwd)
+{
+ QString emu = "xterm";
+ QString icon = "konsole";
+ QString key;
+ QString sch = s_kconfigSchema;
+ QString txt;
+ QString cwd;
+ QFont font = defaultFont;
+ QStrList cmdArgs;
+
+ if (co) {
+ co->setDesktopGroup();
+ emu = co->readEntry("Term", emu);
+ key = co->readEntry("KeyTab", key);
+ sch = co->readEntry("Schema", sch);
+ txt = co->readEntry("Name");
+ font = co->readFontEntry("SessionFont", &font);
+ icon = co->readEntry("Icon", icon);
+ cwd = co->readPathEntry("Cwd");
+ }
+
+ if (!_term.isEmpty())
+ emu = _term;
+
+ if (!_icon.isEmpty())
+ icon = _icon;
+
+ if (!_title.isEmpty())
+ txt = _title;
+
+ // apply workdir only when the session config does not have a directory
+ if (cwd.isEmpty())
+ cwd = s_workDir;
+ // bookmarks take precedence over workdir
+ // however, --workdir option has precedence in the very first session
+ if (!_cwd.isEmpty())
+ cwd = _cwd;
+
+ if (!program.isEmpty()) {
+ cmdArgs = args;
+ }
+ else {
+ program = QFile::decodeName(konsole_shell(cmdArgs));
+
+ if (co) {
+ co->setDesktopGroup();
+ QString cmd = co->readPathEntry("Exec");
+ if (!cmd.isEmpty()) {
+ cmdArgs.append("-c");
+ cmdArgs.append(QFile::encodeName(cmd));
+ }
+ }
+ }
+
+ ColorSchema* schema = colors->find(sch);
+ if (!schema)
+ schema=(ColorSchema*)colors->at(0); //the default one
+ int schmno = schema->numb();
+
+ if (sessions.count()==1 && n_tabbar!=TabNone)
+ tabwidget->setTabBarHidden( false );
+
+ TEWidget* te_old = te;
+ te=new TEWidget(tabwidget);
+
+ connect( te, SIGNAL(configureRequest(TEWidget*, int, int, int)),
+ this, SLOT(configureRequest(TEWidget*,int,int,int)) );
+ if (te_old) {
+ initTEWidget(te, te_old);
+ }
+ else {
+ readProperties(KGlobal::config(), "", true);
+ te->setVTFont(font);
+ te->setScrollbarLocation(n_scroll);
+ te->setBellMode(n_bell);
+ }
+
+ te->setMinimumSize(150,70);
+
+ QString sessionId="session-"+QString::number(++sessionIdCounter);
+ TESession* s = new TESession(te, emu,winId(),sessionId,cwd);
+ s->setProgram(QFile::encodeName(program),cmdArgs);
+ s->setMonitorSilenceSeconds(monitorSilenceSeconds);
+ s->enableFullScripting(b_fullScripting);
+ // If you add any new signal-slot connection below, think about doing it in konsolePart too
+ connect( s,SIGNAL(done(TESession*)),
+ this,SLOT(doneSession(TESession*)) );
+ connect( s, SIGNAL( updateTitle(TESession*) ),
+ this, SLOT( updateTitle(TESession*) ) );
+ connect( s, SIGNAL( notifySessionState(TESession*, int) ),
+ this, SLOT( notifySessionState(TESession*, int)) );
+ connect( s, SIGNAL(disableMasterModeConnections()),
+ this, SLOT(disableMasterModeConnections()) );
+ connect( s, SIGNAL(enableMasterModeConnections()),
+ this, SLOT(enableMasterModeConnections()) );
+ connect( s, SIGNAL(renameSession(TESession*,const QString&)),
+ this, SLOT(slotRenameSession(TESession*, const QString&)) );
+ connect( s->getEmulation(), SIGNAL(changeColumns(int)),
+ this, SLOT(changeColumns(int)) );
+ connect( s->getEmulation(), SIGNAL(changeColLin(int,int)),
+ this, SLOT(changeColLin(int,int)) );
+ connect( s->getEmulation(), SIGNAL(ImageSizeChanged(int,int)),
+ this, SLOT(notifySize(int,int)));
+ connect( s, SIGNAL(zmodemDetected(TESession*)),
+ this, SLOT(slotZModemDetected(TESession*)));
+ connect( s, SIGNAL(updateSessionConfig(TESession*)),
+ this, SLOT(slotUpdateSessionConfig(TESession*)));
+ connect( s, SIGNAL(resizeSession(TESession*, QSize)),
+ this, SLOT(slotResizeSession(TESession*, QSize)));
+ connect( s, SIGNAL(setSessionEncoding(TESession*, const QString &)),
+ this, SLOT(slotSetSessionEncoding(TESession*, const QString &)));
+ connect( s, SIGNAL(getSessionSchema(TESession*, QString &)),
+ this, SLOT(slotGetSessionSchema(TESession*, QString &)));
+ connect( s, SIGNAL(setSessionSchema(TESession*, const QString &)),
+ this, SLOT(slotSetSessionSchema(TESession*, const QString &)));
+ connect( s, SIGNAL(changeTabTextColor(TESession*, int)),
+ this,SLOT(changeTabTextColor(TESession*, int)) );
+
+ s->widget()->setVTFont(defaultFont);// Hack to set font again after newSession
+ s->setSchemaNo(schmno);
+ if (key.isEmpty())
+ s->setKeymapNo(n_defaultKeytab);
+ else {
+ // TODO: Fixes BR77018, see BR83000.
+ if (key.endsWith(".keytab"))
+ key.remove(".keytab");
+ s->setKeymap(key);
+ }
+
+ s->setTitle(txt);
+ s->setIconName(icon);
+ s->setAddToUtmp(b_addToUtmp);
+ s->setXonXoff(b_xonXoff);
+
+ if (b_histEnabled && m_histSize)
+ s->setHistory(HistoryTypeBuffer(m_histSize));
+ else if (b_histEnabled && !m_histSize)
+ s->setHistory(HistoryTypeFile());
+ else
+ s->setHistory(HistoryTypeNone());
+
+ setSessionEncoding( s_encodingName, s );
+
+ addSession(s);
+ runSession(s); // activate and run
+ return sessionId;
+}
+
+/*
+ * Starts a new session based on URL.
+ */
+void Konsole::newSession(const QString& sURL, const QString& title)
+{
+ QStrList args;
+ QString protocol, path, login, host;
+
+ KURL url = KURL(sURL);
+ if ((url.protocol() == "file") && (url.hasPath())) {
+ KSimpleConfig *co = defaultSession();
+ path = url.path();
+ newSession(co, QString::null, QStrList(), QString::null, QString::null,
+ title.isEmpty() ? path : title, path);
+ return;
+ }
+ else if ((!url.protocol().isEmpty()) && (url.hasHost())) {
+ protocol = url.protocol();
+ bool isSSH = (protocol == "ssh");
+ args.append( protocol.latin1() ); /* argv[0] == command to run. */
+ host = url.host();
+ if (url.port() && isSSH) {
+ args.append("-p");
+ args.append(QCString().setNum(url.port()));
+ }
+ if (url.hasUser()) {
+ login = url.user();
+ args.append("-l");
+ args.append(login.latin1());
+ }
+ args.append(host.latin1());
+ if (url.port() && !isSSH)
+ args.append(QCString().setNum(url.port()));
+ newSession( NULL, protocol.latin1() /* protocol */, args /* arguments */,
+ QString::null /*term*/, QString::null /*icon*/,
+ title.isEmpty() ? path : title /*title*/, QString::null /*cwd*/);
+ return;
+ }
+ /*
+ * We can't create a session without a protocol.
+ * We should ideally popup a warning.
+ */
+}
+
+void Konsole::confirmCloseCurrentSession( TESession* _se )
+{
+ if ( !_se )
+ _se = se;
+ if (KMessageBox::warningContinueCancel(this,
+ i18n("Are you sure that you want to close the current session?"),
+ i18n("Close Confirmation"), KGuiItem(i18n("C&lose Session"),"tab_remove"),
+ "ConfirmCloseSession")==KMessageBox::Continue)
+ _se->closeSession();
+}
+
+void Konsole::closeCurrentSession()
+{
+ se->closeSession();
+}
+
+//FIXME: If a child dies during session swap,
+// this routine might be called before
+// session swap is completed.
+
+void Konsole::doneSession(TESession* s)
+{
+
+ if (s == se_previous)
+ se_previous = 0;
+
+ if (se_previous)
+ activateSession(se_previous);
+
+ KRadioAction *ra = session2action.find(s);
+ ra->unplug(m_view);
+ tabwidget->removePage( s->widget() );
+ if (rootxpms[s->widget()]) {
+ delete rootxpms[s->widget()];
+ rootxpms.remove(s->widget());
+ }
+ delete s->widget();
+ if(m_removeSessionButton )
+ m_removeSessionButton->setEnabled(tabwidget->count()>1);
+ session2action.remove(s);
+ action2session.remove(ra);
+ int sessionIndex = sessions.findRef(s);
+ sessions.remove(s);
+ delete ra; // will the toolbar die?
+
+ s->setConnect(false);
+ delete s;
+
+ if (s == se_previous)
+ se_previous = 0;
+
+ if (s == se)
+ { // pick a new session
+ se = 0;
+ if (sessions.count())
+ {
+ se = sessions.at(sessionIndex ? sessionIndex - 1 : 0);
+
+ session2action.find(se)->setChecked(true);
+ //FIXME: this Timer stupidity originated from the connected
+ // design of Emulations. By this the newly activated
+ // session might get a Ctrl(D) if the session has be
+ // terminated by this keypress. A likely problem
+ // can be found in the CMD_prev/nextSession processing.
+ // Since the timer approach only works at good weather,
+ // the whole construction is not suited to what it
+ // should do. Affected is the TEEmulation::setConnect.
+ QTimer::singleShot(1,this,SLOT(activateSession()));
+ }
+ else
+ close();
+ }
+ else {
+ sessions.find(se);
+ uint position=sessions.at();
+ m_moveSessionLeft->setEnabled(position>0);
+ m_moveSessionRight->setEnabled(position<sessions.count()-1);
+ }
+ if (sessions.count()==1) {
+ m_detachSession->setEnabled(false);
+ if (b_dynamicTabHide && !tabwidget->isTabBarHidden())
+ tabwidget->setTabBarHidden(true);
+ }
+}
+
+/*! Cycle to previous session (if any) */
+
+void Konsole::prevSession()
+{
+ sessions.find(se); sessions.prev();
+ if (!sessions.current()) sessions.last();
+ if (sessions.current() && sessions.count() > 1)
+ activateSession(sessions.current());
+}
+
+/*! Cycle to next session (if any) */
+
+void Konsole::nextSession()
+{
+ sessions.find(se); sessions.next();
+ if (!sessions.current()) sessions.first();
+ if (sessions.current() && sessions.count() > 1)
+ activateSession(sessions.current());
+}
+
+void Konsole::slotMovedTab(int from, int to)
+{
+
+ TESession* _se = sessions.take(from);
+ sessions.remove(_se);
+ sessions.insert(to,_se);
+
+ KRadioAction *ra = session2action.find(_se);
+ ra->unplug(m_view);
+ ra->plug(m_view,(m_view->count()-sessions.count()+1)+to);
+
+ if (to==tabwidget->currentPageIndex()) {
+ if (!m_menuCreated)
+ makeGUI();
+ m_moveSessionLeft->setEnabled(to>0);
+ m_moveSessionRight->setEnabled(to<(int)sessions.count()-1);
+ }
+}
+
+/* Move session forward in session list if possible */
+void Konsole::moveSessionLeft()
+{
+ sessions.find(se);
+ uint position=sessions.at();
+ if (position==0)
+ return;
+
+ sessions.remove(position);
+ sessions.insert(position-1,se);
+
+ KRadioAction *ra = session2action.find(se);
+ ra->unplug(m_view);
+ ra->plug(m_view,(m_view->count()-sessions.count()+1)+position-1);
+
+ QColor oldcolor = tabwidget->tabColor(se->widget());
+
+ tabwidget->blockSignals(true);
+ tabwidget->removePage(se->widget());
+ tabwidget->blockSignals(false);
+ QString title = se->Title();
+ createSessionTab(se->widget(), iconSetForSession(se),
+ title.replace('&', "&&"), position-1);
+ tabwidget->showPage(se->widget());
+ tabwidget->setTabColor(se->widget(),oldcolor);
+
+ if (!m_menuCreated)
+ makeGUI();
+ m_moveSessionLeft->setEnabled(position-1>0);
+ m_moveSessionRight->setEnabled(true);
+}
+
+/* Move session back in session list if possible */
+void Konsole::moveSessionRight()
+{
+ sessions.find(se);
+ uint position=sessions.at();
+
+ if (position==sessions.count()-1)
+ return;
+
+ sessions.remove(position);
+ sessions.insert(position+1,se);
+
+ KRadioAction *ra = session2action.find(se);
+ ra->unplug(m_view);
+ ra->plug(m_view,(m_view->count()-sessions.count()+1)+position+1);
+
+ QColor oldcolor = tabwidget->tabColor(se->widget());
+
+ tabwidget->blockSignals(true);
+ tabwidget->removePage(se->widget());
+ tabwidget->blockSignals(false);
+ QString title = se->Title();
+ createSessionTab(se->widget(), iconSetForSession(se),
+ title.replace('&', "&&"), position+1);
+ tabwidget->showPage(se->widget());
+ tabwidget->setTabColor(se->widget(),oldcolor);
+
+ if (!m_menuCreated)
+ makeGUI();
+ m_moveSessionLeft->setEnabled(true);
+ m_moveSessionRight->setEnabled(position+1<sessions.count()-1);
+}
+
+void Konsole::initMonitorActivity(bool state)
+{
+ monitorActivity->setChecked(state);
+ slotToggleMonitor();
+}
+
+void Konsole::initMonitorSilence(bool state)
+{
+ monitorSilence->setChecked(state);
+ slotToggleMonitor();
+}
+
+void Konsole::slotToggleMonitor()
+{
+ se->setMonitorActivity( monitorActivity->isChecked() );
+ se->setMonitorSilence( monitorSilence->isChecked() );
+ notifySessionState(se,NOTIFYNORMAL);
+}
+
+void Konsole::initMasterMode(bool state)
+{
+ masterMode->setChecked(state);
+ slotToggleMasterMode();
+}
+
+void Konsole::initTabColor(QColor color)
+{
+ if ( color.isValid() )
+ tabwidget->setTabColor( se->widget(), color );
+}
+
+void Konsole::initHistory(int lines, bool enable)
+{
+ // If no History#= is given in the profile, use the history
+ // parameter saved in konsolerc.
+ if ( lines < 0 ) lines = m_histSize;
+
+ if ( enable && lines > 0 )
+ se->setHistory( HistoryTypeBuffer( lines ) );
+ else if ( enable ) // Unlimited buffer
+ se->setHistory(HistoryTypeFile());
+ else
+ se->setHistory( HistoryTypeNone() );
+}
+
+void Konsole::slotToggleMasterMode()
+{
+ setMasterMode( masterMode->isChecked() );
+}
+
+void Konsole::setMasterMode(bool _state, TESession* _se)
+{
+ if (!_se)
+ _se = se;
+ if (_se->isMasterMode() == _state)
+ return;
+
+ if (_se==se)
+ masterMode->setChecked( _state );
+
+ disableMasterModeConnections();
+
+ _se->setMasterMode( _state );
+
+ if (_state)
+ enableMasterModeConnections();
+
+ notifySessionState(_se,NOTIFYNORMAL);
+}
+
+void Konsole::notifySessionState(TESession* session, int state)
+{
+ QString state_iconname;
+ switch(state)
+ {
+ case NOTIFYNORMAL : if(session->isMasterMode())
+ state_iconname = "remote";
+ else
+ state_iconname = session->IconName();
+ break;
+ case NOTIFYBELL : state_iconname = "bell";
+ break;
+ case NOTIFYACTIVITY: state_iconname = "activity";
+ break;
+ case NOTIFYSILENCE : state_iconname = "silence";
+ break;
+ }
+ if (!state_iconname.isEmpty()
+ && session->testAndSetStateIconName(state_iconname)
+ && m_tabViewMode != ShowTextOnly) {
+
+ QPixmap normal = KGlobal::instance()->iconLoader()->loadIcon(state_iconname,
+ KIcon::Small, 0, KIcon::DefaultState, 0L, true);
+ QPixmap active = KGlobal::instance()->iconLoader()->loadIcon(state_iconname,
+ KIcon::Small, 0, KIcon::ActiveState, 0L, true);
+
+ // make sure they are not larger than 16x16
+ if (normal.width() > 16 || normal.height() > 16)
+ normal.convertFromImage(normal.convertToImage().smoothScale(16,16));
+ if (active.width() > 16 || active.height() > 16)
+ active.convertFromImage(active.convertToImage().smoothScale(16,16));
+
+ QIconSet iconset;
+ iconset.setPixmap(normal, QIconSet::Small, QIconSet::Normal);
+ iconset.setPixmap(active, QIconSet::Small, QIconSet::Active);
+
+ tabwidget->setTabIconSet(session->widget(), iconset);
+ }
+}
+
+// --| Session support |-------------------------------------------------------
+
+void Konsole::buildSessionMenus()
+{
+ m_session->clear();
+ if (m_tabbarSessionsCommands)
+ m_tabbarSessionsCommands->clear();
+
+ loadSessionCommands();
+ loadScreenSessions();
+
+ createSessionMenus();
+
+ if (kapp->authorizeKAction("file_print"))
+ {
+ m_session->insertSeparator();
+ m_print->plug(m_session);
+ }
+
+ m_session->insertSeparator();
+ m_closeSession->plug(m_session);
+
+ m_session->insertSeparator();
+ m_quit->plug(m_session);
+}
+
+static void insertItemSorted(KPopupMenu *menu, const QIconSet &iconSet, const QString &txt, int id)
+{
+ const int defaultId = SESSION_NEW_SHELL_ID; // The id of the 'new' item.
+ int index = menu->indexOf(defaultId);
+ int count = menu->count();
+ if (index >= 0)
+ {
+ index++; // Skip New Window
+ index++; // Skip separator
+ while(true)
+ {
+ index++;
+ if (index >= count)
+ {
+ index = -1; // Insert at end
+ break;
+ }
+ if (menu->text(menu->idAt(index)) > txt)
+ break; // Insert before this item
+ }
+ }
+ menu->insertItem(iconSet, txt, id, index);
+}
+
+void Konsole::addSessionCommand(const QString &path)
+{
+ KSimpleConfig* co;
+ if (path.isEmpty())
+ co = new KSimpleConfig(locate("appdata", "shell.desktop"), true /* read only */);
+ else
+ co = new KSimpleConfig(path,true);
+ co->setDesktopGroup();
+ QString typ = co->readEntry("Type");
+ QString txt = co->readEntry("Name");
+
+ // try to locate the binary
+ QString exec= co->readPathEntry("Exec");
+ if (exec.startsWith("su -c \'")) {
+ exec = exec.mid(7,exec.length()-8);
+ }
+
+ exec = KRun::binaryName(exec, false);
+ exec = KShell::tildeExpand(exec);
+ QString pexec = KGlobal::dirs()->findExe(exec);
+
+ if (typ.isEmpty() || txt.isEmpty() || typ != "KonsoleApplication"
+ || ( !exec.isEmpty() && pexec.isEmpty() ) )
+ {
+ if (!path.isEmpty())
+ delete co;
+ kdWarning()<<"Unable to use "<<path.latin1()<<endl;
+ return; // ignore
+ }
+
+ no2command.insert(++cmd_serial,co);
+
+ // Add shortcuts only once and not for 'New Shell'.
+ if ( ( b_sessionShortcutsMapped == true ) || ( cmd_serial == SESSION_NEW_SHELL_ID ) ) return;
+
+ // Add an empty shortcut for each Session.
+ QString comment = co->readEntry("Comment");
+ if (comment.isEmpty())
+ comment=txt.prepend(i18n("New "));
+
+ QString name = comment;
+ name.prepend("SSC_"); // Allows easy searching for Session ShortCuts
+ name.replace(" ", "_");
+ sl_sessionShortCuts << name;
+
+ // Is there already this shortcut?
+ KAction* sessionAction;
+ if ( m_shortcuts->action( name.latin1() ) ) {
+ sessionAction = m_shortcuts->action( name.latin1() );
+ } else {
+ sessionAction = new KAction( comment, 0, this, 0, m_shortcuts, name.latin1() );
+ }
+ connect( sessionAction, SIGNAL( activated() ), sessionNumberMapper, SLOT( map() ) );
+ sessionNumberMapper->setMapping( sessionAction, cmd_serial );
+
+}
+
+void Konsole::loadSessionCommands()
+{
+ no2command.clear();
+
+ cmd_serial = 99;
+ cmd_first_screen = -1;
+
+ if (!kapp->authorize("shell_access"))
+ return;
+
+ addSessionCommand(QString::null);
+
+ QStringList lst = KGlobal::dirs()->findAllResources("appdata", "*.desktop", false, true);
+
+ for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it )
+ if (!(*it).endsWith("/shell.desktop"))
+ addSessionCommand(*it);
+
+ b_sessionShortcutsMapped = true;
+}
+
+void Konsole::createSessionMenus()
+{
+ if (no2command.isEmpty()) { // All sessions have been deleted
+ m_session->insertItem(SmallIconSet("window_new"),
+ i18n("New &Window"), SESSION_NEW_WINDOW_ID);
+ m_tabbarSessionsCommands->insertItem(SmallIconSet("window_new"),
+ i18n("New &Window"), SESSION_NEW_WINDOW_ID);
+ return;
+ }
+
+ KSimpleConfig *cfg = no2command[SESSION_NEW_SHELL_ID];
+ QString txt = cfg->readEntry("Name");
+ QString icon = cfg->readEntry("Icon", "konsole");
+ insertItemSorted(m_tabbarSessionsCommands, SmallIconSet(icon),
+ txt.replace('&',"&&"), SESSION_NEW_SHELL_ID );
+
+ QString comment = cfg->readEntry("Comment");
+ if (comment.isEmpty())
+ comment=txt.prepend(i18n("New "));
+ insertItemSorted(m_session, SmallIconSet(icon),
+ comment.replace('&',"&&"), SESSION_NEW_SHELL_ID);
+ m_session->insertItem(SmallIconSet("window_new"),
+ i18n("New &Window"), SESSION_NEW_WINDOW_ID);
+ m_tabbarSessionsCommands->insertItem(SmallIconSet("window_new"),
+ i18n("New &Window"), SESSION_NEW_WINDOW_ID);
+ m_session->insertSeparator();
+ m_tabbarSessionsCommands->insertSeparator();
+
+ QIntDictIterator<KSimpleConfig> it( no2command );
+ for ( ; it.current(); ++it ) {
+ if ( it.currentKey() == SESSION_NEW_SHELL_ID )
+ continue;
+
+ QString txt = (*it).readEntry("Name");
+ QString icon = (*it).readEntry("Icon", "konsole");
+ insertItemSorted(m_tabbarSessionsCommands, SmallIconSet(icon),
+ txt.replace('&',"&&"), it.currentKey() );
+ QString comment = (*it).readEntry("Comment");
+ if (comment.isEmpty())
+ comment=txt.prepend(i18n("New "));
+ insertItemSorted(m_session, SmallIconSet(icon),
+ comment.replace('&',"&&"), it.currentKey());
+ }
+
+ if (m_bookmarksSession)
+ {
+ m_session->insertSeparator();
+ m_session->insertItem(SmallIconSet("keditbookmarks"),
+ i18n("New Shell at Bookmark"), m_bookmarksSession);
+ m_tabbarSessionsCommands->insertSeparator();
+ m_tabbarSessionsCommands->insertItem(SmallIconSet("keditbookmarks"),
+ i18n("Shell at Bookmark"), m_bookmarksSession);
+ }
+}
+
+void Konsole::addScreenSession(const QString &path, const QString &socket)
+{
+ KTempFile *tmpFile = new KTempFile();
+ tmpFile->setAutoDelete(true);
+ KSimpleConfig *co = new KSimpleConfig(tmpFile->name());
+ co->setDesktopGroup();
+ co->writeEntry("Name", socket);
+ QString txt = i18n("Screen is a program controlling screens!", "Screen at %1").arg(socket);
+ co->writeEntry("Comment", txt);
+ co->writePathEntry("Exec", QString::fromLatin1("SCREENDIR=%1 screen -r %2")
+ .arg(path).arg(socket));
+ QString icon = "konsole";
+ cmd_serial++;
+ m_session->insertItem( SmallIconSet( icon ), txt, cmd_serial, cmd_serial - 1 );
+ m_tabbarSessionsCommands->insertItem( SmallIconSet( icon ), txt, cmd_serial );
+ no2command.insert(cmd_serial,co);
+}
+
+void Konsole::loadScreenSessions()
+{
+ if (!kapp->authorize("shell_access"))
+ return;
+ QCString screenDir = getenv("SCREENDIR");
+ if (screenDir.isEmpty())
+ screenDir = QFile::encodeName(QDir::homeDirPath()) + "/.screen/";
+ // Some distributions add a shell function called screen that sets
+ // $SCREENDIR to ~/tmp. In this case the variable won't be set here.
+ if (!QFile::exists(screenDir))
+ screenDir = QFile::encodeName(QDir::homeDirPath()) + "/tmp/";
+ QStringList sessions;
+ // Can't use QDir as it doesn't support FIFOs :(
+ DIR *dir = opendir(screenDir);
+ if (dir)
+ {
+ struct dirent *entry;
+ while ((entry = readdir(dir)))
+ {
+ QCString path = screenDir + "/" + entry->d_name;
+ struct stat st;
+ if (stat(path, &st) != 0)
+ continue;
+
+ int fd;
+ if (S_ISFIFO(st.st_mode) && !(st.st_mode & 0111) && // xbit == attached
+ (fd = open(path, O_WRONLY | O_NONBLOCK)) != -1)
+ {
+ ::close(fd);
+ sessions.append(QFile::decodeName(entry->d_name));
+ }
+ }
+ closedir(dir);
+ }
+ resetScreenSessions();
+ for (QStringList::ConstIterator it = sessions.begin(); it != sessions.end(); ++it)
+ addScreenSession(screenDir, *it);
+}
+
+void Konsole::resetScreenSessions()
+{
+ if (cmd_first_screen == -1)
+ cmd_first_screen = cmd_serial + 1;
+ else
+ {
+ for (int i = cmd_first_screen; i <= cmd_serial; ++i)
+ {
+ m_session->removeItem(i);
+ if (m_tabbarSessionsCommands)
+ m_tabbarSessionsCommands->removeItem(i);
+ no2command.remove(i);
+ }
+ cmd_serial = cmd_first_screen - 1;
+ }
+}
+
+// --| Schema support |-------------------------------------------------------
+
+void Konsole::setSchema(int numb, TEWidget* tewidget)
+{
+ ColorSchema* s = colors->find(numb);
+ if (!s)
+ {
+ s = (ColorSchema*)colors->at(0);
+ kdWarning() << "No schema with serial #"<<numb<<", using "<<s->relPath()<<" (#"<<s->numb()<<")." << endl;
+ s_kconfigSchema = s->relPath();
+ }
+
+ if (s->hasSchemaFileChanged())
+ {
+ const_cast<ColorSchema *>(s)->rereadSchemaFile();
+ }
+ if (s) setSchema(s, tewidget);
+}
+
+void Konsole::setSchema(const QString & path)
+{
+ ColorSchema* s = colors->find(path);
+ if (!s)
+ {
+ s = (ColorSchema*)colors->at(0); //the default one
+ kdWarning() << "No schema with the name " <<path<<", using "<<s->relPath()<<endl;
+ s_kconfigSchema = s->relPath();
+ }
+ if (s->hasSchemaFileChanged())
+ {
+ const_cast<ColorSchema *>(s)->rereadSchemaFile();
+ }
+ if (s) setSchema(s);
+}
+
+// Called via main.cpp for session manager.
+void Konsole::setEncoding(int index)
+{
+ if ( selectSetEncoding ) {
+ selectSetEncoding->setCurrentItem(index);
+ slotSetEncoding();
+ }
+}
+
+void Konsole::setSchema(ColorSchema* s, TEWidget* tewidget)
+{
+ if (!s) return;
+ if (!tewidget) tewidget=te;
+
+ if (tewidget==te) {
+ if (m_schema)
+ {
+ m_schema->setItemChecked(curr_schema,false);
+ m_schema->setItemChecked(s->numb(),true);
+ }
+
+ s_schema = s->relPath();
+ curr_schema = s->numb();
+ pmPath = s->imagePath();
+ }
+ tewidget->setColorTable(s->table()); //FIXME: set twice here to work around a bug
+
+ if (s->useTransparency()) {
+ if (!argb_visual) {
+ if (!rootxpms[tewidget])
+ rootxpms.insert( tewidget, new KRootPixmap(tewidget) );
+ rootxpms[tewidget]->setFadeEffect(s->tr_x(), QColor(s->tr_r(), s->tr_g(), s->tr_b()));
+ } else {
+ tewidget->setBlendColor(qRgba(s->tr_r(), s->tr_g(), s->tr_b(), int(s->tr_x() * 255)));
+ tewidget->setErasePixmap( QPixmap() ); // make sure any background pixmap is unset
+ }
+ } else {
+ if (rootxpms[tewidget]) {
+ delete rootxpms[tewidget];
+ rootxpms.remove(tewidget);
+ }
+ pixmap_menu_activated(s->alignment(), tewidget);
+ tewidget->setBlendColor(qRgba(0, 0, 0, 0xff));
+ }
+
+ tewidget->setColorTable(s->table());
+ QPtrListIterator<TESession> ses_it(sessions);
+ for (; ses_it.current(); ++ses_it)
+ if (tewidget==ses_it.current()->widget()) {
+ ses_it.current()->setSchemaNo(s->numb());
+ break;
+ }
+}
+
+void Konsole::slotDetachSession()
+{
+ detachSession();
+}
+
+void Konsole::detachSession(TESession* _se) {
+ if (!_se) _se=se;
+
+ KRadioAction *ra = session2action.find(_se);
+ ra->unplug(m_view);
+ TEWidget* se_widget = _se->widget();
+ session2action.remove(_se);
+ action2session.remove(ra);
+ int sessionIndex = sessions.findRef(_se);
+ sessions.remove(_se);
+ delete ra;
+
+ if ( _se->isMasterMode() ) {
+ // Disable master mode when detaching master
+ setMasterMode(false);
+ } else {
+ QPtrListIterator<TESession> from_it(sessions);
+ for(; from_it.current(); ++from_it) {
+ TESession *from = from_it.current();
+ if(from->isMasterMode())
+ disconnect(from->widget(), SIGNAL(keyPressedSignal(QKeyEvent*)),
+ _se->getEmulation(), SLOT(onKeyPress(QKeyEvent*)));
+ }
+ }
+
+ QColor se_tabtextcolor = tabwidget->tabColor( _se->widget() );
+
+ disconnect( _se,SIGNAL(done(TESession*)),
+ this,SLOT(doneSession(TESession*)) );
+
+ disconnect( _se->getEmulation(),SIGNAL(ImageSizeChanged(int,int)), this,SLOT(notifySize(int,int)));
+ disconnect( _se->getEmulation(),SIGNAL(changeColLin(int, int)), this,SLOT(changeColLin(int,int)) );
+ disconnect( _se->getEmulation(),SIGNAL(changeColumns(int)), this,SLOT(changeColumns(int)) );
+ disconnect( _se, SIGNAL(changeTabTextColor(TESession*, int)), this, SLOT(changeTabTextColor(TESession*, int)) );
+
+ disconnect( _se,SIGNAL(updateTitle(TESession*)), this,SLOT(updateTitle(TESession*)) );
+ disconnect( _se,SIGNAL(notifySessionState(TESession*,int)), this,SLOT(notifySessionState(TESession*,int)) );
+ disconnect( _se,SIGNAL(disableMasterModeConnections()), this,SLOT(disableMasterModeConnections()) );
+ disconnect( _se,SIGNAL(enableMasterModeConnections()), this,SLOT(enableMasterModeConnections()) );
+ disconnect( _se,SIGNAL(renameSession(TESession*,const QString&)), this,SLOT(slotRenameSession(TESession*,const QString&)) );
+
+ // TODO: "type" isn't passed properly
+ Konsole* konsole = new Konsole(name(), b_histEnabled, !menubar->isHidden(), n_tabbar != TabNone, b_framevis,
+ n_scroll != TEWidget::SCRNONE, 0, false, 0);
+ konsole->enableFullScripting(b_fullScripting);
+ // TODO; Make this work: konsole->enableFixedSize(b_fixedSize);
+ konsole->resize(size());
+ konsole->show();
+ konsole->attachSession(_se);
+ konsole->activateSession(_se);
+ konsole->changeTabTextColor( _se, se_tabtextcolor.rgb() );//restore prev color
+ konsole->slotTabSetViewOptions(m_tabViewMode);
+
+ if (_se==se) {
+ if (se == se_previous)
+ se_previous=NULL;
+
+ // pick a new session
+ if (se_previous)
+ se = se_previous;
+ else
+ se = sessions.at(sessionIndex ? sessionIndex - 1 : 0);
+ session2action.find(se)->setChecked(true);
+ QTimer::singleShot(1,this,SLOT(activateSession()));
+ }
+
+ if (sessions.count()==1)
+ m_detachSession->setEnabled(false);
+
+ tabwidget->removePage( se_widget );
+ if (rootxpms[se_widget]) {
+ delete rootxpms[se_widget];
+ rootxpms.remove(se_widget);
+ }
+ delete se_widget;
+ if (b_dynamicTabHide && tabwidget->count()==1)
+ tabwidget->setTabBarHidden(true);
+
+ if( m_removeSessionButton )
+ m_removeSessionButton->setEnabled(tabwidget->count()>1);
+}
+
+void Konsole::attachSession(TESession* session)
+{
+ if (b_dynamicTabHide && sessions.count()==1 && n_tabbar!=TabNone)
+ tabwidget->setTabBarHidden(false);
+
+ TEWidget* se_widget = session->widget();
+
+ te=new TEWidget(tabwidget);
+
+ connect( te, SIGNAL(configureRequest(TEWidget*, int, int, int)),
+ this, SLOT(configureRequest(TEWidget*,int,int,int)) );
+
+ te->resize(se_widget->size());
+ te->setSize(se_widget->Columns(), se_widget->Lines());
+ initTEWidget(te, se_widget);
+ session->changeWidget(te);
+ te->setFocus();
+ createSessionTab(te, SmallIconSet(session->IconName()), session->Title());
+ setSchema(session->schemaNo());
+ if (session->isMasterMode()) {
+ disableMasterModeConnections(); // no duplicate connections, remove old
+ enableMasterModeConnections();
+ }
+
+ QString title=session->Title();
+ KRadioAction *ra = new KRadioAction(title.replace('&',"&&"), session->IconName(),
+ 0, this, SLOT(activateSession()), m_shortcuts);
+
+ ra->setExclusiveGroup("sessions");
+ ra->setChecked(true);
+
+ action2session.insert(ra, session);
+ session2action.insert(session,ra);
+ sessions.append(session);
+ if (sessions.count()>1)
+ m_detachSession->setEnabled(true);
+
+ if (m_menuCreated)
+ ra->plug(m_view);
+
+ connect( session,SIGNAL(done(TESession*)),
+ this,SLOT(doneSession(TESession*)) );
+
+ connect( session,SIGNAL(updateTitle(TESession*)), this,SLOT(updateTitle(TESession*)) );
+ connect( session,SIGNAL(notifySessionState(TESession*,int)), this,SLOT(notifySessionState(TESession*,int)) );
+
+ connect( session,SIGNAL(disableMasterModeConnections()), this,SLOT(disableMasterModeConnections()) );
+ connect( session,SIGNAL(enableMasterModeConnections()), this,SLOT(enableMasterModeConnections()) );
+ connect( session,SIGNAL(renameSession(TESession*,const QString&)), this,SLOT(slotRenameSession(TESession*,const QString&)) );
+ connect( session->getEmulation(),SIGNAL(ImageSizeChanged(int,int)), this,SLOT(notifySize(int,int)));
+ connect( session->getEmulation(),SIGNAL(changeColumns(int)), this,SLOT(changeColumns(int)) );
+ connect( session->getEmulation(),SIGNAL(changeColLin(int, int)), this,SLOT(changeColLin(int,int)) );
+
+ connect( session, SIGNAL(changeTabTextColor(TESession*, int)), this, SLOT(changeTabTextColor(TESession*, int)) );
+
+ activateSession(session);
+}
+
+void Konsole::setSessionTitle( QString& title, TESession* ses )
+{
+ if ( !ses )
+ ses = se;
+ ses->setTitle( title );
+ slotRenameSession( ses, title );
+}
+
+void Konsole::renameSession(TESession* ses) {
+ QString title = ses->Title();
+ bool ok;
+
+ title = KInputDialog::getText( i18n( "Rename Session" ),
+ i18n( "Session name:" ), title, &ok, this );
+
+ if (!ok) return;
+
+ ses->setTitle(title);
+ slotRenameSession(ses,title);
+}
+
+void Konsole::slotRenameSession() {
+ renameSession(se);
+}
+
+void Konsole::slotRenameSession(TESession* ses, const QString &name)
+{
+ KRadioAction *ra = session2action.find(ses);
+ QString title=name;
+ title=title.replace('&',"&&");
+ ra->setText(title);
+ ra->setIcon( ses->IconName() ); // I don't know why it is needed here
+ if (m_tabViewMode!=ShowIconOnly)
+ tabwidget->setTabLabel( ses->widget(), title );
+ updateTitle();
+}
+
+
+void Konsole::slotClearAllSessionHistories() {
+ for (TESession *_se = sessions.first(); _se; _se = sessions.next())
+ _se->clearHistory();
+}
+
+//////////////////////////////////////////////////////////////////////
+
+HistoryTypeDialog::HistoryTypeDialog(const HistoryType& histType,
+ unsigned int histSize,
+ QWidget *parent)
+ : KDialogBase(Plain, i18n("History Configuration"),
+ Help | Default | Ok | Cancel, Ok,
+ parent, 0, true, true)
+{
+ QFrame *mainFrame = plainPage();
+
+ QHBoxLayout *hb = new QHBoxLayout(mainFrame);
+
+ m_btnEnable = new QCheckBox(i18n("&Enable"), mainFrame);
+ connect(m_btnEnable, SIGNAL(toggled(bool)), SLOT(slotHistEnable(bool)));
+
+ m_label = new QLabel(i18n("&Number of lines: "), mainFrame);
+
+ m_size = new QSpinBox(0, 10 * 1000 * 1000, 100, mainFrame);
+ m_size->setValue(histSize);
+ m_size->setSpecialValueText(i18n("Unlimited (number of lines)", "Unlimited"));
+
+ m_label->setBuddy( m_size );
+
+ m_setUnlimited = new QPushButton(i18n("&Set Unlimited"), mainFrame);
+ connect( m_setUnlimited,SIGNAL(clicked()), this,SLOT(slotSetUnlimited()) );
+
+ hb->addWidget(m_btnEnable);
+ hb->addSpacing(10);
+ hb->addWidget(m_label);
+ hb->addWidget(m_size);
+ hb->addSpacing(10);
+ hb->addWidget(m_setUnlimited);
+
+ if ( ! histType.isOn()) {
+ m_btnEnable->setChecked(false);
+ slotHistEnable(false);
+ } else {
+ m_btnEnable->setChecked(true);
+ m_size->setValue(histType.getSize());
+ slotHistEnable(true);
+ }
+ setHelp("configure-history");
+}
+
+void HistoryTypeDialog::slotDefault()
+{
+ m_btnEnable->setChecked(true);
+ m_size->setValue(DEFAULT_HISTORY_SIZE);
+ slotHistEnable(true);
+}
+
+void HistoryTypeDialog::slotHistEnable(bool b)
+{
+ m_label->setEnabled(b);
+ m_size->setEnabled(b);
+ m_setUnlimited->setEnabled(b);
+ if (b) m_size->setFocus();
+}
+
+void HistoryTypeDialog::slotSetUnlimited()
+{
+ m_size->setValue(0);
+}
+
+unsigned int HistoryTypeDialog::nbLines() const
+{
+ return m_size->value();
+}
+
+bool HistoryTypeDialog::isOn() const
+{
+ return m_btnEnable->isChecked();
+}
+
+void Konsole::slotHistoryType()
+{
+ if (!se) return;
+
+ HistoryTypeDialog dlg(se->history(), m_histSize, this);
+ if (dlg.exec()) {
+ m_clearHistory->setEnabled( dlg.isOn() );
+ m_findHistory->setEnabled( dlg.isOn() );
+ m_findNext->setEnabled( dlg.isOn() );
+ m_findPrevious->setEnabled( dlg.isOn() );
+ m_saveHistory->setEnabled( dlg.isOn() );
+ if (dlg.isOn()) {
+ if (dlg.nbLines() > 0) {
+ se->setHistory(HistoryTypeBuffer(dlg.nbLines()));
+ m_histSize = dlg.nbLines();
+ b_histEnabled = true;
+
+ } else {
+
+ se->setHistory(HistoryTypeFile());
+ m_histSize = 0;
+ b_histEnabled = true;
+
+ }
+
+ } else {
+
+ se->setHistory(HistoryTypeNone());
+ m_histSize = dlg.nbLines();
+ b_histEnabled = false;
+
+ }
+ }
+}
+
+void Konsole::slotClearHistory()
+{
+ se->clearHistory();
+}
+
+void Konsole::slotFindHistory()
+{
+ if( !m_finddialog ) {
+ m_finddialog = new KonsoleFind( this, "konsolefind", false);
+ connect(m_finddialog,SIGNAL(search()),this,SLOT(slotFind()));
+ connect(m_finddialog,SIGNAL(done()),this,SLOT(slotFindDone()));
+ }
+
+ QString string;
+ string = m_finddialog->getText();
+ m_finddialog->setText(string.isEmpty() ? m_find_pattern : string);
+
+ m_find_first = true;
+ m_find_found = false;
+
+ m_finddialog->show();
+ m_finddialog->result();
+}
+
+void Konsole::slotFindNext()
+{
+ if( !m_finddialog ) {
+ slotFindHistory();
+ return;
+ }
+
+ QString string;
+ string = m_finddialog->getText();
+ m_finddialog->setText(string.isEmpty() ? m_find_pattern : string);
+
+ slotFind();
+}
+
+void Konsole::slotFindPrevious()
+{
+ if( !m_finddialog ) {
+ slotFindHistory();
+ return;
+ }
+
+ QString string;
+ string = m_finddialog->getText();
+ m_finddialog->setText(string.isEmpty() ? m_find_pattern : string);
+
+ m_finddialog->setDirection( !m_finddialog->get_direction() );
+ slotFind();
+ m_finddialog->setDirection( !m_finddialog->get_direction() );
+}
+
+void Konsole::slotFind()
+{
+ if (m_find_first) {
+ se->getEmulation()->findTextBegin();
+ m_find_first = false;
+ }
+
+ bool forward = !m_finddialog->get_direction();
+ m_find_pattern = m_finddialog->getText();
+
+ if (se->getEmulation()->findTextNext(m_find_pattern,forward,
+ m_finddialog->case_sensitive(),m_finddialog->reg_exp()))
+ m_find_found = true;
+ else
+ if (m_find_found) {
+ if (forward) {
+ if ( KMessageBox::questionYesNo( m_finddialog,
+ i18n("End of history reached.\n" "Continue from the beginning?"),
+ i18n("Find"), KStdGuiItem::cont(), KStdGuiItem::cancel() ) == KMessageBox::Yes ) {
+ m_find_first = true;
+ slotFind();
+ }
+ }
+ else {
+ if ( KMessageBox::questionYesNo( m_finddialog,
+ i18n("Beginning of history reached.\n" "Continue from the end?"),
+ i18n("Find"), KStdGuiItem::cont(), KStdGuiItem::cancel() ) == KMessageBox::Yes ) {
+ m_find_first = true;
+ slotFind();
+ }
+ }
+ }
+ else
+ KMessageBox::information( m_finddialog,
+ i18n( "Search string '%1' not found." ).arg(KStringHandler::csqueeze(m_find_pattern)),
+ i18n( "Find" ) );
+}
+
+void Konsole::slotFindDone()
+{
+ if (!m_finddialog)
+ return;
+
+ se->getEmulation()->clearSelection();
+ m_finddialog->hide();
+}
+
+void Konsole::slotSaveHistory()
+{
+ // FIXME - mostLocalURL can't handle non-existing files yet, so this
+ // code doesn't work.
+ KURL s_url = KFileDialog::getSaveURL(QString::null, QString::null, 0L, i18n("Save History"));
+ if( s_url.isEmpty())
+ return;
+ KURL url = KIO::NetAccess::mostLocalURL( s_url, 0 );
+
+ if( !url.isLocalFile() ) {
+ KMessageBox::sorry(this, i18n("This is not a local file.\n"));
+ return;
+ }
+
+ int query = KMessageBox::Continue;
+ QFileInfo info;
+ QString name( url.path() );
+ info.setFile( name );
+ if( info.exists() )
+ query = KMessageBox::warningContinueCancel( this,
+ i18n( "A file with this name already exists.\nDo you want to overwrite it?" ), i18n("File Exists"), i18n("Overwrite") );
+
+ if (query==KMessageBox::Continue) {
+ QFile file(url.path());
+ if(!file.open(IO_WriteOnly)) {
+ KMessageBox::sorry(this, i18n("Unable to write to file."));
+ return;
+ }
+
+ QTextStream textStream(&file);
+ assert( se && se->getEmulation() );
+ se->getEmulation()->streamHistory( &textStream );
+
+ file.close();
+ if(file.status()) {
+ KMessageBox::sorry(this, i18n("Could not save history."));
+ return;
+ }
+ }
+}
+
+void Konsole::slotZModemUpload()
+{
+ if (se->zmodemIsBusy())
+ {
+ KMessageBox::sorry(this,
+ i18n("<p>The current session already has a ZModem file transfer in progress."));
+ return;
+ }
+ QString zmodem = KGlobal::dirs()->findExe("sz");
+ if (zmodem.isEmpty())
+ zmodem = KGlobal::dirs()->findExe("lsz");
+ if (zmodem.isEmpty())
+ {
+ KMessageBox::sorry(this,
+ i18n("<p>No suitable ZModem software was found on "
+ "the system.\n"
+ "<p>You may wish to install the 'rzsz' or 'lrzsz' package.\n"));
+ return;
+ }
+
+ QStringList files = KFileDialog::getOpenFileNames(QString::null, QString::null, this,
+ i18n("Select Files to Upload"));
+ if (files.isEmpty())
+ return;
+
+ se->startZModem(zmodem, QString::null, files);
+}
+
+void Konsole::slotZModemDetected(TESession *session)
+{
+ if (!kapp->authorize("zmodem_download")) return;
+
+ if(se != session)
+ activateSession(session);
+
+ QString zmodem = KGlobal::dirs()->findExe("rz");
+ if (zmodem.isEmpty())
+ zmodem = KGlobal::dirs()->findExe("lrz");
+ if (zmodem.isEmpty())
+ {
+ KMessageBox::information(this,
+ i18n("<p>A ZModem file transfer attempt has been detected, "
+ "but no suitable ZModem software was found on "
+ "the system.\n"
+ "<p>You may wish to install the 'rzsz' or 'lrzsz' package.\n"));
+ return;
+ }
+ KURLRequesterDlg dlg(KGlobalSettings::documentPath(),
+ i18n("A ZModem file transfer attempt has been detected.\n"
+ "Please specify the folder you want to store the file(s):"),
+ this, "zmodem_dlg");
+ dlg.setButtonOK(KGuiItem( i18n("&Download"),
+ i18n("Start downloading file to specified folder."),
+ i18n("Start downloading file to specified folder.")));
+ if (!dlg.exec())
+ {
+ session->cancelZModem();
+ }
+ else
+ {
+ const KURL &url = dlg.selectedURL();
+ session->startZModem(zmodem, url.path(), QStringList());
+ }
+}
+
+void Konsole::slotPrint()
+{
+ KPrinter printer;
+ printer.addDialogPage(new PrintSettings());
+ if (printer.setup(this, i18n("Print %1").arg(se->Title())))
+ {
+ printer.setFullPage(false);
+ printer.setCreator("Konsole");
+ QPainter paint;
+ paint.begin(&printer);
+ se->print(paint, printer.option("app-konsole-printfriendly") == "true",
+ printer.option("app-konsole-printexact") == "true");
+ paint.end();
+ }
+}
+
+void Konsole::toggleBidi()
+{
+ b_bidiEnabled=!b_bidiEnabled;
+ QPtrList<TEWidget> tes = activeTEs();
+ for (TEWidget *_te = tes.first(); _te; _te = tes.next()) {
+ _te->setBidiEnabled(b_bidiEnabled);
+ _te->repaint();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+
+SizeDialog::SizeDialog(const unsigned int columns,
+ const unsigned int lines,
+ QWidget *parent)
+ : KDialogBase(Plain, i18n("Size Configuration"),
+ Help | Default | Ok | Cancel, Ok,
+ parent)
+{
+ QFrame *mainFrame = plainPage();
+
+ QHBoxLayout *hb = new QHBoxLayout(mainFrame);
+
+ m_columns = new QSpinBox(20,1000,1,mainFrame);
+ m_columns->setValue(columns);
+
+ m_lines = new QSpinBox(4,1000,1,mainFrame);
+ m_lines->setValue(lines);
+
+ hb->addWidget(new QLabel(i18n("Number of columns:"), mainFrame));
+ hb->addWidget(m_columns);
+ hb->addSpacing(10);
+ hb->addWidget(new QLabel(i18n("Number of lines:"), mainFrame));
+ hb->addWidget(m_lines);
+
+ setHelp("configure-size");
+}
+
+void SizeDialog::slotDefault()
+{
+ m_columns->setValue(80);
+ m_lines->setValue(24);
+}
+
+unsigned int SizeDialog::columns() const
+{
+ return m_columns->value();
+}
+
+unsigned int SizeDialog::lines() const
+{
+ return m_lines->value();
+}
+
+//////////////////////////////////////////////////////////////////////
+
+KonsoleFind::KonsoleFind( QWidget *parent, const char *name, bool /*modal*/ )
+ : KEdFind( parent, name, false ), m_editorDialog(0), m_editRegExp(0)
+{
+ QHBox* row = new QHBox( (QWidget*)group );
+ m_asRegExp = new QCheckBox( i18n("As &regular expression"), row, "asRegexp" );
+
+ if (!KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty()) {
+ m_editRegExp = new QPushButton( i18n("&Edit..."), row, "editRegExp" );
+ connect( m_asRegExp, SIGNAL( toggled(bool) ), m_editRegExp, SLOT( setEnabled(bool) ) );
+ connect( m_editRegExp, SIGNAL( clicked() ), this, SLOT( slotEditRegExp() ) );
+ m_editRegExp->setEnabled( false );
+ }
+}
+
+void KonsoleFind::slotEditRegExp()
+{
+ if ( m_editorDialog == 0 )
+ m_editorDialog = KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor", QString::null, this );
+
+ assert( m_editorDialog );
+
+ KRegExpEditorInterface *iface = dynamic_cast<KRegExpEditorInterface *>( m_editorDialog );
+ assert( iface );
+
+ iface->setRegExp( getText() );
+ bool ret = m_editorDialog->exec();
+ if ( ret == QDialog::Accepted)
+ setText( iface->regExp() );
+}
+
+bool KonsoleFind::reg_exp() const
+{
+ return m_asRegExp->isChecked();
+}
+
+///////////////////////////////////////////////////////////
+// This was to apply changes made to KControl fixed font to all TEs...
+// kvh - 03/10/2005 - We don't do this anymore...
+void Konsole::slotFontChanged()
+{
+ TEWidget *oldTe = te;
+ QPtrList<TEWidget> tes = activeTEs();
+ for (TEWidget *_te = tes.first(); _te; _te = tes.next()) {
+ te = _te;
+// setFont(n_font);
+ }
+ te = oldTe;
+}
+
+void Konsole::biggerFont(void) {
+ if ( !se ) return;
+
+ QFont f = te->getVTFont();
+ f.setPointSize( f.pointSize() + 1 );
+ te->setVTFont( f );
+ activateSession();
+}
+
+void Konsole::smallerFont(void) {
+ if ( !se ) return;
+
+ QFont f = te->getVTFont();
+ if ( f.pointSize() < 6 ) return; // A minimum size
+ f.setPointSize( f.pointSize() - 1 );
+ te->setVTFont( f );
+ activateSession();
+}
+
+bool Konsole::processDynamic(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData)
+{
+ if (b_fullScripting)
+ {
+ if (fun == "feedAllSessions(QString)")
+ {
+ QString arg0;
+ QDataStream arg( data, IO_ReadOnly );
+ arg >> arg0;
+ feedAllSessions(arg0);
+ replyType = "void";
+ return true;
+ }
+ else if (fun == "sendAllSessions(QString)")
+ {
+ QString arg0;
+ QDataStream arg( data, IO_ReadOnly );
+ arg >> arg0;
+ sendAllSessions(arg0);
+ replyType = "void";
+ return true;
+ }
+ }
+ return KonsoleIface::processDynamic(fun, data, replyType, replyData);
+}
+
+QCStringList Konsole::functionsDynamic()
+{
+ QCStringList funcs = KonsoleIface::functionsDynamic();
+ if (b_fullScripting)
+ {
+ funcs << "void feedAllSessions(QString text)";
+ funcs << "void sendAllSessions(QString text)";
+ }
+ return funcs;
+}
+
+void Konsole::enableFullScripting(bool b)
+{
+ b_fullScripting = b;
+ for (TESession *_se = sessions.first(); _se; _se = sessions.next())
+ _se->enableFullScripting(b);
+}
+
+void Konsole::enableFixedSize(bool b)
+{
+ b_fixedSize = b;
+ if (b_fixedSize)
+ {
+ delete m_fullscreen;
+ m_fullscreen = 0;
+ }
+}
+
+QPtrList<TEWidget> Konsole::activeTEs()
+{
+ QPtrList<TEWidget> ret;
+ if (sessions.count()>0)
+ for (TESession *_se = sessions.first(); _se; _se = sessions.next())
+ ret.append(_se->widget());
+ else if (te) // check for startup initalization case in newSession()
+ ret.append(te);
+ return ret;
+}
+
+#include "konsole.moc"
diff --git a/konsole/konsole/konsole.h b/konsole/konsole/konsole.h
new file mode 100644
index 000000000..df9157f7b
--- /dev/null
+++ b/konsole/konsole/konsole.h
@@ -0,0 +1,501 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1996 by Matthias Ettrich <ettrich@kde.org>
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+/* The material contained in here more or less directly orginates from */
+/* kvt, which is copyright (c) 1996 by Matthias Ettrich <ettrich@kde.org> */
+/* */
+
+#ifndef KONSOLE_H
+#define KONSOLE_H
+
+
+#include <kmainwindow.h>
+#include <kdialogbase.h>
+#include <ksimpleconfig.h>
+#include <keditcl.h>
+
+#include <kwinmodule.h>
+
+#include <qstrlist.h>
+#include <qintdict.h>
+#include <qptrdict.h>
+#include <qsignalmapper.h>
+
+#include "TEPty.h"
+#include "TEWidget.h"
+#include "TEmuVt102.h"
+#include "session.h"
+#include "schema.h"
+#include "konsolebookmarkmenu.h"
+#include "konsolebookmarkhandler.h"
+
+#include "konsoleiface.h"
+
+#define KONSOLE_VERSION "1.6.6"
+
+class KRootPixmap;
+class QLabel;
+class QCheckBox;
+class KonsoleFind;
+class KPopupMenu;
+class KAction;
+class KToggleAction;
+class KSelectAction;
+class KRadioAction;
+class KTabWidget;
+class QToolButton;
+
+// Defined in main.C
+const char *konsole_shell(QStrList &args);
+
+class Konsole : public KMainWindow, virtual public KonsoleIface
+{
+ Q_OBJECT
+
+ friend class KonsoleSessionManaged;
+public:
+
+ Konsole(const char * name, int histon, bool menubaron, bool tabbaron,
+ bool frameon, bool scrollbaron,
+ QCString type = 0, bool b_inRestore = false, const int wanted_tabbar = 0,
+ const QString &workdir=QString::null);
+
+ ~Konsole();
+ void setColLin(int columns, int lines);
+ void setAutoClose(bool on);
+ void initFullScreen();
+ void initSessionFont(int fontNo);
+ void initSessionFont(QFont f);
+ void initSessionKeyTab(const QString &keyTab);
+ void initMonitorActivity(bool on);
+ void initMonitorSilence(bool on);
+ void initMasterMode(bool on);
+ void initTabColor(QColor color);
+ void initHistory(int lines, bool enable);
+ void newSession(const QString &program, const QStrList &args, const QString &term, const QString &icon, const QString &title, const QString &cwd);
+ void setSchema(const QString & path);
+ void setEncoding(int);
+ void setSessionTitle(QString&, TESession* = 0);
+ void setSessionEncoding(const QString&, TESession* = 0);
+
+ void enableFullScripting(bool b);
+ void enableFixedSize(bool b);
+
+ void setDefaultSession(const QString &filename);
+ void showTipOnStart();
+
+ // Additional functions for DCOP
+ int sessionCount() { return sessions.count(); }
+
+ QString currentSession();
+ QString newSession(const QString &type);
+ QString sessionId(const int position);
+
+ void activateSession(const QString& sessionId);
+ void feedAllSessions(const QString &text);
+ void sendAllSessions(const QString &text);
+
+ KURL baseURL() const;
+
+ virtual bool processDynamic(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData);
+ virtual QCStringList functionsDynamic();
+
+ void callReadPropertiesInternal(KConfig *config, int number) { readPropertiesInternal(config,number); }
+
+ enum TabPosition { TabNone, TabTop, TabBottom };
+ enum TabViewModes { ShowIconAndText = 0, ShowTextOnly = 1, ShowIconOnly = 2 };
+
+public slots:
+ void activateSession(int position);
+ void activateSession(QWidget*);
+ void slotUpdateSessionConfig(TESession *session);
+ void slotResizeSession(TESession*, QSize);
+ void slotSetSessionEncoding(TESession *session, const QString &encoding);
+ void slotGetSessionSchema(TESession *session, QString &schema);
+ void slotSetSessionSchema(TESession *session, const QString &schema);
+
+ void makeGUI();
+ QString newSession();
+
+protected:
+
+ bool queryClose();
+ void saveProperties(KConfig* config);
+ void readProperties(KConfig* config);
+
+private slots:
+ void configureRequest(TEWidget*,int,int,int);
+ void activateSession();
+ void activateSession(TESession*);
+ void closeCurrentSession();
+ void confirmCloseCurrentSession(TESession* _se=0);
+ void doneSession(TESession*);
+ void slotCouldNotClose();
+ void toggleFullScreen();
+ bool fullScreen();
+ void setFullScreen(bool on);
+ void schema_menu_activated(int item);
+ void pixmap_menu_activated(int item, TEWidget* tewidget=0);
+ void keytab_menu_activated(int item);
+ void schema_menu_check();
+ void attachSession(TESession*);
+ void slotDetachSession();
+ void bookmarks_menu_check();
+ void newSession(int kind);
+ void newSessionTabbar(int kind);
+ void updateSchemaMenu();
+ void updateKeytabMenu();
+ void updateRMBMenu();
+
+ void changeTabTextColor(TESession*, int);
+ void changeColumns(int);
+ void changeColLin(int columns, int lines);
+ void notifySessionState(TESession* session,int state);
+ void notifySize(int columns, int lines);
+ void updateTitle(TESession* _se=0);
+ void prevSession();
+ void nextSession();
+ void activateMenu();
+ void slotMovedTab(int,int);
+ void moveSessionLeft();
+ void moveSessionRight();
+ void allowPrevNext();
+ void setSchema(int n, TEWidget* tewidget=0); // no slot necessary?
+ void sendSignal(int n);
+ void slotClearTerminal();
+ void slotResetClearTerminal();
+ void slotSelectTabbar();
+ void slotToggleMenubar();
+ void slotRenameSession();
+ void slotRenameSession(TESession* ses, const QString &name);
+ void slotToggleMonitor();
+ void slotToggleMasterMode();
+ void slotClearAllSessionHistories();
+ void slotHistoryType();
+ void slotClearHistory();
+ void slotFindHistory();
+ void slotSaveHistory();
+ void slotSelectBell();
+ void slotSelectSize();
+ void slotSelectFont();
+ void slotInstallBitmapFonts();
+ void slotSelectScrollbar();
+ void loadScreenSessions();
+ void updateFullScreen(bool on);
+
+ void slotSaveSettings();
+ void slotSaveSessionsProfile();
+ void slotConfigureNotifications();
+ void slotConfigureKeys();
+ void slotConfigure();
+ void reparseConfiguration();
+
+ void disableMasterModeConnections();
+ void enableMasterModeConnections();
+ void enterURL( const QString&, const QString& );
+ void newSession( const QString&, const QString& );
+
+ void slotFind();
+ void slotFindDone();
+ void slotFindNext();
+ void slotFindPrevious();
+
+ void showTip();
+
+ void slotSetSelectionEnd() { te->setSelectionEnd(); }
+ void slotCopyClipboard() { te->copyClipboard(); }
+ void slotPasteClipboard() { te->pasteClipboard(); }
+ void slotPasteSelection() { te->pasteSelection(); }
+
+ void listSessions();
+ void switchToSession();
+
+ void biggerFont();
+ void smallerFont();
+
+ void slotZModemDetected(TESession *session);
+ void slotZModemUpload();
+
+ void slotPrint();
+
+ void toggleBidi();
+
+ void slotTabContextMenu(QWidget*, const QPoint &);
+ void slotTabDetachSession();
+ void slotTabRenameSession();
+ void slotTabSelectColor();
+ void slotTabCloseSession();
+ void slotTabToggleMonitor();
+ void slotTabToggleMasterMode();
+ void slotTabbarContextMenu(const QPoint &);
+ void slotTabSetViewOptions(int);
+ void slotTabbarToggleDynamicHide();
+ void slotToggleAutoResizeTabs();
+ void slotFontChanged();
+
+ void slotSetEncoding();
+private:
+ KSimpleConfig *defaultSession();
+ QString newSession(KSimpleConfig *co, QString pgm = QString::null, const QStrList &args = QStrList(),
+ const QString &_term = QString::null, const QString &_icon = QString::null,
+ const QString &_title = QString::null, const QString &_cwd = QString::null);
+ void readProperties(KConfig *config, const QString &schema, bool globalConfigOnly);
+ void applySettingsToGUI();
+ void makeTabWidget();
+ void makeBasicGUI();
+ void runSession(TESession* s);
+ void addSession(TESession* s);
+ void detachSession(TESession* _se=0);
+ void setColorPixmaps();
+ void renameSession(TESession* ses);
+
+ void setSchema(ColorSchema* s, TEWidget* tewidget=0);
+ void setMasterMode(bool _state, TESession* _se=0);
+
+ void buildSessionMenus();
+ void addSessionCommand(const QString & path);
+ void loadSessionCommands();
+ void createSessionMenus();
+ void addScreenSession(const QString & path, const QString & socket);
+ void resetScreenSessions();
+ void checkBitmapFonts();
+
+ void initTEWidget(TEWidget* new_te, TEWidget* default_te);
+
+ void createSessionTab(TEWidget *widget, const QIconSet& iconSet,
+ const QString &text, int index = -1);
+ QIconSet iconSetForSession(TESession *session) const;
+
+ bool eventFilter( QObject *o, QEvent *e );
+
+ QPtrList<TEWidget> activeTEs();
+
+ QPtrDict<TESession> action2session;
+ QPtrDict<KRadioAction> session2action;
+ QPtrList<TESession> sessions;
+
+ QIntDict<KSimpleConfig> no2command; //QT4 - convert to QList
+
+ KSimpleConfig* m_defaultSession;
+ QString m_defaultSessionFilename;
+
+ KTabWidget* tabwidget;
+ TEWidget* te; // the visible TEWidget, either sole one or one of many
+ TESession* se;
+ TESession* se_previous;
+ TESession* m_initialSession;
+ ColorSchemaList* colors;
+ QString s_encodingName;
+
+ QPtrDict<KRootPixmap> rootxpms;
+ KWinModule* kWinModule;
+
+ KMenuBar* menubar;
+ KStatusBar* statusbar;
+
+ KPopupMenu* m_session;
+ KPopupMenu* m_edit;
+ KPopupMenu* m_view;
+ KPopupMenu* m_bookmarks;
+ KPopupMenu* m_bookmarksSession;
+ KPopupMenu* m_options;
+ KPopupMenu* m_schema;
+ KPopupMenu* m_keytab;
+ KPopupMenu* m_tabbarSessionsCommands;
+ KPopupMenu* m_signals;
+ KPopupMenu* m_help;
+ KPopupMenu* m_rightButton;
+ KPopupMenu* m_sessionList;
+ KPopupMenu* m_tabPopupMenu;
+ KPopupMenu* m_tabPopupTabsMenu;
+ KPopupMenu* m_tabbarPopupMenu;
+
+ KAction *m_zmodemUpload;
+ KToggleAction *monitorActivity, *m_tabMonitorActivity;
+ KToggleAction *monitorSilence, *m_tabMonitorSilence;
+ KToggleAction *masterMode, *m_tabMasterMode;
+ KToggleAction *showMenubar;
+ KToggleAction *m_fullscreen;
+
+ KSelectAction *selectSize;
+ KSelectAction *selectFont;
+ KSelectAction *selectScrollbar;
+ KSelectAction *selectTabbar;
+ KSelectAction *selectBell;
+ KSelectAction *selectSetEncoding;
+
+ KAction *m_clearHistory;
+ KAction *m_findHistory;
+ KAction *m_findNext;
+ KAction *m_findPrevious;
+ KAction *m_saveHistory;
+ KAction *m_detachSession;
+ KAction *m_moveSessionLeft;
+ KAction *m_moveSessionRight;
+
+ KAction *m_copyClipboard;
+ KAction *m_pasteClipboard;
+ KAction *m_pasteSelection;
+ KAction *m_clearTerminal;
+ KAction *m_resetClearTerminal;
+ KAction *m_clearAllSessionHistories;
+ KAction *m_renameSession;
+ KAction *m_saveProfile;
+ KAction *m_closeSession;
+ KAction *m_print;
+ KAction *m_quit;
+ KAction *m_tabDetachSession;
+
+ KActionCollection *m_shortcuts;
+
+ KonsoleBookmarkHandler *bookmarkHandler;
+ KonsoleBookmarkHandler *bookmarkHandlerSession;
+
+ KonsoleFind* m_finddialog;
+ bool m_find_first;
+ bool m_find_found;
+ QString m_find_pattern;
+
+ int cmd_serial;
+ int cmd_first_screen;
+ int n_keytab;
+ int n_defaultKeytab;
+ int n_scroll;
+ int n_tabbar;
+ int n_bell;
+ int n_render;
+ int curr_schema; // current schema no
+ int wallpaperSource;
+ int sessionIdCounter;
+ int monitorSilenceSeconds;
+
+ QString s_schema;
+ QString s_kconfigSchema;
+ QString s_word_seps; // characters that are considered part of a word
+ QString pmPath; // pixmap path
+ QString dropText;
+ QFont defaultFont;
+ QSize defaultSize;
+
+ QRect _saveGeometry;
+
+ QTimer m_closeTimeout;
+
+ TabViewModes m_tabViewMode;
+ bool b_dynamicTabHide;
+ bool b_autoResizeTabs;
+ bool b_installBitmapFonts;
+
+ bool b_framevis:1;
+ bool b_fullscreen:1;
+ bool m_menuCreated:1;
+ bool b_warnQuit:1;
+ bool isRestored:1;
+ bool b_allowResize:1; // Whether application may resize
+ bool b_fixedSize:1; // Whether user may resize
+ bool b_addToUtmp:1;
+ bool b_xonXoff:1;
+ bool b_bidiEnabled:1;
+
+ bool b_histEnabled:1;
+ bool b_fullScripting:1;
+ bool b_showstartuptip:1;
+ bool b_sessionShortcutsEnabled:1;
+ bool b_sessionShortcutsMapped:1;
+ bool b_matchTabWinTitle:1;
+
+ unsigned int m_histSize;
+ int m_separator_id;
+
+ TESession* m_contextMenuSession;
+
+ QToolButton* m_newSessionButton;
+ QToolButton* m_removeSessionButton;
+ QPoint m_newSessionButtonMousePressPos;
+
+ QSignalMapper* sessionNumberMapper;
+ QStringList sl_sessionShortCuts;
+ QString s_workDir;
+
+ QColor m_tabColor;
+};
+
+class QSpinBox;
+
+class HistoryTypeDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ HistoryTypeDialog(const HistoryType& histType,
+ unsigned int histSize,
+ QWidget *parent);
+
+public slots:
+
+ void slotHistEnable(bool);
+ void slotDefault();
+ void slotSetUnlimited();
+
+ unsigned int nbLines() const;
+ bool isOn() const;
+
+protected:
+ QLabel* m_label;
+ QSpinBox* m_size;
+ QCheckBox* m_btnEnable;
+ QPushButton* m_setUnlimited;
+};
+
+class SizeDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ SizeDialog(unsigned int const columns,
+ unsigned int const lines,
+ QWidget *parent);
+
+public slots:
+ void slotDefault();
+
+ unsigned int columns() const;
+ unsigned int lines() const;
+
+protected:
+ QSpinBox* m_columns;
+ QSpinBox* m_lines;
+};
+
+class KonsoleFind : public KEdFind
+{
+ Q_OBJECT
+public:
+ KonsoleFind( QWidget *parent = 0, const char *name=0, bool modal=true );
+ bool reg_exp() const;
+
+private slots:
+ void slotEditRegExp();
+
+private:
+ QCheckBox* m_asRegExp;
+ QDialog* m_editorDialog;
+ QPushButton* m_editRegExp;
+};
+
+#endif
diff --git a/konsole/konsole/konsole_part.cpp b/konsole/konsole/konsole_part.cpp
new file mode 100644
index 000000000..bfb183935
--- /dev/null
+++ b/konsole/konsole/konsole_part.cpp
@@ -0,0 +1,1133 @@
+/*
+ This file is part of the KDE system
+ Copyright (C) 1999,2000 Boloni Laszlo <lboloni@cpe.ucf.edu>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ */
+
+#include "konsole_part.h"
+
+#include <assert.h>
+
+#include <qfile.h>
+#include <qlayout.h>
+#include <qwmatrix.h>
+
+#include <kaboutdata.h>
+#include <kcharsets.h>
+#include <kdebug.h>
+#include <kfontdialog.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <krun.h>
+#include <kstdaction.h>
+#include <qlabel.h>
+#include <kprocctrl.h>
+
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qpushbutton.h>
+#include <kpopupmenu.h>
+#include <krootpixmap.h>
+#include <kconfig.h>
+#include <kaction.h>
+
+// We can't use the ARGB32 visual when embedded in another application
+bool argb_visual = false;
+
+K_EXPORT_COMPONENT_FACTORY( libkonsolepart, konsoleFactory )
+
+/**
+ * We need one static instance of the factory for our C 'main' function
+ */
+KInstance *konsoleFactory::s_instance = 0L;
+KAboutData *konsoleFactory::s_aboutData = 0;
+
+konsoleFactory::konsoleFactory()
+{
+}
+
+konsoleFactory::~konsoleFactory()
+{
+ if (s_instance)
+ delete s_instance;
+
+ if ( s_aboutData )
+ delete s_aboutData;
+
+ s_instance = 0;
+ s_aboutData = 0;
+}
+
+KParts::Part *konsoleFactory::createPartObject(QWidget *parentWidget, const char *widgetName,
+ QObject *parent, const char *name, const char *classname,
+ const QStringList&)
+{
+// kdDebug(1211) << "konsoleFactory::createPart parentWidget=" << parentWidget << " parent=" << parent << endl;
+ KParts::Part *obj = new konsolePart(parentWidget, widgetName, parent, name, classname);
+ return obj;
+}
+
+KInstance *konsoleFactory::instance()
+{
+ if ( !s_instance )
+ {
+ s_aboutData = new KAboutData("konsole", I18N_NOOP("Konsole"), "1.5");
+ s_instance = new KInstance( s_aboutData );
+ }
+ return s_instance;
+}
+
+#define DEFAULT_HISTORY_SIZE 1000
+
+konsolePart::konsolePart(QWidget *_parentWidget, const char *widgetName, QObject *parent, const char *name, const char *classname)
+ : KParts::ReadOnlyPart(parent, name)
+,te(0)
+,se(0)
+,colors(0)
+,rootxpm(0)
+,blinkingCursor(0)
+,showFrame(0)
+,m_useKonsoleSettings(0)
+,selectBell(0)
+,selectLineSpacing(0)
+,selectScrollbar(0)
+,m_keytab(0)
+,m_schema(0)
+,m_signals(0)
+,m_options(0)
+,m_popupMenu(0)
+,b_useKonsoleSettings(false)
+,b_autoDestroy(true)
+,b_autoStartShell(true)
+,m_histSize(DEFAULT_HISTORY_SIZE)
+,m_runningShell( false )
+{
+ parentWidget=_parentWidget;
+ setInstance(konsoleFactory::instance());
+
+ m_extension = new konsoleBrowserExtension(this);
+
+ // This is needed since only konsole.cpp does it
+ // Without this -> crash on keypress... (David)
+ KeyTrans::loadAll();
+
+ m_streamEnabled = ( classname && strcmp( classname, "TerminalEmulator" ) == 0 );
+
+ QStrList eargs;
+
+
+ const char* shell = getenv("SHELL");
+ if (shell == NULL || *shell == '\0') shell = "/bin/sh";
+ eargs.append(shell);
+ te = new TEWidget(parentWidget,widgetName);
+ te->setMinimumSize(150,70); // allow resizing, cause resize in TEWidget
+
+ setWidget(te);
+ te->setFocus();
+ connect( te,SIGNAL(configureRequest(TEWidget*,int,int,int)),
+ this,SLOT(configureRequest(TEWidget*,int,int,int)) );
+
+ colors = new ColorSchemaList();
+ colors->checkSchemas();
+ colors->sort();
+
+ // Check to see which config file we use: konsolepartrc or konsolerc
+ KConfig* config = new KConfig("konsolepartrc", true);
+ config->setDesktopGroup();
+ b_useKonsoleSettings = config->readBoolEntry("use_konsole_settings", false);
+ delete config;
+
+ readProperties();
+
+ makeGUI();
+
+ if (m_schema)
+ {
+ updateSchemaMenu();
+
+ ColorSchema *sch=colors->find(s_schema);
+ if (sch)
+ curr_schema=sch->numb();
+ else
+ curr_schema = 0;
+
+ for (uint i=0; i<m_schema->count(); i++)
+ m_schema->setItemChecked(i,false);
+
+ m_schema->setItemChecked(curr_schema,true);
+ }
+
+ // insert keymaps into menu
+ if (m_keytab)
+ {
+ m_keytab->clear();
+
+ QStringList kt_titles;
+ typedef QMap<QString,KeyTrans*> QStringKeyTransMap;
+ QStringKeyTransMap kt_map;
+
+ for (int i = 0; i < KeyTrans::count(); i++)
+ {
+ KeyTrans* ktr = KeyTrans::find(i);
+ assert( ktr );
+ QString title=ktr->hdr().lower();
+ kt_titles << title;
+ kt_map[title] = ktr;
+ }
+ kt_titles.sort();
+ for ( QStringList::Iterator it = kt_titles.begin(); it != kt_titles.end(); ++it ) {
+ KeyTrans* ktr = kt_map[*it];
+ assert( ktr );
+ QString title=ktr->hdr();
+ m_keytab->insertItem(title.replace('&',"&&"),ktr->numb());
+ }
+ }
+
+ applySettingsToGUI();
+
+ QTimer::singleShot( 0, this, SLOT( autoShowShell() ) );
+}
+
+void konsolePart::autoShowShell()
+{
+ // possibly clear the screen?
+ if (b_autoStartShell)
+ showShell();
+}
+
+void konsolePart::setAutoDestroy( bool enabled )
+{
+ b_autoDestroy = enabled;
+}
+
+void konsolePart::setAutoStartShell( bool enabled )
+{
+ b_autoStartShell = enabled;
+}
+
+void konsolePart::doneSession(TESession*)
+{
+ // see doneSession in konsole.cpp
+ if (se && b_autoDestroy)
+ {
+// kdDebug(1211) << "doneSession - disconnecting done" << endl;
+ disconnect( se,SIGNAL(done(TESession*)),
+ this,SLOT(doneSession(TESession*)) );
+ se->setConnect(false);
+ //QTimer::singleShot(100,se,SLOT(terminate()));
+// kdDebug(1211) << "se->terminate()" << endl;
+ se->terminate();
+ }
+}
+
+void konsolePart::sessionDestroyed()
+{
+// kdDebug(1211) << "sessionDestroyed()" << endl;
+ disconnect( se, SIGNAL( destroyed() ), this, SLOT( sessionDestroyed() ) );
+ se = 0;
+ if (b_autoDestroy)
+ delete this;
+}
+
+void konsolePart::configureRequest(TEWidget*_te,int,int x,int y)
+{
+ if (m_popupMenu)
+ m_popupMenu->popup(_te->mapToGlobal(QPoint(x,y)));
+}
+
+konsolePart::~konsolePart()
+{
+// kdDebug(1211) << "konsolePart::~konsolePart() this=" << this << endl;
+ if ( se ) {
+ setAutoDestroy(false);
+ se->closeSession();
+
+ // Wait a bit for all childs to clean themselves up.
+ while(se && KProcessController::theKProcessController->waitForProcessExit(1))
+ ;
+
+ disconnect( se, SIGNAL( destroyed() ), this, SLOT( sessionDestroyed() ) );
+// kdDebug(1211) << "Deleting se session" << endl;
+ delete se;
+ se=0;
+ }
+
+ if (colors) delete colors;
+ colors=0;
+
+ //te is deleted by the framework
+}
+
+bool konsolePart::openURL( const KURL & url )
+{
+ //kdDebug(1211) << "konsolePart::openURL " << url.prettyURL() << endl;
+
+ if (currentURL==url) {
+ emit completed();
+ return true;
+ }
+
+ m_url = url;
+ emit setWindowCaption( url.prettyURL() );
+// kdDebug(1211) << "Set Window Caption to " << url.prettyURL() << "\n";
+ emit started( 0 );
+
+ if ( url.isLocalFile() ) {
+ struct stat buff;
+ stat( QFile::encodeName( url.path() ), &buff );
+ QString text = ( S_ISDIR( buff.st_mode ) ? url.path() : url.directory() );
+ showShellInDir( text );
+ }
+
+ emit completed();
+ return true;
+}
+
+void konsolePart::emitOpenURLRequest(const QString &cwd)
+{
+ KURL url;
+ url.setPath(cwd);
+ if (url==currentURL)
+ return;
+ currentURL=url;
+ m_extension->emitOpenURLRequest(url);
+}
+
+
+void konsolePart::makeGUI()
+{
+ if (!kapp->authorizeKAction("konsole_rmb"))
+ return;
+
+ actions = new KActionCollection( (KMainWindow*)parentWidget );
+ settingsActions = new KActionCollection( (KMainWindow*)parentWidget );
+
+ // Send Signal Menu -------------------------------------------------------------
+ if (kapp->authorizeKAction("send_signal"))
+ {
+ m_signals = new KPopupMenu((KMainWindow*)parentWidget);
+ m_signals->insertItem( i18n( "&Suspend Task" ) + " (STOP)", SIGSTOP);
+ m_signals->insertItem( i18n( "&Continue Task" ) + " (CONT)", SIGCONT);
+ m_signals->insertItem( i18n( "&Hangup" ) + " (HUP)", SIGHUP);
+ m_signals->insertItem( i18n( "&Interrupt Task" ) + " (INT)", SIGINT);
+ m_signals->insertItem( i18n( "&Terminate Task" ) + " (TERM)", SIGTERM);
+ m_signals->insertItem( i18n( "&Kill Task" ) + " (KILL)", SIGKILL);
+ m_signals->insertItem( i18n( "User Signal &1") + " (USR1)", SIGUSR1);
+ m_signals->insertItem( i18n( "User Signal &2") + " (USR2)", SIGUSR2);
+ connect(m_signals, SIGNAL(activated(int)), SLOT(sendSignal(int)));
+ }
+
+ // Settings Menu ----------------------------------------------------------------
+ if (kapp->authorizeKAction("settings"))
+ {
+ m_options = new KPopupMenu((KMainWindow*)parentWidget);
+
+ // Scrollbar
+ selectScrollbar = new KSelectAction(i18n("Sc&rollbar"), 0, this,
+ SLOT(slotSelectScrollbar()), settingsActions);
+
+ QStringList scrollitems;
+ scrollitems << i18n("&Hide") << i18n("&Left") << i18n("&Right");
+ selectScrollbar->setItems(scrollitems);
+ selectScrollbar->plug(m_options);
+
+ // Select Bell
+ m_options->insertSeparator();
+ selectBell = new KSelectAction(i18n("&Bell"), SmallIconSet( "bell"), 0 , this,
+ SLOT(slotSelectBell()), settingsActions, "bell");
+
+ QStringList bellitems;
+ bellitems << i18n("System &Bell")
+ << i18n("System &Notification")
+ << i18n("&Visible Bell")
+ << i18n("N&one");
+ selectBell->setItems(bellitems);
+ selectBell->plug(m_options);
+
+ m_fontsizes = new KActionMenu( i18n( "Font" ), SmallIconSet( "text" ), settingsActions, 0L );
+ m_fontsizes->insert( new KAction( i18n( "&Enlarge Font" ), SmallIconSet( "viewmag+" ), 0, this, SLOT( biggerFont() ), settingsActions, "enlarge_font" ) );
+ m_fontsizes->insert( new KAction( i18n( "&Shrink Font" ), SmallIconSet( "viewmag-" ), 0, this, SLOT( smallerFont() ), settingsActions, "shrink_font" ) );
+ m_fontsizes->insert( new KAction( i18n( "Se&lect..." ), SmallIconSet( "font" ), 0, this, SLOT( slotSelectFont() ), settingsActions, "select_font" ) );
+ m_fontsizes->plug(m_options);
+
+ // encoding menu, start with default checked !
+ selectSetEncoding = new KSelectAction( i18n( "&Encoding" ), SmallIconSet("charset" ), 0, this, SLOT(slotSetEncoding()), settingsActions, "set_encoding" );
+ QStringList list = KGlobal::charsets()->descriptiveEncodingNames();
+ list.prepend( i18n( "Default" ) );
+ selectSetEncoding->setItems(list);
+ selectSetEncoding->setCurrentItem (0);
+ selectSetEncoding->plug(m_options);
+
+ // Keyboard Options Menu ---------------------------------------------------
+ if (kapp->authorizeKAction("keyboard"))
+ {
+ m_keytab = new KPopupMenu((KMainWindow*)parentWidget);
+ m_keytab->setCheckable(true);
+ connect(m_keytab, SIGNAL(activated(int)), SLOT(keytab_menu_activated(int)));
+ m_options->insertItem( SmallIconSet( "key_bindings" ), i18n( "&Keyboard" ), m_keytab );
+ }
+
+ // Schema Options Menu -----------------------------------------------------
+ if (kapp->authorizeKAction("schema"))
+ {
+ m_schema = new KPopupMenu((KMainWindow*)parentWidget);
+ m_schema->setCheckable(true);
+ connect(m_schema, SIGNAL(activated(int)), SLOT(schema_menu_activated(int)));
+ connect(m_schema, SIGNAL(aboutToShow()), SLOT(schema_menu_check()));
+ m_options->insertItem( SmallIconSet( "colorize" ), i18n( "Sch&ema" ), m_schema);
+ }
+
+
+ KAction *historyType = new KAction(i18n("&History..."), "history", 0, this,
+ SLOT(slotHistoryType()), settingsActions, "history");
+ historyType->plug(m_options);
+ m_options->insertSeparator();
+
+ // Select line spacing
+ selectLineSpacing = new KSelectAction(i18n("Li&ne Spacing"),
+ SmallIconSet("leftjust"), 0, this,
+ SLOT(slotSelectLineSpacing()), settingsActions );
+
+ QStringList lineSpacingList;
+ lineSpacingList
+ << i18n("&0")
+ << i18n("&1")
+ << i18n("&2")
+ << i18n("&3")
+ << i18n("&4")
+ << i18n("&5")
+ << i18n("&6")
+ << i18n("&7")
+ << i18n("&8");
+ selectLineSpacing->setItems(lineSpacingList);
+ selectLineSpacing->plug(m_options);
+
+ // Blinking Cursor
+ blinkingCursor = new KToggleAction (i18n("Blinking &Cursor"),
+ 0, this,SLOT(slotBlinkingCursor()), settingsActions);
+ blinkingCursor->plug(m_options);
+
+ // Frame on/off
+ showFrame = new KToggleAction(i18n("Show Fr&ame"), 0,
+ this, SLOT(slotToggleFrame()), settingsActions);
+ showFrame->setCheckedState(i18n("Hide Fr&ame"));
+ showFrame->plug(m_options);
+
+ // Word Connectors
+ KAction *WordSeps = new KAction(i18n("Wor&d Connectors..."), 0, this,
+ SLOT(slotWordSeps()), settingsActions);
+ WordSeps->plug(m_options);
+
+ // Use Konsole's Settings
+ m_options->insertSeparator();
+ m_useKonsoleSettings = new KToggleAction( i18n("&Use Konsole's Settings"),
+ 0, this, SLOT(slotUseKonsoleSettings()), 0, "use_konsole_settings" );
+ m_useKonsoleSettings->plug(m_options);
+
+ // Save Settings
+ m_options->insertSeparator();
+ KAction *saveSettings = new KAction(i18n("&Save as Default"), "filesave", 0, this,
+ SLOT(saveProperties()), actions, "save_default");
+ saveSettings->plug(m_options);
+ if (KGlobalSettings::insertTearOffHandle())
+ m_options->insertTearOffHandle();
+ }
+
+ // Popup Menu -------------------------------------------------------------------
+ m_popupMenu = new KPopupMenu((KMainWindow*)parentWidget);
+ KAction* selectionEnd = new KAction(i18n("Set Selection End"), 0, te,
+ SLOT(setSelectionEnd()), actions, "selection_end");
+ selectionEnd->plug(m_popupMenu);
+
+ KAction *copyClipboard = new KAction(i18n("&Copy"), "editcopy", 0,
+ te, SLOT(copyClipboard()), actions, "edit_copy");
+ copyClipboard->plug(m_popupMenu);
+
+ KAction *pasteClipboard = new KAction(i18n("&Paste"), "editpaste", 0,
+ te, SLOT(pasteClipboard()), actions, "edit_paste");
+ pasteClipboard->plug(m_popupMenu);
+
+ if (m_signals)
+ {
+ m_popupMenu->insertItem(i18n("&Send Signal"), m_signals);
+ m_popupMenu->insertSeparator();
+ }
+
+ if (m_options)
+ {
+ m_popupMenu->insertItem(i18n("S&ettings"), m_options);
+ m_popupMenu->insertSeparator();
+ }
+
+ KAction *closeSession = new KAction(i18n("&Close Terminal Emulator"), "fileclose", 0, this,
+ SLOT(closeCurrentSession()), actions, "close_session");
+ closeSession->plug(m_popupMenu);
+ if (KGlobalSettings::insertTearOffHandle())
+ m_popupMenu->insertTearOffHandle();
+}
+
+void konsolePart::applySettingsToGUI()
+{
+ m_useKonsoleSettings->setChecked( b_useKonsoleSettings );
+ setSettingsMenuEnabled( !b_useKonsoleSettings );
+
+ applyProperties();
+
+ if ( b_useKonsoleSettings )
+ return; // Don't change Settings menu items
+
+ if (showFrame)
+ showFrame->setChecked( b_framevis );
+ if (selectScrollbar)
+ selectScrollbar->setCurrentItem(n_scroll);
+ updateKeytabMenu();
+ if (selectBell)
+ selectBell->setCurrentItem(n_bell);
+ if (selectLineSpacing)
+ selectLineSpacing->setCurrentItem(te->lineSpacing());
+ if (blinkingCursor)
+ blinkingCursor->setChecked(te->blinkingCursor());
+ if (m_schema)
+ m_schema->setItemChecked(curr_schema,true);
+ if (selectSetEncoding)
+ selectSetEncoding->setCurrentItem(n_encoding);
+}
+
+void konsolePart::applyProperties()
+{
+ if ( !se ) return;
+
+ if ( b_histEnabled && m_histSize )
+ se->setHistory( HistoryTypeBuffer(m_histSize ) );
+ else if ( b_histEnabled && !m_histSize )
+ se->setHistory(HistoryTypeFile() );
+ else
+ se->setHistory( HistoryTypeNone() );
+ se->setKeymapNo( n_keytab );
+
+ // FIXME: Move this somewhere else...
+ KConfig* config = new KConfig("konsolerc",true);
+ config->setGroup("UTMP");
+ se->setAddToUtmp( config->readBoolEntry("AddToUtmp",true));
+ delete config;
+
+ se->widget()->setVTFont( defaultFont );
+ se->setSchemaNo( curr_schema );
+ slotSetEncoding();
+}
+
+void konsolePart::setSettingsMenuEnabled( bool enable )
+{
+ uint count = settingsActions->count();
+ for ( uint i = 0; i < count; i++ )
+ {
+ settingsActions->action( i )->setEnabled( enable );
+ }
+
+ // FIXME: These are not in settingsActions.
+ // When disabled, the icons are not 'grey-ed' out.
+ m_keytab->setEnabled( enable );
+ m_schema->setEnabled( enable );
+}
+
+void konsolePart::readProperties()
+{
+ KConfig* config;
+
+ if ( b_useKonsoleSettings )
+ config = new KConfig( "konsolerc", true );
+ else
+ config = new KConfig( "konsolepartrc", true );
+
+ config->setDesktopGroup();
+
+ b_framevis = config->readBoolEntry("has frame",false);
+ b_histEnabled = config->readBoolEntry("historyenabled",true);
+ n_bell = QMIN(config->readUnsignedNumEntry("bellmode",TEWidget::BELLSYSTEM),3);
+ n_keytab=config->readNumEntry("keytab",0); // act. the keytab for this session
+ n_scroll = QMIN(config->readUnsignedNumEntry("scrollbar",TEWidget::SCRRIGHT),2);
+ m_histSize = config->readNumEntry("history",DEFAULT_HISTORY_SIZE);
+ s_word_seps= config->readEntry("wordseps",":@-./_~");
+
+ n_encoding = config->readNumEntry("encoding",0);
+
+ QFont tmpFont = KGlobalSettings::fixedFont();
+ defaultFont = config->readFontEntry("defaultfont", &tmpFont);
+
+ QString schema = config->readEntry("Schema");
+
+ s_kconfigSchema=config->readEntry("schema");
+ ColorSchema* sch = colors->find(schema.isEmpty() ? s_kconfigSchema : schema);
+ if (!sch) {
+ sch=(ColorSchema*)colors->at(0); //the default one
+ }
+ if (sch->hasSchemaFileChanged()) sch->rereadSchemaFile();
+ s_schema = sch->relPath();
+ curr_schema = sch->numb();
+ pmPath = sch->imagePath();
+ te->setColorTable(sch->table()); //FIXME: set twice here to work around a bug
+
+ if (sch->useTransparency()) {
+ if (!rootxpm)
+ rootxpm = new KRootPixmap(te);
+ rootxpm->setFadeEffect(sch->tr_x(), QColor(sch->tr_r(), sch->tr_g(), sch->tr_b()));
+ rootxpm->start();
+ rootxpm->repaint(true);
+ }
+ else {
+ if (rootxpm) {
+ rootxpm->stop();
+ delete rootxpm;
+ rootxpm=0;
+ }
+ pixmap_menu_activated(sch->alignment());
+ }
+
+ te->setBellMode(n_bell);
+ te->setBlinkingCursor(config->readBoolEntry("BlinkingCursor",false));
+ te->setFrameStyle( b_framevis?(QFrame::WinPanel|QFrame::Sunken):QFrame::NoFrame );
+ te->setLineSpacing( config->readUnsignedNumEntry( "LineSpacing", 0 ) );
+ te->setScrollbarLocation(n_scroll);
+ te->setWordCharacters(s_word_seps);
+
+ delete config;
+
+ config = new KConfig("konsolerc",true);
+ config->setDesktopGroup();
+ te->setTerminalSizeHint( config->readBoolEntry("TerminalSizeHint",true) );
+ delete config;
+}
+
+void konsolePart::saveProperties()
+{
+ KConfig* config = new KConfig("konsolepartrc");
+ config->setDesktopGroup();
+
+ if ( b_useKonsoleSettings ) { // Don't save Settings if using konsolerc
+ config->writeEntry("use_konsole_settings", m_useKonsoleSettings->isChecked());
+ } else {
+ config->writeEntry("bellmode",n_bell);
+ config->writeEntry("BlinkingCursor", te->blinkingCursor());
+ config->writeEntry("defaultfont", (se->widget())->getVTFont());
+ config->writeEntry("history", se->history().getSize());
+ config->writeEntry("historyenabled", b_histEnabled);
+ config->writeEntry("keytab",n_keytab);
+ config->writeEntry("has frame",b_framevis);
+ config->writeEntry("LineSpacing", te->lineSpacing());
+ config->writeEntry("schema",s_kconfigSchema);
+ config->writeEntry("scrollbar",n_scroll);
+ config->writeEntry("wordseps",s_word_seps);
+ config->writeEntry("encoding",n_encoding);
+ config->writeEntry("use_konsole_settings",m_useKonsoleSettings->isChecked());
+ }
+
+ config->sync();
+ delete config;
+}
+
+void konsolePart::sendSignal(int sn)
+{
+ if (se) se->sendSignal(sn);
+}
+
+void konsolePart::closeCurrentSession()
+{
+ if ( se ) se->closeSession();
+}
+
+void konsolePart::slotToggleFrame()
+{
+ b_framevis = showFrame->isChecked();
+ te->setFrameStyle( b_framevis?(QFrame::WinPanel|QFrame::Sunken):QFrame::NoFrame);
+}
+
+void konsolePart::slotSelectScrollbar()
+{
+ if ( ! se ) return;
+ n_scroll = selectScrollbar->currentItem();
+ te->setScrollbarLocation(n_scroll);
+}
+
+void konsolePart::slotSelectFont() {
+ if ( !se ) return;
+
+ QFont font = se->widget()->getVTFont();
+ if ( KFontDialog::getFont( font, true ) != QDialog::Accepted )
+ return;
+
+ se->widget()->setVTFont( font );
+}
+
+void konsolePart::biggerFont(void) {
+ if ( !se ) return;
+
+ QFont f = te->getVTFont();
+ f.setPointSize( f.pointSize() + 1 );
+ te->setVTFont( f );
+}
+
+void konsolePart::smallerFont(void) {
+ if ( !se ) return;
+
+ QFont f = te->getVTFont();
+ if ( f.pointSize() < 6 ) return; // A minimum size
+ f.setPointSize( f.pointSize() - 1 );
+ te->setVTFont( f );
+}
+
+void konsolePart::updateKeytabMenu()
+{
+ if ( se && m_keytab ) {
+ m_keytab->setItemChecked(n_keytab,false);
+ m_keytab->setItemChecked(se->keymapNo(),true);
+ n_keytab = se->keymapNo();
+ } else if ( m_keytab ) { // no se yet, happens at startup
+ m_keytab->setItemChecked(n_keytab, true);
+ }
+}
+
+void konsolePart::keytab_menu_activated(int item)
+{
+ if ( ! se ) return;
+ se->setKeymapNo(item);
+ updateKeytabMenu();
+}
+
+void konsolePart::schema_menu_activated(int item)
+{
+ setSchema(item);
+ s_kconfigSchema = s_schema; // This is the new default
+}
+
+void konsolePart::schema_menu_check()
+{
+ if (colors->checkSchemas()) {
+ colors->sort();
+ updateSchemaMenu();
+ }
+}
+
+void konsolePart::updateSchemaMenu()
+{
+ if (!m_schema) return;
+
+ m_schema->clear();
+ for (int i = 0; i < (int) colors->count(); i++) {
+ ColorSchema* s = (ColorSchema*)colors->at(i);
+ QString title=s->title();
+ m_schema->insertItem(title.replace('&',"&&"),s->numb(),0);
+ }
+
+ if (te && se) {
+ m_schema->setItemChecked(se->schemaNo(),true);
+ }
+}
+
+void konsolePart::setSchema(int numb)
+{
+ ColorSchema* s = colors->find(numb);
+ if (!s) {
+ kdWarning() << "No schema found. Using default." << endl;
+ s=(ColorSchema*)colors->at(0);
+ }
+ if (s->numb() != numb) {
+ kdWarning() << "No schema with number " << numb << endl;
+ }
+
+ if (s->hasSchemaFileChanged()) {
+ const_cast<ColorSchema *>(s)->rereadSchemaFile();
+ }
+ if (s) setSchema(s);
+}
+
+void konsolePart::setSchema(ColorSchema* s)
+{
+ if (!se) return;
+ if (!s) return;
+
+ if (m_schema) {
+ m_schema->setItemChecked(curr_schema,false);
+ m_schema->setItemChecked(s->numb(),true);
+ }
+
+ s_schema = s->relPath();
+ curr_schema = s->numb();
+ pmPath = s->imagePath();
+ te->setColorTable(s->table()); //FIXME: set twice here to work around a bug
+
+ if (s->useTransparency()) {
+ if (!rootxpm)
+ rootxpm = new KRootPixmap(te);
+ rootxpm->setFadeEffect(s->tr_x(), QColor(s->tr_r(), s->tr_g(), s->tr_b()));
+ rootxpm->start();
+ rootxpm->repaint(true);
+ }
+ else {
+ if (rootxpm) {
+ rootxpm->stop();
+ delete rootxpm;
+ rootxpm=0;
+ }
+ pixmap_menu_activated(s->alignment());
+ }
+
+ te->setColorTable(s->table());
+ se->setSchemaNo(s->numb());
+}
+
+void konsolePart::notifySize(int /* columns */, int /* lines */)
+{
+ ColorSchema *sch=colors->find(s_schema);
+
+ if (sch && sch->alignment() >= 3)
+ pixmap_menu_activated(sch->alignment());
+}
+
+void konsolePart::pixmap_menu_activated(int item)
+{
+ if (item <= 1) pmPath = "";
+ QPixmap pm(pmPath);
+ if (pm.isNull()) {
+ pmPath = "";
+ item = 1;
+ te->setBackgroundColor(te->getDefaultBackColor());
+ return;
+ }
+ // FIXME: respect scrollbar (instead of te->size)
+ n_render= item;
+ switch (item) {
+ case 1: // none
+ case 2: // tile
+ te->setBackgroundPixmap(pm);
+ break;
+ case 3: // center
+ { QPixmap bgPixmap;
+ bgPixmap.resize(te->size());
+ bgPixmap.fill(te->getDefaultBackColor());
+ bitBlt( &bgPixmap, ( te->size().width() - pm.width() ) / 2,
+ ( te->size().height() - pm.height() ) / 2,
+ &pm, 0, 0,
+ pm.width(), pm.height() );
+
+ te->setBackgroundPixmap(bgPixmap);
+ }
+ break;
+ case 4: // full
+ {
+ float sx = (float)te->size().width() / pm.width();
+ float sy = (float)te->size().height() / pm.height();
+ QWMatrix matrix;
+ matrix.scale( sx, sy );
+ te->setBackgroundPixmap(pm.xForm( matrix ));
+ }
+ break;
+ default: // oops
+ n_render = 1;
+ }
+}
+
+void konsolePart::slotHistoryType()
+{
+ if ( ! se ) return;
+ HistoryTypeDialog dlg(se->history(), m_histSize, (KMainWindow*)parentWidget);
+ if (dlg.exec()) {
+ if (dlg.isOn()) {
+ if (dlg.nbLines() > 0) {
+ se->setHistory(HistoryTypeBuffer(dlg.nbLines()));
+ m_histSize = dlg.nbLines();
+ b_histEnabled = true;
+ }
+ else {
+ se->setHistory(HistoryTypeFile());
+ m_histSize = 0;
+ b_histEnabled = true;
+ }
+ }
+ else {
+ se->setHistory(HistoryTypeNone());
+ m_histSize = dlg.nbLines();
+ b_histEnabled = false;
+ }
+ }
+}
+
+void konsolePart::slotSelectBell() {
+ n_bell = selectBell->currentItem();
+ te->setBellMode(n_bell);
+}
+
+void konsolePart::slotSetEncoding()
+{
+ if (!se) return;
+
+ bool found;
+ QString enc = KGlobal::charsets()->encodingForName(selectSetEncoding->currentText());
+ QTextCodec * qtc = KGlobal::charsets()->codecForName(enc, found);
+ if(!found)
+ {
+ kdDebug() << "Codec " << selectSetEncoding->currentText() << " not found!" << endl;
+ qtc = QTextCodec::codecForLocale();
+ }
+
+ n_encoding = selectSetEncoding->currentItem();
+ se->setEncodingNo(selectSetEncoding->currentItem());
+ se->getEmulation()->setCodec(qtc);
+}
+
+void konsolePart::slotSelectLineSpacing()
+{
+ te->setLineSpacing( selectLineSpacing->currentItem() );
+}
+
+void konsolePart::slotBlinkingCursor()
+{
+ te->setBlinkingCursor(blinkingCursor->isChecked());
+}
+
+void konsolePart::slotUseKonsoleSettings()
+{
+ b_useKonsoleSettings = m_useKonsoleSettings->isChecked();
+
+ setSettingsMenuEnabled( !b_useKonsoleSettings );
+
+ readProperties();
+
+ applySettingsToGUI();
+}
+
+void konsolePart::slotWordSeps() {
+ bool ok;
+
+ QString seps = KInputDialog::getText( i18n( "Word Connectors" ),
+ i18n( "Characters other than alphanumerics considered part of a word when double clicking:" ), s_word_seps, &ok, parentWidget );
+ if ( ok )
+ {
+ s_word_seps = seps;
+ te->setWordCharacters(s_word_seps);
+ }
+}
+
+void konsolePart::enableMasterModeConnections()
+{
+ if ( se ) se->setListenToKeyPress(true);
+}
+
+void konsolePart::updateTitle(TESession *)
+{
+ if ( se ) emit setWindowCaption( se->fullTitle() );
+}
+
+void konsolePart::guiActivateEvent( KParts::GUIActivateEvent * )
+{
+ // Don't let ReadOnlyPart::guiActivateEvent reset the window caption
+}
+
+bool konsolePart::doOpenStream( const QString& )
+{
+ return m_streamEnabled;
+}
+
+bool konsolePart::doWriteStream( const QByteArray& data )
+{
+ if ( m_streamEnabled )
+ {
+ QString cmd = QString::fromLocal8Bit( data.data(), data.size() );
+ se->sendSession( cmd );
+ return true;
+ }
+ return false;
+}
+
+bool konsolePart::doCloseStream()
+{
+ return m_streamEnabled;
+}
+
+//////////////////////////////////////////////////////////////////////
+
+HistoryTypeDialog::HistoryTypeDialog(const HistoryType& histType,
+ unsigned int histSize,
+ QWidget *parent)
+ : KDialogBase(Plain, i18n("History Configuration"),
+ Help | Default | Ok | Cancel, Ok,
+ parent)
+{
+ QFrame *mainFrame = plainPage();
+
+ QHBoxLayout *hb = new QHBoxLayout(mainFrame);
+
+ m_btnEnable = new QCheckBox(i18n("&Enable"), mainFrame);
+
+ QObject::connect(m_btnEnable, SIGNAL(toggled(bool)),
+ this, SLOT(slotHistEnable(bool)));
+
+ m_size = new QSpinBox(0, 10 * 1000 * 1000, 100, mainFrame);
+ m_size->setValue(histSize);
+ m_size->setSpecialValueText(i18n("Unlimited (number of lines)", "Unlimited"));
+
+ m_setUnlimited = new QPushButton(i18n("&Set Unlimited"), mainFrame);
+ connect( m_setUnlimited,SIGNAL(clicked()), this,SLOT(slotSetUnlimited()) );
+
+ hb->addWidget(m_btnEnable);
+ hb->addSpacing(10);
+ hb->addWidget(new QLabel(i18n("Number of lines:"), mainFrame));
+ hb->addWidget(m_size);
+ hb->addSpacing(10);
+ hb->addWidget(m_setUnlimited);
+
+ if ( ! histType.isOn()) {
+ m_btnEnable->setChecked(false);
+ slotHistEnable(false);
+ } else {
+ m_btnEnable->setChecked(true);
+ m_size->setValue(histType.getSize());
+ slotHistEnable(true);
+ }
+ setHelp("configure-history");
+}
+
+void HistoryTypeDialog::slotDefault()
+{
+ m_btnEnable->setChecked(true);
+ m_size->setValue(DEFAULT_HISTORY_SIZE);
+ slotHistEnable(true);
+}
+
+void HistoryTypeDialog::slotHistEnable(bool b)
+{
+ m_size->setEnabled(b);
+ m_setUnlimited->setEnabled(b);
+ if (b) m_size->setFocus();
+}
+
+void HistoryTypeDialog::slotSetUnlimited()
+{
+ m_size->setValue(0);
+}
+
+unsigned int HistoryTypeDialog::nbLines() const
+{
+ return m_size->value();
+}
+
+bool HistoryTypeDialog::isOn() const
+{
+ return m_btnEnable->isChecked();
+}
+
+konsoleBrowserExtension::konsoleBrowserExtension(konsolePart *parent)
+ : KParts::BrowserExtension(parent, "konsoleBrowserExtension")
+{
+}
+
+konsoleBrowserExtension::~konsoleBrowserExtension()
+{
+}
+
+void konsoleBrowserExtension::emitOpenURLRequest(const KURL &url)
+{
+ emit openURLRequest(url);
+}
+
+const char* sensibleShell()
+{
+ const char* shell = getenv("SHELL");
+ if (shell == NULL || *shell == '\0') shell = "/bin/sh";
+ return shell;
+}
+
+void konsolePart::startProgram( const QString& program,
+ const QStrList& args )
+{
+// kdDebug(1211) << "konsolePart::startProgram for " << program << endl;
+ if ( !se )
+ newSession();
+ se->setProgram( program, args );
+ se->run();
+}
+
+void konsolePart::newSession()
+{
+ if ( se ) delete se;
+ se = new TESession(te, "xterm", parentWidget->winId());
+ connect( se,SIGNAL(done(TESession*)),
+ this,SLOT(doneSession(TESession*)) );
+ connect( se,SIGNAL(openURLRequest(const QString &)),
+ this,SLOT(emitOpenURLRequest(const QString &)) );
+ connect( se, SIGNAL( updateTitle(TESession*) ),
+ this, SLOT( updateTitle(TESession*) ) );
+ connect( se, SIGNAL(enableMasterModeConnections()),
+ this, SLOT(enableMasterModeConnections()) );
+ connect( se, SIGNAL( processExited(KProcess *) ),
+ this, SIGNAL( processExited(KProcess *) ) );
+ connect( se, SIGNAL( receivedData( const QString& ) ),
+ this, SIGNAL( receivedData( const QString& ) ) );
+ connect( se, SIGNAL( forkedChild() ),
+ this, SIGNAL( forkedChild() ));
+
+ // We ignore the following signals
+ //connect( se, SIGNAL(renameSession(TESession*,const QString&)),
+ // this, SLOT(slotRenameSession(TESession*, const QString&)) );
+ //connect( se->getEmulation(), SIGNAL(changeColumns(int)),
+ // this, SLOT(changeColumns(int)) );
+ //connect( se, SIGNAL(disableMasterModeConnections()),
+ // this, SLOT(disableMasterModeConnections()) );
+
+ applyProperties();
+
+ se->setConnect(true);
+ // se->run();
+ connect( se, SIGNAL( destroyed() ), this, SLOT( sessionDestroyed() ) );
+// setFont( n_font ); // we do this here, to make TEWidget recalculate
+ // its geometry..
+}
+
+void konsolePart::showShellInDir( const QString& dir )
+{
+ if ( ! m_runningShell )
+ {
+ const char* s = sensibleShell();
+ QStrList args;
+ args.append( s );
+ startProgram( s, args );
+ m_runningShell = true;
+ };
+
+ if ( ! dir.isNull() )
+ {
+ QString text = dir;
+ KRun::shellQuote(text);
+ text = QString::fromLatin1("cd ") + text + '\n';
+ te->emitText( text );
+ };
+}
+
+void konsolePart::showShell()
+{
+ if ( ! se ) showShellInDir( QString::null );
+}
+
+void konsolePart::sendInput( const QString& text )
+{
+ te->emitText( text );
+}
+
+#include "konsole_part.moc"
diff --git a/konsole/konsole/konsole_part.h b/konsole/konsole/konsole_part.h
new file mode 100644
index 000000000..6f410d3c3
--- /dev/null
+++ b/konsole/konsole/konsole_part.h
@@ -0,0 +1,241 @@
+/* -*- C++ -*-
+ This file is part of the KDE system
+ Copyright (C) 1999,2000 Boloni Laszlo <lboloni@cpe.ucf.edu>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KONSOLE_PART_H
+#define KONSOLE_PART_H
+
+#include <kparts/browserextension.h>
+#include <kparts/factory.h>
+
+
+#include <kdialogbase.h>
+
+#include <kde_terminal_interface.h>
+
+#include "schema.h"
+#include "session.h"
+
+class KInstance;
+class konsoleBrowserExtension;
+class QPushButton;
+class QSpinBox;
+class KPopupMenu;
+class KActionMenu;
+class QCheckBox;
+class KRootPixmap;
+class KToggleAction;
+class KSelectAction;
+
+namespace KParts { class GUIActivateEvent; }
+
+class konsoleFactory : public KParts::Factory
+{
+ Q_OBJECT
+public:
+ konsoleFactory();
+ virtual ~konsoleFactory();
+
+ virtual KParts::Part* createPartObject(QWidget *parentWidget = 0, const char *widgetName = 0,
+ QObject* parent = 0, const char* name = 0,
+ const char* classname = "KParts::Part",
+ const QStringList &args = QStringList());
+
+ static KInstance *instance();
+
+ private:
+ static KInstance *s_instance;
+ static KAboutData *s_aboutData;
+};
+
+//////////////////////////////////////////////////////////////////////
+
+class konsolePart: public KParts::ReadOnlyPart, public TerminalInterface, public ExtTerminalInterface
+{
+ Q_OBJECT
+ public:
+ konsolePart(QWidget *parentWidget, const char *widgetName, QObject * parent, const char *name, const char *classname = 0);
+ virtual ~konsolePart();
+
+signals:
+ void processExited( KProcess * );
+ void receivedData( const QString& s );
+ void forkedChild();
+ protected:
+ virtual bool openURL( const KURL & url );
+ virtual bool openFile() {return false;} // never used
+ virtual bool closeURL() {return true;}
+ virtual void guiActivateEvent( KParts::GUIActivateEvent * event );
+
+ protected slots:
+ void showShell();
+
+ void doneSession(TESession*);
+ void sessionDestroyed();
+ void configureRequest(TEWidget*,int,int x,int y);
+ void updateTitle(TESession*);
+ void enableMasterModeConnections();
+
+ private slots:
+ void emitOpenURLRequest(const QString &url);
+
+ void readProperties();
+ void saveProperties();
+ void applyProperties();
+ void setSettingsMenuEnabled( bool );
+
+ void sendSignal(int n);
+ void closeCurrentSession();
+
+ void notifySize(int /*columns*/, int /*lines*/);
+
+ void slotToggleFrame();
+ void slotSelectScrollbar();
+ void slotSelectFont();
+ void schema_menu_check();
+ void keytab_menu_activated(int item);
+ void updateSchemaMenu();
+ void setSchema(int n);
+ void pixmap_menu_activated(int item);
+ void schema_menu_activated(int item);
+ void slotHistoryType();
+ void slotSelectBell();
+ void slotSelectLineSpacing();
+ void slotBlinkingCursor();
+ void slotUseKonsoleSettings();
+ void slotWordSeps();
+ void slotSetEncoding();
+ void biggerFont();
+ void smallerFont();
+
+ void autoShowShell();
+
+ private:
+ konsoleBrowserExtension *m_extension;
+ KURL currentURL;
+
+ void makeGUI();
+ void applySettingsToGUI();
+
+ void setSchema(ColorSchema* s);
+ void updateKeytabMenu();
+
+ bool doOpenStream( const QString& );
+ bool doWriteStream( const QByteArray& );
+ bool doCloseStream();
+
+ QWidget* parentWidget;
+ TEWidget* te;
+ TESession* se;
+ ColorSchemaList* colors;
+ KRootPixmap* rootxpm;
+
+ KActionCollection* actions;
+ KActionCollection* settingsActions;
+
+ KToggleAction* blinkingCursor;
+ KToggleAction* showFrame;
+ KToggleAction* m_useKonsoleSettings;
+
+ KSelectAction* selectBell;
+ KSelectAction* selectLineSpacing;
+ KSelectAction* selectScrollbar;
+ KSelectAction* selectSetEncoding;
+
+ KActionMenu* m_fontsizes;
+
+ KPopupMenu* m_keytab;
+ KPopupMenu* m_schema;
+ KPopupMenu* m_signals;
+ KPopupMenu* m_options;
+ KPopupMenu* m_popupMenu;
+
+ QFont defaultFont;
+
+ QString pmPath; // pixmap path
+ QString s_schema;
+ QString s_kconfigSchema;
+ QString s_word_seps; // characters that are considered part of a word
+
+ bool b_framevis:1;
+ bool b_histEnabled:1;
+ bool b_useKonsoleSettings:1;
+ bool b_autoDestroy:1;
+ bool b_autoStartShell:1;
+
+ int curr_schema; // current schema no
+ int n_bell;
+ int n_keytab;
+ int n_render;
+ int n_scroll;
+ unsigned m_histSize;
+ bool m_runningShell;
+ bool m_streamEnabled;
+ int n_encoding;
+
+public:
+ // these are the implementations for the TermEmuInterface
+ // functions...
+ void startProgram( const QString& program,
+ const QStrList& args );
+ void newSession();
+ void showShellInDir( const QString& dir );
+ void sendInput( const QString& text );
+ void setAutoDestroy( bool );
+ void setAutoStartShell( bool );
+};
+
+//////////////////////////////////////////////////////////////////////
+
+class HistoryTypeDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ HistoryTypeDialog(const HistoryType& histType,
+ unsigned int histSize,
+ QWidget *parent);
+
+public slots:
+ void slotDefault();
+ void slotSetUnlimited();
+ void slotHistEnable(bool);
+
+ unsigned int nbLines() const;
+ bool isOn() const;
+
+protected:
+ QCheckBox* m_btnEnable;
+ QSpinBox* m_size;
+ QPushButton* m_setUnlimited;
+};
+
+//////////////////////////////////////////////////////////////////////
+
+class konsoleBrowserExtension : public KParts::BrowserExtension
+{
+ Q_OBJECT
+ friend class konsolePart;
+ public:
+ konsoleBrowserExtension(konsolePart *parent);
+ virtual ~konsoleBrowserExtension();
+
+ void emitOpenURLRequest(const KURL &url);
+};
+
+#endif
diff --git a/konsole/konsole/konsole_wcwidth.cpp b/konsole/konsole/konsole_wcwidth.cpp
new file mode 100644
index 000000000..eeb82f4a2
--- /dev/null
+++ b/konsole/konsole/konsole_wcwidth.cpp
@@ -0,0 +1,216 @@
+/* $XFree86: xc/programs/xterm/wcwidth.c,v 1.3 2001/07/29 22:08:16 tsi Exp $ */
+/*
+ * This is an implementation of wcwidth() and wcswidth() as defined in
+ * "The Single UNIX Specification, Version 2, The Open Group, 1997"
+ * <http://www.UNIX-systems.org/online.html>
+ *
+ * Markus Kuhn -- 2001-01-12 -- public domain
+ */
+
+#include "konsole_wcwidth.h"
+
+struct interval {
+ unsigned short first;
+ unsigned short last;
+};
+
+/* auxiliary function for binary search in interval table */
+static int bisearch(Q_UINT16 ucs, const struct interval *table, int max) {
+ int min = 0;
+ int mid;
+
+ if (ucs < table[0].first || ucs > table[max].last)
+ return 0;
+ while (max >= min) {
+ mid = (min + max) / 2;
+ if (ucs > table[mid].last)
+ min = mid + 1;
+ else if (ucs < table[mid].first)
+ max = mid - 1;
+ else
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* The following functions define the column width of an ISO 10646
+ * character as follows:
+ *
+ * - The null character (U+0000) has a column width of 0.
+ *
+ * - Other C0/C1 control characters and DEL will lead to a return
+ * value of -1.
+ *
+ * - Non-spacing and enclosing combining characters (general
+ * category code Mn or Me in the Unicode database) have a
+ * column width of 0.
+ *
+ * - Other format characters (general category code Cf in the Unicode
+ * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
+ *
+ * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
+ * have a column width of 0.
+ *
+ * - Spacing characters in the East Asian Wide (W) or East Asian
+ * FullWidth (F) category as defined in Unicode Technical
+ * Report #11 have a column width of 2.
+ *
+ * - All remaining characters (including all printable
+ * ISO 8859-1 and WGL4 characters, Unicode control characters,
+ * etc.) have a column width of 1.
+ *
+ * This implementation assumes that Q_UINT16 characters are encoded
+ * in ISO 10646.
+ */
+
+int konsole_wcwidth(Q_UINT16 ucs)
+{
+ /* sorted list of non-overlapping intervals of non-spacing characters */
+ static const struct interval combining[] = {
+ { 0x0300, 0x034E }, { 0x0360, 0x0362 }, { 0x0483, 0x0486 },
+ { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
+ { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
+ { 0x05C4, 0x05C4 }, { 0x064B, 0x0655 }, { 0x0670, 0x0670 },
+ { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
+ { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
+ { 0x07A6, 0x07B0 }, { 0x0901, 0x0902 }, { 0x093C, 0x093C },
+ { 0x0941, 0x0948 }, { 0x094D, 0x094D }, { 0x0951, 0x0954 },
+ { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, { 0x09BC, 0x09BC },
+ { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, { 0x09E2, 0x09E3 },
+ { 0x0A02, 0x0A02 }, { 0x0A3C, 0x0A3C }, { 0x0A41, 0x0A42 },
+ { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, { 0x0A70, 0x0A71 },
+ { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, { 0x0AC1, 0x0AC5 },
+ { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, { 0x0B01, 0x0B01 },
+ { 0x0B3C, 0x0B3C }, { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 },
+ { 0x0B4D, 0x0B4D }, { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 },
+ { 0x0BC0, 0x0BC0 }, { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 },
+ { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 },
+ { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
+ { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, { 0x0DCA, 0x0DCA },
+ { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, { 0x0E31, 0x0E31 },
+ { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, { 0x0EB1, 0x0EB1 },
+ { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, { 0x0EC8, 0x0ECD },
+ { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 },
+ { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, { 0x0F80, 0x0F84 },
+ { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, { 0x0F99, 0x0FBC },
+ { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, { 0x1032, 0x1032 },
+ { 0x1036, 0x1037 }, { 0x1039, 0x1039 }, { 0x1058, 0x1059 },
+ { 0x1160, 0x11FF }, { 0x17B7, 0x17BD }, { 0x17C6, 0x17C6 },
+ { 0x17C9, 0x17D3 }, { 0x180B, 0x180E }, { 0x18A9, 0x18A9 },
+ { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x206A, 0x206F },
+ { 0x20D0, 0x20E3 }, { 0x302A, 0x302F }, { 0x3099, 0x309A },
+ { 0xFB1E, 0xFB1E }, { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF },
+ { 0xFFF9, 0xFFFB }
+ };
+
+ /* test for 8-bit control characters */
+ if (ucs == 0)
+ return 0;
+ if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
+ return -1;
+
+ /* binary search in table of non-spacing characters */
+ if (bisearch(ucs, combining,
+ sizeof(combining) / sizeof(struct interval) - 1))
+ return 0;
+
+ /* if we arrive here, ucs is not a combining or C0/C1 control character */
+
+ return 1 +
+ (ucs >= 0x1100 &&
+ (ucs <= 0x115f || /* Hangul Jamo init. consonants */
+ (ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a &&
+ ucs != 0x303f) || /* CJK ... Yi */
+ (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
+ (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
+ (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
+ (ucs >= 0xff00 && ucs <= 0xff5f) || /* Fullwidth Forms */
+ (ucs >= 0xffe0 && ucs <= 0xffe6) /* do not compare UINT16 with 0x20000 ||
+ (ucs >= 0x20000 && ucs <= 0x2ffff) */));
+}
+
+#if 0
+/*
+ * The following function is the same as konsole_wcwidth(), except that
+ * spacing characters in the East Asian Ambiguous (A) category as
+ * defined in Unicode Technical Report #11 have a column width of 2.
+ * This experimental variant might be useful for users of CJK legacy
+ * encodings who want to migrate to UCS. It is not otherwise
+ * recommended for general use.
+ */
+int konsole_wcwidth_cjk(Q_UINT16 ucs)
+{
+ /* sorted list of non-overlapping intervals of East Asian Ambiguous
+ * characters */
+ static const struct interval ambiguous[] = {
+ { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
+ { 0x00AA, 0x00AA }, { 0x00AD, 0x00AD }, { 0x00B0, 0x00B4 },
+ { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
+ { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
+ { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
+ { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
+ { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
+ { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
+ { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
+ { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
+ { 0x0148, 0x014A }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
+ { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
+ { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
+ { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
+ { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
+ { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB }, { 0x02CD, 0x02CD },
+ { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB }, { 0x02DD, 0x02DD },
+ { 0x0391, 0x03A1 }, { 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 },
+ { 0x03C3, 0x03C9 }, { 0x0401, 0x0401 }, { 0x0410, 0x044F },
+ { 0x0451, 0x0451 }, { 0x2010, 0x2010 }, { 0x2013, 0x2016 },
+ { 0x2018, 0x2019 }, { 0x201C, 0x201D }, { 0x2020, 0x2021 },
+ { 0x2025, 0x2027 }, { 0x2030, 0x2030 }, { 0x2032, 0x2033 },
+ { 0x2035, 0x2035 }, { 0x203B, 0x203B }, { 0x2074, 0x2074 },
+ { 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
+ { 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
+ { 0x2113, 0x2113 }, { 0x2121, 0x2122 }, { 0x2126, 0x2126 },
+ { 0x212B, 0x212B }, { 0x2154, 0x2155 }, { 0x215B, 0x215B },
+ { 0x215E, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
+ { 0x2190, 0x2199 }, { 0x21D2, 0x21D2 }, { 0x21D4, 0x21D4 },
+ { 0x2200, 0x2200 }, { 0x2202, 0x2203 }, { 0x2207, 0x2208 },
+ { 0x220B, 0x220B }, { 0x220F, 0x220F }, { 0x2211, 0x2211 },
+ { 0x2215, 0x2215 }, { 0x221A, 0x221A }, { 0x221D, 0x2220 },
+ { 0x2223, 0x2223 }, { 0x2225, 0x2225 }, { 0x2227, 0x222C },
+ { 0x222E, 0x222E }, { 0x2234, 0x2237 }, { 0x223C, 0x223D },
+ { 0x2248, 0x2248 }, { 0x224C, 0x224C }, { 0x2252, 0x2252 },
+ { 0x2260, 0x2261 }, { 0x2264, 0x2267 }, { 0x226A, 0x226B },
+ { 0x226E, 0x226F }, { 0x2282, 0x2283 }, { 0x2286, 0x2287 },
+ { 0x2295, 0x2295 }, { 0x2299, 0x2299 }, { 0x22A5, 0x22A5 },
+ { 0x22BF, 0x22BF }, { 0x2312, 0x2312 }, { 0x2460, 0x24BF },
+ { 0x24D0, 0x24E9 }, { 0x2500, 0x254B }, { 0x2550, 0x2574 },
+ { 0x2580, 0x258F }, { 0x2592, 0x2595 }, { 0x25A0, 0x25A1 },
+ { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 }, { 0x25B6, 0x25B7 },
+ { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 }, { 0x25C6, 0x25C8 },
+ { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 }, { 0x25E2, 0x25E5 },
+ { 0x25EF, 0x25EF }, { 0x2605, 0x2606 }, { 0x2609, 0x2609 },
+ { 0x260E, 0x260F }, { 0x261C, 0x261C }, { 0x261E, 0x261E },
+ { 0x2640, 0x2640 }, { 0x2642, 0x2642 }, { 0x2660, 0x2661 },
+ { 0x2663, 0x2665 }, { 0x2667, 0x266A }, { 0x266C, 0x266D },
+ { 0x266F, 0x266F }, { 0x300A, 0x300B }, { 0x301A, 0x301B },
+ { 0xE000, 0xF8FF }, { 0xFFFD, 0xFFFD }
+ };
+
+ /* binary search in table of non-spacing characters */
+ if (bisearch(ucs, ambiguous,
+ sizeof(ambiguous) / sizeof(struct interval) - 1))
+ return 2;
+
+ return konsole_wcwidth(ucs);
+}
+#endif
+
+// single byte char: +1, multi byte char: +2
+int string_width( const QString &txt )
+{
+ int w = 0;
+ for ( uint i = 0; i < txt.length(); ++i )
+ w += konsole_wcwidth( txt[ i ].unicode() );
+ return w;
+}
diff --git a/konsole/konsole/konsole_wcwidth.h b/konsole/konsole/konsole_wcwidth.h
new file mode 100644
index 000000000..274fc5b7d
--- /dev/null
+++ b/konsole/konsole/konsole_wcwidth.h
@@ -0,0 +1,19 @@
+/* $XFree86: xc/programs/xterm/wcwidth.h,v 1.2 2001/06/18 19:09:27 dickey Exp $ */
+
+/* Markus Kuhn -- 2001-01-12 -- public domain */
+/* Adaptions for KDE by Waldo Bastian <bastian@kde.org> */
+
+#ifndef _KONSOLE_WCWIDTH_H_
+#define _KONSOLE_WCWIDTH_H_
+
+#include <qglobal.h>
+#include <qstring.h>
+
+int konsole_wcwidth(Q_UINT16 ucs);
+#if 0
+int konsole_wcwidth_cjk(Q_UINT16 ucs);
+#endif
+
+int string_width( const QString &txt );
+
+#endif
diff --git a/konsole/konsole/konsolebookmarkhandler.cpp b/konsole/konsole/konsolebookmarkhandler.cpp
new file mode 100644
index 000000000..27bdb4f87
--- /dev/null
+++ b/konsole/konsole/konsolebookmarkhandler.cpp
@@ -0,0 +1,104 @@
+/* This file was part of the KDE libraries
+ Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation, version 2.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// Born as kdelibs/kio/kfile/kfilebookmarkhandler.cpp
+
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kshell.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <kdebug.h>
+#include <qfile.h>
+
+#include "konsole.h"
+#include "konsolebookmarkmenu.h"
+#include "konsolebookmarkhandler.h"
+
+KonsoleBookmarkHandler::KonsoleBookmarkHandler( Konsole *konsole, bool toplevel )
+ : QObject( konsole, "KonsoleBookmarkHandler" ),
+ KBookmarkOwner(),
+ m_konsole( konsole )
+{
+ m_menu = new KPopupMenu( konsole, "bookmark menu" );
+
+ // KDE3.5 - Konsole's bookmarks are now in konsole/bookmarks.xml
+ // TODO: Consider removing for KDE4
+ QString new_bm_file = locateLocal( "data", "konsole/bookmarks.xml" );
+ if ( !QFile::exists( new_bm_file ) ) {
+ QString old_bm_file = locateLocal( "data", "kfile/bookmarks.xml" );
+ if ( QFile::exists( old_bm_file ) )
+ // We want sync here...
+ if ( !KIO::NetAccess::copy( KURL( old_bm_file ),
+ KURL ( new_bm_file ), 0 ) ) {
+ kdWarning()<<KIO::NetAccess::lastErrorString()<<endl;
+ }
+ }
+
+ m_file = locate( "data", "konsole/bookmarks.xml" );
+ if ( m_file.isEmpty() )
+ m_file = locateLocal( "data", "konsole/bookmarks.xml" );
+
+ KBookmarkManager *manager = KBookmarkManager::managerForFile( m_file, false);
+ manager->setEditorOptions(kapp->caption(), false);
+ manager->setUpdate( true );
+ manager->setShowNSBookmarks( false );
+
+ connect( manager, SIGNAL( changed(const QString &, const QString &) ),
+ SLOT( slotBookmarksChanged(const QString &, const QString &) ) );
+
+ if (toplevel) {
+ m_bookmarkMenu = new KonsoleBookmarkMenu( manager, this, m_menu,
+ konsole->actionCollection(), true );
+ } else {
+ m_bookmarkMenu = new KonsoleBookmarkMenu( manager, this, m_menu,
+ NULL, false /* Not toplevel */
+ ,false /* No 'Add Bookmark' */);
+ }
+}
+
+KonsoleBookmarkHandler::~KonsoleBookmarkHandler()
+{
+ delete m_bookmarkMenu;
+}
+
+QString KonsoleBookmarkHandler::currentURL() const
+{
+ return m_konsole->baseURL().prettyURL();
+}
+
+QString KonsoleBookmarkHandler::currentTitle() const
+{
+ const KURL &u = m_konsole->baseURL();
+ if (u.isLocalFile())
+ {
+ QString path = u.path();
+ path = KShell::tildeExpand(path);
+ return path;
+ }
+ return u.prettyURL();
+}
+
+void KonsoleBookmarkHandler::slotBookmarksChanged( const QString &,
+ const QString &)
+{
+ // This is called when someone changes bookmarks in konsole....
+ m_bookmarkMenu->slotBookmarksChanged("");
+}
+
+#include "konsolebookmarkhandler.moc"
diff --git a/konsole/konsole/konsolebookmarkhandler.h b/konsole/konsole/konsolebookmarkhandler.h
new file mode 100644
index 000000000..63ab747d9
--- /dev/null
+++ b/konsole/konsole/konsolebookmarkhandler.h
@@ -0,0 +1,62 @@
+/* This file wass part of the KDE libraries
+ Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation, version 2.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// Born as kdelibs/kio/kfile/kfilebookmarkhandler.h
+
+#ifndef KONSOLEBOOKMARKHANDLER_H
+#define KONSOLEBOOKMARKHANDLER_H
+
+#include <kbookmarkmanager.h>
+#include "konsolebookmarkmenu.h"
+
+class KPopupMenu;
+class KonsoleBookmarkMenu;
+class KBookmarkManager;
+
+class KonsoleBookmarkHandler : public QObject, public KBookmarkOwner
+{
+ Q_OBJECT
+
+public:
+ KonsoleBookmarkHandler( Konsole *konsole, bool toplevel );
+ ~KonsoleBookmarkHandler();
+
+ QPopupMenu * popupMenu();
+
+ // KBookmarkOwner interface:
+ virtual void openBookmarkURL( const QString& url, const QString& title )
+ { emit openURL( url, title ); }
+ virtual QString currentURL() const;
+ virtual QString currentTitle() const;
+
+ KPopupMenu *menu() const { return m_menu; }
+
+private slots:
+ void slotBookmarksChanged( const QString &, const QString & caller );
+
+signals:
+ void openURL( const QString& url, const QString& title );
+
+private:
+ Konsole *m_konsole;
+ KPopupMenu *m_menu;
+ KonsoleBookmarkMenu *m_bookmarkMenu;
+ QString m_file;
+};
+
+#endif // KONSOLEBOOKMARKHANDLER_H
diff --git a/konsole/konsole/konsolebookmarkmenu.cpp b/konsole/konsole/konsolebookmarkmenu.cpp
new file mode 100644
index 000000000..ea82a75e3
--- /dev/null
+++ b/konsole/konsole/konsolebookmarkmenu.cpp
@@ -0,0 +1,156 @@
+/* This file was part of the KDE libraries
+ Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation, version 2.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kaction.h>
+
+#include "konsole.h"
+#include "konsolebookmarkmenu.h"
+#include "konsolebookmarkhandler.h"
+
+KonsoleBookmarkMenu::KonsoleBookmarkMenu( KBookmarkManager* mgr,
+ KonsoleBookmarkHandler * _owner, KPopupMenu * _parentMenu,
+ KActionCollection *collec, bool _isRoot, bool _add,
+ const QString & parentAddress )
+: KBookmarkMenu( mgr, _owner, _parentMenu, collec, _isRoot, _add,
+ parentAddress),
+ m_kOwner(_owner)
+{
+ m_bAddShortcuts = false;
+ /*
+ * First, we disconnect KBookmarkMenu::slotAboutToShow()
+ * Then, we connect KonsoleBookmarkMenu::slotAboutToShow().
+ * They are named differently because the SLOT() macro thinks we want
+ * KonsoleBookmarkMenu::KBookmarkMenu::slotAboutToShow()
+ * Could this be solved if slotAboutToShow() is virtual in KBookmarMenu?
+ */
+ disconnect( _parentMenu, SIGNAL( aboutToShow() ), this,
+ SLOT( slotAboutToShow() ) );
+ connect( _parentMenu, SIGNAL( aboutToShow() ),
+ SLOT( slotAboutToShow2() ) );
+}
+
+/*
+ * Duplicate this exactly because KBookmarkMenu::slotBookmarkSelected can't
+ * be overrided. I would have preferred to NOT have to do this.
+ *
+ * Why did I do this?
+ * - when KBookmarkMenu::fillbBookmarkMenu() creates sub-KBookmarkMenus.
+ * - when ... adds KActions, it uses KBookmarkMenu::slotBookmarkSelected()
+ * instead of KonsoleBookmarkMenu::slotBookmarkSelected().
+ */
+void KonsoleBookmarkMenu::slotAboutToShow2()
+{
+ // Did the bookmarks change since the last time we showed them ?
+ if ( m_bDirty )
+ {
+ m_bDirty = false;
+ refill();
+ }
+}
+
+void KonsoleBookmarkMenu::refill()
+{
+ m_lstSubMenus.clear();
+ QPtrListIterator<KAction> it( m_actions );
+ for (; it.current(); ++it )
+ it.current()->unplug( m_parentMenu );
+ m_parentMenu->clear();
+ m_actions.clear();
+ fillBookmarkMenu();
+ m_parentMenu->adjustSize();
+}
+
+void KonsoleBookmarkMenu::fillBookmarkMenu()
+{
+ if ( m_bIsRoot )
+ {
+ if ( m_bAddBookmark )
+ addAddBookmark();
+
+ addEditBookmarks();
+
+ if ( m_bAddBookmark )
+ addNewFolder();
+ }
+
+ KBookmarkGroup parentBookmark = m_pManager->findByAddress( m_parentAddress ).toGroup();
+ Q_ASSERT(!parentBookmark.isNull());
+ bool separatorInserted = false;
+ for ( KBookmark bm = parentBookmark.first(); !bm.isNull();
+ bm = parentBookmark.next(bm) )
+ {
+ QString text = bm.text();
+ text.replace( '&', "&&" );
+ if ( !separatorInserted && m_bIsRoot) { // inserted before the first konq bookmark, to avoid the separator if no konq bookmark
+ m_parentMenu->insertSeparator();
+ separatorInserted = true;
+ }
+ if ( !bm.isGroup() )
+ {
+ if ( bm.isSeparator() )
+ {
+ m_parentMenu->insertSeparator();
+ }
+ else
+ {
+ // kdDebug(1203) << "Creating URL bookmark menu item for " << bm.text() << endl;
+ // create a normal URL item, with ID as a name
+ KAction * action = new KAction( text, bm.icon(), 0,
+ this, SLOT( slotBookmarkSelected() ),
+ m_actionCollection, bm.url().url().utf8() );
+
+ action->setStatusText( bm.url().prettyURL() );
+
+ action->plug( m_parentMenu );
+ m_actions.append( action );
+ }
+ }
+ else
+ {
+ // kdDebug(1203) << "Creating bookmark submenu named " << bm.text() << endl;
+ KActionMenu * actionMenu = new KActionMenu( text, bm.icon(),
+ m_actionCollection, 0L );
+ actionMenu->plug( m_parentMenu );
+ m_actions.append( actionMenu );
+ KonsoleBookmarkMenu *subMenu = new KonsoleBookmarkMenu( m_pManager,
+ m_kOwner, actionMenu->popupMenu(),
+ m_actionCollection, false,
+ m_bAddBookmark, bm.address() );
+ m_lstSubMenus.append( subMenu );
+ }
+ }
+
+ if ( !m_bIsRoot && m_bAddBookmark )
+ {
+ if ( m_parentMenu->count() > 0 )
+ m_parentMenu->insertSeparator();
+ addAddBookmark();
+ addNewFolder();
+ }
+}
+
+void KonsoleBookmarkMenu::slotBookmarkSelected()
+{
+ if ( !m_pOwner ) return; // this view doesn't handle bookmarks...
+ m_kOwner->openBookmarkURL( QString::fromUtf8(sender()->name()), /* URL */
+ ( (KAction *)sender() )->text() /* Title */ );
+}
+
+#include "konsolebookmarkmenu.moc"
diff --git a/konsole/konsole/konsolebookmarkmenu.h b/konsole/konsole/konsolebookmarkmenu.h
new file mode 100644
index 000000000..e4540da69
--- /dev/null
+++ b/konsole/konsole/konsolebookmarkmenu.h
@@ -0,0 +1,72 @@
+/* This file was part of the KDE libraries
+ Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation, version 2.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KONSOLEBOOKMARKMENU_H
+#define KONSOLEBOOKMARKMENU_H
+
+#include <qptrlist.h>
+#include <kbookmark.h>
+#include <kbookmarkmenu.h>
+
+#include "konsolebookmarkhandler.h"
+
+
+class QString;
+class KBookmark;
+class KAction;
+class KActionMenu;
+class KActionCollection;
+class KBookmarkOwner;
+class KBookmarkMenu;
+class KPopupMenu;
+class KonsoleBookmarkMenu;
+
+class KonsoleBookmarkMenu : public KBookmarkMenu
+{
+ Q_OBJECT
+
+public:
+ KonsoleBookmarkMenu( KBookmarkManager* mgr,
+ KonsoleBookmarkHandler * _owner, KPopupMenu * _parentMenu,
+ KActionCollection *collec, bool _isRoot,
+ bool _add = true, const QString & parentAddress = "");
+
+ void fillBookmarkMenu();
+
+public slots:
+
+signals:
+
+private slots:
+
+private:
+ KonsoleBookmarkHandler * m_kOwner;
+
+protected slots:
+ void slotAboutToShow2();
+ void slotBookmarkSelected();
+
+protected:
+ void refill();
+
+private:
+ class KonsoleBookmarkMenuPrivate;
+ KonsoleBookmarkMenuPrivate *d;
+};
+
+#endif // KONSOLEBOOKMARKMENU_H
diff --git a/konsole/konsole/konsoleiface.h b/konsole/konsole/konsoleiface.h
new file mode 100644
index 000000000..fc3002a35
--- /dev/null
+++ b/konsole/konsole/konsoleiface.h
@@ -0,0 +1,49 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 2001 by Stephan Binner <binner@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef KONSOLEIFACE_H
+#define KONSOLEIFACE_H
+
+#include <dcopobject.h>
+
+class KonsoleIface : virtual public DCOPObject
+{
+ K_DCOP
+ k_dcop:
+
+ virtual int sessionCount() = 0;
+
+ virtual QString currentSession() = 0;
+ virtual QString newSession() = 0;
+ virtual QString newSession(const QString &type) = 0;
+ virtual QString sessionId(const int position) = 0;
+
+ virtual void activateSession(const QString &sessionId) = 0;
+
+ virtual void nextSession() = 0;
+ virtual void prevSession() = 0;
+ virtual void moveSessionLeft() = 0;
+ virtual void moveSessionRight() = 0;
+ virtual bool fullScreen() = 0;
+ virtual void setFullScreen(bool on) = 0;
+ virtual ASYNC reparseConfiguration() = 0;
+};
+
+#endif // KONSOLEIFACE_H
diff --git a/konsole/konsole/kwrited.cpp b/konsole/konsole/kwrited.cpp
new file mode 100644
index 000000000..7b0e1167b
--- /dev/null
+++ b/konsole/konsole/kwrited.cpp
@@ -0,0 +1,143 @@
+/*
+ kwrited is a write(1) receiver for KDE.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+// System
+#include <iostream>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+
+// X11
+#include <X11/Xlib.h>
+#include <fixx11h.h>
+
+// Qt
+#include <dcopclient.h>
+#include <qsocketnotifier.h>
+
+// KDE
+#include <kuniqueapplication.h>
+#include <kcmdlineargs.h>
+#include <klocale.h>
+#include <kglobalsettings.h>
+#include <kdebug.h>
+#include <kcrash.h>
+#include <kpty.h>
+#include <kuser.h>
+#include <kglobal.h>
+
+// kwrited
+#include "kwrited.h"
+#include <config.h>
+
+/* TODO
+ for anyone who likes to do improvements here, go ahead.
+ - check FIXMEs below
+ - add Menu
+ - accept messages (on/off)
+ - pop up on incoming messages
+ - clear messages
+ - allow max. lines
+ - add CORBA interface?
+ - add session awareness.
+ - add client complements.
+*/
+
+KWrited::KWrited() : QTextEdit()
+{
+ int pref_width, pref_height;
+
+ setFont(KGlobalSettings::fixedFont());
+ pref_width = (2 * KGlobalSettings::desktopGeometry(0).width()) / 3;
+ pref_height = fontMetrics().lineSpacing() * 10;
+ setMinimumWidth(pref_width);
+ setMinimumHeight(pref_height);
+ setReadOnly(true);
+ setFocusPolicy(QWidget::NoFocus);
+ setWordWrap(QTextEdit::WidgetWidth);
+ setTextFormat(Qt::PlainText);
+
+ pty = new KPty();
+ pty->open();
+ pty->login(KUser().loginName().local8Bit().data(), getenv("DISPLAY"));
+ QSocketNotifier *sn = new QSocketNotifier(pty->masterFd(), QSocketNotifier::Read, this);
+ connect(sn, SIGNAL(activated(int)), this, SLOT(block_in(int)));
+
+ QString txt = i18n("KWrited - Listening on Device %1").arg(pty->ttyName());
+ setCaption(txt);
+
+ kdDebug() << txt << endl;
+}
+
+KWrited::~KWrited()
+{
+ pty->logout();
+ delete pty;
+}
+
+void KWrited::block_in(int fd)
+{
+ char buf[4096];
+ int len = read(fd, buf, 4096);
+ if (len <= 0)
+ return;
+
+ insert( QString::fromLocal8Bit( buf, len ).remove('\r') );
+ show();
+ raise();
+}
+
+void KWrited::clearText()
+{
+ clear();
+}
+
+QPopupMenu *KWrited::createPopupMenu( const QPoint &pos )
+{
+ QPopupMenu *menu = QTextEdit::createPopupMenu( pos );
+
+ menu->insertItem( i18n( "Clear Messages" ),
+ this, SLOT( clearText() ),
+ 0, -1, 0 );
+
+ return menu;
+}
+
+KWritedModule::KWritedModule( const QCString& obj )
+ : KDEDModule( obj )
+{
+ KGlobal::locale()->insertCatalogue("konsole");
+ pro = new KWrited;
+}
+
+KWritedModule::~KWritedModule()
+{
+ delete pro;
+ KGlobal::locale()->removeCatalogue("konsole");
+}
+
+extern "C"
+KDE_EXPORT KDEDModule* create_kwrited( const QCString& obj )
+ {
+ return new KWritedModule( obj );
+ }
+
+#include "kwrited.moc"
diff --git a/konsole/konsole/kwrited.h b/konsole/konsole/kwrited.h
new file mode 100644
index 000000000..71da6eff1
--- /dev/null
+++ b/konsole/konsole/kwrited.h
@@ -0,0 +1,56 @@
+/*
+ kwrited is a write(1) receiver for KDE.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef KWRITED_H
+#define KWRITED_H
+
+#include <qtextedit.h>
+#include <kdedmodule.h>
+#include <qpopupmenu.h>
+#include <qtextedit.h>
+
+class KPty;
+
+class KWrited : public QTextEdit
+{ Q_OBJECT
+public:
+ KWrited();
+ ~KWrited();
+protected:
+ virtual QPopupMenu *createPopupMenu(const QPoint &);
+private slots:
+ void block_in(int fd);
+ void clearText(void);
+private:
+ KPty* pty;
+};
+
+class KWritedModule : public KDEDModule
+{
+ Q_OBJECT
+ K_DCOP
+public:
+ KWritedModule( const QCString& obj );
+ ~KWritedModule();
+private:
+ KWrited* pro;
+};
+
+#endif
diff --git a/konsole/konsole/linefont.h b/konsole/konsole/linefont.h
new file mode 100644
index 000000000..9873c43d4
--- /dev/null
+++ b/konsole/konsole/linefont.h
@@ -0,0 +1,21 @@
+// WARNING: Autogenerated by "fontembedder ./linefont.src".
+// You probably do not want to hand-edit this!
+
+static const Q_UINT32 LineChars[] = {
+ 0x00007c00, 0x000fffe0, 0x00421084, 0x00e739ce, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00427000, 0x004e7380, 0x00e77800, 0x00ef7bc0,
+ 0x00421c00, 0x00439ce0, 0x00e73c00, 0x00e7bde0, 0x00007084, 0x000e7384, 0x000079ce, 0x000f7bce,
+ 0x00001c84, 0x00039ce4, 0x00003dce, 0x0007bdee, 0x00427084, 0x004e7384, 0x004279ce, 0x00e77884,
+ 0x00e779ce, 0x004f7bce, 0x00ef7bc4, 0x00ef7bce, 0x00421c84, 0x00439ce4, 0x00423dce, 0x00e73c84,
+ 0x00e73dce, 0x0047bdee, 0x00e7bde4, 0x00e7bdee, 0x00427c00, 0x0043fce0, 0x004e7f80, 0x004fffe0,
+ 0x004fffe0, 0x00e7fde0, 0x006f7fc0, 0x00efffe0, 0x00007c84, 0x0003fce4, 0x000e7f84, 0x000fffe4,
+ 0x00007dce, 0x0007fdee, 0x000f7fce, 0x000fffee, 0x00427c84, 0x0043fce4, 0x004e7f84, 0x004fffe4,
+ 0x00427dce, 0x00e77c84, 0x00e77dce, 0x0047fdee, 0x004e7fce, 0x00e7fde4, 0x00ef7f84, 0x004fffee,
+ 0x00efffe4, 0x00e7fdee, 0x00ef7fce, 0x00efffee, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x000f83e0, 0x00a5294a, 0x004e1380, 0x00a57800, 0x00ad0bc0, 0x004390e0, 0x00a53c00, 0x00a5a1e0,
+ 0x000e1384, 0x0000794a, 0x000f0b4a, 0x000390e4, 0x00003d4a, 0x0007a16a, 0x004e1384, 0x00a5694a,
+ 0x00ad2b4a, 0x004390e4, 0x00a52d4a, 0x00a5a16a, 0x004f83e0, 0x00a57c00, 0x00ad83e0, 0x000f83e4,
+ 0x00007d4a, 0x000f836a, 0x004f93e4, 0x00a57d4a, 0x00ad836a, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00001c00, 0x00001084, 0x00007000, 0x00421000,
+ 0x00039ce0, 0x000039ce, 0x000e7380, 0x00e73800, 0x000e7f80, 0x00e73884, 0x0003fce0, 0x004239ce
+};
diff --git a/konsole/konsole/linefont.src b/konsole/konsole/linefont.src
new file mode 100644
index 000000000..6835253f4
--- /dev/null
+++ b/konsole/konsole/linefont.src
@@ -0,0 +1,786 @@
+#2500: single horizontal line
+2500
+
+
+-----
+
+
+
+#2501: triple horizontal line
+2501
+
+-----
+-----
+-----
+
+
+#2502: single vertical line
+2502
+ |
+ |
+ |
+ |
+ |
+
+#2503: triple vertical line
+2503
+ |||
+ |||
+ |||
+ |||
+ |||
+
+#2504-250B are dashed - not handled
+
+#250C: top-left corner (lines on bottom + right)
+250C
+
+
+ .--
+ |
+ |
+
+#250D: as above, but top line triple-width
+250D
+
+ .--
+ .--
+ |--
+ |
+
+#250E: now the vert line triple-width
+250E
+
+
+ ..--
+ |||
+ |||
+
+#250F: and now both lines triple-width
+250F
+
+ .___
+ |.--
+ ||._
+ |||
+
+#2510: top-right corner
+2510
+
+
+--.
+ |
+ |
+
+2511
+
+==.
+==.
+==|
+ |
+
+2512
+
+
+==..
+ |||
+ |||
+
+2513
+
+===.
+==.|
+=.||
+ |||
+
+#2514: bottom-left corner
+2514
+ |
+ |
+ .==
+
+
+
+2515
+ |
+ |==
+ |==
+ ===
+
+
+
+2516
+ |||
+ |||
+ |.==
+
+
+
+2517
+ |||
+ ||.=
+ |.==
+ .===
+
+
+#2518: bottm-right corner
+2518
+ |
+ |
+==.
+
+
+
+2519
+ |
+==|
+==|
+===
+
+
+
+251A
+ |||
+ |||
+====
+
+
+
+251B
+ |||
+=.||
+==.|
+===.
+
+
+#251C: Join of vertical line and one from the right
+251C
+ |
+ |
+ |==
+ |
+ |
+
+251D
+ |
+ |==
+ |==
+ |==
+ |
+
+251E
+ |||
+ |||
+ ||==
+ |
+ |
+
+251F
+ |
+ |
+ ||==
+ |||
+ |||
+
+
+2520
+ |||
+ |||
+ ||==
+ |||
+ |||
+
+2521
+ |||
+ |||=
+ ||==
+ .|==
+ |
+
+2522
+ |
+ .|==
+ ||==
+ |||=
+ |||
+
+2523
+ |||
+ ||.=
+ ||==
+ ||.=
+ |||
+
+#2524: Join of vertical line and one from the left
+2524
+ |
+ |
+==|
+ |
+ |
+
+2525
+ |
+==|
+==|
+==|
+ |
+
+2526
+ |||
+ |||
+==+|
+ |
+ |
+
+2527
+ |
+ |
+==+|
+ |||
+ |||
+
+2528
+ |||
+ |||
+==+|
+ |||
+ |||
+
+2529
+ |||
+=+||
+==+|
+===+
+ |
+
+252A
+ |
+=+||
+==+|
+===+
+ |||
+
+252B
+ |||
+=+||
+==+|
+=+||
+ |||
+
+#252C: horizontal line joined to from below
+252C
+
+
+=====
+ |
+ |
+
+252D
+
+===
+==|==
+==|
+ |
+
+252E
+
+ ===
+==|==
+ |==
+ |
+
+252F
+
+==+==
+==|==
+==|==
+ |
+
+2530
+
+=====
+=====
+==|==
+ |
+
+2531
+
+===|
+==||=
+=|||
+ |||
+
+2532
+
+ |===
+=||==
+ ||==
+ ||
+
+2533
+
+=====
+==|==
+=+|+=
+ |||
+
+#2534: bottom line, connected to from top
+2534
+ |
+ |
+=====
+
+
+
+2535
+ |
+==|
+=====
+===
+
+
+2536
+ |
+ |==
+=====
+ ===
+
+
+2537
+ |
+==|==
+=====
+=====
+
+
+2538
+ |||
+ |||
+=====
+
+
+
+2539
+ |||
+==||
+=====
+===|
+
+
+
+253A
+ |||
+ ||==
+=|===
+ |===
+
+
+253B
+ |||
+==|==
+=====
+=====
+
+
+#253C: vertical + horizontal lines intersecting
+253C
+ |
+ |
+=====
+ |
+ |
+
+253D
+ |
+==|
+=====
+==|
+ |
+
+253E
+ |
+ |==
+=====
+ |==
+ |
+
+253F
+ |
+==|==
+=====
+==|==
+ |
+
+2540
+ |||
+ |||
+=====
+ |
+ |
+
+2541
+ |
+ |
+=====
+ |||
+ |||
+
+2542
+ |||
+ |||
+=====
+ |||
+ |||
+
+2543
+ |||
+=|||
+=====
+==|+
+ |
+
+2544
+ |||
+ ||==
+=====
+ |==
+ |
+
+2545
+ |
+==|+
+=====
+=|||
+ |||
+
+2546
+ |
+ |==
+=====
+ ||==
+ |||
+
+2547
+ |||
+=|||=
+=====
+=|||=
+ |
+
+2548
+ |
+=|||=
+=====
+=|||=
+ |||
+
+2549
+ |||
+=|||
+=====
+=|||
+ |||
+
+254A
+ |||
+ |||=
+=====
+ |||=
+ |||
+
+254B
+ |||
+=|||=
+=====
+=|||=
+ |||
+
+#254C-254F are dashed
+2550
+
+_____
+
+_____
+
+
+2551
+ | |
+ | |
+ | |
+ | |
+ | |
+
+2552
+
+ |--
+ |
+ |--
+ |
+
+2553
+
+
+ ----
+ | |
+ | |
+
+2554
+
+ +---
+ |
+ + +-
+ | |
+
+2555
+
+--+
+ |
+--+
+ |
+
+2556
+
+
+-+-+
+ | |
+ | |
+
+2557
+
+---+
+ |
+-+ |
+ | |
+
+2558
+ |
+ +--
+ |
+ +--
+
+2559
+ | |
+ | |
+ +-+-
+
+
+
+255A
+ | |
+ | +-
+ |
+ +---
+
+
+255B
+ |
+--+
+ |
+--+
+
+
+255C
+ | |
+ | |
+-+-+
+
+
+255D
+ | |
+-+ |
+ |
+---+
+
+
+255E
+ |
+ +--
+ |
+ +--
+ |
+
+255F
+ | |
+ | |
+ | +-
+ | |
+ | |
+
+2560
+ | |
+ | +-
+ | |
+ | +-
+ | |
+
+2561
+ |
+--+
+ |
+--+
+ |
+
+2562
+ | |
+ | |
+-+ +
+ | |
+ | |
+
+2563
+ | |
+-+ |
+ |
+-+ |
+ | |
+
+2564
+
+-----
+
+--+--
+ |
+
+2565
+
+
+-+-+-
+ | |
+ | |
+
+2566
+
+-----
+
+-+ +-
+ | |
+
+2567
+ |
+--+--
+
+-----
+
+
+2568
+ | |
+ | |
+-+-+-
+
+
+
+2569
+ | |
+-+ +-
+
+-----
+
+
+256A
+ |
+--+--
+ |
+--+--
+ |
+
+256B
+ | |
+ | |
+-+-+-
+ | |
+ | |
+
+256C
+ | |
+-+ +-
+
+-+ +-
+ | |
+
+#256F-2570 are curly,
+#2571-2573 are slashes and X
+
+2574
+
+
+___
+
+
+
+2575
+ |
+ |
+ |
+
+
+
+2576
+
+
+ ___
+
+
+
+2577
+
+
+ |
+ |
+ |
+
+2578
+
+___
+___
+___
+
+
+2579
+ |||
+ |||
+ |||
+
+
+
+257A
+
+ ___
+ ___
+ ___
+
+
+257B
+
+
+ |||
+ |||
+ |||
+
+257C
+
+ ___
+_____
+ ___
+
+
+257D
+ |
+ |
+ |||
+ |||
+ |||
+
+257E
+
+___
+_____
+___
+
+
+257F
+ |||
+ |||
+ |||
+ |
+ |
diff --git a/konsole/konsole/main.cpp b/konsole/konsole/main.cpp
new file mode 100644
index 000000000..48e9eab2a
--- /dev/null
+++ b/konsole/konsole/main.cpp
@@ -0,0 +1,671 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1996 by Matthias Ettrich <ettrich@kde.org>
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+/* The material contained in here more or less directly orginates from */
+/* kvt, which is copyright (c) 1996 by Matthias Ettrich <ettrich@kde.org> */
+/* */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <qdir.h>
+#include <qsessionmanager.h>
+#include <qwidgetlist.h>
+
+#include <dcopclient.h>
+
+#include <klocale.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <kimageio.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <kio/netaccess.h>
+#include <kmessagebox.h>
+
+#include <config.h>
+
+#include "konsole.h"
+
+#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && QT_VERSION >= 0x030300
+#define COMPOSITE
+#endif
+
+#ifdef COMPOSITE
+# include <X11/Xlib.h>
+# include <X11/extensions/Xrender.h>
+# include <fixx11h.h>
+# include <dlfcn.h>
+#endif
+
+static const char description[] =
+ I18N_NOOP("X terminal for use with KDE.");
+
+// { "T <title>", 0, 0 },
+static KCmdLineOptions options[] =
+{
+ { "name <name>", I18N_NOOP("Set window class"), 0 },
+ { "ls", I18N_NOOP("Start login shell"), 0 },
+ { "T <title>", I18N_NOOP("Set the window title"), 0 },
+ { "tn <terminal>", I18N_NOOP("Specify terminal type as set in the TERM\nenvironment variable"), "xterm" },
+ { "noclose", I18N_NOOP("Do not close Konsole when command exits"), 0 },
+ { "nohist", I18N_NOOP("Do not save lines in history"), 0 },
+ { "nomenubar", I18N_NOOP("Do not display menubar"), 0 },
+ { "notabbar", 0, 0 },
+ { "notoolbar", I18N_NOOP("Do not display tab bar"), 0 },
+ { "noframe", I18N_NOOP("Do not display frame"), 0 },
+ { "noscrollbar", I18N_NOOP("Do not display scrollbar"), 0 },
+ { "noxft", I18N_NOOP("Do not use Xft (anti-aliasing)"), 0 },
+#ifdef COMPOSITE
+ { "real-transparency", I18N_NOOP("Enable experimental support for real transparency"), 0 },
+#endif
+ { "vt_sz CCxLL", I18N_NOOP("Terminal size in columns x lines"), 0 },
+ { "noresize", I18N_NOOP("Terminal size is fixed"), 0 },
+ { "type <type>", I18N_NOOP("Start with given session type"), 0 },
+ { "types", I18N_NOOP("List available session types"), 0 },
+ { "keytab <name>", I18N_NOOP("Set keytab to 'name'"), 0 },
+ { "keytabs", I18N_NOOP("List available keytabs"), 0 },
+ { "profile <name>", I18N_NOOP("Start with given session profile"), 0 },
+ { "profiles", I18N_NOOP("List available session profiles"), 0 },
+ { "schema <name> | <file>", I18N_NOOP("Set schema to 'name' or use 'file'"), 0 },
+ { "schemas", 0, 0 },
+ { "schemata", I18N_NOOP("List available schemata"), 0 },
+ { "script", I18N_NOOP("Enable extended DCOP Qt functions"), 0 },
+ { "workdir <dir>", I18N_NOOP("Change working directory to 'dir'"), 0 },
+ { "!e <command>", I18N_NOOP("Execute 'command' instead of shell"), 0 },
+ // WABA: All options after -e are treated as arguments.
+ { "+[args]", I18N_NOOP("Arguments for 'command'"), 0 },
+ KCmdLineLastOption
+};
+
+static bool has_noxft = false;
+static bool login_shell = false;
+static bool full_script = false;
+static bool auto_close = true;
+static bool fixed_size = false;
+
+bool argb_visual = false;
+
+const char *konsole_shell(QStrList &args)
+{
+ const char* shell = getenv("SHELL");
+ if (shell == NULL || *shell == '\0') shell = "/bin/sh";
+ if (login_shell)
+ {
+ char* t = (char*)strrchr(shell,'/');
+ if (t) // see sh(1)
+ {
+ t = strdup(t);
+ *t = '-';
+ args.append(t);
+ free(t);
+ }
+ else
+ args.append(shell);
+ }
+ else
+ args.append(shell);
+ return shell;
+}
+
+/**
+ The goal of this class is to add "--noxft" and "--ls" to the restoreCommand
+ if konsole was started with any of those options.
+ */
+class KonsoleSessionManaged: public KSessionManaged {
+public:
+ bool saveState( QSessionManager&sm) {
+ QStringList restartCommand = sm.restartCommand();
+ if (has_noxft)
+ restartCommand.append("--noxft");
+ if (login_shell)
+ restartCommand.append("--ls");
+ if (full_script)
+ restartCommand.append("--script");
+ if (!auto_close)
+ restartCommand.append("--noclose");
+ if (fixed_size)
+ restartCommand.append("--noresize");
+ sm.setRestartCommand(restartCommand);
+ return true;
+ }
+};
+
+
+
+/* --| main |------------------------------------------------------ */
+extern "C" int KDE_EXPORT kdemain(int argc, char* argv[])
+{
+ setgid(getgid()); setuid(getuid()); // drop privileges
+
+ // deal with shell/command ////////////////////////////
+ bool histon = true;
+ bool menubaron = true;
+ bool tabbaron = true;
+ bool frameon = true;
+ bool scrollbaron = true;
+ bool showtip = true;
+
+ KAboutData aboutData( "konsole", I18N_NOOP("Konsole"),
+ KONSOLE_VERSION, description, KAboutData::License_GPL_V2,
+ "Copyright (c) 1997-2006, Lars Doelle");
+ aboutData.addAuthor("Robert Knight",I18N_NOOP("Maintainer"), "robertknight@gmail.com");
+ aboutData.addAuthor("Lars Doelle",I18N_NOOP("Author"), "lars.doelle@on-line.de");
+ aboutData.addCredit("Kurt V. Hindenburg",
+ I18N_NOOP("bug fixing and improvements"),
+ "kurt.hindenburg@gmail.com");
+ aboutData.addCredit("Waldo Bastian",
+ I18N_NOOP("bug fixing and improvements"),
+ "bastian@kde.org");
+ aboutData.addCredit("Stephan Binner",
+ I18N_NOOP("bug fixing and improvements"),
+ "binner@kde.org");
+ aboutData.addCredit("Chris Machemer",
+ I18N_NOOP("bug fixing"),
+ "machey@ceinetworks.com");
+ aboutData.addCredit("Stephan Kulow",
+ I18N_NOOP("Solaris support and work on history"),
+ "coolo@kde.org");
+ aboutData.addCredit("Alexander Neundorf",
+ I18N_NOOP("faster startup, bug fixing"),
+ "neundorf@kde.org");
+ aboutData.addCredit("Peter Silva",
+ I18N_NOOP("decent marking"),
+ "peter.silva@videotron.ca");
+ aboutData.addCredit("Lotzi Boloni",
+ I18N_NOOP("partification\n"
+ "Toolbar and session names"),
+ "boloni@cs.purdue.edu");
+ aboutData.addCredit("David Faure",
+ I18N_NOOP("partification\n"
+ "overall improvements"),
+ "David.Faure@insa-lyon.fr");
+ aboutData.addCredit("Antonio Larrosa",
+ I18N_NOOP("transparency"),
+ "larrosa@kde.org");
+ aboutData.addCredit("Matthias Ettrich",
+ I18N_NOOP("most of main.C donated via kvt\n"
+ "overall improvements"),
+ "ettrich@kde.org");
+ aboutData.addCredit("Warwick Allison",
+ I18N_NOOP("schema and selection improvements"),
+ "warwick@troll.no");
+ aboutData.addCredit("Dan Pilone",
+ I18N_NOOP("SGI Port"),
+ "pilone@slac.com");
+ aboutData.addCredit("Kevin Street",
+ I18N_NOOP("FreeBSD port"),
+ "street@iname.com");
+ aboutData.addCredit("Sven Fischer",
+ I18N_NOOP("bug fixing"),
+ "herpes@kawo2.rwth-aachen.de");
+ aboutData.addCredit("Dale M. Flaven",
+ I18N_NOOP("bug fixing"),
+ "dflaven@netport.com");
+ aboutData.addCredit("Martin Jones",
+ I18N_NOOP("bug fixing"),
+ "mjones@powerup.com.au");
+ aboutData.addCredit("Lars Knoll",
+ I18N_NOOP("bug fixing"),
+ "knoll@mpi-hd.mpg.de");
+ aboutData.addCredit("",I18N_NOOP("Thanks to many others.\n"
+ "The above list only reflects the contributors\n"
+ "I managed to keep track of."));
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
+ //1.53 sec
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt");
+ has_noxft = !args->isSet("xft");
+ TEWidget::setAntialias( !has_noxft );
+ TEWidget::setStandalone( true );
+
+ // The following Qt options have no effect; warn users.
+ if( qtargs->isSet("background") )
+ kdWarning() << "The Qt option -bg, --background has no effect." << endl;
+ if( qtargs->isSet("foreground") )
+ kdWarning() << "The Qt option -fg, --foreground has no effect." << endl;
+ if( qtargs->isSet("button") )
+ kdWarning() << "The Qt option -btn, --button has no effect." << endl;
+ if( qtargs->isSet("font") )
+ kdWarning() << "The Qt option -fn, --font has no effect." << endl;
+
+ KApplication* a = NULL;
+#ifdef COMPOSITE
+ if ( args->isSet("real-transparency")) {
+ char *display = 0;
+ if ( qtargs->isSet("display"))
+ display = qtargs->getOption( "display" ).data();
+
+ Display *dpy = XOpenDisplay( display );
+ if ( !dpy ) {
+ kdError() << "cannot connect to X server " << display << endl;
+ exit( 1 );
+ }
+
+ int screen = DefaultScreen( dpy );
+ Colormap colormap = 0;
+ Visual *visual = 0;
+ int event_base, error_base;
+
+ if ( XRenderQueryExtension( dpy, &event_base, &error_base ) ) {
+ int nvi;
+ XVisualInfo templ;
+ templ.screen = screen;
+ templ.depth = 32;
+ templ.c_class = TrueColor;
+ XVisualInfo *xvi = XGetVisualInfo( dpy, VisualScreenMask | VisualDepthMask
+ | VisualClassMask, &templ, &nvi );
+
+ for ( int i = 0; i < nvi; i++ ) {
+ XRenderPictFormat *format = XRenderFindVisualFormat( dpy, xvi[i].visual );
+ if ( format->type == PictTypeDirect && format->direct.alphaMask ) {
+ visual = xvi[i].visual;
+ colormap = XCreateColormap( dpy, RootWindow( dpy, screen ), visual, AllocNone );
+ kdDebug() << "found visual with alpha support" << endl;
+ argb_visual = true;
+ break;
+ }
+ }
+ }
+ // The QApplication ctor used is normally intended for applications not using Qt
+ // as the primary toolkit (e.g. Motif apps also using Qt), with some slightly
+ // unpleasant side effects (e.g. #83974). This code checks if qt-copy patch #0078
+ // is applied, which allows turning this off.
+ bool* qt_no_foreign_hack = static_cast< bool* >( dlsym( RTLD_DEFAULT, "qt_no_foreign_hack" ));
+ if( qt_no_foreign_hack )
+ *qt_no_foreign_hack = true;
+ // else argb_visual = false ... ? *shrug*
+
+ if( argb_visual )
+ a = new KApplication( dpy, Qt::HANDLE( visual ), Qt::HANDLE( colormap ) );
+ else
+ XCloseDisplay( dpy );
+ }
+ if( a == NULL )
+ a = new KApplication;
+#else
+ KApplication* a = new KApplication;
+#endif
+
+ QString dataPathBase = KStandardDirs::kde_default("data").append("konsole/");
+ KGlobal::dirs()->addResourceType("wallpaper", dataPathBase + "wallpapers");
+
+ KImageIO::registerFormats(); // add io for additional image formats
+ //2.1 secs
+
+ QString title;
+ if(args->isSet("T")) {
+ title = QFile::decodeName(args->getOption("T"));
+ }
+ if(qtargs->isSet("title")) {
+ title = QFile::decodeName(qtargs->getOption("title"));
+ }
+
+ QString term = "";
+ if(args->isSet("tn")) {
+ term=QString::fromLatin1(args->getOption("tn"));
+ }
+ login_shell = args->isSet("ls");
+
+ QStrList eargs;
+
+ const char* shell = 0;
+ if (!args->getOption("e").isEmpty())
+ {
+ if (args->isSet("ls"))
+ KCmdLineArgs::usage(i18n("You can't use BOTH -ls and -e.\n"));
+ shell = strdup(args->getOption("e"));
+ eargs.append(shell);
+ for(int i=0; i < args->count(); i++)
+ eargs.append( args->arg(i) );
+
+ if (title.isEmpty() &&
+ (kapp->caption() == kapp->aboutData()->programName()))
+ {
+ title = QFile::decodeName(shell); // program executed in the title bar
+ }
+ showtip = false;
+ }
+
+ QCString sz = "";
+ sz = args->getOption("vt_sz");
+ histon = args->isSet("hist");
+ menubaron = args->isSet("menubar");
+ tabbaron = args->isSet("tabbar") && args->isSet("toolbar");
+ frameon = args->isSet("frame");
+ scrollbaron = args->isSet("scrollbar");
+ QCString wname = qtargs->getOption("name");
+ full_script = args->isSet("script");
+ auto_close = args->isSet("close");
+ fixed_size = !args->isSet("resize");
+
+ if (!full_script)
+ a->dcopClient()->setQtBridgeEnabled(false);
+
+ QCString type = "";
+
+ if(args->isSet("type")) {
+ type = args->getOption("type");
+ }
+ if(args->isSet("types")) {
+ QStringList types = KGlobal::dirs()->findAllResources("appdata", "*.desktop", false, true);
+ types.sort();
+ for(QStringList::ConstIterator it = types.begin();
+ it != types.end(); ++it)
+ {
+ QString file = *it;
+ file = file.mid(file.findRev('/')+1);
+ if (file.endsWith(".desktop"))
+ file = file.left(file.length()-8);
+ printf("%s\n", QFile::encodeName(file).data());
+ }
+ return 0;
+ }
+ if(args->isSet("schemas") || args->isSet("schemata")) {
+ ColorSchemaList colors;
+ colors.checkSchemas();
+ for(int i = 0; i < (int) colors.count(); i++)
+ {
+ ColorSchema *schema = colors.find(i);
+ QString relPath = schema->relPath();
+ if (!relPath.isEmpty())
+ printf("%s\n", QFile::encodeName(relPath).data());
+ }
+ return 0;
+ }
+
+ if(args->isSet("keytabs")) {
+ QStringList lst = KGlobal::dirs()->findAllResources("data", "konsole/*.keytab");
+
+ printf("default\n"); // 'buildin' keytab
+ lst.sort();
+ for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it )
+ {
+ QFileInfo fi(*it);
+ QString file = fi.baseName();
+ printf("%s\n", QFile::encodeName(file).data());
+ }
+ return 0;
+ }
+
+ QString workDir = QFile::decodeName( args->getOption("workdir") );
+
+ QString keytab = "";
+ if (args->isSet("keytab"))
+ keytab = QFile::decodeName(args->getOption("keytab"));
+
+ QString schema = "";
+ if (args->isSet("schema"))
+ schema = args->getOption("schema");
+
+ KConfig * sessionconfig = 0;
+ QString profile = "";
+ if (args->isSet("profile")) {
+ profile = args->getOption("profile");
+ QString path = locate( "data", "konsole/profiles/" + profile );
+ if ( QFile::exists( path ) )
+ sessionconfig=new KConfig( path, true );
+ else
+ profile = "";
+ }
+ if (args->isSet("profiles"))
+ {
+ QStringList profiles = KGlobal::dirs()->findAllResources("data", "konsole/profiles/*", false, true);
+ profiles.sort();
+ for(QStringList::ConstIterator it = profiles.begin();
+ it != profiles.end(); ++it)
+ {
+ QString file = *it;
+ file = file.mid(file.findRev('/')+1);
+ printf("%s\n", QFile::encodeName(file).data());
+ }
+ return 0;
+ }
+
+
+ //FIXME: more: font
+
+ args->clear();
+
+ int c = 0, l = 0;
+ if ( !sz.isEmpty() )
+ {
+ char *ls = (char*)strchr( sz.data(), 'x' );
+ if ( ls != NULL )
+ {
+ *ls='\0';
+ ls++;
+ c=atoi(sz.data());
+ l=atoi(ls);
+ }
+ else
+ {
+ KCmdLineArgs::usage(i18n("expected --vt_sz <#columns>x<#lines> e.g. 80x40\n"));
+ }
+ }
+
+ if (!kapp->authorizeKAction("size"))
+ fixed_size = true;
+
+ // ///////////////////////////////////////////////
+
+ // Ignore SIGHUP so that we don't get killed when
+ // our parent-shell gets closed.
+ signal(SIGHUP, SIG_IGN);
+
+ putenv((char*)"COLORTERM="); // to trigger mc's color detection
+ KonsoleSessionManaged ksm;
+
+ if (a->isRestored() || !profile.isEmpty())
+ {
+ if (!shell)
+ shell = konsole_shell(eargs);
+
+ if (profile.isEmpty())
+ sessionconfig = a->sessionConfig();
+ sessionconfig->setDesktopGroup();
+ int n = 1;
+
+ QString key;
+ QString sTitle;
+ QString sPgm;
+ QString sTerm;
+ QString sIcon;
+ QString sCwd;
+ int n_tabbar;
+
+ // TODO: Session management stores everything in same group,
+ // should use one group / mainwindow
+ while (KMainWindow::canBeRestored(n) || !profile.isEmpty())
+ {
+ sessionconfig->setGroup(QString("%1").arg(n));
+ if (!sessionconfig->hasKey("Pgm0"))
+ sessionconfig->setDesktopGroup(); // Backwards compatible
+
+ int session_count = sessionconfig->readNumEntry("numSes");
+ int counter = 0;
+
+ wname = sessionconfig->readEntry("class",wname).latin1();
+
+ sPgm = sessionconfig->readEntry("Pgm0", shell);
+ sessionconfig->readListEntry("Args0", eargs);
+ sTitle = sessionconfig->readEntry("Title0", title);
+ sTerm = sessionconfig->readEntry("Term0");
+ sIcon = sessionconfig->readEntry("Icon0","konsole");
+ sCwd = sessionconfig->readPathEntry("Cwd0");
+ workDir = sessionconfig->readPathEntry("workdir");
+ n_tabbar = QMIN(sessionconfig->readUnsignedNumEntry("tabbar",Konsole::TabBottom),2);
+ Konsole *m = new Konsole(wname,histon,menubaron,tabbaron,frameon,scrollbaron,0/*type*/,true,n_tabbar, workDir);
+
+ m->newSession(sPgm, eargs, sTerm, sIcon, sTitle, sCwd);
+
+ m->enableFullScripting(full_script);
+ m->enableFixedSize(fixed_size);
+ m->restore(n);
+ sessionconfig->setGroup(QString("%1").arg(n));
+ if (!sessionconfig->hasKey("Pgm0"))
+ sessionconfig->setDesktopGroup(); // Backwards compatible
+ m->makeGUI();
+ m->setEncoding(sessionconfig->readNumEntry("Encoding0"));
+ m->setSchema(sessionconfig->readEntry("Schema0"));
+ // Use konsolerc default as tmpFont instead?
+ QFont tmpFont = KGlobalSettings::fixedFont();
+ m->initSessionFont(sessionconfig->readFontEntry("SessionFont0", &tmpFont));
+ m->initSessionKeyTab(sessionconfig->readEntry("KeyTab0"));
+ m->initMonitorActivity(sessionconfig->readBoolEntry("MonitorActivity0",false));
+ m->initMonitorSilence(sessionconfig->readBoolEntry("MonitorSilence0",false));
+ m->initMasterMode(sessionconfig->readBoolEntry("MasterMode0",false));
+ m->initTabColor(sessionconfig->readColorEntry("TabColor0"));
+ // -1 will be changed to the default history in konsolerc
+ m->initHistory(sessionconfig->readNumEntry("History0", -1),
+ sessionconfig->readBoolEntry("HistoryEnabled0", true));
+ counter++;
+
+ // show() before 2nd+ sessions are created allows --profile to
+ // initialize the TE size correctly.
+ m->show();
+
+ while (counter < session_count)
+ {
+ key = QString("Title%1").arg(counter);
+ sTitle = sessionconfig->readEntry(key, title);
+ key = QString("Args%1").arg(counter);
+ sessionconfig->readListEntry(key, eargs);
+
+ key = QString("Pgm%1").arg(counter);
+
+ // if the -e option is passed on the command line, this overrides the program specified
+ // in the profile file
+ if ( args->isSet("e") )
+ sPgm = (shell ? QFile::decodeName(shell) : QString::null);
+ else
+ sPgm = sessionconfig->readEntry(key, shell);
+
+ key = QString("Term%1").arg(counter);
+ sTerm = sessionconfig->readEntry(key);
+ key = QString("Icon%1").arg(counter);
+ sIcon = sessionconfig->readEntry(key,"konsole");
+ key = QString("Cwd%1").arg(counter);
+ sCwd = sessionconfig->readPathEntry(key);
+ m->newSession(sPgm, eargs, sTerm, sIcon, sTitle, sCwd);
+ m->setSessionTitle(sTitle); // Use title as is
+ key = QString("Schema%1").arg(counter);
+ m->setSchema(sessionconfig->readEntry(key));
+ key = QString("Encoding%1").arg(counter);
+ m->setEncoding(sessionconfig->readNumEntry(key));
+ key = QString("SessionFont%1").arg(counter);
+ QFont tmpFont = KGlobalSettings::fixedFont();
+ m->initSessionFont(sessionconfig->readFontEntry(key, &tmpFont));
+ key = QString("KeyTab%1").arg(counter);
+ m->initSessionKeyTab(sessionconfig->readEntry(key));
+ key = QString("MonitorActivity%1").arg(counter);
+ m->initMonitorActivity(sessionconfig->readBoolEntry(key,false));
+ key = QString("MonitorSilence%1").arg(counter);
+ m->initMonitorSilence(sessionconfig->readBoolEntry(key,false));
+ key = QString("MasterMode%1").arg(counter);
+ m->initMasterMode(sessionconfig->readBoolEntry(key,false));
+ key = QString("TabColor%1").arg(counter);
+ m->initTabColor(sessionconfig->readColorEntry(key));
+ // -1 will be changed to the default history in konsolerc
+ key = QString("History%1").arg(counter);
+ QString key2 = QString("HistoryEnabled%1").arg(counter);
+ m->initHistory(sessionconfig->readNumEntry(key, -1),
+ sessionconfig->readBoolEntry(key2, true));
+ counter++;
+ }
+ m->setDefaultSession( sessionconfig->readEntry("DefaultSession","shell.desktop") );
+
+ m->initFullScreen();
+ if ( !profile.isEmpty() ) {
+ m->callReadPropertiesInternal(sessionconfig,1);
+ profile = "";
+ // Hack to work-around sessions initialized with minimum size
+ for (int i=0;i<counter;i++)
+ m->activateSession( i );
+ m->setColLin(c,l); // will use default height and width if called with (0,0)
+ }
+ // works only for the first one, but there won't be more.
+ n++;
+ m->activateSession( sessionconfig->readNumEntry("ActiveSession",0) );
+ m->setAutoClose(auto_close);
+ }
+ }
+ else
+ {
+ Konsole* m = new Konsole(wname,histon,menubaron,tabbaron,frameon,scrollbaron,type, false, 0, workDir);
+ m->newSession((shell ? QFile::decodeName(shell) : QString::null), eargs, term, QString::null, title, workDir);
+ m->enableFullScripting(full_script);
+ m->enableFixedSize(fixed_size);
+ //3.8 :-(
+ //exit(0);
+
+ if (!keytab.isEmpty())
+ m->initSessionKeyTab(keytab);
+
+ if (!schema.isEmpty()) {
+ if (schema.right(7)!=".schema")
+ schema+=".schema";
+ m->setSchema(schema);
+ m->activateSession(0); // Fixes BR83162, transp. schema + notabbar
+ }
+
+ m->setColLin(c,l); // will use default height and width if called with (0,0)
+
+ m->initFullScreen();
+ m->show();
+ if (showtip)
+ m->showTipOnStart();
+ m->setAutoClose(auto_close);
+ }
+
+ int ret = a->exec();
+
+ //// Temporary code, waiting for Qt to do this properly
+
+ // Delete all toplevel widgets that have WDestructiveClose
+ QWidgetList *list = QApplication::topLevelWidgets();
+ // remove all toplevel widgets that have a parent (i.e. they
+ // got WTopLevel explicitly), they'll be deleted by the parent
+ list->first();
+ while( list->current())
+ {
+ if( list->current()->parentWidget() != NULL || !list->current()->testWFlags( Qt::WDestructiveClose ) )
+ {
+ list->remove();
+ continue;
+ }
+ list->next();
+ }
+ QWidgetListIt it(*list);
+ QWidget * w;
+ while( (w=it.current()) != 0 ) {
+ ++it;
+ delete w;
+ }
+ delete list;
+
+ delete a;
+
+ return ret;
+}
diff --git a/konsole/konsole/printsettings.cpp b/konsole/konsole/printsettings.cpp
new file mode 100644
index 000000000..22997ba28
--- /dev/null
+++ b/konsole/konsole/printsettings.cpp
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (c) 2002 Michael Goffioul <kdeprint@swing.be>
+ * (c) 2003 Waldo Bastian <bastian@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#include "printsettings.h"
+
+#include <klocale.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+
+PrintSettings::PrintSettings(QWidget *parent, const char *name)
+: KPrintDialogPage(parent, name)
+{
+ setTitle(i18n("Options"));
+
+ m_printfriendly = new QCheckBox(i18n("Printer &friendly mode (black text, no background)"), this);
+ m_printfriendly->setChecked(true);
+ m_printexact = new QCheckBox(i18n("&Pixel for pixel"), this);
+ m_printexact->setChecked(false);
+ m_printheader = new QCheckBox(i18n("Print &header"), this);
+ m_printheader->setChecked(true);
+
+ m_printheader->hide(); // Not yet implemented.
+
+ QVBoxLayout *l0 = new QVBoxLayout(this, 0, 10);
+ l0->addWidget(m_printfriendly);
+ l0->addWidget(m_printexact);
+ l0->addWidget(m_printheader);
+ l0->addStretch(1);
+}
+
+PrintSettings::~PrintSettings()
+{
+}
+
+void PrintSettings::getOptions(QMap<QString,QString>& opts, bool /*incldef*/)
+{
+ opts["app-konsole-printfriendly"] = (m_printfriendly->isChecked() ? "true" : "false");
+ opts["app-konsole-printexact"] = (m_printexact->isChecked() ? "true" : "false");
+ opts["app-konsole-printheader"] = (m_printheader->isChecked() ? "true" : "false");
+}
+
+void PrintSettings::setOptions(const QMap<QString,QString>& opts)
+{
+ m_printfriendly->setChecked(opts["app-konsole-printfriendly"] != "false");
+ m_printexact->setChecked(opts["app-konsole-printexact"] == "true");
+ m_printheader->setChecked(opts["app-konsole-printheader"] != "false");
+}
+
+#include "printsettings.moc"
diff --git a/konsole/konsole/printsettings.h b/konsole/konsole/printsettings.h
new file mode 100644
index 000000000..5d2f4389e
--- /dev/null
+++ b/konsole/konsole/printsettings.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (c) 2002 Michael Goffioul <kdeprint@swing.be>
+ * Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#ifndef PRINTSETTINGS_H
+#define PRINTSETTINGS_H
+
+#include <kdeprint/kprintdialogpage.h>
+
+class QCheckBox;
+
+class PrintSettings : public KPrintDialogPage
+{
+ Q_OBJECT
+public:
+ PrintSettings(QWidget *parent = 0, const char *name = 0);
+ ~PrintSettings();
+
+ void getOptions(QMap<QString,QString>& opts, bool incldef = false);
+ void setOptions(const QMap<QString,QString>& opts);
+
+private:
+ QCheckBox *m_printfriendly;
+ QCheckBox *m_printexact;
+ QCheckBox *m_printheader;
+};
+
+#endif
diff --git a/konsole/konsole/schema.cpp b/konsole/konsole/schema.cpp
new file mode 100644
index 000000000..0002e198b
--- /dev/null
+++ b/konsole/konsole/schema.cpp
@@ -0,0 +1,634 @@
+/* schema.C
+**
+** Copyright (C) 1998-1999 by Lars Doelle <lars.doelle@on-line.de>
+** Copyright (C) 2000 by Adriaan de Groot <groot@kde.org>
+**
+** A file that defines the objects for storing color schema's
+** in konsole. This file is part of the KDE project, see
+** http://www.kde.org/
+** for more information.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+
+/* Lars' comments were the following. They are not true anymore: */
+
+/*
+** This is new stuff, so no docs yet.
+**
+** The identifier is the path. `m_numb' is guarantied to range from 0 to
+** count-1. Note when reloading the path can be assumed to still identify
+** a know schema, while the `m_numb' may vary.
+*/
+
+
+/*
+** NUMB IS NOT GUARANTEED ANYMORE. Since schema's may be created and
+** destroyed as the list is checked, there may be gaps in the serial
+** m_numbers and m_numb may be .. whatever. The default schema always has
+** m_number 0, the rest may vary. Use find(int) to find a schema with
+** a particular m_number, but remember that find may return NULL.
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "schema.h"
+#include "kapplication.h"
+
+#include <qdir.h>
+#include <qdatetime.h>
+#include <kstandarddirs.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+
+typedef QPtrListIterator<ColorSchema> ColorSchemaListIterator;
+
+
+// Number all the new color schema's (non-default) from 1.
+//
+//
+int ColorSchema::serial = 1;
+
+// Names of all the colors, to be used as group names
+// in the config files. These do not have to be i18n'ed.
+//
+//
+static const char *colornames[TABLE_COLORS] =
+{
+ "fgnormal",
+ "bgnormal",
+ "bg0",
+ "bg1",
+ "bg2",
+ "bg3",
+ "bg4",
+ "bg5",
+ "bg6",
+ "bg7",
+ "fgintense",
+ "bgintense",
+ "bg0i",
+ "bg1i",
+ "bg2i",
+ "bg3i",
+ "bg4i",
+ "bg5i",
+ "bg6i",
+ "bg7i"
+} ;
+
+
+static const ColorEntry default_table[TABLE_COLORS] =
+ // The following are almost IBM standard color codes, with some slight
+ // gamma correction for the dim colors to compensate for bright X screens.
+ // It contains the 8 ansiterm/xterm colors in 2 intensities.
+{
+ ColorEntry( QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry(
+QColor(0xFF,0xFF,0xFF), 1, 0 ), // Dfore, Dback
+ ColorEntry( QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry(
+QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red
+ ColorEntry( QColor(0x18,0xB2,0x18), 0, 0 ), ColorEntry(
+QColor(0xB2,0x68,0x18), 0, 0 ), // Green, Yellow
+ ColorEntry( QColor(0x18,0x18,0xB2), 0, 0 ), ColorEntry(
+QColor(0xB2,0x18,0xB2), 0, 0 ), // Blue, Magenta
+ ColorEntry( QColor(0x18,0xB2,0xB2), 0, 0 ), ColorEntry(
+QColor(0xB2,0xB2,0xB2), 0, 0 ), // Cyan, White
+ // intensive
+ ColorEntry( QColor(0x00,0x00,0x00), 0, 1 ), ColorEntry(
+QColor(0xFF,0xFF,0xFF), 1, 0 ),
+ ColorEntry( QColor(0x68,0x68,0x68), 0, 0 ), ColorEntry(
+QColor(0xFF,0x54,0x54), 0, 0 ),
+ ColorEntry( QColor(0x54,0xFF,0x54), 0, 0 ), ColorEntry(
+QColor(0xFF,0xFF,0x54), 0, 0 ),
+ ColorEntry( QColor(0x54,0x54,0xFF), 0, 0 ), ColorEntry(
+QColor(0xFF,0x54,0xFF), 0, 0 ),
+ ColorEntry( QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry(
+QColor(0xFF,0xFF,0xFF), 0, 0 )
+};
+
+ColorSchema::ColorSchema(const QString& pathname)
+:m_fileRead(false)
+,lastRead(new QDateTime())
+{
+ //start with a valid time, aleXXX
+ *lastRead = QDateTime::currentDateTime();
+ QString fPath = pathname.startsWith("/") ? pathname : locate("data", "konsole/"+pathname);
+ if (fPath.isEmpty() || !QFile::exists(fPath))
+ {
+ fRelPath = QString::null;
+ setDefaultSchema();
+ }
+ else
+ {
+ fRelPath = pathname;
+ clearSchema();
+/* this is done on demand, see the headers, aleXXX
+ (void) rereadSchemaFile(); */
+ }
+
+ m_numb = serial++;
+}
+
+ColorSchema::ColorSchema()
+:m_fileRead(false)
+,fRelPath(QString::null)
+,lastRead(0L)
+{
+ setDefaultSchema();
+ m_numb = 0;
+}
+
+ColorSchema::ColorSchema(KConfig& c)
+:m_fileRead(false)
+,fRelPath(QString::null)
+,lastRead(0L)
+{
+ clearSchema();
+
+ c.setGroup("SchemaGeneral");
+
+ m_title = c.readEntry("Title",i18n("[no title]"));
+ m_imagePath = c.readEntry("ImagePath");
+ m_alignment = c.readNumEntry("ImageAlignment",1);
+ m_useTransparency = c.readBoolEntry("UseTransparency",false);
+
+ m_tr_r = c.readNumEntry("TransparentR",0);
+ m_tr_g = c.readNumEntry("TransparentG",0);
+ m_tr_b = c.readNumEntry("TransparentB",0);
+ m_tr_x = c.readDoubleNumEntry("TransparentX",0.0);
+
+ for (int i=0; i < TABLE_COLORS; i++)
+ {
+ readConfigColor(c,colorName(i),m_table[i]);
+ }
+
+ m_numb = serial++;
+}
+
+
+ColorSchema::~ColorSchema()
+{
+ delete lastRead;
+}
+
+void ColorSchema::clearSchema()
+{
+ int i;
+
+ for (i = 0; i < TABLE_COLORS; i++)
+ {
+ m_table[i].color = QColor(0,0,0);
+ m_table[i].transparent = 0;
+ m_table[i].bold = 0;
+ }
+ m_title = i18n("[no title]");
+ m_imagePath = "";
+ m_alignment = 1;
+ m_useTransparency = false;
+ m_tr_x = 0.0;
+ m_tr_r = 0;
+ m_tr_g = 0;
+ m_tr_b = 0;
+}
+
+void ColorSchema::setDefaultSchema()
+{
+ m_numb = 0;
+ m_title = i18n("Konsole Default");
+ m_imagePath = ""; // background pixmap
+ m_alignment = 1; // none
+ m_useTransparency = false; // not use pseudo-transparency by default
+ m_tr_r = m_tr_g = m_tr_b = 0; // just to be on the safe side
+ m_tr_x = 0.0;
+ for (int i = 0; i < TABLE_COLORS; i++)
+ {
+ m_table[i] = default_table[i];
+ }
+}
+
+/* static */ QString ColorSchema::colorName(int i)
+{
+ if ((i<0) || (i>=TABLE_COLORS))
+ {
+ kdWarning() << "Request for color name "
+ << i
+ << " out of range."
+ << endl;
+ return QString::null;
+ }
+
+ return QString(colornames[i]);
+}
+
+void ColorSchema::writeConfigColor(KConfig& c,
+ const QString& name,
+ const ColorEntry& e) const
+{
+ KConfigGroupSaver(&c,name);
+ c.setGroup(name);
+ c.writeEntry("Color",e.color);
+ c.writeEntry("Transparency",(bool) e.transparent);
+ c.writeEntry("Bold",(bool) e.bold);
+}
+
+void ColorSchema::readConfigColor(KConfig& c,
+ const QString& name,
+ ColorEntry& e)
+{
+ KConfigGroupSaver(&c,name);
+ c.setGroup(name);
+
+ e.color = c.readColorEntry("Color");
+ e.transparent = c.readBoolEntry("Transparent",false);
+ e.bold = c.readBoolEntry("Bold",false);
+}
+
+
+void ColorSchema::writeConfig(const QString& path) const
+{
+// KONSOLEDEBUG << "Writing schema " << relPath << " to file " << path << endl;
+
+ KConfig c(path,false,false);
+
+ c.setGroup("SchemaGeneral");
+ c.writeEntry("Title",m_title);
+ c.writeEntry("ImagePath",m_imagePath);
+ c.writeEntry("ImageAlignment",m_alignment);
+ c.writeEntry("UseTransparency",m_useTransparency);
+
+ c.writeEntry("TransparentR",m_tr_r);
+ c.writeEntry("TransparentG",m_tr_g);
+ c.writeEntry("TransparentB",m_tr_b);
+ c.writeEntry("TransparentX",m_tr_x);
+
+ for (int i=0; i < TABLE_COLORS; i++)
+ {
+ writeConfigColor(c,colorName(i),m_table[i]);
+ }
+}
+
+static int random_hue = -1;
+
+bool ColorSchema::rereadSchemaFile()
+{
+ QString fPath = fRelPath.isEmpty() ? "" : (fRelPath.startsWith("/") ? fRelPath : locate("data", "konsole/"+fRelPath));
+ if (fPath.isEmpty() || !QFile::exists(fPath))
+ return false;
+
+ //KONSOLEDEBUG << "Rereading schema file " << fPath << endl;
+
+ FILE *sysin = fopen(QFile::encodeName(fPath),"r");
+ if (!sysin)
+ {
+ int e = errno;
+
+ kdWarning() << "Schema file "
+ << fPath
+ << " could not be opened ("
+ << strerror(e)
+ << ")"
+ << endl;
+ return false;
+ }
+
+ char line[100];
+
+ *lastRead = QDateTime::currentDateTime();
+
+ while (fscanf(sysin,"%80[^\n]\n",line) > 0)
+ {
+ if (strlen(line) > 5)
+ {
+ if (!strncmp(line,"title",5))
+ {
+ m_title = i18n(line+6);
+ }
+ if (!strncmp(line,"image",5))
+ { char rend[100], path[100]; int attr = 1;
+ if (sscanf(line,"image %s %s",rend,path) != 2)
+ continue;
+ if (!strcmp(rend,"tile" )) attr = 2; else
+ if (!strcmp(rend,"center")) attr = 3; else
+ if (!strcmp(rend,"full" )) attr = 4; else
+ continue;
+
+ QString qline(line);
+ m_imagePath = locate("wallpaper", qline.mid( qline.find(" ",7)+1 ) );
+ m_alignment = attr;
+ }
+ if (!strncmp(line,"transparency",12))
+ { float rx;
+ int rr, rg, rb;
+
+ // Transparency needs 4 parameters: fade strength and the 3
+ // components of the fade color.
+ if (sscanf(line,"transparency %g %d %d %d",&rx,&rr,&rg,&rb) != 4)
+ continue;
+ m_useTransparency=true;
+ m_tr_x=rx;
+ m_tr_r=rr;
+ m_tr_g=rg;
+ m_tr_b=rb;
+ }
+ if (!strncmp(line,"rcolor",6))
+ { int fi,ch,cs,cv,tr,bo;
+ if(sscanf(line,"rcolor %d %d %d %d %d",&fi,&cs,&cv,&tr,&bo) != 5)
+ continue;
+ if (!(0 <= fi && fi <= TABLE_COLORS)) continue;
+ if (random_hue == -1)
+ random_hue = (KApplication::random()%32) * 11;
+ ch = random_hue;
+ if (!(0 <= cs && cs <= 255 )) continue;
+ if (!(0 <= cv && cv <= 255 )) continue;
+ if (!(0 <= tr && tr <= 1 )) continue;
+ if (!(0 <= bo && bo <= 1 )) continue;
+ m_table[fi].color = QColor();
+ m_table[fi].color.setHsv(ch,cs,cv);
+ m_table[fi].transparent = tr;
+ m_table[fi].bold = bo;
+ }
+ if (!strncmp(line,"color",5))
+ { int fi,cr,cg,cb,tr,bo;
+ if(sscanf(line,"color %d %d %d %d %d %d",&fi,&cr,&cg,&cb,&tr,&bo) != 6)
+ continue;
+ if (!(0 <= fi && fi <= TABLE_COLORS)) continue;
+ if (!(0 <= cr && cr <= 255 )) continue;
+ if (!(0 <= cg && cg <= 255 )) continue;
+ if (!(0 <= cb && cb <= 255 )) continue;
+ if (!(0 <= tr && tr <= 1 )) continue;
+ if (!(0 <= bo && bo <= 1 )) continue;
+ m_table[fi].color = QColor(cr,cg,cb);
+ m_table[fi].transparent = tr;
+ m_table[fi].bold = bo;
+ }
+ if (!strncmp(line,"sysfg",5))
+ { int fi,tr,bo;
+ if(sscanf(line,"sysfg %d %d %d",&fi,&tr,&bo) != 3)
+ continue;
+ if (!(0 <= fi && fi <= TABLE_COLORS)) continue;
+ if (!(0 <= tr && tr <= 1 )) continue;
+ if (!(0 <= bo && bo <= 1 )) continue;
+ m_table[fi].color = kapp->palette().active().text();
+ m_table[fi].transparent = tr;
+ m_table[fi].bold = bo;
+ }
+ if (!strncmp(line,"sysbg",5))
+ { int fi,tr,bo;
+ if(sscanf(line,"sysbg %d %d %d",&fi,&tr,&bo) != 3)
+ continue;
+ if (!(0 <= fi && fi <= TABLE_COLORS)) continue;
+ if (!(0 <= tr && tr <= 1 )) continue;
+ if (!(0 <= bo && bo <= 1 )) continue;
+ m_table[fi].color = kapp->palette().active().base();
+ m_table[fi].transparent = tr;
+ m_table[fi].bold = bo;
+ }
+ }
+ }
+ fclose(sysin);
+ m_fileRead=true;
+ return true;
+}
+
+bool ColorSchema::hasSchemaFileChanged() const
+{
+ QString fPath = fRelPath.isEmpty() ? "" : locate("data", "konsole/"+fRelPath);
+
+ //KONSOLEDEBUG << "Checking schema file " << fPath << endl;
+
+ // The default color schema never changes.
+ //
+ //
+ if (fPath.isEmpty()) return false;
+
+ QFileInfo i(fPath);
+
+ if (i.exists())
+ {
+ QDateTime written = i.lastModified();
+
+ if (written != (*lastRead))
+ {
+// KONSOLEDEBUG << "Schema file was modified " << written.toString() << endl;
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ kdWarning() << "Schema file no longer exists."
+ << endl;
+ return false;
+ }
+}
+
+void ColorSchema::updateLastRead(const QDateTime& dt)
+{
+ if (lastRead)
+ {
+ *lastRead=dt;
+ }
+}
+
+
+ColorSchemaList::ColorSchemaList() :
+ QPtrList<ColorSchema> ()
+{
+// KONSOLEDEBUG << "Got new color list" << endl;
+
+ defaultSchema = new ColorSchema();
+ append(defaultSchema);
+ setAutoDelete(true);
+
+ ColorSchema::serial=1; // Needed for detached sessions
+}
+
+ColorSchemaList::~ColorSchemaList()
+{
+ ColorSchema::serial=1;
+}
+
+
+ColorSchema *ColorSchemaList::find(const QString& path)
+{
+ if (path.isEmpty())
+ return find(0);
+ //KONSOLEDEBUG << "Looking for schema " << path << endl;
+ //kdDebug(1211)<<"ColorSchema::find() count()=="<<count()<<endl;
+ ColorSchemaListIterator it(*this);
+ ColorSchema *c;
+
+ if (path.startsWith("/")) {
+ //KONSOLEDEBUG << " schema given as a full path... " << path << endl;
+ ColorSchema *newSchema = new ColorSchema(path);
+ if (newSchema)
+ append(newSchema);
+ return newSchema;
+ }
+
+ while ((c=it.current()))
+ {
+ if ((*it)->relPath() == path)
+ return *it;
+ ++it;
+ }
+
+ //list is empty except the default schema
+ if (count()==1)
+ {
+ //kdDebug(1211)<<"ColorSchema::find() empty"<<endl;
+ ColorSchema *newSchema = new ColorSchema(path);
+ if (newSchema)
+ append(newSchema);
+ return newSchema;
+ };
+ return 0;
+}
+
+ColorSchema *ColorSchemaList::find(int i)
+{
+ //KONSOLEDEBUG << "Looking for schema m_number " << i << endl;
+
+ ColorSchemaListIterator it(*this);
+ ColorSchema *c;
+
+ while ((c=it.current()))
+ {
+ if ((*it)->numb() == i) return *it;
+ ++it;
+ }
+
+ return 0;
+}
+
+bool ColorSchemaList::updateAllSchemaTimes(const QDateTime& now)
+{
+// KONSOLEDEBUG << "Updating time stamps" << endl;
+
+ QStringList list;
+ KGlobal::dirs()->findAllResources("data", "konsole/*.schema", false, true, list);
+ QStringList::ConstIterator it;
+ bool r = false;
+
+ for (it=list.begin(); it!=list.end(); ++it)
+ {
+ QString filename=*it;
+ int j=filename.findRev('/');
+ if (j>-1)
+ filename = filename.mid(8);
+
+ ColorSchema *sc = find(filename);
+
+ if (!sc)
+ {
+// KONSOLEDEBUG << "Found new schema " << filename << endl;
+
+ ColorSchema *newSchema = new ColorSchema(filename);
+ if (newSchema)
+ {
+ append(newSchema);
+ r=true;
+ }
+ }
+ else
+ {
+ if (sc->hasSchemaFileChanged())
+ {
+ sc->rereadSchemaFile();
+ }
+ else
+ {
+ sc->updateLastRead(now);
+ }
+ }
+ }
+ //this has to be done explicitly now, to avoid reading all schema files on startup, aleXXX
+// sort();
+ return r;
+}
+
+bool ColorSchemaList::deleteOldSchemas(const QDateTime& now)
+{
+// KONSOLEDEBUG << "Checking for vanished schemas" << endl;
+
+ ColorSchemaListIterator it(*this);
+ ColorSchema *p ;
+ bool r = false;
+
+ while ((p=it.current()))
+ {
+ if ((p->getLastRead()) && (*(p->getLastRead())) < now)
+ {
+ KONSOLEDEBUG << "Found deleted schema "
+ << p->relPath()
+ << endl;
+ ++it;
+ remove(p);
+ r=true;
+ if (!it.current())
+ {
+ break;
+ }
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ return r;
+}
+
+
+bool ColorSchemaList::checkSchemas()
+{
+// KONSOLEDEBUG << "Checking for new schemas" << endl;
+
+ bool r = false; // Any new schema's found?
+
+ // All schemas whose schema files can still be found
+ // will have their lastRead timestamps updated to
+ // now.
+ //
+ //
+ QDateTime now = QDateTime::currentDateTime();
+
+
+ r = updateAllSchemaTimes(now);
+ r = r || deleteOldSchemas(now);
+
+ return r;
+}
+
+int ColorSchemaList::compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2)
+{
+ ColorSchema* schema1=(ColorSchema*)item1;
+ ColorSchema* schema2=(ColorSchema*)item2;
+ return -1*QString::compare(schema1->title(),schema2->title());
+}
+
+
diff --git a/konsole/konsole/schema.h b/konsole/konsole/schema.h
new file mode 100644
index 000000000..3ba718350
--- /dev/null
+++ b/konsole/konsole/schema.h
@@ -0,0 +1,243 @@
+/* schema.h
+**
+** Copyright (C) 1998-1999 by Lars Doelle <lars.doelle@on-line.de>
+** Copyright (C) 2000 by Adriaan de Groot <groot@kde.org>
+**
+** A file that defines the objects for storing color schema's
+** in konsole. This file is part of the KDE project, see
+** http://www.kde.org/
+** for more information.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Lars' code has almost completely disappeared from this file.
+** The new setup is more object-oriented and disposes of some
+** nasty static deleters.
+**
+** Basically you want to create a ColorSchemaList and then call
+** checkSchema's to get all the schema's available. Iterate through
+** the items in the list (with a constiterator) and so whatever.
+** The ColorSchemaList inherits protected from QList to prevent you
+** from doing silly things to the elements of the list.
+*/
+
+#ifndef SCHEMA_include
+#define SCHEMA_include
+
+#include <qstring.h>
+#include <qptrlist.h>
+
+#include "TECommon.h"
+
+#ifndef KONSOLEDEBUG
+/*
+** konsole has claimed debug area 1211. This isn't really the right place
+** to define KONSOLEDEBUG but there is no "global.h" or central "konsole.h"
+** file included by all parts of konsole, so this will have to do.
+*/
+#define KONSOLEDEBUG kdDebug(1211)
+#endif
+
+class QDateTime;
+class KConfig;
+
+class ColorSchema
+{
+friend class ColorSchemaList; //only for resetting serial to one when deleting the list
+
+public:
+ /**
+ * Create ColorSchema from the given pathname.
+ * If the given pathname does not exist, a ColorSchema
+ * with the same settings as the default schema is returned.
+ */
+ ColorSchema(const QString& pathname);
+ ~ColorSchema();
+ /**
+ * Construct a color schema from the given config file.
+ * (This is different from the constructor with a pathname
+ * because that reads the hackneyed schema file syntax and
+ * this is a KDE config file)
+ */
+ ColorSchema(KConfig&);
+
+ /**
+ * Constructor for the default schema (with no path).
+ */
+ ColorSchema();
+
+ QString relPath() const { return fRelPath; } ;
+
+ /**
+ * Check if the schema file whose pathname was given
+ * to the constructor has changed since it was last read.
+ */
+ bool hasSchemaFileChanged() const;
+
+ /**
+ * Actually read a schema file (using the path given
+ * to the constructor of the ColorSchema).
+ */
+ bool rereadSchemaFile();
+
+ /**
+ * Writes a ColorSchema to a config file with the
+ * given name.
+ */
+ void writeConfig(const QString& filename) const;
+
+ /**
+ * Returns the (non-i18n) name of the i'th color,
+ * or QString::null if i is not a color name. This
+ * should be used as a group name to store the
+ * information about the i'th color.
+ */
+ static QString colorName(int i);
+
+ /**
+ * Update the timestamp in the color schema indicating
+ * when the schema's file whas last checked and read.
+ */
+ void updateLastRead(const QDateTime& dt);
+
+
+protected:
+ /**
+ * Clear a schema. Used by constructors to clean up the
+ * data members before filling them.
+ */
+ void clearSchema();
+
+ /**
+ * Set the data members' values to those of the
+ * default schema.
+ */
+ void setDefaultSchema();
+
+
+ /**
+ * Write a single ColorEntry to the config file
+ * under the given name (ie. in the group name).
+ */
+ void writeConfigColor(KConfig& c,
+ const QString& name,
+ const ColorEntry& e) const;
+ /**
+ * Read a single ColorEntry from the config file.
+ */
+ void readConfigColor(KConfig& c,
+ const QString& name,
+ ColorEntry& e) ;
+
+ public:
+ int numb() {if (!m_fileRead) rereadSchemaFile();return m_numb;};
+ const QString& title() {if (!m_fileRead) rereadSchemaFile();return m_title;};
+ const QString& imagePath() {if (!m_fileRead) rereadSchemaFile();return m_imagePath;};
+ int alignment() {if (!m_fileRead) rereadSchemaFile();return m_alignment;};
+ const ColorEntry* table() {if (!m_fileRead) rereadSchemaFile();return m_table;};
+ bool useTransparency() {if (!m_fileRead) rereadSchemaFile();return m_useTransparency;};
+ double tr_x() {if (!m_fileRead) rereadSchemaFile();return m_tr_x;};
+ int tr_r() {if (!m_fileRead) rereadSchemaFile();return m_tr_r;};
+ int tr_g() {if (!m_fileRead) rereadSchemaFile();return m_tr_g;};
+ int tr_b() {if (!m_fileRead) rereadSchemaFile();return m_tr_b;};
+ QDateTime* getLastRead() {return lastRead;}; // Time last checked for updates
+
+ private:
+ int m_numb;
+ int m_tr_r, m_tr_g, m_tr_b;
+ int m_alignment;
+ QString m_title;
+ QString m_imagePath;
+ ColorEntry m_table[TABLE_COLORS];
+ bool m_useTransparency:1;
+ bool m_fileRead:1;
+ double m_tr_x;
+ QString fRelPath; // File name of schema file
+ QDateTime *lastRead; // Time last checked for updates
+ static int serial; // Serial number so that every
+ // ColorSchema has a unique number.
+};
+
+class ColorSchemaList : protected QPtrList<ColorSchema>
+{
+public:
+ /**
+ * The following functions are redeclared public since
+ * they're needed, but we still want to inherit protected
+ * from QPtrList to prevent unsightly -- and perhaps dangerous --
+ * tampering with the ColorSchemaList.
+ */
+ uint count() const { return QPtrList<ColorSchema>::count(); } ;
+ const ColorSchema *at(unsigned int i)
+ { return QPtrList<ColorSchema>::at(i); } ;
+
+ void sort() {QPtrList<ColorSchema>::sort();};
+
+ ColorSchemaList();
+ virtual ~ColorSchemaList();
+ /**
+ * Check if any new color schema files have been added since
+ * the last time checkSchemas() was called. Any new files
+ * are added to the list of schemas automatically.
+ *
+ * @return true if there were any changes to the list of schemas
+ * @return false otherwise
+ */
+ bool checkSchemas();
+
+ /**
+ * Returns the color schema read from the given path,
+ * or NULL if no color schema with the given path is found.
+ */
+ ColorSchema *find(const QString & path);
+ /**
+ * Returns the serial number of the color schema
+ * with the given serial number, or NULL if there is none.
+ */
+ ColorSchema *find(int);
+ ColorSchema *findAny(const QString& path)
+ {
+ ColorSchema *p = find(path);
+ if (p) return p;
+ return defaultSchema;
+ } ;
+protected:
+ virtual int compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2);
+
+private:
+ /**
+ * These next two functions are used internally by
+ * checkSchemas. updateAllSchemaTimes sets the timestamp
+ * on all the ColorSchema's whose config / schema file
+ * can still be found, and deleteOldSchema's does the
+ * actual removal of schema's without a config file.
+ */
+ bool updateAllSchemaTimes(const QDateTime&);
+ bool deleteOldSchemas(const QDateTime&);
+
+ /**
+ * This isn't really used, but it could be. A newly
+ * constructed ColorSchemaList contains one element:
+ * the defaultSchema, with serial number 0.
+ */
+ ColorSchema *defaultSchema;
+} ;
+
+#endif
diff --git a/konsole/konsole/session.cpp b/konsole/konsole/session.cpp
new file mode 100644
index 000000000..2310255a8
--- /dev/null
+++ b/konsole/konsole/session.cpp
@@ -0,0 +1,838 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#include "session.h"
+#include "zmodem_dialog.h"
+
+#include <kdebug.h>
+#include <dcopclient.h>
+#include <kmessagebox.h>
+#include <knotifyclient.h>
+#include <klocale.h>
+#include <kprocio.h>
+#include <krun.h>
+#include <kshell.h>
+#include <kstandarddirs.h>
+
+#include <stdlib.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qregexp.h>
+#include <qtextedit.h>
+
+/*! \class TESession
+
+ Sessions are combinations of TEPTy and Emulations.
+
+ The stuff in here does not belong to the terminal emulation framework,
+ but to main.cpp. It serves it's duty by providing a single reference
+ to TEPTy/Emulation pairs. In fact, it is only there to demonstrate one
+ of the abilities of the framework - multible sessions.
+*/
+
+TESession::TESession(TEWidget* _te, const QString &_term, ulong _winId, const QString &_sessionId, const QString &_initial_cwd)
+ : DCOPObject( _sessionId.latin1() )
+ , sh(0)
+ , connected(true)
+ , monitorActivity(false)
+ , monitorSilence(false)
+ , notifiedActivity(false)
+ , masterMode(false)
+ , autoClose(true)
+ , wantedClose(false)
+ , schema_no(0)
+ , font_no(3)
+ , silence_seconds(10)
+ , add_to_utmp(true)
+ , xon_xoff(false)
+ , pgm(QString())
+ , args(QStrList())
+ , sessionId(_sessionId)
+ , cwd("")
+ , initial_cwd(_initial_cwd)
+ , zmodemBusy(false)
+ , zmodemProc(0)
+ , zmodemProgress(0)
+ , encoding_no(0)
+{
+ //kdDebug(1211)<<"TESession ctor() new TEPty"<<endl;
+ te = _te;
+ //kdDebug(1211)<<"TESession ctor() new TEmuVt102"<<endl;
+ em = new TEmuVt102(te);
+ font_h = te-> fontHeight();
+ font_w = te-> fontWidth();
+ QObject::connect(te,SIGNAL(changedContentSizeSignal(int,int)),
+ this,SLOT(onContentSizeChange(int,int)));
+ QObject::connect(te,SIGNAL(changedFontMetricSignal(int,int)),
+ this,SLOT(onFontMetricChange(int,int)));
+
+ term = _term;
+ winId = _winId;
+ iconName = "konsole";
+
+ setPty( new TEPty() );
+
+ connect( em, SIGNAL( changeTitle( int, const QString & ) ),
+ this, SLOT( setUserTitle( int, const QString & ) ) );
+ connect( em, SIGNAL( notifySessionState(int) ),
+ this, SLOT( notifySessionState(int) ) );
+ monitorTimer = new QTimer(this);
+ connect(monitorTimer, SIGNAL(timeout()), this, SLOT(monitorTimerDone()));
+
+ connect( em, SIGNAL( zmodemDetected() ), this, SLOT(slotZModemDetected()));
+
+ connect( em, SIGNAL( changeTabTextColor( int ) ),
+ this, SLOT( changeTabTextColor( int ) ) );
+
+ //kdDebug(1211)<<"TESession ctor() done"<<endl;
+}
+
+void TESession::setPty(TEPty *_sh)
+{
+ if ( sh ) {
+ delete sh;
+ }
+ sh = _sh;
+ connect( sh, SIGNAL( forkedChild() ),
+ this, SIGNAL( forkedChild() ));
+
+ //kdDebug(1211)<<"TESession ctor() sh->setSize()"<<endl;
+ sh->setSize(te->Lines(),te->Columns()); // not absolutely nessesary
+ sh->useUtf8(em->utf8());
+ //kdDebug(1211)<<"TESession ctor() connecting"<<endl;
+ connect( sh,SIGNAL(block_in(const char*,int)),this,SLOT(onRcvBlock(const char*,int)) );
+
+ connect( em,SIGNAL(sndBlock(const char*,int)),sh,SLOT(send_bytes(const char*,int)) );
+ connect( em,SIGNAL(lockPty(bool)),sh,SLOT(lockPty(bool)) );
+ connect( em,SIGNAL(useUtf8(bool)),sh,SLOT(useUtf8(bool)) );
+
+ connect( sh,SIGNAL(done(int)), this,SLOT(done(int)) );
+
+ if (!sh->error().isEmpty())
+ QTimer::singleShot(0, this, SLOT(ptyError()));
+}
+
+void TESession::ptyError()
+{
+ // FIXME: sh->error() is always empty
+ if ( sh->error().isEmpty() )
+ KMessageBox::error( te->topLevelWidget(),
+ i18n("Konsole is unable to open a PTY (pseudo teletype). It is likely that this is due to an incorrect configuration of the PTY devices. Konsole needs to have read/write access to the PTY devices."),
+ i18n("A Fatal Error Has Occurred") );
+ else
+ KMessageBox::error(te->topLevelWidget(), sh->error());
+ emit done(this);
+}
+
+void TESession::changeWidget(TEWidget* w)
+{
+ QObject::disconnect(te,SIGNAL(changedContentSizeSignal(int,int)),
+ this,SLOT(onContentSizeChange(int,int)));
+ QObject::disconnect(te,SIGNAL(changedFontMetricSignal(int,int)),
+ this,SLOT(onFontMetricChange(int,int)));
+ te=w;
+ em->changeGUI(w);
+ font_h = te->fontHeight();
+ font_w = te->fontWidth();
+ sh->setSize(te->Lines(),te->Columns()); // not absolutely nessesary
+
+ te->setDefaultBackColor(modifiedBackground);
+
+ QObject::connect(te,SIGNAL(changedContentSizeSignal(int,int)),
+ this,SLOT(onContentSizeChange(int,int)));
+ QObject::connect(te,SIGNAL(changedFontMetricSignal(int,int)),
+ this,SLOT(onFontMetricChange(int,int)));
+}
+
+void TESession::setProgram( const QString &_pgm, const QStrList &_args )
+{
+ pgm = _pgm;
+ args = _args;
+}
+
+void TESession::run()
+{
+ // Upon a KPty error, there is no description on what that error was...
+ // Check to see if the given program is executable.
+ QString exec = QFile::encodeName(pgm);
+ exec = KRun::binaryName(exec, false);
+ exec = KShell::tildeExpand(exec);
+ QString pexec = KGlobal::dirs()->findExe(exec);
+ if ( pexec.isEmpty() ) {
+ kdError()<<"can not execute "<<exec<<endl;
+ QTimer::singleShot(1, this, SLOT(done()));
+ return;
+ }
+
+ QString appId=kapp->dcopClient()->appId();
+
+ QString cwd_save = QDir::currentDirPath();
+ if (!initial_cwd.isEmpty())
+ QDir::setCurrent(initial_cwd);
+ sh->setXonXoff(xon_xoff);
+
+ int result = sh->run(QFile::encodeName(pgm), args, term.latin1(),
+ winId, add_to_utmp,
+ ("DCOPRef("+appId+",konsole)").latin1(),
+ ("DCOPRef("+appId+","+sessionId+")").latin1());
+ if (result < 0) { // Error in opening pseudo teletype
+ kdWarning()<<"Unable to open a pseudo teletype!"<<endl;
+ QTimer::singleShot(0, this, SLOT(ptyError()));
+ }
+ sh->setErase(em->getErase());
+
+ if (!initial_cwd.isEmpty())
+ QDir::setCurrent(cwd_save);
+ else
+ initial_cwd=cwd_save;
+
+ sh->setWriteable(false); // We are reachable via kwrited.
+}
+
+void TESession::changeTabTextColor( int color )
+{
+ emit changeTabTextColor( this, color );
+}
+
+void TESession::setUserTitle( int what, const QString &caption )
+{
+ // (btw: what=0 changes title and icon, what=1 only icon, what=2 only title
+ if ((what == 0) || (what == 2))
+ userTitle = caption;
+ if ((what == 0) || (what == 1))
+ iconText = caption;
+ if (what == 11) {
+ QString colorString = caption.section(';',0,0);
+ QColor backColor = QColor(colorString);
+ if (backColor.isValid()){// change color via \033]11;Color\007
+ if (backColor != modifiedBackground) {
+ modifiedBackground = backColor;
+ te->setDefaultBackColor(backColor);
+ }
+ }
+ }
+ if (what == 30)
+ renameSession(caption);
+ if (what == 31) {
+ cwd=caption;
+ cwd=cwd.replace( QRegExp("^~"), QDir::homeDirPath() );
+ emit openURLRequest(cwd);
+ }
+ if (what == 32) { // change icon via \033]32;Icon\007
+ iconName = caption;
+ te->update();
+ }
+
+ emit updateTitle(this);
+}
+
+QString TESession::fullTitle() const
+{
+ QString res = title;
+ if ( !userTitle.isEmpty() )
+ res = userTitle + " - " + res;
+ return res;
+}
+
+void TESession::monitorTimerDone()
+{
+ if (monitorSilence) {
+ KNotifyClient::event(winId, "Silence", i18n("Silence in session '%1'").arg(title));
+ emit notifySessionState(this,NOTIFYSILENCE);
+ }
+ notifiedActivity=false;
+}
+
+void TESession::notifySessionState(int state)
+{
+ if (state==NOTIFYBELL) {
+ te->Bell(em->isConnected(),i18n("Bell in session '%1'").arg(title));
+ } else if (state==NOTIFYACTIVITY) {
+ if (monitorSilence) {
+ monitorTimer->start(silence_seconds*1000,true);
+ }
+ if (!monitorActivity)
+ return;
+ if (!notifiedActivity) {
+ KNotifyClient::event(winId, "Activity", i18n("Activity in session '%1'").arg(title));
+ notifiedActivity=true;
+ monitorTimer->start(silence_seconds*1000,true);
+ }
+ }
+
+ emit notifySessionState(this, state);
+}
+
+void TESession::onContentSizeChange(int height, int width)
+{
+ // ensure that image is at least one line high by one column wide
+ const int columns = QMAX( width/font_w , 1 );
+ const int lines = QMAX( height/font_h , 1 );
+
+ em->onImageSizeChange( lines , columns );
+ sh->setSize( lines , columns );
+}
+
+void TESession::onFontMetricChange(int height, int width)
+{
+ //kdDebug(1211)<<"TESession::onFontMetricChange " << height << " " << width << endl;
+ if (connected) {
+ font_h = height;
+ font_w = width;
+ }
+}
+
+bool TESession::sendSignal(int signal)
+{
+ return sh->kill(signal);
+}
+
+bool TESession::closeSession()
+{
+ autoClose = true;
+ wantedClose = true;
+ if (!sh->isRunning() || !sendSignal(SIGHUP))
+ {
+ // Forced close.
+ QTimer::singleShot(1, this, SLOT(done()));
+ }
+ return true;
+}
+
+void TESession::feedSession(const QString &text)
+{
+ emit disableMasterModeConnections();
+ setListenToKeyPress(true);
+ te->emitText(text);
+ setListenToKeyPress(false);
+ emit enableMasterModeConnections();
+}
+
+void TESession::sendSession(const QString &text)
+{
+ QString newtext=text;
+ newtext.append("\r");
+ feedSession(newtext);
+}
+
+void TESession::renameSession(const QString &name)
+{
+ title=name;
+ emit renameSession(this,name);
+}
+
+TESession::~TESession()
+{
+ //kdDebug(1211) << "disconnnecting..." << endl;
+ QObject::disconnect( sh, SIGNAL( done(int) ),
+ this, SLOT( done(int) ) );
+ delete em;
+ delete sh;
+
+ delete zmodemProc;
+}
+
+void TESession::setConnect(bool c)
+{
+ connected=c;
+ em->setConnect(c);
+ setListenToKeyPress(c);
+}
+
+void TESession::setListenToKeyPress(bool l)
+{
+ em->setListenToKeyPress(l);
+}
+
+void TESession::done() {
+ emit processExited(sh);
+ emit done(this);
+}
+
+void TESession::done(int exitStatus)
+{
+ if (!autoClose)
+ {
+ userTitle = i18n("<Finished>");
+ emit updateTitle(this);
+ return;
+ }
+ if (!wantedClose && (exitStatus || sh->signalled()))
+ {
+ if (sh->normalExit())
+ KNotifyClient::event(winId, "Finished", i18n("Session '%1' exited with status %2.").arg(title).arg(exitStatus));
+ else if (sh->signalled())
+ {
+ if (sh->coreDumped())
+ KNotifyClient::event(winId, "Finished", i18n("Session '%1' exited with signal %2 and dumped core.").arg(title).arg(sh->exitSignal()));
+ else
+ KNotifyClient::event(winId, "Finished", i18n("Session '%1' exited with signal %2.").arg(title).arg(sh->exitSignal()));
+ }
+ else
+ KNotifyClient::event(winId, "Finished", i18n("Session '%1' exited unexpectedly.").arg(title));
+ }
+ emit processExited(sh);
+ emit done(this);
+}
+
+void TESession::terminate()
+{
+ delete this;
+}
+
+TEmulation* TESession::getEmulation()
+{
+ return em;
+}
+
+// following interfaces might be misplaced ///
+
+int TESession::schemaNo()
+{
+ return schema_no;
+}
+
+int TESession::encodingNo()
+{
+ return encoding_no;
+}
+
+int TESession::keymapNo()
+{
+ return em->keymapNo();
+}
+
+QString TESession::keymap()
+{
+ return em->keymap();
+}
+
+int TESession::fontNo()
+{
+ return font_no;
+}
+
+const QString & TESession::Term()
+{
+ return term;
+}
+
+const QString & TESession::SessionId()
+{
+ return sessionId;
+}
+
+void TESession::setSchemaNo(int sn)
+{
+ schema_no = sn;
+}
+
+void TESession::setEncodingNo(int index)
+{
+ encoding_no = index;
+}
+
+void TESession::setKeymapNo(int kn)
+{
+ em->setKeymap(kn);
+}
+
+void TESession::setKeymap(const QString &id)
+{
+ em->setKeymap(id);
+}
+
+void TESession::setFontNo(int fn)
+{
+ font_no = fn;
+}
+
+void TESession::setTitle(const QString& _title)
+{
+ title = _title;
+ //kdDebug(1211)<<"Session setTitle " << title <<endl;
+}
+
+const QString& TESession::Title()
+{
+ return title;
+}
+
+void TESession::setIconName(const QString& _iconName)
+{
+ iconName = _iconName;
+}
+
+void TESession::setIconText(const QString& _iconText)
+{
+ iconText = _iconText;
+ //kdDebug(1211)<<"Session setIconText " << iconText <<endl;
+}
+
+const QString& TESession::IconName()
+{
+ return iconName;
+}
+
+const QString& TESession::IconText()
+{
+ return iconText;
+}
+
+bool TESession::testAndSetStateIconName (const QString& newname)
+{
+ if (newname != stateIconName)
+ {
+ stateIconName = newname;
+ return true;
+ }
+ return false;
+}
+
+void TESession::setHistory(const HistoryType &hType)
+{
+ em->setHistory(hType);
+}
+
+const HistoryType& TESession::history()
+{
+ return em->history();
+}
+
+void TESession::clearHistory()
+{
+ if (history().isOn()) {
+ int histSize = history().getSize();
+ setHistory(HistoryTypeNone());
+ if (histSize)
+ setHistory(HistoryTypeBuffer(histSize));
+ else
+ setHistory(HistoryTypeFile());
+ }
+}
+
+QStrList TESession::getArgs()
+{
+ return args;
+}
+
+QString TESession::getPgm()
+{
+ return pgm;
+}
+
+QString TESession::getCwd()
+{
+#ifdef HAVE_PROC_CWD
+ if (cwd.isEmpty()) {
+ QFileInfo Cwd(QString("/proc/%1/cwd").arg(sh->pid()));
+ if(Cwd.isSymLink())
+ return Cwd.readLink();
+ }
+#endif /* HAVE_PROC_CWD */
+ return cwd;
+}
+
+bool TESession::isMonitorActivity() { return monitorActivity; }
+bool TESession::isMonitorSilence() { return monitorSilence; }
+bool TESession::isMasterMode() { return masterMode; }
+
+void TESession::setMonitorActivity(bool _monitor)
+{
+ monitorActivity=_monitor;
+ notifiedActivity=false;
+}
+
+void TESession::setMonitorSilence(bool _monitor)
+{
+ if (monitorSilence==_monitor)
+ return;
+
+ monitorSilence=_monitor;
+ if (monitorSilence)
+ monitorTimer->start(silence_seconds*1000,true);
+ else
+ monitorTimer->stop();
+}
+
+void TESession::setMonitorSilenceSeconds(int seconds)
+{
+ silence_seconds=seconds;
+ if (monitorSilence) {
+ monitorTimer->start(silence_seconds*1000,true);
+ }
+}
+
+void TESession::setMasterMode(bool _master)
+{
+ masterMode=_master;
+}
+
+void TESession::setAddToUtmp(bool set)
+{
+ add_to_utmp = set;
+}
+
+void TESession::setXonXoff(bool set)
+{
+ xon_xoff = set;
+}
+
+void TESession::slotZModemDetected()
+{
+ if (!zmodemBusy)
+ {
+ QTimer::singleShot(10, this, SLOT(emitZModemDetected()));
+ zmodemBusy = true;
+ }
+}
+
+void TESession::emitZModemDetected()
+{
+ emit zmodemDetected(this);
+}
+
+void TESession::cancelZModem()
+{
+ sh->send_bytes("\030\030\030\030", 4); // Abort
+ zmodemBusy = false;
+}
+
+void TESession::startZModem(const QString &zmodem, const QString &dir, const QStringList &list)
+{
+ zmodemBusy = true;
+ zmodemProc = new KProcIO;
+
+ (*zmodemProc) << zmodem << "-v";
+ for(QStringList::ConstIterator it = list.begin();
+ it != list.end();
+ ++it)
+ {
+ (*zmodemProc) << (*it);
+ }
+
+ if (!dir.isEmpty())
+ zmodemProc->setWorkingDirectory(dir);
+ zmodemProc->start(KProcIO::NotifyOnExit, false);
+
+ // Override the read-processing of KProcIO
+ disconnect(zmodemProc,SIGNAL (receivedStdout (KProcess *, char *, int)), 0, 0);
+ connect(zmodemProc,SIGNAL (receivedStdout (KProcess *, char *, int)),
+ this, SLOT(zmodemSendBlock(KProcess *, char *, int)));
+ connect(zmodemProc,SIGNAL (receivedStderr (KProcess *, char *, int)),
+ this, SLOT(zmodemStatus(KProcess *, char *, int)));
+ connect(zmodemProc,SIGNAL (processExited(KProcess *)),
+ this, SLOT(zmodemDone()));
+
+ disconnect( sh,SIGNAL(block_in(const char*,int)), this, SLOT(onRcvBlock(const char*,int)) );
+ connect( sh,SIGNAL(block_in(const char*,int)), this, SLOT(zmodemRcvBlock(const char*,int)) );
+ connect( sh,SIGNAL(buffer_empty()), this, SLOT(zmodemContinue()));
+
+ zmodemProgress = new ZModemDialog(te->topLevelWidget(), false,
+ i18n("ZModem Progress"));
+
+ connect(zmodemProgress, SIGNAL(user1Clicked()),
+ this, SLOT(zmodemDone()));
+
+ zmodemProgress->show();
+}
+
+void TESession::zmodemSendBlock(KProcess *, char *data, int len)
+{
+ sh->send_bytes(data, len);
+// qWarning("<-- %d bytes", len);
+ if (sh->buffer_full())
+ {
+ zmodemProc->suspend();
+// qWarning("ZModem suspend");
+ }
+}
+
+void TESession::zmodemContinue()
+{
+ zmodemProc->resume();
+// qWarning("ZModem resume");
+}
+
+void TESession::zmodemStatus(KProcess *, char *data, int len)
+{
+ QCString msg(data, len+1);
+ while(!msg.isEmpty())
+ {
+ int i = msg.find('\015');
+ int j = msg.find('\012');
+ QCString txt;
+ if ((i != -1) && ((j == -1) || (i < j)))
+ {
+ msg = msg.mid(i+1);
+ }
+ else if (j != -1)
+ {
+ txt = msg.left(j);
+ msg = msg.mid(j+1);
+ }
+ else
+ {
+ txt = msg;
+ msg.truncate(0);
+ }
+ if (!txt.isEmpty())
+ zmodemProgress->addProgressText(QString::fromLocal8Bit(txt));
+ }
+}
+
+void TESession::zmodemRcvBlock(const char *data, int len)
+{
+ QByteArray ba;
+ ba.duplicate(data, len);
+ zmodemProc->writeStdin(ba);
+// qWarning("--> %d bytes", len);
+}
+
+void TESession::zmodemDone()
+{
+ if (zmodemProc)
+ {
+ delete zmodemProc;
+ zmodemProc = 0;
+ zmodemBusy = false;
+
+ disconnect( sh,SIGNAL(block_in(const char*,int)), this ,SLOT(zmodemRcvBlock(const char*,int)) );
+ disconnect( sh,SIGNAL(buffer_empty()), this, SLOT(zmodemContinue()));
+ connect( sh,SIGNAL(block_in(const char*,int)), this, SLOT(onRcvBlock(const char*,int)) );
+
+ sh->send_bytes("\030\030\030\030", 4); // Abort
+ sh->send_bytes("\001\013\n", 3); // Try to get prompt back
+ zmodemProgress->done();
+ }
+}
+
+
+bool TESession::processDynamic(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData)
+{
+ if (fullScripting)
+ {
+ if (fun == "feedSession(QString)")
+ {
+ QString arg0;
+ QDataStream arg( data, IO_ReadOnly );
+ arg >> arg0;
+ feedSession(arg0);
+ replyType = "void";
+ return true;
+ }
+ else if (fun == "sendSession(QString)")
+ {
+ QString arg0;
+ QDataStream arg( data, IO_ReadOnly );
+ arg >> arg0;
+ sendSession(arg0);
+ replyType = "void";
+ return true;
+ }
+ }
+ return SessionIface::processDynamic(fun, data, replyType, replyData);
+
+}
+
+QCStringList TESession::functionsDynamic()
+{
+ QCStringList funcs = SessionIface::functionsDynamic();
+ if (fullScripting)
+ {
+ funcs << "void feedSession(QString text)";
+ funcs << "void sendSession(QString text)";
+ }
+ return funcs;
+}
+
+
+void TESession::onRcvBlock( const char* buf, int len )
+{
+ em->onRcvBlock( buf, len );
+ emit receivedData( QString::fromLatin1( buf, len ) );
+}
+
+void TESession::print( QPainter &paint, bool friendly, bool exact )
+{
+ te->print(paint, friendly, exact);
+}
+
+QString TESession::schema()
+{
+ QString currentSchema;
+ emit getSessionSchema(this, currentSchema);
+ return currentSchema;
+}
+
+void TESession::setSchema(const QString &schema)
+{
+ emit setSessionSchema(this, schema);
+}
+
+QString TESession::font()
+{
+ return te->getVTFont().toString();
+}
+
+void TESession::setFont(const QString &font)
+{
+ QFont tmp;
+ if (tmp.fromString(font))
+ te->setVTFont(tmp);
+ else
+ kdWarning()<<"unknown font: "<<font<<endl;
+}
+
+QString TESession::encoding()
+{
+ return em->codec()->name();
+}
+
+void TESession::setEncoding(const QString &encoding)
+{
+ emit setSessionEncoding(this, encoding);
+}
+
+QString TESession::keytab()
+{
+ return keymap();
+}
+
+void TESession::setKeytab(const QString &keytab)
+{
+ setKeymap(keytab);
+ emit updateSessionConfig(this);
+}
+
+QSize TESession::size()
+{
+ return em->imageSize();
+}
+
+void TESession::setSize(QSize size)
+{
+ if ((size.width() <= 1) || (size.height() <= 1))
+ return;
+
+ emit resizeSession(this, size);
+}
+
+#include "session.moc"
diff --git a/konsole/konsole/session.h b/konsole/konsole/session.h
new file mode 100644
index 000000000..90352cb5e
--- /dev/null
+++ b/konsole/konsole/session.h
@@ -0,0 +1,232 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef SESSION_H
+#define SESSION_H
+
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <qstrlist.h>
+
+#include "TEPty.h"
+#include "TEWidget.h"
+#include "TEmuVt102.h"
+
+#include "sessioniface.h"
+
+class KProcIO;
+class KProcess;
+class ZModemDialog;
+
+class TESession : public QObject, virtual public SessionIface
+{ Q_OBJECT
+
+public:
+
+ TESession(TEWidget* w,
+ const QString &term, ulong winId, const QString &sessionId="session-1",
+ const QString &initial_cwd = QString::null);
+ void changeWidget(TEWidget* w);
+ void setPty( TEPty *_sh );
+ TEWidget* widget() { return te; }
+ ~TESession();
+
+ void setConnect(bool r); // calls setListenToKeyPress(r)
+ void setListenToKeyPress(bool l);
+ TEmulation* getEmulation(); // to control emulation
+ bool isSecure();
+ bool isMonitorActivity();
+ bool isMonitorSilence();
+ bool isMasterMode();
+ int schemaNo();
+ int encodingNo();
+ int fontNo();
+ const QString& Term();
+ const QString& SessionId();
+ const QString& Title();
+ const QString& IconName();
+ const QString& IconText();
+ QString fullTitle() const;
+ int keymapNo();
+ QString keymap();
+ QStrList getArgs();
+ QString getPgm();
+ QString getCwd();
+ QString getInitial_cwd() { return initial_cwd; }
+ void setInitial_cwd(const QString& _cwd) { initial_cwd=_cwd; }
+
+ void setHistory(const HistoryType&);
+ const HistoryType& history();
+
+ void setMonitorActivity(bool);
+ void setMonitorSilence(bool);
+ void setMonitorSilenceSeconds(int seconds);
+ void setMasterMode(bool);
+ void setSchemaNo(int sn);
+ void setEncodingNo(int index);
+ void setKeymapNo(int kn);
+ void setKeymap(const QString& _id);
+ void setFontNo(int fn);
+ void setTitle(const QString& _title);
+ void setIconName(const QString& _iconName);
+ void setIconText(const QString& _iconText);
+ void setAddToUtmp(bool);
+ void setXonXoff(bool);
+ bool testAndSetStateIconName (const QString& newname);
+ bool sendSignal(int signal);
+
+ void setAutoClose(bool b) { autoClose = b; }
+
+ // Additional functions for DCOP
+ bool closeSession();
+ void clearHistory();
+ void feedSession(const QString &text);
+ void sendSession(const QString &text);
+ void renameSession(const QString &name);
+ QString sessionName() { return title; }
+ int sessionPID() { return sh->pid(); }
+
+ virtual bool processDynamic(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData);
+ virtual QCStringList functionsDynamic();
+ void enableFullScripting(bool b) { fullScripting = b; }
+
+ void startZModem(const QString &rz, const QString &dir, const QStringList &list);
+ void cancelZModem();
+ bool zmodemIsBusy() { return zmodemBusy; }
+
+ void print(QPainter &paint, bool friendly, bool exact);
+
+ QString schema();
+ void setSchema(const QString &schema);
+ QString encoding();
+ void setEncoding(const QString &encoding);
+ QString keytab();
+ void setKeytab(const QString &keytab);
+ QSize size();
+ void setSize(QSize size);
+ void setFont(const QString &font);
+ QString font();
+
+public slots:
+
+ void run();
+ void setProgram( const QString &_pgm, const QStrList &_args );
+ void done();
+ void done(int);
+ void terminate();
+ void setUserTitle( int, const QString &caption );
+ void changeTabTextColor( int );
+ void ptyError();
+ void slotZModemDetected();
+ void emitZModemDetected();
+
+ void zmodemStatus(KProcess *, char *data, int len);
+ void zmodemSendBlock(KProcess *, char *data, int len);
+ void zmodemRcvBlock(const char *data, int len);
+ void zmodemDone();
+ void zmodemContinue();
+
+signals:
+
+ void processExited(KProcess *);
+ void forkedChild();
+ void receivedData( const QString& text );
+ void done(TESession*);
+ void updateTitle(TESession*);
+ void notifySessionState(TESession* session, int state);
+ void changeTabTextColor( TESession*, int );
+
+ void disableMasterModeConnections();
+ void enableMasterModeConnections();
+ void renameSession(TESession* ses, const QString &name);
+
+ void openURLRequest(const QString &cwd);
+
+ void zmodemDetected(TESession *);
+ void updateSessionConfig(TESession *);
+ void resizeSession(TESession *session, QSize size);
+ void setSessionEncoding(TESession *session, const QString &encoding);
+ void getSessionSchema(TESession *session, QString &schema);
+ void setSessionSchema(TESession *session, const QString &schema);
+
+private slots:
+ void onRcvBlock( const char* buf, int len );
+ void monitorTimerDone();
+ void notifySessionState(int state);
+ void onContentSizeChange(int height, int width);
+ void onFontMetricChange(int height, int width);
+
+private:
+
+ TEPty* sh;
+ TEWidget* te;
+ TEmulation* em;
+
+ bool connected;
+ bool monitorActivity;
+ bool monitorSilence;
+ bool notifiedActivity;
+ bool masterMode;
+ bool autoClose;
+ bool wantedClose;
+ QTimer* monitorTimer;
+
+ //FIXME: using the indices here
+ // is propably very bad. We should
+ // use a persistent reference instead.
+ int schema_no;
+ int font_no;
+ int silence_seconds;
+
+ int font_h;
+ int font_w;
+
+ QString title;
+ QString userTitle;
+ QString iconName;
+ QString iconText; // as set by: echo -en '\033]1;IconText\007
+ bool add_to_utmp;
+ bool xon_xoff;
+ bool fullScripting;
+
+ QString stateIconName;
+
+ QString pgm;
+ QStrList args;
+
+ QString term;
+ ulong winId;
+ QString sessionId;
+
+ QString cwd;
+ QString initial_cwd;
+
+ // ZModem
+ bool zmodemBusy;
+ KProcIO* zmodemProc;
+ ZModemDialog* zmodemProgress;
+
+ // Color/Font Changes by ESC Sequences
+
+ QColor modifiedBackground; // as set by: echo -en '\033]11;Color\007
+ int encoding_no;
+};
+
+#endif
diff --git a/konsole/konsole/sessioniface.h b/konsole/konsole/sessioniface.h
new file mode 100644
index 000000000..51ee5ca80
--- /dev/null
+++ b/konsole/konsole/sessioniface.h
@@ -0,0 +1,51 @@
+/*
+ This file is part of Konsole, an X terminal.
+ Copyright (C) 2001 by Stephan Binner <binner@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+*/
+
+#ifndef SESSIONIFACE_H
+#define SESSIONIFACE_H
+
+#include <dcopobject.h>
+
+class SessionIface : virtual public DCOPObject
+{
+ K_DCOP
+ k_dcop:
+
+ virtual bool closeSession() =0;
+ virtual bool sendSignal(int signal) =0;
+
+ virtual void clearHistory() =0;
+ virtual void renameSession(const QString &name) =0;
+ virtual QString sessionName() =0;
+ virtual int sessionPID() =0;
+
+ virtual QString schema() =0;
+ virtual void setSchema(const QString &schema) =0;
+ virtual QString encoding() =0;
+ virtual void setEncoding(const QString &encoding) =0;
+ virtual QString keytab() =0;
+ virtual void setKeytab(const QString &keyboard) =0;
+ virtual QSize size() =0;
+ virtual void setSize(QSize size) =0;
+ virtual QString font() =0;
+ virtual void setFont(const QString &font) =0;
+};
+
+#endif // SESSIONIFACE_H
diff --git a/konsole/konsole/x-konsole.desktop b/konsole/konsole/x-konsole.desktop
new file mode 100644
index 000000000..e70d77e47
--- /dev/null
+++ b/konsole/konsole/x-konsole.desktop
@@ -0,0 +1,74 @@
+[Desktop Entry]
+Type=MimeType
+MimeType=application/x-konsole
+X-KDE-AutoEmbed=true
+Icon=konsole
+Patterns=*.shell;
+Comment=File to Open a Shell
+Comment[af]=Lêer om 'n tolk mee oop te maak
+Comment[ar]=ملف لفتح محارة
+Comment[az]=Qabığı Açacaq Fayl
+Comment[be]=Файл адкрыцця абалонкі
+Comment[bg]=Файл за отваряне в конзолата
+Comment[bn]=শেল খোলার জন্য ফাইল
+Comment[bs]=Datoteka za otvaranje shella
+Comment[ca]=Fitxer per a obrir una shell
+Comment[cs]=Soubor k otevření příkazové řádky
+Comment[csb]=Lopk do òtemkniãcô pòwłoczi
+Comment[da]=Fil som skal åbnes i en skal
+Comment[de]=Datei zum Öffnen einer Shell
+Comment[el]=Αρχείο για άνοιγμα ενός κελύφους
+Comment[eo]=Dosiero por malfermi komandinterpretilon
+Comment[es]=Archivo para abrir un intérprete de órdenes
+Comment[et]=Shelli avamise rakendus
+Comment[eu]=Shella irekitzeko fitxategia
+Comment[fa]=پرونده برای باز کردن پوسته
+Comment[fi]=Tiedosto, joka avaa komentoikkunan
+Comment[fr]=Fichier pour ouvrir un « shell »
+Comment[fy]=Triem om in flues te iepenjen
+Comment[ga]=Comhad a osclaíonn blaosc
+Comment[gl]=Ficheiro para abrir unha shell
+Comment[he]=קובץ לפתיחת מעטפת
+Comment[hi]=शैल खोलने हेतु फ़ाइल
+Comment[hr]=Otvaranje ljuske nije uspjelo
+Comment[hu]=Parancsértelmező megnyitási fájlja
+Comment[is]=Skrá sem opnar skel
+Comment[it]=File per aprire una shell
+Comment[ja]=シェルを開くファイル
+Comment[ka]=გარსის გასახსნელი ფაილი
+Comment[kk]=Қоршау-ортада ашатын файл
+Comment[km]=ឯកសារ​ដើម្បី​បើក​សែល​មួយ
+Comment[lt]=Byla apvalkalo atidarymui
+Comment[lv]=Fails čaulas atvēršanai
+Comment[mk]=Датотека за отворање на школка
+Comment[ms]=Fail untuk Buka Shell
+Comment[mt]=Fajl biex jiftaħ shell
+Comment[nb]=Fil for å åpne et skall
+Comment[nds]=Datei för't Opmaken vun en Konsool
+Comment[ne]=शेल खोल्ने फाइल
+Comment[nl]=Bestand om een shell te openen
+Comment[nn]=Fil for opning av skal
+Comment[pa]=ਇੱਕ ਸੈੱਲ ਖੋਲਣ ਲਈ ਫਾਇਲ
+Comment[pl]=Plik do otwarcia powłoki
+Comment[pt]=Ficheiro para Abrir uma Consola
+Comment[pt_BR]=Arquivo para Abrir um Shell
+Comment[ro]=Fișier pentru execuția unui interpretor
+Comment[ru]=Файл для открытия оболочки
+Comment[rw]=Idosiye yo Gufungura Sheli
+Comment[se]=Fiila mainna rahpá skálžžu
+Comment[sk]=Súbor na otvorenie shellu
+Comment[sl]=Datoteka za odprtje lupine
+Comment[sr]=Фајл за отварање шкољке
+Comment[sr@Latn]=Fajl za otvaranje školjke
+Comment[sv]=Fil som ska öppnas i ett skal
+Comment[ta]=ஷெல்லை திறப்பதற்கு கோப்பு
+Comment[th]=แฟ้มที่จะใช้เปิดเชลล์
+Comment[tr]=Kabuk'a Açılacak Dosya
+Comment[tt]=Qabıq Açu öçen Birem
+Comment[uk]=Файл, який треба відкрити у оболонці
+Comment[uz]=Shelni ochish uchun fayl
+Comment[uz@cyrillic]=Шелни очиш учун файл
+Comment[vi]=Tập tin để Mở một Trình giao diện
+Comment[wa]=Fitchî a drovi dins on shell
+Comment[zh_CN]=打开 Shell 的文件
+Comment[zh_TW]=要打開 shell 的檔案
diff --git a/konsole/konsole/zmodem_dialog.cpp b/konsole/konsole/zmodem_dialog.cpp
new file mode 100644
index 000000000..31148ddc6
--- /dev/null
+++ b/konsole/konsole/zmodem_dialog.cpp
@@ -0,0 +1,56 @@
+/* This file is part of the KDE libraries
+ * Copyright (C) 2002 Waldo Bastian <bastian@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#include "zmodem_dialog.h"
+
+#include <qtextedit.h>
+
+#include <klocale.h>
+
+ZModemDialog::ZModemDialog(QWidget *parent, bool modal, const QString &caption)
+ : KDialogBase(parent, "zmodem_progress", modal, caption,
+ User1|Close, User1, true,
+ i18n("&Stop"))
+{
+ setEscapeButton(User1);
+ enableButton(Close, false);
+ textEdit = new QTextEdit(this);
+ textEdit->setMinimumSize(400, 100);
+ setMainWidget(textEdit);
+ connect(this, SIGNAL(user1Clicked()), this, SLOT(slotClose()));
+}
+
+void ZModemDialog::addProgressText(const QString &txt)
+{
+ int p = textEdit->paragraphs();
+ textEdit->insertParagraph(txt, p);
+}
+
+void ZModemDialog::done()
+{
+ enableButton(Close, true);
+ enableButton(User1, false);
+}
+
+void ZModemDialog::slotClose()
+{
+ KDialogBase::slotClose();
+ delayedDestruct();
+}
+
+#include "zmodem_dialog.moc"
diff --git a/konsole/konsole/zmodem_dialog.h b/konsole/konsole/zmodem_dialog.h
new file mode 100644
index 000000000..045e1c566
--- /dev/null
+++ b/konsole/konsole/zmodem_dialog.h
@@ -0,0 +1,49 @@
+/* This file is part of the KDE libraries
+ * Copyright (C) 2002 Waldo Bastian <bastian@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#ifndef ZMODEM_DIALOG_H
+#define ZMODEM_DIALOG_H
+
+#include <kdialogbase.h>
+
+class QTextEdit;
+
+class ZModemDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ ZModemDialog(QWidget *parent, bool modal, const QString &caption);
+
+ /**
+ * Adds a line of text to the progress window
+ */
+ void addProgressText(const QString &);
+
+ /**
+ * To indicate the process is finished.
+ */
+ void done();
+
+public slots:
+ void slotClose();
+
+private:
+ QTextEdit *textEdit;
+};
+
+#endif