From 25661234c035ed5cd4e238b27e84b6b5a47da24a Mon Sep 17 00:00:00 2001 From: Petr Vanek Date: Fri, 1 Oct 2010 16:08:52 +0200 Subject: [PATCH] K&R formatting --- lib/BlockArray.cpp | 47 +- lib/BlockArray.h | 17 +- lib/Character.h | 143 +- lib/CharacterColor.h | 290 +-- lib/ColorTables.h | 43 +- lib/Emulation.cpp | 327 ++-- lib/Emulation.h | 639 +++---- lib/Filter.cpp | 146 +- lib/Filter.h | 170 +- lib/History.cpp | 473 +++-- lib/History.h | 305 +-- lib/KeyboardTranslator.cpp | 401 ++-- lib/KeyboardTranslator.h | 237 +-- lib/LineFont.h | 32 +- lib/Pty.cpp | 296 ++- lib/Pty.h | 116 +- lib/Screen.cpp | 1485 +++++++-------- lib/Screen.h | 355 ++-- lib/ScreenWindow.cpp | 141 +- lib/ScreenWindow.h | 73 +- lib/Session.cpp | 595 +++--- lib/Session.h | 791 ++++---- lib/ShellCommand.cpp | 100 +- lib/ShellCommand.h | 16 +- lib/TerminalCharacterDecoder.cpp | 190 +- lib/TerminalCharacterDecoder.h | 84 +- lib/TerminalDisplay.cpp | 3065 ++++++++++++++---------------- lib/TerminalDisplay.h | 346 ++-- lib/Vt102Emulation.cpp | 1738 +++++++++++------ lib/Vt102Emulation.h | 200 +- lib/k3process.cpp | 1170 ++++++------ lib/k3process.h | 1293 ++++++------- lib/k3processcontroller.cpp | 286 ++- lib/k3processcontroller.h | 150 +- lib/konsole_wcwidth.cpp | 275 +-- lib/kpty.cpp | 279 ++- lib/kpty.h | 259 +-- lib/qtermwidget.cpp | 107 +- lib/qtermwidget.h | 56 +- 39 files changed, 8510 insertions(+), 8226 deletions(-) diff --git a/lib/BlockArray.cpp b/lib/BlockArray.cpp index b8fc82f..b64f396 100644 --- a/lib/BlockArray.cpp +++ b/lib/BlockArray.cpp @@ -39,13 +39,13 @@ using namespace Konsole; 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) + : 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) @@ -68,8 +68,18 @@ size_t BlockArray::append(Block *block) 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); } + 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; @@ -119,7 +129,7 @@ const Block* BlockArray::at(size_t i) qDebug() << "BlockArray::at() i > index\n"; return 0; } - + // if (index - i >= length) { // kDebug(1211) << "BlockArray::at() index - i >= length\n"; // return 0; @@ -132,7 +142,10 @@ const Block* BlockArray::at(size_t i) Block *block = (Block*)mmap(0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize); - if (block == (Block*)-1) { perror("mmap"); return 0; } + if (block == (Block*)-1) { + perror("mmap"); + return 0; + } lastmap = block; lastmap_index = i; @@ -201,7 +214,7 @@ bool BlockArray::setHistorySize(size_t newsize) } else { decreaseBuffer(newsize); if (ftruncate(ion, length*blocksize) == -1) - perror("ftruncate"); + perror("ftruncate"); size = newsize; return true; @@ -296,14 +309,13 @@ void BlockArray::increaseBuffer() FILE *fion = fdopen(dup(ion), "w+b"); if (!fion) { perror("fdopen/dup"); - delete [] buffer1; - delete [] buffer2; + delete [] buffer1; + delete [] buffer2; return; } int res; - for (int i = 0; i < runs; i++) - { + for (int i = 0; i < runs; i++) { // free one block in chain int firstblock = (offset + i) % size; res = fseek(fion, firstblock * blocksize, SEEK_SET); @@ -313,8 +325,7 @@ void BlockArray::increaseBuffer() if (res != 1) perror("fread"); int newpos = 0; - for (int j = 1, cursor=firstblock; j < bpr; j++) - { + for (int j = 1, cursor=firstblock; j < bpr; j++) { cursor = (cursor + offset) % size; newpos = (cursor - offset + size) % size; moveBlock(fion, cursor, newpos, buffer2); diff --git a/lib/BlockArray.h b/lib/BlockArray.h index ca47388..37c91b9 100644 --- a/lib/BlockArray.h +++ b/lib/BlockArray.h @@ -1,7 +1,7 @@ /* This file is part of Konsole, an X terminal. Copyright (C) 2000 by Stephan Kulow - + Rewritten for QT4 by e_k , Copyright (C)2008 This program is free software; you can redistribute it and/or modify @@ -34,14 +34,17 @@ namespace Konsole { struct Block { - Block() { size = 0; } + Block() { + size = 0; + } unsigned char data[ENTRIES]; size_t size; }; // /////////////////////////////////////////////////////// -class BlockArray { +class BlockArray +{ public: /** * Creates a history file for holding @@ -95,11 +98,15 @@ public: */ bool setSize(size_t newsize); - size_t len() const { return length; } + size_t len() const { + return length; + } bool has(size_t index) const; - size_t getCurrent() const { return current; } + size_t getCurrent() const { + return current; + } private: void unmap(); diff --git a/lib/Character.h b/lib/Character.h index 0978ce5..4d63185 100644 --- a/lib/Character.h +++ b/lib/Character.h @@ -1,6 +1,6 @@ /* This file is part of Konsole, KDE's terminal. - + Copyright (C) 2007 by Robert Knight Copyright (C) 1997,1998 by Lars Doelle @@ -58,96 +58,95 @@ static const int LINE_DOUBLEHEIGHT = (1 << 2); class Character { public: - /** - * Constructs a new character. - * - * @param _c The unicode character value of this character. - * @param _f The foreground color used to draw the character. - * @param _b The color used to draw the character's background. - * @param _r A set of rendition flags which specify how this character is to be drawn. - */ - inline Character(quint16 _c = ' ', - CharacterColor _f = CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR), - CharacterColor _b = CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR), - quint8 _r = DEFAULT_RENDITION) - : character(_c), rendition(_r), foregroundColor(_f), backgroundColor(_b) {} - - union - { - /** The unicode character value for this character. */ - quint16 character; - /** - * Experimental addition which allows a single Character instance to contain more than - * one unicode character. + /** + * Constructs a new character. * - * charSequence is a hash code which can be used to look up the unicode - * character sequence in the ExtendedCharTable used to create the sequence. + * @param _c The unicode character value of this character. + * @param _f The foreground color used to draw the character. + * @param _b The color used to draw the character's background. + * @param _r A set of rendition flags which specify how this character is to be drawn. */ - quint16 charSequence; - }; + inline Character(quint16 _c = ' ', + CharacterColor _f = CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR), + CharacterColor _b = CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR), + quint8 _r = DEFAULT_RENDITION) + : character(_c), rendition(_r), foregroundColor(_f), backgroundColor(_b) {} - /** A combination of RENDITION flags which specify options for drawing the character. */ - quint8 rendition; + union { + /** The unicode character value for this character. */ + quint16 character; + /** + * Experimental addition which allows a single Character instance to contain more than + * one unicode character. + * + * charSequence is a hash code which can be used to look up the unicode + * character sequence in the ExtendedCharTable used to create the sequence. + */ + quint16 charSequence; + }; - /** The foreground color used to draw this character. */ - CharacterColor foregroundColor; - /** The color used to draw this character's background. */ - CharacterColor backgroundColor; + /** A combination of RENDITION flags which specify options for drawing the character. */ + quint8 rendition; - /** - * Returns true if this character has a transparent background when - * it is drawn with the specified @p palette. - */ - bool isTransparent(const ColorEntry* palette) const; - /** - * Returns true if this character should always be drawn in bold when - * it is drawn with the specified @p palette, independent of whether - * or not the character has the RE_BOLD rendition flag. - */ - bool isBold(const ColorEntry* base) const; - - /** - * Compares two characters and returns true if they have the same unicode character value, - * rendition and colors. - */ - friend bool operator == (const Character& a, const Character& b); - /** - * Compares two characters and returns true if they have different unicode character values, - * renditions or colors. - */ - friend bool operator != (const Character& a, const Character& b); + /** The foreground color used to draw this character. */ + CharacterColor foregroundColor; + /** The color used to draw this character's background. */ + CharacterColor backgroundColor; + + /** + * Returns true if this character has a transparent background when + * it is drawn with the specified @p palette. + */ + bool isTransparent(const ColorEntry* palette) const; + /** + * Returns true if this character should always be drawn in bold when + * it is drawn with the specified @p palette, independent of whether + * or not the character has the RE_BOLD rendition flag. + */ + bool isBold(const ColorEntry* base) const; + + /** + * Compares two characters and returns true if they have the same unicode character value, + * rendition and colors. + */ + friend bool operator == (const Character& a, const Character& b); + /** + * Compares two characters and returns true if they have different unicode character values, + * renditions or colors. + */ + friend bool operator != (const Character& a, const Character& b); }; inline bool operator == (const Character& a, const Character& b) -{ - return a.character == b.character && - a.rendition == b.rendition && - a.foregroundColor == b.foregroundColor && - a.backgroundColor == b.backgroundColor; +{ + return a.character == b.character && + a.rendition == b.rendition && + a.foregroundColor == b.foregroundColor && + a.backgroundColor == b.backgroundColor; } inline bool operator != (const Character& a, const Character& b) { - return a.character != b.character || - a.rendition != b.rendition || - a.foregroundColor != b.foregroundColor || - a.backgroundColor != b.backgroundColor; + return a.character != b.character || + a.rendition != b.rendition || + a.foregroundColor != b.foregroundColor || + a.backgroundColor != b.backgroundColor; } inline bool Character::isTransparent(const ColorEntry* base) const { - return ((backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) && - base[backgroundColor._u+0+(backgroundColor._v?BASE_COLORS:0)].transparent) - || ((backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) && - base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].transparent); + return ((backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) && + base[backgroundColor._u+0+(backgroundColor._v?BASE_COLORS:0)].transparent) + || ((backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) && + base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].transparent); } inline bool Character::isBold(const ColorEntry* base) const { - return ((backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) && + return ((backgroundColor._colorSpace == COLOR_SPACE_DEFAULT) && base[backgroundColor._u+0+(backgroundColor._v?BASE_COLORS:0)].bold) - || ((backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) && - base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].bold); + || ((backgroundColor._colorSpace == COLOR_SPACE_SYSTEM) && + base[backgroundColor._u+2+(backgroundColor._v?BASE_COLORS:0)].bold); } extern unsigned short vt100_graphics[32]; @@ -183,7 +182,7 @@ public: * which was added to the table using createExtendedChar(). * * @param hash The hash key returned by createExtendedChar() - * @param length This variable is set to the length of the + * @param length This variable is set to the length of the * character sequence. * * @return A unicode character sequence of size @p length. @@ -195,7 +194,7 @@ public: private: // calculates the hash key of a sequence of unicode points of size 'length' ushort extendedCharHash(ushort* unicodePoints , ushort length) const; - // tests whether the entry in the table specified by 'hash' matches the + // tests whether the entry in the table specified by 'hash' matches the // character sequence 'unicodePoints' of size 'length' bool extendedCharMatch(ushort hash , ushort* unicodePoints , ushort length) const; // internal, maps hash keys to character sequence buffers. The first ushort diff --git a/lib/CharacterColor.h b/lib/CharacterColor.h index d16b141..483c6e0 100644 --- a/lib/CharacterColor.h +++ b/lib/CharacterColor.h @@ -1,6 +1,6 @@ /* This file is part of Konsole, KDE's terminal. - + Copyright (C) 2007 by Robert Knight Copyright (C) 1997,1998 by Lars Doelle @@ -31,14 +31,14 @@ namespace Konsole { -/** - * An entry in a terminal display's color palette. +/** + * An entry in a terminal display's color palette. * * A color palette is an array of 16 ColorEntry instances which map * system color indexes (from 0 to 15) into actual colors. * * Each entry can be set as bold, in which case any text - * drawn using the color should be drawn in bold. + * drawn using the color should be drawn in bold. * * Each entry can also be transparent, in which case the terminal * display should avoid drawing the background for any characters @@ -47,44 +47,43 @@ namespace Konsole class ColorEntry { public: - /** - * Constructs a new color palette entry. - * - * @param c The color value for this entry. - * @param tr Specifies that the color should be transparent when used as a background color. - * @param b Specifies that text drawn with this color should be bold. - */ - ColorEntry(QColor c, bool tr, bool b) : color(c), transparent(tr), bold(b) {} + /** + * Constructs a new color palette entry. + * + * @param c The color value for this entry. + * @param tr Specifies that the color should be transparent when used as a background color. + * @param b Specifies that text drawn with this color should be bold. + */ + ColorEntry(QColor c, bool tr, bool b) : color(c), transparent(tr), bold(b) {} - /** - * Constructs a new color palette entry with an undefined color, and - * with the transparent and bold flags set to false. - */ - ColorEntry() : transparent(false), bold(false) {} - - /** - * Sets the color, transparency and boldness of this color to those of @p rhs. - */ - void operator=(const ColorEntry& rhs) - { - color = rhs.color; - transparent = rhs.transparent; - bold = rhs.bold; - } + /** + * Constructs a new color palette entry with an undefined color, and + * with the transparent and bold flags set to false. + */ + ColorEntry() : transparent(false), bold(false) {} - /** The color value of this entry for display. */ - QColor color; + /** + * Sets the color, transparency and boldness of this color to those of @p rhs. + */ + void operator=(const ColorEntry& rhs) { + color = rhs.color; + transparent = rhs.transparent; + bold = rhs.bold; + } - /** - * If true character backgrounds using this color should be transparent. - * This is not applicable when the color is used to render text. - */ - bool transparent; - /** - * If true characters drawn using this color should be bold. - * This is not applicable when the color is used to draw a character's background. - */ - bool bold; + /** The color value of this entry for display. */ + QColor color; + + /** + * If true character backgrounds using this color should be transparent. + * This is not applicable when the color is used to render text. + */ + bool transparent; + /** + * If true characters drawn using this color should be bold. + * This is not applicable when the color is used to draw a character's background. + */ + bool bold; }; @@ -107,19 +106,19 @@ static const ColorEntry base_color_table[TABLE_COLORS] = // 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 ) + // 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 ) }; /* CharacterColor is a union of the various color spaces. @@ -152,32 +151,29 @@ class CharacterColor friend class Character; public: - /** Constructs a new CharacterColor whoose color and color space are undefined. */ - CharacterColor() - : _colorSpace(COLOR_SPACE_UNDEFINED), - _u(0), - _v(0), - _w(0) - {} + /** Constructs a new CharacterColor whoose color and color space are undefined. */ + CharacterColor() + : _colorSpace(COLOR_SPACE_UNDEFINED), + _u(0), + _v(0), + _w(0) {} - /** - * Constructs a new CharacterColor using the specified @p colorSpace and with - * color value @p co - * - * The meaning of @p co depends on the @p colorSpace used. - * - * TODO : Document how @p co relates to @p colorSpace - * - * TODO : Add documentation about available color spaces. - */ - CharacterColor(quint8 colorSpace, int co) - : _colorSpace(colorSpace), - _u(0), - _v(0), - _w(0) - { - switch (colorSpace) - { + /** + * Constructs a new CharacterColor using the specified @p colorSpace and with + * color value @p co + * + * The meaning of @p co depends on the @p colorSpace used. + * + * TODO : Document how @p co relates to @p colorSpace + * + * TODO : Add documentation about available color spaces. + */ + CharacterColor(quint8 colorSpace, int co) + : _colorSpace(colorSpace), + _u(0), + _v(0), + _w(0) { + switch (colorSpace) { case COLOR_SPACE_DEFAULT: _u = co & 1; break; @@ -185,7 +181,7 @@ public: _u = co & 7; _v = (co >> 3) & 1; break; - case COLOR_SPACE_256: + case COLOR_SPACE_256: _u = co & 255; break; case COLOR_SPACE_RGB: @@ -195,59 +191,58 @@ public: break; default: _colorSpace = COLOR_SPACE_UNDEFINED; + } } - } - /** - * Returns true if this character color entry is valid. - */ - bool isValid() - { + /** + * Returns true if this character color entry is valid. + */ + bool isValid() { return _colorSpace != COLOR_SPACE_UNDEFINED; - } - - /** - * Toggles the value of this color between a normal system color and the corresponding intensive - * system color. - * - * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM - * color spaces. - */ - void toggleIntensive(); + } - /** - * Returns the color within the specified color @palette - * - * The @p palette is only used if this color is one of the 16 system colors, otherwise - * it is ignored. - */ - QColor color(const ColorEntry* palette) const; - - /** - * Compares two colors and returns true if they represent the same color value and - * use the same color space. - */ - friend bool operator == (const CharacterColor& a, const CharacterColor& b); - /** - * Compares two colors and returns true if they represent different color values - * or use different color spaces. - */ - friend bool operator != (const CharacterColor& a, const CharacterColor& b); + /** + * Toggles the value of this color between a normal system color and the corresponding intensive + * system color. + * + * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM + * color spaces. + */ + void toggleIntensive(); + + /** + * Returns the color within the specified color @palette + * + * The @p palette is only used if this color is one of the 16 system colors, otherwise + * it is ignored. + */ + QColor color(const ColorEntry* palette) const; + + /** + * Compares two colors and returns true if they represent the same color value and + * use the same color space. + */ + friend bool operator == (const CharacterColor& a, const CharacterColor& b); + /** + * Compares two colors and returns true if they represent different color values + * or use different color spaces. + */ + friend bool operator != (const CharacterColor& a, const CharacterColor& b); private: - quint8 _colorSpace; + quint8 _colorSpace; - // bytes storing the character color - quint8 _u; - quint8 _v; - quint8 _w; + // bytes storing the character color + quint8 _u; + quint8 _v; + quint8 _w; }; inline bool operator == (const CharacterColor& a, const CharacterColor& b) -{ +{ return a._colorSpace == b._colorSpace && - a._u == b._u && - a._v == b._v && + a._u == b._u && + a._v == b._v && a._w == b._w; } @@ -258,41 +253,48 @@ inline bool operator != (const CharacterColor& a, const CharacterColor& b) inline const QColor color256(quint8 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; + // 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); + // 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 CharacterColor::color(const ColorEntry* base) const { - switch (_colorSpace) - { - case COLOR_SPACE_DEFAULT: return base[_u+0+(_v?BASE_COLORS:0)].color; - case COLOR_SPACE_SYSTEM: return base[_u+2+(_v?BASE_COLORS:0)].color; - case COLOR_SPACE_256: return color256(_u,base); - case COLOR_SPACE_RGB: return QColor(_u,_v,_w); - case COLOR_SPACE_UNDEFINED: return QColor(); - } + switch (_colorSpace) { + case COLOR_SPACE_DEFAULT: + return base[_u+0+(_v?BASE_COLORS:0)].color; + case COLOR_SPACE_SYSTEM: + return base[_u+2+(_v?BASE_COLORS:0)].color; + case COLOR_SPACE_256: + return color256(_u,base); + case COLOR_SPACE_RGB: + return QColor(_u,_v,_w); + case COLOR_SPACE_UNDEFINED: + return QColor(); + } - Q_ASSERT(false); // invalid color space + Q_ASSERT(false); // invalid color space - return QColor(); + return QColor(); } inline void CharacterColor::toggleIntensive() { - if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT) - { - _v = !_v; - } + if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT) { + _v = !_v; + } } diff --git a/lib/ColorTables.h b/lib/ColorTables.h index 321d6db..d759607 100644 --- a/lib/ColorTables.h +++ b/lib/ColorTables.h @@ -5,8 +5,7 @@ using namespace Konsole; -static const ColorEntry whiteonblack_color_table[TABLE_COLORS] = -{ +static const ColorEntry whiteonblack_color_table[TABLE_COLORS] = { // normal ColorEntry(QColor(0xFF,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0x00,0x00,0x00), 1, 0 ), // Dfore, Dback ColorEntry(QColor(0x00,0x00,0x00), 0, 0 ), ColorEntry( QColor(0xB2,0x18,0x18), 0, 0 ), // Black, Red @@ -21,13 +20,12 @@ static const ColorEntry whiteonblack_color_table[TABLE_COLORS] = ColorEntry(QColor(0x54,0xFF,0xFF), 0, 0 ), ColorEntry( QColor(0xFF,0xFF,0xFF), 0, 0 ) }; -static const ColorEntry greenonblack_color_table[TABLE_COLORS] = -{ - ColorEntry(QColor( 24, 240, 24), 0, 0), ColorEntry(QColor( 0, 0, 0), 1, 0), - ColorEntry(QColor( 0, 0, 0), 0, 0), ColorEntry(QColor( 178, 24, 24), 0, 0), - ColorEntry(QColor( 24, 178, 24), 0, 0), ColorEntry(QColor( 178, 104, 24), 0, 0), - ColorEntry(QColor( 24, 24, 178), 0, 0), ColorEntry(QColor( 178, 24, 178), 0, 0), - ColorEntry(QColor( 24, 178, 178), 0, 0), ColorEntry(QColor( 178, 178, 178), 0, 0), +static const ColorEntry greenonblack_color_table[TABLE_COLORS] = { + ColorEntry(QColor( 24, 240, 24), 0, 0), ColorEntry(QColor( 0, 0, 0), 1, 0), + ColorEntry(QColor( 0, 0, 0), 0, 0), ColorEntry(QColor( 178, 24, 24), 0, 0), + ColorEntry(QColor( 24, 178, 24), 0, 0), ColorEntry(QColor( 178, 104, 24), 0, 0), + ColorEntry(QColor( 24, 24, 178), 0, 0), ColorEntry(QColor( 178, 24, 178), 0, 0), + ColorEntry(QColor( 24, 178, 178), 0, 0), ColorEntry(QColor( 178, 178, 178), 0, 0), // intensive colors ColorEntry(QColor( 24, 240, 24), 0, 1 ), ColorEntry(QColor( 0, 0, 0), 1, 0 ), ColorEntry(QColor( 104, 104, 104), 0, 0 ), ColorEntry(QColor( 255, 84, 84), 0, 0 ), @@ -36,22 +34,21 @@ static const ColorEntry greenonblack_color_table[TABLE_COLORS] = ColorEntry(QColor( 84, 255, 255), 0, 0 ), ColorEntry(QColor( 255, 255, 255), 0, 0 ) }; -static const ColorEntry blackonlightyellow_color_table[TABLE_COLORS] = -{ - ColorEntry(QColor( 0, 0, 0), 0, 0), ColorEntry(QColor( 255, 255, 221), 1, 0), - ColorEntry(QColor( 0, 0, 0), 0, 0), ColorEntry(QColor( 178, 24, 24), 0, 0), - ColorEntry(QColor( 24, 178, 24), 0, 0), ColorEntry(QColor( 178, 104, 24), 0, 0), - ColorEntry(QColor( 24, 24, 178), 0, 0), ColorEntry(QColor( 178, 24, 178), 0, 0), - ColorEntry(QColor( 24, 178, 178), 0, 0), ColorEntry(QColor( 178, 178, 178), 0, 0), - ColorEntry(QColor( 0, 0, 0), 0, 1), ColorEntry(QColor( 255, 255, 221), 1, 0), - ColorEntry(QColor(104, 104, 104), 0, 0), ColorEntry(QColor( 255, 84, 84), 0, 0), - ColorEntry(QColor( 84, 255, 84), 0, 0), ColorEntry(QColor( 255, 255, 84), 0, 0), - ColorEntry(QColor( 84, 84, 255), 0, 0), ColorEntry(QColor( 255, 84, 255), 0, 0), +static const ColorEntry blackonlightyellow_color_table[TABLE_COLORS] = { + ColorEntry(QColor( 0, 0, 0), 0, 0), ColorEntry(QColor( 255, 255, 221), 1, 0), + ColorEntry(QColor( 0, 0, 0), 0, 0), ColorEntry(QColor( 178, 24, 24), 0, 0), + ColorEntry(QColor( 24, 178, 24), 0, 0), ColorEntry(QColor( 178, 104, 24), 0, 0), + ColorEntry(QColor( 24, 24, 178), 0, 0), ColorEntry(QColor( 178, 24, 178), 0, 0), + ColorEntry(QColor( 24, 178, 178), 0, 0), ColorEntry(QColor( 178, 178, 178), 0, 0), + ColorEntry(QColor( 0, 0, 0), 0, 1), ColorEntry(QColor( 255, 255, 221), 1, 0), + ColorEntry(QColor(104, 104, 104), 0, 0), ColorEntry(QColor( 255, 84, 84), 0, 0), + ColorEntry(QColor( 84, 255, 84), 0, 0), ColorEntry(QColor( 255, 255, 84), 0, 0), + ColorEntry(QColor( 84, 84, 255), 0, 0), ColorEntry(QColor( 255, 84, 255), 0, 0), ColorEntry(QColor( 84, 255, 255), 0, 0), ColorEntry(QColor( 255, 255, 255), 0, 0) }; - - - + + + #endif diff --git a/lib/Emulation.cpp b/lib/Emulation.cpp index e767a42..038051d 100644 --- a/lib/Emulation.cpp +++ b/lib/Emulation.cpp @@ -1,7 +1,7 @@ /* This file is part of Konsole, an X terminal. - Copyright (C) 2007 Robert Knight + Copyright (C) 2007 Robert Knight Copyright (C) 1997,1998 by Lars Doelle Copyright (C) 1996 by Matthias Ettrich @@ -63,24 +63,24 @@ using namespace Konsole; */ Emulation::Emulation() : - _currentScreen(0), - _codec(0), - _decoder(0), - _keyTranslator(0), - _usesMouse(false) + _currentScreen(0), + _codec(0), + _decoder(0), + _keyTranslator(0), + _usesMouse(false) { - // create screens with a default size - _screen[0] = new Screen(40,80); - _screen[1] = new Screen(40,80); - _currentScreen = _screen[0]; + // create screens with a default size + _screen[0] = new Screen(40,80); + _screen[1] = new Screen(40,80); + _currentScreen = _screen[0]; - QObject::connect(&_bulkTimer1, SIGNAL(timeout()), this, SLOT(showBulk()) ); - QObject::connect(&_bulkTimer2, SIGNAL(timeout()), this, SLOT(showBulk()) ); - - // listen for mouse status changes - connect( this , SIGNAL(programUsesMouseChanged(bool)) , - SLOT(usesMouseChanged(bool)) ); + QObject::connect(&_bulkTimer1, SIGNAL(timeout()), this, SLOT(showBulk()) ); + QObject::connect(&_bulkTimer2, SIGNAL(timeout()), this, SLOT(showBulk()) ); + + // listen for mouse status changes + connect( this , SIGNAL(programUsesMouseChanged(bool)) , + SLOT(usesMouseChanged(bool)) ); } bool Emulation::programUsesMouse() const @@ -112,16 +112,15 @@ ScreenWindow* Emulation::createWindow() Emulation::~Emulation() { - QListIterator windowIter(_windows); + QListIterator windowIter(_windows); - while (windowIter.hasNext()) - { - delete windowIter.next(); - } + while (windowIter.hasNext()) { + delete windowIter.next(); + } - delete _screen[0]; - delete _screen[1]; - delete _decoder; + delete _screen[0]; + delete _screen[1]; + delete _decoder; } /*! change between primary and alternate _screen @@ -129,19 +128,17 @@ Emulation::~Emulation() void Emulation::setScreen(int n) { - Screen *old = _currentScreen; - _currentScreen = _screen[n&1]; - if (_currentScreen != old) - { - old->setBusySelecting(false); + Screen *old = _currentScreen; + _currentScreen = _screen[n&1]; + if (_currentScreen != old) { + old->setBusySelecting(false); - // tell all windows onto this emulation to switch to the newly active _screen - QListIterator windowIter(_windows); - while ( windowIter.hasNext() ) - { - windowIter.next()->setScreen(_currentScreen); - } - } + // tell all windows onto this emulation to switch to the newly active _screen + QListIterator windowIter(_windows); + while ( windowIter.hasNext() ) { + windowIter.next()->setScreen(_currentScreen); + } + } } void Emulation::clearHistory() @@ -150,25 +147,25 @@ void Emulation::clearHistory() } void Emulation::setHistory(const HistoryType& t) { - _screen[0]->setScroll(t); + _screen[0]->setScroll(t); - showBulk(); + showBulk(); } const HistoryType& Emulation::history() { - return _screen[0]->getScroll(); + return _screen[0]->getScroll(); } void Emulation::setCodec(const QTextCodec * qtc) { - Q_ASSERT( qtc ); + Q_ASSERT( qtc ); - _codec = qtc; - delete _decoder; - _decoder = _codec->makeDecoder(); + _codec = qtc; + delete _decoder; + _decoder = _codec->makeDecoder(); - emit useUtf8Request(utf8()); + emit useUtf8Request(utf8()); } void Emulation::setCodec(EmulationCodec codec) @@ -181,12 +178,12 @@ void Emulation::setCodec(EmulationCodec codec) void Emulation::setKeyBindings(const QString& name) { - _keyTranslator = KeyboardTranslatorManager::instance()->findTranslator(name); + _keyTranslator = KeyboardTranslatorManager::instance()->findTranslator(name); } QString Emulation::keyBindings() { - return _keyTranslator->name(); + return _keyTranslator->name(); } @@ -206,17 +203,27 @@ void Emulation::receiveChar(int c) // process application unicode input to terminal // this is a trivial scanner { - c &= 0xff; - switch (c) - { - case '\b' : _currentScreen->BackSpace(); break; - case '\t' : _currentScreen->Tabulate(); break; - case '\n' : _currentScreen->NewLine(); break; - case '\r' : _currentScreen->Return(); break; - case 0x07 : emit stateSet(NOTIFYBELL); - break; - default : _currentScreen->ShowCharacter(c); break; - }; + c &= 0xff; + switch (c) { + case '\b' : + _currentScreen->BackSpace(); + break; + case '\t' : + _currentScreen->Tabulate(); + break; + case '\n' : + _currentScreen->NewLine(); + break; + case '\r' : + _currentScreen->Return(); + break; + case 0x07 : + emit stateSet(NOTIFYBELL); + break; + default : + _currentScreen->ShowCharacter(c); + break; + }; } /* ------------------------------------------------------------------------- */ @@ -230,16 +237,15 @@ void Emulation::receiveChar(int c) void Emulation::sendKeyEvent( QKeyEvent* ev ) { - emit stateSet(NOTIFYNORMAL); - - 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 sendBlock(ev->text().toAscii(),ev->text().length()); - emit sendData(ev->text().toUtf8(),ev->text().length()); - } + emit stateSet(NOTIFYNORMAL); + + 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 sendBlock(ev->text().toAscii(),ev->text().length()); + emit sendData(ev->text().toUtf8(),ev->text().length()); + } } void Emulation::sendString(const char*,int) @@ -261,29 +267,26 @@ TODO: Character composition from the old code. See #96536 void Emulation::receiveData(const char* text, int length) { - emit stateSet(NOTIFYACTIVITY); + emit stateSet(NOTIFYACTIVITY); + + bufferedUpdate(); - bufferedUpdate(); - QString unicodeText = _decoder->toUnicode(text,length); - //send characters to terminal emulator - for (int i=0;i 3) && (strncmp(text+i+1, "B00", 3) == 0)) - emit zmodemDetected(); - } - } + //look for z-modem indicator + //-- someone who understands more about z-modems that I do may be able to move + //this check into the above for loop? + for (int i=0; i 3) && (strncmp(text+i+1, "B00", 3) == 0)) + emit zmodemDetected(); + } + } } //OLDER VERSION @@ -294,13 +297,13 @@ void Emulation::receiveData(const char* text, int length) // //There is something about stopping the _decoder if "we get a control code halfway a multi-byte sequence" (see below) //which hasn't been ported into the newer function (above). Hopefully someone who understands this better -//can find an alternative way of handling the check. +//can find an alternative way of handling the check. /*void Emulation::onRcvBlock(const char *s, int len) { emit notifySessionState(NOTIFYACTIVITY); - + bufferedUpdate(); for (int i = 0; i < len; i++) { @@ -338,49 +341,52 @@ void Emulation::receiveData(const char* text, int length) // Selection --------------------------------------------------------------- -- #if 0 -void Emulation::onSelectionBegin(const int x, const int y, const bool columnmode) { - if (!connected) return; - _currentScreen->setSelectionStart( x,y,columnmode); - showBulk(); +void Emulation::onSelectionBegin(const int x, const int y, const bool columnmode) +{ + if (!connected) return; + _currentScreen->setSelectionStart( x,y,columnmode); + showBulk(); } -void Emulation::onSelectionExtend(const int x, const int y) { - if (!connected) return; - _currentScreen->setSelectionEnd(x,y); - showBulk(); +void Emulation::onSelectionExtend(const int x, const int y) +{ + if (!connected) return; + _currentScreen->setSelectionEnd(x,y); + showBulk(); } -void Emulation::setSelection(const bool preserve_line_breaks) { - if (!connected) return; - QString t = _currentScreen->selectedText(preserve_line_breaks); - if (!t.isNull()) - { - QListIterator< TerminalDisplay* > viewIter(_views); +void Emulation::setSelection(const bool preserve_line_breaks) +{ + if (!connected) return; + QString t = _currentScreen->selectedText(preserve_line_breaks); + if (!t.isNull()) { + QListIterator< TerminalDisplay* > viewIter(_views); - while (viewIter.hasNext()) - viewIter.next()->setSelection(t); - } + while (viewIter.hasNext()) + viewIter.next()->setSelection(t); + } } void Emulation::testIsSelected(const int x, const int y, bool &selected) { - if (!connected) return; - selected=_currentScreen->isSelected(x,y); + if (!connected) return; + selected=_currentScreen->isSelected(x,y); } -void Emulation::clearSelection() { - if (!connected) return; - _currentScreen->clearSelection(); - showBulk(); -} - -#endif - -void Emulation::writeToStream( TerminalCharacterDecoder* _decoder , - int startLine , - int endLine) +void Emulation::clearSelection() { - _currentScreen->writeToStream(_decoder,startLine,endLine); + if (!connected) return; + _currentScreen->clearSelection(); + showBulk(); +} + +#endif + +void Emulation::writeToStream( TerminalCharacterDecoder* _decoder , + int startLine , + int endLine) +{ + _currentScreen->writeToStream(_decoder,startLine,endLine); } int Emulation::lineCount() @@ -409,44 +415,42 @@ void Emulation::showBulk() void Emulation::bufferedUpdate() { - _bulkTimer1.setSingleShot(true); - _bulkTimer1.start(BULK_TIMEOUT1); - if (!_bulkTimer2.isActive()) - { - _bulkTimer2.setSingleShot(true); - _bulkTimer2.start(BULK_TIMEOUT2); - } + _bulkTimer1.setSingleShot(true); + _bulkTimer1.start(BULK_TIMEOUT1); + if (!_bulkTimer2.isActive()) { + _bulkTimer2.setSingleShot(true); + _bulkTimer2.start(BULK_TIMEOUT2); + } } char Emulation::getErase() const { - return '\b'; + return '\b'; } void Emulation::setImageSize(int lines, int columns) { - //kDebug() << "Resizing image to: " << lines << "by" << columns << QTime::currentTime().msec(); - Q_ASSERT( lines > 0 ); - Q_ASSERT( columns > 0 ); + //kDebug() << "Resizing image to: " << lines << "by" << columns << QTime::currentTime().msec(); + Q_ASSERT( lines > 0 ); + Q_ASSERT( columns > 0 ); - _screen[0]->resizeImage(lines,columns); - _screen[1]->resizeImage(lines,columns); + _screen[0]->resizeImage(lines,columns); + _screen[1]->resizeImage(lines,columns); - emit imageSizeChanged(lines,columns); + emit imageSizeChanged(lines,columns); - bufferedUpdate(); + bufferedUpdate(); } QSize Emulation::imageSize() { - return QSize(_currentScreen->getColumns(), _currentScreen->getLines()); + return QSize(_currentScreen->getColumns(), _currentScreen->getLines()); } ushort ExtendedCharTable::extendedCharHash(ushort* unicodePoints , ushort length) const { ushort hash = 0; - for ( ushort i = 0 ; i < length ; i++ ) - { + for ( ushort i = 0 ; i < length ; i++ ) { hash = 31*hash + unicodePoints[i]; } return hash; @@ -455,17 +459,16 @@ bool ExtendedCharTable::extendedCharMatch(ushort hash , ushort* unicodePoints , { ushort* entry = extendedCharTable[hash]; - // compare given length with stored sequence length ( given as the first ushort in the - // stored buffer ) - if ( entry == 0 || entry[0] != length ) - return false; + // compare given length with stored sequence length ( given as the first ushort in the + // stored buffer ) + if ( entry == 0 || entry[0] != length ) + return false; // if the lengths match, each character must be checked. the stored buffer starts at // entry[1] - for ( int i = 0 ; i < length ; i++ ) - { + for ( int i = 0 ; i < length ; i++ ) { if ( entry[i+1] != unicodePoints[i] ) - return false; - } + return false; + } return true; } ushort ExtendedCharTable::createExtendedChar(ushort* unicodePoints , ushort length) @@ -474,30 +477,26 @@ ushort ExtendedCharTable::createExtendedChar(ushort* unicodePoints , ushort leng ushort hash = extendedCharHash(unicodePoints,length); // check existing entry for match - while ( extendedCharTable.contains(hash) ) - { - if ( extendedCharMatch(hash,unicodePoints,length) ) - { - // this sequence already has an entry in the table, + while ( extendedCharTable.contains(hash) ) { + if ( extendedCharMatch(hash,unicodePoints,length) ) { + // this sequence already has an entry in the table, // return its hash return hash; - } - else - { + } else { // if hash is already used by another, different sequence of unicode character // points then try next hash hash++; } - } + } - - // add the new sequence to the table and - // return that index + + // add the new sequence to the table and + // return that index ushort* buffer = new ushort[length+1]; buffer[0] = length; for ( int i = 0 ; i < length ; i++ ) - buffer[i+1] = unicodePoints[i]; - + buffer[i+1] = unicodePoints[i]; + extendedCharTable.insert(hash,buffer); return hash; @@ -509,13 +508,10 @@ ushort* ExtendedCharTable::lookupExtendedChar(ushort hash , ushort& length) cons // argument and return a pointer to the character sequence ushort* buffer = extendedCharTable[hash]; - if ( buffer ) - { + if ( buffer ) { length = buffer[0]; return buffer+1; - } - else - { + } else { length = 0; return 0; } @@ -528,8 +524,7 @@ ExtendedCharTable::~ExtendedCharTable() { // free all allocated character buffers QHashIterator iter(extendedCharTable); - while ( iter.hasNext() ) - { + while ( iter.hasNext() ) { iter.next(); delete[] iter.value(); } diff --git a/lib/Emulation.h b/lib/Emulation.h index 2782df7..9cb6bb4 100644 --- a/lib/Emulation.h +++ b/lib/Emulation.h @@ -1,6 +1,6 @@ /* This file is part of Konsole, an X terminal. - + Copyright (C) 2007 by Robert Knight Copyright (C) 1997,1998 by Lars Doelle @@ -28,7 +28,7 @@ // System #include -// Qt +// Qt #include //#include #include @@ -45,56 +45,55 @@ class Screen; class ScreenWindow; class TerminalCharacterDecoder; -/** - * This enum describes the available states which +/** + * This enum describes the available states which * the terminal emulation may be set to. * - * These are the values used by Emulation::stateChanged() + * These are the values used by Emulation::stateChanged() */ -enum -{ +enum { /** The emulation is currently receiving user input. */ - NOTIFYNORMAL=0, - /** + NOTIFYNORMAL=0, + /** * The terminal program has triggered a bell event * to get the user's attention. */ - NOTIFYBELL=1, - /** - * The emulation is currently receiving data from its + NOTIFYBELL=1, + /** + * The emulation is currently receiving data from its * terminal input. */ NOTIFYACTIVITY=2, - // unused here? - NOTIFYSILENCE=3 + // unused here? + NOTIFYSILENCE=3 }; /** * Base class for terminal emulation back-ends. * - * The back-end is responsible for decoding an incoming character stream and + * The back-end is responsible for decoding an incoming character stream and * producing an output image of characters. * * When input from the terminal is received, the receiveData() slot should be called with - * the data which has arrived. The emulation will process the data and update the + * the data which has arrived. The emulation will process the data and update the * screen image accordingly. The codec used to decode the incoming character stream - * into the unicode characters used internally can be specified using setCodec() + * into the unicode characters used internally can be specified using setCodec() * - * The size of the screen image can be specified by calling setImageSize() with the + * The size of the screen image can be specified by calling setImageSize() with the * desired number of lines and columns. When new lines are added, old content - * is moved into a history store, which can be set by calling setHistory(). + * is moved into a history store, which can be set by calling setHistory(). * - * The screen image can be accessed by creating a ScreenWindow onto this emulation - * by calling createWindow(). Screen windows provide access to a section of the - * output. Each screen window covers the same number of lines and columns as the + * The screen image can be accessed by creating a ScreenWindow onto this emulation + * by calling createWindow(). Screen windows provide access to a section of the + * output. Each screen window covers the same number of lines and columns as the * image size returned by imageSize(). The screen window can be moved up and down - * and provides transparent access to both the current on-screen image and the + * and provides transparent access to both the current on-screen image and the * previous output. The screen windows emit an outputChanged signal * when the section of the image they are looking at changes. * Graphical views can then render the contents of a screen window, listening for notifications - * of output changes from the screen window which they are associated with and updating - * accordingly. + * of output changes from the screen window which they are associated with and updating + * accordingly. * * The emulation also is also responsible for converting input from the connected views such * as keypresses and mouse activity into a character string which can be sent @@ -107,9 +106,9 @@ enum * character sequences. The name of the key bindings set used can be specified using * setKeyBindings() * - * The emulation maintains certain state information which changes depending on the - * input received. The emulation can be reset back to its starting state by calling - * reset(). + * The emulation maintains certain state information which changes depending on the + * input received. The emulation can be reset back to its starting state by calling + * reset(). * * The emulation also maintains an activity state, which specifies whether * terminal is currently active ( when data is received ), normal @@ -120,344 +119,348 @@ enum * a 'bell' event in different ways. */ class Emulation : public QObject -{ -Q_OBJECT +{ + Q_OBJECT public: - - /** Constructs a new terminal emulation */ - Emulation(); - ~Emulation(); - /** - * Creates a new window onto the output from this emulation. The contents - * of the window are then rendered by views which are set to use this window using the - * TerminalDisplay::setScreenWindow() method. - */ - ScreenWindow* createWindow(); + /** Constructs a new terminal emulation */ + Emulation(); + ~Emulation(); - /** Returns the size of the screen image which the emulation produces */ - QSize imageSize(); + /** + * Creates a new window onto the output from this emulation. The contents + * of the window are then rendered by views which are set to use this window using the + * TerminalDisplay::setScreenWindow() method. + */ + ScreenWindow* createWindow(); - /** - * Returns the total number of lines, including those stored in the history. - */ - int lineCount(); + /** Returns the size of the screen image which the emulation produces */ + QSize imageSize(); - - /** - * Sets the history store used by this emulation. When new lines - * are added to the output, older lines at the top of the screen are transferred to a history - * store. - * - * The number of lines which are kept and the storage location depend on the - * type of store. - */ - void setHistory(const HistoryType&); - /** Returns the history store used by this emulation. See setHistory() */ - const HistoryType& history(); - /** Clears the history scroll. */ - void clearHistory(); + /** + * Returns the total number of lines, including those stored in the history. + */ + int lineCount(); - /** - * Copies the output history from @p startLine to @p endLine - * into @p stream, using @p decoder to convert the terminal - * characters into text. - * - * @param decoder A decoder which converts lines of terminal characters with - * appearance attributes into output text. PlainTextDecoder is the most commonly - * used decoder. - * @param startLine The first - */ - virtual void writeToStream(TerminalCharacterDecoder* decoder,int startLine,int endLine); - - - /** Returns the codec used to decode incoming characters. See setCodec() */ - const QTextCodec* codec() { return _codec; } - /** Sets the codec used to decode incoming characters. */ - void setCodec(const QTextCodec*); - /** - * Convenience method. - * Returns true if the current codec used to decode incoming - * characters is UTF-8 - */ - bool utf8() { Q_ASSERT(_codec); return _codec->mibEnum() == 106; } - + /** + * Sets the history store used by this emulation. When new lines + * are added to the output, older lines at the top of the screen are transferred to a history + * store. + * + * The number of lines which are kept and the storage location depend on the + * type of store. + */ + void setHistory(const HistoryType&); + /** Returns the history store used by this emulation. See setHistory() */ + const HistoryType& history(); + /** Clears the history scroll. */ + void clearHistory(); - /** TODO Document me */ - virtual char getErase() const; + /** + * Copies the output history from @p startLine to @p endLine + * into @p stream, using @p decoder to convert the terminal + * characters into text. + * + * @param decoder A decoder which converts lines of terminal characters with + * appearance attributes into output text. PlainTextDecoder is the most commonly + * used decoder. + * @param startLine The first + */ + virtual void writeToStream(TerminalCharacterDecoder* decoder,int startLine,int endLine); - /** - * Sets the key bindings used to key events - * ( received through sendKeyEvent() ) into character - * streams to send to the terminal. - */ - void setKeyBindings(const QString& name); - /** - * Returns the name of the emulation's current key bindings. - * See setKeyBindings() - */ - QString keyBindings(); - /** - * Copies the current image into the history and clears the screen. - */ - virtual void clearEntireScreen() =0; + /** Returns the codec used to decode incoming characters. See setCodec() */ + const QTextCodec* codec() { + return _codec; + } + /** Sets the codec used to decode incoming characters. */ + void setCodec(const QTextCodec*); - /** Resets the state of the terminal. */ - virtual void reset() =0; + /** + * Convenience method. + * Returns true if the current codec used to decode incoming + * characters is UTF-8 + */ + bool utf8() { + Q_ASSERT(_codec); + return _codec->mibEnum() == 106; + } - /** - * Returns true if the active terminal program wants - * mouse input events. - * - * The programUsesMouseChanged() signal is emitted when this - * changes. - */ - bool programUsesMouse() const; -public slots: + /** TODO Document me */ + virtual char getErase() const; - /** Change the size of the emulation's image */ - virtual void setImageSize(int lines, int columns); - - /** - * Interprets a sequence of characters and sends the result to the terminal. - * This is equivalent to calling sendKeyEvent() for each character in @p text in succession. - */ - virtual void sendText(const QString& text) = 0; + /** + * Sets the key bindings used to key events + * ( received through sendKeyEvent() ) into character + * streams to send to the terminal. + */ + void setKeyBindings(const QString& name); + /** + * Returns the name of the emulation's current key bindings. + * See setKeyBindings() + */ + QString keyBindings(); - /** - * Interprets a key press event and emits the sendData() signal with - * the resulting character stream. - */ - virtual void sendKeyEvent(QKeyEvent*); - - /** - * Converts information about a mouse event into an xterm-compatible escape - * sequence and emits the character sequence via sendData() - */ - virtual void sendMouseEvent(int buttons, int column, int line, int eventType); - - /** - * Sends a string of characters to the foreground terminal process. - * - * @param string The characters to send. - * @param length Length of @p string or if set to a negative value, @p string will - * be treated as a null-terminated string and its length will be determined automatically. - */ - virtual void sendString(const char* string, int length = -1) = 0; + /** + * Copies the current image into the history and clears the screen. + */ + virtual void clearEntireScreen() =0; - /** - * Processes an incoming stream of characters. receiveData() decodes the incoming - * character buffer using the current codec(), and then calls receiveChar() for - * each unicode character in the resulting buffer. - * - * receiveData() also starts a timer which causes the outputChanged() signal - * to be emitted when it expires. The timer allows multiple updates in quick - * succession to be buffered into a single outputChanged() signal emission. - * - * @param buffer A string of characters received from the terminal program. - * @param len The length of @p buffer - */ - void receiveData(const char* buffer,int len); + /** Resets the state of the terminal. */ + virtual void reset() =0; + + /** + * Returns true if the active terminal program wants + * mouse input events. + * + * The programUsesMouseChanged() signal is emitted when this + * changes. + */ + bool programUsesMouse() const; + +public slots: + + /** Change the size of the emulation's image */ + virtual void setImageSize(int lines, int columns); + + /** + * Interprets a sequence of characters and sends the result to the terminal. + * This is equivalent to calling sendKeyEvent() for each character in @p text in succession. + */ + virtual void sendText(const QString& text) = 0; + + /** + * Interprets a key press event and emits the sendData() signal with + * the resulting character stream. + */ + virtual void sendKeyEvent(QKeyEvent*); + + /** + * Converts information about a mouse event into an xterm-compatible escape + * sequence and emits the character sequence via sendData() + */ + virtual void sendMouseEvent(int buttons, int column, int line, int eventType); + + /** + * Sends a string of characters to the foreground terminal process. + * + * @param string The characters to send. + * @param length Length of @p string or if set to a negative value, @p string will + * be treated as a null-terminated string and its length will be determined automatically. + */ + virtual void sendString(const char* string, int length = -1) = 0; + + /** + * Processes an incoming stream of characters. receiveData() decodes the incoming + * character buffer using the current codec(), and then calls receiveChar() for + * each unicode character in the resulting buffer. + * + * receiveData() also starts a timer which causes the outputChanged() signal + * to be emitted when it expires. The timer allows multiple updates in quick + * succession to be buffered into a single outputChanged() signal emission. + * + * @param buffer A string of characters received from the terminal program. + * @param len The length of @p buffer + */ + void receiveData(const char* buffer,int len); signals: - /** - * Emitted when a buffer of data is ready to send to the - * standard input of the terminal. - * - * @param data The buffer of data ready to be sent - * @paran len The length of @p data in bytes - */ - void sendData(const char* data,int len); + /** + * Emitted when a buffer of data is ready to send to the + * standard input of the terminal. + * + * @param data The buffer of data ready to be sent + * @paran len The length of @p data in bytes + */ + void sendData(const char* data,int len); - /** - * Requests that sending of input to the emulation - * from the terminal process be suspended or resumed. - * - * @param suspend If true, requests that sending of - * input from the terminal process' stdout be - * suspended. Otherwise requests that sending of - * input be resumed. - */ - void lockPtyRequest(bool suspend); + /** + * Requests that sending of input to the emulation + * from the terminal process be suspended or resumed. + * + * @param suspend If true, requests that sending of + * input from the terminal process' stdout be + * suspended. Otherwise requests that sending of + * input be resumed. + */ + void lockPtyRequest(bool suspend); - /** - * Requests that the pty used by the terminal process - * be set to UTF 8 mode. - * - * TODO: More documentation - */ - void useUtf8Request(bool); + /** + * Requests that the pty used by the terminal process + * be set to UTF 8 mode. + * + * TODO: More documentation + */ + void useUtf8Request(bool); - /** - * Emitted when the activity state of the emulation is set. - * - * @param state The new activity state, one of NOTIFYNORMAL, NOTIFYACTIVITY - * or NOTIFYBELL - */ - void stateSet(int state); + /** + * Emitted when the activity state of the emulation is set. + * + * @param state The new activity state, one of NOTIFYNORMAL, NOTIFYACTIVITY + * or NOTIFYBELL + */ + void stateSet(int state); - /** TODO Document me */ - void zmodemDetected(); + /** TODO Document me */ + void zmodemDetected(); - /** - * Requests that the color of the text used - * to represent the tabs associated with this - * emulation be changed. This is a Konsole-specific - * extension from pre-KDE 4 times. - * - * TODO: Document how the parameter works. - */ - void changeTabTextColorRequest(int color); + /** + * Requests that the color of the text used + * to represent the tabs associated with this + * emulation be changed. This is a Konsole-specific + * extension from pre-KDE 4 times. + * + * TODO: Document how the parameter works. + */ + void changeTabTextColorRequest(int color); - /** - * This is emitted when the program running in the shell indicates whether or - * not it is interested in mouse events. - * - * @param usesMouse This will be true if the program wants to be informed about - * mouse events or false otherwise. - */ - void programUsesMouseChanged(bool usesMouse); + /** + * This is emitted when the program running in the shell indicates whether or + * not it is interested in mouse events. + * + * @param usesMouse This will be true if the program wants to be informed about + * mouse events or false otherwise. + */ + void programUsesMouseChanged(bool usesMouse); - /** - * Emitted when the contents of the screen image change. - * The emulation buffers the updates from successive image changes, - * and only emits outputChanged() at sensible intervals when - * there is a lot of terminal activity. - * - * Normally there is no need for objects other than the screen windows - * created with createWindow() to listen for this signal. - * - * ScreenWindow objects created using createWindow() will emit their - * own outputChanged() signal in response to this signal. - */ - void outputChanged(); + /** + * Emitted when the contents of the screen image change. + * The emulation buffers the updates from successive image changes, + * and only emits outputChanged() at sensible intervals when + * there is a lot of terminal activity. + * + * Normally there is no need for objects other than the screen windows + * created with createWindow() to listen for this signal. + * + * ScreenWindow objects created using createWindow() will emit their + * own outputChanged() signal in response to this signal. + */ + void outputChanged(); - /** - * Emitted when the program running in the terminal wishes to update the - * session's title. This also allows terminal programs to customize other - * aspects of the terminal emulation display. - * - * This signal is emitted when the escape sequence "\033]ARG;VALUE\007" - * is received in the input string, where ARG is a number specifying what - * should change and VALUE is a string specifying the new value. - * - * TODO: The name of this method is not very accurate since this method - * is used to perform a whole range of tasks besides just setting - * the user-title of the session. - * - * @param title Specifies what to change. - *
    - *
  • 0 - Set window icon text and session title to @p newTitle
  • - *
  • 1 - Set window icon text to @p newTitle
  • - *
  • 2 - Set session title to @p newTitle
  • - *
  • 11 - Set the session's default background color to @p newTitle, - * where @p newTitle can be an HTML-style string (#RRGGBB) or a named - * color (eg 'red', 'blue'). - * See http://doc.trolltech.com/4.2/qcolor.html#setNamedColor for more - * details. - *
  • - *
  • 31 - Supposedly treats @p newTitle as a URL and opens it (NOT IMPLEMENTED)
  • - *
  • 32 - Sets the icon associated with the session. @p newTitle is the name - * of the icon to use, which can be the name of any icon in the current KDE icon - * theme (eg: 'konsole', 'kate', 'folder_home')
  • - *
- * @param newTitle Specifies the new title - */ + /** + * Emitted when the program running in the terminal wishes to update the + * session's title. This also allows terminal programs to customize other + * aspects of the terminal emulation display. + * + * This signal is emitted when the escape sequence "\033]ARG;VALUE\007" + * is received in the input string, where ARG is a number specifying what + * should change and VALUE is a string specifying the new value. + * + * TODO: The name of this method is not very accurate since this method + * is used to perform a whole range of tasks besides just setting + * the user-title of the session. + * + * @param title Specifies what to change. + *
    + *
  • 0 - Set window icon text and session title to @p newTitle
  • + *
  • 1 - Set window icon text to @p newTitle
  • + *
  • 2 - Set session title to @p newTitle
  • + *
  • 11 - Set the session's default background color to @p newTitle, + * where @p newTitle can be an HTML-style string (#RRGGBB) or a named + * color (eg 'red', 'blue'). + * See http://doc.trolltech.com/4.2/qcolor.html#setNamedColor for more + * details. + *
  • + *
  • 31 - Supposedly treats @p newTitle as a URL and opens it (NOT IMPLEMENTED)
  • + *
  • 32 - Sets the icon associated with the session. @p newTitle is the name + * of the icon to use, which can be the name of any icon in the current KDE icon + * theme (eg: 'konsole', 'kate', 'folder_home')
  • + *
+ * @param newTitle Specifies the new title + */ - void titleChanged(int title,const QString& newTitle); + void titleChanged(int title,const QString& newTitle); - /** - * Emitted when the program running in the terminal changes the - * screen size. - */ - void imageSizeChanged(int lineCount , int columnCount); + /** + * Emitted when the program running in the terminal changes the + * screen size. + */ + void imageSizeChanged(int lineCount , int columnCount); - /** - * Emitted when the terminal program requests to change various properties - * of the terminal display. - * - * A profile change command occurs when a special escape sequence, followed - * by a string containing a series of name and value pairs is received. - * This string can be parsed using a ProfileCommandParser instance. - * - * @param text A string expected to contain a series of key and value pairs in - * the form: name=value;name2=value2 ... - */ - void profileChangeCommandReceived(const QString& text); + /** + * Emitted when the terminal program requests to change various properties + * of the terminal display. + * + * A profile change command occurs when a special escape sequence, followed + * by a string containing a series of name and value pairs is received. + * This string can be parsed using a ProfileCommandParser instance. + * + * @param text A string expected to contain a series of key and value pairs in + * the form: name=value;name2=value2 ... + */ + void profileChangeCommandReceived(const QString& text); protected: - virtual void setMode (int mode) = 0; - virtual void resetMode(int mode) = 0; - - /** - * Processes an incoming character. See receiveData() - * @p ch A unicode character code. - */ - virtual void receiveChar(int ch); + virtual void setMode (int mode) = 0; + virtual void resetMode(int mode) = 0; - /** - * Sets the active screen. The terminal has two screens, primary and alternate. - * The primary screen is used by default. When certain interactive programs such - * as Vim are run, they trigger a switch to the alternate screen. - * - * @param index 0 to switch to the primary screen, or 1 to switch to the alternate screen - */ - void setScreen(int index); + /** + * Processes an incoming character. See receiveData() + * @p ch A unicode character code. + */ + virtual void receiveChar(int ch); - enum EmulationCodec - { - LocaleCodec = 0, - Utf8Codec = 1 - }; - void setCodec(EmulationCodec codec); // codec number, 0 = locale, 1=utf8 + /** + * Sets the active screen. The terminal has two screens, primary and alternate. + * The primary screen is used by default. When certain interactive programs such + * as Vim are run, they trigger a switch to the alternate screen. + * + * @param index 0 to switch to the primary screen, or 1 to switch to the alternate screen + */ + void setScreen(int index); + + enum EmulationCodec { + LocaleCodec = 0, + Utf8Codec = 1 + }; + void setCodec(EmulationCodec codec); // codec number, 0 = locale, 1=utf8 - QList _windows; - - Screen* _currentScreen; // pointer to the screen which is currently active, - // this is one of the elements in the screen[] array + QList _windows; - Screen* _screen[2]; // 0 = primary screen ( used by most programs, including the shell - // scrollbars are enabled in this mode ) - // 1 = alternate ( used by vi , emacs etc. - // scrollbars are not enabled in this mode ) - - - //decodes an incoming C-style character stream into a unicode QString using - //the current text codec. (this allows for rendering of non-ASCII characters in text files etc.) - const QTextCodec* _codec; - QTextDecoder* _decoder; + Screen* _currentScreen; // pointer to the screen which is currently active, + // this is one of the elements in the screen[] array - const KeyboardTranslator* _keyTranslator; // the keyboard layout + Screen* _screen[2]; // 0 = primary screen ( used by most programs, including the shell + // scrollbars are enabled in this mode ) + // 1 = alternate ( used by vi , emacs etc. + // scrollbars are not enabled in this mode ) + + + //decodes an incoming C-style character stream into a unicode QString using + //the current text codec. (this allows for rendering of non-ASCII characters in text files etc.) + const QTextCodec* _codec; + QTextDecoder* _decoder; + + const KeyboardTranslator* _keyTranslator; // the keyboard layout protected slots: - /** - * Schedules an update of attached views. - * Repeated calls to bufferedUpdate() in close succession will result in only a single update, - * much like the Qt buffered update of widgets. - */ - void bufferedUpdate(); + /** + * Schedules an update of attached views. + * Repeated calls to bufferedUpdate() in close succession will result in only a single update, + * much like the Qt buffered update of widgets. + */ + void bufferedUpdate(); -private slots: +private slots: - // triggered by timer, causes the emulation to send an updated screen image to each - // view - void showBulk(); + // triggered by timer, causes the emulation to send an updated screen image to each + // view + void showBulk(); - void usesMouseChanged(bool usesMouse); + void usesMouseChanged(bool usesMouse); private: - bool _usesMouse; - QTimer _bulkTimer1; - QTimer _bulkTimer2; - + bool _usesMouse; + QTimer _bulkTimer1; + QTimer _bulkTimer2; + }; } diff --git a/lib/Filter.cpp b/lib/Filter.cpp index c3f4919..90419e0 100644 --- a/lib/Filter.cpp +++ b/lib/Filter.cpp @@ -46,9 +46,8 @@ using namespace Konsole; FilterChain::~FilterChain() { QMutableListIterator iter(*this); - - while ( iter.hasNext() ) - { + + while ( iter.hasNext() ) { Filter* filter = iter.next(); iter.remove(); delete filter; @@ -92,12 +91,10 @@ void FilterChain::clear() Filter::HotSpot* FilterChain::hotSpotAt(int line , int column) const { QListIterator iter(*this); - while (iter.hasNext()) - { + while (iter.hasNext()) { Filter* filter = iter.next(); Filter::HotSpot* spot = filter->hotSpotAt(line,column); - if ( spot != 0 ) - { + if ( spot != 0 ) { return spot; } } @@ -109,8 +106,7 @@ QList FilterChain::hotSpots() const { QList list; QListIterator iter(*this); - while (iter.hasNext()) - { + while (iter.hasNext()) { Filter* filter = iter.next(); list << filter->hotSpots(); } @@ -119,8 +115,8 @@ QList FilterChain::hotSpots() const //QList FilterChain::hotSpotsAtLine(int line) const; TerminalImageFilterChain::TerminalImageFilterChain() -: _buffer(0) -, _linePositions(0) + : _buffer(0) + , _linePositions(0) { } @@ -143,7 +139,7 @@ void TerminalImageFilterChain::setImage(const Character* const image , int lines PlainTextDecoder decoder; decoder.setTrailingWhitespace(false); - + //qDebug("%s %d", __FILE__, __LINE__); // setup new shared buffers for the filters to process on QString* newBuffer = new QString(); @@ -160,8 +156,7 @@ void TerminalImageFilterChain::setImage(const Character* const image , int lines QTextStream lineStream(_buffer); decoder.begin(&lineStream); - for (int i=0 ; i < lines ; i++) - { + for (int i=0 ; i < lines ; i++) { _linePositions->append(_buffer->length()); decoder.decodeLine(image + i*columns,columns,LINE_DEFAULT); @@ -170,29 +165,28 @@ void TerminalImageFilterChain::setImage(const Character* const image , int lines // being treated as part of a link that occurs at the start of the next line // // the downside is that links which are spread over more than one line are not - // highlighted. + // highlighted. // // TODO - Use the "line wrapped" attribute associated with lines in a // terminal image to avoid adding this imaginary character for wrapped // lines if ( !(lineProperties.value(i,LINE_DEFAULT) & LINE_WRAPPED) ) - lineStream << QChar('\n'); + lineStream << QChar('\n'); } decoder.end(); // qDebug("%s %d", __FILE__, __LINE__); } Filter::Filter() : -_linePositions(0), -_buffer(0) + _linePositions(0), + _buffer(0) { } Filter::~Filter() { QListIterator iter(_hotspotList); - while (iter.hasNext()) - { + while (iter.hasNext()) { delete iter.next(); } } @@ -214,32 +208,27 @@ void Filter::getLineColumn(int position , int& startLine , int& startColumn) Q_ASSERT( _buffer ); - for (int i = 0 ; i < _linePositions->count() ; i++) - { + for (int i = 0 ; i < _linePositions->count() ; i++) { //kDebug() << "line position at " << i << " = " << _linePositions[i]; int nextLine = 0; - if ( i == _linePositions->count()-1 ) - { + if ( i == _linePositions->count()-1 ) { nextLine = _buffer->length() + 1; - } - else - { + } else { nextLine = _linePositions->value(i+1); } - // kDebug() << "pos - " << position << " line pos(" << i<< ") " << _linePositions->value(i) << - // " next = " << nextLine << " buffer len = " << _buffer->length(); + // kDebug() << "pos - " << position << " line pos(" << i<< ") " << _linePositions->value(i) << + // " next = " << nextLine << " buffer len = " << _buffer->length(); - if ( _linePositions->value(i) <= position && position < nextLine ) - { + if ( _linePositions->value(i) <= position && position < nextLine ) { startLine = i; startColumn = position - _linePositions->value(i); return; } } } - + /*void Filter::addLine(const QString& text) { @@ -258,10 +247,9 @@ void Filter::addHotSpot(HotSpot* spot) { _hotspotList << spot; - for (int line = spot->startLine() ; line <= spot->endLine() ; line++) - { + for (int line = spot->startLine() ; line <= spot->endLine() ; line++) { _hotspots.insert(line,spot); - } + } } QList Filter::hotSpots() const { @@ -276,15 +264,14 @@ Filter::HotSpot* Filter::hotSpotAt(int line , int column) const { QListIterator spotIter(_hotspots.values(line)); - while (spotIter.hasNext()) - { + while (spotIter.hasNext()) { HotSpot* spot = spotIter.next(); - + if ( spot->startLine() == line && spot->startColumn() > column ) continue; if ( spot->endLine() == line && spot->endColumn() < column ) continue; - + return spot; } @@ -292,11 +279,11 @@ Filter::HotSpot* Filter::hotSpotAt(int line , int column) const } Filter::HotSpot::HotSpot(int startLine , int startColumn , int endLine , int endColumn) - : _startLine(startLine) - , _startColumn(startColumn) - , _endLine(endLine) - , _endColumn(endColumn) - , _type(NotSpecified) + : _startLine(startLine) + , _startColumn(startColumn) + , _endLine(endLine) + , _endColumn(endColumn) + , _type(NotSpecified) { } QString Filter::HotSpot::tooltip() const @@ -337,7 +324,7 @@ RegExpFilter::RegExpFilter() } RegExpFilter::HotSpot::HotSpot(int startLine,int startColumn,int endLine,int endColumn) - : Filter::HotSpot(startLine,startColumn,endLine,endColumn) + : Filter::HotSpot(startLine,startColumn,endLine,endColumn) { setType(Marker); } @@ -355,7 +342,7 @@ QStringList RegExpFilter::HotSpot::capturedTexts() const return _capturedTexts; } -void RegExpFilter::setRegExp(const QRegExp& regExp) +void RegExpFilter::setRegExp(const QRegExp& regExp) { _searchText = regExp; } @@ -380,21 +367,19 @@ void RegExpFilter::process() if ( _searchText.exactMatch(emptyString) ) return; - while(pos >= 0) - { + while (pos >= 0) { pos = _searchText.indexIn(*text,pos); - if ( pos >= 0 ) - { + if ( pos >= 0 ) { int startLine = 0; int endLine = 0; int startColumn = 0; int endColumn = 0; - + //kDebug() << "pos from " << pos << " to " << pos + _searchText.matchedLength(); - + getLineColumn(pos,startLine,startColumn); getLineColumn(pos + _searchText.matchedLength(),endLine,endColumn); @@ -402,33 +387,33 @@ void RegExpFilter::process() //kDebug() << "end " << endLine << " / " << endColumn; RegExpFilter::HotSpot* spot = newHotSpot(startLine,startColumn, - endLine,endColumn); + endLine,endColumn); spot->setCapturedTexts(_searchText.capturedTexts()); - addHotSpot( spot ); + addHotSpot( spot ); pos += _searchText.matchedLength(); // if matchedLength == 0, the program will get stuck in an infinite loop Q_ASSERT( _searchText.matchedLength() > 0 ); } - } + } } RegExpFilter::HotSpot* RegExpFilter::newHotSpot(int startLine,int startColumn, - int endLine,int endColumn) + int endLine,int endColumn) { return new RegExpFilter::HotSpot(startLine,startColumn, - endLine,endColumn); + endLine,endColumn); } RegExpFilter::HotSpot* UrlFilter::newHotSpot(int startLine,int startColumn,int endLine, - int endColumn) + int endColumn) { return new UrlFilter::HotSpot(startLine,startColumn, - endLine,endColumn); + endLine,endColumn); } UrlFilter::HotSpot::HotSpot(int startLine,int startColumn,int endLine,int endColumn) -: RegExpFilter::HotSpot(startLine,startColumn,endLine,endColumn) -, _urlObject(new FilterObject(this)) + : RegExpFilter::HotSpot(startLine,startColumn,endLine,endColumn) + , _urlObject(new FilterObject(this)) { setType(Link); } @@ -439,16 +424,16 @@ QString UrlFilter::HotSpot::tooltip() const const UrlType kind = urlType(); if ( kind == StandardUrl ) - return QString(); + return QString(); else if ( kind == Email ) - return QString(); + return QString(); else return QString(); } UrlFilter::HotSpot::UrlType UrlFilter::HotSpot::urlType() const { QString url = capturedTexts().first(); - + if ( FullUrlRegExp.exactMatch(url) ) return StandardUrl; else if ( EmailAddressRegExp.exactMatch(url) ) @@ -465,41 +450,35 @@ void UrlFilter::HotSpot::activate(QObject* object) const QString& actionName = object ? object->objectName() : QString(); - if ( actionName == "copy-action" ) - { + if ( actionName == "copy-action" ) { //kDebug() << "Copying url to clipboard:" << url; QApplication::clipboard()->setText(url); return; } - if ( !object || actionName == "open-action" ) - { - if ( kind == StandardUrl ) - { + if ( !object || actionName == "open-action" ) { + if ( kind == StandardUrl ) { // if the URL path does not include the protocol ( eg. "www.kde.org" ) then // prepend http:// ( eg. "www.kde.org" --> "http://www.kde.org" ) - if (!url.contains("://")) - { + if (!url.contains("://")) { url.prepend("http://"); } - } - else if ( kind == Email ) - { + } else if ( kind == Email ) { url.prepend("mailto:"); } - + // new KRun(url,QApplication::activeWindow()); } } -// Note: Altering these regular expressions can have a major effect on the performance of the filters +// Note: Altering these regular expressions can have a major effect on the performance of the filters // used for finding URLs in the text, especially if they are very general and could match very long // pieces of text. // Please be careful when altering them. //regexp matches: -// full url: +// full url: // protocolname:// or www. followed by anything other than whitespaces, <, >, ' or ", and ends before whitespaces, <, >, ', ", ], !, comma and dot const QRegExp UrlFilter::FullUrlRegExp("(www\\.(?!\\.)|[a-z][a-z0-9+.-]*://)[^\\s<>'\"]+[^!,\\.\\s<>'\"\\]]"); // email address: @@ -508,7 +487,7 @@ const QRegExp UrlFilter::EmailAddressRegExp("\\b(\\w|\\.|-)+@(\\w|\\.|-)+\\.\\w+ // matches full url or email address const QRegExp UrlFilter::CompleteUrlRegExp('('+FullUrlRegExp.pattern()+'|'+ - EmailAddressRegExp.pattern()+')'); + EmailAddressRegExp.pattern()+')'); UrlFilter::UrlFilter() { @@ -533,13 +512,10 @@ QList UrlFilter::HotSpot::actions() Q_ASSERT( kind == StandardUrl || kind == Email ); - if ( kind == StandardUrl ) - { + if ( kind == StandardUrl ) { openAction->setText(("Open Link")); copyAction->setText(("Copy Link Address")); - } - else if ( kind == Email ) - { + } else if ( kind == Email ) { openAction->setText(("Send Email To...")); copyAction->setText(("Copy Email Address")); } @@ -556,7 +532,7 @@ QList UrlFilter::HotSpot::actions() list << openAction; list << copyAction; - return list; + return list; } //#include "moc_Filter.cpp" diff --git a/lib/Filter.h b/lib/Filter.h index 06ea5e3..f15f23f 100644 --- a/lib/Filter.h +++ b/lib/Filter.h @@ -46,7 +46,7 @@ namespace Konsole * activate() method should be called. Depending on the type of hotspot this will trigger a suitable response. * * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser. - * Hotspots may have more than one action, in which case the list of actions can be obtained using the + * Hotspots may have more than one action, in which case the list of actions can be obtained using the * actions() method. * * Different subclasses of filter will return different types of hotspot. @@ -66,76 +66,75 @@ public: * activate() method should be called. Depending on the type of hotspot this will trigger a suitable response. * * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser. - * Hotspots may have more than one action, in which case the list of actions can be obtained using the - * actions() method. These actions may then be displayed in a popup menu or toolbar for example. + * Hotspots may have more than one action, in which case the list of actions can be obtained using the + * actions() method. These actions may then be displayed in a popup menu or toolbar for example. */ class HotSpot { public: - /** - * Constructs a new hotspot which covers the area from (@p startLine,@p startColumn) to (@p endLine,@p endColumn) - * in a block of text. - */ - HotSpot(int startLine , int startColumn , int endLine , int endColumn); - virtual ~HotSpot(); + /** + * Constructs a new hotspot which covers the area from (@p startLine,@p startColumn) to (@p endLine,@p endColumn) + * in a block of text. + */ + HotSpot(int startLine , int startColumn , int endLine , int endColumn); + virtual ~HotSpot(); - enum Type - { + enum Type { // the type of the hotspot is not specified NotSpecified, // this hotspot represents a clickable link Link, // this hotspot represents a marker Marker - }; + }; - /** Returns the line when the hotspot area starts */ - int startLine() const; - /** Returns the line where the hotspot area ends */ - int endLine() const; - /** Returns the column on startLine() where the hotspot area starts */ - int startColumn() const; - /** Returns the column on endLine() where the hotspot area ends */ - int endColumn() const; - /** - * Returns the type of the hotspot. This is usually used as a hint for views on how to represent - * the hotspot graphically. eg. Link hotspots are typically underlined when the user mouses over them - */ - Type type() const; - /** - * Causes the an action associated with a hotspot to be triggered. - * - * @param object The object which caused the hotspot to be triggered. This is - * typically null ( in which case the default action should be performed ) or - * one of the objects from the actions() list. In which case the associated - * action should be performed. - */ - virtual void activate(QObject* object = 0) = 0; - /** - * Returns a list of actions associated with the hotspot which can be used in a - * menu or toolbar - */ - virtual QList actions(); + /** Returns the line when the hotspot area starts */ + int startLine() const; + /** Returns the line where the hotspot area ends */ + int endLine() const; + /** Returns the column on startLine() where the hotspot area starts */ + int startColumn() const; + /** Returns the column on endLine() where the hotspot area ends */ + int endColumn() const; + /** + * Returns the type of the hotspot. This is usually used as a hint for views on how to represent + * the hotspot graphically. eg. Link hotspots are typically underlined when the user mouses over them + */ + Type type() const; + /** + * Causes the an action associated with a hotspot to be triggered. + * + * @param object The object which caused the hotspot to be triggered. This is + * typically null ( in which case the default action should be performed ) or + * one of the objects from the actions() list. In which case the associated + * action should be performed. + */ + virtual void activate(QObject* object = 0) = 0; + /** + * Returns a list of actions associated with the hotspot which can be used in a + * menu or toolbar + */ + virtual QList actions(); - /** - * Returns the text of a tooltip to be shown when the mouse moves over the hotspot, or - * an empty string if there is no tooltip associated with this hotspot. - * - * The default implementation returns an empty string. - */ - virtual QString tooltip() const; + /** + * Returns the text of a tooltip to be shown when the mouse moves over the hotspot, or + * an empty string if there is no tooltip associated with this hotspot. + * + * The default implementation returns an empty string. + */ + virtual QString tooltip() const; protected: - /** Sets the type of a hotspot. This should only be set once */ - void setType(Type type); + /** Sets the type of a hotspot. This should only be set once */ + void setType(Type type); private: - int _startLine; - int _startColumn; - int _endLine; - int _endColumn; - Type _type; - + int _startLine; + int _startColumn; + int _endLine; + int _endColumn; + Type _type; + }; /** Constructs a new filter. */ @@ -145,9 +144,9 @@ public: /** Causes the filter to process the block of text currently in its internal buffer */ virtual void process() = 0; - /** + /** * Empties the filters internal buffer and resets the line count back to 0. - * All hotspots are deleted. + * All hotspots are deleted. */ void reset(); @@ -163,7 +162,7 @@ public: /** Returns the list of hotspots identified by the filter which occur on a given line */ QList hotSpotsAtLine(int line) const; - /** + /** * TODO: Document me */ void setBuffer(const QString* buffer , const QList* linePositions); @@ -179,22 +178,22 @@ protected: private: QMultiHash _hotspots; QList _hotspotList; - + const QList* _linePositions; const QString* _buffer; }; -/** - * A filter which searches for sections of text matching a regular expression and creates a new RegExpFilter::HotSpot +/** + * A filter which searches for sections of text matching a regular expression and creates a new RegExpFilter::HotSpot * instance for them. * * Subclasses can reimplement newHotSpot() to return custom hotspot types when matches for the regular expression - * are found. + * are found. */ class RegExpFilter : public Filter { public: - /** + /** * Type of hotspot created by RegExpFilter. The capturedTexts() method can be used to find the text * matched by the filter's regular expression. */ @@ -215,31 +214,31 @@ public: /** Constructs a new regular expression filter */ RegExpFilter(); - /** - * Sets the regular expression which the filter searches for in blocks of text. + /** + * Sets the regular expression which the filter searches for in blocks of text. * * Regular expressions which match the empty string are treated as not matching - * anything. + * anything. */ void setRegExp(const QRegExp& text); /** Returns the regular expression which the filter searches for in blocks of text */ QRegExp regExp() const; - /** - * Reimplemented to search the filter's text buffer for text matching regExp() + /** + * Reimplemented to search the filter's text buffer for text matching regExp() * * If regexp matches the empty string, then process() will return immediately - * without finding results. + * without finding results. */ virtual void process(); protected: - /** + /** * Called when a match for the regular expression is encountered. Subclasses should reimplement this * to return custom hotspot types */ virtual RegExpFilter::HotSpot* newHotSpot(int startLine,int startColumn, - int endLine,int endColumn); + int endLine,int endColumn); private: QRegExp _searchText; @@ -248,14 +247,14 @@ private: class FilterObject; /** A filter which matches URLs in blocks of text */ -class UrlFilter : public RegExpFilter +class UrlFilter : public RegExpFilter { public: - /** - * Hotspot type created by UrlFilter instances. The activate() method opens a web browser + /** + * Hotspot type created by UrlFilter instances. The activate() method opens a web browser * at the given URL when called. */ - class HotSpot : public RegExpFilter::HotSpot + class HotSpot : public RegExpFilter::HotSpot { public: HotSpot(int startLine,int startColumn,int endLine,int endColumn); @@ -263,7 +262,7 @@ public: virtual QList actions(); - /** + /** * Open a web browser at the current URL. The url itself can be determined using * the capturedTexts() method. */ @@ -271,8 +270,7 @@ public: virtual QString tooltip() const; private: - enum UrlType - { + enum UrlType { StandardUrl, Email, Unknown @@ -288,17 +286,17 @@ protected: virtual RegExpFilter::HotSpot* newHotSpot(int,int,int,int); private: - + static const QRegExp FullUrlRegExp; static const QRegExp EmailAddressRegExp; // combined OR of FullUrlRegExp and EmailAddressRegExp - static const QRegExp CompleteUrlRegExp; + static const QRegExp CompleteUrlRegExp; }; class FilterObject : public QObject { -Q_OBJECT + Q_OBJECT public: FilterObject(Filter::HotSpot* filter) : _filter(filter) {} private slots: @@ -307,11 +305,11 @@ private: Filter::HotSpot* _filter; }; -/** - * A chain which allows a group of filters to be processed as one. +/** + * A chain which allows a group of filters to be processed as one. * The chain owns the filters added to it and deletes them when the chain itself is destroyed. * - * Use addFilter() to add a new filter to the chain. + * Use addFilter() to add a new filter to the chain. * When new text to be filtered arrives, use addLine() to add each additional * line of text which needs to be processed and then after adding the last line, use * process() to cause each filter in the chain to process the text. @@ -341,12 +339,12 @@ public: /** Resets each filter in the chain */ void reset(); /** - * Processes each filter in the chain + * Processes each filter in the chain */ void process(); /** Sets the buffer for each filter in the chain to process. */ - void setBuffer(const QString* buffer , const QList* linePositions); + void setBuffer(const QString* buffer , const QList* linePositions); /** Returns the first hotspot which occurs at @p line, @p column or 0 if no hotspot was found */ Filter::HotSpot* hotSpotAt(int line , int column) const; @@ -372,7 +370,7 @@ public: * @param columns The number of columns in the terminal image */ void setImage(const Character* const image , int lines , int columns, - const QVector& lineProperties); + const QVector& lineProperties); private: QString* _buffer; diff --git a/lib/History.cpp b/lib/History.cpp index 1e3d721..f6c34fd 100644 --- a/lib/History.cpp +++ b/lib/History.cpp @@ -84,21 +84,20 @@ FIXME: There is noticeable decrease in speed, also. Perhaps, */ HistoryFile::HistoryFile() - : ion(-1), - length(0), - fileMap(0) + : ion(-1), + length(0), + fileMap(0) { - if (tmpFile.open()) - { - tmpFile.setAutoRemove(true); - ion = tmpFile.handle(); - } + if (tmpFile.open()) { + tmpFile.setAutoRemove(true); + ion = tmpFile.handle(); + } } HistoryFile::~HistoryFile() { - if (fileMap) - unmap(); + if (fileMap) + unmap(); } //TODO: Mapping the entire file in will cause problems if the history file becomes exceedingly large, @@ -106,75 +105,87 @@ HistoryFile::~HistoryFile() //to avoid this. void HistoryFile::map() { - assert( fileMap == 0 ); + assert( fileMap == 0 ); - fileMap = (char*)mmap( 0 , length , PROT_READ , MAP_PRIVATE , ion , 0 ); + fileMap = (char*)mmap( 0 , length , PROT_READ , MAP_PRIVATE , ion , 0 ); //if mmap'ing fails, fall back to the read-lseek combination - if ( fileMap == MAP_FAILED ) - { - readWriteBalance = 0; - fileMap = 0; - qDebug() << ": mmap'ing history failed. errno = " << errno; + if ( fileMap == MAP_FAILED ) { + readWriteBalance = 0; + fileMap = 0; + qDebug() << ": mmap'ing history failed. errno = " << errno; } } void HistoryFile::unmap() { - int result = munmap( fileMap , length ); - assert( result == 0 ); + int result = munmap( fileMap , length ); + assert( result == 0 ); - fileMap = 0; + fileMap = 0; } bool HistoryFile::isMapped() { - return (fileMap != 0); + return (fileMap != 0); } void HistoryFile::add(const unsigned char* bytes, int len) { - if ( fileMap ) - unmap(); - - readWriteBalance++; + if ( fileMap ) + unmap(); - int rc = 0; + readWriteBalance++; - 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; + 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) { - //count number of get() calls vs. number of add() calls. - //If there are many more get() calls compared with add() - //calls (decided by using MAP_THRESHOLD) then mmap the log - //file to improve performance. - readWriteBalance--; - if ( !fileMap && readWriteBalance < MAP_THRESHOLD ) - map(); + //count number of get() calls vs. number of add() calls. + //If there are many more get() calls compared with add() + //calls (decided by using MAP_THRESHOLD) then mmap the log + //file to improve performance. + readWriteBalance--; + if ( !fileMap && readWriteBalance < MAP_THRESHOLD ) + map(); - if ( fileMap ) - { - for (int i=0;i 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; } - } + 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; + return length; } @@ -182,23 +193,23 @@ int HistoryFile::len() HistoryScroll::HistoryScroll(HistoryType* t) - : m_histType(t) + : m_histType(t) { } HistoryScroll::~HistoryScroll() { - delete m_histType; + delete m_histType; } bool HistoryScroll::hasScroll() { - return true; + 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 @@ -210,82 +221,81 @@ bool HistoryScroll::hasScroll() */ HistoryScrollFile::HistoryScrollFile(const QString &logFileName) - : HistoryScroll(new HistoryTypeFile(logFileName)), - m_logFileName(logFileName) + : HistoryScroll(new HistoryTypeFile(logFileName)), + m_logFileName(logFileName) { } HistoryScrollFile::~HistoryScrollFile() { } - + int HistoryScrollFile::getLines() { - return index.len() / sizeof(int); + return index.len() / sizeof(int); } int HistoryScrollFile::getLineLen(int lineno) { - return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(Character); + return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(Character); } 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; + 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()) - { - - if (!index.isMapped()) - index.map(); - - int res; - index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int)); - return res; + if (lineno <= 0) return 0; + if (lineno <= getLines()) { + + if (!index.isMapped()) + index.map(); + + int res; + index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int)); + return res; } - return cells.len(); + return cells.len(); } void HistoryScrollFile::getCells(int lineno, int colno, int count, Character res[]) { - cells.get((unsigned char*)res,count*sizeof(Character),startOfLine(lineno)+colno*sizeof(Character)); + cells.get((unsigned char*)res,count*sizeof(Character),startOfLine(lineno)+colno*sizeof(Character)); } void HistoryScrollFile::addCells(const Character text[], int count) { - cells.add((unsigned char*)text,count*sizeof(Character)); + cells.add((unsigned char*)text,count*sizeof(Character)); } void HistoryScrollFile::addLine(bool previousWrapped) { - if (index.isMapped()) - index.unmap(); + if (index.isMapped()) + index.unmap(); - 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)); + 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 maxLineCount) - : HistoryScroll(new HistoryTypeBuffer(maxLineCount)) - ,_historyBuffer() - ,_maxLineCount(0) - ,_usedLines(0) - ,_head(0) + : HistoryScroll(new HistoryTypeBuffer(maxLineCount)) + ,_historyBuffer() + ,_maxLineCount(0) + ,_usedLines(0) + ,_head(0) { - setMaxNbLines(maxLineCount); + setMaxNbLines(maxLineCount); } HistoryScrollBuffer::~HistoryScrollBuffer() @@ -299,8 +309,7 @@ void HistoryScrollBuffer::addCellsVector(const QVector& cells) if ( _usedLines < _maxLineCount ) _usedLines++; - if ( _head >= _maxLineCount ) - { + if ( _head >= _maxLineCount ) { _head = 0; } @@ -309,10 +318,10 @@ void HistoryScrollBuffer::addCellsVector(const QVector& cells) } void HistoryScrollBuffer::addCells(const Character a[], int count) { - HistoryLine newLine(count); - qCopy(a,a+count,newLine.begin()); + HistoryLine newLine(count); + qCopy(a,a+count,newLine.begin()); - addCellsVector(newLine); + addCellsVector(newLine); } void HistoryScrollBuffer::addLine(bool previousWrapped) @@ -327,64 +336,57 @@ int HistoryScrollBuffer::getLines() int HistoryScrollBuffer::getLineLen(int lineNumber) { - Q_ASSERT( lineNumber >= 0 && lineNumber < _maxLineCount ); + Q_ASSERT( lineNumber >= 0 && lineNumber < _maxLineCount ); - if ( lineNumber < _usedLines ) - { - return _historyBuffer[bufferIndex(lineNumber)].size(); - } - else - { - return 0; - } + if ( lineNumber < _usedLines ) { + return _historyBuffer[bufferIndex(lineNumber)].size(); + } else { + return 0; + } } bool HistoryScrollBuffer::isWrappedLine(int lineNumber) { - Q_ASSERT( lineNumber >= 0 && lineNumber < _maxLineCount ); - - if (lineNumber < _usedLines) - { - //kDebug() << "Line" << lineNumber << "wrapped is" << _wrappedLine[bufferIndex(lineNumber)]; - return _wrappedLine[bufferIndex(lineNumber)]; - } - else - return false; + Q_ASSERT( lineNumber >= 0 && lineNumber < _maxLineCount ); + + if (lineNumber < _usedLines) { + //kDebug() << "Line" << lineNumber << "wrapped is" << _wrappedLine[bufferIndex(lineNumber)]; + return _wrappedLine[bufferIndex(lineNumber)]; + } else + return false; } void HistoryScrollBuffer::getCells(int lineNumber, int startColumn, int count, Character* buffer) { - if ( count == 0 ) return; + if ( count == 0 ) return; - Q_ASSERT( lineNumber < _maxLineCount ); + Q_ASSERT( lineNumber < _maxLineCount ); - if (lineNumber >= _usedLines) - { - memset(buffer, 0, count * sizeof(Character)); - return; - } - - const HistoryLine& line = _historyBuffer[bufferIndex(lineNumber)]; + if (lineNumber >= _usedLines) { + memset(buffer, 0, count * sizeof(Character)); + return; + } - //kDebug() << "startCol " << startColumn; - //kDebug() << "line.size() " << line.size(); - //kDebug() << "count " << count; + const HistoryLine& line = _historyBuffer[bufferIndex(lineNumber)]; - Q_ASSERT( startColumn <= line.size() - count ); - - memcpy(buffer, line.constData() + startColumn , count * sizeof(Character)); + //kDebug() << "startCol " << startColumn; + //kDebug() << "line.size() " << line.size(); + //kDebug() << "count " << count; + + Q_ASSERT( startColumn <= line.size() - count ); + + memcpy(buffer, line.constData() + startColumn , count * sizeof(Character)); } void HistoryScrollBuffer::setMaxNbLines(unsigned int lineCount) { HistoryLine* oldBuffer = _historyBuffer; HistoryLine* newBuffer = new HistoryLine[lineCount]; - - for ( int i = 0 ; i < qMin(_usedLines,(int)lineCount) ; i++ ) - { + + for ( int i = 0 ; i < qMin(_usedLines,(int)lineCount) ; i++ ) { newBuffer[i] = oldBuffer[bufferIndex(i)]; } - + _usedLines = qMin(_usedLines,(int)lineCount); _maxLineCount = lineCount; _head = ( _usedLines == _maxLineCount ) ? 0 : _usedLines-1; @@ -401,12 +403,9 @@ int HistoryScrollBuffer::bufferIndex(int lineNumber) Q_ASSERT( lineNumber < _maxLineCount ); Q_ASSERT( (_usedLines == _maxLineCount) || lineNumber <= _head ); - if ( _usedLines == _maxLineCount ) - { + if ( _usedLines == _maxLineCount ) { return (_head+lineNumber+1) % _maxLineCount; - } - else - { + } else { return lineNumber; } } @@ -415,7 +414,7 @@ int HistoryScrollBuffer::bufferIndex(int lineNumber) // History Scroll None ////////////////////////////////////// HistoryScrollNone::HistoryScrollNone() - : HistoryScroll(new HistoryTypeNone()) + : HistoryScroll(new HistoryTypeNone()) { } @@ -425,22 +424,22 @@ HistoryScrollNone::~HistoryScrollNone() bool HistoryScrollNone::hasScroll() { - return false; + return false; } int HistoryScrollNone::getLines() { - return 0; + return 0; } int HistoryScrollNone::getLineLen(int) { - return 0; + return 0; } bool HistoryScrollNone::isWrappedLine(int /*lineno*/) { - return false; + return false; } void HistoryScrollNone::getCells(int, int, int, Character []) @@ -458,9 +457,9 @@ void HistoryScrollNone::addLine(bool) // History Scroll BlockArray ////////////////////////////////////// HistoryScrollBlockArray::HistoryScrollBlockArray(size_t size) - : HistoryScroll(new HistoryTypeBlockArray(size)) + : HistoryScroll(new HistoryTypeBlockArray(size)) { - m_blockArray.setHistorySize(size); // nb. of lines. + m_blockArray.setHistorySize(size); // nb. of lines. } HistoryScrollBlockArray::~HistoryScrollBlockArray() @@ -469,7 +468,7 @@ HistoryScrollBlockArray::~HistoryScrollBlockArray() int HistoryScrollBlockArray::getLines() { - return m_lineLengths.count(); + return m_lineLengths.count(); } int HistoryScrollBlockArray::getLineLen(int lineno) @@ -482,44 +481,44 @@ int HistoryScrollBlockArray::getLineLen(int lineno) bool HistoryScrollBlockArray::isWrappedLine(int /*lineno*/) { - return false; + return false; } void HistoryScrollBlockArray::getCells(int lineno, int colno, int count, Character res[]) { - if (!count) return; + if (!count) return; - const Block *b = m_blockArray.at(lineno); + const Block *b = m_blockArray.at(lineno); - if (!b) { - memset(res, 0, count * sizeof(Character)); // still better than random data - return; - } + if (!b) { + memset(res, 0, count * sizeof(Character)); // still better than random data + return; + } - assert(((colno + count) * sizeof(Character)) < ENTRIES); - memcpy(res, b->data + (colno * sizeof(Character)), count * sizeof(Character)); + assert(((colno + count) * sizeof(Character)) < ENTRIES); + memcpy(res, b->data + (colno * sizeof(Character)), count * sizeof(Character)); } void HistoryScrollBlockArray::addCells(const Character a[], int count) { - Block *b = m_blockArray.lastBlock(); - - if (!b) return; + Block *b = m_blockArray.lastBlock(); - // put cells in block's data - assert((count * sizeof(Character)) < ENTRIES); + if (!b) return; - memset(b->data, 0, ENTRIES); + // put cells in block's data + assert((count * sizeof(Character)) < ENTRIES); - memcpy(b->data, a, count * sizeof(Character)); - b->size = count * sizeof(Character); + memset(b->data, 0, ENTRIES); - size_t res = m_blockArray.newBlock(); - assert (res > 0); - Q_UNUSED( res ); + memcpy(b->data, a, count * sizeof(Character)); + b->size = count * sizeof(Character); - m_lineLengths.insert(m_blockArray.getCurrent(), count); + size_t res = m_blockArray.newBlock(); + assert (res > 0); + Q_UNUSED( res ); + + m_lineLengths.insert(m_blockArray.getCurrent(), count); } void HistoryScrollBlockArray::addLine(bool) @@ -546,153 +545,143 @@ HistoryTypeNone::HistoryTypeNone() bool HistoryTypeNone::isEnabled() const { - return false; + return false; } HistoryScroll* HistoryTypeNone::scroll(HistoryScroll *old) const { - delete old; - return new HistoryScrollNone(); + delete old; + return new HistoryScrollNone(); } int HistoryTypeNone::maximumLineCount() const { - return 0; + return 0; } ////////////////////////////// HistoryTypeBlockArray::HistoryTypeBlockArray(size_t size) - : m_size(size) + : m_size(size) { } bool HistoryTypeBlockArray::isEnabled() const { - return true; + return true; } int HistoryTypeBlockArray::maximumLineCount() const { - return m_size; + return m_size; } HistoryScroll* HistoryTypeBlockArray::scroll(HistoryScroll *old) const { - delete old; - return new HistoryScrollBlockArray(m_size); + delete old; + return new HistoryScrollBlockArray(m_size); } ////////////////////////////// HistoryTypeBuffer::HistoryTypeBuffer(unsigned int nbLines) - : m_nbLines(nbLines) + : m_nbLines(nbLines) { } bool HistoryTypeBuffer::isEnabled() const { - return true; + return true; } int HistoryTypeBuffer::maximumLineCount() const { - return m_nbLines; + return m_nbLines; } HistoryScroll* HistoryTypeBuffer::scroll(HistoryScroll *old) const { - if (old) - { - HistoryScrollBuffer *oldBuffer = dynamic_cast(old); - if (oldBuffer) - { - oldBuffer->setMaxNbLines(m_nbLines); - return oldBuffer; - } + if (old) { + HistoryScrollBuffer *oldBuffer = dynamic_cast(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; + HistoryScroll *newScroll = new HistoryScrollBuffer(m_nbLines); + int lines = old->getLines(); + int startLine = 0; + if (lines > (int) m_nbLines) + startLine = lines - m_nbLines; - Character line[LINE_SIZE]; - for(int i = startLine; i < lines; i++) - { - int size = old->getLineLen(i); - if (size > LINE_SIZE) - { - Character *tmp_line = new Character[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)); - } + Character line[LINE_SIZE]; + for (int i = startLine; i < lines; i++) { + int size = old->getLineLen(i); + if (size > LINE_SIZE) { + Character *tmp_line = new Character[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; } - delete old; - return newScroll; - } - return new HistoryScrollBuffer(m_nbLines); + return new HistoryScrollBuffer(m_nbLines); } ////////////////////////////// HistoryTypeFile::HistoryTypeFile(const QString& fileName) - : m_fileName(fileName) + : m_fileName(fileName) { } bool HistoryTypeFile::isEnabled() const { - return true; + return true; } const QString& HistoryTypeFile::getFileName() const { - return m_fileName; + return m_fileName; } HistoryScroll* HistoryTypeFile::scroll(HistoryScroll *old) const { - if (dynamic_cast(old)) - return old; // Unchanged. + if (dynamic_cast(old)) + return old; // Unchanged. - HistoryScroll *newScroll = new HistoryScrollFile(m_fileName); + HistoryScroll *newScroll = new HistoryScrollFile(m_fileName); - Character line[LINE_SIZE]; - int lines = (old != 0) ? old->getLines() : 0; - for(int i = 0; i < lines; i++) - { - int size = old->getLineLen(i); - if (size > LINE_SIZE) - { - Character *tmp_line = new Character[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)); - } - } + Character line[LINE_SIZE]; + int lines = (old != 0) ? old->getLines() : 0; + for (int i = 0; i < lines; i++) { + int size = old->getLineLen(i); + if (size > LINE_SIZE) { + Character *tmp_line = new Character[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; + delete old; + return newScroll; } int HistoryTypeFile::maximumLineCount() const { - return 0; + return 0; } diff --git a/lib/History.h b/lib/History.h index a26a367..bb3c4cd 100644 --- a/lib/History.h +++ b/lib/History.h @@ -43,37 +43,37 @@ namespace Konsole class HistoryFile { public: - HistoryFile(); - virtual ~HistoryFile(); + 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(); + virtual void add(const unsigned char* bytes, int len); + virtual void get(unsigned char* bytes, int len, int loc); + virtual int len(); - //mmaps the file in read-only mode - void map(); - //un-mmaps the file - void unmap(); - //returns true if the file is mmap'ed - bool isMapped(); + //mmaps the file in read-only mode + void map(); + //un-mmaps the file + void unmap(); + //returns true if the file is mmap'ed + bool isMapped(); private: - int ion; - int length; - QTemporaryFile tmpFile; + int ion; + int length; + QTemporaryFile tmpFile; - //pointer to start of mmap'ed file data, or 0 if the file is not mmap'ed - char* fileMap; - - //incremented whenver 'add' is called and decremented whenever - //'get' is called. - //this is used to detect when a large number of lines are being read and processed from the history - //and automatically mmap the file for better performance (saves the overhead of many lseek-read calls). - int readWriteBalance; + //pointer to start of mmap'ed file data, or 0 if the file is not mmap'ed + char* fileMap; - //when readWriteBalance goes below this threshold, the file will be mmap'ed automatically - static const int MAP_THRESHOLD = -1000; + //incremented whenver 'add' is called and decremented whenever + //'get' is called. + //this is used to detect when a large number of lines are being read and processed from the history + //and automatically mmap the file for better performance (saves the overhead of many lseek-read calls). + int readWriteBalance; + + //when readWriteBalance goes below this threshold, the file will be mmap'ed automatically + static const int MAP_THRESHOLD = -1000; }; #endif @@ -87,40 +87,45 @@ class HistoryType; class HistoryScroll { public: - HistoryScroll(HistoryType*); - virtual ~HistoryScroll(); + HistoryScroll(HistoryType*); + virtual ~HistoryScroll(); - virtual bool hasScroll(); + 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, Character res[]) = 0; - virtual bool isWrappedLine(int lineno) = 0; + // access to history + virtual int getLines() = 0; + virtual int getLineLen(int lineno) = 0; + virtual void getCells(int lineno, int colno, int count, Character res[]) = 0; + virtual bool isWrappedLine(int lineno) = 0; - // backward compatibility (obsolete) - Character getCell(int lineno, int colno) { Character res; getCells(lineno,colno,1,&res); return res; } + // backward compatibility (obsolete) + Character getCell(int lineno, int colno) { + Character res; + getCells(lineno,colno,1,&res); + return res; + } - // adding lines. - virtual void addCells(const Character a[], int count) = 0; - // convenience method - this is virtual so that subclasses can take advantage - // of QVector's implicit copying - virtual void addCellsVector(const QVector& cells) - { - addCells(cells.data(),cells.size()); - } + // adding lines. + virtual void addCells(const Character a[], int count) = 0; + // convenience method - this is virtual so that subclasses can take advantage + // of QVector's implicit copying + virtual void addCellsVector(const QVector& cells) { + addCells(cells.data(),cells.size()); + } - virtual void addLine(bool previousWrapped=false) = 0; + virtual void addLine(bool previousWrapped=false) = 0; - // - // FIXME: Passing around constant references to HistoryType instances - // is very unsafe, because those references will no longer - // be valid if the history scroll is deleted. - // - const HistoryType& getType() { return *m_histType; } + // + // FIXME: Passing around constant references to HistoryType instances + // is very unsafe, because those references will no longer + // be valid if the history scroll is deleted. + // + const HistoryType& getType() { + return *m_histType; + } protected: - HistoryType* m_histType; + HistoryType* m_histType; }; @@ -133,24 +138,24 @@ protected: class HistoryScrollFile : public HistoryScroll { public: - HistoryScrollFile(const QString &logFileName); - virtual ~HistoryScrollFile(); + HistoryScrollFile(const QString &logFileName); + virtual ~HistoryScrollFile(); - virtual int getLines(); - virtual int getLineLen(int lineno); - virtual void getCells(int lineno, int colno, int count, Character res[]); - virtual bool isWrappedLine(int lineno); + virtual int getLines(); + virtual int getLineLen(int lineno); + virtual void getCells(int lineno, int colno, int count, Character res[]); + virtual bool isWrappedLine(int lineno); - virtual void addCells(const Character a[], int count); - virtual void addLine(bool previousWrapped=false); + virtual void addCells(const Character a[], int count); + virtual void addLine(bool previousWrapped=false); private: - int startOfLine(int lineno); + int startOfLine(int lineno); - QString m_logFileName; - HistoryFile index; // lines Row(int) - HistoryFile cells; // text Row(Character) - HistoryFile lineflags; // flags Row(unsigned char) + QString m_logFileName; + HistoryFile index; // lines Row(int) + HistoryFile cells; // text Row(Character) + HistoryFile lineflags; // flags Row(unsigned char) }; @@ -160,39 +165,41 @@ private: class HistoryScrollBuffer : public HistoryScroll { public: - typedef QVector HistoryLine; + typedef QVector HistoryLine; - HistoryScrollBuffer(unsigned int maxNbLines = 1000); - virtual ~HistoryScrollBuffer(); + HistoryScrollBuffer(unsigned int maxNbLines = 1000); + virtual ~HistoryScrollBuffer(); - virtual int getLines(); - virtual int getLineLen(int lineno); - virtual void getCells(int lineno, int colno, int count, Character res[]); - virtual bool isWrappedLine(int lineno); + virtual int getLines(); + virtual int getLineLen(int lineno); + virtual void getCells(int lineno, int colno, int count, Character res[]); + virtual bool isWrappedLine(int lineno); - virtual void addCells(const Character a[], int count); - virtual void addCellsVector(const QVector& cells); - virtual void addLine(bool previousWrapped=false); + virtual void addCells(const Character a[], int count); + virtual void addCellsVector(const QVector& cells); + virtual void addLine(bool previousWrapped=false); + + void setMaxNbLines(unsigned int nbLines); + unsigned int maxNbLines() { + return _maxLineCount; + } - void setMaxNbLines(unsigned int nbLines); - unsigned int maxNbLines() { return _maxLineCount; } - private: - int bufferIndex(int lineNumber); + int bufferIndex(int lineNumber); - HistoryLine* _historyBuffer; - QBitArray _wrappedLine; - int _maxLineCount; - int _usedLines; - int _head; - - //QVector m_histBuffer; - //QBitArray m_wrappedLine; - //unsigned int m_maxNbLines; - //unsigned int m_nbLines; - //unsigned int m_arrayIndex; - //bool m_buffFilled; + HistoryLine* _historyBuffer; + QBitArray _wrappedLine; + int _maxLineCount; + int _usedLines; + int _head; + + //QVector m_histBuffer; + //QBitArray m_wrappedLine; + //unsigned int m_maxNbLines; + //unsigned int m_nbLines; + //unsigned int m_arrayIndex; + //bool m_buffFilled; }; /*class HistoryScrollBufferV2 : public HistoryScroll @@ -217,18 +224,18 @@ public: class HistoryScrollNone : public HistoryScroll { public: - HistoryScrollNone(); - virtual ~HistoryScrollNone(); + HistoryScrollNone(); + virtual ~HistoryScrollNone(); - virtual bool hasScroll(); + virtual bool hasScroll(); - virtual int getLines(); - virtual int getLineLen(int lineno); - virtual void getCells(int lineno, int colno, int count, Character res[]); - virtual bool isWrappedLine(int lineno); + virtual int getLines(); + virtual int getLineLen(int lineno); + virtual void getCells(int lineno, int colno, int count, Character res[]); + virtual bool isWrappedLine(int lineno); - virtual void addCells(const Character a[], int count); - virtual void addLine(bool previousWrapped=false); + virtual void addCells(const Character a[], int count); + virtual void addLine(bool previousWrapped=false); }; ////////////////////////////////////////////////////////////////////// @@ -237,20 +244,20 @@ public: class HistoryScrollBlockArray : public HistoryScroll { public: - HistoryScrollBlockArray(size_t size); - virtual ~HistoryScrollBlockArray(); + HistoryScrollBlockArray(size_t size); + virtual ~HistoryScrollBlockArray(); - virtual int getLines(); - virtual int getLineLen(int lineno); - virtual void getCells(int lineno, int colno, int count, Character res[]); - virtual bool isWrappedLine(int lineno); + virtual int getLines(); + virtual int getLineLen(int lineno); + virtual void getCells(int lineno, int colno, int count, Character res[]); + virtual bool isWrappedLine(int lineno); - virtual void addCells(const Character a[], int count); - virtual void addLine(bool previousWrapped=false); + virtual void addCells(const Character a[], int count); + virtual void addLine(bool previousWrapped=false); protected: - BlockArray m_blockArray; - QHash m_lineLengths; + BlockArray m_blockArray; + QHash m_lineLengths; }; ////////////////////////////////////////////////////////////////////// @@ -260,81 +267,83 @@ protected: class HistoryType { public: - HistoryType(); - virtual ~HistoryType(); + HistoryType(); + virtual ~HistoryType(); - /** - * Returns true if the history is enabled ( can store lines of output ) - * or false otherwise. - */ - virtual bool isEnabled() const = 0; - /** - * Returns true if the history size is unlimited. - */ - bool isUnlimited() const { return maximumLineCount() == 0; } - /** - * Returns the maximum number of lines which this history type - * can store or 0 if the history can store an unlimited number of lines. - */ - virtual int maximumLineCount() const = 0; + /** + * Returns true if the history is enabled ( can store lines of output ) + * or false otherwise. + */ + virtual bool isEnabled() const = 0; + /** + * Returns true if the history size is unlimited. + */ + bool isUnlimited() const { + return maximumLineCount() == 0; + } + /** + * Returns the maximum number of lines which this history type + * can store or 0 if the history can store an unlimited number of lines. + */ + virtual int maximumLineCount() const = 0; - virtual HistoryScroll* scroll(HistoryScroll *) const = 0; + virtual HistoryScroll* scroll(HistoryScroll *) const = 0; }; class HistoryTypeNone : public HistoryType { public: - HistoryTypeNone(); + HistoryTypeNone(); - virtual bool isEnabled() const; - virtual int maximumLineCount() const; + virtual bool isEnabled() const; + virtual int maximumLineCount() const; - virtual HistoryScroll* scroll(HistoryScroll *) const; + virtual HistoryScroll* scroll(HistoryScroll *) const; }; class HistoryTypeBlockArray : public HistoryType { public: - HistoryTypeBlockArray(size_t size); - - virtual bool isEnabled() const; - virtual int maximumLineCount() const; + HistoryTypeBlockArray(size_t size); - virtual HistoryScroll* scroll(HistoryScroll *) const; + virtual bool isEnabled() const; + virtual int maximumLineCount() const; + + virtual HistoryScroll* scroll(HistoryScroll *) const; protected: - size_t m_size; + size_t m_size; }; -#if 1 +#if 1 class HistoryTypeFile : public HistoryType { public: - HistoryTypeFile(const QString& fileName=QString()); + HistoryTypeFile(const QString& fileName=QString()); - virtual bool isEnabled() const; - virtual const QString& getFileName() const; - virtual int maximumLineCount() const; + virtual bool isEnabled() const; + virtual const QString& getFileName() const; + virtual int maximumLineCount() const; - virtual HistoryScroll* scroll(HistoryScroll *) const; + virtual HistoryScroll* scroll(HistoryScroll *) const; protected: - QString m_fileName; + QString m_fileName; }; class HistoryTypeBuffer : public HistoryType { public: - HistoryTypeBuffer(unsigned int nbLines); - - virtual bool isEnabled() const; - virtual int maximumLineCount() const; + HistoryTypeBuffer(unsigned int nbLines); - virtual HistoryScroll* scroll(HistoryScroll *) const; + virtual bool isEnabled() const; + virtual int maximumLineCount() const; + + virtual HistoryScroll* scroll(HistoryScroll *) const; protected: - unsigned int m_nbLines; + unsigned int m_nbLines; }; #endif diff --git a/lib/KeyboardTranslator.cpp b/lib/KeyboardTranslator.cpp index b8c053e..6cd0fc2 100644 --- a/lib/KeyboardTranslator.cpp +++ b/lib/KeyboardTranslator.cpp @@ -50,12 +50,12 @@ using namespace Konsole; //; //and this is default now translator - default.keytab from original Konsole -const char* KeyboardTranslatorManager::defaultTranslatorText = +const char* KeyboardTranslatorManager::defaultTranslatorText = #include "ExtendedDefaultTranslator.h" -; + ; KeyboardTranslatorManager::KeyboardTranslatorManager() - : _haveLoadedAll(false) + : _haveLoadedAll(false) { } KeyboardTranslatorManager::~KeyboardTranslatorManager() @@ -73,22 +73,21 @@ void KeyboardTranslatorManager::findTranslators() filters << "*.keytab"; dir.setNameFilters(filters); QStringList list = dir.entryList(filters); //(".keytab"); // = KGlobal::dirs()->findAllResources("data", - // "konsole/*.keytab", - // KStandardDirs::NoDuplicates); + // "konsole/*.keytab", + // KStandardDirs::NoDuplicates); list = dir.entryList(filters); // add the name of each translator to the list and associated // the name with a null pointer to indicate that the translator // has not yet been loaded from disk QStringListIterator listIter(list); - while (listIter.hasNext()) - { + while (listIter.hasNext()) { QString translatorPath = listIter.next(); QString name = QFileInfo(translatorPath).baseName(); - + if ( !_translators.contains(name) ) { _translators.insert(name,0); - } + } } _haveLoadedAll = true; } @@ -98,7 +97,7 @@ const KeyboardTranslator* KeyboardTranslatorManager::findTranslator(const QStrin if ( name.isEmpty() ) return defaultTranslator(); -//here was smth wrong in original Konsole source +//here was smth wrong in original Konsole source findTranslators(); if ( _translators.contains(name) && _translators[name] != 0 ) { @@ -123,11 +122,10 @@ bool KeyboardTranslatorManager::saveTranslator(const KeyboardTranslator* transla qDebug() << "Saving translator to" << path; QFile destination(path); - - if (!destination.open(QIODevice::WriteOnly | QIODevice::Text)) - { - qWarning() << "Unable to save keyboard translation:" - << destination.errorString(); + + if (!destination.open(QIODevice::WriteOnly | QIODevice::Text)) { + qWarning() << "Unable to save keyboard translation:" + << destination.errorString(); return false; } @@ -135,7 +133,7 @@ bool KeyboardTranslatorManager::saveTranslator(const KeyboardTranslator* transla { KeyboardTranslatorWriter writer(&destination); writer.writeHeader(translator->description()); - + QListIterator iter(translator->entries()); while ( iter.hasNext() ) writer.writeEntry(iter.next()); @@ -150,8 +148,8 @@ KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(const QString& nam { const QString& path = findTranslatorPath(name); - QFile source(path); - + QFile source(path); + if (name.isEmpty() || !source.open(QIODevice::ReadOnly | QIODevice::Text)) return 0; @@ -175,26 +173,23 @@ KeyboardTranslator* KeyboardTranslatorManager::loadTranslator(QIODevice* source, KeyboardTranslator* translator = new KeyboardTranslator(name); KeyboardTranslatorReader reader(source); translator->setDescription( reader.description() ); - + while ( reader.hasNextEntry() ) { translator->addEntry(reader.nextEntry()); - } + } source->close(); - if ( !reader.parseError() ) - { + if ( !reader.parseError() ) { return translator; - } - else - { + } else { delete translator; return 0; } } KeyboardTranslatorWriter::KeyboardTranslatorWriter(QIODevice* destination) -: _destination(destination) + : _destination(destination) { Q_ASSERT( destination && destination->isWritable() ); @@ -230,7 +225,7 @@ void KeyboardTranslatorWriter::writeEntry( const KeyboardTranslator::Entry& entr // KeySequence begins with the name of the key ( taken from the Qt::Key enum ) // and is followed by the keyboard modifiers and state flags ( with + or - in front // of each modifier or flag to indicate whether it is required ). All keyboard modifiers -// and flags are optional, if a particular modifier or state is not specified it is +// and flags are optional, if a particular modifier or state is not specified it is // assumed not to be a part of the sequence. The key sequence may contain whitespace // // eg: "key Up+Shift : scrollLineUp" @@ -241,30 +236,26 @@ void KeyboardTranslatorWriter::writeEntry( const KeyboardTranslator::Entry& entr // KeyboardTranslatorReader::KeyboardTranslatorReader( QIODevice* source ) - : _source(source) - , _hasNext(false) + : _source(source) + , _hasNext(false) { - // read input until we find the description - while ( _description.isEmpty() && !source->atEnd() ) - { + // read input until we find the description + while ( _description.isEmpty() && !source->atEnd() ) { const QList& tokens = tokenize( QString(source->readLine()) ); - - if ( !tokens.isEmpty() && tokens.first().type == Token::TitleKeyword ) - { + + if ( !tokens.isEmpty() && tokens.first().type == Token::TitleKeyword ) { _description = (tokens[1].text.toUtf8()); } - } + } - readNext(); + readNext(); } -void KeyboardTranslatorReader::readNext() +void KeyboardTranslatorReader::readNext() { // find next entry - while ( !_source->atEnd() ) - { + while ( !_source->atEnd() ) { const QList& tokens = tokenize( QString(_source->readLine()) ); - if ( !tokens.isEmpty() && tokens.first().type == Token::KeyKeyword ) - { + if ( !tokens.isEmpty() && tokens.first().type == Token::KeyKeyword ) { KeyboardTranslator::States flags = KeyboardTranslator::NoState; KeyboardTranslator::States flagMask = KeyboardTranslator::NoState; Qt::KeyboardModifiers modifiers = Qt::NoModifier; @@ -277,21 +268,18 @@ void KeyboardTranslatorReader::readNext() modifiers, modifierMask, flags, - flagMask); + flagMask); KeyboardTranslator::Command command = KeyboardTranslator::NoCommand; QByteArray text; // get text or command - if ( tokens[2].type == Token::OutputText ) - { + if ( tokens[2].type == Token::OutputText ) { text = tokens[2].text.toLocal8Bit(); - } - else if ( tokens[2].type == Token::Command ) - { + } else if ( tokens[2].type == Token::Command ) { // identify command - if (!parseAsCommand(tokens[2].text,command)) - qWarning() << "Command" << tokens[2].text << "not understood."; + if (!parseAsCommand(tokens[2].text,command)) + qWarning() << "Command" << tokens[2].text << "not understood."; } KeyboardTranslator::Entry newEntry; @@ -309,15 +297,15 @@ void KeyboardTranslatorReader::readNext() return; } - } + } _hasNext = false; } -bool KeyboardTranslatorReader::parseAsCommand(const QString& text,KeyboardTranslator::Command& command) +bool KeyboardTranslatorReader::parseAsCommand(const QString& text,KeyboardTranslator::Command& command) { - if ( text.compare("erase",Qt::CaseInsensitive) == 0 ) - command = KeyboardTranslator::EraseCommand; + if ( text.compare("erase",Qt::CaseInsensitive) == 0 ) + command = KeyboardTranslator::EraseCommand; else if ( text.compare("scrollpageup",Qt::CaseInsensitive) == 0 ) command = KeyboardTranslator::ScrollPageUpCommand; else if ( text.compare("scrollpagedown",Qt::CaseInsensitive) == 0 ) @@ -329,19 +317,19 @@ bool KeyboardTranslatorReader::parseAsCommand(const QString& text,KeyboardTransl else if ( text.compare("scrolllock",Qt::CaseInsensitive) == 0 ) command = KeyboardTranslator::ScrollLockCommand; else - return false; + return false; - return true; + return true; } bool KeyboardTranslatorReader::decodeSequence(const QString& text, - int& keyCode, - Qt::KeyboardModifiers& modifiers, - Qt::KeyboardModifiers& modifierMask, - KeyboardTranslator::States& flags, - KeyboardTranslator::States& flagMask) + int& keyCode, + Qt::KeyboardModifiers& modifiers, + Qt::KeyboardModifiers& modifierMask, + KeyboardTranslator::States& flags, + KeyboardTranslator::States& flagMask) { - bool isWanted = true; + bool isWanted = true; bool endOfItem = false; QString buffer; @@ -350,39 +338,32 @@ bool KeyboardTranslatorReader::decodeSequence(const QString& text, KeyboardTranslator::States tempFlags = flags; KeyboardTranslator::States tempFlagMask = flagMask; - for ( int i = 0 ; i < text.count() ; i++ ) - { + for ( int i = 0 ; i < text.count() ; i++ ) { const QChar& ch = text[i]; bool isLastLetter = ( i == text.count()-1 ); endOfItem = true; - if ( ch.isLetterOrNumber() ) - { + if ( ch.isLetterOrNumber() ) { endOfItem = false; buffer.append(ch); } - if ( (endOfItem || isLastLetter) && !buffer.isEmpty() ) - { + if ( (endOfItem || isLastLetter) && !buffer.isEmpty() ) { Qt::KeyboardModifier itemModifier = Qt::NoModifier; int itemKeyCode = 0; KeyboardTranslator::State itemFlag = KeyboardTranslator::NoState; - if ( parseAsModifier(buffer,itemModifier) ) - { + if ( parseAsModifier(buffer,itemModifier) ) { tempModifierMask |= itemModifier; if ( isWanted ) tempModifiers |= itemModifier; - } - else if ( parseAsStateFlag(buffer,itemFlag) ) - { + } else if ( parseAsStateFlag(buffer,itemFlag) ) { tempFlagMask |= itemFlag; if ( isWanted ) tempFlags |= itemFlag; - } - else if ( parseAsKeyCode(buffer,itemKeyCode) ) + } else if ( parseAsKeyCode(buffer,itemKeyCode) ) keyCode = itemKeyCode; else qDebug() << "Unable to parse key binding item:" << buffer; @@ -390,13 +371,13 @@ bool KeyboardTranslatorReader::decodeSequence(const QString& text, buffer.clear(); } - // check if this is a wanted / not-wanted flag and update the + // check if this is a wanted / not-wanted flag and update the // state ready for the next item if ( ch == '+' ) - isWanted = true; + isWanted = true; else if ( ch == '-' ) - isWanted = false; - } + isWanted = false; + } modifiers = tempModifiers; modifierMask = tempModifierMask; @@ -416,8 +397,8 @@ bool KeyboardTranslatorReader::parseAsModifier(const QString& item , Qt::Keyboar modifier = Qt::AltModifier; else if ( item == "meta" ) modifier = Qt::MetaModifier; - else if ( item == "keypad" ) - modifier = Qt::KeypadModifier; + else if ( item == "keypad" ) + modifier = Qt::KeypadModifier; else return false; @@ -443,12 +424,10 @@ bool KeyboardTranslatorReader::parseAsStateFlag(const QString& item , KeyboardTr bool KeyboardTranslatorReader::parseAsKeyCode(const QString& item , int& keyCode) { QKeySequence sequence = QKeySequence::fromString(item); - if ( !sequence.isEmpty() ) - { + if ( !sequence.isEmpty() ) { keyCode = sequence[0]; - if ( sequence.count() > 1 ) - { + if ( sequence.count() > 1 ) { qDebug() << "Unhandled key codes in sequence: " << item; } } @@ -471,21 +450,21 @@ bool KeyboardTranslatorReader::hasNextEntry() { return _hasNext; } -KeyboardTranslator::Entry KeyboardTranslatorReader::createEntry( const QString& condition , - const QString& result ) +KeyboardTranslator::Entry KeyboardTranslatorReader::createEntry( const QString& condition , + const QString& result ) { QString entryString("keyboard \"temporary\"\nkey "); entryString.append(condition); entryString.append(" : "); - // if 'result' is the name of a command then the entry result will be that command, - // otherwise the result will be treated as a string to echo when the key sequence - // specified by 'condition' is pressed - KeyboardTranslator::Command command; - if (parseAsCommand(result,command)) - entryString.append(result); - else - entryString.append('\"' + result + '\"'); + // if 'result' is the name of a command then the entry result will be that command, + // otherwise the result will be treated as a string to echo when the key sequence + // specified by 'condition' is pressed + KeyboardTranslator::Command command; + if (parseAsCommand(result,command)) + entryString.append(result); + else + entryString.append('\"' + result + '\"'); QByteArray array = entryString.toUtf8(); @@ -501,7 +480,7 @@ KeyboardTranslator::Entry KeyboardTranslatorReader::createEntry( const QString& return entry; } -KeyboardTranslator::Entry KeyboardTranslatorReader::nextEntry() +KeyboardTranslator::Entry KeyboardTranslatorReader::nextEntry() { Q_ASSERT( _hasNext ); @@ -530,50 +509,40 @@ QList KeyboardTranslatorReader::tokenize(const QList list; - if ( text.isEmpty() || comment.exactMatch(text) ) - { + if ( text.isEmpty() || comment.exactMatch(text) ) { return list; } - if ( title.exactMatch(text) ) - { + if ( title.exactMatch(text) ) { Token titleToken = { Token::TitleKeyword , QString() }; Token textToken = { Token::TitleText , title.capturedTexts()[1] }; - + list << titleToken << textToken; - } - else if ( key.exactMatch(text) ) - { + } else if ( key.exactMatch(text) ) { Token keyToken = { Token::KeyKeyword , QString() }; Token sequenceToken = { Token::KeySequence , key.capturedTexts()[1].remove(' ') }; list << keyToken << sequenceToken; - if ( key.capturedTexts()[3].isEmpty() ) - { + if ( key.capturedTexts()[3].isEmpty() ) { // capturedTexts()[2] is a command Token commandToken = { Token::Command , key.capturedTexts()[2] }; - list << commandToken; - } - else - { + list << commandToken; + } else { // capturedTexts()[3] is the output string - Token outputToken = { Token::OutputText , key.capturedTexts()[3] }; - list << outputToken; - } - } - else - { + Token outputToken = { Token::OutputText , key.capturedTexts()[3] }; + list << outputToken; + } + } else { qWarning() << "Line in keyboard translator file could not be understood:" << text; } return list; } -QList KeyboardTranslatorManager::allTranslators() +QList KeyboardTranslatorManager::allTranslators() { - if ( !_haveLoadedAll ) - { + if ( !_haveLoadedAll ) { findTranslators(); } @@ -581,12 +550,12 @@ QList KeyboardTranslatorManager::allTranslators() } KeyboardTranslator::Entry::Entry() -: _keyCode(0) -, _modifiers(Qt::NoModifier) -, _modifierMask(Qt::NoModifier) -, _state(NoState) -, _stateMask(NoState) -, _command(NoCommand) + : _keyCode(0) + , _modifiers(Qt::NoModifier) + , _modifierMask(Qt::NoModifier) + , _state(NoState) + , _stateMask(NoState) + , _command(NoCommand) { } @@ -601,14 +570,14 @@ bool KeyboardTranslator::Entry::operator==(const Entry& rhs) const _text == rhs._text; } -bool KeyboardTranslator::Entry::matches(int keyCode , +bool KeyboardTranslator::Entry::matches(int keyCode , Qt::KeyboardModifiers modifiers, States state) const { if ( _keyCode != keyCode ) return false; - if ( (modifiers & _modifierMask) != (_modifiers & _modifierMask) ) + if ( (modifiers & _modifierMask) != (_modifiers & _modifierMask) ) return false; // if modifiers is non-zero, the 'any modifier' state is implicit @@ -618,14 +587,13 @@ bool KeyboardTranslator::Entry::matches(int keyCode , if ( (state & _stateMask) != (_state & _stateMask) ) return false; - // special handling for the 'Any Modifier' state, which checks for the presence of + // special handling for the 'Any Modifier' state, which checks for the presence of // any or no modifiers. In this context, the 'keypad' modifier does not count. bool anyModifiersSet = modifiers != 0 && modifiers != Qt::KeypadModifier; - if ( _stateMask & KeyboardTranslator::AnyModifierState ) - { + if ( _stateMask & KeyboardTranslator::AnyModifierState ) { // test fails if any modifier is required but none are set if ( (_state & KeyboardTranslator::AnyModifierState) && !anyModifiersSet ) - return false; + return false; // test fails if no modifier is allowed but one or more are set if ( !(_state & KeyboardTranslator::AnyModifierState) && anyModifiersSet ) @@ -638,31 +606,39 @@ QByteArray KeyboardTranslator::Entry::escapedText(bool expandWildCards,Qt::Keybo { QByteArray result(text(expandWildCards,modifiers)); - for ( int i = 0 ; i < result.count() ; i++ ) - { + for ( int i = 0 ; i < result.count() ; i++ ) { char ch = result[i]; char replacement = 0; - switch ( ch ) - { - case 27 : replacement = 'E'; break; - case 8 : replacement = 'b'; break; - case 12 : replacement = 'f'; break; - case 9 : replacement = 't'; break; - case 13 : replacement = 'r'; break; - case 10 : replacement = 'n'; break; - default: - // any character which is not printable is replaced by an equivalent - // \xhh escape sequence (where 'hh' are the corresponding hex digits) - if ( !QChar(ch).isPrint() ) - replacement = 'x'; + switch ( ch ) { + case 27 : + replacement = 'E'; + break; + case 8 : + replacement = 'b'; + break; + case 12 : + replacement = 'f'; + break; + case 9 : + replacement = 't'; + break; + case 13 : + replacement = 'r'; + break; + case 10 : + replacement = 'n'; + break; + default: + // any character which is not printable is replaced by an equivalent + // \xhh escape sequence (where 'hh' are the corresponding hex digits) + if ( !QChar(ch).isPrint() ) + replacement = 'x'; } - if ( replacement == 'x' ) - { - result.replace(i,1,"\\x"+QByteArray(1,ch).toInt(0, 16)); - } else if ( replacement != 0 ) - { + if ( replacement == 'x' ) { + result.replace(i,1,"\\x"+QByteArray(1,ch).toInt(0, 16)); + } else if ( replacement != 0 ) { result.remove(i,1); result.insert(i,'\\'); result.insert(i+1,replacement); @@ -675,53 +651,61 @@ QByteArray KeyboardTranslator::Entry::unescape(const QByteArray& input) const { QByteArray result(input); - for ( int i = 0 ; i < result.count()-1 ; i++ ) - { + for ( int i = 0 ; i < result.count()-1 ; i++ ) { QByteRef ch = result[i]; - if ( ch == '\\' ) - { - char replacement[2] = {0,0}; - int charsToRemove = 2; - bool escapedChar = true; + if ( ch == '\\' ) { + char replacement[2] = {0,0}; + int charsToRemove = 2; + bool escapedChar = true; - switch ( result[i+1] ) - { - case 'E' : replacement[0] = 27; break; - case 'b' : replacement[0] = 8 ; break; - case 'f' : replacement[0] = 12; break; - case 't' : replacement[0] = 9 ; break; - case 'r' : replacement[0] = 13; break; - case 'n' : replacement[0] = 10; break; - case 'x' : - { - // format is \xh or \xhh where 'h' is a hexadecimal - // digit from 0-9 or A-F which should be replaced - // with the corresponding character value - char hexDigits[3] = {0}; + switch ( result[i+1] ) { + case 'E' : + replacement[0] = 27; + break; + case 'b' : + replacement[0] = 8 ; + break; + case 'f' : + replacement[0] = 12; + break; + case 't' : + replacement[0] = 9 ; + break; + case 'r' : + replacement[0] = 13; + break; + case 'n' : + replacement[0] = 10; + break; + case 'x' : { + // format is \xh or \xhh where 'h' is a hexadecimal + // digit from 0-9 or A-F which should be replaced + // with the corresponding character value + char hexDigits[3] = {0}; - if ( (i < result.count()-2) && isxdigit(result[i+2]) ) - hexDigits[0] = result[i+2]; - if ( (i < result.count()-3) && isxdigit(result[i+3]) ) - hexDigits[1] = result[i+3]; + if ( (i < result.count()-2) && isxdigit(result[i+2]) ) + hexDigits[0] = result[i+2]; + if ( (i < result.count()-3) && isxdigit(result[i+3]) ) + hexDigits[1] = result[i+3]; - int charValue = 0; - sscanf(hexDigits,"%x",&charValue); - - replacement[0] = (char)charValue; + int charValue = 0; + sscanf(hexDigits,"%x",&charValue); - charsToRemove = 2 + strlen(hexDigits); - } - break; - default: - escapedChar = false; - } + replacement[0] = (char)charValue; - if ( escapedChar ) - result.replace(i,charsToRemove,replacement); + charsToRemove = 2 + strlen(hexDigits); + } + break; + default: + escapedChar = false; + } + + if ( escapedChar ) + result.replace(i,charsToRemove,replacement); } } - + return result; } @@ -743,8 +727,8 @@ void KeyboardTranslator::Entry::insertModifier( QString& item , int modifier ) c item += "Alt"; else if ( modifier == Qt::MetaModifier ) item += "Meta"; - else if ( modifier == Qt::KeypadModifier ) - item += "KeyPad"; + else if ( modifier == Qt::KeypadModifier ) + item += "KeyPad"; } void KeyboardTranslator::Entry::insertState( QString& item , int state ) const { @@ -771,8 +755,8 @@ QString KeyboardTranslator::Entry::resultToString(bool expandWildCards,Qt::Keybo { if ( !_text.isEmpty() ) return escapedText(expandWildCards,modifiers); - else if ( _command == EraseCommand ) - return "Erase"; + else if ( _command == EraseCommand ) + return "Erase"; else if ( _command == ScrollPageUpCommand ) return "ScrollPageUp"; else if ( _command == ScrollPageDownCommand ) @@ -794,7 +778,7 @@ QString KeyboardTranslator::Entry::conditionToString() const insertModifier( result , Qt::ShiftModifier ); insertModifier( result , Qt::ControlModifier ); insertModifier( result , Qt::AltModifier ); - insertModifier( result , Qt::MetaModifier ); + insertModifier( result , Qt::MetaModifier ); // add states insertState( result , KeyboardTranslator::AlternateScreenState ); @@ -807,11 +791,11 @@ QString KeyboardTranslator::Entry::conditionToString() const } KeyboardTranslator::KeyboardTranslator(const QString& name) -: _name(name) + : _name(name) { } -void KeyboardTranslator::setDescription(const QString& description) +void KeyboardTranslator::setDescription(const QString& description) { _description = description; } @@ -850,26 +834,22 @@ void KeyboardTranslator::removeEntry(const Entry& entry) } KeyboardTranslator::Entry KeyboardTranslator::findEntry(int keyCode, Qt::KeyboardModifiers modifiers, States state) const { - if ( _entries.contains(keyCode) ) - { + if ( _entries.contains(keyCode) ) { QList entriesForKey = _entries.values(keyCode); - + QListIterator iter(entriesForKey); - while (iter.hasNext()) - { + while (iter.hasNext()) { const Entry& next = iter.next(); if ( next.matches(keyCode,modifiers,state) ) return next; } return Entry(); // entry not found - } - else - { + } else { return Entry(); } - + } void KeyboardTranslatorManager::addTranslator(KeyboardTranslator* translator) { @@ -877,7 +857,7 @@ void KeyboardTranslatorManager::addTranslator(KeyboardTranslator* translator) if ( !saveTranslator(translator) ) qWarning() << "Unable to save translator" << translator->name() - << "to disk."; + << "to disk."; } bool KeyboardTranslatorManager::deleteTranslator(const QString& name) { @@ -885,13 +865,10 @@ bool KeyboardTranslatorManager::deleteTranslator(const QString& name) // locate and delete QString path = findTranslatorPath(name); - if ( QFile::remove(path) ) - { + if ( QFile::remove(path) ) { _translators.remove(name); - return true; - } - else - { + return true; + } else { qWarning() << "Failed to remove translator - " << path; return false; } diff --git a/lib/KeyboardTranslator.h b/lib/KeyboardTranslator.h index e0082ae..bbe584b 100644 --- a/lib/KeyboardTranslator.h +++ b/lib/KeyboardTranslator.h @@ -42,10 +42,12 @@ typedef void (*CleanUpFunction)(); */ class CleanUpGlobalStatic { - public: - CleanUpFunction func; +public: + CleanUpFunction func; - inline ~CleanUpGlobalStatic() { func(); } + inline ~CleanUpGlobalStatic() { + func(); + } }; @@ -102,8 +104,8 @@ static struct K_GLOBAL_STATIC_STRUCT_NAME(NAME) \ delete x; \ } \ } NAME; - - + + @@ -113,7 +115,7 @@ class QTextStream; namespace Konsole { -/** +/** * A convertor which maps between key sequences pressed by the user and the * character strings which should be sent to the terminal and commands * which should be invoked when those character sequences are pressed. @@ -129,7 +131,7 @@ namespace Konsole class KeyboardTranslator { public: - /** + /** * The meaning of a particular key sequence may depend upon the state which * the terminal emulation is in. Therefore findEntry() may return a different * Entry depending upon the state flags supplied. @@ -137,15 +139,14 @@ public: * This enum describes the states which may be associated with with a particular * entry in the keyboard translation entry. */ - enum State - { + enum State { /** Indicates that no special state is active */ NoState = 0, /** * TODO More documentation */ NewLineState = 1, - /** + /** * Indicates that the terminal is in 'Ansi' mode. * TODO: More documentation */ @@ -156,10 +157,10 @@ public: CursorKeysState = 4, /** * Indicates that the alternate screen ( typically used by interactive programs - * such as screen or vim ) is active + * such as screen or vim ) is active */ AlternateScreenState = 8, - /** Indicates that any of the modifier keys is active. */ + /** Indicates that any of the modifier keys is active. */ AnyModifierState = 16 }; Q_DECLARE_FLAGS(States,State) @@ -167,8 +168,7 @@ public: /** * This enum describes commands which are associated with particular key sequences. */ - enum Command - { + enum Command { /** Indicates that no command is associated with this command sequence */ NoCommand = 0, /** TODO Document me */ @@ -183,8 +183,8 @@ public: ScrollLineDownCommand = 16, /** Toggles scroll lock mode */ ScrollLockCommand = 32, - /** Echos the operating system specific erase character. */ - EraseCommand = 64 + /** Echos the operating system specific erase character. */ + EraseCommand = 64 }; Q_DECLARE_FLAGS(Commands,Command) @@ -196,14 +196,14 @@ public: class Entry { public: - /** + /** * Constructs a new entry for a keyboard translator. */ Entry(); - /** + /** * Returns true if this entry is null. - * This is true for newly constructed entries which have no properties set. + * This is true for newly constructed entries which have no properties set. */ bool isNull() const; @@ -212,15 +212,15 @@ public: /** Sets the command associated with this entry. */ void setCommand(Command command); - /** - * Returns the character sequence associated with this entry, optionally replacing + /** + * Returns the character sequence associated with this entry, optionally replacing * wildcard '*' characters with numbers to indicate the keyboard modifiers being pressed. * * TODO: The numbers used to replace '*' characters are taken from the Konsole/KDE 3 code. - * Document them. + * Document them. * * @param expandWildCards Specifies whether wild cards (occurrences of the '*' character) in - * the entry should be replaced with a number to indicate the modifier keys being pressed. + * the entry should be replaced with a number to indicate the modifier keys being pressed. * * @param modifiers The keyboard modifiers being pressed. */ @@ -230,7 +230,7 @@ public: /** Sets the character sequence associated with this entry */ void setText(const QByteArray& text); - /** + /** * Returns the character sequence associated with this entry, * with any non-printable characters replaced with escape sequences. * @@ -247,13 +247,13 @@ public: /** Sets the character code associated with this entry */ void setKeyCode(int keyCode); - /** - * Returns a bitwise-OR of the enabled keyboard modifiers associated with this entry. + /** + * Returns a bitwise-OR of the enabled keyboard modifiers associated with this entry. * If a modifier is set in modifierMask() but not in modifiers(), this means that the entry * only matches when that modifier is NOT pressed. * * If a modifier is not set in modifierMask() then the entry matches whether the modifier - * is pressed or not. + * is pressed or not. */ Qt::KeyboardModifiers modifiers() const; @@ -265,13 +265,13 @@ public: /** See modifierMask() and modifiers() */ void setModifierMask( Qt::KeyboardModifiers modifiers ); - /** - * Returns a bitwise-OR of the enabled state flags associated with this entry. - * If flag is set in stateMask() but not in state(), this means that the entry only + /** + * Returns a bitwise-OR of the enabled state flags associated with this entry. + * If flag is set in stateMask() but not in state(), this means that the entry only * matches when the terminal is NOT in that state. * * If a state is not set in stateMask() then the entry matches whether the terminal - * is in that state or not. + * is in that state or not. */ States state() const; @@ -283,13 +283,13 @@ public: /** See stateMask() */ void setStateMask( States mask ); - /** - * Returns the key code and modifiers associated with this entry + /** + * Returns the key code and modifiers associated with this entry * as a QKeySequence */ //QKeySequence keySequence() const; - /** + /** * Returns this entry's conditions ( ie. its key code, modifier and state criteria ) * as a string. */ @@ -305,16 +305,16 @@ public: QString resultToString(bool expandWildCards = false, Qt::KeyboardModifiers modifiers = Qt::NoModifier) const; - /** + /** * Returns true if this entry matches the given key sequence, specified * as a combination of @p keyCode , @p modifiers and @p state. */ - bool matches( int keyCode , - Qt::KeyboardModifiers modifiers , + bool matches( int keyCode , + Qt::KeyboardModifiers modifiers , States flags ) const; bool operator==(const Entry& rhs) const; - + private: void insertModifier( QString& item , int modifier ) const; void insertState( QString& item , int state ) const; @@ -332,7 +332,7 @@ public: /** Constructs a new keyboard translator with the given @p name */ KeyboardTranslator(const QString& name); - + //KeyboardTranslator(const KeyboardTranslator& other); /** Returns the name of this keyboard translator */ @@ -350,7 +350,7 @@ public: /** * Looks for an entry in this keyboard translator which matches the given * key code, keyboard modifiers and state flags. - * + * * Returns the matching entry if found or a null Entry otherwise ( ie. * entry.isNull() will return true ) * @@ -358,11 +358,11 @@ public: * @param modifiers A combination of modifiers * @param state Optional flags which specify the current state of the terminal */ - Entry findEntry(int keyCode , - Qt::KeyboardModifiers modifiers , + Entry findEntry(int keyCode , + Qt::KeyboardModifiers modifiers , States state = NoState) const; - /** + /** * Adds an entry to this keyboard translator's table. Entries can be looked up according * to their key sequence using findEntry() */ @@ -385,16 +385,16 @@ public: private: QHash _entries; // entries in this keyboard translation, - // entries are indexed according to - // their keycode + // entries are indexed according to + // their keycode QString _name; QString _description; }; Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardTranslator::States) Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardTranslator::Commands) -/** - * Parses the contents of a Keyboard Translator (.keytab) file and +/** + * Parses the contents of a Keyboard Translator (.keytab) file and * returns the entries found in it. * * Usage example: @@ -414,7 +414,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardTranslator::Commands) * if ( !reader.parseError() ) * { * // parsing succeeded, do something with the translator - * } + * } * else * { * // parsing failed @@ -427,18 +427,18 @@ public: /** Constructs a new reader which parses the given @p source */ KeyboardTranslatorReader( QIODevice* source ); - /** - * Returns the description text. - * TODO: More documentation + /** + * Returns the description text. + * TODO: More documentation */ QString description() const; /** Returns true if there is another entry in the source stream */ bool hasNextEntry(); /** Returns the next entry found in the source stream */ - KeyboardTranslator::Entry nextEntry(); + KeyboardTranslator::Entry nextEntry(); - /** + /** * Returns true if an error occurred whilst parsing the input or * false if no error occurred. */ @@ -448,15 +448,13 @@ public: * Parses a condition and result string for a translator entry * and produces a keyboard translator entry. * - * The condition and result strings are in the same format as in + * The condition and result strings are in the same format as in */ static KeyboardTranslator::Entry createEntry( const QString& condition , - const QString& result ); + const QString& result ); private: - struct Token - { - enum Type - { + struct Token { + enum Type { TitleKeyword, TitleText, KeyKeyword, @@ -469,17 +467,17 @@ private: }; QList tokenize(const QString&); void readNext(); - bool decodeSequence(const QString& , - int& keyCode, - Qt::KeyboardModifiers& modifiers, - Qt::KeyboardModifiers& modifierMask, - KeyboardTranslator::States& state, - KeyboardTranslator::States& stateFlags); + bool decodeSequence(const QString& , + int& keyCode, + Qt::KeyboardModifiers& modifiers, + Qt::KeyboardModifiers& modifierMask, + KeyboardTranslator::States& state, + KeyboardTranslator::States& stateFlags); static bool parseAsModifier(const QString& item , Qt::KeyboardModifier& modifier); static bool parseAsStateFlag(const QString& item , KeyboardTranslator::State& state); static bool parseAsKeyCode(const QString& item , int& keyCode); - static bool parseAsCommand(const QString& text , KeyboardTranslator::Command& command); + static bool parseAsCommand(const QString& text , KeyboardTranslator::Command& command); QIODevice* _source; QString _description; @@ -491,23 +489,23 @@ private: class KeyboardTranslatorWriter { public: - /** + /** * Constructs a new writer which saves data into @p destination. * The caller is responsible for closing the device when writing is complete. */ KeyboardTranslatorWriter(QIODevice* destination); ~KeyboardTranslatorWriter(); - /** - * Writes the header for the keyboard translator. - * @param description Description of the keyboard translator. + /** + * Writes the header for the keyboard translator. + * @param description Description of the keyboard translator. */ void writeHeader( const QString& description ); /** Writes a translator entry. */ - void writeEntry( const KeyboardTranslator::Entry& entry ); + void writeEntry( const KeyboardTranslator::Entry& entry ); private: - QIODevice* _destination; + QIODevice* _destination; QTextStream* _writer; }; @@ -518,7 +516,7 @@ private: class KeyboardTranslatorManager { public: - /** + /** * Constructs a new KeyboardTranslatorManager and loads the list of * available keyboard translations. * @@ -529,7 +527,7 @@ public: ~KeyboardTranslatorManager(); /** - * Adds a new translator. If a translator with the same name + * Adds a new translator. If a translator with the same name * already exists, it will be replaced by the new translator. * * TODO: More documentation. @@ -546,55 +544,67 @@ public: /** Returns the default translator for Konsole. */ const KeyboardTranslator* defaultTranslator(); - /** + /** * Returns the keyboard translator with the given name or 0 if no translator * with that name exists. * * The first time that a translator with a particular name is requested, - * the on-disk .keyboard file is loaded and parsed. + * the on-disk .keyboard file is loaded and parsed. */ const KeyboardTranslator* findTranslator(const QString& name); /** * Returns a list of the names of available keyboard translators. * - * The first time this is called, a search for available + * The first time this is called, a search for available * translators is started. */ QList allTranslators(); /** Returns the global KeyboardTranslatorManager instance. */ - static KeyboardTranslatorManager* instance(); + static KeyboardTranslatorManager* instance(); private: static const char* defaultTranslatorText; - + void findTranslators(); // locate the available translators - KeyboardTranslator* loadTranslator(const QString& name); // loads the translator - // with the given name + KeyboardTranslator* loadTranslator(const QString& name); // loads the translator + // with the given name KeyboardTranslator* loadTranslator(QIODevice* device,const QString& name); bool saveTranslator(const KeyboardTranslator* translator); QString findTranslatorPath(const QString& name); - + QHash _translators; // maps translator-name -> KeyboardTranslator - // instance + // instance bool _haveLoadedAll; }; -inline int KeyboardTranslator::Entry::keyCode() const { return _keyCode; } -inline void KeyboardTranslator::Entry::setKeyCode(int keyCode) { _keyCode = keyCode; } +inline int KeyboardTranslator::Entry::keyCode() const +{ + return _keyCode; +} +inline void KeyboardTranslator::Entry::setKeyCode(int keyCode) +{ + _keyCode = keyCode; +} -inline void KeyboardTranslator::Entry::setModifiers( Qt::KeyboardModifiers modifier ) -{ +inline void KeyboardTranslator::Entry::setModifiers( Qt::KeyboardModifiers modifier ) +{ _modifiers = modifier; } -inline Qt::KeyboardModifiers KeyboardTranslator::Entry::modifiers() const { return _modifiers; } - -inline void KeyboardTranslator::Entry::setModifierMask( Qt::KeyboardModifiers mask ) -{ - _modifierMask = mask; +inline Qt::KeyboardModifiers KeyboardTranslator::Entry::modifiers() const +{ + return _modifiers; +} + +inline void KeyboardTranslator::Entry::setModifierMask( Qt::KeyboardModifiers mask ) +{ + _modifierMask = mask; +} +inline Qt::KeyboardModifiers KeyboardTranslator::Entry::modifierMask() const +{ + return _modifierMask; } -inline Qt::KeyboardModifiers KeyboardTranslator::Entry::modifierMask() const { return _modifierMask; } inline bool KeyboardTranslator::Entry::isNull() const { @@ -602,51 +612,58 @@ inline bool KeyboardTranslator::Entry::isNull() const } inline void KeyboardTranslator::Entry::setCommand( Command command ) -{ - _command = command; +{ + _command = command; +} +inline KeyboardTranslator::Command KeyboardTranslator::Entry::command() const +{ + return _command; } -inline KeyboardTranslator::Command KeyboardTranslator::Entry::command() const { return _command; } inline void KeyboardTranslator::Entry::setText( const QByteArray& text ) -{ +{ _text = unescape(text); } inline int oneOrZero(int value) { return value ? 1 : 0; } -inline QByteArray KeyboardTranslator::Entry::text(bool expandWildCards,Qt::KeyboardModifiers modifiers) const +inline QByteArray KeyboardTranslator::Entry::text(bool expandWildCards,Qt::KeyboardModifiers modifiers) const { QByteArray expandedText = _text; - - if (expandWildCards) - { + + if (expandWildCards) { int modifierValue = 1; modifierValue += oneOrZero(modifiers & Qt::ShiftModifier); modifierValue += oneOrZero(modifiers & Qt::AltModifier) << 1; modifierValue += oneOrZero(modifiers & Qt::ControlModifier) << 2; - for (int i=0;i<_text.length();i++) - { + for (int i=0; i<_text.length(); i++) { if (expandedText[i] == '*') expandedText[i] = '0' + modifierValue; } } - return expandedText; + return expandedText; } inline void KeyboardTranslator::Entry::setState( States state ) -{ - _state = state; +{ + _state = state; +} +inline KeyboardTranslator::States KeyboardTranslator::Entry::state() const +{ + return _state; } -inline KeyboardTranslator::States KeyboardTranslator::Entry::state() const { return _state; } inline void KeyboardTranslator::Entry::setStateMask( States stateMask ) -{ - _stateMask = stateMask; +{ + _stateMask = stateMask; +} +inline KeyboardTranslator::States KeyboardTranslator::Entry::stateMask() const +{ + return _stateMask; } -inline KeyboardTranslator::States KeyboardTranslator::Entry::stateMask() const { return _stateMask; } } diff --git a/lib/LineFont.h b/lib/LineFont.h index 9b64143..9c080ea 100644 --- a/lib/LineFont.h +++ b/lib/LineFont.h @@ -2,20 +2,20 @@ // You probably do not want to hand-edit this! static const quint32 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 + 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/lib/Pty.cpp b/lib/Pty.cpp index 144e5e2..6ddeac8 100644 --- a/lib/Pty.cpp +++ b/lib/Pty.cpp @@ -43,16 +43,16 @@ using namespace Konsole; void Pty::donePty() { - emit done(exitStatus()); + emit done(exitStatus()); } void Pty::setWindowSize(int lines, int cols) { - _windowColumns = cols; - _windowLines = lines; + _windowColumns = cols; + _windowLines = lines; - if (pty()->masterFd() >= 0) - pty()->setWinSize(lines, cols); + if (pty()->masterFd() >= 0) + pty()->setWinSize(lines, cols); } QSize Pty::windowSize() const { @@ -61,82 +61,76 @@ QSize Pty::windowSize() const void Pty::setXonXoff(bool enable) { - _xonXoff = enable; + _xonXoff = enable; - if (pty()->masterFd() >= 0) - { - struct ::termios ttmode; - pty()->tcGetAttr(&ttmode); - if (!enable) - ttmode.c_iflag &= ~(IXOFF | IXON); - else - ttmode.c_iflag |= (IXOFF | IXON); - if (!pty()->tcSetAttr(&ttmode)) - qWarning("Unable to set terminal attributes."); - } + if (pty()->masterFd() >= 0) { + struct ::termios ttmode; + pty()->tcGetAttr(&ttmode); + if (!enable) + ttmode.c_iflag &= ~(IXOFF | IXON); + else + ttmode.c_iflag |= (IXOFF | IXON); + if (!pty()->tcSetAttr(&ttmode)) + qWarning("Unable to set terminal attributes."); + } } void Pty::setUtf8Mode(bool enable) { #ifdef IUTF8 // XXX not a reasonable place to check it. - _utf8 = enable; + _utf8 = enable; - if (pty()->masterFd() >= 0) - { - struct ::termios ttmode; - pty()->tcGetAttr(&ttmode); - if (!enable) - ttmode.c_iflag &= ~IUTF8; - else - ttmode.c_iflag |= IUTF8; - if (!pty()->tcSetAttr(&ttmode)) - qWarning("Unable to set terminal attributes."); - } + if (pty()->masterFd() >= 0) { + struct ::termios ttmode; + pty()->tcGetAttr(&ttmode); + if (!enable) + ttmode.c_iflag &= ~IUTF8; + else + ttmode.c_iflag |= IUTF8; + if (!pty()->tcSetAttr(&ttmode)) + qWarning("Unable to set terminal attributes."); + } #endif } void Pty::setErase(char erase) { - _eraseChar = erase; - - if (pty()->masterFd() >= 0) - { - struct ::termios ttmode; + _eraseChar = erase; - pty()->tcGetAttr(&ttmode); + if (pty()->masterFd() >= 0) { + struct ::termios ttmode; - ttmode.c_cc[VERASE] = erase; + pty()->tcGetAttr(&ttmode); - if (!pty()->tcSetAttr(&ttmode)) - qWarning("Unable to set terminal attributes."); - } + ttmode.c_cc[VERASE] = erase; + + if (!pty()->tcSetAttr(&ttmode)) + qWarning("Unable to set terminal attributes."); + } } char Pty::erase() const { - if (pty()->masterFd() >= 0) - { - qDebug() << "Getting erase char"; - struct ::termios ttyAttributes; - pty()->tcGetAttr(&ttyAttributes); - return ttyAttributes.c_cc[VERASE]; - } + if (pty()->masterFd() >= 0) { + qDebug() << "Getting erase char"; + struct ::termios ttyAttributes; + pty()->tcGetAttr(&ttyAttributes); + return ttyAttributes.c_cc[VERASE]; + } - return _eraseChar; + return _eraseChar; } void Pty::addEnvironmentVariables(const QStringList& environment) { QListIterator iter(environment); - while (iter.hasNext()) - { + while (iter.hasNext()) { QString pair = iter.next(); // split on the first '=' character int pos = pair.indexOf('='); - - if ( pos >= 0 ) - { + + if ( pos >= 0 ) { QString variable = pair.left(pos); QString value = pair.mid(pos+1); @@ -148,106 +142,106 @@ void Pty::addEnvironmentVariables(const QStringList& environment) } } -int Pty::start(const QString& program, - const QStringList& programArguments, - const QStringList& environment, - ulong winid, +int Pty::start(const QString& program, + const QStringList& programArguments, + const QStringList& environment, + ulong winid, bool addToUtmp -// const QString& dbusService, +// const QString& dbusService, // const QString& dbusSession) - ) + ) { - clearArguments(); + clearArguments(); - setBinaryExecutable(program.toLatin1()); + setBinaryExecutable(program.toLatin1()); - addEnvironmentVariables(environment); + addEnvironmentVariables(environment); - QStringListIterator it( programArguments ); - while (it.hasNext()) - arguments.append( it.next().toUtf8() ); + QStringListIterator it( programArguments ); + while (it.hasNext()) + arguments.append( it.next().toUtf8() ); // if ( !dbusService.isEmpty() ) // setEnvironment("KONSOLE_DBUS_SERVICE",dbusService); // if ( !dbusSession.isEmpty() ) // setEnvironment("KONSOLE_DBUS_SESSION", dbusSession); - setEnvironment("WINDOWID", QString::number(winid)); + setEnvironment("WINDOWID", QString::number(winid)); - // unless the LANGUAGE environment variable has been set explicitly - // set it to a null string - // this fixes the problem where KCatalog sets the LANGUAGE environment - // variable during the application's startup to something which - // differs from LANG,LC_* etc. and causes programs run from - // the terminal to display mesages in the wrong language - // - // this can happen if LANG contains a language which KDE - // does not have a translation for - // - // BR:149300 - if (!environment.contains("LANGUAGE")) - setEnvironment("LANGUAGE",QString()); + // unless the LANGUAGE environment variable has been set explicitly + // set it to a null string + // this fixes the problem where KCatalog sets the LANGUAGE environment + // variable during the application's startup to something which + // differs from LANG,LC_* etc. and causes programs run from + // the terminal to display mesages in the wrong language + // + // this can happen if LANG contains a language which KDE + // does not have a translation for + // + // BR:149300 + if (!environment.contains("LANGUAGE")) + setEnvironment("LANGUAGE",QString()); - setUsePty(All, addToUtmp); + setUsePty(All, addToUtmp); - pty()->open(); - - struct ::termios ttmode; - pty()->tcGetAttr(&ttmode); - if (!_xonXoff) - ttmode.c_iflag &= ~(IXOFF | IXON); - else - ttmode.c_iflag |= (IXOFF | IXON); + pty()->open(); + + struct ::termios ttmode; + pty()->tcGetAttr(&ttmode); + if (!_xonXoff) + ttmode.c_iflag &= ~(IXOFF | IXON); + else + ttmode.c_iflag |= (IXOFF | IXON); #ifdef IUTF8 // XXX not a reasonable place to check it. - if (!_utf8) - ttmode.c_iflag &= ~IUTF8; - else - ttmode.c_iflag |= IUTF8; + if (!_utf8) + ttmode.c_iflag &= ~IUTF8; + else + ttmode.c_iflag |= IUTF8; #endif - if (_eraseChar != 0) - ttmode.c_cc[VERASE] = _eraseChar; - - if (!pty()->tcSetAttr(&ttmode)) - qWarning("Unable to set terminal attributes."); - - pty()->setWinSize(_windowLines, _windowColumns); + if (_eraseChar != 0) + ttmode.c_cc[VERASE] = _eraseChar; - if ( K3Process::start(NotifyOnExit, (Communication) (Stdin | Stdout)) == false ) - return -1; + if (!pty()->tcSetAttr(&ttmode)) + qWarning("Unable to set terminal attributes."); - resume(); // Start... - return 0; + pty()->setWinSize(_windowLines, _windowColumns); + + if ( K3Process::start(NotifyOnExit, (Communication) (Stdin | Stdout)) == false ) + return -1; + + resume(); // Start... + return 0; } void Pty::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)); + 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)); } Pty::Pty() - : _bufferFull(false), - _windowColumns(0), - _windowLines(0), - _eraseChar(0), - _xonXoff(true), - _utf8(true) + : _bufferFull(false), + _windowColumns(0), + _windowLines(0), + _eraseChar(0), + _xonXoff(true), + _utf8(true) { - connect(this, SIGNAL(receivedStdout(K3Process *, char *, int )), - this, SLOT(dataReceived(K3Process *,char *, int))); - connect(this, SIGNAL(processExited(K3Process *)), - this, SLOT(donePty())); - connect(this, SIGNAL(wroteStdin(K3Process *)), - this, SLOT(writeReady())); - _pty = new KPty; + connect(this, SIGNAL(receivedStdout(K3Process *, char *, int )), + this, SLOT(dataReceived(K3Process *,char *, int))); + connect(this, SIGNAL(processExited(K3Process *)), + this, SLOT(donePty())); + connect(this, SIGNAL(wroteStdin(K3Process *)), + this, SLOT(writeReady())); + _pty = new KPty; - setUsePty(All, false); // utmp will be overridden later + setUsePty(All, false); // utmp will be overridden later } Pty::~Pty() @@ -257,62 +251,60 @@ Pty::~Pty() void Pty::writeReady() { - _pendingSendJobs.erase(_pendingSendJobs.begin()); - _bufferFull = false; - doSendJobs(); + _pendingSendJobs.erase(_pendingSendJobs.begin()); + _bufferFull = false; + doSendJobs(); } -void Pty::doSendJobs() { - if(_pendingSendJobs.isEmpty()) - { - emit bufferEmpty(); - return; - } - - SendJob& job = _pendingSendJobs.first(); +void Pty::doSendJobs() +{ + if (_pendingSendJobs.isEmpty()) { + emit bufferEmpty(); + return; + } - - if (!writeStdin( job.data(), job.length() )) - { - qWarning("Pty::doSendJobs - Could not send input data to terminal process."); - return; - } - _bufferFull = true; + SendJob& job = _pendingSendJobs.first(); + + + if (!writeStdin( job.data(), job.length() )) { + qWarning("Pty::doSendJobs - Could not send input data to terminal process."); + return; + } + _bufferFull = true; } void Pty::appendSendJob(const char* s, int len) { - _pendingSendJobs.append(SendJob(s,len)); + _pendingSendJobs.append(SendJob(s,len)); } void Pty::sendData(const char* s, int len) { - appendSendJob(s,len); - if (!_bufferFull) - doSendJobs(); + appendSendJob(s,len); + if (!_bufferFull) + doSendJobs(); } void Pty::dataReceived(K3Process *,char *buf, int len) { - emit receivedData(buf,len); + emit receivedData(buf,len); } void Pty::lockPty(bool lock) { - if (lock) - suspend(); - else - resume(); + if (lock) + suspend(); + else + resume(); } int Pty::foregroundProcessGroup() const { int pid = tcgetpgrp(pty()->masterFd()); - if ( pid != -1 ) - { + if ( pid != -1 ) { return pid; - } + } return 0; } diff --git a/lib/Pty.h b/lib/Pty.h index f3e9432..3b6aecb 100644 --- a/lib/Pty.h +++ b/lib/Pty.h @@ -1,6 +1,6 @@ /* - This file is part of Konsole, KDE's terminal emulator. - + This file is part of Konsole, KDE's terminal emulator. + Copyright (C) 2007 by Robert Knight Copyright (C) 1997,1998 by Lars Doelle @@ -38,8 +38,8 @@ namespace Konsole { /** - * The Pty class is used to start the terminal process, - * send data to it, receive data from it and manipulate + * The Pty class is used to start the terminal process, + * send data to it, receive data from it and manipulate * various properties of the pseudo-teletype interface * used to communicate with the process. * @@ -48,28 +48,28 @@ namespace Konsole * send data to or receive data from the process. * * To start the terminal process, call the start() method - * with the program name and appropriate arguments. + * with the program name and appropriate arguments. */ class Pty: public K3Process { -Q_OBJECT + Q_OBJECT - public: - - /** +public: + + /** * Constructs a new Pty. - * + * * Connect to the sendData() slot and receivedData() signal to prepare * for sending and receiving data from the terminal process. * - * To start the terminal process, call the run() method with the + * To start the terminal process, call the run() method with the * name of the program to start and appropriate arguments. */ Pty(); ~Pty(); /** - * Starts the terminal process. + * Starts the terminal process. * * Returns 0 if the process was started successfully or non-zero * otherwise. @@ -82,16 +82,16 @@ Q_OBJECT * @param winid Specifies the value of the WINDOWID environment variable * in the process's environment. * @param addToUtmp Specifies whether a utmp entry should be created for - * the pty used. See K3Process::setUsePty() - * @param dbusService Specifies the value of the KONSOLE_DBUS_SERVICE + * the pty used. See K3Process::setUsePty() + * @param dbusService Specifies the value of the KONSOLE_DBUS_SERVICE * environment variable in the process's environment. * @param dbusSession Specifies the value of the KONSOLE_DBUS_SESSION - * environment variable in the process's environment. + * environment variable in the process's environment. */ - int start( const QString& program, - const QStringList& arguments, - const QStringList& environment, - ulong winid, + int start( const QString& program, + const QStringList& arguments, + const QStringList& environment, + ulong winid, bool addToUtmp // const QString& dbusService, // const QString& dbusSession @@ -100,25 +100,25 @@ Q_OBJECT /** TODO: Document me */ void setWriteable(bool writeable); - /** + /** * Enables or disables Xon/Xoff flow control. */ void setXonXoff(bool on); - /** - * Sets the size of the window (in lines and columns of characters) + /** + * Sets the size of the window (in lines and columns of characters) * used by this teletype. */ void setWindowSize(int lines, int cols); - + /** Returns the size of the window used by this teletype. See setWindowSize() */ QSize windowSize() const; /** TODO Document me */ void setErase(char erase); - /** */ - char erase() const; + /** */ + char erase() const; /** * Returns the process id of the teletype's current foreground @@ -129,15 +129,17 @@ Q_OBJECT * 0 will be returned. */ int foregroundProcessGroup() const; - + /** * Returns whether the buffer used to send data to the * terminal process is full. */ - bool bufferFull() const { return _bufferFull; } + bool bufferFull() const { + return _bufferFull; + } - public slots: +public slots: /** * Put the pty into UTF-8 mode on systems which support it. @@ -145,7 +147,7 @@ Q_OBJECT void setUtf8Mode(bool on); /** - * Suspend or resume processing of data from the standard + * Suspend or resume processing of data from the standard * output of the terminal process. * * See K3Process::suspend() and K3Process::resume() @@ -154,9 +156,9 @@ Q_OBJECT * otherwise processing is resumed. */ void lockPty(bool lock); - - /** - * Sends data to the process currently controlling the + + /** + * Sends data to the process currently controlling the * teletype ( whose id is returned by foregroundProcessGroup() ) * * @param buffer Pointer to the data to send. @@ -164,7 +166,7 @@ Q_OBJECT */ void sendData(const char* buffer, int length); - signals: +signals: /** * Emitted when the terminal process terminates. @@ -181,19 +183,19 @@ Q_OBJECT * @param length Length of @p buffer */ void receivedData(const char* buffer, int length); - + /** * Emitted when the buffer used to send data to the terminal * process becomes empty, i.e. all data has been sent. */ void bufferEmpty(); - - private slots: - + +private slots: + // called when terminal process exits void donePty(); - // called when data is received from the terminal process + // called when data is received from the terminal process void dataReceived(K3Process*, char* buffer, int length); // sends the first enqueued buffer of data to the // terminal process @@ -202,35 +204,39 @@ Q_OBJECT // receive more data void writeReady(); - private: +private: // takes a list of key=value pairs and adds them // to the environment for the process void addEnvironmentVariables(const QStringList& environment); - // enqueues a buffer of data to be sent to the + // enqueues a buffer of data to be sent to the // terminal process void appendSendJob(const char* buffer, int length); - - // a buffer of data in the queue to be sent to the - // terminal process - class SendJob { - public: - SendJob() {} - SendJob(const char* b, int len) : buffer(len) - { - memcpy( buffer.data() , b , len ); + + // a buffer of data in the queue to be sent to the + // terminal process + class SendJob + { + public: + SendJob() {} + SendJob(const char* b, int len) : buffer(len) { + memcpy( buffer.data() , b , len ); } - - const char* data() const { return buffer.constData(); } - int length() const { return buffer.size(); } - private: - QVector buffer; + + const char* data() const { + return buffer.constData(); + } + int length() const { + return buffer.size(); + } + private: + QVector buffer; }; QList _pendingSendJobs; bool _bufferFull; - int _windowColumns; + int _windowColumns; int _windowLines; char _eraseChar; bool _xonXoff; diff --git a/lib/Screen.cpp b/lib/Screen.cpp index 093fbc2..d3d43e9 100644 --- a/lib/Screen.cpp +++ b/lib/Screen.cpp @@ -47,10 +47,10 @@ using namespace Konsole; //Macro to convert x,y position on screen to position within an image. // -//Originally the image was stored as one large contiguous block of +//Originally the image was stored as one large contiguous block of //memory, so a position within the image could be represented as an //offset from the beginning of the block. For efficiency reasons this -//is no longer the case. +//is no longer the case. //Many internal parts of this class still use this representation for parameters and so on, //notably moveImage() and clearImage(). //This macro converts from an X,Y position into an image offset. @@ -60,38 +60,38 @@ using namespace Konsole; Character Screen::defaultChar = Character(' ', - CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR), - CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR), - DEFAULT_RENDITION); + CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR), + CharacterColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR), + DEFAULT_RENDITION); //#define REVERSE_WRAPPED_LINES // for wrapped line debug Screen::Screen(int l, int c) - : lines(l), - columns(c), - screenLines(new ImageLine[lines+1] ), - _scrolledLines(0), - _droppedLines(0), - hist(new HistoryScrollNone()), - cuX(0), cuY(0), - 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(CharacterColor()), ef_bg(CharacterColor()), ef_re(0), - sa_cuX(0), sa_cuY(0), - sa_cu_re(0), - lastPos(-1) + : lines(l), + columns(c), + screenLines(new ImageLine[lines+1] ), + _scrolledLines(0), + _droppedLines(0), + hist(new HistoryScrollNone()), + cuX(0), cuY(0), + 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(CharacterColor()), ef_bg(CharacterColor()), ef_re(0), + sa_cuX(0), sa_cuY(0), + sa_cu_re(0), + lastPos(-1) { - lineProperties.resize(lines+1); - for (int i=0;i bmargin ? lines-1 : bmargin; - cuX = qMin(columns-1,cuX); // nowrap! - cuY = qMin(stop,cuY+n); + if (n == 0) n = 1; // Default + int stop = cuY > bmargin ? lines-1 : bmargin; + cuX = qMin(columns-1,cuX); // nowrap! + cuY = qMin(stop,cuY+n); } /*! @@ -161,9 +161,9 @@ void Screen::cursorDown(int n) void Screen::cursorLeft(int n) //=CUB { - if (n == 0) n = 1; // Default - cuX = qMin(columns-1,cuX); // nowrap! - cuX = qMax(0,cuX-n); + if (n == 0) n = 1; // Default + cuX = qMin(columns-1,cuX); // nowrap! + cuX = qMax(0,cuX-n); } /*! @@ -175,25 +175,25 @@ void Screen::cursorLeft(int n) void Screen::cursorRight(int n) //=CUF { - if (n == 0) n = 1; // Default - cuX = qMin(columns-1,cuX+n); + if (n == 0) n = 1; // Default + cuX = qMin(columns-1,cuX+n); } void Screen::setMargins(int top, int bot) //=STBM { - if (top == 0) top = 1; // Default - if (bot == 0) bot = lines; // Default - top = top - 1; // Adjust to internal lineno - bot = bot - 1; // Adjust to internal lineno - if ( !( 0 <= top && top < bot && bot < lines ) ) - { qDebug()<<" setRegion("< 0) - cuY -= 1; + if (cuY == tmargin) + scrollDown(tmargin,1); + else if (cuY > 0) + cuY -= 1; } /*! @@ -236,54 +234,55 @@ void Screen::reverseIndex() void Screen::NextLine() //=NEL { - Return(); index(); + Return(); + index(); } void Screen::eraseChars(int n) { - if (n == 0) n = 1; // Default - int p = qMax(0,qMin(cuX+n-1,columns-1)); - clearImage(loc(cuX,cuY),loc(p,cuY),' '); + if (n == 0) n = 1; // Default + int p = qMax(0,qMin(cuX+n-1,columns-1)); + clearImage(loc(cuX,cuY),loc(p,cuY),' '); } void Screen::deleteChars(int n) { - Q_ASSERT( n >= 0 ); + Q_ASSERT( n >= 0 ); - // always delete at least one char - if (n == 0) - n = 1; + // always delete at least one char + if (n == 0) + n = 1; - // if cursor is beyond the end of the line there is nothing to do - if ( cuX >= screenLines[cuY].count() ) - return; + // if cursor is beyond the end of the line there is nothing to do + if ( cuX >= screenLines[cuY].count() ) + return; - if ( cuX+n >= screenLines[cuY].count() ) - n = screenLines[cuY].count() - 1 - cuX; + if ( cuX+n >= screenLines[cuY].count() ) + n = screenLines[cuY].count() - 1 - cuX; - Q_ASSERT( n >= 0 ); - Q_ASSERT( cuX+n < screenLines[cuY].count() ); + Q_ASSERT( n >= 0 ); + Q_ASSERT( cuX+n < screenLines[cuY].count() ); - screenLines[cuY].remove(cuX,n); + screenLines[cuY].remove(cuX,n); } void Screen::insertChars(int n) { - if (n == 0) n = 1; // Default + if (n == 0) n = 1; // Default - if ( screenLines[cuY].size() < cuX ) - screenLines[cuY].resize(cuX); + if ( screenLines[cuY].size() < cuX ) + screenLines[cuY].resize(cuX); - screenLines[cuY].insert(cuX,n,' '); + screenLines[cuY].insert(cuX,n,' '); - if ( screenLines[cuY].count() > columns ) - screenLines[cuY].resize(columns); + if ( screenLines[cuY].count() > columns ) + screenLines[cuY].resize(columns); } void Screen::deleteLines(int n) { - if (n == 0) n = 1; // Default - scrollUp(cuY,n); + if (n == 0) n = 1; // Default + scrollUp(cuY,n); } /*! insert `n' lines at the cursor position. @@ -293,8 +292,8 @@ void Screen::deleteLines(int n) void Screen::insertLines(int n) { - if (n == 0) n = 1; // Default - scrollDown(cuY,n); + if (n == 0) n = 1; // Default + scrollDown(cuY,n); } // Mode Operations ----------------------------------------------------------- @@ -303,60 +302,64 @@ void Screen::insertLines(int n) void Screen::setMode(int m) { - currParm.mode[m] = true; - switch(m) - { - case MODE_Origin : cuX = 0; cuY = tmargin; break; //FIXME: home - } + currParm.mode[m] = true; + switch (m) { + case MODE_Origin : + cuX = 0; + cuY = tmargin; + break; //FIXME: home + } } /*! Reset a specific mode. */ void Screen::resetMode(int m) { - currParm.mode[m] = false; - switch(m) - { - case MODE_Origin : cuX = 0; cuY = 0; break; //FIXME: home - } + currParm.mode[m] = false; + switch (m) { + case MODE_Origin : + cuX = 0; + cuY = 0; + break; //FIXME: home + } } /*! Save a specific mode. */ void Screen::saveMode(int m) { - saveParm.mode[m] = currParm.mode[m]; + saveParm.mode[m] = currParm.mode[m]; } /*! Restore a specific mode. */ void Screen::restoreMode(int m) { - currParm.mode[m] = saveParm.mode[m]; + currParm.mode[m] = saveParm.mode[m]; } bool Screen::getMode(int m) const { - return currParm.mode[m]; + return currParm.mode[m]; } void Screen::saveCursor() { - sa_cuX = cuX; - sa_cuY = cuY; - sa_cu_re = cu_re; - sa_cu_fg = cu_fg; - sa_cu_bg = cu_bg; + sa_cuX = cuX; + sa_cuY = cuY; + sa_cu_re = cu_re; + sa_cu_fg = cu_fg; + sa_cu_bg = cu_bg; } void Screen::restoreCursor() { - cuX = qMin(sa_cuX,columns-1); - cuY = qMin(sa_cuY,lines-1); - cu_re = sa_cu_re; - cu_fg = sa_cu_fg; - cu_bg = sa_cu_bg; - effectiveRendition(); + 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(); } /* ------------------------------------------------------------------------- */ @@ -381,50 +384,49 @@ void Screen::restoreCursor() void Screen::resizeImage(int new_lines, int new_columns) { - if ((new_lines==lines) && (new_columns==columns)) return; + 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); + 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); + } } - } - // create new screen lines and copy from old to new - - ImageLine* newScreenLines = new ImageLine[new_lines+1]; - for (int i=0; i < qMin(lines-1,new_lines+1) ;i++) - newScreenLines[i]=screenLines[i]; - for (int i=lines;(i > 0) && (i 0) && (i 0) && (i 0) && (ir &= ~RE_TRANSPARENT; +{ + CharacterColor f = p.foregroundColor; + CharacterColor b = p.backgroundColor; + + p.foregroundColor = b; + p.backgroundColor = f; //p->r &= ~RE_TRANSPARENT; } void Screen::effectiveRendition() // calculate rendition { - //copy "current rendition" straight into "effective rendition", which is then later copied directly - //into the image[] array which holds the characters and their appearance properties. - //- The old version below filtered out all attributes other than underline and blink at this stage, - //so that they would not be copied into the image[] array and hence would not be visible by TerminalDisplay - //which actually paints the screen using the information from the image[] array. - //I don't know why it did this, but I'm fairly sure it was the wrong thing to do. The net result - //was that bold text wasn't printed in bold by Konsole. - ef_re = cu_re; - - //OLD VERSION: - //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(); + //copy "current rendition" straight into "effective rendition", which is then later copied directly + //into the image[] array which holds the characters and their appearance properties. + //- The old version below filtered out all attributes other than underline and blink at this stage, + //so that they would not be copied into the image[] array and hence would not be visible by TerminalDisplay + //which actually paints the screen using the information from the image[] array. + //I don't know why it did this, but I'm fairly sure it was the wrong thing to do. The net result + //was that bold text wasn't printed in bold by Konsole. + ef_re = cu_re; + + //OLD VERSION: + //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(); } /*! @@ -513,126 +512,116 @@ void Screen::effectiveRendition() void Screen::copyFromHistory(Character* dest, int startLine, int count) const { - Q_ASSERT( startLine >= 0 && count > 0 && startLine + count <= hist->getLines() ); + Q_ASSERT( startLine >= 0 && count > 0 && startLine + count <= hist->getLines() ); - for (int line = startLine; line < startLine + count; line++) - { - const int length = qMin(columns,hist->getLineLen(line)); - const int destLineOffset = (line-startLine)*columns; + for (int line = startLine; line < startLine + count; line++) { + const int length = qMin(columns,hist->getLineLen(line)); + const int destLineOffset = (line-startLine)*columns; - hist->getCells(line,0,length,dest + destLineOffset); + hist->getCells(line,0,length,dest + destLineOffset); - for (int column = length; column < columns; column++) - dest[destLineOffset+column] = defaultChar; - - // invert selected text - if (sel_begin !=-1) - { - for (int column = 0; column < columns; column++) - { - if (isSelected(column,line)) - { - reverseRendition(dest[destLineOffset + column]); - } - } - } - } + for (int column = length; column < columns; column++) + dest[destLineOffset+column] = defaultChar; + + // invert selected text + if (sel_begin !=-1) { + for (int column = 0; column < columns; column++) { + if (isSelected(column,line)) { + reverseRendition(dest[destLineOffset + column]); + } + } + } + } } void Screen::copyFromScreen(Character* dest , int startLine , int count) const { - Q_ASSERT( startLine >= 0 && count > 0 && startLine + count <= lines ); + Q_ASSERT( startLine >= 0 && count > 0 && startLine + count <= lines ); - for (int line = startLine; line < (startLine+count) ; line++) - { - int srcLineStartIndex = line*columns; - int destLineStartIndex = (line-startLine)*columns; + for (int line = startLine; line < (startLine+count) ; line++) { + int srcLineStartIndex = line*columns; + int destLineStartIndex = (line-startLine)*columns; - for (int column = 0; column < columns; column++) - { - int srcIndex = srcLineStartIndex + column; - int destIndex = destLineStartIndex + column; + for (int column = 0; column < columns; column++) { + int srcIndex = srcLineStartIndex + column; + int destIndex = destLineStartIndex + column; - dest[destIndex] = screenLines[srcIndex/columns].value(srcIndex%columns,defaultChar); + dest[destIndex] = screenLines[srcIndex/columns].value(srcIndex%columns,defaultChar); - // invert selected text - if (sel_begin != -1 && isSelected(column,line + hist->getLines())) - reverseRendition(dest[destIndex]); - } + // invert selected text + if (sel_begin != -1 && isSelected(column,line + hist->getLines())) + reverseRendition(dest[destIndex]); + } } } void Screen::getImage( Character* dest, int size, int startLine, int endLine ) const { - Q_ASSERT( startLine >= 0 ); - Q_ASSERT( endLine >= startLine && endLine < hist->getLines() + lines ); + Q_ASSERT( startLine >= 0 ); + Q_ASSERT( endLine >= startLine && endLine < hist->getLines() + lines ); - const int mergedLines = endLine - startLine + 1; + const int mergedLines = endLine - startLine + 1; - Q_ASSERT( size >= mergedLines * columns ); - Q_UNUSED( size ); + Q_ASSERT( size >= mergedLines * columns ); + Q_UNUSED( size ); - const int linesInHistoryBuffer = qBound(0,hist->getLines()-startLine,mergedLines); - const int linesInScreenBuffer = mergedLines - linesInHistoryBuffer; + const int linesInHistoryBuffer = qBound(0,hist->getLines()-startLine,mergedLines); + const int linesInScreenBuffer = mergedLines - linesInHistoryBuffer; - // copy lines from history buffer - if (linesInHistoryBuffer > 0) { - copyFromHistory(dest,startLine,linesInHistoryBuffer); + // copy lines from history buffer + if (linesInHistoryBuffer > 0) { + copyFromHistory(dest,startLine,linesInHistoryBuffer); } - // copy lines from screen buffer - if (linesInScreenBuffer > 0) { - copyFromScreen(dest + linesInHistoryBuffer*columns, - startLine + linesInHistoryBuffer - hist->getLines(), - linesInScreenBuffer); - } - - // invert display when in screen mode - if (getMode(MODE_Screen)) - { - for (int i = 0; i < mergedLines*columns; i++) - reverseRendition(dest[i]); // for reverse display - } + // copy lines from screen buffer + if (linesInScreenBuffer > 0) { + copyFromScreen(dest + linesInHistoryBuffer*columns, + startLine + linesInHistoryBuffer - hist->getLines(), + linesInScreenBuffer); + } - // mark the character at the current cursor position - int cursorIndex = loc(cuX, cuY + linesInHistoryBuffer); - if(getMode(MODE_Cursor) && cursorIndex < columns*mergedLines) - dest[cursorIndex].rendition |= RE_CURSOR; + // invert display when in screen mode + if (getMode(MODE_Screen)) { + for (int i = 0; i < mergedLines*columns; i++) + reverseRendition(dest[i]); // for reverse display + } + + // mark the character at the current cursor position + int cursorIndex = loc(cuX, cuY + linesInHistoryBuffer); + if (getMode(MODE_Cursor) && cursorIndex < columns*mergedLines) + dest[cursorIndex].rendition |= RE_CURSOR; } QVector Screen::getLineProperties( int startLine , int endLine ) const { - Q_ASSERT( startLine >= 0 ); - Q_ASSERT( endLine >= startLine && endLine < hist->getLines() + lines ); + Q_ASSERT( startLine >= 0 ); + Q_ASSERT( endLine >= startLine && endLine < hist->getLines() + lines ); - const int mergedLines = endLine-startLine+1; - const int linesInHistory = qBound(0,hist->getLines()-startLine,mergedLines); - const int linesInScreen = mergedLines - linesInHistory; + const int mergedLines = endLine-startLine+1; + const int linesInHistory = qBound(0,hist->getLines()-startLine,mergedLines); + const int linesInScreen = mergedLines - linesInHistory; - QVector result(mergedLines); - int index = 0; + QVector result(mergedLines); + int index = 0; - // copy properties for lines in history - for (int line = startLine; line < startLine + linesInHistory; line++) - { - //TODO Support for line properties other than wrapped lines - if (hist->isWrappedLine(line)) - { - result[index] = (LineProperty)(result[index] | LINE_WRAPPED); - } - index++; - } - - // copy properties for lines in screen buffer - const int firstScreenLine = startLine + linesInHistory - hist->getLines(); - for (int line = firstScreenLine; line < firstScreenLine+linesInScreen; line++) - { - result[index]=lineProperties[line]; - index++; - } + // copy properties for lines in history + for (int line = startLine; line < startLine + linesInHistory; line++) { + //TODO Support for line properties other than wrapped lines + if (hist->isWrappedLine(line)) { + result[index] = (LineProperty)(result[index] | LINE_WRAPPED); + } + index++; + } - return result; + // copy properties for lines in screen buffer + const int firstScreenLine = startLine + linesInHistory - hist->getLines(); + for (int line = firstScreenLine; line < firstScreenLine+linesInScreen; line++) { + result[index]=lineProperties[line]; + index++; + } + + return result; } /*! @@ -640,21 +629,24 @@ QVector Screen::getLineProperties( int startLine , int endLine ) c void Screen::reset(bool clearScreen) { - 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_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); + resetMode(MODE_Screen); // screen not inverse + resetMode(MODE_NewLine); - tmargin=0; - bmargin=lines-1; + tmargin=0; + bmargin=lines-1; - setDefaultRendition(); - saveCursor(); + setDefaultRendition(); + saveCursor(); - if ( clearScreen ) - clear(); + if ( clearScreen ) + clear(); } /*! Clear the entire screen and home the cursor. @@ -662,64 +654,64 @@ void Screen::reset(bool clearScreen) void Screen::clear() { - clearEntireScreen(); - home(); + clearEntireScreen(); + home(); } void Screen::BackSpace() { - cuX = qMin(columns-1,cuX); // nowrap! - cuX = qMax(0,cuX-1); - // if (BS_CLEARS) image[loc(cuX,cuY)].character = ' '; + cuX = qMin(columns-1,cuX); // nowrap! + cuX = qMax(0,cuX-1); +// if (BS_CLEARS) image[loc(cuX,cuY)].character = ' '; - if (screenLines[cuY].size() < cuX+1) - screenLines[cuY].resize(cuX+1); + if (screenLines[cuY].size() < cuX+1) + screenLines[cuY].resize(cuX+1); - if (BS_CLEARS) screenLines[cuY][cuX].character = ' '; + if (BS_CLEARS) screenLines[cuY][cuX].character = ' '; } void Screen::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--; - } + // 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 Screen::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--; - } + // 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 Screen::clearTabStops() { - for (int i = 0; i < columns; i++) tabstops[i] = false; + for (int i = 0; i < columns; i++) tabstops[i] = false; } void Screen::changeTabStop(bool set) { - if (cuX >= columns) return; - tabstops[cuX] = set; + if (cuX >= columns) return; + tabstops[cuX] = set; } void Screen::initTabStops() { - delete[] tabstops; - tabstops = new bool[columns]; + 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); + // 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); } /*! @@ -730,8 +722,8 @@ void Screen::initTabStops() void Screen::NewLine() { - if (getMode(MODE_NewLine)) Return(); - index(); + if (getMode(MODE_NewLine)) Return(); + index(); } /*! put `c' literally onto the screen at the current cursor position. @@ -742,100 +734,93 @@ void Screen::NewLine() void Screen::checkSelection(int from, int to) { - if (sel_begin == -1) return; - int scr_TL = loc(0, hist->getLines()); - //Clear entire selection if it overlaps region [from, to] - if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) ) - { - clearSelection(); - } + if (sel_begin == -1) return; + int scr_TL = loc(0, hist->getLines()); + //Clear entire selection if it overlaps region [from, to] + if ( (sel_BR > (from+scr_TL) )&&(sel_TL < (to+scr_TL)) ) { + clearSelection(); + } } void Screen::ShowCharacter(unsigned short c) { - // Note that VT100 does wrapping BEFORE putting the character. - // This has impact on the assumption of valid cursor positions. - // We indicate the fact that a newline has to be triggered by - // putting the cursor one right to the last column of the screen. + // 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); + int w = konsole_wcwidth(c); - if (w <= 0) - return; + if (w <= 0) + return; - if (cuX+w > columns) { - if (getMode(MODE_Wrap)) { - lineProperties[cuY] = (LineProperty)(lineProperties[cuY] | LINE_WRAPPED); - NextLine(); + if (cuX+w > columns) { + if (getMode(MODE_Wrap)) { + lineProperties[cuY] = (LineProperty)(lineProperties[cuY] | LINE_WRAPPED); + NextLine(); + } else + cuX = columns-w; } - else - cuX = columns-w; - } - // ensure current line vector has enough elements - int size = screenLines[cuY].size(); - if (size == 0 && cuY > 0) - { - screenLines[cuY].resize( qMax(screenLines[cuY-1].size() , cuX+w) ); - } - else - { - if (size < cuX+w) - { - screenLines[cuY].resize(cuX+w); + // ensure current line vector has enough elements + int size = screenLines[cuY].size(); + if (size == 0 && cuY > 0) { + screenLines[cuY].resize( qMax(screenLines[cuY-1].size() , cuX+w) ); + } else { + if (size < cuX+w) { + screenLines[cuY].resize(cuX+w); + } } - } - if (getMode(MODE_Insert)) insertChars(w); + if (getMode(MODE_Insert)) insertChars(w); - lastPos = loc(cuX,cuY); + lastPos = loc(cuX,cuY); - // check if selection is still valid. - checkSelection(cuX,cuY); + // check if selection is still valid. + checkSelection(cuX,cuY); - Character& currentChar = screenLines[cuY][cuX]; + Character& currentChar = screenLines[cuY][cuX]; - currentChar.character = c; - currentChar.foregroundColor = ef_fg; - currentChar.backgroundColor = ef_bg; - currentChar.rendition = ef_re; + currentChar.character = c; + currentChar.foregroundColor = ef_fg; + currentChar.backgroundColor = ef_bg; + currentChar.rendition = ef_re; - int i = 0; - int newCursorX = cuX + w--; - while(w) - { - i++; - - if ( screenLines[cuY].size() < cuX + i + 1 ) - screenLines[cuY].resize(cuX+i+1); - - Character& ch = screenLines[cuY][cuX + i]; - ch.character = 0; - ch.foregroundColor = ef_fg; - ch.backgroundColor = ef_bg; - ch.rendition = ef_re; + int i = 0; + int newCursorX = cuX + w--; + while (w) { + i++; - w--; - } - cuX = newCursorX; + if ( screenLines[cuY].size() < cuX + i + 1 ) + screenLines[cuY].resize(cuX+i+1); + + Character& ch = screenLines[cuY][cuX + i]; + ch.character = 0; + ch.foregroundColor = ef_fg; + ch.backgroundColor = ef_bg; + ch.rendition = ef_re; + + w--; + } + cuX = newCursorX; } void Screen::compose(const QString& /*compose*/) { - Q_ASSERT( 0 /*Not implemented yet*/ ); + Q_ASSERT( 0 /*Not implemented yet*/ ); -/* if (lastPos == -1) - return; - - QChar c(image[lastPos].character); - compose.prepend(c); - //compose.compose(); ### FIXME! - image[lastPos].character = compose[0].unicode();*/ + /* if (lastPos == -1) + return; + + QChar c(image[lastPos].character); + compose.prepend(c); + //compose.compose(); ### FIXME! + image[lastPos].character = compose[0].unicode();*/ } int Screen::scrolledLines() const { - return _scrolledLines; + return _scrolledLines; } int Screen::droppedLines() const { @@ -856,9 +841,9 @@ void Screen::resetScrolledLines() void Screen::scrollUp(int n) { - if (n == 0) n = 1; // Default - if (tmargin == 0) addHistLine(); // hist.history - scrollUp(tmargin, n); + if (n == 0) n = 1; // Default + if (tmargin == 0) addHistLine(); // hist.history + scrollUp(tmargin, n); } /*! scroll up `n' lines within current region. @@ -873,20 +858,20 @@ QRect Screen::lastScrolledRegion() const void Screen::scrollUp(int from, int n) { - if (n <= 0 || from + n > bmargin) return; + if (n <= 0 || from + n > bmargin) return; - _scrolledLines -= n; - _lastScrolledRegion = QRect(0,tmargin,columns-1,(bmargin-tmargin)); + _scrolledLines -= n; + _lastScrolledRegion = QRect(0,tmargin,columns-1,(bmargin-tmargin)); - //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),' '); + //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 Screen::scrollDown(int n) { - if (n == 0) n = 1; // Default - scrollDown(tmargin, n); + if (n == 0) n = 1; // Default + scrollDown(tmargin, n); } /*! scroll down `n' lines within current region. @@ -897,56 +882,57 @@ void Screen::scrollDown(int n) void Screen::scrollDown(int from, int n) { - //kDebug() << "Screen::scrollDown( from: " << from << " , n: " << n << ")"; - - _scrolledLines += n; + //kDebug() << "Screen::scrollDown( from: " << from << " , n: " << n << ")"; + + _scrolledLines += 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),' '); + 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),' '); } void Screen::setCursorYX(int y, int x) { - setCursorY(y); setCursorX(x); + setCursorY(y); + setCursorX(x); } void Screen::setCursorX(int x) { - if (x == 0) x = 1; // Default - x -= 1; // Adjust - cuX = qMax(0,qMin(columns-1, x)); + if (x == 0) x = 1; // Default + x -= 1; // Adjust + cuX = qMax(0,qMin(columns-1, x)); } void Screen::setCursorY(int y) { - if (y == 0) y = 1; // Default - y -= 1; // Adjust - cuY = qMax(0,qMin(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) )); + if (y == 0) y = 1; // Default + y -= 1; // Adjust + cuY = qMax(0,qMin(lines -1, y + (getMode(MODE_Origin) ? tmargin : 0) )); } void Screen::home() { - cuX = 0; - cuY = 0; + cuX = 0; + cuY = 0; } void Screen::Return() { - cuX = 0; + cuX = 0; } int Screen::getCursorX() const { - return cuX; + return cuX; } int Screen::getCursorY() const { - return cuY; + return cuY; } // Erasing --------------------------------------------------------------------- @@ -968,27 +954,25 @@ int Screen::getCursorY() const */ void Screen::clearImage(int loca, int loce, char c) -{ - int scr_TL=loc(0,hist->getLines()); - //FIXME: check positions +{ + 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(); - } + //Clear entire selection if it overlaps region to be moved... + if ( (sel_BR > (loca+scr_TL) )&&(sel_TL < (loce+scr_TL)) ) { + clearSelection(); + } - int topLine = loca/columns; - int bottomLine = loce/columns; + int topLine = loca/columns; + int bottomLine = loce/columns; - Character clearCh(c,cu_fg,cu_bg,DEFAULT_RENDITION); - - //if the character being used to clear the area is the same as the - //default character, the affected lines can simply be shrunk. - bool isDefaultCh = (clearCh == Character()); + Character clearCh(c,cu_fg,cu_bg,DEFAULT_RENDITION); - for (int y=topLine;y<=bottomLine;y++) - { + //if the character being used to clear the area is the same as the + //default character, the affected lines can simply be shrunk. + bool isDefaultCh = (clearCh == Character()); + + for (int y=topLine; y<=bottomLine; y++) { lineProperties[y] = 0; int endCol = ( y == bottomLine) ? loce%columns : columns-1; @@ -996,24 +980,21 @@ void Screen::clearImage(int loca, int loce, char c) QVector& line = screenLines[y]; - if ( isDefaultCh && endCol == columns-1 ) - { + if ( isDefaultCh && endCol == columns-1 ) { line.resize(startCol); - } - else - { + } else { if (line.size() < endCol + 1) line.resize(endCol+1); Character* data = line.data(); - for (int i=startCol;i<=endCol;i++) + for (int i=startCol; i<=endCol; i++) data[i]=clearCh; } - } + } } /*! move image between (including) `sourceBegin' and `sourceEnd' to 'dest'. - + The 'dest', 'sourceBegin' and 'sourceEnd' parameters can be generated using the loc(column,line) macro. @@ -1026,101 +1007,91 @@ NOTE: moveImage() can only move whole lines. void Screen::moveImage(int dest, int sourceBegin, int sourceEnd) { - //kDebug() << "moving image from (" << (sourceBegin/columns) - // << "," << (sourceEnd/columns) << ") to " << - // (dest/columns); + //kDebug() << "moving image from (" << (sourceBegin/columns) + // << "," << (sourceEnd/columns) << ") to " << + // (dest/columns); - Q_ASSERT( sourceBegin <= sourceEnd ); - - int lines=(sourceEnd-sourceBegin)/columns; + Q_ASSERT( sourceBegin <= sourceEnd ); - //move screen image and line properties: - //the source and destination areas of the image may overlap, - //so it matters that we do the copy in the right order - - //forwards if dest < sourceBegin or backwards otherwise. - //(search the web for 'memmove implementation' for details) - if (dest < sourceBegin) - { - for (int i=0;i<=lines;i++) - { - screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ]; - lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i]; + int lines=(sourceEnd-sourceBegin)/columns; + + //move screen image and line properties: + //the source and destination areas of the image may overlap, + //so it matters that we do the copy in the right order - + //forwards if dest < sourceBegin or backwards otherwise. + //(search the web for 'memmove implementation' for details) + if (dest < sourceBegin) { + for (int i=0; i<=lines; i++) { + screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ]; + lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i]; + } + } else { + for (int i=lines; i>=0; i--) { + screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ]; + lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i]; + } } - } - else - { - for (int i=lines;i>=0;i--) - { - screenLines[ (dest/columns)+i ] = screenLines[ (sourceBegin/columns)+i ]; - lineProperties[(dest/columns)+i]=lineProperties[(sourceBegin/columns)+i]; + + if (lastPos != -1) { + int diff = dest - sourceBegin; // Scroll by this amount + lastPos += diff; + if ((lastPos < 0) || (lastPos >= (lines*columns))) + lastPos = -1; } - } - if (lastPos != -1) - { - int diff = dest - sourceBegin; // Scroll by this amount - lastPos += diff; - if ((lastPos < 0) || (lastPos >= (lines*columns))) - lastPos = -1; - } - - // Adjust selection to follow scroll. - if (sel_begin != -1) - { - bool beginIsTL = (sel_begin == sel_TL); - int diff = dest - sourceBegin; // Scroll by this amount - int scr_TL=loc(0,hist->getLines()); - int srca = sourceBegin+scr_TL; // Translate index from screen to global - int srce = sourceEnd+scr_TL; // Translate index from screen to global - int desta = srca+diff; - int deste = srce+diff; + // Adjust selection to follow scroll. + if (sel_begin != -1) { + bool beginIsTL = (sel_begin == sel_TL); + int diff = dest - sourceBegin; // Scroll by this amount + int scr_TL=loc(0,hist->getLines()); + int srca = sourceBegin+scr_TL; // Translate index from screen to global + int srce = sourceEnd+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_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 >= 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 (sel_BR < 0) { + clearSelection(); + } else { + if (sel_TL < 0) + sel_TL = 0; + } - if (beginIsTL) - sel_begin = sel_TL; - else - sel_begin = sel_BR; - } + if (beginIsTL) + sel_begin = sel_TL; + else + sel_begin = sel_BR; + } } void Screen::clearToEndOfScreen() { - clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' '); + clearImage(loc(cuX,cuY),loc(columns-1,lines-1),' '); } void Screen::clearToBeginOfScreen() { - clearImage(loc(0,0),loc(cuX,cuY),' '); + clearImage(loc(0,0),loc(cuX,cuY),' '); } void Screen::clearEntireScreen() { - // Add entire screen to history - for (int i = 0; i < (lines-1); i++) - { - addHistLine(); scrollUp(0,1); - } + // 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),' '); + clearImage(loc(0,0),loc(columns-1,lines-1),' '); } /*! fill screen with 'E' @@ -1129,62 +1100,62 @@ void Screen::clearEntireScreen() void Screen::helpAlign() { - clearImage(loc(0,0),loc(columns-1,lines-1),'E'); + clearImage(loc(0,0),loc(columns-1,lines-1),'E'); } void Screen::clearToEndOfLine() { - clearImage(loc(cuX,cuY),loc(columns-1,cuY),' '); + clearImage(loc(cuX,cuY),loc(columns-1,cuY),' '); } void Screen::clearToBeginOfLine() { - clearImage(loc(0,cuY),loc(cuX,cuY),' '); + clearImage(loc(0,cuY),loc(cuX,cuY),' '); } void Screen::clearEntireLine() { - clearImage(loc(0,cuY),loc(columns-1,cuY),' '); + clearImage(loc(0,cuY),loc(columns-1,cuY),' '); } void Screen::setRendition(int re) { - cu_re |= re; - effectiveRendition(); + cu_re |= re; + effectiveRendition(); } void Screen::resetRendition(int re) { - cu_re &= ~re; - effectiveRendition(); + cu_re &= ~re; + effectiveRendition(); } void Screen::setDefaultRendition() { - setForeColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR); - setBackColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR); - cu_re = DEFAULT_RENDITION; - effectiveRendition(); + setForeColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR); + setBackColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR); + cu_re = DEFAULT_RENDITION; + effectiveRendition(); } void Screen::setForeColor(int space, int color) { - cu_fg = CharacterColor(space, color); + cu_fg = CharacterColor(space, color); - if ( cu_fg.isValid() ) - effectiveRendition(); - else - setForeColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR); + if ( cu_fg.isValid() ) + effectiveRendition(); + else + setForeColor(COLOR_SPACE_DEFAULT,DEFAULT_FORE_COLOR); } void Screen::setBackColor(int space, int color) { - cu_bg = CharacterColor(space, color); + cu_bg = CharacterColor(space, color); - if ( cu_bg.isValid() ) - effectiveRendition(); - else - setBackColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR); + if ( cu_bg.isValid() ) + effectiveRendition(); + else + setBackColor(COLOR_SPACE_DEFAULT,DEFAULT_BACK_COLOR); } /* ------------------------------------------------------------------------- */ @@ -1195,102 +1166,94 @@ void Screen::setBackColor(int space, int color) void Screen::clearSelection() { - sel_BR = -1; - sel_TL = -1; - sel_begin = -1; + sel_BR = -1; + sel_TL = -1; + sel_begin = -1; } void Screen::getSelectionStart(int& column , int& line) { - if ( sel_TL != -1 ) - { + if ( sel_TL != -1 ) { column = sel_TL % columns; - line = sel_TL / columns; - } - else - { + line = sel_TL / columns; + } else { column = cuX + getHistLines(); line = cuY + getHistLines(); } } void Screen::getSelectionEnd(int& column , int& line) { - if ( sel_BR != -1 ) - { + if ( sel_BR != -1 ) { column = sel_BR % columns; line = sel_BR / columns; - } - else - { + } else { column = cuX + getHistLines(); line = cuY + getHistLines(); - } + } } void Screen::setSelectionStart(/*const ScreenCursor& viewCursor ,*/ const int x, const int y, const bool mode) { // kDebug(1211) << "setSelBeginXY(" << x << "," << y << ")"; - sel_begin = loc(x,y); //+histCursor) ; + sel_begin = loc(x,y); //+histCursor) ; - /* FIXME, HACK to correct for x too far to the right... */ - if (x == columns) sel_begin--; + /* 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; + sel_BR = sel_begin; + sel_TL = sel_begin; + columnmode = mode; } void Screen::setSelectionEnd( const int x, const int y) { // kDebug(1211) << "setSelExtentXY(" << x << "," << y << ")"; - if (sel_begin == -1) return; - int l = loc(x,y); // + histCursor); + 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--; + 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; - } + sel_TL = sel_begin; + sel_BR = l; + } } bool Screen::isSelected( const int x,const int y) const { - if (columnmode) { - int sel_Left,sel_Right; - if ( sel_TL % columns < sel_BR % columns ) { - sel_Left = sel_TL; sel_Right = sel_BR; + 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 >= sel_TL / columns ) && ( y <= sel_BR / columns ); + //( y+histCursor >= sel_TL / columns ) && ( y+histCursor <= sel_BR / columns ); } else { - sel_Left = sel_BR; sel_Right = sel_TL; + //int pos = loc(x,y+histCursor); + int pos = loc(x,y); + return ( pos >= sel_TL && pos <= sel_BR ); } - return ( x >= sel_Left % columns ) && ( x <= sel_Right % columns ) && - ( y >= sel_TL / columns ) && ( y <= sel_BR / columns ); - //( y+histCursor >= sel_TL / columns ) && ( y+histCursor <= sel_BR / columns ); - } - else { - //int pos = loc(x,y+histCursor); - int pos = loc(x,y); - return ( pos >= sel_TL && pos <= sel_BR ); - } } QString Screen::selectedText(bool preserveLineBreaks) { - QString result; - QTextStream stream(&result, QIODevice::ReadWrite); - - PlainTextDecoder decoder; - decoder.begin(&stream); - writeSelectionToStream(&decoder , preserveLineBreaks); - decoder.end(); - - return result; + QString result; + QTextStream stream(&result, QIODevice::ReadWrite); + + PlainTextDecoder decoder; + decoder.begin(&stream); + writeSelectionToStream(&decoder , preserveLineBreaks); + decoder.end(); + + return result; } bool Screen::isSelectionValid() const @@ -1298,134 +1261,125 @@ bool Screen::isSelectionValid() const return ( sel_TL >= 0 && sel_BR >= 0 ); } -void Screen::writeSelectionToStream(TerminalCharacterDecoder* decoder , +void Screen::writeSelectionToStream(TerminalCharacterDecoder* decoder , bool preserveLineBreaks) { // do nothing if selection is invalid if ( !isSelectionValid() ) return; - int top = sel_TL / columns; - int left = sel_TL % columns; + int top = sel_TL / columns; + int left = sel_TL % columns; - int bottom = sel_BR / columns; - int right = sel_BR % columns; + int bottom = sel_BR / columns; + int right = sel_BR % columns; Q_ASSERT( top >= 0 && left >= 0 && bottom >= 0 && right >= 0 ); //kDebug() << "sel_TL = " << sel_TL; //kDebug() << "columns = " << columns; - for (int y=top;y<=bottom;y++) - { - int start = 0; - if ( y == top || columnmode ) start = left; - - int count = -1; - if ( y == bottom || columnmode ) count = right - start + 1; + for (int y=top; y<=bottom; y++) { + int start = 0; + if ( y == top || columnmode ) start = left; - const bool appendNewLine = ( y != bottom ); - copyLineToStream( y, - start, - count, - decoder, - appendNewLine, - preserveLineBreaks ); - } + int count = -1; + if ( y == bottom || columnmode ) count = right - start + 1; + + const bool appendNewLine = ( y != bottom ); + copyLineToStream( y, + start, + count, + decoder, + appendNewLine, + preserveLineBreaks ); + } } -void Screen::copyLineToStream(int line , - int start, +void Screen::copyLineToStream(int line , + int start, int count, TerminalCharacterDecoder* decoder, bool appendNewLine, bool preserveLineBreaks) { - //buffer to hold characters for decoding - //the buffer is static to avoid initialising every - //element on each call to copyLineToStream - //(which is unnecessary since all elements will be overwritten anyway) - static const int MAX_CHARS = 1024; - static Character characterBuffer[MAX_CHARS]; - - assert( count < MAX_CHARS ); + //buffer to hold characters for decoding + //the buffer is static to avoid initialising every + //element on each call to copyLineToStream + //(which is unnecessary since all elements will be overwritten anyway) + static const int MAX_CHARS = 1024; + static Character characterBuffer[MAX_CHARS]; - LineProperty currentLineProperties = 0; + assert( count < MAX_CHARS ); - //determine if the line is in the history buffer or the screen image - if (line < hist->getLines()) - { - const int lineLength = hist->getLineLen(line); + LineProperty currentLineProperties = 0; - // ensure that start position is before end of line - start = qMin(start,qMax(0,lineLength-1)); + //determine if the line is in the history buffer or the screen image + if (line < hist->getLines()) { + const int lineLength = hist->getLineLen(line); - //retrieve line from history buffer - if (count == -1) - { - count = lineLength-start; - } - else - { - count = qMin(start+count,lineLength)-start; - } + // ensure that start position is before end of line + start = qMin(start,qMax(0,lineLength-1)); - // safety checks - assert( start >= 0 ); - assert( count >= 0 ); - assert( (start+count) <= hist->getLineLen(line) ); - - hist->getCells(line,start,count,characterBuffer); - - if ( hist->isWrappedLine(line) ) - currentLineProperties |= LINE_WRAPPED; - } - else - { - if ( count == -1 ) - count = columns - start; - - assert( count >= 0 ); - - const int screenLine = line-hist->getLines(); - - Character* data = screenLines[screenLine].data(); - int length = screenLines[screenLine].count(); - - //retrieve line from screen image - for (int i=start;i < qMin(start+count,length);i++) - { - characterBuffer[i-start] = data[i]; - } - - // count cannot be any greater than length - count = qBound(0,count,length-start); - - Q_ASSERT( screenLine < lineProperties.count() ); - currentLineProperties |= lineProperties[screenLine]; - } - - //do not decode trailing whitespace characters - for (int i=count-1 ; i >= 0; i--) - if (QChar(characterBuffer[i].character).isSpace()) - count--; - else - break; - - // add new line character at end - const bool omitLineBreak = (currentLineProperties & LINE_WRAPPED) || - !preserveLineBreaks; - - if ( !omitLineBreak && appendNewLine && (count+1 < MAX_CHARS) ) - { - characterBuffer[count] = '\n'; - count++; + //retrieve line from history buffer + if (count == -1) { + count = lineLength-start; + } else { + count = qMin(start+count,lineLength)-start; } - //decode line and write to text stream - decoder->decodeLine( (Character*) characterBuffer , - count, currentLineProperties ); + // safety checks + assert( start >= 0 ); + assert( count >= 0 ); + assert( (start+count) <= hist->getLineLen(line) ); + + hist->getCells(line,start,count,characterBuffer); + + if ( hist->isWrappedLine(line) ) + currentLineProperties |= LINE_WRAPPED; + } else { + if ( count == -1 ) + count = columns - start; + + assert( count >= 0 ); + + const int screenLine = line-hist->getLines(); + + Character* data = screenLines[screenLine].data(); + int length = screenLines[screenLine].count(); + + //retrieve line from screen image + for (int i=start; i < qMin(start+count,length); i++) { + characterBuffer[i-start] = data[i]; + } + + // count cannot be any greater than length + count = qBound(0,count,length-start); + + Q_ASSERT( screenLine < lineProperties.count() ); + currentLineProperties |= lineProperties[screenLine]; + } + + //do not decode trailing whitespace characters + for (int i=count-1 ; i >= 0; i--) + if (QChar(characterBuffer[i].character).isSpace()) + count--; + else + break; + + // add new line character at end + const bool omitLineBreak = (currentLineProperties & LINE_WRAPPED) || + !preserveLineBreaks; + + if ( !omitLineBreak && appendNewLine && (count+1 < MAX_CHARS) ) { + characterBuffer[count] = '\n'; + count++; + } + + //decode line and write to text stream + decoder->decodeLine( (Character*) characterBuffer , + count, currentLineProperties ); } // Method below has been removed because of its reliance on 'histCursor' @@ -1437,132 +1391,121 @@ void Screen::copyLineToStream(int line , sel_BR = sel_begin; sel_TL = sel_begin; setSelectionEnd(columns-1,lines-1+hist->getLines()-histCursor); - + writeSelectionToStream(stream,decoder); - + clearSelection(); }*/ void Screen::writeToStream(TerminalCharacterDecoder* decoder, int from, int to) { - sel_begin = loc(0,from); - sel_TL = sel_begin; - sel_BR = loc(columns-1,to); - writeSelectionToStream(decoder); - clearSelection(); + sel_begin = loc(0,from); + sel_TL = sel_begin; + sel_BR = loc(columns-1,to); + writeSelectionToStream(decoder); + clearSelection(); } QString Screen::getHistoryLine(int no) { - sel_begin = loc(0,no); - sel_TL = sel_begin; - sel_BR = loc(columns-1,no); - return selectedText(false); + sel_begin = loc(0,no); + sel_TL = sel_begin; + sel_BR = loc(columns-1,no); + return selectedText(false); } void Screen::addHistLine() { - // add line to history buffer - // we have to take care about scrolling, too... + // add line to history buffer + // we have to take care about scrolling, too... - if (hasScroll()) - { - int oldHistLines = hist->getLines(); + if (hasScroll()) { + int oldHistLines = hist->getLines(); - hist->addCellsVector(screenLines[0]); - hist->addLine( lineProperties[0] & LINE_WRAPPED ); + hist->addCellsVector(screenLines[0]); + hist->addLine( lineProperties[0] & LINE_WRAPPED ); - int newHistLines = hist->getLines(); + int newHistLines = hist->getLines(); - bool beginIsTL = (sel_begin == sel_TL); + bool beginIsTL = (sel_begin == sel_TL); - // If the history is full, increment the count - // of dropped lines - if ( newHistLines == oldHistLines ) - _droppedLines++; + // If the history is full, increment the count + // of dropped lines + if ( newHistLines == oldHistLines ) + _droppedLines++; - // Adjust selection for the new point of reference - if (newHistLines > oldHistLines) - { - if (sel_begin != -1) - { - sel_TL += columns; - sel_BR += columns; - } + // Adjust selection for the new point of reference + if (newHistLines > oldHistLines) { + if (sel_begin != -1) { + sel_TL += columns; + sel_BR += columns; + } + } + + 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 (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; - } - } - } int Screen::getHistLines() { - return hist->getLines(); + return hist->getLines(); } void Screen::setScroll(const HistoryType& t , bool copyPreviousScroll) { - clearSelection(); + clearSelection(); - if ( copyPreviousScroll ) - hist = t.scroll(hist); - else - { - HistoryScroll* oldScroll = hist; - hist = t.scroll(0); - delete oldScroll; - } + if ( copyPreviousScroll ) + hist = t.scroll(hist); + else { + HistoryScroll* oldScroll = hist; + hist = t.scroll(0); + delete oldScroll; + } } bool Screen::hasScroll() { - return hist->hasScroll(); + return hist->hasScroll(); } const HistoryType& Screen::getScroll() { - return hist->getType(); + return hist->getType(); } void Screen::setLineProperty(LineProperty property , bool enable) { - if ( enable ) - { - lineProperties[cuY] = (LineProperty)(lineProperties[cuY] | property); - } - else - { - lineProperties[cuY] = (LineProperty)(lineProperties[cuY] & ~property); - } + if ( enable ) { + lineProperties[cuY] = (LineProperty)(lineProperties[cuY] | property); + } else { + lineProperties[cuY] = (LineProperty)(lineProperties[cuY] & ~property); + } } void Screen::fillWithDefaultChar(Character* dest, int count) { - for (int i=0;iNew line mode is disabled. TODO Document me * * - * If @p clearScreen is true then the screen contents are erased entirely, + * If @p clearScreen is true then the screen contents are erased entirely, * otherwise they are unaltered. */ void reset(bool clearScreen = true); - - /** - * Displays a new character at the current cursor position. - * + + /** + * Displays a new character at the current cursor position. + * * If the cursor is currently positioned at the right-edge of the screen and - * line wrapping is enabled then the character is added at the start of a new + * line wrapping is enabled then the character is added at the start of a new * line below the current one. * - * If the MODE_Insert screen mode is currently enabled then the character - * is inserted at the current cursor position, otherwise it will replace the - * character already at the current cursor position. - */ + * If the MODE_Insert screen mode is currently enabled then the character + * is inserted at the current cursor position, otherwise it will replace the + * character already at the current cursor position. + */ void ShowCharacter(unsigned short c); - + // Do composition with last shown character FIXME: Not implemented yet for KDE 4 void compose(const QString& compose); - - /** - * Resizes the image to a new fixed size of @p new_lines by @p new_columns. + + /** + * Resizes the image to a new fixed size of @p new_lines by @p new_columns. * In the case that @p new_columns is smaller than the current number of columns, * existing lines are not truncated. This prevents characters from being lost * if the terminal display is resized smaller and then larger again. @@ -356,9 +355,9 @@ public: * truncated when making the screen image smaller) */ void resizeImage(int new_lines, int new_columns); - + /** - * Returns the current screen image. + * Returns the current screen image. * The result is an array of Characters of size [getLines()][getColumns()] which * must be freed by the caller after use. * @@ -369,36 +368,40 @@ public: */ void getImage( Character* dest , int size , int startLine , int endLine ) const; - /** + /** * Returns the additional attributes associated with lines in the image. - * The most important attribute is LINE_WRAPPED which specifies that the + * The most important attribute is LINE_WRAPPED which specifies that the * line is wrapped, * other attributes control the size of characters in the line. */ QVector getLineProperties( int startLine , int endLine ) const; - + /** Return the number of lines. */ - int getLines() { return lines; } + int getLines() { + return lines; + } /** Return the number of columns. */ - int getColumns() { return columns; } + int getColumns() { + return columns; + } /** Return the number of lines in the history buffer. */ int getHistLines (); - /** - * Sets the type of storage used to keep lines in the history. - * If @p copyPreviousScroll is true then the contents of the previous + /** + * Sets the type of storage used to keep lines in the history. + * If @p copyPreviousScroll is true then the contents of the previous * history buffer are copied into the new scroll. */ void setScroll(const HistoryType& , bool copyPreviousScroll = true); /** Returns the type of storage used to keep lines in the history. */ const HistoryType& getScroll(); - /** + /** * Returns true if this screen keeps lines that are scrolled off the screen * in a history buffer. */ bool hasScroll(); - /** + /** * Sets the start of the selection. * * @param column The column index of the first character in the selection. @@ -406,21 +409,21 @@ public: * @param columnmode True if the selection is in column mode. */ void setSelectionStart(const int column, const int line, const bool columnmode); - + /** * Sets the end of the current selection. * * @param column The column index of the last character in the selection. - * @param line The line index of the last character in the selection. - */ + * @param line The line index of the last character in the selection. + */ void setSelectionEnd(const int column, const int line); - + /** * Retrieves the start of the selection or the cursor position if there * is no selection. */ void getSelectionStart(int& column , int& line); - + /** * Retrieves the end of the selection or the cursor position if there * is no selection. @@ -430,87 +433,89 @@ public: /** Clears the current selection */ void clearSelection(); - void setBusySelecting(bool busy) { sel_busy = busy; } + void setBusySelecting(bool busy) { + sel_busy = busy; + } - /** - * Returns true if the character at (@p column, @p line) is part of the - * current selection. - */ + /** + * Returns true if the character at (@p column, @p line) is part of the + * current selection. + */ bool isSelected(const int column,const int line) const; - /** - * Convenience method. Returns the currently selected text. - * @param preserveLineBreaks Specifies whether new line characters should + /** + * Convenience method. Returns the currently selected text. + * @param preserveLineBreaks Specifies whether new line characters should * be inserted into the returned text at the end of each terminal line. */ QString selectedText(bool preserveLineBreaks); - - /** - * Copies part of the output to a stream. - * - * @param decoder A decoder which coverts terminal characters into text - * @param from The first line in the history to retrieve - * @param to The last line in the history to retrieve - */ - void writeToStream(TerminalCharacterDecoder* decoder, int from, int to); - /** + /** + * Copies part of the output to a stream. + * + * @param decoder A decoder which coverts terminal characters into text + * @param from The first line in the history to retrieve + * @param to The last line in the history to retrieve + */ + void writeToStream(TerminalCharacterDecoder* decoder, int from, int to); + + /** * Sets the selection to line @p no in the history and returns * the text of that line from the history buffer. */ QString getHistoryLine(int no); - /** - * Copies the selected characters, set using @see setSelBeginXY and @see setSelExtentXY - * into a stream. - * - * @param decoder A decoder which converts terminal characters into text. - * PlainTextDecoder is the most commonly used decoder which coverts characters - * into plain text with no formatting. - * @param preserveLineBreaks Specifies whether new line characters should - * be inserted into the returned text at the end of each terminal line. - */ - void writeSelectionToStream(TerminalCharacterDecoder* decoder , bool + /** + * Copies the selected characters, set using @see setSelBeginXY and @see setSelExtentXY + * into a stream. + * + * @param decoder A decoder which converts terminal characters into text. + * PlainTextDecoder is the most commonly used decoder which coverts characters + * into plain text with no formatting. + * @param preserveLineBreaks Specifies whether new line characters should + * be inserted into the returned text at the end of each terminal line. + */ + void writeSelectionToStream(TerminalCharacterDecoder* decoder , bool preserveLineBreaks = true); /** TODO Document me */ void checkSelection(int from, int to); - /** - * Sets or clears an attribute of the current line. - * - * @param property The attribute to set or clear - * Possible properties are: - * LINE_WRAPPED: Specifies that the line is wrapped. - * LINE_DOUBLEWIDTH: Specifies that the characters in the current line should be double the normal width. - * LINE_DOUBLEHEIGHT:Specifies that the characters in the current line should be double the normal height. + /** + * Sets or clears an attribute of the current line. + * + * @param property The attribute to set or clear + * Possible properties are: + * LINE_WRAPPED: Specifies that the line is wrapped. + * LINE_DOUBLEWIDTH: Specifies that the characters in the current line should be double the normal width. + * LINE_DOUBLEHEIGHT:Specifies that the characters in the current line should be double the normal height. * Double-height lines are formed of two lines containing the same characters, - * with both having the LINE_DOUBLEHEIGHT attribute. This allows other parts of the + * with both having the LINE_DOUBLEHEIGHT attribute. This allows other parts of the * code to work on the assumption that all lines are the same height. - * - * @param enable true to apply the attribute to the current line or false to remove it - */ - void setLineProperty(LineProperty property , bool enable); + * + * @param enable true to apply the attribute to the current line or false to remove it + */ + void setLineProperty(LineProperty property , bool enable); - /** + /** * Returns the number of lines that the image has been scrolled up or down by, * since the last call to resetScrolledLines(). * * a positive return value indicates that the image has been scrolled up, - * a negative return value indicates that the image has been scrolled down. + * a negative return value indicates that the image has been scrolled down. */ int scrolledLines() const; /** * Returns the region of the image which was last scrolled. * - * This is the area of the image from the top margin to the + * This is the area of the image from the top margin to the * bottom margin when the last scroll occurred. */ QRect lastScrolledRegion() const; - /** + /** * Resets the count of the number of lines that the image has been scrolled up or down by, * see scrolledLines() */ @@ -523,7 +528,7 @@ public: * * If the history is not unlimited then it will drop * the oldest lines of output if new lines are added when - * it is full. + * it is full. */ int droppedLines() const; @@ -533,29 +538,29 @@ public: */ void resetDroppedLines(); - /** - * Fills the buffer @p dest with @p count instances of the default (ie. blank) - * Character style. - */ - static void fillWithDefaultChar(Character* dest, int count); + /** + * Fills the buffer @p dest with @p count instances of the default (ie. blank) + * Character style. + */ + static void fillWithDefaultChar(Character* dest, int count); -private: +private: - //copies a line of text from the screen or history into a stream using a - //specified character decoder - //line - the line number to copy, from 0 (the earliest line in the history) up to - // hist->getLines() + lines - 1 - //start - the first column on the line to copy - //count - the number of characters on the line to copy - //decoder - a decoder which coverts terminal characters (an Character array) into text + //copies a line of text from the screen or history into a stream using a + //specified character decoder + //line - the line number to copy, from 0 (the earliest line in the history) up to + // hist->getLines() + lines - 1 + //start - the first column on the line to copy + //count - the number of characters on the line to copy + //decoder - a decoder which coverts terminal characters (an Character array) into text //appendNewLine - if true a new line character (\n) is appended to the end of the line - void copyLineToStream(int line, - int start, - int count, + void copyLineToStream(int line, + int start, + int count, TerminalCharacterDecoder* decoder, bool appendNewLine, bool preserveLineBreaks); - + //fills a section of the screen image with the character 'c' //the parameters are specified as offsets from the start of the screen image. //the loc(x,y) macro can be used to generate these values from a column,line pair. @@ -565,7 +570,7 @@ private: //the parameters are specified as offsets from the start of the screen image. //the loc(x,y) macro can be used to generate these values from a column,line pair. void moveImage(int dest, int sourceBegin, int sourceEnd); - + void scrollUp(int from, int i); void scrollDown(int from, int i); @@ -578,12 +583,12 @@ private: bool isSelectionValid() const; - // copies 'count' lines from the screen buffer into 'dest', - // starting from 'startLine', where 0 is the first line in the screen buffer - void copyFromScreen(Character* dest, int startLine, int count) const; - // copies 'count' lines from the history buffer into 'dest', - // starting from 'startLine', where 0 is the first line in the history - void copyFromHistory(Character* dest, int startLine, int count) const; + // copies 'count' lines from the screen buffer into 'dest', + // starting from 'startLine', where 0 is the first line in the screen buffer + void copyFromScreen(Character* dest, int startLine, int count) const; + // copies 'count' lines from the history buffer into 'dest', + // starting from 'startLine', where 0 is the first line in the history + void copyFromHistory(Character* dest, int startLine, int count) const; // screen image ---------------- @@ -598,11 +603,11 @@ private: int _droppedLines; - QVarLengthArray lineProperties; - + QVarLengthArray lineProperties; + // history buffer --------------- HistoryScroll *hist; - + // cursor location int cuX; int cuY; @@ -637,7 +642,7 @@ private: // // save cursor, rendition & states ------------ - // + // // cursor location int sa_cuX; @@ -647,7 +652,7 @@ private: quint8 sa_cu_re; CharacterColor sa_cu_fg; CharacterColor sa_cu_bg; - + // last position where we added a character int lastPos; diff --git a/lib/ScreenWindow.cpp b/lib/ScreenWindow.cpp index f29dcd0..44da2d2 100644 --- a/lib/ScreenWindow.cpp +++ b/lib/ScreenWindow.cpp @@ -31,19 +31,19 @@ using namespace Konsole; ScreenWindow::ScreenWindow(QObject* parent) - : QObject(parent) - , _windowBuffer(0) - , _windowBufferSize(0) - , _bufferNeedsUpdate(true) - , _windowLines(1) - , _currentLine(0) - , _trackOutput(true) - , _scrollCount(0) + : QObject(parent) + , _windowBuffer(0) + , _windowBufferSize(0) + , _bufferNeedsUpdate(true) + , _windowLines(1) + , _currentLine(0) + , _trackOutput(true) + , _scrollCount(0) { } ScreenWindow::~ScreenWindow() { - delete[] _windowBuffer; + delete[] _windowBuffer; } void ScreenWindow::setScreen(Screen* screen) { @@ -59,43 +59,42 @@ Screen* ScreenWindow::screen() const Character* ScreenWindow::getImage() { - // reallocate internal buffer if the window size has changed - int size = windowLines() * windowColumns(); - if (_windowBuffer == 0 || _windowBufferSize != size) - { - delete[] _windowBuffer; - _windowBufferSize = size; - _windowBuffer = new Character[size]; - _bufferNeedsUpdate = true; - } + // reallocate internal buffer if the window size has changed + int size = windowLines() * windowColumns(); + if (_windowBuffer == 0 || _windowBufferSize != size) { + delete[] _windowBuffer; + _windowBufferSize = size; + _windowBuffer = new Character[size]; + _bufferNeedsUpdate = true; + } - if (!_bufferNeedsUpdate) - return _windowBuffer; - - _screen->getImage(_windowBuffer,size, - currentLine(),endWindowLine()); + if (!_bufferNeedsUpdate) + return _windowBuffer; - // this window may look beyond the end of the screen, in which - // case there will be an unused area which needs to be filled - // with blank characters - fillUnusedArea(); + _screen->getImage(_windowBuffer,size, + currentLine(),endWindowLine()); - _bufferNeedsUpdate = false; - return _windowBuffer; + // this window may look beyond the end of the screen, in which + // case there will be an unused area which needs to be filled + // with blank characters + fillUnusedArea(); + + _bufferNeedsUpdate = false; + return _windowBuffer; } void ScreenWindow::fillUnusedArea() { - int screenEndLine = _screen->getHistLines() + _screen->getLines() - 1; - int windowEndLine = currentLine() + windowLines() - 1; + int screenEndLine = _screen->getHistLines() + _screen->getLines() - 1; + int windowEndLine = currentLine() + windowLines() - 1; - int unusedLines = windowEndLine - screenEndLine; - int charsToFill = unusedLines * windowColumns(); + int unusedLines = windowEndLine - screenEndLine; + int charsToFill = unusedLines * windowColumns(); - Screen::fillWithDefaultChar(_windowBuffer + _windowBufferSize - charsToFill,charsToFill); + Screen::fillWithDefaultChar(_windowBuffer + _windowBufferSize - charsToFill,charsToFill); } -// return the index of the line at the end of this window, or if this window +// return the index of the line at the end of this window, or if this window // goes beyond the end of the screen, the index of the line at the end // of the screen. // @@ -104,17 +103,17 @@ void ScreenWindow::fillUnusedArea() // int ScreenWindow::endWindowLine() const { - return qMin(currentLine() + windowLines() - 1, - lineCount() - 1); + return qMin(currentLine() + windowLines() - 1, + lineCount() - 1); } QVector ScreenWindow::getLineProperties() { QVector result = _screen->getLineProperties(currentLine(),endWindowLine()); - - if (result.count() != windowLines()) - result.resize(windowLines()); - return result; + if (result.count() != windowLines()) + result.resize(windowLines()); + + return result; } QString ScreenWindow::selectedText( bool preserveLineBreaks ) const @@ -135,8 +134,8 @@ void ScreenWindow::getSelectionEnd( int& column , int& line ) void ScreenWindow::setSelectionStart( int column , int line , bool columnMode ) { _screen->setSelectionStart( column , qMin(line + currentLine(),endWindowLine()) , columnMode); - - _bufferNeedsUpdate = true; + + _bufferNeedsUpdate = true; emit selectionChanged(); } @@ -144,7 +143,7 @@ void ScreenWindow::setSelectionEnd( int column , int line ) { _screen->setSelectionEnd( column , qMin(line + currentLine(),endWindowLine()) ); - _bufferNeedsUpdate = true; + _bufferNeedsUpdate = true; emit selectionChanged(); } @@ -162,12 +161,12 @@ void ScreenWindow::clearSelection() void ScreenWindow::setWindowLines(int lines) { - Q_ASSERT(lines > 0); - _windowLines = lines; + Q_ASSERT(lines > 0); + _windowLines = lines; } int ScreenWindow::windowLines() const { - return _windowLines; + return _windowLines; } int ScreenWindow::windowColumns() const @@ -188,11 +187,11 @@ int ScreenWindow::columnCount() const QPoint ScreenWindow::cursorPosition() const { QPoint position; - + position.setX( _screen->getCursorX() ); position.setY( _screen->getCursorY() ); - return position; + return position; } int ScreenWindow::currentLine() const @@ -202,13 +201,10 @@ int ScreenWindow::currentLine() const void ScreenWindow::scrollBy( RelativeScrollMode mode , int amount ) { - if ( mode == ScrollLines ) - { + if ( mode == ScrollLines ) { scrollTo( currentLine() + amount ); - } - else if ( mode == ScrollPages ) - { - scrollTo( currentLine() + amount * ( windowLines() / 2 ) ); + } else if ( mode == ScrollPages ) { + scrollTo( currentLine() + amount * ( windowLines() / 2 ) ); } } @@ -219,8 +215,8 @@ bool ScreenWindow::atEndOfOutput() const void ScreenWindow::scrollTo( int line ) { - int maxCurrentLineNumber = lineCount() - windowLines(); - line = qBound(0,line,maxCurrentLineNumber); + int maxCurrentLineNumber = lineCount() - windowLines(); + line = qBound(0,line,maxCurrentLineNumber); const int delta = line - _currentLine; _currentLine = line; @@ -249,48 +245,45 @@ int ScreenWindow::scrollCount() const return _scrollCount; } -void ScreenWindow::resetScrollCount() +void ScreenWindow::resetScrollCount() { _scrollCount = 0; } QRect ScreenWindow::scrollRegion() const { - bool equalToScreenSize = windowLines() == _screen->getLines(); + bool equalToScreenSize = windowLines() == _screen->getLines(); - if ( atEndOfOutput() && equalToScreenSize ) - return _screen->lastScrolledRegion(); - else - return QRect(0,0,windowColumns(),windowLines()); + if ( atEndOfOutput() && equalToScreenSize ) + return _screen->lastScrolledRegion(); + else + return QRect(0,0,windowColumns(),windowLines()); } void ScreenWindow::notifyOutputChanged() { // move window to the bottom of the screen and update scroll count // if this window is currently tracking the bottom of the screen - if ( _trackOutput ) - { + if ( _trackOutput ) { _scrollCount -= _screen->scrolledLines(); _currentLine = qMax(0,_screen->getHistLines() - (windowLines()-_screen->getLines())); - } - else - { - // if the history is not unlimited then it may + } else { + // if the history is not unlimited then it may // have run out of space and dropped the oldest // lines of output - in this case the screen - // window's current line number will need to + // window's current line number will need to // be adjusted - otherwise the output will scroll - _currentLine = qMax(0,_currentLine - - _screen->droppedLines()); + _currentLine = qMax(0,_currentLine - + _screen->droppedLines()); // ensure that the screen window's current position does // not go beyond the bottom of the screen _currentLine = qMin( _currentLine , _screen->getHistLines() ); } - _bufferNeedsUpdate = true; + _bufferNeedsUpdate = true; - emit outputChanged(); + emit outputChanged(); } //#include "moc_ScreenWindow.cpp" diff --git a/lib/ScreenWindow.h b/lib/ScreenWindow.h index d2955ab..f993e13 100644 --- a/lib/ScreenWindow.h +++ b/lib/ScreenWindow.h @@ -39,7 +39,7 @@ class Screen; * Provides a window onto a section of a terminal screen. * This window can then be rendered by a terminal display widget ( TerminalDisplay ). * - * To use the screen window, create a new ScreenWindow() instance and associated it with + * To use the screen window, create a new ScreenWindow() instance and associated it with * a terminal screen using setScreen(). * Use the scrollTo() method to scroll the window up and down on the screen. * Call the getImage() method to retrieve the character image which is currently visible in the window. @@ -53,10 +53,10 @@ class Screen; */ class ScreenWindow : public QObject { -Q_OBJECT + Q_OBJECT public: - /** + /** * Constructs a new screen window with the given parent. * A screen must be specified by calling setScreen() before calling getImage() or getLineProperties(). * @@ -66,14 +66,14 @@ public: * between all views on a session. */ ScreenWindow(QObject* parent = 0); - virtual ~ScreenWindow(); + virtual ~ScreenWindow(); /** Sets the screen which this window looks onto */ void setScreen(Screen* screen); /** Returns the screen which this window looks onto */ Screen* screen() const; - /** + /** * Returns the image of characters which are currently visible through this window * onto the screen. * @@ -90,14 +90,14 @@ public: /** * Returns the number of lines which the region of the window - * specified by scrollRegion() has been scrolled by since the last call - * to resetScrollCount(). scrollRegion() is in most cases the + * specified by scrollRegion() has been scrolled by since the last call + * to resetScrollCount(). scrollRegion() is in most cases the * whole window, but will be a smaller area in, for example, applications * which provide split-screen facilities. * * This is not guaranteed to be accurate, but allows views to optimise * rendering by reducing the amount of costly text rendering that - * needs to be done when the output is scrolled. + * needs to be done when the output is scrolled. */ int scrollCount() const; @@ -107,7 +107,7 @@ public: void resetScrollCount(); /** - * Returns the area of the window which was last scrolled, this is + * Returns the area of the window which was last scrolled, this is * usually the whole window area. * * Like scrollCount(), this is not guaranteed to be accurate, @@ -115,8 +115,8 @@ public: */ QRect scrollRegion() const; - /** - * Sets the start of the selection to the given @p line and @p column within + /** + * Sets the start of the selection to the given @p line and @p column within * the window. */ void setSelectionStart( int column , int line , bool columnMode ); @@ -124,7 +124,7 @@ public: * Sets the end of the selection to the given @p line and @p column within * the window. */ - void setSelectionEnd( int column , int line ); + void setSelectionEnd( int column , int line ); /** * Retrieves the start of the selection within the window. */ @@ -137,18 +137,18 @@ public: * Returns true if the character at @p line , @p column is part of the selection. */ bool isSelected( int column , int line ); - /** + /** * Clears the current selection */ void clearSelection(); - /** Sets the number of lines in the window */ - void setWindowLines(int lines); + /** Sets the number of lines in the window */ + void setWindowLines(int lines); /** Returns the number of lines in the window */ int windowLines() const; /** Returns the number of columns in the window */ int windowColumns() const; - + /** Returns the total number of lines in the screen */ int lineCount() const; /** Returns the total number of columns in the screen */ @@ -157,13 +157,13 @@ public: /** Returns the index of the line which is currently at the top of this window */ int currentLine() const; - /** - * Returns the position of the cursor + /** + * Returns the position of the cursor * within the window. */ QPoint cursorPosition() const; - /** + /** * Convenience method. Returns true if the window is currently at the bottom * of the screen. */ @@ -172,32 +172,31 @@ public: /** Scrolls the window so that @p line is at the top of the window */ void scrollTo( int line ); - enum RelativeScrollMode - { + enum RelativeScrollMode { ScrollLines, ScrollPages }; - /** + /** * Scrolls the window relative to its current position on the screen. * * @param mode Specifies whether @p amount refers to the number of lines or the number - * of pages to scroll. + * of pages to scroll. * @param amount The number of lines or pages ( depending on @p mode ) to scroll by. If * this number is positive, the view is scrolled down. If this number is negative, the view * is scrolled up. */ void scrollBy( RelativeScrollMode mode , int amount ); - /** + /** * Specifies whether the window should automatically move to the bottom * of the screen when new output is added. * - * If this is set to true, the window will be moved to the bottom of the associated screen ( see + * If this is set to true, the window will be moved to the bottom of the associated screen ( see * screen() ) when the notifyOutputChanged() method is called. */ void setTrackOutput(bool trackOutput); - /** + /** * Returns whether the window automatically moves to the bottom of the screen as * new output is added. See setTrackOutput() */ @@ -211,7 +210,7 @@ public: QString selectedText( bool preserveLineBreaks ) const; public slots: - /** + /** * Notifies the window that the contents of the associated terminal screen have changed. * This moves the window to the bottom of the screen if trackOutput() is true and causes * the outputChanged() signal to be emitted. @@ -220,13 +219,13 @@ public slots: signals: /** - * Emitted when the contents of the associated terminal screen ( see screen() ) changes. + * Emitted when the contents of the associated terminal screen ( see screen() ) changes. */ void outputChanged(); /** * Emitted when the screen window is scrolled to a different position. - * + * * @param line The line which is now at the top of the window. */ void scrolled(int line); @@ -237,19 +236,19 @@ signals: void selectionChanged(); private: - int endWindowLine() const; - void fillUnusedArea(); + int endWindowLine() const; + void fillUnusedArea(); Screen* _screen; // see setScreen() , screen() - Character* _windowBuffer; - int _windowBufferSize; - bool _bufferNeedsUpdate; + Character* _windowBuffer; + int _windowBufferSize; + bool _bufferNeedsUpdate; - int _windowLines; + int _windowLines; int _currentLine; // see scrollTo() , currentLine() - bool _trackOutput; // see setTrackOutput() , trackOutput() + bool _trackOutput; // see setTrackOutput() , trackOutput() int _scrollCount; // count of lines which the window has been scrolled by since - // the last call to resetScrollCount() + // the last call to resetScrollCount() }; } diff --git a/lib/Session.cpp b/lib/Session.cpp index 910a39f..771d59d 100644 --- a/lib/Session.cpp +++ b/lib/Session.cpp @@ -48,26 +48,26 @@ using namespace Konsole; int Session::lastSessionId = 0; Session::Session() : - _shellProcess(0) - , _emulation(0) - , _monitorActivity(false) - , _monitorSilence(false) - , _notifiedActivity(false) - , _autoClose(true) - , _wantedClose(false) - , _silenceSeconds(10) - , _addToUtmp(false) // disabled by default because of a bug encountered on certain systems - // which caused Konsole to hang when closing a tab and then opening a new - // one. A 'QProcess destroyed while still running' warning was being - // printed to the terminal. Likely a problem in KPty::logout() - // or KPty::login() which uses a QProcess to start /usr/bin/utempter - , _flowControl(true) - , _fullScripting(false) - , _sessionId(0) + _shellProcess(0) + , _emulation(0) + , _monitorActivity(false) + , _monitorSilence(false) + , _notifiedActivity(false) + , _autoClose(true) + , _wantedClose(false) + , _silenceSeconds(10) + , _addToUtmp(false) // disabled by default because of a bug encountered on certain systems + // which caused Konsole to hang when closing a tab and then opening a new + // one. A 'QProcess destroyed while still running' warning was being + // printed to the terminal. Likely a problem in KPty::logout() + // or KPty::login() which uses a QProcess to start /usr/bin/utempter + , _flowControl(true) + , _fullScripting(false) + , _sessionId(0) // , _zmodemBusy(false) // , _zmodemProc(0) // , _zmodemProgress(0) - , _hasDarkBackground(false) + , _hasDarkBackground(false) { //prepare DBus communication // new SessionAdaptor(this); @@ -81,15 +81,15 @@ Session::Session() : _emulation = new Vt102Emulation(); connect( _emulation, SIGNAL( titleChanged( int, const QString & ) ), - this, SLOT( setUserTitle( int, const QString & ) ) ); + this, SLOT( setUserTitle( int, const QString & ) ) ); connect( _emulation, SIGNAL( stateSet(int) ), - this, SLOT( activityStateSet(int) ) ); + this, SLOT( activityStateSet(int) ) ); // connect( _emulation, SIGNAL( zmodemDetected() ), this , // SLOT( fireZModemDetected() ) ); connect( _emulation, SIGNAL( changeTabTextColorRequest( int ) ), - this, SIGNAL( changeTabTextColorRequest( int ) ) ); + this, SIGNAL( changeTabTextColorRequest( int ) ) ); connect( _emulation, SIGNAL(profileChangeCommandReceived(const QString&)), - this, SIGNAL( profileChangeCommandReceived(const QString&)) ); + this, SIGNAL( profileChangeCommandReceived(const QString&)) ); // TODO // connect( _emulation,SIGNAL(imageSizeChanged(int,int)) , this , // SLOT(onEmulationSizeChange(int,int)) ); @@ -98,9 +98,9 @@ Session::Session() : _shellProcess->setUtf8Mode(_emulation->utf8()); connect( _shellProcess,SIGNAL(receivedData(const char*,int)),this, - SLOT(onReceiveBlock(const char*,int)) ); + SLOT(onReceiveBlock(const char*,int)) ); connect( _emulation,SIGNAL(sendData(const char*,int)),_shellProcess, - SLOT(sendData(const char*,int)) ); + SLOT(sendData(const char*,int)) ); connect( _emulation,SIGNAL(lockPtyRequest(bool)),_shellProcess,SLOT(lockPty(bool)) ); connect( _emulation,SIGNAL(useUtf8Request(bool)),_shellProcess,SLOT(setUtf8Mode(bool)) ); @@ -128,9 +128,8 @@ WId Session::windowId() const // returned if ( _views.count() == 0 ) - return 0; - else - { + return 0; + else { QWidget* window = _views.first(); Q_ASSERT( window ); @@ -180,24 +179,23 @@ QList Session::views() const void Session::addView(TerminalDisplay* widget) { - Q_ASSERT( !_views.contains(widget) ); + Q_ASSERT( !_views.contains(widget) ); _views.append(widget); - if ( _emulation != 0 ) - { + if ( _emulation != 0 ) { // connect emulation - view signals and slots connect( widget , SIGNAL(keyPressedSignal(QKeyEvent*)) , _emulation , - SLOT(sendKeyEvent(QKeyEvent*)) ); + SLOT(sendKeyEvent(QKeyEvent*)) ); connect( widget , SIGNAL(mouseSignal(int,int,int,int)) , _emulation , - SLOT(sendMouseEvent(int,int,int,int)) ); + SLOT(sendMouseEvent(int,int,int,int)) ); connect( widget , SIGNAL(sendStringToEmu(const char*)) , _emulation , - SLOT(sendString(const char*)) ); + SLOT(sendString(const char*)) ); // allow emulation to notify view when the foreground process // indicates whether or not it is interested in mouse signals connect( _emulation , SIGNAL(programUsesMouseChanged(bool)) , widget , - SLOT(setUsesMouse(bool)) ); + SLOT(setUsesMouse(bool)) ); widget->setUsesMouse( _emulation->programUsesMouse() ); @@ -206,13 +204,13 @@ void Session::addView(TerminalDisplay* widget) //connect view signals and slots QObject::connect( widget ,SIGNAL(changedContentSizeSignal(int,int)),this, - SLOT(onViewSizeChange(int,int))); + SLOT(onViewSizeChange(int,int))); QObject::connect( widget ,SIGNAL(destroyed(QObject*)) , this , - SLOT(viewDestroyed(QObject*)) ); + SLOT(viewDestroyed(QObject*)) ); //slot for close - QObject::connect(this, SIGNAL(finished()), widget, SLOT(close())); - + QObject::connect(this, SIGNAL(finished()), widget, SLOT(close())); + } void Session::viewDestroyed(QObject* view) @@ -228,10 +226,9 @@ void Session::removeView(TerminalDisplay* widget) { _views.removeAll(widget); - disconnect(widget,0,this,0); + disconnect(widget,0,this,0); - if ( _emulation != 0 ) - { + if ( _emulation != 0 ) { // disconnect // - key presses signals from widget // - mouse activity signals from widget @@ -244,151 +241,141 @@ void Session::removeView(TerminalDisplay* widget) disconnect( _emulation , 0 , widget , 0); } - // close the session automatically when the last view is removed - if ( _views.count() == 0 ) - { - close(); - } + // close the session automatically when the last view is removed + if ( _views.count() == 0 ) { + close(); + } } void Session::run() { - //check that everything is in place to run the session - if (_program.isEmpty()) - qDebug() << "Session::run() - program to run not set."; - if (_arguments.isEmpty()) - qDebug() << "Session::run() - no command line arguments specified."; + //check that everything is in place to run the session + if (_program.isEmpty()) + qDebug() << "Session::run() - program to run not set."; + if (_arguments.isEmpty()) + qDebug() << "Session::run() - no command line arguments specified."; - // 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(_program); + // 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(_program); - // if 'exec' is not specified, fall back to default shell. if that - // is not set then fall back to /bin/sh - if ( exec.isEmpty() ) - exec = getenv("SHELL"); - if ( exec.isEmpty() ) - exec = "/bin/sh"; + // if 'exec' is not specified, fall back to default shell. if that + // is not set then fall back to /bin/sh + if ( exec.isEmpty() ) + exec = getenv("SHELL"); + if ( exec.isEmpty() ) + exec = "/bin/sh"; - // if no arguments are specified, fall back to shell - QStringList arguments = _arguments.join(QChar(' ')).isEmpty() ? - QStringList() << exec : _arguments; - QString pexec = exec; + // if no arguments are specified, fall back to shell + QStringList arguments = _arguments.join(QChar(' ')).isEmpty() ? + QStringList() << exec : _arguments; + QString pexec = exec; - if ( pexec.isEmpty() ) { - qDebug()<<"can not execute "<setWorkingDirectory(_initialWorkingDir); - else - _shellProcess->setWorkingDirectory(cwd); + QString cwd = QDir::currentPath(); + if (!_initialWorkingDir.isEmpty()) + _shellProcess->setWorkingDirectory(_initialWorkingDir); + else + _shellProcess->setWorkingDirectory(cwd); // _shellProcess->setWorkingDirectory(QDir::homePath()); - _shellProcess->setXonXoff(_flowControl); - _shellProcess->setErase(_emulation->getErase()); + _shellProcess->setXonXoff(_flowControl); + _shellProcess->setErase(_emulation->getErase()); - // this is not strictly accurate use of the COLORFGBG variable. This does not - // tell the terminal exactly which colors are being used, but instead approximates - // the color scheme as "black on white" or "white on black" depending on whether - // the background color is deemed dark or not - QString backgroundColorHint = _hasDarkBackground ? "COLORFGBG=15;0" : "COLORFGBG=0;15"; + // this is not strictly accurate use of the COLORFGBG variable. This does not + // tell the terminal exactly which colors are being used, but instead approximates + // the color scheme as "black on white" or "white on black" depending on whether + // the background color is deemed dark or not + QString backgroundColorHint = _hasDarkBackground ? "COLORFGBG=15;0" : "COLORFGBG=0;15"; - int result = _shellProcess->start(QFile::encodeName(_program), - arguments, - _environment << backgroundColorHint, - windowId(), - _addToUtmp); + int result = _shellProcess->start(QFile::encodeName(_program), + arguments, + _environment << backgroundColorHint, + windowId(), + _addToUtmp); - if (result < 0) - { - return; - } + if (result < 0) { + return; + } - _shellProcess->setWriteable(false); // We are reachable via kwrited. + _shellProcess->setWriteable(false); // We are reachable via kwrited. - emit started(); + emit started(); } void Session::setUserTitle( int what, const QString &caption ) { //set to true if anything is actually changed (eg. old _nameTitle != new _nameTitle ) - bool modified = false; + bool modified = false; // (btw: what=0 changes _userTitle and icon, what=1 only icon, what=2 only _nameTitle - if ((what == 0) || (what == 2)) - { - if ( _userTitle != caption ) { - _userTitle = caption; - modified = true; - } + if ((what == 0) || (what == 2)) { + if ( _userTitle != caption ) { + _userTitle = caption; + modified = true; + } } - if ((what == 0) || (what == 1)) - { - if ( _iconText != caption ) { - _iconText = caption; - modified = true; - } - } - - if (what == 11) - { - QString colorString = caption.section(';',0,0); - qDebug() << __FILE__ << __LINE__ << ": setting background colour to " << colorString; - QColor backColor = QColor(colorString); - if (backColor.isValid()){// change color via \033]11;Color\007 - if (backColor != _modifiedBackground) - { - _modifiedBackground = backColor; - - // bail out here until the code to connect the terminal display - // to the changeBackgroundColor() signal has been written - // and tested - just so we don't forget to do this. - Q_ASSERT( 0 ); - - emit changeBackgroundColorRequest(backColor); - } - } + if ((what == 0) || (what == 1)) { + if ( _iconText != caption ) { + _iconText = caption; + modified = true; + } } - if (what == 30) - { - if ( _nameTitle != caption ) { - setTitle(Session::NameRole,caption); - return; - } - } + if (what == 11) { + QString colorString = caption.section(';',0,0); + qDebug() << __FILE__ << __LINE__ << ": setting background colour to " << colorString; + QColor backColor = QColor(colorString); + if (backColor.isValid()) {// change color via \033]11;Color\007 + if (backColor != _modifiedBackground) { + _modifiedBackground = backColor; - if (what == 31) - { - QString cwd=caption; - cwd=cwd.replace( QRegExp("^~"), QDir::homePath() ); - emit openUrlRequest(cwd); - } + // bail out here until the code to connect the terminal display + // to the changeBackgroundColor() signal has been written + // and tested - just so we don't forget to do this. + Q_ASSERT( 0 ); + + emit changeBackgroundColorRequest(backColor); + } + } + } + + if (what == 30) { + if ( _nameTitle != caption ) { + setTitle(Session::NameRole,caption); + return; + } + } + + if (what == 31) { + QString cwd=caption; + cwd=cwd.replace( QRegExp("^~"), QDir::homePath() ); + emit openUrlRequest(cwd); + } // change icon via \033]32;Icon\007 - if (what == 32) - { - if ( _iconName != caption ) { - _iconName = caption; + if (what == 32) { + if ( _iconName != caption ) { + _iconName = caption; - modified = true; - } + modified = true; + } } - if (what == 50) - { + if (what == 50) { emit profileChangeCommandReceived(caption); return; } - if ( modified ) - emit titleChanged(); + if ( modified ) + emit titleChanged(); } QString Session::userTitle() const @@ -414,68 +401,64 @@ QString Session::tabTitleFormat(TabTitleContext context) const void Session::monitorTimerDone() { - //FIXME: The idea here is that the notification popup will appear to tell the user than output from - //the terminal has stopped and the popup will disappear when the user activates the session. - // - //This breaks with the addition of multiple views of a session. The popup should disappear - //when any of the views of the session becomes active - + //FIXME: The idea here is that the notification popup will appear to tell the user than output from + //the terminal has stopped and the popup will disappear when the user activates the session. + // + //This breaks with the addition of multiple views of a session. The popup should disappear + //when any of the views of the session becomes active - //FIXME: Make message text for this notification and the activity notification more descriptive. - if (_monitorSilence) { + + //FIXME: Make message text for this notification and the activity notification more descriptive. + if (_monitorSilence) { // KNotification::event("Silence", ("Silence in session '%1'", _nameTitle), QPixmap(), // QApplication::activeWindow(), // KNotification::CloseWhenWidgetActivated); - emit stateChanged(NOTIFYSILENCE); - } - else - { - emit stateChanged(NOTIFYNORMAL); - } + emit stateChanged(NOTIFYSILENCE); + } else { + emit stateChanged(NOTIFYNORMAL); + } - _notifiedActivity=false; + _notifiedActivity=false; } void Session::activityStateSet(int state) { - if (state==NOTIFYBELL) - { - QString s; s.sprintf("Bell in session '%s'",_nameTitle.toAscii().data()); - - emit bellRequest( s ); - } - else if (state==NOTIFYACTIVITY) - { - if (_monitorSilence) { - _monitorTimer->start(_silenceSeconds*1000); - } + if (state==NOTIFYBELL) { + QString s; + s.sprintf("Bell in session '%s'",_nameTitle.toAscii().data()); - if ( _monitorActivity ) { - //FIXME: See comments in Session::monitorTimerDone() - if (!_notifiedActivity) { + emit bellRequest( s ); + } else if (state==NOTIFYACTIVITY) { + if (_monitorSilence) { + _monitorTimer->start(_silenceSeconds*1000); + } + + if ( _monitorActivity ) { + //FIXME: See comments in Session::monitorTimerDone() + if (!_notifiedActivity) { // KNotification::event("Activity", ("Activity in session '%1'", _nameTitle), QPixmap(), // QApplication::activeWindow(), // KNotification::CloseWhenWidgetActivated); - _notifiedActivity=true; - } + _notifiedActivity=true; + } + } } - } - if ( state==NOTIFYACTIVITY && !_monitorActivity ) - state = NOTIFYNORMAL; - if ( state==NOTIFYSILENCE && !_monitorSilence ) - state = NOTIFYNORMAL; + if ( state==NOTIFYACTIVITY && !_monitorActivity ) + state = NOTIFYNORMAL; + if ( state==NOTIFYSILENCE && !_monitorSilence ) + state = NOTIFYNORMAL; - emit stateChanged(state); + emit stateChanged(state); } void Session::onViewSizeChange(int /*height*/, int /*width*/) { - updateTerminalSize(); + updateTerminalSize(); } void Session::onEmulationSizeChange(int lines , int columns) { - setSize( QSize(lines,columns) ); + setSize( QSize(lines,columns) ); } void Session::updateTerminalSize() @@ -492,21 +475,18 @@ void Session::updateTerminalSize() const int VIEW_COLUMNS_THRESHOLD = 2; //select largest number of lines and columns that will fit in all visible views - while ( viewIter.hasNext() ) - { + while ( viewIter.hasNext() ) { TerminalDisplay* view = viewIter.next(); if ( view->isHidden() == false && - view->lines() >= VIEW_LINES_THRESHOLD && - view->columns() >= VIEW_COLUMNS_THRESHOLD ) - { + view->lines() >= VIEW_LINES_THRESHOLD && + view->columns() >= VIEW_COLUMNS_THRESHOLD ) { minLines = (minLines == -1) ? view->lines() : qMin( minLines , view->lines() ); minColumns = (minColumns == -1) ? view->columns() : qMin( minColumns , view->columns() ); } } // backend emulation must have a _terminal of at least 1 column x 1 line in size - if ( minLines > 0 && minColumns > 0 ) - { + if ( minLines > 0 && minColumns > 0 ) { _emulation->setImageSize( minLines , minColumns ); _shellProcess->setWindowSize( minLines , minColumns ); } @@ -535,29 +515,28 @@ void Session::refresh() bool Session::sendSignal(int signal) { - return _shellProcess->kill(signal); + return _shellProcess->kill(signal); } void Session::close() { - _autoClose = true; - _wantedClose = true; - if (!_shellProcess->isRunning() || !sendSignal(SIGHUP)) - { - // Forced close. - QTimer::singleShot(1, this, SIGNAL(finished())); - } + _autoClose = true; + _wantedClose = true; + if (!_shellProcess->isRunning() || !sendSignal(SIGHUP)) { + // Forced close. + QTimer::singleShot(1, this, SIGNAL(finished())); + } } void Session::sendText(const QString &text) const { - _emulation->sendText(text); + _emulation->sendText(text); } Session::~Session() { - delete _emulation; - delete _shellProcess; + delete _emulation; + delete _shellProcess; // delete _zmodemProc; } @@ -566,57 +545,54 @@ void Session::setProfileKey(const QString& key) _profileKey = key; emit profileChanged(key); } -QString Session::profileKey() const { return _profileKey; } +QString Session::profileKey() const +{ + return _profileKey; +} void Session::done(int exitStatus) { - if (!_autoClose) - { - _userTitle = (""); - emit titleChanged(); - return; - } - if (!_wantedClose && (exitStatus || _shellProcess->signalled())) - { - QString message; - - if (_shellProcess->normalExit()) - message.sprintf ("Session '%s' exited with status %d.", _nameTitle.toAscii().data(), exitStatus); - else if (_shellProcess->signalled()) - { - if (_shellProcess->coreDumped()) - { - - message.sprintf("Session '%s' exited with signal %d and dumped core.", _nameTitle.toAscii().data(), _shellProcess->exitSignal()); - } - else { - message.sprintf("Session '%s' exited with signal %d.", _nameTitle.toAscii().data(), _shellProcess->exitSignal()); - } + if (!_autoClose) { + _userTitle = (""); + emit titleChanged(); + return; } - else - message.sprintf ("Session '%s' exited unexpectedly.", _nameTitle.toAscii().data()); + if (!_wantedClose && (exitStatus || _shellProcess->signalled())) { + QString message; - //FIXME: See comments in Session::monitorTimerDone() + if (_shellProcess->normalExit()) + message.sprintf ("Session '%s' exited with status %d.", _nameTitle.toAscii().data(), exitStatus); + else if (_shellProcess->signalled()) { + if (_shellProcess->coreDumped()) { + + message.sprintf("Session '%s' exited with signal %d and dumped core.", _nameTitle.toAscii().data(), _shellProcess->exitSignal()); + } else { + message.sprintf("Session '%s' exited with signal %d.", _nameTitle.toAscii().data(), _shellProcess->exitSignal()); + } + } else + message.sprintf ("Session '%s' exited unexpectedly.", _nameTitle.toAscii().data()); + + //FIXME: See comments in Session::monitorTimerDone() // KNotification::event("Finished", message , QPixmap(), // QApplication::activeWindow(), // KNotification::CloseWhenWidgetActivated); - } - emit finished(); + } + emit finished(); } Emulation* Session::emulation() const { - return _emulation; + return _emulation; } QString Session::keyBindings() const { - return _emulation->keyBindings(); + return _emulation->keyBindings(); } QStringList Session::environment() const { - return _environment; + return _environment; } void Session::setEnvironment(const QStringList& environment) @@ -626,18 +602,17 @@ void Session::setEnvironment(const QStringList& environment) int Session::sessionId() const { - return _sessionId; + return _sessionId; } void Session::setKeyBindings(const QString &id) { - _emulation->setKeyBindings(id); + _emulation->setKeyBindings(id); } void Session::setTitle(TitleRole role , const QString& newTitle) { - if ( title(role) != newTitle ) - { + if ( title(role) != newTitle ) { if ( role == NameRole ) _nameTitle = newTitle; else if ( role == DisplayedTitleRole ) @@ -659,8 +634,7 @@ QString Session::title(TitleRole role) const void Session::setIconName(const QString& iconName) { - if ( iconName != _iconName ) - { + if ( iconName != _iconName ) { _iconName = iconName; emit titleChanged(); } @@ -668,28 +642,28 @@ void Session::setIconName(const QString& iconName) void Session::setIconText(const QString& iconText) { - _iconText = iconText; - //kDebug(1211)<<"Session setIconText " << _iconText; + _iconText = iconText; + //kDebug(1211)<<"Session setIconText " << _iconText; } QString Session::iconName() const { - return _iconName; + return _iconName; } QString Session::iconText() const { - return _iconText; + return _iconText; } void Session::setHistoryType(const HistoryType &hType) { - _emulation->setHistory(hType); + _emulation->setHistory(hType); } const HistoryType& Session::historyType() const { - return _emulation->history(); + return _emulation->history(); } void Session::clearHistory() @@ -699,71 +673,75 @@ void Session::clearHistory() QStringList Session::arguments() const { - return _arguments; + return _arguments; } QString Session::program() const { - return _program; + return _program; } // unused currently -bool Session::isMonitorActivity() const { return _monitorActivity; } +bool Session::isMonitorActivity() const +{ + return _monitorActivity; +} // unused currently -bool Session::isMonitorSilence() const { return _monitorSilence; } +bool Session::isMonitorSilence() const +{ + return _monitorSilence; +} void Session::setMonitorActivity(bool _monitor) { - _monitorActivity=_monitor; - _notifiedActivity=false; + _monitorActivity=_monitor; + _notifiedActivity=false; - activityStateSet(NOTIFYNORMAL); + activityStateSet(NOTIFYNORMAL); } void Session::setMonitorSilence(bool _monitor) { - if (_monitorSilence==_monitor) - return; + if (_monitorSilence==_monitor) + return; - _monitorSilence=_monitor; - if (_monitorSilence) - { - _monitorTimer->start(_silenceSeconds*1000); - } - else - _monitorTimer->stop(); + _monitorSilence=_monitor; + if (_monitorSilence) { + _monitorTimer->start(_silenceSeconds*1000); + } else + _monitorTimer->stop(); - activityStateSet(NOTIFYNORMAL); + activityStateSet(NOTIFYNORMAL); } void Session::setMonitorSilenceSeconds(int seconds) { - _silenceSeconds=seconds; - if (_monitorSilence) { - _monitorTimer->start(_silenceSeconds*1000); - } + _silenceSeconds=seconds; + if (_monitorSilence) { + _monitorTimer->start(_silenceSeconds*1000); + } } void Session::setAddToUtmp(bool set) { - _addToUtmp = set; + _addToUtmp = set; } void Session::setFlowControlEnabled(bool enabled) { - if (_flowControl == enabled) - return; + if (_flowControl == enabled) + return; - _flowControl = enabled; + _flowControl = enabled; - if (_shellProcess) - _shellProcess->setXonXoff(_flowControl); - - emit flowControlEnabledChanged(enabled); + if (_shellProcess) + _shellProcess->setXonXoff(_flowControl); + + emit flowControlEnabledChanged(enabled); } bool Session::flowControlEnabled() const { - return _flowControl; + return _flowControl; } //void Session::fireZModemDetected() //{ @@ -886,15 +864,15 @@ void Session::onReceiveBlock( const char* buf, int len ) QSize Session::size() { - return _emulation->imageSize(); + return _emulation->imageSize(); } void Session::setSize(const QSize& size) { - if ((size.width() <= 1) || (size.height() <= 1)) - return; + if ((size.width() <= 1) || (size.height() <= 1)) + return; - emit resizeRequest(size); + emit resizeRequest(size); } int Session::foregroundProcessId() const { @@ -906,7 +884,7 @@ int Session::processId() const } SessionGroup::SessionGroup() - : _masterMode(0) + : _masterMode(0) { } SessionGroup::~SessionGroup() @@ -914,9 +892,18 @@ SessionGroup::~SessionGroup() // disconnect all connectAll(false); } -int SessionGroup::masterMode() const { return _masterMode; } -QList SessionGroup::sessions() const { return _sessions.keys(); } -bool SessionGroup::masterStatus(Session* session) const { return _sessions[session]; } +int SessionGroup::masterMode() const +{ + return _masterMode; +} +QList SessionGroup::sessions() const +{ + return _sessions.keys(); +} +bool SessionGroup::masterStatus(Session* session) const +{ + return _sessions[session]; +} void SessionGroup::addSession(Session* session) { @@ -940,10 +927,10 @@ void SessionGroup::removeSession(Session* session) } void SessionGroup::setMasterMode(int mode) { - _masterMode = mode; + _masterMode = mode; - connectAll(false); - connectAll(true); + connectAll(false); + connectAll(true); } QList SessionGroup::masters() const { @@ -953,17 +940,14 @@ void SessionGroup::connectAll(bool connect) { QListIterator masterIter(masters()); - while ( masterIter.hasNext() ) - { + while ( masterIter.hasNext() ) { Session* master = masterIter.next(); QListIterator otherIter(_sessions.keys()); - while ( otherIter.hasNext() ) - { + while ( otherIter.hasNext() ) { Session* other = otherIter.next(); - if ( other != master ) - { + if ( other != master ) { if ( connect ) connectPair(master,other); else @@ -972,25 +956,26 @@ void SessionGroup::connectAll(bool connect) } } } -void SessionGroup::setMasterStatus(Session* session, bool master) { +void SessionGroup::setMasterStatus(Session* session, bool master) +{ bool wasMaster = _sessions[session]; _sessions[session] = master; if ((!wasMaster && !master) - || (wasMaster && master)) { - return; - } + || (wasMaster && master)) { + return; + } QListIterator iter(_sessions.keys()); while (iter.hasNext()) { Session* other = iter.next(); if (other != session) { - if (master) { + if (master) { connectPair(session, other); - } else { + } else { disconnectPair(session, other); - } + } } } } @@ -999,8 +984,7 @@ void SessionGroup::connectPair(Session* master , Session* other) { // qDebug() << k_funcinfo; - if ( _masterMode & CopyInputToAll ) - { + if ( _masterMode & CopyInputToAll ) { qDebug() << "Connection session " << master->nameTitle() << "to" << other->nameTitle(); connect( master->emulation() , SIGNAL(sendData(const char*,int)) , other->emulation() , @@ -1011,12 +995,11 @@ void SessionGroup::disconnectPair(Session* master , Session* other) { // qDebug() << k_funcinfo; - if ( _masterMode & CopyInputToAll ) - { + if ( _masterMode & CopyInputToAll ) { qDebug() << "Disconnecting session " << master->nameTitle() << "from" << other->nameTitle(); disconnect( master->emulation() , SIGNAL(sendData(const char*,int)) , other->emulation() , - SLOT(sendString(const char*,int)) ); + SLOT(sendString(const char*,int)) ); } } diff --git a/lib/Session.h b/lib/Session.h index 7b2ae25..161128e 100644 --- a/lib/Session.h +++ b/lib/Session.h @@ -56,308 +56,312 @@ class TerminalDisplay; */ class Session : public QObject { -Q_OBJECT + Q_OBJECT public: - Q_PROPERTY(QString name READ nameTitle) - Q_PROPERTY(int processId READ processId) - Q_PROPERTY(QString keyBindings READ keyBindings WRITE setKeyBindings) - Q_PROPERTY(QSize size READ size WRITE setSize) + Q_PROPERTY(QString name READ nameTitle) + Q_PROPERTY(int processId READ processId) + Q_PROPERTY(QString keyBindings READ keyBindings WRITE setKeyBindings) + Q_PROPERTY(QSize size READ size WRITE setSize) - /** - * Constructs a new session. - * - * To start the terminal process, call the run() method, - * after specifying the program and arguments - * using setProgram() and setArguments() - * - * If no program or arguments are specified explicitly, the Session - * falls back to using the program specified in the SHELL environment - * variable. - */ - Session(); - ~Session(); - - /** - * Returns true if the session is currently running. This will be true - * after run() has been called successfully. - */ - bool isRunning() const; - - /** - * Sets the profile associated with this session. - * - * @param profileKey A key which can be used to obtain the current - * profile settings from the SessionManager - */ - void setProfileKey(const QString& profileKey); - /** - * Returns the profile key associated with this session. - * This can be passed to the SessionManager to obtain the current - * profile settings. - */ - QString profileKey() const; - - /** - * Adds a new view for this session. - * - * The viewing widget will display the output from the terminal and - * input from the viewing widget (key presses, mouse activity etc.) - * will be sent to the terminal. - * - * Views can be removed using removeView(). The session is automatically - * closed when the last view is removed. - */ - void addView(TerminalDisplay* widget); - /** - * Removes a view from this session. When the last view is removed, - * the session will be closed automatically. - * - * @p widget will no longer display output from or send input - * to the terminal - */ - void removeView(TerminalDisplay* widget); - - /** - * Returns the views connected to this session - */ - QList views() const; - - /** - * Returns the terminal emulation instance being used to encode / decode - * characters to / from the process. - */ - Emulation* emulation() const; - - /** - * Returns the environment of this session as a list of strings like - * VARIABLE=VALUE - */ - QStringList environment() const; - /** - * Sets the environment for this session. - * @p environment should be a list of strings like - * VARIABLE=VALUE - */ - void setEnvironment(const QStringList& environment); - - /** Returns the unique ID for this session. */ - int sessionId() const; - - /** - * Return the session title set by the user (ie. the program running - * in the terminal), or an empty string if the user has not set a custom title - */ - QString userTitle() const; - - /** - * This enum describes the contexts for which separate - * tab title formats may be specified. - */ - enum TabTitleContext - { - /** Default tab title format */ - LocalTabTitle, /** - * Tab title format used session currently contains - * a connection to a remote computer (via SSH) + * Constructs a new session. + * + * To start the terminal process, call the run() method, + * after specifying the program and arguments + * using setProgram() and setArguments() + * + * If no program or arguments are specified explicitly, the Session + * falls back to using the program specified in the SHELL environment + * variable. */ - RemoteTabTitle - }; - /** - * Sets the format used by this session for tab titles. - * - * @param context The context whoose format should be set. - * @param format The tab title format. This may be a mixture - * of plain text and dynamic elements denoted by a '%' character - * followed by a letter. (eg. %d for directory). The dynamic - * elements available depend on the @p context - */ - void setTabTitleFormat(TabTitleContext context , const QString& format); - /** Returns the format used by this session for tab titles. */ - QString tabTitleFormat(TabTitleContext context) const; + Session(); + ~Session(); + + /** + * Returns true if the session is currently running. This will be true + * after run() has been called successfully. + */ + bool isRunning() const; + + /** + * Sets the profile associated with this session. + * + * @param profileKey A key which can be used to obtain the current + * profile settings from the SessionManager + */ + void setProfileKey(const QString& profileKey); + /** + * Returns the profile key associated with this session. + * This can be passed to the SessionManager to obtain the current + * profile settings. + */ + QString profileKey() const; + + /** + * Adds a new view for this session. + * + * The viewing widget will display the output from the terminal and + * input from the viewing widget (key presses, mouse activity etc.) + * will be sent to the terminal. + * + * Views can be removed using removeView(). The session is automatically + * closed when the last view is removed. + */ + void addView(TerminalDisplay* widget); + /** + * Removes a view from this session. When the last view is removed, + * the session will be closed automatically. + * + * @p widget will no longer display output from or send input + * to the terminal + */ + void removeView(TerminalDisplay* widget); + + /** + * Returns the views connected to this session + */ + QList views() const; + + /** + * Returns the terminal emulation instance being used to encode / decode + * characters to / from the process. + */ + Emulation* emulation() const; + + /** + * Returns the environment of this session as a list of strings like + * VARIABLE=VALUE + */ + QStringList environment() const; + /** + * Sets the environment for this session. + * @p environment should be a list of strings like + * VARIABLE=VALUE + */ + void setEnvironment(const QStringList& environment); + + /** Returns the unique ID for this session. */ + int sessionId() const; + + /** + * Return the session title set by the user (ie. the program running + * in the terminal), or an empty string if the user has not set a custom title + */ + QString userTitle() const; + + /** + * This enum describes the contexts for which separate + * tab title formats may be specified. + */ + enum TabTitleContext { + /** Default tab title format */ + LocalTabTitle, + /** + * Tab title format used session currently contains + * a connection to a remote computer (via SSH) + */ + RemoteTabTitle + }; + /** + * Sets the format used by this session for tab titles. + * + * @param context The context whoose format should be set. + * @param format The tab title format. This may be a mixture + * of plain text and dynamic elements denoted by a '%' character + * followed by a letter. (eg. %d for directory). The dynamic + * elements available depend on the @p context + */ + void setTabTitleFormat(TabTitleContext context , const QString& format); + /** Returns the format used by this session for tab titles. */ + QString tabTitleFormat(TabTitleContext context) const; - /** Returns the arguments passed to the shell process when run() is called. */ - QStringList arguments() const; - /** Returns the program name of the shell process started when run() is called. */ - QString program() const; + /** Returns the arguments passed to the shell process when run() is called. */ + QStringList arguments() const; + /** Returns the program name of the shell process started when run() is called. */ + QString program() const; - /** - * Sets the command line arguments which the session's program will be passed when - * run() is called. - */ - void setArguments(const QStringList& arguments); - /** Sets the program to be executed when run() is called. */ - void setProgram(const QString& program); + /** + * Sets the command line arguments which the session's program will be passed when + * run() is called. + */ + void setArguments(const QStringList& arguments); + /** Sets the program to be executed when run() is called. */ + void setProgram(const QString& program); - /** Returns the session's current working directory. */ - QString initialWorkingDirectory() { return _initialWorkingDir; } + /** Returns the session's current working directory. */ + QString initialWorkingDirectory() { + return _initialWorkingDir; + } - /** - * Sets the initial working directory for the session when it is run - * This has no effect once the session has been started. - */ - void setInitialWorkingDirectory( const QString& dir ); + /** + * Sets the initial working directory for the session when it is run + * This has no effect once the session has been started. + */ + void setInitialWorkingDirectory( const QString& dir ); - /** - * Sets the type of history store used by this session. - * Lines of output produced by the terminal are added - * to the history store. The type of history store - * used affects the number of lines which can be - * remembered before they are lost and the storage - * (in memory, on-disk etc.) used. - */ - void setHistoryType(const HistoryType& type); - /** - * Returns the type of history store used by this session. - */ - const HistoryType& historyType() const; - /** - * Clears the history store used by this session. - */ - void clearHistory(); + /** + * Sets the type of history store used by this session. + * Lines of output produced by the terminal are added + * to the history store. The type of history store + * used affects the number of lines which can be + * remembered before they are lost and the storage + * (in memory, on-disk etc.) used. + */ + void setHistoryType(const HistoryType& type); + /** + * Returns the type of history store used by this session. + */ + const HistoryType& historyType() const; + /** + * Clears the history store used by this session. + */ + void clearHistory(); - /** - * Enables monitoring for activity in the session. - * This will cause notifySessionState() to be emitted - * with the NOTIFYACTIVITY state flag when output is - * received from the terminal. - */ - void setMonitorActivity(bool); - /** Returns true if monitoring for activity is enabled. */ - bool isMonitorActivity() const; + /** + * Enables monitoring for activity in the session. + * This will cause notifySessionState() to be emitted + * with the NOTIFYACTIVITY state flag when output is + * received from the terminal. + */ + void setMonitorActivity(bool); + /** Returns true if monitoring for activity is enabled. */ + bool isMonitorActivity() const; - /** - * Enables monitoring for silence in the session. - * This will cause notifySessionState() to be emitted - * with the NOTIFYSILENCE state flag when output is not - * received from the terminal for a certain period of - * time, specified with setMonitorSilenceSeconds() - */ - void setMonitorSilence(bool); - /** - * Returns true if monitoring for inactivity (silence) - * in the session is enabled. - */ - bool isMonitorSilence() const; - /** See setMonitorSilence() */ - void setMonitorSilenceSeconds(int seconds); + /** + * Enables monitoring for silence in the session. + * This will cause notifySessionState() to be emitted + * with the NOTIFYSILENCE state flag when output is not + * received from the terminal for a certain period of + * time, specified with setMonitorSilenceSeconds() + */ + void setMonitorSilence(bool); + /** + * Returns true if monitoring for inactivity (silence) + * in the session is enabled. + */ + bool isMonitorSilence() const; + /** See setMonitorSilence() */ + void setMonitorSilenceSeconds(int seconds); - /** - * Sets the key bindings used by this session. The bindings - * specify how input key sequences are translated into - * the character stream which is sent to the terminal. - * - * @param id The name of the key bindings to use. The - * names of available key bindings can be determined using the - * KeyboardTranslatorManager class. - */ - void setKeyBindings(const QString& id); - /** Returns the name of the key bindings used by this session. */ - QString keyBindings() const; + /** + * Sets the key bindings used by this session. The bindings + * specify how input key sequences are translated into + * the character stream which is sent to the terminal. + * + * @param id The name of the key bindings to use. The + * names of available key bindings can be determined using the + * KeyboardTranslatorManager class. + */ + void setKeyBindings(const QString& id); + /** Returns the name of the key bindings used by this session. */ + QString keyBindings() const; - /** - * This enum describes the available title roles. - */ - enum TitleRole - { - /** The name of the session. */ - NameRole, - /** The title of the session which is displayed in tabs etc. */ - DisplayedTitleRole - }; + /** + * This enum describes the available title roles. + */ + enum TitleRole { + /** The name of the session. */ + NameRole, + /** The title of the session which is displayed in tabs etc. */ + DisplayedTitleRole + }; - /** Sets the session's title for the specified @p role to @p title. */ - void setTitle(TitleRole role , const QString& title); - /** Returns the session's title for the specified @p role. */ - QString title(TitleRole role) const; - /** Convenience method used to read the name property. Returns title(Session::NameRole). */ - QString nameTitle() const { return title(Session::NameRole); } + /** Sets the session's title for the specified @p role to @p title. */ + void setTitle(TitleRole role , const QString& title); + /** Returns the session's title for the specified @p role. */ + QString title(TitleRole role) const; + /** Convenience method used to read the name property. Returns title(Session::NameRole). */ + QString nameTitle() const { + return title(Session::NameRole); + } - /** Sets the name of the icon associated with this session. */ - void setIconName(const QString& iconName); - /** Returns the name of the icon associated with this session. */ - QString iconName() const; + /** Sets the name of the icon associated with this session. */ + void setIconName(const QString& iconName); + /** Returns the name of the icon associated with this session. */ + QString iconName() const; - /** Sets the text of the icon associated with this session. */ - void setIconText(const QString& iconText); - /** Returns the text of the icon associated with this session. */ - QString iconText() const; + /** Sets the text of the icon associated with this session. */ + void setIconText(const QString& iconText); + /** Returns the text of the icon associated with this session. */ + QString iconText() const; - /** Specifies whether a utmp entry should be created for the pty used by this session. */ - void setAddToUtmp(bool); + /** Specifies whether a utmp entry should be created for the pty used by this session. */ + void setAddToUtmp(bool); - /** Sends the specified @p signal to the terminal process. */ - bool sendSignal(int signal); + /** Sends the specified @p signal to the terminal process. */ + bool sendSignal(int signal); - /** - * Specifies whether to close the session automatically when the terminal - * process terminates. - */ - void setAutoClose(bool b) { _autoClose = b; } + /** + * Specifies whether to close the session automatically when the terminal + * process terminates. + */ + void setAutoClose(bool b) { + _autoClose = b; + } - /** - * Sets whether flow control is enabled for this terminal - * session. - */ - void setFlowControlEnabled(bool enabled); + /** + * Sets whether flow control is enabled for this terminal + * session. + */ + void setFlowControlEnabled(bool enabled); - /** Returns whether flow control is enabled for this terminal session. */ - bool flowControlEnabled() const; + /** Returns whether flow control is enabled for this terminal session. */ + bool flowControlEnabled() const; - /** - * Sends @p text to the current foreground terminal program. - */ - void sendText(const QString& text) const; + /** + * Sends @p text to the current foreground terminal program. + */ + void sendText(const QString& text) const; - /** - * Returns the process id of the terminal process. - * This is the id used by the system API to refer to the process. - */ - int processId() const; + /** + * Returns the process id of the terminal process. + * This is the id used by the system API to refer to the process. + */ + int processId() const; - /** - * Returns the process id of the terminal's foreground process. - * This is initially the same as processId() but can change - * as the user starts other programs inside the terminal. - */ - int foregroundProcessId() const; + /** + * Returns the process id of the terminal's foreground process. + * This is initially the same as processId() but can change + * as the user starts other programs inside the terminal. + */ + int foregroundProcessId() const; - /** Returns the terminal session's window size in lines and columns. */ - QSize size(); - /** - * Emits a request to resize the session to accommodate - * the specified window size. - * - * @param size The size in lines and columns to request. - */ - void setSize(const QSize& size); + /** Returns the terminal session's window size in lines and columns. */ + QSize size(); + /** + * Emits a request to resize the session to accommodate + * the specified window size. + * + * @param size The size in lines and columns to request. + */ + void setSize(const QSize& size); - /** Sets the text codec used by this session's terminal emulation. */ - void setCodec(QTextCodec* codec); + /** Sets the text codec used by this session's terminal emulation. */ + void setCodec(QTextCodec* codec); - /** - * Sets whether the session has a dark background or not. The session - * uses this information to set the COLORFGBG variable in the process's - * environment, which allows the programs running in the terminal to determine - * whether the background is light or dark and use appropriate colors by default. - * - * This has no effect once the session is running. - */ - void setDarkBackground(bool darkBackground); - /** - * Returns true if the session has a dark background. - * See setDarkBackground() - */ - bool hasDarkBackground() const; + /** + * Sets whether the session has a dark background or not. The session + * uses this information to set the COLORFGBG variable in the process's + * environment, which allows the programs running in the terminal to determine + * whether the background is light or dark and use appropriate colors by default. + * + * This has no effect once the session is running. + */ + void setDarkBackground(bool darkBackground); + /** + * Returns true if the session has a dark background. + * See setDarkBackground() + */ + bool hasDarkBackground() const; - /** - * Attempts to get the shell program to redraw the current display area. - * This can be used after clearing the screen, for example, to get the - * shell to redraw the prompt line. - */ - void refresh(); + /** + * Attempts to get the shell program to redraw the current display area. + * This can be used after clearing the screen, for example, to get the + * shell to redraw the prompt line. + */ + void refresh(); // void startZModem(const QString &rz, const QString &dir, const QStringList &list); // void cancelZModem(); @@ -365,117 +369,117 @@ public: public slots: - /** - * Starts the terminal session. - * - * This creates the terminal process and connects the teletype to it. - */ - void run(); + /** + * Starts the terminal session. + * + * This creates the terminal process and connects the teletype to it. + */ + void run(); - /** - * Closes the terminal session. This sends a hangup signal - * (SIGHUP) to the terminal process and causes the done(Session*) - * signal to be emitted. - */ - void close(); + /** + * Closes the terminal session. This sends a hangup signal + * (SIGHUP) to the terminal process and causes the done(Session*) + * signal to be emitted. + */ + void close(); - /** - * Changes the session title or other customizable aspects of the terminal - * emulation display. For a list of what may be changed see the - * Emulation::titleChanged() signal. - */ - void setUserTitle( int, const QString &caption ); + /** + * Changes the session title or other customizable aspects of the terminal + * emulation display. For a list of what may be changed see the + * Emulation::titleChanged() signal. + */ + void setUserTitle( int, const QString &caption ); signals: - /** Emitted when the terminal process starts. */ - void started(); + /** Emitted when the terminal process starts. */ + void started(); - /** - * Emitted when the terminal process exits. - */ - void finished(); + /** + * Emitted when the terminal process exits. + */ + void finished(); - /** - * Emitted when output is received from the terminal process. - */ - void receivedData( const QString& text ); + /** + * Emitted when output is received from the terminal process. + */ + void receivedData( const QString& text ); - /** Emitted when the session's title has changed. */ - void titleChanged(); + /** Emitted when the session's title has changed. */ + void titleChanged(); - /** Emitted when the session's profile has changed. */ - void profileChanged(const QString& profile); + /** Emitted when the session's profile has changed. */ + void profileChanged(const QString& profile); - /** - * Emitted when the activity state of this session changes. - * - * @param state The new state of the session. This may be one - * of NOTIFYNORMAL, NOTIFYSILENCE or NOTIFYACTIVITY - */ - void stateChanged(int state); + /** + * Emitted when the activity state of this session changes. + * + * @param state The new state of the session. This may be one + * of NOTIFYNORMAL, NOTIFYSILENCE or NOTIFYACTIVITY + */ + void stateChanged(int state); - /** Emitted when a bell event occurs in the session. */ - void bellRequest( const QString& message ); + /** Emitted when a bell event occurs in the session. */ + void bellRequest( const QString& message ); - /** - * Requests that the color the text for any tabs associated with - * this session should be changed; - * - * TODO: Document what the parameter does - */ - void changeTabTextColorRequest(int); + /** + * Requests that the color the text for any tabs associated with + * this session should be changed; + * + * TODO: Document what the parameter does + */ + void changeTabTextColorRequest(int); - /** - * Requests that the background color of views on this session - * should be changed. - */ - void changeBackgroundColorRequest(const QColor&); + /** + * Requests that the background color of views on this session + * should be changed. + */ + void changeBackgroundColorRequest(const QColor&); - /** TODO: Document me. */ - void openUrlRequest(const QString& url); + /** TODO: Document me. */ + void openUrlRequest(const QString& url); - /** TODO: Document me. */ + /** TODO: Document me. */ // void zmodemDetected(); - /** - * Emitted when the terminal process requests a change - * in the size of the terminal window. - * - * @param size The requested window size in terms of lines and columns. - */ - void resizeRequest(const QSize& size); + /** + * Emitted when the terminal process requests a change + * in the size of the terminal window. + * + * @param size The requested window size in terms of lines and columns. + */ + void resizeRequest(const QSize& size); - /** - * Emitted when a profile change command is received from the terminal. - * - * @param text The text of the command. This is a string of the form - * "PropertyName=Value;PropertyName=Value ..." - */ - void profileChangeCommandReceived(const QString& text); + /** + * Emitted when a profile change command is received from the terminal. + * + * @param text The text of the command. This is a string of the form + * "PropertyName=Value;PropertyName=Value ..." + */ + void profileChangeCommandReceived(const QString& text); - /** - * Emitted when the flow control state changes. - * - * @param enabled True if flow control is enabled or false otherwise. - */ - void flowControlEnabledChanged(bool enabled); + /** + * Emitted when the flow control state changes. + * + * @param enabled True if flow control is enabled or false otherwise. + */ + void flowControlEnabledChanged(bool enabled); private slots: - void done(int); + void done(int); // void fireZModemDetected(); - void onReceiveBlock( const char* buffer, int len ); - void monitorTimerDone(); + void onReceiveBlock( const char* buffer, int len ); + void monitorTimerDone(); - void onViewSizeChange(int height, int width); - void onEmulationSizeChange(int lines , int columns); + void onViewSizeChange(int height, int width); + void onEmulationSizeChange(int lines , int columns); - void activityStateSet(int); + void activityStateSet(int); - //automatically detach views from sessions when view is destroyed - void viewDestroyed(QObject* view); + //automatically detach views from sessions when view is destroyed + void viewDestroyed(QObject* view); // void zmodemReadStatus(); // void zmodemReadAndSendBlock(); @@ -484,61 +488,61 @@ private slots: private: - void updateTerminalSize(); - WId windowId() const; + void updateTerminalSize(); + WId windowId() const; - int _uniqueIdentifier; + int _uniqueIdentifier; - Pty* _shellProcess; - Emulation* _emulation; + Pty* _shellProcess; + Emulation* _emulation; - QList _views; + QList _views; - bool _monitorActivity; - bool _monitorSilence; - bool _notifiedActivity; - bool _masterMode; - bool _autoClose; - bool _wantedClose; - QTimer* _monitorTimer; + bool _monitorActivity; + bool _monitorSilence; + bool _notifiedActivity; + bool _masterMode; + bool _autoClose; + bool _wantedClose; + QTimer* _monitorTimer; - int _silenceSeconds; + int _silenceSeconds; - QString _nameTitle; - QString _displayTitle; - QString _userTitle; + QString _nameTitle; + QString _displayTitle; + QString _userTitle; - QString _localTabTitleFormat; - QString _remoteTabTitleFormat; + QString _localTabTitleFormat; + QString _remoteTabTitleFormat; - QString _iconName; - QString _iconText; // as set by: echo -en '\033]1;IconText\007 - bool _addToUtmp; - bool _flowControl; - bool _fullScripting; + QString _iconName; + QString _iconText; // as set by: echo -en '\033]1;IconText\007 + bool _addToUtmp; + bool _flowControl; + bool _fullScripting; - QString _program; - QStringList _arguments; + QString _program; + QStringList _arguments; - QStringList _environment; - int _sessionId; + QStringList _environment; + int _sessionId; - QString _initialWorkingDir; + QString _initialWorkingDir; - // ZModem + // ZModem // bool _zmodemBusy; // KProcess* _zmodemProc; // ZModemDialog* _zmodemProgress; - // Color/Font Changes by ESC Sequences + // Color/Font Changes by ESC Sequences - QColor _modifiedBackground; // as set by: echo -en '\033]11;Color\007 + QColor _modifiedBackground; // as set by: echo -en '\033]11;Color\007 - QString _profileKey; + QString _profileKey; - bool _hasDarkBackground; + bool _hasDarkBackground; - static int lastSessionId; + static int lastSessionId; }; @@ -550,7 +554,7 @@ private: */ class SessionGroup : public QObject { -Q_OBJECT + Q_OBJECT public: /** Constructs an empty session group. */ @@ -582,8 +586,7 @@ public: * This enum describes the options for propagating certain activity or * changes in the group's master sessions to all sessions in the group. */ - enum MasterMode - { + enum MasterMode { /** * Any input key presses in the master sessions are sent to all * sessions in the group. diff --git a/lib/ShellCommand.cpp b/lib/ShellCommand.cpp index 764dd66..ee91ce5 100644 --- a/lib/ShellCommand.cpp +++ b/lib/ShellCommand.cpp @@ -38,8 +38,7 @@ ShellCommand::ShellCommand(const QString& fullCommand) QString builder; - for ( int i = 0 ; i < fullCommand.count() ; i++ ) - { + for ( int i = 0 ; i < fullCommand.count() ; i++ ) { QChar ch = fullCommand[i]; const bool isLastChar = ( i == fullCommand.count() - 1 ); @@ -47,15 +46,13 @@ ShellCommand::ShellCommand(const QString& fullCommand) if ( !isLastChar && isQuote ) inQuotes = !inQuotes; - else - { + else { if ( (!ch.isSpace() || inQuotes) && !isQuote ) builder.append(ch); - if ( (ch.isSpace() && !inQuotes) || ( i == fullCommand.count()-1 ) ) - { - _arguments << builder; - builder.clear(); + if ( (ch.isSpace() && !inQuotes) || ( i == fullCommand.count()-1 ) ) { + _arguments << builder; + builder.clear(); } } } @@ -63,7 +60,7 @@ ShellCommand::ShellCommand(const QString& fullCommand) ShellCommand::ShellCommand(const QString& command , const QStringList& arguments) { _arguments = arguments; - + if ( !_arguments.isEmpty() ) _arguments[0] == command; } @@ -90,14 +87,14 @@ bool ShellCommand::isRootCommand() const bool ShellCommand::isAvailable() const { Q_ASSERT(0); // not implemented yet - return false; + return false; } QStringList ShellCommand::expand(const QStringList& items) { QStringList result; foreach( QString item , items ) - result << expand(item); + result << expand(item); return result; } @@ -116,53 +113,52 @@ QString ShellCommand::expand(const QString& text) */ static bool expandEnv( QString &text ) { - // Find all environment variables beginning with '$' - // - int pos = 0; + // Find all environment variables beginning with '$' + // + int pos = 0; - bool expanded = false; + bool expanded = false; - while ( (pos = text.indexOf(QLatin1Char('$'), pos)) != -1 ) { + while ( (pos = text.indexOf(QLatin1Char('$'), pos)) != -1 ) { - // Skip escaped '$' - // - if ( pos > 0 && text.at(pos-1) == QLatin1Char('\\') ) { - pos++; - } - // Variable found => expand - // - else { - // Find the end of the variable = next '/' or ' ' - // - int pos2 = text.indexOf( QLatin1Char(' '), pos+1 ); - int pos_tmp = text.indexOf( QLatin1Char('/'), pos+1 ); + // Skip escaped '$' + // + if ( pos > 0 && text.at(pos-1) == QLatin1Char('\\') ) { + pos++; + } + // Variable found => expand + // + else { + // Find the end of the variable = next '/' or ' ' + // + int pos2 = text.indexOf( QLatin1Char(' '), pos+1 ); + int pos_tmp = text.indexOf( QLatin1Char('/'), pos+1 ); - if ( pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2) ) - pos2 = pos_tmp; + if ( pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2) ) + pos2 = pos_tmp; - if ( pos2 == -1 ) - pos2 = text.length(); + if ( pos2 == -1 ) + pos2 = text.length(); - // Replace if the variable is terminated by '/' or ' ' - // and defined - // - if ( pos2 >= 0 ) { - int len = pos2 - pos; - QString key = text.mid( pos+1, len-1); - QString value = - QString::fromLocal8Bit( ::getenv(key.toLocal8Bit()) ); + // Replace if the variable is terminated by '/' or ' ' + // and defined + // + if ( pos2 >= 0 ) { + int len = pos2 - pos; + QString key = text.mid( pos+1, len-1); + QString value = + QString::fromLocal8Bit( ::getenv(key.toLocal8Bit()) ); - if ( !value.isEmpty() ) { - expanded = true; - text.replace( pos, len, value ); - pos = pos + value.length(); - } - else { - pos = pos2; - } - } - } - } + if ( !value.isEmpty() ) { + expanded = true; + text.replace( pos, len, value ); + pos = pos + value.length(); + } else { + pos = pos2; + } + } + } + } - return expanded; + return expanded; } diff --git a/lib/ShellCommand.h b/lib/ShellCommand.h index 44e0db8..2f30ae0 100644 --- a/lib/ShellCommand.h +++ b/lib/ShellCommand.h @@ -28,8 +28,8 @@ namespace Konsole { -/** - * A class to parse and extract information about shell commands. +/** + * A class to parse and extract information about shell commands. * * ShellCommand can be used to: * @@ -38,7 +38,7 @@ namespace Konsole * into its component parts (eg. the command "/bin/sh" and the arguments * "-c","/path/to/my/script") * - *
  • Take a command and a list of arguments and combine them to + *
  • Take a command and a list of arguments and combine them to * form a complete command line. *
  • *
  • Determine whether the binary specified by a command exists in the @@ -47,7 +47,7 @@ namespace Konsole *
  • Determine whether a command-line specifies the execution of * another command as the root user using su/sudo etc. *
  • - * + * */ class ShellCommand { @@ -55,7 +55,7 @@ public: /** * Constructs a ShellCommand from a command line. * - * @param fullCommand The command line to parse. + * @param fullCommand The command line to parse. */ ShellCommand(const QString& fullCommand); /** @@ -68,8 +68,8 @@ public: /** Returns the arguments. */ QStringList arguments() const; - /** - * Returns the full command line. + /** + * Returns the full command line. */ QString fullCommand() const; @@ -85,7 +85,7 @@ public: static QStringList expand(const QStringList& items); private: - QStringList _arguments; + QStringList _arguments; }; } diff --git a/lib/TerminalCharacterDecoder.cpp b/lib/TerminalCharacterDecoder.cpp index 18571d9..8b70700 100644 --- a/lib/TerminalCharacterDecoder.cpp +++ b/lib/TerminalCharacterDecoder.cpp @@ -1,8 +1,8 @@ /* This file is part of Konsole, an X terminal. - + Copyright (C) 2006 by Robert Knight - + Rewritten for QT4 by e_k , Copyright (C)2008 This program is free software; you can redistribute it and/or modify @@ -31,8 +31,8 @@ using namespace Konsole; PlainTextDecoder::PlainTextDecoder() - : _output(0) - , _includeTrailingWhitespace(true) + : _output(0) + , _includeTrailingWhitespace(true) { } @@ -46,33 +46,31 @@ bool PlainTextDecoder::trailingWhitespace() const } void PlainTextDecoder::begin(QTextStream* output) { - _output = output; + _output = output; } void PlainTextDecoder::end() { _output = 0; } void PlainTextDecoder::decodeLine(const Character* const characters, int count, LineProperty /*properties*/ - ) + ) { Q_ASSERT( _output ); - //TODO should we ignore or respect the LINE_WRAPPED line property? + //TODO should we ignore or respect the LINE_WRAPPED line property? + + //note: we build up a QString and send it to the text stream rather writing into the text + //stream a character at a time because it is more efficient. + //(since QTextStream always deals with QStrings internally anyway) + QString plainText; + plainText.reserve(count); - //note: we build up a QString and send it to the text stream rather writing into the text - //stream a character at a time because it is more efficient. - //(since QTextStream always deals with QStrings internally anyway) - QString plainText; - plainText.reserve(count); - int outputCount = count; // if inclusion of trailing whitespace is disabled then find the end of the // line - if ( !_includeTrailingWhitespace ) - { - for (int i = count-1 ; i >= 0 ; i--) - { + if ( !_includeTrailingWhitespace ) { + for (int i = count-1 ; i >= 0 ; i--) { if ( characters[i].character != ' ' ) break; else @@ -80,21 +78,20 @@ void PlainTextDecoder::decodeLine(const Character* const characters, int count, } } - for (int i=0;i') - text.append(">"); - else - text.append(ch); - } - else - { - text.append(" "); //HTML truncates multiple spaces, so use a space marker instead - } - - } + //open the span with the current style + openSpan(text,style); + _innerSpanOpen = true; + } - //close any remaining open inner spans - if ( _innerSpanOpen ) - closeSpan(text); + //handle whitespace + if (ch.isSpace()) + spaceCount++; + else + spaceCount = 0; - //start new line - text.append("
    "); - - *_output << text; + + //output current character + if (spaceCount < 2) { + //escape HTML tag characters and just display others as they are + if ( ch == '<' ) + text.append("<"); + else if (ch == '>') + text.append(">"); + else + text.append(ch); + } else { + text.append(" "); //HTML truncates multiple spaces, so use a space marker instead + } + + } + + //close any remaining open inner spans + if ( _innerSpanOpen ) + closeSpan(text); + + //start new line + text.append("
    "); + + *_output << text; } void HTMLDecoder::openSpan(QString& text , const QString& style) { - text.append( QString("").arg(style) ); + text.append( QString("").arg(style) ); } void HTMLDecoder::closeSpan(QString& text) { - text.append(""); + text.append(""); } void HTMLDecoder::setColorTable(const ColorEntry* table) { - _colorTable = table; + _colorTable = table; } diff --git a/lib/TerminalCharacterDecoder.h b/lib/TerminalCharacterDecoder.h index 5d97fc3..79b96ab 100644 --- a/lib/TerminalCharacterDecoder.h +++ b/lib/TerminalCharacterDecoder.h @@ -1,8 +1,8 @@ /* This file is part of Konsole, an X terminal. - + Copyright (C) 2006-7 by Robert Knight - + Rewritten for QT4 by e_k , Copyright (C)2008 This program is free software; you can redistribute it and/or modify @@ -38,29 +38,29 @@ namespace Konsole * and background colours and other appearance-related properties into text strings. * * Derived classes may produce either plain text with no other colour or appearance information, or - * they may produce text which incorporates these additional properties. + * they may produce text which incorporates these additional properties. */ class TerminalCharacterDecoder { public: - virtual ~TerminalCharacterDecoder() {} + virtual ~TerminalCharacterDecoder() {} /** Begin decoding characters. The resulting text is appended to @p output. */ virtual void begin(QTextStream* output) = 0; /** End decoding. */ virtual void end() = 0; - /** - * Converts a line of terminal characters with associated properties into a text string - * and writes the string into an output QTextStream. - * - * @param characters An array of characters of length @p count. - * @param properties Additional properties which affect all characters in the line - * @param output The output stream which receives the decoded text - */ - virtual void decodeLine(const Character* const characters, - int count, - LineProperty properties) = 0; + /** + * Converts a line of terminal characters with associated properties into a text string + * and writes the string into an output QTextStream. + * + * @param characters An array of characters of length @p count. + * @param properties Additional properties which affect all characters in the line + * @param output The output stream which receives the decoded text + */ + virtual void decodeLine(const Character* const characters, + int count, + LineProperty properties) = 0; }; /** @@ -70,10 +70,10 @@ public: class PlainTextDecoder : public TerminalCharacterDecoder { public: - PlainTextDecoder(); + PlainTextDecoder(); - /** - * Set whether trailing whitespace at the end of lines should be included + /** + * Set whether trailing whitespace at the end of lines should be included * in the output. * Defaults to true. */ @@ -87,11 +87,11 @@ public: virtual void begin(QTextStream* output); virtual void end(); - virtual void decodeLine(const Character* const characters, - int count, - LineProperty properties); + virtual void decodeLine(const Character* const characters, + int count, + LineProperty properties); + - private: QTextStream* _output; bool _includeTrailingWhitespace; @@ -103,34 +103,34 @@ private: class HTMLDecoder : public TerminalCharacterDecoder { public: - /** - * Constructs an HTML decoder using a default black-on-white color scheme. - */ - HTMLDecoder(); + /** + * Constructs an HTML decoder using a default black-on-white color scheme. + */ + HTMLDecoder(); - /** - * Sets the colour table which the decoder uses to produce the HTML colour codes in its - * output - */ - void setColorTable( const ColorEntry* table ); - - virtual void decodeLine(const Character* const characters, - int count, - LineProperty properties); + /** + * Sets the colour table which the decoder uses to produce the HTML colour codes in its + * output + */ + void setColorTable( const ColorEntry* table ); + + virtual void decodeLine(const Character* const characters, + int count, + LineProperty properties); virtual void begin(QTextStream* output); virtual void end(); private: - void openSpan(QString& text , const QString& style); - void closeSpan(QString& text); + void openSpan(QString& text , const QString& style); + void closeSpan(QString& text); QTextStream* _output; - const ColorEntry* _colorTable; - bool _innerSpanOpen; - quint8 _lastRendition; - CharacterColor _lastForeColor; - CharacterColor _lastBackColor; + const ColorEntry* _colorTable; + bool _innerSpanOpen; + quint8 _lastRendition; + CharacterColor _lastForeColor; + CharacterColor _lastBackColor; }; diff --git a/lib/TerminalDisplay.cpp b/lib/TerminalDisplay.cpp index 5d87c61..fea68de 100644 --- a/lib/TerminalDisplay.cpp +++ b/lib/TerminalDisplay.cpp @@ -1,9 +1,9 @@ /* This file is part of Konsole, a terminal emulator for KDE. - + Copyright (C) 2006-7 by Robert Knight Copyright (C) 1997,1998 by Lars Doelle - + Rewritten for QT4 by e_k , Copyright (C)2008 This program is free software; you can redistribute it and/or modify @@ -88,40 +88,38 @@ ScreenWindow* TerminalDisplay::screenWindow() const void TerminalDisplay::setScreenWindow(ScreenWindow* window) { // disconnect existing screen window if any - if ( _screenWindow ) - { + if ( _screenWindow ) { disconnect( _screenWindow , 0 , this , 0 ); } _screenWindow = window; - if ( window ) - { + if ( window ) { //#warning "The order here is not specified - does it matter whether updateImage or updateLineProperties comes first?" connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties()) ); connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage()) ); - window->setWindowLines(_lines); + window->setWindowLines(_lines); } } const ColorEntry* TerminalDisplay::colorTable() const { - return _colorTable; + return _colorTable; } void TerminalDisplay::setColorTable(const ColorEntry table[]) { - for (int i = 0; i < TABLE_COLORS; i++) - _colorTable[i] = table[i]; + for (int i = 0; i < TABLE_COLORS; i++) + _colorTable[i] = table[i]; - QPalette p = palette(); - p.setColor( backgroundRole(), _colorTable[DEFAULT_BACK_COLOR].color ); - setPalette( p ); + QPalette p = palette(); + p.setColor( backgroundRole(), _colorTable[DEFAULT_BACK_COLOR].color ); + setPalette( p ); - // Avoid propagating the palette change to the scroll bar - _scrollBar->setPalette( QApplication::palette() ); + // Avoid propagating the palette change to the scroll bar + _scrollBar->setPalette( QApplication::palette() ); - update(); + update(); } /* ------------------------------------------------------------------------- */ @@ -142,83 +140,82 @@ void TerminalDisplay::setColorTable(const ColorEntry table[]) QCodec. */ -static inline bool isLineChar(quint16 c) { return ((c & 0xFF80) == 0x2500);} +static inline bool isLineChar(quint16 c) +{ + return ((c & 0xFF80) == 0x2500); +} static inline bool isLineCharString(const QString& string) { - return (string.length() > 0) && (isLineChar(string.at(0).unicode())); + return (string.length() > 0) && (isLineChar(string.at(0).unicode())); } - + // assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i. -unsigned short Konsole::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 +unsigned short Konsole::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 }; void TerminalDisplay::fontChange(const QFont&) { - QFontMetrics fm(font()); - _fontHeight = fm.height() + _lineSpacing; + QFontMetrics fm(font()); + _fontHeight = fm.height() + _lineSpacing; - // waba TerminalDisplay 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 - _fontWidth = qRound((double)fm.width(REPCHAR)/(double)strlen(REPCHAR)); + // waba TerminalDisplay 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 + _fontWidth = qRound((double)fm.width(REPCHAR)/(double)strlen(REPCHAR)); - _fixedFont = true; + _fixedFont = true; - int fw = fm.width(REPCHAR[0]); - for(unsigned int i=1; i< strlen(REPCHAR); i++) - { - if (fw != fm.width(REPCHAR[i])) - { - _fixedFont = false; - break; + int fw = fm.width(REPCHAR[0]); + for (unsigned int i=1; i< strlen(REPCHAR); i++) { + if (fw != fm.width(REPCHAR[i])) { + _fixedFont = false; + break; + } } - } - if (_fontWidth < 1) - _fontWidth=1; + if (_fontWidth < 1) + _fontWidth=1; - _fontAscent = fm.ascent(); + _fontAscent = fm.ascent(); - emit changedFontMetricSignal( _fontHeight, _fontWidth ); - propagateSize(); - update(); + emit changedFontMetricSignal( _fontHeight, _fontWidth ); + propagateSize(); + update(); } void TerminalDisplay::setVTFont(const QFont& f) { - QFont font = f; + QFont font = f; - QFontMetrics metrics(font); + QFontMetrics metrics(font); - if ( metrics.height() < height() && metrics.maxWidth() < width() ) - { - // hint that text should be drawn without anti-aliasing. - // depending on the user's font configuration, this may not be respected - if (!_antialiasText) - font.setStyleStrategy( QFont::NoAntialias ); - - // experimental optimization. Konsole assumes that the terminal is using a - // mono-spaced font, in which case kerning information should have an effect. - // Disabling kerning saves some computation when rendering text. - font.setKerning(false); + if ( metrics.height() < height() && metrics.maxWidth() < width() ) { + // hint that text should be drawn without anti-aliasing. + // depending on the user's font configuration, this may not be respected + if (!_antialiasText) + font.setStyleStrategy( QFont::NoAntialias ); - QWidget::setFont(font); - fontChange(font); - } + // experimental optimization. Konsole assumes that the terminal is using a + // mono-spaced font, in which case kerning information should have an effect. + // Disabling kerning saves some computation when rendering text. + font.setKerning(false); + + QWidget::setFont(font); + fontChange(font); + } } void TerminalDisplay::setFont(const QFont &) { - // ignore font change request if not coming from konsole itself + // ignore font change request if not coming from konsole itself } /* ------------------------------------------------------------------------- */ @@ -228,112 +225,112 @@ void TerminalDisplay::setFont(const QFont &) /* ------------------------------------------------------------------------- */ TerminalDisplay::TerminalDisplay(QWidget *parent) -:QWidget(parent) -,_screenWindow(0) -,_allowBell(true) -,_gridLayout(0) -,_fontHeight(1) -,_fontWidth(1) -,_fontAscent(1) -,_lines(1) -,_columns(1) -,_usedLines(1) -,_usedColumns(1) -,_contentHeight(1) -,_contentWidth(1) -,_image(0) -,_randomSeed(0) -,_resizing(false) -,_terminalSizeHint(false) -,_terminalSizeStartup(true) -,_bidiEnabled(false) -,_actSel(0) -,_wordSelectionMode(false) -,_lineSelectionMode(false) -,_preserveLineBreaks(false) -,_columnSelectionMode(false) -,_scrollbarLocation(NoScrollBar) -,_wordCharacters(":@-./_~") -,_bellMode(SystemBeepBell) -,_blinking(false) -,_cursorBlinking(false) -,_hasBlinkingCursor(false) -,_ctrlDrag(false) -,_tripleClickMode(SelectWholeLine) -,_isFixedSize(false) -,_possibleTripleClick(false) -,_resizeWidget(0) -,_resizeTimer(0) -,_flowControlWarningEnabled(false) -,_outputSuspendedLabel(0) -,_lineSpacing(0) -,_colorsInverted(false) -,_blendColor(qRgba(0,0,0,0xff)) -,_filterChain(new TerminalImageFilterChain()) -,_cursorShape(BlockCursor) + :QWidget(parent) + ,_screenWindow(0) + ,_allowBell(true) + ,_gridLayout(0) + ,_fontHeight(1) + ,_fontWidth(1) + ,_fontAscent(1) + ,_lines(1) + ,_columns(1) + ,_usedLines(1) + ,_usedColumns(1) + ,_contentHeight(1) + ,_contentWidth(1) + ,_image(0) + ,_randomSeed(0) + ,_resizing(false) + ,_terminalSizeHint(false) + ,_terminalSizeStartup(true) + ,_bidiEnabled(false) + ,_actSel(0) + ,_wordSelectionMode(false) + ,_lineSelectionMode(false) + ,_preserveLineBreaks(false) + ,_columnSelectionMode(false) + ,_scrollbarLocation(NoScrollBar) + ,_wordCharacters(":@-./_~") + ,_bellMode(SystemBeepBell) + ,_blinking(false) + ,_cursorBlinking(false) + ,_hasBlinkingCursor(false) + ,_ctrlDrag(false) + ,_tripleClickMode(SelectWholeLine) + ,_isFixedSize(false) + ,_possibleTripleClick(false) + ,_resizeWidget(0) + ,_resizeTimer(0) + ,_flowControlWarningEnabled(false) + ,_outputSuspendedLabel(0) + ,_lineSpacing(0) + ,_colorsInverted(false) + ,_blendColor(qRgba(0,0,0,0xff)) + ,_filterChain(new TerminalImageFilterChain()) + ,_cursorShape(BlockCursor) { - // terminal applications are not designed with Right-To-Left in mind, - // so the layout is forced to Left-To-Right - setLayoutDirection(Qt::LeftToRight); + // terminal applications are not designed with Right-To-Left in mind, + // so the layout is forced to Left-To-Right + setLayoutDirection(Qt::LeftToRight); - // The offsets are not yet calculated. - // Do not calculate these too often to be more smoothly when resizing - // konsole in opaque mode. - _topMargin = DEFAULT_TOP_MARGIN; - _leftMargin = DEFAULT_LEFT_MARGIN; + // The offsets are not yet calculated. + // Do not calculate these too often to be more smoothly when resizing + // konsole in opaque mode. + _topMargin = DEFAULT_TOP_MARGIN; + _leftMargin = DEFAULT_LEFT_MARGIN; - // create scroll bar for scrolling output up and down - // set the scroll bar's slider to occupy the whole area of the scroll bar initially - _scrollBar = new QScrollBar(this); - setScroll(0,0); - _scrollBar->setCursor( Qt::ArrowCursor ); - connect(_scrollBar, SIGNAL(valueChanged(int)), this, - SLOT(scrollBarPositionChanged(int))); + // create scroll bar for scrolling output up and down + // set the scroll bar's slider to occupy the whole area of the scroll bar initially + _scrollBar = new QScrollBar(this); + setScroll(0,0); + _scrollBar->setCursor( Qt::ArrowCursor ); + connect(_scrollBar, SIGNAL(valueChanged(int)), this, + SLOT(scrollBarPositionChanged(int))); - // setup timers for blinking cursor and text - _blinkTimer = new QTimer(this); - connect(_blinkTimer, SIGNAL(timeout()), this, SLOT(blinkEvent())); - _blinkCursorTimer = new QTimer(this); - connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent())); + // setup timers for blinking cursor and text + _blinkTimer = new QTimer(this); + connect(_blinkTimer, SIGNAL(timeout()), this, SLOT(blinkEvent())); + _blinkCursorTimer = new QTimer(this); + connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent())); // QCursor::setAutoHideCursor( this, true ); - - setUsesMouse(true); - setColorTable(whiteonblack_color_table); -// setColorTable(blackonlightyellow_color_table); - setMouseTracking(true); - // Enable drag and drop - setAcceptDrops(true); // attempt - dragInfo.state = diNone; + setUsesMouse(true); + setColorTable(whiteonblack_color_table); +// setColorTable(blackonlightyellow_color_table); + setMouseTracking(true); - setFocusPolicy( Qt::WheelFocus ); + // Enable drag and drop + setAcceptDrops(true); // attempt + dragInfo.state = diNone; - // enable input method support - setAttribute(Qt::WA_InputMethodEnabled, true); + setFocusPolicy( Qt::WheelFocus ); - // this is an important optimization, it tells Qt - // that TerminalDisplay will handle repainting its entire area. - setAttribute(Qt::WA_OpaquePaintEvent); + // enable input method support + setAttribute(Qt::WA_InputMethodEnabled, true); - _gridLayout = new QGridLayout(this); - _gridLayout->setMargin(0); + // this is an important optimization, it tells Qt + // that TerminalDisplay will handle repainting its entire area. + setAttribute(Qt::WA_OpaquePaintEvent); - setLayout( _gridLayout ); + _gridLayout = new QGridLayout(this); + _gridLayout->setMargin(0); - //set up a warning message when the user presses Ctrl+S to avoid confusion - connect( this,SIGNAL(flowControlKeyPressed(bool)),this,SLOT(outputSuspended(bool)) ); + setLayout( _gridLayout ); + + //set up a warning message when the user presses Ctrl+S to avoid confusion + connect( this,SIGNAL(flowControlKeyPressed(bool)),this,SLOT(outputSuspended(bool)) ); } TerminalDisplay::~TerminalDisplay() { - qApp->removeEventFilter( this ); - - delete[] _image; + qApp->removeEventFilter( this ); - delete _gridLayout; - delete _outputSuspendedLabel; - delete _filterChain; + delete[] _image; + + delete _gridLayout; + delete _outputSuspendedLabel; + delete _filterChain; } /* ------------------------------------------------------------------------- */ @@ -361,8 +358,7 @@ where _ = none */ -enum LineEncode -{ +enum LineEncode { TopL = (1<<1), TopC = (1<<2), TopR = (1<<3), @@ -458,26 +454,24 @@ static void drawLineChar(QPainter& paint, int x, int y, int w, int h, uchar code } -void TerminalDisplay::drawLineCharString( QPainter& painter, int x, int y, const QString& str, - const Character* attributes) +void TerminalDisplay::drawLineCharString( QPainter& painter, int x, int y, const QString& str, + const Character* attributes) { - const QPen& currentPen = painter.pen(); - - if ( attributes->rendition & RE_BOLD ) - { - QPen boldPen(currentPen); - boldPen.setWidth(3); - painter.setPen( boldPen ); - } - - for (int i=0 ; i < str.length(); i++) - { - uchar code = str[i].cell(); - if (LineChars[code]) - drawLineChar(painter, x + (_fontWidth*i), y, _fontWidth, _fontHeight, code); - } + const QPen& currentPen = painter.pen(); - painter.setPen( currentPen ); + if ( attributes->rendition & RE_BOLD ) { + QPen boldPen(currentPen); + boldPen.setWidth(3); + painter.setPen( boldPen ); + } + + for (int i=0 ; i < str.length(); i++) { + uchar code = str[i].cell(); + if (LineChars[code]) + drawLineChar(painter, x + (_fontWidth*i), y, _fontWidth, _fontHeight, code); + } + + painter.setPen( currentPen ); } void TerminalDisplay::setKeyboardCursorShape(KeyboardCursorShape shape) @@ -492,9 +486,9 @@ void TerminalDisplay::setKeyboardCursorColor(bool useForegroundColor, const QCol { if (useForegroundColor) _cursorColor = QColor(); // an invalid color means that - // the foreground color of the - // current character should - // be used + // the foreground color of the + // current character should + // be used else _cursorColor = color; @@ -511,12 +505,9 @@ void TerminalDisplay::setOpacity(qreal opacity) // enable automatic background filling to prevent the display // flickering if there is no transparency - if ( color.alpha() == 255 ) - { + if ( color.alpha() == 255 ) { setAutoFillBackground(true); - } - else - { + } else { setAutoFillBackground(false); } @@ -525,38 +516,36 @@ void TerminalDisplay::setOpacity(qreal opacity) void TerminalDisplay::drawBackground(QPainter& painter, const QRect& rect, const QColor& backgroundColor, bool useOpacitySetting ) { - // the area of the widget showing the contents of the terminal display is drawn - // using the background color from the color scheme set with setColorTable() - // - // the area of the widget behind the scroll-bar is drawn using the background - // brush from the scroll-bar's palette, to give the effect of the scroll-bar - // being outside of the terminal display and visual consistency with other KDE - // applications. - // - QRect scrollBarArea = _scrollBar->isVisible() ? - rect.intersected(_scrollBar->geometry()) : - QRect(); - QRegion contentsRegion = QRegion(rect).subtracted(scrollBarArea); - QRect contentsRect = contentsRegion.boundingRect(); + // the area of the widget showing the contents of the terminal display is drawn + // using the background color from the color scheme set with setColorTable() + // + // the area of the widget behind the scroll-bar is drawn using the background + // brush from the scroll-bar's palette, to give the effect of the scroll-bar + // being outside of the terminal display and visual consistency with other KDE + // applications. + // + QRect scrollBarArea = _scrollBar->isVisible() ? + rect.intersected(_scrollBar->geometry()) : + QRect(); + QRegion contentsRegion = QRegion(rect).subtracted(scrollBarArea); + QRect contentsRect = contentsRegion.boundingRect(); - if ( HAVE_TRANSPARENCY && qAlpha(_blendColor) < 0xff && useOpacitySetting ) - { - QColor color(backgroundColor); - color.setAlpha(qAlpha(_blendColor)); + if ( HAVE_TRANSPARENCY && qAlpha(_blendColor) < 0xff && useOpacitySetting ) { + QColor color(backgroundColor); + color.setAlpha(qAlpha(_blendColor)); - painter.save(); - painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.fillRect(contentsRect, color); - painter.restore(); - } - else { - painter.fillRect(contentsRect, backgroundColor); - } + painter.save(); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(contentsRect, color); + painter.restore(); + } else { + painter.fillRect(contentsRect, backgroundColor); + } - painter.fillRect(scrollBarArea,_scrollBar->palette().background()); + painter.fillRect(scrollBarArea,_scrollBar->palette().background()); } -void TerminalDisplay::drawCursor(QPainter& painter, +void TerminalDisplay::drawCursor(QPainter& painter, const QRect& rect, const QColor& foregroundColor, const QColor& /*backgroundColor*/, @@ -564,17 +553,15 @@ void TerminalDisplay::drawCursor(QPainter& painter, { QRect cursorRect = rect; cursorRect.setHeight(_fontHeight - _lineSpacing - 1); - - if (!_cursorBlinking) - { - if ( _cursorColor.isValid() ) - painter.setPen(_cursorColor); - else { - painter.setPen(foregroundColor); - } - if ( _cursorShape == BlockCursor ) - { + if (!_cursorBlinking) { + if ( _cursorColor.isValid() ) + painter.setPen(_cursorColor); + else { + painter.setPen(foregroundColor); + } + + if ( _cursorShape == BlockCursor ) { // draw the cursor outline, adjusting the area so that // it is draw entirely inside 'rect' int penWidth = qMax(1,painter.pen().width()); @@ -583,29 +570,26 @@ void TerminalDisplay::drawCursor(QPainter& painter, penWidth/2, - penWidth/2 - penWidth%2, - penWidth/2 - penWidth%2)); - if ( hasFocus() ) - { + if ( hasFocus() ) { painter.fillRect(cursorRect, _cursorColor.isValid() ? _cursorColor : foregroundColor); - - if ( !_cursorColor.isValid() ) - { + + if ( !_cursorColor.isValid() ) { // invert the colour used to draw the text to ensure that the character at // the cursor position is readable invertCharacterColor = true; } } - } - else if ( _cursorShape == UnderlineCursor ) + } else if ( _cursorShape == UnderlineCursor ) painter.drawLine(cursorRect.left(), cursorRect.bottom(), cursorRect.right(), cursorRect.bottom()); - else if ( _cursorShape == IBeamCursor ) + else if ( _cursorShape == IBeamCursor ) painter.drawLine(cursorRect.left(), cursorRect.top(), cursorRect.left(), cursorRect.bottom()); - + } } @@ -617,56 +601,52 @@ void TerminalDisplay::drawCharacters(QPainter& painter, { // don't draw text which is currently blinking if ( _blinking && (style->rendition & RE_BLINK) ) - return; - + return; + // setup bold and underline bool useBold = style->rendition & RE_BOLD || style->isBold(_colorTable) || font().bold(); bool useUnderline = style->rendition & RE_UNDERLINE || font().underline(); QFont font = painter.font(); - if ( font.bold() != useBold - || font.underline() != useUnderline ) - { - font.setBold(useBold); - font.setUnderline(useUnderline); - painter.setFont(font); + if ( font.bold() != useBold + || font.underline() != useUnderline ) { + font.setBold(useBold); + font.setUnderline(useUnderline); + painter.setFont(font); } const CharacterColor& textColor = ( invertCharacterColor ? style->backgroundColor : style->foregroundColor ); const QColor color = textColor.color(_colorTable); QPen pen = painter.pen(); - if ( pen.color() != color ) - { + if ( pen.color() != color ) { pen.setColor(color); painter.setPen(color); } // draw text if ( isLineCharString(text) ) { - drawLineCharString(painter,rect.x(),rect.y(),text,style); - } - else - { - // the drawText(rect,flags,string) overload is used here with null flags - // instead of drawText(rect,string) because the (rect,string) overload causes - // the application's default layout direction to be used instead of - // the widget-specific layout direction, which should always be - // Qt::LeftToRight for this widget + drawLineCharString(painter,rect.x(),rect.y(),text,style); + } else { + // the drawText(rect,flags,string) overload is used here with null flags + // instead of drawText(rect,string) because the (rect,string) overload causes + // the application's default layout direction to be used instead of + // the widget-specific layout direction, which should always be + // Qt::LeftToRight for this widget painter.drawText(rect,0,text); - } + } } -void TerminalDisplay::drawTextFragment(QPainter& painter , +void TerminalDisplay::drawTextFragment(QPainter& painter , const QRect& rect, - const QString& text, + const QString& text, const Character* style) { painter.save(); - // setup painter + // setup painter const QColor foregroundColor = style->foregroundColor.color(_colorTable); const QColor backgroundColor = style->backgroundColor.color(_colorTable); - + // draw background if different from the display's background color if ( backgroundColor != palette().background().color() ) drawBackground(painter,rect,backgroundColor, false /* do not use transparency */); @@ -683,8 +663,14 @@ void TerminalDisplay::drawTextFragment(QPainter& painter , painter.restore(); } -void TerminalDisplay::setRandomSeed(uint randomSeed) { _randomSeed = randomSeed; } -uint TerminalDisplay::randomSeed() const { return _randomSeed; } +void TerminalDisplay::setRandomSeed(uint randomSeed) +{ + _randomSeed = randomSeed; +} +uint TerminalDisplay::randomSeed() const +{ + return _randomSeed; +} #if 0 /*! @@ -708,38 +694,38 @@ void TerminalDisplay::setCursorPos(const int curx, const int cury) // scrolls the image by 'lines', down if lines > 0 or up otherwise. // -// the terminal emulation keeps track of the scrolling of the character -// image as it receives input, and when the view is updated, it calls scrollImage() -// with the final scroll amount. this improves performance because scrolling the -// display is much cheaper than re-rendering all the text for the -// part of the image which has moved up or down. +// the terminal emulation keeps track of the scrolling of the character +// image as it receives input, and when the view is updated, it calls scrollImage() +// with the final scroll amount. this improves performance because scrolling the +// display is much cheaper than re-rendering all the text for the +// part of the image which has moved up or down. // Instead only new lines have to be drawn // -// note: it is important that the area of the display which is -// scrolled aligns properly with the character grid - -// which has a top left point at (_leftMargin,_topMargin) , -// a cell width of _fontWidth and a cell height of _fontHeight). +// note: it is important that the area of the display which is +// scrolled aligns properly with the character grid - +// which has a top left point at (_leftMargin,_topMargin) , +// a cell width of _fontWidth and a cell height of _fontHeight). void TerminalDisplay::scrollImage(int lines , const QRect& screenWindowRegion) { - // if the flow control warning is enabled this will interfere with the - // scrolling optimisations and cause artifacts. the simple solution here - // is to just disable the optimisation whilst it is visible - if ( _outputSuspendedLabel && _outputSuspendedLabel->isVisible() ) { - return; - } + // if the flow control warning is enabled this will interfere with the + // scrolling optimisations and cause artifacts. the simple solution here + // is to just disable the optimisation whilst it is visible + if ( _outputSuspendedLabel && _outputSuspendedLabel->isVisible() ) { + return; + } // constrain the region to the display // the bottom of the region is capped to the number of lines in the display's // internal image - 2, so that the height of 'region' is strictly less // than the height of the internal image. QRect region = screenWindowRegion; - region.setBottom( qMin(region.bottom(),this->_lines-2) ); + region.setBottom( qMin(region.bottom(),this->_lines-2) ); - if ( lines == 0 - || _image == 0 - || !region.isValid() - || (region.top() + abs(lines)) >= region.bottom() - || this->_lines <= region.height() ) return; + if ( lines == 0 + || _image == 0 + || !region.isValid() + || (region.top() + abs(lines)) >= region.bottom() + || this->_lines <= region.height() ) return; QRect scrollRect; @@ -748,7 +734,7 @@ void TerminalDisplay::scrollImage(int lines , const QRect& screenWindowRegion) int top = _topMargin + (region.top() * _fontHeight); int linesToMove = region.height() - abs(lines); - int bytesToMove = linesToMove * + int bytesToMove = linesToMove * this->_columns * sizeof(Character); @@ -756,343 +742,329 @@ void TerminalDisplay::scrollImage(int lines , const QRect& screenWindowRegion) Q_ASSERT( bytesToMove > 0 ); //scroll internal image - if ( lines > 0 ) - { + if ( lines > 0 ) { // check that the memory areas that we are going to move are valid - Q_ASSERT( (char*)lastCharPos + bytesToMove < + Q_ASSERT( (char*)lastCharPos + bytesToMove < (char*)(_image + (this->_lines * this->_columns)) ); - - Q_ASSERT( (lines*this->_columns) < _imageSize ); + + Q_ASSERT( (lines*this->_columns) < _imageSize ); //scroll internal image down - memmove( firstCharPos , lastCharPos , bytesToMove ); - + memmove( firstCharPos , lastCharPos , bytesToMove ); + //set region of display to scroll, making sure that - //the region aligns correctly to the character grid - scrollRect = QRect( _leftMargin , top, - this->_usedColumns * _fontWidth , + //the region aligns correctly to the character grid + scrollRect = QRect( _leftMargin , top, + this->_usedColumns * _fontWidth , linesToMove * _fontHeight ); - } - else - { + } else { // check that the memory areas that we are going to move are valid - Q_ASSERT( (char*)firstCharPos + bytesToMove < + Q_ASSERT( (char*)firstCharPos + bytesToMove < (char*)(_image + (this->_lines * this->_columns)) ); //scroll internal image up - memmove( lastCharPos , firstCharPos , bytesToMove ); - + memmove( lastCharPos , firstCharPos , bytesToMove ); + //set region of the display to scroll, making sure that //the region aligns correctly to the character grid QPoint topPoint( _leftMargin , top + abs(lines)*_fontHeight ); scrollRect = QRect( topPoint , - QSize( this->_usedColumns*_fontWidth , - linesToMove * _fontHeight )); + QSize( this->_usedColumns*_fontWidth , + linesToMove * _fontHeight )); } //scroll the display vertically to match internal _image scroll( 0 , _fontHeight * (-lines) , scrollRect ); } -QRegion TerminalDisplay::hotSpotRegion() const +QRegion TerminalDisplay::hotSpotRegion() const { - QRegion region; - foreach( Filter::HotSpot* hotSpot , _filterChain->hotSpots() ) - { - QRect rect; - rect.setLeft(hotSpot->startColumn()); - rect.setTop(hotSpot->startLine()); - rect.setRight(hotSpot->endColumn()); - rect.setBottom(hotSpot->endLine()); + QRegion region; + foreach( Filter::HotSpot* hotSpot , _filterChain->hotSpots() ) { + QRect rect; + rect.setLeft(hotSpot->startColumn()); + rect.setTop(hotSpot->startLine()); + rect.setRight(hotSpot->endColumn()); + rect.setBottom(hotSpot->endLine()); - region |= imageToWidget(rect); - } - return region; + region |= imageToWidget(rect); + } + return region; } -void TerminalDisplay::processFilters() +void TerminalDisplay::processFilters() { - if (!_screenWindow) - return; + if (!_screenWindow) + return; - QRegion preUpdateHotSpots = hotSpotRegion(); + QRegion preUpdateHotSpots = hotSpotRegion(); - // use _screenWindow->getImage() here rather than _image because - // other classes may call processFilters() when this display's - // ScreenWindow emits a scrolled() signal - which will happen before - // updateImage() is called on the display and therefore _image is - // out of date at this point - _filterChain->setImage( _screenWindow->getImage(), - _screenWindow->windowLines(), - _screenWindow->windowColumns(), - _screenWindow->getLineProperties() ); + // use _screenWindow->getImage() here rather than _image because + // other classes may call processFilters() when this display's + // ScreenWindow emits a scrolled() signal - which will happen before + // updateImage() is called on the display and therefore _image is + // out of date at this point + _filterChain->setImage( _screenWindow->getImage(), + _screenWindow->windowLines(), + _screenWindow->windowColumns(), + _screenWindow->getLineProperties() ); _filterChain->process(); - QRegion postUpdateHotSpots = hotSpotRegion(); + QRegion postUpdateHotSpots = hotSpotRegion(); - update( preUpdateHotSpots | postUpdateHotSpots ); + update( preUpdateHotSpots | postUpdateHotSpots ); } -void TerminalDisplay::updateImage() +void TerminalDisplay::updateImage() { - if ( !_screenWindow ) - return; + if ( !_screenWindow ) + return; - // optimization - scroll the existing image where possible and - // avoid expensive text drawing for parts of the image that - // can simply be moved up or down - scrollImage( _screenWindow->scrollCount() , - _screenWindow->scrollRegion() ); - _screenWindow->resetScrollCount(); + // optimization - scroll the existing image where possible and + // avoid expensive text drawing for parts of the image that + // can simply be moved up or down + scrollImage( _screenWindow->scrollCount() , + _screenWindow->scrollRegion() ); + _screenWindow->resetScrollCount(); - Character* const newimg = _screenWindow->getImage(); - int lines = _screenWindow->windowLines(); - int columns = _screenWindow->windowColumns(); + Character* const newimg = _screenWindow->getImage(); + int lines = _screenWindow->windowLines(); + int columns = _screenWindow->windowColumns(); - setScroll( _screenWindow->currentLine() , _screenWindow->lineCount() ); + setScroll( _screenWindow->currentLine() , _screenWindow->lineCount() ); - if (!_image) - updateImageSize(); // Create _image + if (!_image) + updateImageSize(); // Create _image - Q_ASSERT( this->_usedLines <= this->_lines ); - Q_ASSERT( this->_usedColumns <= this->_columns ); + Q_ASSERT( this->_usedLines <= this->_lines ); + Q_ASSERT( this->_usedColumns <= this->_columns ); - int y,x,len; + int y,x,len; - QPoint tL = contentsRect().topLeft(); + QPoint tL = contentsRect().topLeft(); - int tLx = tL.x(); - int tLy = tL.y(); - _hasBlinker = false; + int tLx = tL.x(); + int tLy = tL.y(); + _hasBlinker = false; - CharacterColor cf; // undefined - CharacterColor _clipboard; // undefined - int cr = -1; // undefined + CharacterColor cf; // undefined + CharacterColor _clipboard; // undefined + int cr = -1; // undefined - const int linesToUpdate = qMin(this->_lines, qMax(0,lines )); - const int columnsToUpdate = qMin(this->_columns,qMax(0,columns)); + const int linesToUpdate = qMin(this->_lines, qMax(0,lines )); + const int columnsToUpdate = qMin(this->_columns,qMax(0,columns)); - QChar *disstrU = new QChar[columnsToUpdate]; - char *dirtyMask = new char[columnsToUpdate+2]; - QRegion dirtyRegion; + QChar *disstrU = new QChar[columnsToUpdate]; + char *dirtyMask = new char[columnsToUpdate+2]; + QRegion dirtyRegion; - // debugging variable, this records the number of lines that are found to - // be 'dirty' ( ie. have changed from the old _image to the new _image ) and - // which therefore need to be repainted - int dirtyLineCount = 0; + // debugging variable, this records the number of lines that are found to + // be 'dirty' ( ie. have changed from the old _image to the new _image ) and + // which therefore need to be repainted + int dirtyLineCount = 0; - for (y = 0; y < linesToUpdate; y++) - { - const Character* currentLine = &_image[y*this->_columns]; - const Character* const newLine = &newimg[y*columns]; + for (y = 0; y < linesToUpdate; y++) { + const Character* currentLine = &_image[y*this->_columns]; + const Character* const newLine = &newimg[y*columns]; - bool updateLine = false; - - // 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, columnsToUpdate+2); - - for( x = 0 ; x < columnsToUpdate ; x++) - { - if ( newLine[x] != currentLine[x] ) - { - dirtyMask[x] = true; - } - } + bool updateLine = false; - if (!_resizing) // not while _resizing, we're expecting a paintEvent - for (x = 0; x < columnsToUpdate; x++) - { - _hasBlinker |= (newLine[x].rendition & 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]) - { - quint16 c = newLine[x+0].character; - if ( !c ) - continue; - int p = 0; - disstrU[p++] = c; //fontMap(c); - bool lineDraw = isLineChar(c); - bool doubleWidth = (x+1 == columnsToUpdate) ? false : (newLine[x+1].character == 0); - cr = newLine[x].rendition; - _clipboard = newLine[x].backgroundColor; - if (newLine[x].foregroundColor != cf) cf = newLine[x].foregroundColor; - int lln = columnsToUpdate - x; - for (len = 1; len < lln; len++) - { - const Character& ch = newLine[x+len]; + // 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, columnsToUpdate+2); - if (!ch.character) - continue; // Skip trailing part of multi-col chars. - - bool nextIsDoubleWidth = (x+len+1 == columnsToUpdate) ? false : (newLine[x+len+1].character == 0); - - if ( ch.foregroundColor != cf || - ch.backgroundColor != _clipboard || - ch.rendition != cr || - !dirtyMask[x+len] || - isLineChar(c) != lineDraw || - nextIsDoubleWidth != doubleWidth ) - break; - - disstrU[p++] = c; //fontMap(c); + for ( x = 0 ; x < columnsToUpdate ; x++) { + if ( newLine[x] != currentLine[x] ) { + dirtyMask[x] = true; + } } - QString unistr(disstrU, p); + if (!_resizing) // not while _resizing, we're expecting a paintEvent + for (x = 0; x < columnsToUpdate; x++) { + _hasBlinker |= (newLine[x].rendition & RE_BLINK); - bool saveFixedFont = _fixedFont; - if (lineDraw) - _fixedFont = false; - if (doubleWidth) - _fixedFont = false; + // 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]) { + quint16 c = newLine[x+0].character; + if ( !c ) + continue; + int p = 0; + disstrU[p++] = c; //fontMap(c); + bool lineDraw = isLineChar(c); + bool doubleWidth = (x+1 == columnsToUpdate) ? false : (newLine[x+1].character == 0); + cr = newLine[x].rendition; + _clipboard = newLine[x].backgroundColor; + if (newLine[x].foregroundColor != cf) cf = newLine[x].foregroundColor; + int lln = columnsToUpdate - x; + for (len = 1; len < lln; len++) { + const Character& ch = newLine[x+len]; - updateLine = true; + if (!ch.character) + continue; // Skip trailing part of multi-col chars. - _fixedFont = saveFixedFont; - x += len - 1; - } - + bool nextIsDoubleWidth = (x+len+1 == columnsToUpdate) ? false : (newLine[x+len+1].character == 0); + + if ( ch.foregroundColor != cf || + ch.backgroundColor != _clipboard || + ch.rendition != cr || + !dirtyMask[x+len] || + isLineChar(c) != lineDraw || + nextIsDoubleWidth != doubleWidth ) + break; + + disstrU[p++] = c; //fontMap(c); + } + + QString unistr(disstrU, p); + + bool saveFixedFont = _fixedFont; + if (lineDraw) + _fixedFont = false; + if (doubleWidth) + _fixedFont = false; + + updateLine = true; + + _fixedFont = saveFixedFont; + x += len - 1; + } + + } + + //both the top and bottom halves of double height _lines must always be redrawn + //although both top and bottom halves contain the same characters, only + //the top one is actually + //drawn. + if (_lineProperties.count() > y) + updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT); + + // if the characters on the line are different in the old and the new _image + // then this line must be repainted. + if (updateLine) { + dirtyLineCount++; + + // add the area occupied by this line to the region which needs to be + // repainted + QRect dirtyRect = QRect( _leftMargin+tLx , + _topMargin+tLy+_fontHeight*y , + _fontWidth * columnsToUpdate , + _fontHeight ); + + dirtyRegion |= dirtyRect; + } + + // replace the line of characters in the old _image with the + // current line of the new _image + memcpy((void*)currentLine,(const void*)newLine,columnsToUpdate*sizeof(Character)); } - //both the top and bottom halves of double height _lines must always be redrawn - //although both top and bottom halves contain the same characters, only - //the top one is actually - //drawn. - if (_lineProperties.count() > y) - updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT); - - // if the characters on the line are different in the old and the new _image - // then this line must be repainted. - if (updateLine) - { - dirtyLineCount++; - - // add the area occupied by this line to the region which needs to be - // repainted - QRect dirtyRect = QRect( _leftMargin+tLx , - _topMargin+tLy+_fontHeight*y , - _fontWidth * columnsToUpdate , - _fontHeight ); - - dirtyRegion |= dirtyRect; + // if the new _image is smaller than the previous _image, then ensure that the area + // outside the new _image is cleared + if ( linesToUpdate < _usedLines ) { + dirtyRegion |= QRect( _leftMargin+tLx , + _topMargin+tLy+_fontHeight*linesToUpdate , + _fontWidth * this->_columns , + _fontHeight * (_usedLines-linesToUpdate) ); } + _usedLines = linesToUpdate; - // replace the line of characters in the old _image with the - // current line of the new _image - memcpy((void*)currentLine,(const void*)newLine,columnsToUpdate*sizeof(Character)); - } + if ( columnsToUpdate < _usedColumns ) { + dirtyRegion |= QRect( _leftMargin+tLx+columnsToUpdate*_fontWidth , + _topMargin+tLy , + _fontWidth * (_usedColumns-columnsToUpdate) , + _fontHeight * this->_lines ); + } + _usedColumns = columnsToUpdate; - // if the new _image is smaller than the previous _image, then ensure that the area - // outside the new _image is cleared - if ( linesToUpdate < _usedLines ) - { - dirtyRegion |= QRect( _leftMargin+tLx , - _topMargin+tLy+_fontHeight*linesToUpdate , - _fontWidth * this->_columns , - _fontHeight * (_usedLines-linesToUpdate) ); - } - _usedLines = linesToUpdate; - - if ( columnsToUpdate < _usedColumns ) - { - dirtyRegion |= QRect( _leftMargin+tLx+columnsToUpdate*_fontWidth , - _topMargin+tLy , - _fontWidth * (_usedColumns-columnsToUpdate) , - _fontHeight * this->_lines ); - } - _usedColumns = columnsToUpdate; + dirtyRegion |= _inputMethodData.previousPreeditRect; - dirtyRegion |= _inputMethodData.previousPreeditRect; + // update the parts of the display which have changed + update(dirtyRegion); - // update the parts of the display which have changed - update(dirtyRegion); - - if ( _hasBlinker && !_blinkTimer->isActive()) _blinkTimer->start( BLINK_DELAY ); - if (!_hasBlinker && _blinkTimer->isActive()) { _blinkTimer->stop(); _blinking = false; } - delete[] dirtyMask; - delete[] disstrU; + if ( _hasBlinker && !_blinkTimer->isActive()) _blinkTimer->start( BLINK_DELAY ); + if (!_hasBlinker && _blinkTimer->isActive()) { + _blinkTimer->stop(); + _blinking = false; + } + delete[] dirtyMask; + delete[] disstrU; } void TerminalDisplay::showResizeNotification() { - if (_terminalSizeHint && isVisible()) - { - if (_terminalSizeStartup) { - _terminalSizeStartup=false; - return; - } - if (!_resizeWidget) - { - _resizeWidget = new QLabel(("Size: XXX x XXX"), this); - _resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width(("Size: XXX x XXX"))); - _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height()); - _resizeWidget->setAlignment(Qt::AlignCenter); + if (_terminalSizeHint && isVisible()) { + if (_terminalSizeStartup) { + _terminalSizeStartup=false; + return; + } + if (!_resizeWidget) { + _resizeWidget = new QLabel(("Size: XXX x XXX"), this); + _resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width(("Size: XXX x XXX"))); + _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height()); + _resizeWidget->setAlignment(Qt::AlignCenter); - _resizeWidget->setStyleSheet("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)"); + _resizeWidget->setStyleSheet("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)"); - _resizeTimer = new QTimer(this); - _resizeTimer->setSingleShot(true); - connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide())); + _resizeTimer = new QTimer(this); + _resizeTimer->setSingleShot(true); + connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide())); - } - QString sizeStr; - sizeStr.sprintf("Size: %d x %d", _columns, _lines); - _resizeWidget->setText(sizeStr); - _resizeWidget->move((width()-_resizeWidget->width())/2, - (height()-_resizeWidget->height())/2+20); - _resizeWidget->show(); - _resizeTimer->start(1000); - } + } + QString sizeStr; + sizeStr.sprintf("Size: %d x %d", _columns, _lines); + _resizeWidget->setText(sizeStr); + _resizeWidget->move((width()-_resizeWidget->width())/2, + (height()-_resizeWidget->height())/2+20); + _resizeWidget->show(); + _resizeTimer->start(1000); + } } void TerminalDisplay::setBlinkingCursor(bool blink) { - _hasBlinkingCursor=blink; - - if (blink && !_blinkCursorTimer->isActive()) - _blinkCursorTimer->start(BLINK_DELAY); - - if (!blink && _blinkCursorTimer->isActive()) - { - _blinkCursorTimer->stop(); - if (_cursorBlinking) - blinkCursorEvent(); - else - _cursorBlinking = false; - } + _hasBlinkingCursor=blink; + + if (blink && !_blinkCursorTimer->isActive()) + _blinkCursorTimer->start(BLINK_DELAY); + + if (!blink && _blinkCursorTimer->isActive()) { + _blinkCursorTimer->stop(); + if (_cursorBlinking) + blinkCursorEvent(); + else + _cursorBlinking = false; + } } void TerminalDisplay::paintEvent( QPaintEvent* pe ) { //qDebug("%s %d paintEvent", __FILE__, __LINE__); - QPainter paint(this); + QPainter paint(this); //qDebug("%s %d paintEvent %d %d", __FILE__, __LINE__, paint.window().top(), paint.window().right()); - foreach (QRect rect, (pe->region() & contentsRect()).rects()) - { - drawBackground(paint,rect,palette().background().color(), true /* use opacity setting */); - drawContents(paint, rect); - } + foreach (QRect rect, (pe->region() & contentsRect()).rects()) { + drawBackground(paint,rect,palette().background().color(), true /* use opacity setting */); + drawContents(paint, rect); + } // drawBackground(paint,contentsRect(),palette().background().color(), true /* use opacity setting */); -// drawContents(paint, contentsRect()); - drawInputMethodPreeditString(paint,preeditRect()); - paintFilters(paint); +// drawContents(paint, contentsRect()); + drawInputMethodPreeditString(paint,preeditRect()); + paintFilters(paint); - paint.end(); + paint.end(); } QPoint TerminalDisplay::cursorPosition() const { - if (_screenWindow) - return _screenWindow->cursorPosition(); - else - return QPoint(0,0); + if (_screenWindow) + return _screenWindow->cursorPosition(); + else + return QPoint(0,0); } QRect TerminalDisplay::preeditRect() const @@ -1106,14 +1078,14 @@ QRect TerminalDisplay::preeditRect() const _topMargin + _fontHeight*cursorPosition().y(), _fontWidth*preeditLength, _fontHeight); -} +} void TerminalDisplay::drawInputMethodPreeditString(QPainter& painter , const QRect& rect) { if ( _inputMethodData.preeditString.isEmpty() ) { return; } - const QPoint cursorPos = cursorPosition(); + const QPoint cursorPos = cursorPosition(); bool invertColors = false; const QColor background = _colorTable[DEFAULT_BACK_COLOR].color; @@ -1124,7 +1096,7 @@ void TerminalDisplay::drawInputMethodPreeditString(QPainter& painter , const QRe drawCursor(painter,rect,foreground,background,invertColors); drawCharacters(painter,rect,_inputMethodData.preeditString,style,invertColors); - _inputMethodData.previousPreeditRect = rect; + _inputMethodData.previousPreeditRect = rect; } FilterChain* TerminalDisplay::filterChain() const @@ -1146,26 +1118,24 @@ void TerminalDisplay::paintFilters(QPainter& painter) painter.setPen( QPen(cursorCharacter.foregroundColor.color(colorTable())) ); - // iterate over hotspots identified by the display's currently active filters + // iterate over hotspots identified by the display's currently active filters // and draw appropriate visuals to indicate the presence of the hotspot QList spots = _filterChain->hotSpots(); QListIterator iter(spots); - while (iter.hasNext()) - { + while (iter.hasNext()) { Filter::HotSpot* spot = iter.next(); - for ( int line = spot->startLine() ; line <= spot->endLine() ; line++ ) - { + for ( int line = spot->startLine() ; line <= spot->endLine() ; line++ ) { int startColumn = 0; - int endColumn = _columns-1; // TODO use number of _columns which are actually - // occupied on this line rather than the width of the - // display in _columns + int endColumn = _columns-1; // TODO use number of _columns which are actually + // occupied on this line rather than the width of the + // display in _columns // ignore whitespace at the end of the lines while ( QChar(_image[loc(endColumn,line)].character).isSpace() && endColumn > 0 ) endColumn--; - + // increment here because the column which we want to set 'endColumn' to // is the first whitespace character at the end of the line endColumn++; @@ -1181,18 +1151,17 @@ void TerminalDisplay::paintFilters(QPainter& painter) // hotspots // // subtracting one pixel from all sides also prevents an edge case where - // moving the mouse outside a link could still leave it underlined + // moving the mouse outside a link could still leave it underlined // because the check below for the position of the cursor // finds it on the border of the target area QRect r; r.setCoords( startColumn*_fontWidth + 1, line*_fontHeight + 1, - endColumn*_fontWidth - 1, (line+1)*_fontHeight - 1 ); - - // Underline link hotspots - if ( spot->type() == Filter::HotSpot::Link ) - { + endColumn*_fontWidth - 1, (line+1)*_fontHeight - 1 ); + + // Underline link hotspots + if ( spot->type() == Filter::HotSpot::Link ) { QFontMetrics metrics(font()); - + // find the baseline (which is the invisible line that the characters in the font sit on, // with some having tails dangling below) int baseline = r.bottom() - metrics.descent(); @@ -1200,14 +1169,13 @@ void TerminalDisplay::paintFilters(QPainter& painter) int underlinePos = baseline + metrics.underlinePos(); if ( r.contains( mapFromGlobal(QCursor::pos()) ) ) - painter.drawLine( r.left() , underlinePos , + painter.drawLine( r.left() , underlinePos , r.right() , underlinePos ); } // Marker hotspots simply have a transparent rectanglular shape // drawn on top of them - else if ( spot->type() == Filter::HotSpot::Marker ) - { - //TODO - Do not use a hardcoded colour for this + else if ( spot->type() == Filter::HotSpot::Marker ) { + //TODO - Do not use a hardcoded colour for this painter.fillRect(r,QBrush(QColor(255,0,0,120))); } } @@ -1217,151 +1185,141 @@ void TerminalDisplay::drawContents(QPainter &paint, const QRect &rect) { //qDebug("%s %d drawContents and rect x=%d y=%d w=%d h=%d", __FILE__, __LINE__, rect.x(), rect.y(),rect.width(),rect.height()); - QPoint tL = contentsRect().topLeft(); + QPoint tL = contentsRect().topLeft(); // int tLx = tL.x(); - int tLy = tL.y(); + int tLy = tL.y(); - int tLx = (_contentWidth - _usedColumns * _fontWidth)/2; -// int tLy = (_contentHeight - _usedLines * _fontHeight)/2; -//qDebug("%d %d %d %d", tLx, tLy, _contentWidth, _usedColumns * _fontWidth); + int tLx = (_contentWidth - _usedColumns * _fontWidth)/2; +// int tLy = (_contentHeight - _usedLines * _fontHeight)/2; +//qDebug("%d %d %d %d", tLx, tLy, _contentWidth, _usedColumns * _fontWidth); - int lux = qMin(_usedColumns-1, qMax(0,(rect.left() - tLx - _leftMargin ) / _fontWidth)); - int luy = qMin(_usedLines-1, qMax(0, (rect.top() - tLy - _topMargin ) / _fontHeight)); - int rlx = qMin(_usedColumns-1, qMax(0, (rect.right() - tLx - _leftMargin ) / _fontWidth)); - int rly = qMin(_usedLines-1, qMax(0, (rect.bottom() - tLy - _topMargin ) / _fontHeight)); + int lux = qMin(_usedColumns-1, qMax(0,(rect.left() - tLx - _leftMargin ) / _fontWidth)); + int luy = qMin(_usedLines-1, qMax(0, (rect.top() - tLy - _topMargin ) / _fontHeight)); + int rlx = qMin(_usedColumns-1, qMax(0, (rect.right() - tLx - _leftMargin ) / _fontWidth)); + int rly = qMin(_usedLines-1, qMax(0, (rect.bottom() - tLy - _topMargin ) / _fontHeight)); - const int bufferSize = _usedColumns; - QChar *disstrU = new QChar[bufferSize]; - for (int y = luy; y <= rly; y++) - { - quint16 c = _image[loc(lux,y)].character; - int x = lux; - if(!c && x) - x--; // Search for start of multi-column character - for (; x <= rlx; x++) - { - int len = 1; - int p = 0; + const int bufferSize = _usedColumns; + QChar *disstrU = new QChar[bufferSize]; + for (int y = luy; y <= rly; y++) { + quint16 c = _image[loc(lux,y)].character; + int x = lux; + if (!c && x) + x--; // Search for start of multi-column character + for (; x <= rlx; x++) { + int len = 1; + int p = 0; - // is this a single character or a sequence of characters ? - if ( _image[loc(x,y)].rendition & RE_EXTENDED_CHAR ) - { - // sequence of characters - ushort extendedCharLength = 0; - ushort* chars = ExtendedCharTable::instance - .lookupExtendedChar(_image[loc(x,y)].charSequence,extendedCharLength); - for ( int index = 0 ; index < extendedCharLength ; index++ ) - { - Q_ASSERT( p < bufferSize ); - disstrU[p++] = chars[index]; - } - } - else - { - // single character - c = _image[loc(x,y)].character; - if (c) - { - Q_ASSERT( p < bufferSize ); - disstrU[p++] = c; //fontMap(c); - } - } + // is this a single character or a sequence of characters ? + if ( _image[loc(x,y)].rendition & RE_EXTENDED_CHAR ) { + // sequence of characters + ushort extendedCharLength = 0; + ushort* chars = ExtendedCharTable::instance + .lookupExtendedChar(_image[loc(x,y)].charSequence,extendedCharLength); + for ( int index = 0 ; index < extendedCharLength ; index++ ) { + Q_ASSERT( p < bufferSize ); + disstrU[p++] = chars[index]; + } + } else { + // single character + c = _image[loc(x,y)].character; + if (c) { + Q_ASSERT( p < bufferSize ); + disstrU[p++] = c; //fontMap(c); + } + } - bool lineDraw = isLineChar(c); - bool doubleWidth = (_image[ qMin(loc(x,y)+1,_imageSize) ].character == 0); - CharacterColor currentForeground = _image[loc(x,y)].foregroundColor; - CharacterColor currentBackground = _image[loc(x,y)].backgroundColor; - quint8 currentRendition = _image[loc(x,y)].rendition; - - while (x+len <= rlx && - _image[loc(x+len,y)].foregroundColor == currentForeground && - _image[loc(x+len,y)].backgroundColor == currentBackground && - _image[loc(x+len,y)].rendition == currentRendition && - (_image[ qMin(loc(x+len,y)+1,_imageSize) ].character == 0) == doubleWidth && - isLineChar( c = _image[loc(x+len,y)].character) == lineDraw) // Assignment! - { - if (c) - disstrU[p++] = c; //fontMap(c); - if (doubleWidth) // assert((_image[loc(x+len,y)+1].character == 0)), see above if condition - len++; // Skip trailing part of multi-column character - len++; - } - if ((x+len < _usedColumns) && (!_image[loc(x+len,y)].character)) - len++; // Adjust for trailing part of multi-column character + bool lineDraw = isLineChar(c); + bool doubleWidth = (_image[ qMin(loc(x,y)+1,_imageSize) ].character == 0); + CharacterColor currentForeground = _image[loc(x,y)].foregroundColor; + CharacterColor currentBackground = _image[loc(x,y)].backgroundColor; + quint8 currentRendition = _image[loc(x,y)].rendition; - bool save__fixedFont = _fixedFont; - if (lineDraw) - _fixedFont = false; - if (doubleWidth) - _fixedFont = false; - QString unistr(disstrU,p); - - if (y < _lineProperties.size()) - { - if (_lineProperties[y] & LINE_DOUBLEWIDTH) { - paint.scale(2,1); - } - - if (_lineProperties[y] & LINE_DOUBLEHEIGHT) { - paint.scale(1,2); - } - } + while (x+len <= rlx && + _image[loc(x+len,y)].foregroundColor == currentForeground && + _image[loc(x+len,y)].backgroundColor == currentBackground && + _image[loc(x+len,y)].rendition == currentRendition && + (_image[ qMin(loc(x+len,y)+1,_imageSize) ].character == 0) == doubleWidth && + isLineChar( c = _image[loc(x+len,y)].character) == lineDraw) { // Assignment! + if (c) + disstrU[p++] = c; //fontMap(c); + if (doubleWidth) // assert((_image[loc(x+len,y)+1].character == 0)), see above if condition + len++; // Skip trailing part of multi-column character + len++; + } + if ((x+len < _usedColumns) && (!_image[loc(x+len,y)].character)) + len++; // Adjust for trailing part of multi-column character - //calculate the area in which the text will be drawn - QRect textArea = QRect( _leftMargin+tLx+_fontWidth*x , - _topMargin+tLy+_fontHeight*y , - _fontWidth*len, - _fontHeight); - - //move the calculated area to take account of scaling applied to the painter. - //the position of the area from the origin (0,0) is scaled - //by the opposite of whatever - //transformation has been applied to the painter. this ensures that - //painting does actually start from textArea.topLeft() - //(instead of textArea.topLeft() * painter-scale) - QMatrix inverted = paint.matrix().inverted(); + bool save__fixedFont = _fixedFont; + if (lineDraw) + _fixedFont = false; + if (doubleWidth) + _fixedFont = false; + QString unistr(disstrU,p); + + if (y < _lineProperties.size()) { + if (_lineProperties[y] & LINE_DOUBLEWIDTH) { + paint.scale(2,1); + } + + if (_lineProperties[y] & LINE_DOUBLEHEIGHT) { + paint.scale(1,2); + } + } + + //calculate the area in which the text will be drawn + QRect textArea = QRect( _leftMargin+tLx+_fontWidth*x , + _topMargin+tLy+_fontHeight*y , + _fontWidth*len, + _fontHeight); + + //move the calculated area to take account of scaling applied to the painter. + //the position of the area from the origin (0,0) is scaled + //by the opposite of whatever + //transformation has been applied to the painter. this ensures that + //painting does actually start from textArea.topLeft() + //(instead of textArea.topLeft() * painter-scale) + QMatrix inverted = paint.matrix().inverted(); // textArea.moveTopLeft( inverted.map(textArea.topLeft()) ); - textArea.moveCenter( inverted.map(textArea.center()) ); + textArea.moveCenter( inverted.map(textArea.center()) ); - - //paint text fragment - drawTextFragment( paint, - textArea, - unistr, - &_image[loc(x,y)] ); //, - //0, - //!_isPrinting ); - - _fixedFont = save__fixedFont; - - //reset back to single-width, single-height _lines - paint.resetMatrix(); - if (y < _lineProperties.size()-1) - { - //double-height _lines are represented by two adjacent _lines - //containing the same characters - //both _lines will have the LINE_DOUBLEHEIGHT attribute. - //If the current line has the LINE_DOUBLEHEIGHT attribute, - //we can therefore skip the next line - if (_lineProperties[y] & LINE_DOUBLEHEIGHT) - y++; - } - - x += len - 1; + //paint text fragment + drawTextFragment( paint, + textArea, + unistr, + &_image[loc(x,y)] ); //, + //0, + //!_isPrinting ); + + _fixedFont = save__fixedFont; + + //reset back to single-width, single-height _lines + paint.resetMatrix(); + + if (y < _lineProperties.size()-1) { + //double-height _lines are represented by two adjacent _lines + //containing the same characters + //both _lines will have the LINE_DOUBLEHEIGHT attribute. + //If the current line has the LINE_DOUBLEHEIGHT attribute, + //we can therefore skip the next line + if (_lineProperties[y] & LINE_DOUBLEHEIGHT) + y++; + } + + x += len - 1; + } } - } - delete [] disstrU; + delete [] disstrU; } void TerminalDisplay::blinkEvent() { - _blinking = !_blinking; + _blinking = !_blinking; - //TODO: Optimise to only repaint the areas of the widget - // where there is blinking text - // rather than repainting the whole widget. - update(); + //TODO: Optimise to only repaint the areas of the widget + // where there is blinking text + // rather than repainting the whole widget. + update(); } QRect TerminalDisplay::imageToWidget(const QRect& imageArea) const @@ -1378,11 +1336,11 @@ QRect TerminalDisplay::imageToWidget(const QRect& imageArea) const void TerminalDisplay::blinkCursorEvent() { - _cursorBlinking = !_cursorBlinking; + _cursorBlinking = !_cursorBlinking; - QRect cursorRect = imageToWidget( QRect(cursorPosition(),QSize(1,1)) ); + QRect cursorRect = imageToWidget( QRect(cursorPosition(),QSize(1,1)) ); - update(cursorRect); + update(cursorRect); } /* ------------------------------------------------------------------------- */ @@ -1393,67 +1351,63 @@ void TerminalDisplay::blinkCursorEvent() void TerminalDisplay::resizeEvent(QResizeEvent*) { - updateImageSize(); + updateImageSize(); } void TerminalDisplay::propagateSize() { - if (_isFixedSize) - { - setSize(_columns, _lines); - QWidget::setFixedSize(sizeHint()); - parentWidget()->adjustSize(); - parentWidget()->setFixedSize(parentWidget()->sizeHint()); - return; - } - if (_image) - updateImageSize(); + if (_isFixedSize) { + setSize(_columns, _lines); + QWidget::setFixedSize(sizeHint()); + parentWidget()->adjustSize(); + parentWidget()->setFixedSize(parentWidget()->sizeHint()); + return; + } + if (_image) + updateImageSize(); } void TerminalDisplay::updateImageSize() { //qDebug("%s %d updateImageSize", __FILE__, __LINE__); - Character* oldimg = _image; - int oldlin = _lines; - int oldcol = _columns; + Character* oldimg = _image; + int oldlin = _lines; + int oldcol = _columns; - makeImage(); + makeImage(); - - // copy the old image to reduce flicker - int lines = qMin(oldlin,_lines); - int columns = qMin(oldcol,_columns); - if (oldimg) - { - for (int line = 0; line < lines; line++) - { - memcpy((void*)&_image[_columns*line], - (void*)&oldimg[oldcol*line],columns*sizeof(Character)); + // copy the old image to reduce flicker + int lines = qMin(oldlin,_lines); + int columns = qMin(oldcol,_columns); + + if (oldimg) { + for (int line = 0; line < lines; line++) { + memcpy((void*)&_image[_columns*line], + (void*)&oldimg[oldcol*line],columns*sizeof(Character)); + } + delete[] oldimg; } - delete[] oldimg; - } - if (_screenWindow) - _screenWindow->setWindowLines(_lines); + if (_screenWindow) + _screenWindow->setWindowLines(_lines); - _resizing = (oldlin!=_lines) || (oldcol!=_columns); + _resizing = (oldlin!=_lines) || (oldcol!=_columns); - if ( _resizing ) - { - showResizeNotification(); - emit changedContentSizeSignal(_contentHeight, _contentWidth); // expose resizeEvent - } - - _resizing = false; + if ( _resizing ) { + showResizeNotification(); + emit changedContentSizeSignal(_contentHeight, _contentWidth); // expose resizeEvent + } + + _resizing = false; } -//showEvent and hideEvent are reimplemented here so that it appears to other classes that the +//showEvent and hideEvent are reimplemented here so that it appears to other classes that the //display has been resized when the display is hidden or shown. // -//this allows +//this allows //TODO: Perhaps it would be better to have separate signals for show and hide instead of using -//the same signal as the one for a content size change +//the same signal as the one for a content size change void TerminalDisplay::showEvent(QShowEvent*) { emit changedContentSizeSignal(_contentHeight,_contentWidth); @@ -1471,463 +1425,443 @@ void TerminalDisplay::hideEvent(QHideEvent*) void TerminalDisplay::scrollBarPositionChanged(int) { - if ( !_screenWindow ) - return; + if ( !_screenWindow ) + return; - _screenWindow->scrollTo( _scrollBar->value() ); + _screenWindow->scrollTo( _scrollBar->value() ); - // if the thumb has been moved to the bottom of the _scrollBar then set - // the display to automatically track new output, - // that is, scroll down automatically - // to how new _lines as they are added - const bool atEndOfOutput = (_scrollBar->value() == _scrollBar->maximum()); - _screenWindow->setTrackOutput( atEndOfOutput ); + // if the thumb has been moved to the bottom of the _scrollBar then set + // the display to automatically track new output, + // that is, scroll down automatically + // to how new _lines as they are added + const bool atEndOfOutput = (_scrollBar->value() == _scrollBar->maximum()); + _screenWindow->setTrackOutput( atEndOfOutput ); - updateImage(); + updateImage(); } void TerminalDisplay::setScroll(int cursor, int slines) { //qDebug("%s %d setScroll", __FILE__, __LINE__); - // update _scrollBar if the range or value has changed, - // otherwise return - // - // setting the range or value of a _scrollBar will always trigger - // a repaint, so it should be avoided if it is not necessary - if ( _scrollBar->minimum() == 0 && - _scrollBar->maximum() == (slines - _lines) && - _scrollBar->value() == cursor ) - { + // update _scrollBar if the range or value has changed, + // otherwise return + // + // setting the range or value of a _scrollBar will always trigger + // a repaint, so it should be avoided if it is not necessary + if ( _scrollBar->minimum() == 0 && + _scrollBar->maximum() == (slines - _lines) && + _scrollBar->value() == cursor ) { return; - } + } - disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); - _scrollBar->setRange(0,slines - _lines); - _scrollBar->setSingleStep(1); - _scrollBar->setPageStep(_lines); - _scrollBar->setValue(cursor); - connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); + disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); + _scrollBar->setRange(0,slines - _lines); + _scrollBar->setSingleStep(1); + _scrollBar->setPageStep(_lines); + _scrollBar->setValue(cursor); + connect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); } void TerminalDisplay::setScrollBarPosition(ScrollBarPosition position) { - if (_scrollbarLocation == position) { -// return; - } - - if ( position == NoScrollBar ) - _scrollBar->hide(); - else - _scrollBar->show(); + if (_scrollbarLocation == position) { +// return; + } - _topMargin = _leftMargin = 1; - _scrollbarLocation = position; - - propagateSize(); - update(); + if ( position == NoScrollBar ) + _scrollBar->hide(); + else + _scrollBar->show(); + + _topMargin = _leftMargin = 1; + _scrollbarLocation = position; + + propagateSize(); + update(); } void TerminalDisplay::mousePressEvent(QMouseEvent* ev) { - if ( _possibleTripleClick && (ev->button()==Qt::LeftButton) ) { - mouseTripleClickEvent(ev); - return; - } - - if ( !contentsRect().contains(ev->pos()) ) return; - - if ( !_screenWindow ) return; - - int charLine; - int charColumn; - getCharacterPosition(ev->pos(),charLine,charColumn); - QPoint pos = QPoint(charColumn,charLine); - - if ( ev->button() == Qt::LeftButton) - { - _lineSelectionMode = false; - _wordSelectionMode = 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); - - selected = _screenWindow->isSelected(pos.x(),pos.y()); - - if ((!_ctrlDrag || ev->modifiers() & Qt::ControlModifier) && selected ) { - // The user clicked inside selected text - dragInfo.state = diPending; - dragInfo.start = ev->pos(); + if ( _possibleTripleClick && (ev->button()==Qt::LeftButton) ) { + mouseTripleClickEvent(ev); + return; } - else { - // No reason to ever start a drag event - dragInfo.state = diNone; - _preserveLineBreaks = !( ( ev->modifiers() & Qt::ControlModifier ) && !(ev->modifiers() & Qt::AltModifier) ); - _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier); + if ( !contentsRect().contains(ev->pos()) ) return; - if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) - { - _screenWindow->clearSelection(); + if ( !_screenWindow ) return; - //emit clearSelectionSignal(); - pos.ry() += _scrollBar->value(); - _iPntSel = _pntSel = pos; - _actSel = 1; // left mouse button pressed but nothing selected yet. - - } - else - { - emit mouseSignal( 0, charColumn + 1, charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0); - } + int charLine; + int charColumn; + getCharacterPosition(ev->pos(),charLine,charColumn); + QPoint pos = QPoint(charColumn,charLine); + + if ( ev->button() == Qt::LeftButton) { + _lineSelectionMode = false; + _wordSelectionMode = 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); + + selected = _screenWindow->isSelected(pos.x(),pos.y()); + + if ((!_ctrlDrag || ev->modifiers() & Qt::ControlModifier) && 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; + + _preserveLineBreaks = !( ( ev->modifiers() & Qt::ControlModifier ) && !(ev->modifiers() & Qt::AltModifier) ); + _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier); + + if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) { + _screenWindow->clearSelection(); + + //emit clearSelectionSignal(); + pos.ry() += _scrollBar->value(); + _iPntSel = _pntSel = pos; + _actSel = 1; // left mouse button pressed but nothing selected yet. + + } else { + emit mouseSignal( 0, charColumn + 1, charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0); + } + } + } else if ( ev->button() == Qt::MidButton ) { + if ( _mouseMarks || (!_mouseMarks && (ev->modifiers() & Qt::ShiftModifier)) ) + emitSelection(true,ev->modifiers() & Qt::ControlModifier); + else + emit mouseSignal( 1, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0); + } else if ( ev->button() == Qt::RightButton ) { + if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) { + emit configureRequest( this, + ev->modifiers() & (Qt::ShiftModifier|Qt::ControlModifier), + ev->pos() + ); + } else + emit mouseSignal( 2, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0); } - } - else if ( ev->button() == Qt::MidButton ) - { - if ( _mouseMarks || (!_mouseMarks && (ev->modifiers() & Qt::ShiftModifier)) ) - emitSelection(true,ev->modifiers() & Qt::ControlModifier); - else - emit mouseSignal( 1, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0); - } - else if ( ev->button() == Qt::RightButton ) - { - if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) - { - emit configureRequest( this, - ev->modifiers() & (Qt::ShiftModifier|Qt::ControlModifier), - ev->pos() - ); - } - else - emit mouseSignal( 2, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0); - } } QList TerminalDisplay::filterActions(const QPoint& position) { - int charLine, charColumn; - getCharacterPosition(position,charLine,charColumn); + int charLine, charColumn; + getCharacterPosition(position,charLine,charColumn); - Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn); + Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn); - return spot ? spot->actions() : QList(); + return spot ? spot->actions() : QList(); } void TerminalDisplay::mouseMoveEvent(QMouseEvent* ev) { - int charLine = 0; - int charColumn = 0; + int charLine = 0; + int charColumn = 0; - getCharacterPosition(ev->pos(),charLine,charColumn); + getCharacterPosition(ev->pos(),charLine,charColumn); - // handle filters - // change link hot-spot appearance on mouse-over - Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn); - if ( spot && spot->type() == Filter::HotSpot::Link) - { - QRect previousHotspotArea = _mouseOverHotspotArea; - _mouseOverHotspotArea.setCoords( qMin(spot->startColumn() , spot->endColumn()) * _fontWidth, - spot->startLine() * _fontHeight, - qMax(spot->startColumn() , spot->endColumn()) * _fontHeight, - (spot->endLine()+1) * _fontHeight ); + // handle filters + // change link hot-spot appearance on mouse-over + Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn); + if ( spot && spot->type() == Filter::HotSpot::Link) { + QRect previousHotspotArea = _mouseOverHotspotArea; + _mouseOverHotspotArea.setCoords( qMin(spot->startColumn() , spot->endColumn()) * _fontWidth, + spot->startLine() * _fontHeight, + qMax(spot->startColumn() , spot->endColumn()) * _fontHeight, + (spot->endLine()+1) * _fontHeight ); - // display tooltips when mousing over links - // TODO: Extend this to work with filter types other than links - const QString& tooltip = spot->tooltip(); - if ( !tooltip.isEmpty() ) - { - QToolTip::showText( mapToGlobal(ev->pos()) , tooltip , this , _mouseOverHotspotArea ); - } + // display tooltips when mousing over links + // TODO: Extend this to work with filter types other than links + const QString& tooltip = spot->tooltip(); + if ( !tooltip.isEmpty() ) { + QToolTip::showText( mapToGlobal(ev->pos()) , tooltip , this , _mouseOverHotspotArea ); + } - update( _mouseOverHotspotArea | previousHotspotArea ); - } - else if ( _mouseOverHotspotArea.isValid() ) - { + update( _mouseOverHotspotArea | previousHotspotArea ); + } else if ( _mouseOverHotspotArea.isValid() ) { update( _mouseOverHotspotArea ); // set hotspot area to an invalid rectangle _mouseOverHotspotArea = QRect(); - } - - // for auto-hiding the cursor, we need mouseTracking - if (ev->buttons() == Qt::NoButton ) return; - - // if the terminal is interested in mouse movements - // then emit a mouse movement signal, unless the shift - // key is being held down, which overrides this. - if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) - { - int button = 3; - if (ev->buttons() & Qt::LeftButton) - button = 0; - if (ev->buttons() & Qt::MidButton) - button = 1; - if (ev->buttons() & Qt::RightButton) - button = 2; - - - emit mouseSignal( button, - charColumn + 1, - charLine + 1 +_scrollBar->value() -_scrollBar->maximum(), - 1 ); - - 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 = 10; //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. - - _screenWindow->clearSelection(); - 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; + // for auto-hiding the cursor, we need mouseTracking + if (ev->buttons() == Qt::NoButton ) return; - // don't extend selection while pasting - if (ev->buttons() & Qt::MidButton) return; + // if the terminal is interested in mouse movements + // then emit a mouse movement signal, unless the shift + // key is being held down, which overrides this. + if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) { + int button = 3; + if (ev->buttons() & Qt::LeftButton) + button = 0; + if (ev->buttons() & Qt::MidButton) + button = 1; + if (ev->buttons() & Qt::RightButton) + button = 2; - extendSelection( ev->pos() ); + + emit mouseSignal( button, + charColumn + 1, + charLine + 1 +_scrollBar->value() -_scrollBar->maximum(), + 1 ); + + 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 = 10; //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. + + _screenWindow->clearSelection(); + 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->buttons() & Qt::MidButton) return; + + extendSelection( ev->pos() ); } #if 0 void TerminalDisplay::setSelectionEnd() { - extendSelection( _configureRequestPoint ); + extendSelection( _configureRequestPoint ); } #endif -void TerminalDisplay::extendSelection(const QPoint& position) { - QPoint pos = position; +void TerminalDisplay::extendSelection(const QPoint& position) +{ + QPoint pos = position; - if (!_screenWindow) { - 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 + _leftMargin) { - pos.setX(tLx + _leftMargin); - } - if (pos.x() > tLx + _leftMargin + _usedColumns * _fontWidth - 1) { - pos.setX(tLx + _leftMargin + _usedColumns * _fontWidth); - } - if (pos.y() < tLy + _topMargin) { - pos.setY(tLy + _topMargin); - } - if (pos.y() > tLy + _topMargin + _usedLines * _fontHeight - 1) { - pos.setY(tLy + _topMargin + _usedLines * _fontHeight - 1); - } - - if (pos.y() == tLy + _topMargin + _usedLines * _fontHeight - 1) { - _scrollBar->setValue(_scrollBar->value() + yMouseScroll); // scrollforward - } - if (pos.y() == tLy + _topMargin) { - _scrollBar->setValue(_scrollBar->value() - yMouseScroll); // scrollback - } - - int charColumn = 0; - int charLine = 0; - getCharacterPosition(pos, charLine, charColumn); - - QPoint here = QPoint(charColumn, charLine); - QPoint ohere(here); - QPoint _iPntSelCorr = _iPntSel; - _iPntSelCorr.ry() -= _scrollBar->value(); - QPoint _pntSelCorr = _pntSel; - _pntSelCorr.ry() -= _scrollBar->value(); - bool swapping = false; - - if (_wordSelectionMode) { - // Extend to word boundaries - int i = 0; - int selClass = 0; - - 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 <= _imageSize) { - selClass = charClass(_image[i].character); - while (((left.x() > 0) || (left.y() > 0 && (_lineProperties[left.y() - 1] & LINE_WRAPPED))) - && charClass(_image[i - 1].character) == selClass) { - i--; - if (left.x() > 0) { - left.rx()--; - } else { - left.rx() = _usedColumns - 1; - left.ry()--; - } - } + if (!_screenWindow) { + return; } - // 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 <= _imageSize) { - selClass = charClass(_image[i].character); - while (((right.x() < _usedColumns - 1) || (right.y() < _usedLines - 1 && (_lineProperties[right.y()] & LINE_WRAPPED))) - && charClass(_image[i + 1].character) == selClass) { - i++; - if (right.x() < _usedColumns - 1) { - right.rx()++; - } else { - right.rx() = 0; - right.ry()++; - } - } + 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 + _leftMargin) { + pos.setX(tLx + _leftMargin); + } + if (pos.x() > tLx + _leftMargin + _usedColumns * _fontWidth - 1) { + pos.setX(tLx + _leftMargin + _usedColumns * _fontWidth); + } + if (pos.y() < tLy + _topMargin) { + pos.setY(tLy + _topMargin); + } + if (pos.y() > tLy + _topMargin + _usedLines * _fontHeight - 1) { + pos.setY(tLy + _topMargin + _usedLines * _fontHeight - 1); } - // Pick which is start (ohere) and which is extension (here) - if (left_not_right) { - here = left; - ohere = right; - } else { - here = right; - ohere = left; + if (pos.y() == tLy + _topMargin + _usedLines * _fontHeight - 1) { + _scrollBar->setValue(_scrollBar->value() + yMouseScroll); // scrollforward } - ohere.rx()++; - } - - if (_lineSelectionMode) { - // 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 && (_lineProperties[above.y() - 1] & LINE_WRAPPED)) { - above.ry()--; - } - while (below.y() < _usedLines - 1 && (_lineProperties[below.y()] & LINE_WRAPPED)) { - below.ry()++; - } - - above.setX(0); - below.setX(_usedColumns - 1); - - // Pick which is start (ohere) and which is extension (here) - if (above_not_below) { - here = above; - ohere = below; - } else { - here = below; - ohere = above; + if (pos.y() == tLy + _topMargin) { + _scrollBar->setValue(_scrollBar->value() - yMouseScroll); // scrollback } - QPoint newSelBegin = QPoint(ohere.x(), ohere.y()); - swapping = !(_tripleSelBegin == newSelBegin); - _tripleSelBegin = newSelBegin; + int charColumn = 0; + int charLine = 0; + getCharacterPosition(pos, charLine, charColumn); - ohere.rx()++; - } + QPoint here = QPoint(charColumn, charLine); + QPoint ohere(here); + QPoint _iPntSelCorr = _iPntSel; + _iPntSelCorr.ry() -= _scrollBar->value(); + QPoint _pntSelCorr = _pntSel; + _pntSelCorr.ry() -= _scrollBar->value(); + bool swapping = false; - int offset = 0; - if (!_wordSelectionMode && !_lineSelectionMode) { - int i = 0; - int selClass = 0; + if (_wordSelectionMode) { + // Extend to word boundaries + int i = 0; + int selClass = 0; - 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; + 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 && !_columnSelectionMode) { - i = loc(right.x(), right.y()); - if (i >= 0 && i <= _imageSize) { - selClass = charClass(_image[i - 1].character); - if (selClass == ' ') { - while (right.x() < _usedColumns - 1 && charClass(_image[i + 1].character) == selClass && (right.y() < _usedLines - 1) && - !(_lineProperties[right.y()] & LINE_WRAPPED)) { - i++; - right.rx()++; - } - if (right.x() < _usedColumns - 1) { - right = left_not_right ? _iPntSelCorr : here; - } else { - right.rx()++; // will be balanced later because of offset=-1; - } + // 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 <= _imageSize) { + selClass = charClass(_image[i].character); + while (((left.x() > 0) || (left.y() > 0 && (_lineProperties[left.y() - 1] & LINE_WRAPPED))) + && charClass(_image[i - 1].character) == selClass) { + i--; + if (left.x() > 0) { + left.rx()--; + } else { + left.rx() = _usedColumns - 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 <= _imageSize) { + selClass = charClass(_image[i].character); + while (((right.x() < _usedColumns - 1) || (right.y() < _usedLines - 1 && (_lineProperties[right.y()] & LINE_WRAPPED))) + && charClass(_image[i + 1].character) == selClass) { + i++; + if (right.x() < _usedColumns - 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()++; } - // 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 (_lineSelectionMode) { + // 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 && (_lineProperties[above.y() - 1] & LINE_WRAPPED)) { + above.ry()--; + } + while (below.y() < _usedLines - 1 && (_lineProperties[below.y()] & LINE_WRAPPED)) { + below.ry()++; + } + + above.setX(0); + below.setX(_usedColumns - 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()++; } - } - if ((here == _pntSelCorr) && (scroll == _scrollBar->value())) { - return; // not moved - } + int offset = 0; + if (!_wordSelectionMode && !_lineSelectionMode) { + int i = 0; + int selClass = 0; - if (here == ohere) { - return; // It's not left, it's not right. - } + 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 && !_columnSelectionMode) { + i = loc(right.x(), right.y()); + if (i >= 0 && i <= _imageSize) { + selClass = charClass(_image[i - 1].character); + if (selClass == ' ') { + while (right.x() < _usedColumns - 1 && charClass(_image[i + 1].character) == selClass && (right.y() < _usedLines - 1) && + !(_lineProperties[right.y()] & LINE_WRAPPED)) { + i++; + right.rx()++; + } + if (right.x() < _usedColumns - 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 (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) { + _screenWindow->setSelectionStart(ohere.x(), ohere.y(), true); + } else { + _screenWindow->setSelectionStart(ohere.x() - 1 - offset , ohere.y(), false); + } + + } + + _actSel = 2; // within selection + _pntSel = here; + _pntSel.ry() += _scrollBar->value(); - if (_actSel < 2 || swapping) { if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) { - _screenWindow->setSelectionStart(ohere.x(), ohere.y(), true); + _screenWindow->setSelectionEnd(here.x(), here.y()); } else { - _screenWindow->setSelectionStart(ohere.x() - 1 - offset , ohere.y(), false); + _screenWindow->setSelectionEnd(here.x() + offset, here.y()); } - - } - - _actSel = 2; // within selection - _pntSel = here; - _pntSel.ry() += _scrollBar->value(); - - if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) { - _screenWindow->setSelectionEnd(here.x(), here.y()); - } else { - _screenWindow->setSelectionEnd(here.x() + offset, here.y()); - } } void TerminalDisplay::mouseReleaseEvent(QMouseEvent* ev) @@ -1939,46 +1873,40 @@ void TerminalDisplay::mouseReleaseEvent(QMouseEvent* ev) int charColumn; getCharacterPosition(ev->pos(),charLine,charColumn); - if ( ev->button() == Qt::LeftButton) - { - emit isBusySelecting(false); - if(dragInfo.state == diPending) - { - // We had a drag event pending but never confirmed. Kill selection - _screenWindow->clearSelection(); - //emit clearSelectionSignal(); + if ( ev->button() == Qt::LeftButton) { + emit isBusySelecting(false); + if (dragInfo.state == diPending) { + // We had a drag event pending but never confirmed. Kill selection + _screenWindow->clearSelection(); + //emit clearSelectionSignal(); + } else { + if ( _actSel > 1 ) { + setSelection( _screenWindow->selectedText(_preserveLineBreaks) ); + } + + _actSel = 0; + + //FIXME: emits a release event even if the mouse is + // outside the range. The procedure used in `mouseMoveEvent' + // applies here, too. + + if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) + emit mouseSignal( 3, // release + charColumn + 1, + charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0); + } + dragInfo.state = diNone; } - else - { - if ( _actSel > 1 ) - { - setSelection( _screenWindow->selectedText(_preserveLineBreaks) ); - } - _actSel = 0; - //FIXME: emits a release event even if the mouse is - // outside the range. The procedure used in `mouseMoveEvent' - // applies here, too. - - if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) - emit mouseSignal( 3, // release - charColumn + 1, - charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0); + if ( !_mouseMarks && + ((ev->button() == Qt::RightButton && !(ev->modifiers() & Qt::ShiftModifier)) + || ev->button() == Qt::MidButton) ) { + emit mouseSignal( 3, + charColumn + 1, + charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , + 0); } - dragInfo.state = diNone; - } - - - if ( !_mouseMarks && - ((ev->button() == Qt::RightButton && !(ev->modifiers() & Qt::ShiftModifier)) - || ev->button() == Qt::MidButton) ) - { - emit mouseSignal( 3, - charColumn + 1, - charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , - 0); - } } void TerminalDisplay::getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const @@ -2006,193 +1934,184 @@ void TerminalDisplay::getCharacterPosition(const QPoint& widgetPoint,int& line,i void TerminalDisplay::updateLineProperties() { - if ( !_screenWindow ) + if ( !_screenWindow ) return; - _lineProperties = _screenWindow->getLineProperties(); + _lineProperties = _screenWindow->getLineProperties(); } void TerminalDisplay::mouseDoubleClickEvent(QMouseEvent* ev) { - if ( ev->button() != Qt::LeftButton) return; - if ( !_screenWindow ) return; + if ( ev->button() != Qt::LeftButton) return; + if ( !_screenWindow ) return; - int charLine = 0; - int charColumn = 0; + int charLine = 0; + int charColumn = 0; - getCharacterPosition(ev->pos(),charLine,charColumn); + getCharacterPosition(ev->pos(),charLine,charColumn); - QPoint pos(charColumn,charLine); + QPoint pos(charColumn,charLine); - // pass on double click as two clicks. - if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) - { - // 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->maximum(), - 0 ); // left button - return; - } + // pass on double click as two clicks. + if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) { + // 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->maximum(), + 0 ); // left button + return; + } - _screenWindow->clearSelection(); - QPoint bgnSel = pos; - QPoint endSel = pos; - int i = loc(bgnSel.x(),bgnSel.y()); - _iPntSel = bgnSel; - _iPntSel.ry() += _scrollBar->value(); + _screenWindow->clearSelection(); + QPoint bgnSel = pos; + QPoint endSel = pos; + int i = loc(bgnSel.x(),bgnSel.y()); + _iPntSel = bgnSel; + _iPntSel.ry() += _scrollBar->value(); - _wordSelectionMode = true; + _wordSelectionMode = true; - // find word boundaries... - int selClass = charClass(_image[i].character); - { - // find the start of the word - int x = bgnSel.x(); - while ( ((x>0) || (bgnSel.y()>0 && (_lineProperties[bgnSel.y()-1] & LINE_WRAPPED) )) - && charClass(_image[i-1].character) == selClass ) - { - i--; - if (x>0) - x--; - else - { - x=_usedColumns-1; - bgnSel.ry()--; - } - } + // find word boundaries... + int selClass = charClass(_image[i].character); + { + // find the start of the word + int x = bgnSel.x(); + while ( ((x>0) || (bgnSel.y()>0 && (_lineProperties[bgnSel.y()-1] & LINE_WRAPPED) )) + && charClass(_image[i-1].character) == selClass ) { + i--; + if (x>0) + x--; + else { + x=_usedColumns-1; + bgnSel.ry()--; + } + } - bgnSel.setX(x); - _screenWindow->setSelectionStart( bgnSel.x() , bgnSel.y() , false ); + bgnSel.setX(x); + _screenWindow->setSelectionStart( bgnSel.x() , bgnSel.y() , false ); - // find the end of the word - i = loc( endSel.x(), endSel.y() ); - x = endSel.x(); - while( ((x<_usedColumns-1) || (endSel.y()<_usedLines-1 && (_lineProperties[endSel.y()] & LINE_WRAPPED) )) - && charClass(_image[i+1].character) == selClass ) - { - i++; - if (x<_usedColumns-1) - x++; - else - { - x=0; - endSel.ry()++; - } - } + // find the end of the word + i = loc( endSel.x(), endSel.y() ); + x = endSel.x(); + while ( ((x<_usedColumns-1) || (endSel.y()<_usedLines-1 && (_lineProperties[endSel.y()] & LINE_WRAPPED) )) + && charClass(_image[i+1].character) == selClass ) { + i++; + if (x<_usedColumns-1) + x++; + else { + x=0; + endSel.ry()++; + } + } - endSel.setX(x); + endSel.setX(x); - // In word selection mode don't select @ (64) if at end of word. - if ( ( QChar( _image[i].character ) == '@' ) && ( ( endSel.x() - bgnSel.x() ) > 0 ) ) - endSel.setX( x - 1 ); + // In word selection mode don't select @ (64) if at end of word. + if ( ( QChar( _image[i].character ) == '@' ) && ( ( endSel.x() - bgnSel.x() ) > 0 ) ) + endSel.setX( x - 1 ); - _actSel = 2; // within selection - - _screenWindow->setSelectionEnd( endSel.x() , endSel.y() ); - - setSelection( _screenWindow->selectedText(_preserveLineBreaks) ); - } + _actSel = 2; // within selection - _possibleTripleClick=true; + _screenWindow->setSelectionEnd( endSel.x() , endSel.y() ); - QTimer::singleShot(QApplication::doubleClickInterval(),this, - SLOT(tripleClickTimeout())); + setSelection( _screenWindow->selectedText(_preserveLineBreaks) ); + } + + _possibleTripleClick=true; + + QTimer::singleShot(QApplication::doubleClickInterval(),this, + SLOT(tripleClickTimeout())); } void TerminalDisplay::wheelEvent( QWheelEvent* ev ) { - if (ev->orientation() != Qt::Vertical) - return; + if (ev->orientation() != Qt::Vertical) + return; - if ( _mouseMarks ) - _scrollBar->event(ev); - else - { - int charLine; - int charColumn; - getCharacterPosition( ev->pos() , charLine , charColumn ); - - emit mouseSignal( ev->delta() > 0 ? 4 : 5, - charColumn + 1, - charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , - 0); - } + if ( _mouseMarks ) + _scrollBar->event(ev); + else { + int charLine; + int charColumn; + getCharacterPosition( ev->pos() , charLine , charColumn ); + + emit mouseSignal( ev->delta() > 0 ? 4 : 5, + charColumn + 1, + charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , + 0); + } } void TerminalDisplay::tripleClickTimeout() { - _possibleTripleClick=false; + _possibleTripleClick=false; } void TerminalDisplay::mouseTripleClickEvent(QMouseEvent* ev) { - if ( !_screenWindow ) return; + if ( !_screenWindow ) return; - int charLine; - int charColumn; - getCharacterPosition(ev->pos(),charLine,charColumn); - _iPntSel = QPoint(charColumn,charLine); + int charLine; + int charColumn; + getCharacterPosition(ev->pos(),charLine,charColumn); + _iPntSel = QPoint(charColumn,charLine); - _screenWindow->clearSelection(); + _screenWindow->clearSelection(); - _lineSelectionMode = true; - _wordSelectionMode = false; + _lineSelectionMode = true; + _wordSelectionMode = false; - _actSel = 2; // within selection - emit isBusySelecting(true); // Keep it steady... + _actSel = 2; // within selection + emit isBusySelecting(true); // Keep it steady... - while (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) ) - _iPntSel.ry()--; - - if (_tripleClickMode == SelectForwardsFromCursor) { - // find word boundary start - int i = loc(_iPntSel.x(),_iPntSel.y()); - int selClass = charClass(_image[i].character); - int x = _iPntSel.x(); - - while ( ((x>0) || - (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) ) - ) - && charClass(_image[i-1].character) == selClass ) - { - i--; - if (x>0) - x--; - else - { - x=_columns-1; - _iPntSel.ry()--; - } + while (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) ) + _iPntSel.ry()--; + + if (_tripleClickMode == SelectForwardsFromCursor) { + // find word boundary start + int i = loc(_iPntSel.x(),_iPntSel.y()); + int selClass = charClass(_image[i].character); + int x = _iPntSel.x(); + + while ( ((x>0) || + (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) ) + ) + && charClass(_image[i-1].character) == selClass ) { + i--; + if (x>0) + x--; + else { + x=_columns-1; + _iPntSel.ry()--; + } + } + + _screenWindow->setSelectionStart( x , _iPntSel.y() , false ); + _tripleSelBegin = QPoint( x, _iPntSel.y() ); + } else if (_tripleClickMode == SelectWholeLine) { + _screenWindow->setSelectionStart( 0 , _iPntSel.y() , false ); + _tripleSelBegin = QPoint( 0, _iPntSel.y() ); } - _screenWindow->setSelectionStart( x , _iPntSel.y() , false ); - _tripleSelBegin = QPoint( x, _iPntSel.y() ); - } - else if (_tripleClickMode == SelectWholeLine) { - _screenWindow->setSelectionStart( 0 , _iPntSel.y() , false ); - _tripleSelBegin = QPoint( 0, _iPntSel.y() ); - } + while (_iPntSel.y()<_lines-1 && (_lineProperties[_iPntSel.y()] & LINE_WRAPPED) ) + _iPntSel.ry()++; - while (_iPntSel.y()<_lines-1 && (_lineProperties[_iPntSel.y()] & LINE_WRAPPED) ) - _iPntSel.ry()++; - - _screenWindow->setSelectionEnd( _columns - 1 , _iPntSel.y() ); + _screenWindow->setSelectionEnd( _columns - 1 , _iPntSel.y() ); - setSelection(_screenWindow->selectedText(_preserveLineBreaks)); + setSelection(_screenWindow->selectedText(_preserveLineBreaks)); - _iPntSel.ry() += _scrollBar->value(); + _iPntSel.ry() += _scrollBar->value(); } bool TerminalDisplay::focusNextPrevChild( bool next ) { - if (next) - return false; // This disables changing the active part in konqueror - // when pressing Tab - return QWidget::focusNextPrevChild( next ); + if (next) + return false; // This disables changing the active part in konqueror + // when pressing Tab + return QWidget::focusNextPrevChild( next ); } @@ -2202,7 +2121,7 @@ int TerminalDisplay::charClass(quint16 ch) const if ( qch.isSpace() ) return ' '; if ( qch.isLetterOrNumber() || _wordCharacters.contains(qch, Qt::CaseInsensitive ) ) - return 'a'; + return 'a'; // Everything else is weird return 1; @@ -2210,13 +2129,13 @@ int TerminalDisplay::charClass(quint16 ch) const void TerminalDisplay::setWordCharacters(const QString& wc) { - _wordCharacters = wc; + _wordCharacters = wc; } void TerminalDisplay::setUsesMouse(bool on) { - _mouseMarks = on; - setCursor( _mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor ); + _mouseMarks = on; + setCursor( _mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor ); } bool TerminalDisplay::usesMouse() const { @@ -2233,46 +2152,45 @@ bool TerminalDisplay::usesMouse() const void TerminalDisplay::emitSelection(bool useXselection,bool appendReturn) { - if ( !_screenWindow ) - return; + if ( !_screenWindow ) + return; - // Paste Clipboard by simulating keypress events - QString text = QApplication::clipboard()->text(useXselection ? QClipboard::Selection : - QClipboard::Clipboard); - if(appendReturn) - text.append("\r"); - if ( ! text.isEmpty() ) - { - text.replace("\n", "\r"); - QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text); - emit keyPressedSignal(&e); // expose as a big fat keypress event - - _screenWindow->clearSelection(); - } + // Paste Clipboard by simulating keypress events + QString text = QApplication::clipboard()->text(useXselection ? QClipboard::Selection : + QClipboard::Clipboard); + if (appendReturn) + text.append("\r"); + if ( ! text.isEmpty() ) { + text.replace("\n", "\r"); + QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text); + emit keyPressedSignal(&e); // expose as a big fat keypress event + + _screenWindow->clearSelection(); + } } void TerminalDisplay::setSelection(const QString& t) { - QApplication::clipboard()->setText(t, QClipboard::Selection); + QApplication::clipboard()->setText(t, QClipboard::Selection); } void TerminalDisplay::copyClipboard() { - if ( !_screenWindow ) - return; + if ( !_screenWindow ) + return; - QString text = _screenWindow->selectedText(_preserveLineBreaks); - QApplication::clipboard()->setText(text); + QString text = _screenWindow->selectedText(_preserveLineBreaks); + QApplication::clipboard()->setText(text); } void TerminalDisplay::pasteClipboard() { - emitSelection(false,false); + emitSelection(false,false); } void TerminalDisplay::pasteSelection() { - emitSelection(true,false); + emitSelection(true,false); } /* ------------------------------------------------------------------------- */ @@ -2283,12 +2201,12 @@ void TerminalDisplay::pasteSelection() void TerminalDisplay::setFlowControlWarningEnabled( bool enable ) { - _flowControlWarningEnabled = enable; - - // if the dialog is currently visible and the flow control warning has - // been disabled then hide the dialog - if (!enable) - outputSuspended(false); + _flowControlWarningEnabled = enable; + + // if the dialog is currently visible and the flow control warning has + // been disabled then hide the dialog + if (!enable) + outputSuspended(false); } void TerminalDisplay::keyPressEvent( QKeyEvent* event ) @@ -2298,52 +2216,40 @@ void TerminalDisplay::keyPressEvent( QKeyEvent* event ) bool emitKeyPressSignal = true; // XonXoff flow control - if (event->modifiers() & Qt::ControlModifier && _flowControlWarningEnabled) - { - if ( event->key() == Qt::Key_S ) { - //qDebug("%s %d keyPressEvent, output suspended", __FILE__, __LINE__); - emit flowControlKeyPressed(true /*output suspended*/); - } - else if ( event->key() == Qt::Key_Q ) { - //qDebug("%s %d keyPressEvent, output enabled", __FILE__, __LINE__); - emit flowControlKeyPressed(false /*output enabled*/); - } - } + if (event->modifiers() & Qt::ControlModifier && _flowControlWarningEnabled) { + if ( event->key() == Qt::Key_S ) { + //qDebug("%s %d keyPressEvent, output suspended", __FILE__, __LINE__); + emit flowControlKeyPressed(true /*output suspended*/); + } else if ( event->key() == Qt::Key_Q ) { + //qDebug("%s %d keyPressEvent, output enabled", __FILE__, __LINE__); + emit flowControlKeyPressed(false /*output enabled*/); + } + } // Keyboard-based navigation - if ( event->modifiers() == Qt::ShiftModifier ) - { + if ( event->modifiers() == Qt::ShiftModifier ) { bool update = true; - if ( event->key() == Qt::Key_PageUp ) - { - //qDebug("%s %d pageup", __FILE__, __LINE__); + if ( event->key() == Qt::Key_PageUp ) { + //qDebug("%s %d pageup", __FILE__, __LINE__); _screenWindow->scrollBy( ScreenWindow::ScrollPages , -1 ); - } - else if ( event->key() == Qt::Key_PageDown ) - { - //qDebug("%s %d pagedown", __FILE__, __LINE__); + } else if ( event->key() == Qt::Key_PageDown ) { + //qDebug("%s %d pagedown", __FILE__, __LINE__); _screenWindow->scrollBy( ScreenWindow::ScrollPages , 1 ); - } - else if ( event->key() == Qt::Key_Up ) - { - //qDebug("%s %d keyup", __FILE__, __LINE__); + } else if ( event->key() == Qt::Key_Up ) { + //qDebug("%s %d keyup", __FILE__, __LINE__); _screenWindow->scrollBy( ScreenWindow::ScrollLines , -1 ); - } - else if ( event->key() == Qt::Key_Down ) - { - //qDebug("%s %d keydown", __FILE__, __LINE__); + } else if ( event->key() == Qt::Key_Down ) { + //qDebug("%s %d keydown", __FILE__, __LINE__); _screenWindow->scrollBy( ScreenWindow::ScrollLines , 1 ); - } - else { + } else { update = false; - } + } - if ( update ) - { - //qDebug("%s %d updating", __FILE__, __LINE__); + if ( update ) { + //qDebug("%s %d updating", __FILE__, __LINE__); _screenWindow->setTrackOutput( _screenWindow->atEndOfOutput() ); - + updateLineProperties(); updateImage(); @@ -2351,19 +2257,18 @@ void TerminalDisplay::keyPressEvent( QKeyEvent* event ) emitKeyPressSignal = false; } } - - _screenWindow->setTrackOutput( true ); - - _actSel=0; // Key stroke implies a screen update, so TerminalDisplay won't - // know where the current selection is. - if (_hasBlinkingCursor) - { - _blinkCursorTimer->start(BLINK_DELAY); - if (_cursorBlinking) - blinkCursorEvent(); - else - _cursorBlinking = false; + _screenWindow->setTrackOutput( true ); + + _actSel=0; // Key stroke implies a screen update, so TerminalDisplay won't + // know where the current selection is. + + if (_hasBlinkingCursor) { + _blinkCursorTimer->start(BLINK_DELAY); + if (_cursorBlinking) + blinkCursorEvent(); + else + _cursorBlinking = false; } if ( emitKeyPressSignal ) @@ -2379,41 +2284,39 @@ void TerminalDisplay::inputMethodEvent( QInputMethodEvent* event ) _inputMethodData.preeditString = event->preeditString(); update(preeditRect() | _inputMethodData.previousPreeditRect); - + event->accept(); } QVariant TerminalDisplay::inputMethodQuery( Qt::InputMethodQuery query ) const { const QPoint cursorPos = _screenWindow ? _screenWindow->cursorPosition() : QPoint(0,0); - switch ( query ) - { - case Qt::ImMicroFocus: - return imageToWidget(QRect(cursorPos.x(),cursorPos.y(),1,1)); - break; - case Qt::ImFont: - return font(); - break; - case Qt::ImCursorPosition: - // return the cursor position within the current line - return cursorPos.x(); - break; - case Qt::ImSurroundingText: - { - // return the text from the current line - QString lineText; - QTextStream stream(&lineText); - PlainTextDecoder decoder; - decoder.begin(&stream); - decoder.decodeLine(&_image[loc(0,cursorPos.y())],_usedColumns,_lineProperties[cursorPos.y()]); - decoder.end(); - return lineText; - } - break; - case Qt::ImCurrentSelection: - return QString(); - break; - default: - break; + switch ( query ) { + case Qt::ImMicroFocus: + return imageToWidget(QRect(cursorPos.x(),cursorPos.y(),1,1)); + break; + case Qt::ImFont: + return font(); + break; + case Qt::ImCursorPosition: + // return the cursor position within the current line + return cursorPos.x(); + break; + case Qt::ImSurroundingText: { + // return the text from the current line + QString lineText; + QTextStream stream(&lineText); + PlainTextDecoder decoder; + decoder.begin(&stream); + decoder.decodeLine(&_image[loc(0,cursorPos.y())],_usedColumns,_lineProperties[cursorPos.y()]); + decoder.end(); + return lineText; + } + break; + case Qt::ImCurrentSelection: + return QString(); + break; + default: + break; } return QVariant(); @@ -2421,46 +2324,43 @@ QVariant TerminalDisplay::inputMethodQuery( Qt::InputMethodQuery query ) const bool TerminalDisplay::event( QEvent *e ) { - if ( e->type() == QEvent::ShortcutOverride ) - { - QKeyEvent* keyEvent = static_cast( e ); + if ( e->type() == QEvent::ShortcutOverride ) { + QKeyEvent* keyEvent = static_cast( e ); - // a check to see if keyEvent->text() is empty is used - // to avoid intercepting the press of the modifier key on its own. - // - // this is important as it allows a press and release of the Alt key - // on its own to focus the menu bar, making it possible to - // work with the menu without using the mouse - if ( (keyEvent->modifiers() == Qt::AltModifier) && - !keyEvent->text().isEmpty() ) - { - keyEvent->accept(); - return true; - } + // a check to see if keyEvent->text() is empty is used + // to avoid intercepting the press of the modifier key on its own. + // + // this is important as it allows a press and release of the Alt key + // on its own to focus the menu bar, making it possible to + // work with the menu without using the mouse + if ( (keyEvent->modifiers() == Qt::AltModifier) && + !keyEvent->text().isEmpty() ) { + keyEvent->accept(); + return true; + } - // Override any of the following shortcuts because - // they are needed by the terminal - int keyCode = keyEvent->key() | keyEvent->modifiers(); - switch ( keyCode ) - { - // list is taken from the QLineEdit::event() code - case Qt::Key_Tab: - case Qt::Key_Delete: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_Backspace: - case Qt::Key_Left: - case Qt::Key_Right: - keyEvent->accept(); - return true; + // Override any of the following shortcuts because + // they are needed by the terminal + int keyCode = keyEvent->key() | keyEvent->modifiers(); + switch ( keyCode ) { + // list is taken from the QLineEdit::event() code + case Qt::Key_Tab: + case Qt::Key_Delete: + case Qt::Key_Home: + case Qt::Key_End: + case Qt::Key_Backspace: + case Qt::Key_Left: + case Qt::Key_Right: + keyEvent->accept(); + return true; + } } - } - return QWidget::event( e ); + return QWidget::event( e ); } void TerminalDisplay::setBellMode(int mode) { - _bellMode=mode; + _bellMode=mode; } void TerminalDisplay::enableBell() @@ -2470,151 +2370,140 @@ void TerminalDisplay::enableBell() void TerminalDisplay::bell(const QString&) { - if (_bellMode==NoBell) return; + if (_bellMode==NoBell) return; - //limit the rate at which bells can occur - //...mainly for sound effects where rapid bells in sequence - //produce a horrible noise - if ( _allowBell ) - { - _allowBell = false; - QTimer::singleShot(500,this,SLOT(enableBell())); - - if (_bellMode==SystemBeepBell) - { + //limit the rate at which bells can occur + //...mainly for sound effects where rapid bells in sequence + //produce a horrible noise + if ( _allowBell ) { + _allowBell = false; + QTimer::singleShot(500,this,SLOT(enableBell())); + + if (_bellMode==SystemBeepBell) { // KNotification::beep(); - } - else if (_bellMode==NotifyBell) - { + } else if (_bellMode==NotifyBell) { // KNotification::event("BellVisible", message,QPixmap(),this); - } - else if (_bellMode==VisualBell) - { - swapColorTable(); - QTimer::singleShot(200,this,SLOT(swapColorTable())); + } else if (_bellMode==VisualBell) { + swapColorTable(); + QTimer::singleShot(200,this,SLOT(swapColorTable())); + } } - } } void TerminalDisplay::swapColorTable() { - ColorEntry color = _colorTable[1]; - _colorTable[1]=_colorTable[0]; - _colorTable[0]= color; - _colorsInverted = !_colorsInverted; - update(); + ColorEntry color = _colorTable[1]; + _colorTable[1]=_colorTable[0]; + _colorTable[0]= color; + _colorsInverted = !_colorsInverted; + update(); } void TerminalDisplay::clearImage() { - // We initialize _image[_imageSize] too. See makeImage() - for (int i = 0; i <= _imageSize; i++) - { - _image[i].character = ' '; - _image[i].foregroundColor = CharacterColor(COLOR_SPACE_DEFAULT, - DEFAULT_FORE_COLOR); - _image[i].backgroundColor = CharacterColor(COLOR_SPACE_DEFAULT, - DEFAULT_BACK_COLOR); - _image[i].rendition = DEFAULT_RENDITION; - } + // We initialize _image[_imageSize] too. See makeImage() + for (int i = 0; i <= _imageSize; i++) { + _image[i].character = ' '; + _image[i].foregroundColor = CharacterColor(COLOR_SPACE_DEFAULT, + DEFAULT_FORE_COLOR); + _image[i].backgroundColor = CharacterColor(COLOR_SPACE_DEFAULT, + DEFAULT_BACK_COLOR); + _image[i].rendition = DEFAULT_RENDITION; + } } void TerminalDisplay::calcGeometry() { - _scrollBar->resize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent), - contentsRect().height()); - switch(_scrollbarLocation) - { + _scrollBar->resize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent), + contentsRect().height()); + switch (_scrollbarLocation) { case NoScrollBar : - _leftMargin = DEFAULT_LEFT_MARGIN; - _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN; - break; + _leftMargin = DEFAULT_LEFT_MARGIN; + _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN; + break; case ScrollBarLeft : - _leftMargin = DEFAULT_LEFT_MARGIN + _scrollBar->width(); - _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width(); - _scrollBar->move(contentsRect().topLeft()); - break; + _leftMargin = DEFAULT_LEFT_MARGIN + _scrollBar->width(); + _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width(); + _scrollBar->move(contentsRect().topLeft()); + break; case ScrollBarRight: - _leftMargin = DEFAULT_LEFT_MARGIN; - _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width(); - _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width()-1,0)); - break; - } + _leftMargin = DEFAULT_LEFT_MARGIN; + _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width(); + _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width()-1,0)); + break; + } - _topMargin = DEFAULT_TOP_MARGIN; - _contentHeight = contentsRect().height() - 2 * DEFAULT_TOP_MARGIN + /* mysterious */ 1; + _topMargin = DEFAULT_TOP_MARGIN; + _contentHeight = contentsRect().height() - 2 * DEFAULT_TOP_MARGIN + /* mysterious */ 1; - if (!_isFixedSize) - { - // ensure that display is always at least one column wide - _columns = qMax(1,_contentWidth / _fontWidth); - _usedColumns = qMin(_usedColumns,_columns); - - // ensure that display is always at least one line high - _lines = qMax(1,_contentHeight / _fontHeight); - _usedLines = qMin(_usedLines,_lines); - } + if (!_isFixedSize) { + // ensure that display is always at least one column wide + _columns = qMax(1,_contentWidth / _fontWidth); + _usedColumns = qMin(_usedColumns,_columns); + + // ensure that display is always at least one line high + _lines = qMax(1,_contentHeight / _fontHeight); + _usedLines = qMin(_usedLines,_lines); + } } void TerminalDisplay::makeImage() { //qDebug("%s %d makeImage", __FILE__, __LINE__); - calcGeometry(); + calcGeometry(); - // confirm that array will be of non-zero size, since the painting code - // assumes a non-zero array length - Q_ASSERT( _lines > 0 && _columns > 0 ); - Q_ASSERT( _usedLines <= _lines && _usedColumns <= _columns ); + // confirm that array will be of non-zero size, since the painting code + // assumes a non-zero array length + Q_ASSERT( _lines > 0 && _columns > 0 ); + Q_ASSERT( _usedLines <= _lines && _usedColumns <= _columns ); - _imageSize=_lines*_columns; - - // We over-commit one character so that we can be more relaxed in dealing with - // certain boundary conditions: _image[_imageSize] is a valid but unused position - _image = new Character[_imageSize+1]; + _imageSize=_lines*_columns; - clearImage(); + // We over-commit one character so that we can be more relaxed in dealing with + // certain boundary conditions: _image[_imageSize] is a valid but unused position + _image = new Character[_imageSize+1]; + + clearImage(); } // calculate the needed size void TerminalDisplay::setSize(int columns, int lines) { - //FIXME - Not quite correct, a small amount of additional space - // will be used for margins, the scrollbar etc. - // we need to allow for this so that '_size' does allow - // enough room for the specified number of columns and lines to fit + //FIXME - Not quite correct, a small amount of additional space + // will be used for margins, the scrollbar etc. + // we need to allow for this so that '_size' does allow + // enough room for the specified number of columns and lines to fit - QSize newSize = QSize( columns * _fontWidth , - lines * _fontHeight ); + QSize newSize = QSize( columns * _fontWidth , + lines * _fontHeight ); - if ( newSize != size() ) - { - _size = newSize; - updateGeometry(); - } + if ( newSize != size() ) { + _size = newSize; + updateGeometry(); + } } void TerminalDisplay::setFixedSize(int cols, int lins) { - _isFixedSize = true; - - //ensure that display is at least one line by one column in size - _columns = qMax(1,cols); - _lines = qMax(1,lins); - _usedColumns = qMin(_usedColumns,_columns); - _usedLines = qMin(_usedLines,_lines); + _isFixedSize = true; - if (_image) - { - delete[] _image; - makeImage(); - } - setSize(cols, lins); - QWidget::setFixedSize(_size); + //ensure that display is at least one line by one column in size + _columns = qMax(1,cols); + _lines = qMax(1,lins); + _usedColumns = qMin(_usedColumns,_columns); + _usedLines = qMin(_usedLines,_lines); + + if (_image) { + delete[] _image; + makeImage(); + } + setSize(cols, lins); + QWidget::setFixedSize(_size); } QSize TerminalDisplay::sizeHint() const { - return _size; + return _size; } @@ -2626,112 +2515,110 @@ QSize TerminalDisplay::sizeHint() const void TerminalDisplay::dragEnterEvent(QDragEnterEvent* event) { - if (event->mimeData()->hasFormat("text/plain")) - event->acceptProposedAction(); + if (event->mimeData()->hasFormat("text/plain")) + event->acceptProposedAction(); } void TerminalDisplay::dropEvent(QDropEvent* event) { // KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); - QString dropText; -/* if (!urls.isEmpty()) - { - for ( int i = 0 ; i < urls.count() ; i++ ) - { - KUrl url = KIO::NetAccess::mostLocalUrl( urls[i] , 0 ); - QString urlText; + QString dropText; + /* if (!urls.isEmpty()) + { + for ( int i = 0 ; i < urls.count() ; i++ ) + { + KUrl url = KIO::NetAccess::mostLocalUrl( urls[i] , 0 ); + QString urlText; - if (url.isLocalFile()) - urlText = url.path(); - else - urlText = url.url(); - - // in future it may be useful to be able to insert file names with drag-and-drop - // without quoting them (this only affects paths with spaces in) - urlText = KShell::quoteArg(urlText); - - dropText += urlText; + if (url.isLocalFile()) + urlText = url.path(); + else + urlText = url.url(); - if ( i != urls.count()-1 ) - dropText += ' '; + // in future it may be useful to be able to insert file names with drag-and-drop + // without quoting them (this only affects paths with spaces in) + urlText = KShell::quoteArg(urlText); + + dropText += urlText; + + if ( i != urls.count()-1 ) + dropText += ' '; + } + } + else + { + dropText = event->mimeData()->text(); + } + */ + if (event->mimeData()->hasFormat("text/plain")) { + emit sendStringToEmu(dropText.toLocal8Bit()); } - } - else - { - dropText = event->mimeData()->text(); - } -*/ - if(event->mimeData()->hasFormat("text/plain")) - { - emit sendStringToEmu(dropText.toLocal8Bit()); - } } void TerminalDisplay::doDrag() { - dragInfo.state = diDragging; - dragInfo.dragObject = new QDrag(this); - QMimeData *mimeData = new QMimeData; - mimeData->setText(QApplication::clipboard()->text(QClipboard::Selection)); - dragInfo.dragObject->setMimeData(mimeData); - dragInfo.dragObject->start(Qt::CopyAction); - // Don't delete the QTextDrag object. Qt will delete it when it's done with it. + dragInfo.state = diDragging; + dragInfo.dragObject = new QDrag(this); + QMimeData *mimeData = new QMimeData; + mimeData->setText(QApplication::clipboard()->text(QClipboard::Selection)); + dragInfo.dragObject->setMimeData(mimeData); + dragInfo.dragObject->start(Qt::CopyAction); + // Don't delete the QTextDrag object. Qt will delete it when it's done with it. } void TerminalDisplay::outputSuspended(bool suspended) { - //create the label when this function is first called - if (!_outputSuspendedLabel) - { - //This label includes a link to an English language website - //describing the 'flow control' (Xon/Xoff) feature found in almost - //all terminal emulators. - //If there isn't a suitable article available in the target language the link - //can simply be removed. - _outputSuspendedLabel = new QLabel( ("Output has been " - "suspended" - " by pressing Ctrl+S." - " Press Ctrl+Q to resume."), - this ); + //create the label when this function is first called + if (!_outputSuspendedLabel) { + //This label includes a link to an English language website + //describing the 'flow control' (Xon/Xoff) feature found in almost + //all terminal emulators. + //If there isn't a suitable article available in the target language the link + //can simply be removed. + _outputSuspendedLabel = new QLabel( ("Output has been " + "suspended" + " by pressing Ctrl+S." + " Press Ctrl+Q to resume."), + this ); - QPalette palette(_outputSuspendedLabel->palette()); - - palette.setColor(QPalette::Normal, QPalette::WindowText, QColor(Qt::white)); - palette.setColor(QPalette::Normal, QPalette::Window, QColor(Qt::black)); + QPalette palette(_outputSuspendedLabel->palette()); + + palette.setColor(QPalette::Normal, QPalette::WindowText, QColor(Qt::white)); + palette.setColor(QPalette::Normal, QPalette::Window, QColor(Qt::black)); // KColorScheme::adjustForeground(palette,KColorScheme::NeutralText); // KColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground); - _outputSuspendedLabel->setPalette(palette); - _outputSuspendedLabel->setAutoFillBackground(true); - _outputSuspendedLabel->setBackgroundRole(QPalette::Base); - _outputSuspendedLabel->setFont(QApplication::font()); - _outputSuspendedLabel->setMargin(5); + _outputSuspendedLabel->setPalette(palette); + _outputSuspendedLabel->setAutoFillBackground(true); + _outputSuspendedLabel->setBackgroundRole(QPalette::Base); + _outputSuspendedLabel->setFont(QApplication::font()); + _outputSuspendedLabel->setMargin(5); - //enable activation of "Xon/Xoff" link in label - _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse | - Qt::LinksAccessibleByKeyboard); - _outputSuspendedLabel->setOpenExternalLinks(true); - _outputSuspendedLabel->setVisible(false); + //enable activation of "Xon/Xoff" link in label + _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse | + Qt::LinksAccessibleByKeyboard); + _outputSuspendedLabel->setOpenExternalLinks(true); + _outputSuspendedLabel->setVisible(false); - _gridLayout->addWidget(_outputSuspendedLabel); - _gridLayout->addItem( new QSpacerItem(0,0,QSizePolicy::Expanding, - QSizePolicy::Expanding), - 1,0); + _gridLayout->addWidget(_outputSuspendedLabel); + _gridLayout->addItem( new QSpacerItem(0,0,QSizePolicy::Expanding, + QSizePolicy::Expanding), + 1,0); } - _outputSuspendedLabel->setVisible(suspended); + _outputSuspendedLabel->setVisible(suspended); } uint TerminalDisplay::lineSpacing() const { - return _lineSpacing; + return _lineSpacing; } void TerminalDisplay::setLineSpacing(uint i) { - _lineSpacing = i; - setVTFont(font()); // Trigger an update. + _lineSpacing = i; + setVTFont(font()); // Trigger an update. } //#include "moc_TerminalDisplay.cpp" diff --git a/lib/TerminalDisplay.h b/lib/TerminalDisplay.h index 6b3c6d8..a92532f 100644 --- a/lib/TerminalDisplay.h +++ b/lib/TerminalDisplay.h @@ -60,14 +60,14 @@ class ScreenWindow; * A widget which displays output from a terminal emulation and sends input keypresses and mouse activity * to the terminal. * - * When the terminal emulation receives new output from the program running in the terminal, + * When the terminal emulation receives new output from the program running in the terminal, * it will update the display by calling updateImage(). * * TODO More documentation */ class TerminalDisplay : public QWidget { - Q_OBJECT + Q_OBJECT public: /** Constructs a new terminal display widget with the specified parent. */ @@ -92,25 +92,24 @@ public: /** Sets the opacity of the terminal display. */ void setOpacity(qreal opacity); - /** + /** * This enum describes the location where the scroll bar is positioned in the display widget. */ - enum ScrollBarPosition - { + enum ScrollBarPosition { /** Do not show the scroll bar. */ - NoScrollBar=0, + NoScrollBar=0, /** Show the scroll bar on the left side of the display. */ - ScrollBarLeft=1, + ScrollBarLeft=1, /** Show the scroll bar on the right side of the display. */ - ScrollBarRight=2 + ScrollBarRight=2 }; - /** + /** * Specifies whether the terminal display has a vertical scroll bar, and if so whether it * is shown on the left or right side of the display. */ void setScrollBarPosition(ScrollBarPosition position); - /** + /** * Sets the current position and range of the display's scroll bar. * * @param cursor The position of the scroll bar's thumb. @@ -118,7 +117,7 @@ public: */ void setScroll(int cursor, int lines); - /** + /** * Returns the display's filter chain. When the image for the display is updated, * the text is passed through each filter in the chain. Each filter can define * hotspots which correspond to certain strings (such as URLs or particular words). @@ -131,11 +130,11 @@ public: */ FilterChain* filterChain() const; - /** + /** * Updates the filters in the display's filter chain. This will cause * the hotspots to be updated to match the current image. * - * WARNING: This function can be expensive depending on the + * WARNING: This function can be expensive depending on the * image size and number of filters in the filterChain() * * TODO - This API does not really allow efficient usage. Revise it so @@ -144,38 +143,47 @@ public: * eg: * - Area of interest may be known ( eg. mouse cursor hovering * over an area ) - */ + */ void processFilters(); - /** + /** * Returns a list of menu actions created by the filters for the content * at the given @p position. */ QList filterActions(const QPoint& position); /** Returns true if the cursor is set to blink or false otherwise. */ - bool blinkingCursor() { return _hasBlinkingCursor; } + bool blinkingCursor() { + return _hasBlinkingCursor; + } /** Specifies whether or not the cursor blinks. */ void setBlinkingCursor(bool blink); - void setCtrlDrag(bool enable) { _ctrlDrag=enable; } - bool ctrlDrag() { return _ctrlDrag; } + void setCtrlDrag(bool enable) { + _ctrlDrag=enable; + } + bool ctrlDrag() { + return _ctrlDrag; + } - /** + /** * This enum describes the methods for selecting text when - * the user triple-clicks within the display. - */ - enum TripleClickMode - { - /** Select the whole line underneath the cursor. */ - SelectWholeLine, - /** Select from the current cursor position to the end of the line. */ - SelectForwardsFromCursor - }; - /** Sets how the text is selected when the user triple clicks within the display. */ - void setTripleClickMode(TripleClickMode mode) { _tripleClickMode = mode; } - /** See setTripleClickSelectionMode() */ - TripleClickMode tripleClickMode() { return _tripleClickMode; } + * the user triple-clicks within the display. + */ + enum TripleClickMode { + /** Select the whole line underneath the cursor. */ + SelectWholeLine, + /** Select from the current cursor position to the end of the line. */ + SelectForwardsFromCursor + }; + /** Sets how the text is selected when the user triple clicks within the display. */ + void setTripleClickMode(TripleClickMode mode) { + _tripleClickMode = mode; + } + /** See setTripleClickSelectionMode() */ + TripleClickMode tripleClickMode() { + return _tripleClickMode; + } void setLineSpacing(uint); uint lineSpacing() const; @@ -186,26 +194,25 @@ public: * This enum describes the available shapes for the keyboard cursor. * See setKeyboardCursorShape() */ - enum KeyboardCursorShape - { + enum KeyboardCursorShape { /** A rectangular block which covers the entire area of the cursor character. */ BlockCursor, - /** + /** * A single flat line which occupies the space at the bottom of the cursor * character's area. */ UnderlineCursor, - /** - * An cursor shaped like the capital letter 'I', similar to the IBeam + /** + * An cursor shaped like the capital letter 'I', similar to the IBeam * cursor used in Qt/KDE text editors. */ IBeamCursor }; - /** - * Sets the shape of the keyboard cursor. This is the cursor drawn + /** + * Sets the shape of the keyboard cursor. This is the cursor drawn * at the position in the terminal where keyboard input will appear. * - * In addition the terminal display widget also has a cursor for + * In addition the terminal display widget also has a cursor for * the mouse pointer, which can be set using the QWidget::setCursor() * method. * @@ -218,7 +225,7 @@ public: KeyboardCursorShape keyboardCursorShape() const; /** - * Sets the color used to draw the keyboard cursor. + * Sets the color used to draw the keyboard cursor. * * The keyboard cursor defaults to using the foreground color of the character * underneath it. @@ -232,10 +239,10 @@ public: */ void setKeyboardCursorColor(bool useForegroundColor , const QColor& color); - /** + /** * Returns the color of the keyboard cursor, or an invalid color if the keyboard * cursor color is set to change according to the foreground color of the character - * underneath it. + * underneath it. */ QColor keyboardCursorColor() const; @@ -245,7 +252,9 @@ public: * This will depend upon the height of the widget and the current font. * See fontHeight() */ - int lines() { return _lines; } + int lines() { + return _lines; + } /** * Returns the number of characters of text which can be displayed on * each line in the widget. @@ -253,26 +262,32 @@ public: * This will depend upon the width of the widget and the current font. * See fontWidth() */ - int columns() { return _columns; } + int columns() { + return _columns; + } /** * Returns the height of the characters in the font used to draw the text in the display. */ - int fontHeight() { return _fontHeight; } + int fontHeight() { + return _fontHeight; + } /** - * Returns the width of the characters in the display. + * Returns the width of the characters in the display. * This assumes the use of a fixed-width font. */ - int fontWidth() { return _fontWidth; } + int fontWidth() { + return _fontWidth; + } void setSize(int cols, int lins); void setFixedSize(int cols, int lins); - + // reimplemented QSize sizeHint() const; /** - * Sets which characters, in addition to letters and numbers, + * Sets which characters, in addition to letters and numbers, * are regarded as being part of a word for the purposes * of selecting words in the display by double clicking on them. * @@ -283,64 +298,69 @@ public: * of a word ( in addition to letters and numbers ). */ void setWordCharacters(const QString& wc); - /** - * Returns the characters which are considered part of a word for the + /** + * Returns the characters which are considered part of a word for the * purpose of selecting words in the display with the mouse. * * @see setWordCharacters() */ - QString wordCharacters() { return _wordCharacters; } + QString wordCharacters() { + return _wordCharacters; + } - /** - * Sets the type of effect used to alert the user when a 'bell' occurs in the + /** + * Sets the type of effect used to alert the user when a 'bell' occurs in the * terminal session. * * The terminal session can trigger the bell effect by calling bell() with * the alert message. */ void setBellMode(int mode); - /** + /** * Returns the type of effect used to alert the user when a 'bell' occurs in * the terminal session. - * + * * See setBellMode() */ - int bellMode() { return _bellMode; } + int bellMode() { + return _bellMode; + } /** * This enum describes the different types of sounds and visual effects which * can be used to alert the user when a 'bell' occurs in the terminal * session. */ - enum BellMode - { + enum BellMode { /** A system beep. */ - SystemBeepBell=0, - /** + SystemBeepBell=0, + /** * KDE notification. This may play a sound, show a passive popup * or perform some other action depending on the user's settings. */ - NotifyBell=1, + NotifyBell=1, /** A silent, visual bell (eg. inverting the display's colors briefly) */ - VisualBell=2, + VisualBell=2, /** No bell effects */ - NoBell=3 + NoBell=3 }; 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(); } + 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. + * is larger than the size of the display itself. */ void setVTFont(const QFont& font); @@ -348,34 +368,48 @@ public: * Specified whether anti-aliasing of text in the terminal display * is enabled or not. Defaults to enabled. */ - static void setAntialias( bool antialias ) { _antialiasText = antialias; } - /** + static void setAntialias( bool antialias ) { + _antialiasText = antialias; + } + /** * Returns true if anti-aliasing of text in the terminal is enabled. */ - static bool antialias() { return _antialiasText; } - + static bool antialias() { + return _antialiasText; + } + /** - * Sets whether or not the current height and width of the + * Sets whether or not the current height and width of the * terminal in lines and columns is displayed whilst the widget * is being resized. */ - void setTerminalSizeHint(bool on) { _terminalSizeHint=on; } - /** + void setTerminalSizeHint(bool on) { + _terminalSizeHint=on; + } + /** * Returns whether or not the current height and width of * the terminal in lines and columns is displayed whilst the widget * is being resized. */ - bool terminalSizeHint() { return _terminalSizeHint; } - /** + bool terminalSizeHint() { + return _terminalSizeHint; + } + /** * Sets whether the terminal size display is shown briefly * after the widget is first shown. * * See setTerminalSizeHint() , isTerminalSizeHint() */ - void setTerminalSizeStartup(bool on) { _terminalSizeStartup=on; } + void setTerminalSizeStartup(bool on) { + _terminalSizeStartup=on; + } - void setBidiEnabled(bool set) { _bidiEnabled=set; } - bool isBidiEnabled() { return _bidiEnabled; } + void setBidiEnabled(bool set) { + _bidiEnabled=set; + } + bool isBidiEnabled() { + return _bidiEnabled; + } /** * Sets the terminal screen section which is displayed in this widget. @@ -393,21 +427,21 @@ public: public slots: - /** + /** * Causes the terminal display to fetch the latest character image from the associated * terminal screen ( see setScreenWindow() ) and redraw the display. */ - void updateImage(); + void updateImage(); /** - * Causes the terminal display to fetch the latest line status flags from the - * associated terminal screen ( see setScreenWindow() ). - */ + * Causes the terminal display to fetch the latest line status flags from the + * associated terminal screen ( see setScreenWindow() ). + */ void updateLineProperties(); /** Copies the selected text to the clipboard. */ void copyClipboard(); - /** - * Pastes the content of the clipboard into the + /** + * Pastes the content of the clipboard into the * display. */ void pasteClipboard(); @@ -417,21 +451,21 @@ public slots: */ void pasteSelection(); - /** - * Changes whether the flow control warning box should be shown when the flow control - * stop key (Ctrl+S) are pressed. - */ - void setFlowControlWarningEnabled(bool enabled); - - /** - * Causes the widget to display or hide a message informing the user that terminal - * output has been suspended (by using the flow control key combination Ctrl+S) - * - * @param suspended True if terminal output has been suspended and the warning message should - * be shown or false to indicate that terminal output has been resumed and that - * the warning message should disappear. - */ - void outputSuspended(bool suspended); + /** + * Changes whether the flow control warning box should be shown when the flow control + * stop key (Ctrl+S) are pressed. + */ + void setFlowControlWarningEnabled(bool enabled); + + /** + * Causes the widget to display or hide a message informing the user that terminal + * output has been suspended (by using the flow control key combination Ctrl+S) + * + * @param suspended True if terminal output has been suspended and the warning message should + * be shown or false to indicate that terminal output has been resumed and that + * the warning message should disappear. + */ + void outputSuspended(bool suspended); /** * Sets whether the program whoose output is being displayed in the view @@ -440,7 +474,7 @@ public slots: * If this is set to true, mouse signals will be emitted by the view when the user clicks, drags * or otherwise moves the mouse inside the view. * The user interaction needed to create selections will also change, and the user will be required - * to hold down the shift key to create a selection or perform other mouse activities inside the + * to hold down the shift key to create a selection or perform other mouse activities inside the * view area - since the program running in the terminal is being allowed to handle normal mouse * events itself. * @@ -448,11 +482,11 @@ public slots: * or false otherwise. */ void setUsesMouse(bool usesMouse); - + /** See setUsesMouse() */ bool usesMouse() const; - /** + /** * Shows a notification that a bell event has occurred in the terminal. * TODO: More documentation here */ @@ -466,14 +500,14 @@ signals: void keyPressedSignal(QKeyEvent *e); /** - * Emitted when the user presses the suspend or resume flow control key combinations - * + * Emitted when the user presses the suspend or resume flow control key combinations + * * @param suspend true if the user pressed Ctrl+S (the suspend output key combination) or * false if the user pressed Ctrl+Q (the resume output key combination) */ void flowControlKeyPressed(bool suspend); - - /** + + /** * A mouse event occurred. * @param button The mouse button (0 for left button, 1 for middle button, 2 for right button, 3 for release) * @param column The character column where the event occurred @@ -484,7 +518,7 @@ signals: void changedFontMetricSignal(int height, int width); void changedContentSizeSignal(int height, int width); - /** + /** * Emitted when the user right clicks on the display, or right-clicks with the Shift * key held down if usesMouse() is true. * @@ -492,8 +526,8 @@ signals: */ void configureRequest( TerminalDisplay*, int state, const QPoint& position ); - void isBusySelecting(bool); - void sendStringToEmu(const char*); + void isBusySelecting(bool); + void sendStringToEmu(const char*); protected: virtual bool event( QEvent * ); @@ -515,7 +549,7 @@ protected: virtual void wheelEvent( QWheelEvent* ); virtual bool focusNextPrevChild( bool next ); - + // drag and drop virtual void dragEnterEvent(QDragEnterEvent* event); virtual void dropEvent(QDropEvent* event); @@ -523,9 +557,9 @@ protected: enum DragState { diNone, diPending, diDragging }; struct _dragInfo { - DragState state; - QPoint start; - QDrag *dragObject; + DragState state; + QPoint start; + QDrag *dragObject; } dragInfo; virtual int charClass(quint16) const; @@ -543,7 +577,7 @@ protected slots: void scrollBarPositionChanged(int value); void blinkEvent(); void blinkCursorEvent(); - + //Renables bell noises and visuals. Used to disable further bells for a short period of time //after emitting the first in a sequence of bell events. void enableBell(); @@ -559,26 +593,26 @@ private: // divides the part of the display specified by 'rect' into // fragments according to their colors and styles and calls - // drawTextFragment() to draw the fragments + // drawTextFragment() to draw the fragments void drawContents(QPainter &paint, const QRect &rect); // draws a section of text, all the text in this section // has a common color and style - void drawTextFragment(QPainter& painter, const QRect& rect, - const QString& text, const Character* style); + void drawTextFragment(QPainter& painter, const QRect& rect, + const QString& text, const Character* style); // draws the background for a text fragment // if useOpacitySetting is true then the color's alpha value will be set to // the display's transparency (set with setOpacity()), otherwise the background // will be drawn fully opaque void drawBackground(QPainter& painter, const QRect& rect, const QColor& color, - bool useOpacitySetting); + bool useOpacitySetting); // draws the cursor character - void drawCursor(QPainter& painter, const QRect& rect , const QColor& foregroundColor, - const QColor& backgroundColor , bool& invertColors); + void drawCursor(QPainter& painter, const QRect& rect , const QColor& foregroundColor, + const QColor& backgroundColor , bool& invertColors); // draws the characters or line graphics in a text fragment - void drawCharacters(QPainter& painter, const QRect& rect, const QString& text, - const Character* style, bool invertCharacterColor); + void drawCharacters(QPainter& painter, const QRect& rect, const QString& text, + const Character* style, bool invertCharacterColor); // draws a string of line graphics - void drawLineCharString(QPainter& painter, int x, int y, + void drawLineCharString(QPainter& painter, int x, int y, const QString& str, const Character* attributes); // draws the preedit string for input methods @@ -586,10 +620,10 @@ private: // -- - // maps an area in the character image to an area on the widget + // maps an area in the character image to an area on the widget QRect imageToWidget(const QRect& imageArea) const; - // maps a point on the widget to the position ( ie. line and column ) + // maps a point on the widget to the position ( ie. line and column ) // of the character at that point. void getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const; @@ -600,8 +634,8 @@ private: // current size in columns and lines void showResizeNotification(); - // scrolls the image by a number of lines. - // 'lines' may be positive ( to scroll the image down ) + // scrolls the image by a number of lines. + // 'lines' may be positive ( to scroll the image down ) // or negative ( to scroll the image up ) // 'region' is the part of the image to scroll - currently only // the top, bottom and height of 'region' are taken into account, @@ -612,18 +646,18 @@ private: void propagateSize(); void updateImageSize(); void makeImage(); - + void paintFilters(QPainter& painter); - // returns a region covering all of the areas of the widget which contain - // a hotspot - QRegion hotSpotRegion() const; + // returns a region covering all of the areas of the widget which contain + // a hotspot + QRegion hotSpotRegion() const; - // returns the position of the cursor in columns and lines - QPoint cursorPosition() const; + // returns the position of the cursor in columns and lines + QPoint cursorPosition() const; // the window onto the terminal screen which this display - // is currently showing. + // is currently showing. QPointer _screenWindow; bool _allowBell; @@ -640,19 +674,19 @@ private: int _lines; // the number of lines that can be displayed in the widget int _columns; // the number of columns that can be displayed in the widget - + int _usedLines; // the number of lines that are actually being used, this will be less - // than 'lines' if the character image provided with setImage() is smaller - // than the maximum image size which can be displayed + // than 'lines' if the character image provided with setImage() is smaller + // than the maximum image size which can be displayed int _usedColumns; // the number of columns that are actually being used, this will be less - // than 'columns' if the character image provided with setImage() is smaller - // than the maximum image size which can be displayed - + // than 'columns' if the character image provided with setImage() is smaller + // than the maximum image size which can be displayed + int _contentHeight; int _contentWidth; Character* _image; // [lines][columns] - // only the area [usedLines][usedColumns] in the image contains valid data + // only the area [usedLines][usedColumns] in the image contains valid data int _imageSize; QVector _lineProperties; @@ -696,24 +730,24 @@ private: int _dndFileCount; bool _possibleTripleClick; // is set in mouseDoubleClickEvent and deleted - // after QApplication::doubleClickInterval() delay + // after QApplication::doubleClickInterval() delay QLabel* _resizeWidget; QTimer* _resizeTimer; - bool _flowControlWarningEnabled; + bool _flowControlWarningEnabled; //widgets related to the warning message that appears when the user presses Ctrl+S to suspend //terminal output - informing them what has happened and how to resume output - QLabel* _outputSuspendedLabel; - + QLabel* _outputSuspendedLabel; + uint _lineSpacing; bool _colorsInverted; // true during visual bell QSize _size; - + QRgb _blendColor; // list of filters currently applied to the display. used for links and @@ -725,11 +759,10 @@ private: // custom cursor color. if this is invalid then the foreground // color of the character under the cursor is used - QColor _cursorColor; + QColor _cursorColor; - struct InputMethodData - { + struct InputMethodData { QString preeditString; QRect previousPreeditRect; }; @@ -739,12 +772,11 @@ private: //the delay in milliseconds between redrawing blinking text static const int BLINK_DELAY = 500; - static const int DEFAULT_LEFT_MARGIN = 1; - static const int DEFAULT_TOP_MARGIN = 1; + static const int DEFAULT_LEFT_MARGIN = 1; + static const int DEFAULT_TOP_MARGIN = 1; public: - static void setTransparencyEnabled(bool enable) - { + static void setTransparencyEnabled(bool enable) { HAVE_TRANSPARENCY = enable; } }; diff --git a/lib/Vt102Emulation.cpp b/lib/Vt102Emulation.cpp index 5c7bb12..9fbebdc 100644 --- a/lib/Vt102Emulation.cpp +++ b/lib/Vt102Emulation.cpp @@ -36,7 +36,7 @@ #undef HAVE_XKB #endif -// Standard +// Standard #include #include #include @@ -85,16 +85,16 @@ using namespace Konsole; /* ------------------------------------------------------------------------- */ -Vt102Emulation::Vt102Emulation() - : Emulation(), - _titleUpdateTimer(new QTimer(this)) +Vt102Emulation::Vt102Emulation() + : Emulation(), + _titleUpdateTimer(new QTimer(this)) { - _titleUpdateTimer->setSingleShot(true); + _titleUpdateTimer->setSingleShot(true); - QObject::connect(_titleUpdateTimer , SIGNAL(timeout()) , this , SLOT(updateTitle())); + QObject::connect(_titleUpdateTimer , SIGNAL(timeout()) , this , SLOT(updateTitle())); - initTokenizer(); - reset(); + initTokenizer(); + reset(); } Vt102Emulation::~Vt102Emulation() @@ -103,30 +103,30 @@ Vt102Emulation::~Vt102Emulation() void Vt102Emulation::clearEntireScreen() { - _currentScreen->clearEntireScreen(); + _currentScreen->clearEntireScreen(); - bufferedUpdate(); + bufferedUpdate(); } void Vt102Emulation::reset() { - //kDebug(1211)<<"Vt102Emulation::reset() resetToken()"; - resetToken(); - //kDebug(1211)<<"Vt102Emulation::reset() resetModes()"; - resetModes(); - //kDebug(1211)<<"Vt102Emulation::reset() resetCharSet()"; - resetCharset(0); - //kDebug(1211)<<"Vt102Emulation::reset() reset screen0()"; - _screen[0]->reset(); - //kDebug(1211)<<"Vt102Emulation::reset() resetCharSet()"; - resetCharset(1); - //kDebug(1211)<<"Vt102Emulation::reset() reset _screen 1"; - _screen[1]->reset(); - //kDebug(1211)<<"Vt102Emulation::reset() setCodec()"; - setCodec(LocaleCodec); - //kDebug(1211)<<"Vt102Emulation::reset() done"; - - bufferedUpdate(); + //kDebug(1211)<<"Vt102Emulation::reset() resetToken()"; + resetToken(); + //kDebug(1211)<<"Vt102Emulation::reset() resetModes()"; + resetModes(); + //kDebug(1211)<<"Vt102Emulation::reset() resetCharSet()"; + resetCharset(0); + //kDebug(1211)<<"Vt102Emulation::reset() reset screen0()"; + _screen[0]->reset(); + //kDebug(1211)<<"Vt102Emulation::reset() resetCharSet()"; + resetCharset(1); + //kDebug(1211)<<"Vt102Emulation::reset() reset _screen 1"; + _screen[1]->reset(); + //kDebug(1211)<<"Vt102Emulation::reset() setCodec()"; + setCodec(LocaleCodec); + //kDebug(1211)<<"Vt102Emulation::reset() done"; + + bufferedUpdate(); } /* ------------------------------------------------------------------------- */ @@ -215,24 +215,27 @@ void Vt102Emulation::reset() void Vt102Emulation::resetToken() { - ppos = 0; argc = 0; argv[0] = 0; argv[1] = 0; + ppos = 0; + argc = 0; + argv[0] = 0; + argv[1] = 0; } void Vt102Emulation::addDigit(int dig) { - argv[argc] = 10*argv[argc] + dig; + argv[argc] = 10*argv[argc] + dig; } void Vt102Emulation::addArgument() { - argc = qMin(argc+1,MAXARGS-1); - argv[argc] = 0; + argc = qMin(argc+1,MAXARGS-1); + argv[argc] = 0; } void Vt102Emulation::pushToToken(int cc) { - pbuf[ppos] = cc; - ppos = qMin(ppos+1,MAXPBUF-1); + pbuf[ppos] = cc; + ppos = qMin(ppos+1,MAXPBUF-1); } // Character Classes used while decoding @@ -246,17 +249,19 @@ void Vt102Emulation::pushToToken(int cc) #define CPS 64 void Vt102Emulation::initTokenizer() -{ int i; quint8* 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 = (quint8*)"@ABCDGHILMPSTXZcdfry"; *s; s++) tbl[*s] |= CPN; +{ + int i; + quint8* 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 = (quint8*)"@ABCDGHILMPSTXZcdfry"; *s; s++) tbl[*s] |= CPN; // resize = \e[8;;t - for(s = (quint8*)"t"; *s; s++) tbl[*s] |= CPS; - for(s = (quint8*)"0123456789" ; *s; s++) tbl[*s] |= DIG; - for(s = (quint8*)"()+*%" ; *s; s++) tbl[*s] |= SCS; - for(s = (quint8*)"()+*#[]%" ; *s; s++) tbl[*s] |= GRP; - resetToken(); + for (s = (quint8*)"t"; *s; s++) tbl[*s] |= CPS; + for (s = (quint8*)"0123456789" ; *s; s++) tbl[*s] |= DIG; + for (s = (quint8*)"()+*%" ; *s; s++) tbl[*s] |= SCS; + for (s = (quint8*)"()+*#[]%" ; *s; s++) tbl[*s] |= GRP; + resetToken(); } /* Ok, here comes the nasty part of the decoder. @@ -293,101 +298,168 @@ void Vt102Emulation::initTokenizer() // process an incoming unicode character void Vt102Emulation::receiveChar(int cc) -{ - int i; - if (cc == 127) return; //VT100: ignore. +{ + 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; } - } + 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 + pushToToken(cc); // advance the state - int* s = pbuf; - int p = ppos; + 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; receiveChar('['); 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; } + if (getMode(MODE_Ansi)) { // decide on proper action + if (lec(1,0,ESC)) { + return; + } + if (lec(1,0,ESC+128)) { + s[0] = ESC; + receiveChar('['); + 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;;t - if (eps( CPS)) { tau( TY_CSI_PS(cc, argv[0]), argv[1], argv[2]); resetToken(); return; } + 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;;; ... m -or- ESC[ ... 38;2;;; ... m - i += 2; - tau( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_RGB, (argv[i] << 16) | (argv[i+1] << 8) | argv[i+2]); - i += 2; + 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;;; ... m -or- ESC[ ... 38;2;;; ... m + i += 2; + tau( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_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; ... m -or- ESC[ ... 38;5; ... m + i += 2; + tau( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_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; } - else if (cc == 'm' && argc - i >= 2 && (argv[i] == 38 || argv[i] == 48) && argv[i+1] == 5) - { // ESC[ ... 48;5; ... m -or- ESC[ ... 38;5; ... m - i += 2; - tau( TY_CSI_PS(cc, argv[i-2]), COLOR_SPACE_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 Vt102Emulation::XtermHack() -{ int i,arg = 0; - for (i = 2; i < ppos && '0'<=pbuf[i] && pbuf[i]<'9' ; i++) - arg = 10*arg + (pbuf[i]-'0'); - if (pbuf[i] != ';') { ReportErrorToken(); return; } - QChar *str = new QChar[ppos-i-2]; - for (int j = 0; j < ppos-i-2; j++) str[j] = pbuf[i+1+j]; - QString unistr(str,ppos-i-2); - - // arg == 1 doesn't change the title. In XTerm it only changes the icon name - // (btw: arg=0 changes title and icon, arg=1 only icon, arg=2 only title -// emit changeTitle(arg,unistr); - _pendingTitleUpdates[arg] = unistr; - _titleUpdateTimer->start(20); +{ + 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); - delete [] str; + // 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); + _pendingTitleUpdates[arg] = unistr; + _titleUpdateTimer->start(20); + + delete [] str; } void Vt102Emulation::updateTitle() { - QListIterator iter( _pendingTitleUpdates.keys() ); - while (iter.hasNext()) { - int arg = iter.next(); - emit titleChanged( arg , _pendingTitleUpdates[arg] ); - } + QListIterator iter( _pendingTitleUpdates.keys() ); + while (iter.hasNext()) { + int arg = iter.next(); + emit titleChanged( arg , _pendingTitleUpdates[arg] ); + } - _pendingTitleUpdates.clear(); + _pendingTitleUpdates.clear(); } // Interpreting Codes --------------------------------------------------------- @@ -411,387 +483,835 @@ void Vt102Emulation::updateTitle() void Vt102Emulation::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; -} + 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) - { + switch (token) { - case TY_CHR( ) : _currentScreen->ShowCharacter (p ); break; //UTF16 + case TY_CHR( ) : + _currentScreen->ShowCharacter (p ); + break; //UTF16 - // 127 DEL : ignored on input + // 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 stateSet(NOTIFYBELL); - break; //VT100 - case TY_CTL('H' ) : _currentScreen->BackSpace ( ); break; //VT100 - case TY_CTL('I' ) : _currentScreen->Tabulate ( ); break; //VT100 - case TY_CTL('J' ) : _currentScreen->NewLine ( ); break; //VT100 - case TY_CTL('K' ) : _currentScreen->NewLine ( ); break; //VT100 - case TY_CTL('L' ) : _currentScreen->NewLine ( ); break; //VT100 - case TY_CTL('M' ) : _currentScreen->Return ( ); break; //VT100 + 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 stateSet(NOTIFYBELL); + break; //VT100 + case TY_CTL('H' ) : + _currentScreen->BackSpace ( ); + break; //VT100 + case TY_CTL('I' ) : + _currentScreen->Tabulate ( ); + break; //VT100 + case TY_CTL('J' ) : + _currentScreen->NewLine ( ); + break; //VT100 + case TY_CTL('K' ) : + _currentScreen->NewLine ( ); + break; //VT100 + case TY_CTL('L' ) : + _currentScreen->NewLine ( ); + break; //VT100 + case TY_CTL('M' ) : + _currentScreen->Return ( ); + break; //VT100 - case TY_CTL('N' ) : useCharset ( 1); break; //VT100 - case TY_CTL('O' ) : useCharset ( 0); 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' ) : _currentScreen->ShowCharacter ( 0x2592); break; //VT100 - case TY_CTL('Y' ) : /* EM : ignored */ break; - case TY_CTL('Z' ) : _currentScreen->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_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' ) : + _currentScreen->ShowCharacter ( 0x2592); + break; //VT100 + case TY_CTL('Y' ) : /* EM : ignored */ + break; + case TY_CTL('Z' ) : + _currentScreen->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' ) : _currentScreen->index ( ); break; //VT100 - case TY_ESC('E' ) : _currentScreen->NextLine ( ); break; //VT100 - case TY_ESC('H' ) : _currentScreen->changeTabStop (true ); break; //VT100 - case TY_ESC('M' ) : _currentScreen->reverseIndex ( ); break; //VT100 - case TY_ESC('Z' ) : reportTerminalType ( ); break; - case TY_ESC('c' ) : reset ( ); break; + case TY_ESC('D' ) : + _currentScreen->index ( ); + break; //VT100 + case TY_ESC('E' ) : + _currentScreen->NextLine ( ); + break; //VT100 + case TY_ESC('H' ) : + _currentScreen->changeTabStop (true ); + break; //VT100 + case TY_ESC('M' ) : + _currentScreen->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('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('=' ) : + 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 (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 (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 (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('+', '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 (Utf8Codec ); break; //LINUX - case TY_ESC_CS('%', '@') : setCodec (LocaleCodec ); break; //LINUX + case TY_ESC_CS('%', 'G') : + setCodec (Utf8Codec ); + break; //LINUX + case TY_ESC_CS('%', '@') : + setCodec (LocaleCodec ); + break; //LINUX - case TY_ESC_DE('3' ) : /* Double height line, top half */ - _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true ); - _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true ); - break; - case TY_ESC_DE('4' ) : /* Double height line, bottom half */ - _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true ); - _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true ); - break; + case TY_ESC_DE('3' ) : /* Double height line, top half */ + _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true ); + _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true ); + break; + case TY_ESC_DE('4' ) : /* Double height line, bottom half */ + _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true ); + _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true ); + break; case TY_ESC_DE('5' ) : /* Single width, single height line*/ - _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , false); - _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false); - break; - case TY_ESC_DE('6' ) : /* Double width, single height line*/ - _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true); - _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false); - break; - case TY_ESC_DE('8' ) : _currentScreen->helpAlign ( ); break; + _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , false); + _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false); + break; + case TY_ESC_DE('6' ) : /* Double width, single height line*/ + _currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true); + _currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false); + break; + case TY_ESC_DE('8' ) : + _currentScreen->helpAlign ( ); + break; // resize = \e[8;;t - case TY_CSI_PS('t', 8) : setImageSize( q /* colums */, p /* lines */ ); break; + case TY_CSI_PS('t', 8) : + setImageSize( q /* colums */, p /* lines */ ); + break; // change tab text color : \e[28;t color: 0-16,777,215 - case TY_CSI_PS('t', 28) : emit changeTabTextColorRequest ( p ); break; + case TY_CSI_PS('t', 28) : + emit changeTabTextColorRequest ( p ); + break; - case TY_CSI_PS('K', 0) : _currentScreen->clearToEndOfLine ( ); break; - case TY_CSI_PS('K', 1) : _currentScreen->clearToBeginOfLine ( ); break; - case TY_CSI_PS('K', 2) : _currentScreen->clearEntireLine ( ); break; - case TY_CSI_PS('J', 0) : _currentScreen->clearToEndOfScreen ( ); break; - case TY_CSI_PS('J', 1) : _currentScreen->clearToBeginOfScreen ( ); break; - case TY_CSI_PS('J', 2) : _currentScreen->clearEntireScreen ( ); break; - case TY_CSI_PS('g', 0) : _currentScreen->changeTabStop (false ); break; //VT100 - case TY_CSI_PS('g', 3) : _currentScreen->clearTabStops ( ); break; //VT100 - case TY_CSI_PS('h', 4) : _currentScreen-> 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) : _currentScreen-> 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('K', 0) : + _currentScreen->clearToEndOfLine ( ); + break; + case TY_CSI_PS('K', 1) : + _currentScreen->clearToBeginOfLine ( ); + break; + case TY_CSI_PS('K', 2) : + _currentScreen->clearEntireLine ( ); + break; + case TY_CSI_PS('J', 0) : + _currentScreen->clearToEndOfScreen ( ); + break; + case TY_CSI_PS('J', 1) : + _currentScreen->clearToBeginOfScreen ( ); + break; + case TY_CSI_PS('J', 2) : + _currentScreen->clearEntireScreen ( ); + break; + case TY_CSI_PS('g', 0) : + _currentScreen->changeTabStop (false ); + break; //VT100 + case TY_CSI_PS('g', 3) : + _currentScreen->clearTabStops ( ); + break; //VT100 + case TY_CSI_PS('h', 4) : + _currentScreen-> 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) : + _currentScreen-> 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) : _currentScreen->setDefaultRendition ( ); break; - case TY_CSI_PS('m', 1) : _currentScreen-> setRendition (RE_BOLD ); break; //VT100 - case TY_CSI_PS('m', 4) : _currentScreen-> setRendition (RE_UNDERLINE); break; //VT100 - case TY_CSI_PS('m', 5) : _currentScreen-> setRendition (RE_BLINK ); break; //VT100 - case TY_CSI_PS('m', 7) : _currentScreen-> 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) : _currentScreen->resetRendition (RE_BOLD ); break; - case TY_CSI_PS('m', 24) : _currentScreen->resetRendition (RE_UNDERLINE); break; - case TY_CSI_PS('m', 25) : _currentScreen->resetRendition (RE_BLINK ); break; - case TY_CSI_PS('m', 27) : _currentScreen->resetRendition (RE_REVERSE ); break; + case TY_CSI_PS('m', 0) : + _currentScreen->setDefaultRendition ( ); + break; + case TY_CSI_PS('m', 1) : + _currentScreen-> setRendition (RE_BOLD ); + break; //VT100 + case TY_CSI_PS('m', 4) : + _currentScreen-> setRendition (RE_UNDERLINE); + break; //VT100 + case TY_CSI_PS('m', 5) : + _currentScreen-> setRendition (RE_BLINK ); + break; //VT100 + case TY_CSI_PS('m', 7) : + _currentScreen-> 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) : + _currentScreen->resetRendition (RE_BOLD ); + break; + case TY_CSI_PS('m', 24) : + _currentScreen->resetRendition (RE_UNDERLINE); + break; + case TY_CSI_PS('m', 25) : + _currentScreen->resetRendition (RE_BLINK ); + break; + case TY_CSI_PS('m', 27) : + _currentScreen->resetRendition (RE_REVERSE ); + break; - case TY_CSI_PS('m', 30) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 0); break; - case TY_CSI_PS('m', 31) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 1); break; - case TY_CSI_PS('m', 32) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 2); break; - case TY_CSI_PS('m', 33) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 3); break; - case TY_CSI_PS('m', 34) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 4); break; - case TY_CSI_PS('m', 35) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 5); break; - case TY_CSI_PS('m', 36) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 6); break; - case TY_CSI_PS('m', 37) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 7); break; + case TY_CSI_PS('m', 30) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 0); + break; + case TY_CSI_PS('m', 31) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 1); + break; + case TY_CSI_PS('m', 32) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 2); + break; + case TY_CSI_PS('m', 33) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 3); + break; + case TY_CSI_PS('m', 34) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 4); + break; + case TY_CSI_PS('m', 35) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 5); + break; + case TY_CSI_PS('m', 36) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 6); + break; + case TY_CSI_PS('m', 37) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 7); + break; - case TY_CSI_PS('m', 38) : _currentScreen->setForeColor (p, q); break; + case TY_CSI_PS('m', 38) : + _currentScreen->setForeColor (p, q); + break; - case TY_CSI_PS('m', 39) : _currentScreen->setForeColor (COLOR_SPACE_DEFAULT, 0); break; + case TY_CSI_PS('m', 39) : + _currentScreen->setForeColor (COLOR_SPACE_DEFAULT, 0); + break; - case TY_CSI_PS('m', 40) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 0); break; - case TY_CSI_PS('m', 41) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 1); break; - case TY_CSI_PS('m', 42) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 2); break; - case TY_CSI_PS('m', 43) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 3); break; - case TY_CSI_PS('m', 44) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 4); break; - case TY_CSI_PS('m', 45) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 5); break; - case TY_CSI_PS('m', 46) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 6); break; - case TY_CSI_PS('m', 47) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 7); break; + case TY_CSI_PS('m', 40) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 0); + break; + case TY_CSI_PS('m', 41) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 1); + break; + case TY_CSI_PS('m', 42) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 2); + break; + case TY_CSI_PS('m', 43) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 3); + break; + case TY_CSI_PS('m', 44) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 4); + break; + case TY_CSI_PS('m', 45) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 5); + break; + case TY_CSI_PS('m', 46) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 6); + break; + case TY_CSI_PS('m', 47) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 7); + break; - case TY_CSI_PS('m', 48) : _currentScreen->setBackColor (p, q); break; + case TY_CSI_PS('m', 48) : + _currentScreen->setBackColor (p, q); + break; - case TY_CSI_PS('m', 49) : _currentScreen->setBackColor (COLOR_SPACE_DEFAULT, 1); break; + case TY_CSI_PS('m', 49) : + _currentScreen->setBackColor (COLOR_SPACE_DEFAULT, 1); + break; - case TY_CSI_PS('m', 90) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 8); break; - case TY_CSI_PS('m', 91) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 9); break; - case TY_CSI_PS('m', 92) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 10); break; - case TY_CSI_PS('m', 93) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 11); break; - case TY_CSI_PS('m', 94) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 12); break; - case TY_CSI_PS('m', 95) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 13); break; - case TY_CSI_PS('m', 96) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 14); break; - case TY_CSI_PS('m', 97) : _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 15); break; + case TY_CSI_PS('m', 90) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 8); + break; + case TY_CSI_PS('m', 91) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 9); + break; + case TY_CSI_PS('m', 92) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 10); + break; + case TY_CSI_PS('m', 93) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 11); + break; + case TY_CSI_PS('m', 94) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 12); + break; + case TY_CSI_PS('m', 95) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 13); + break; + case TY_CSI_PS('m', 96) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 14); + break; + case TY_CSI_PS('m', 97) : + _currentScreen->setForeColor (COLOR_SPACE_SYSTEM, 15); + break; - case TY_CSI_PS('m', 100) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 8); break; - case TY_CSI_PS('m', 101) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 9); break; - case TY_CSI_PS('m', 102) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 10); break; - case TY_CSI_PS('m', 103) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 11); break; - case TY_CSI_PS('m', 104) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 12); break; - case TY_CSI_PS('m', 105) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 13); break; - case TY_CSI_PS('m', 106) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 14); break; - case TY_CSI_PS('m', 107) : _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 15); break; + case TY_CSI_PS('m', 100) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 8); + break; + case TY_CSI_PS('m', 101) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 9); + break; + case TY_CSI_PS('m', 102) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 10); + break; + case TY_CSI_PS('m', 103) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 11); + break; + case TY_CSI_PS('m', 104) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 12); + break; + case TY_CSI_PS('m', 105) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 13); + break; + case TY_CSI_PS('m', 106) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 14); + break; + case TY_CSI_PS('m', 107) : + _currentScreen->setBackColor (COLOR_SPACE_SYSTEM, 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_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('@' ) : _currentScreen->insertChars (p ); break; - case TY_CSI_PN('A' ) : _currentScreen->cursorUp (p ); break; //VT100 - case TY_CSI_PN('B' ) : _currentScreen->cursorDown (p ); break; //VT100 - case TY_CSI_PN('C' ) : _currentScreen->cursorRight (p ); break; //VT100 - case TY_CSI_PN('D' ) : _currentScreen->cursorLeft (p ); break; //VT100 - case TY_CSI_PN('G' ) : _currentScreen->setCursorX (p ); break; //LINUX - case TY_CSI_PN('H' ) : _currentScreen->setCursorYX (p, q); break; //VT100 - case TY_CSI_PN('I' ) : _currentScreen->Tabulate (p ); break; - case TY_CSI_PN('L' ) : _currentScreen->insertLines (p ); break; - case TY_CSI_PN('M' ) : _currentScreen->deleteLines (p ); break; - case TY_CSI_PN('P' ) : _currentScreen->deleteChars (p ); break; - case TY_CSI_PN('S' ) : _currentScreen->scrollUp (p ); break; - case TY_CSI_PN('T' ) : _currentScreen->scrollDown (p ); break; - case TY_CSI_PN('X' ) : _currentScreen->eraseChars (p ); break; - case TY_CSI_PN('Z' ) : _currentScreen->backTabulate (p ); break; - case TY_CSI_PN('c' ) : reportTerminalType ( ); break; //VT100 - case TY_CSI_PN('d' ) : _currentScreen->setCursorY (p ); break; //LINUX - case TY_CSI_PN('f' ) : _currentScreen->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_PN('@' ) : + _currentScreen->insertChars (p ); + break; + case TY_CSI_PN('A' ) : + _currentScreen->cursorUp (p ); + break; //VT100 + case TY_CSI_PN('B' ) : + _currentScreen->cursorDown (p ); + break; //VT100 + case TY_CSI_PN('C' ) : + _currentScreen->cursorRight (p ); + break; //VT100 + case TY_CSI_PN('D' ) : + _currentScreen->cursorLeft (p ); + break; //VT100 + case TY_CSI_PN('G' ) : + _currentScreen->setCursorX (p ); + break; //LINUX + case TY_CSI_PN('H' ) : + _currentScreen->setCursorYX (p, q); + break; //VT100 + case TY_CSI_PN('I' ) : + _currentScreen->Tabulate (p ); + break; + case TY_CSI_PN('L' ) : + _currentScreen->insertLines (p ); + break; + case TY_CSI_PN('M' ) : + _currentScreen->deleteLines (p ); + break; + case TY_CSI_PN('P' ) : + _currentScreen->deleteChars (p ); + break; + case TY_CSI_PN('S' ) : + _currentScreen->scrollUp (p ); + break; + case TY_CSI_PN('T' ) : + _currentScreen->scrollDown (p ); + break; + case TY_CSI_PN('X' ) : + _currentScreen->eraseChars (p ); + break; + case TY_CSI_PN('Z' ) : + _currentScreen->backTabulate (p ); + break; + case TY_CSI_PN('c' ) : + reportTerminalType ( ); + break; //VT100 + case TY_CSI_PN('d' ) : + _currentScreen->setCursorY (p ); + break; //LINUX + case TY_CSI_PN('f' ) : + _currentScreen->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('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('l', 2) : + resetMode (MODE_Ansi ); + break; //VT100 - case TY_CSI_PR('h', 3) : clearScreenAndSetColumns(132); break; //VT100 - case TY_CSI_PR('l', 3) : clearScreenAndSetColumns(80); break; //VT100 + case TY_CSI_PR('h', 3) : + clearScreenAndSetColumns(132); + break; //VT100 + case TY_CSI_PR('l', 3) : + clearScreenAndSetColumns(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', 4) : /* IGNORED: soft scrolling */ + break; //VT100 + case TY_CSI_PR('l', 4) : /* IGNORED: soft scrolling */ + break; //VT100 - case TY_CSI_PR('h', 5) : _currentScreen-> setMode (MODE_Screen ); break; //VT100 - case TY_CSI_PR('l', 5) : _currentScreen-> resetMode (MODE_Screen ); break; //VT100 + case TY_CSI_PR('h', 5) : + _currentScreen-> setMode (MODE_Screen ); + break; //VT100 + case TY_CSI_PR('l', 5) : + _currentScreen-> resetMode (MODE_Screen ); + break; //VT100 - case TY_CSI_PR('h', 6) : _currentScreen-> setMode (MODE_Origin ); break; //VT100 - case TY_CSI_PR('l', 6) : _currentScreen-> resetMode (MODE_Origin ); break; //VT100 - case TY_CSI_PR('s', 6) : _currentScreen-> saveMode (MODE_Origin ); break; //FIXME - case TY_CSI_PR('r', 6) : _currentScreen->restoreMode (MODE_Origin ); break; //FIXME + case TY_CSI_PR('h', 6) : + _currentScreen-> setMode (MODE_Origin ); + break; //VT100 + case TY_CSI_PR('l', 6) : + _currentScreen-> resetMode (MODE_Origin ); + break; //VT100 + case TY_CSI_PR('s', 6) : + _currentScreen-> saveMode (MODE_Origin ); + break; //FIXME + case TY_CSI_PR('r', 6) : + _currentScreen->restoreMode (MODE_Origin ); + break; //FIXME - case TY_CSI_PR('h', 7) : _currentScreen-> setMode (MODE_Wrap ); break; //VT100 - case TY_CSI_PR('l', 7) : _currentScreen-> resetMode (MODE_Wrap ); break; //VT100 - case TY_CSI_PR('s', 7) : _currentScreen-> saveMode (MODE_Wrap ); break; //FIXME - case TY_CSI_PR('r', 7) : _currentScreen->restoreMode (MODE_Wrap ); break; //FIXME + case TY_CSI_PR('h', 7) : + _currentScreen-> setMode (MODE_Wrap ); + break; //VT100 + case TY_CSI_PR('l', 7) : + _currentScreen-> resetMode (MODE_Wrap ); + break; //VT100 + case TY_CSI_PR('s', 7) : + _currentScreen-> saveMode (MODE_Wrap ); + break; //FIXME + case TY_CSI_PR('r', 7) : + _currentScreen->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', 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', 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', 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', 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', 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', 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 + 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 - // - - //Note about mouse modes: - //There are four mouse modes which xterm-compatible terminals can support - 1000,1001,1002,1003 - //Konsole currently supports mode 1000 (basic mouse press and release) and mode 1002 (dragging the mouse). - //TODO: Implementation of mouse modes 1001 (something called hilight tracking) and - //1003 (a slight variation on dragging the mouse) - // - - 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 + // XTerm defines the following modes: + // SET_VT200_MOUSE 1000 + // SET_VT200_HIGHLIGHT_MOUSE 1001 + // SET_BTN_EVENT_MOUSE 1002 + // SET_ANY_EVENT_MOUSE 1003 + // - case TY_CSI_PR('h', 1001) : /* IGNORED: hilite mouse tracking */ break; //XTERM - case TY_CSI_PR('l', 1001) : resetMode (MODE_Mouse1001); 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 + //Note about mouse modes: + //There are four mouse modes which xterm-compatible terminals can support - 1000,1001,1002,1003 + //Konsole currently supports mode 1000 (basic mouse press and release) and mode 1002 (dragging the mouse). + //TODO: Implementation of mouse modes 1001 (something called hilight tracking) and + //1003 (a slight variation on dragging the mouse) + // - case TY_CSI_PR('h', 1002) : setMode (MODE_Mouse1002); break; //XTERM - case TY_CSI_PR('l', 1002) : resetMode (MODE_Mouse1002); break; //XTERM - case TY_CSI_PR('s', 1002) : saveMode (MODE_Mouse1002); break; //XTERM - case TY_CSI_PR('r', 1002) : restoreMode (MODE_Mouse1002); break; //XTERM + 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', 1003) : setMode (MODE_Mouse1003); break; //XTERM - case TY_CSI_PR('l', 1003) : resetMode (MODE_Mouse1003); break; //XTERM - case TY_CSI_PR('s', 1003) : saveMode (MODE_Mouse1003); break; //XTERM - case TY_CSI_PR('r', 1003) : restoreMode (MODE_Mouse1003); break; //XTERM + case TY_CSI_PR('h', 1001) : /* IGNORED: hilite mouse tracking */ + break; //XTERM + case TY_CSI_PR('l', 1001) : + resetMode (MODE_Mouse1001); + break; //XTERM + case TY_CSI_PR('s', 1001) : /* IGNORED: hilite mouse tracking */ + break; //XTERM + case TY_CSI_PR('r', 1001) : /* IGNORED: hilite mouse tracking */ + break; //XTERM - case TY_CSI_PR('h', 1047) : setMode (MODE_AppScreen); break; //XTERM - case TY_CSI_PR('l', 1047) : _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 + case TY_CSI_PR('h', 1002) : + setMode (MODE_Mouse1002); + break; //XTERM + case TY_CSI_PR('l', 1002) : + resetMode (MODE_Mouse1002); + break; //XTERM + case TY_CSI_PR('s', 1002) : + saveMode (MODE_Mouse1002); + break; //XTERM + case TY_CSI_PR('r', 1002) : + restoreMode (MODE_Mouse1002); + 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 + case TY_CSI_PR('h', 1003) : + setMode (MODE_Mouse1003); + break; //XTERM + case TY_CSI_PR('l', 1003) : + resetMode (MODE_Mouse1003); + break; //XTERM + case TY_CSI_PR('s', 1003) : + saveMode (MODE_Mouse1003); + break; //XTERM + case TY_CSI_PR('r', 1003) : + restoreMode (MODE_Mouse1003); + 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 + 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: weird DEC reset sequence - case TY_CSI_PE('p' ) : /* IGNORED: reset ( ) */ break; + //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: when changing between vt52 and ansi mode evtl do some resetting. - case TY_VT52('A' ) : _currentScreen->cursorUp ( 1); break; //VT52 - case TY_VT52('B' ) : _currentScreen->cursorDown ( 1); break; //VT52 - case TY_VT52('C' ) : _currentScreen->cursorRight ( 1); break; //VT52 - case TY_VT52('D' ) : _currentScreen->cursorLeft ( 1); break; //VT52 + //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 - case TY_VT52('F' ) : setAndUseCharset (0, '0'); break; //VT52 - case TY_VT52('G' ) : setAndUseCharset (0, 'B'); break; //VT52 + //FIXME: weird DEC reset sequence + case TY_CSI_PE('p' ) : /* IGNORED: reset ( ) */ + break; - case TY_VT52('H' ) : _currentScreen->setCursorYX (1,1 ); break; //VT52 - case TY_VT52('I' ) : _currentScreen->reverseIndex ( ); break; //VT52 - case TY_VT52('J' ) : _currentScreen->clearToEndOfScreen ( ); break; //VT52 - case TY_VT52('K' ) : _currentScreen->clearToEndOfLine ( ); break; //VT52 - case TY_VT52('Y' ) : _currentScreen->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 + //FIXME: when changing between vt52 and ansi mode evtl do some resetting. + case TY_VT52('A' ) : + _currentScreen->cursorUp ( 1); + break; //VT52 + case TY_VT52('B' ) : + _currentScreen->cursorDown ( 1); + break; //VT52 + case TY_VT52('C' ) : + _currentScreen->cursorRight ( 1); + break; //VT52 + case TY_VT52('D' ) : + _currentScreen->cursorLeft ( 1); + break; //VT52 - case TY_CSI_PG('c' ) : reportSecondaryAttributes( ); break; //VT100 + case TY_VT52('F' ) : + setAndUseCharset (0, '0'); + break; //VT52 + case TY_VT52('G' ) : + setAndUseCharset (0, 'B'); + break; //VT52 - default : ReportErrorToken(); break; - }; + case TY_VT52('H' ) : + _currentScreen->setCursorYX (1,1 ); + break; //VT52 + case TY_VT52('I' ) : + _currentScreen->reverseIndex ( ); + break; //VT52 + case TY_VT52('J' ) : + _currentScreen->clearToEndOfScreen ( ); + break; //VT52 + case TY_VT52('K' ) : + _currentScreen->clearToEndOfLine ( ); + break; //VT52 + case TY_VT52('Y' ) : + _currentScreen->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; + }; } void Vt102Emulation::clearScreenAndSetColumns(int columnCount) { - setImageSize(_currentScreen->getLines(),columnCount); + setImageSize(_currentScreen->getLines(),columnCount); clearEntireScreen(); - setDefaultMargins(); + setDefaultMargins(); _currentScreen->setCursorYX(0,0); } @@ -801,7 +1321,7 @@ void Vt102Emulation::clearScreenAndSetColumns(int columnCount) /* */ /* ------------------------------------------------------------------------- */ -/* +/* Outgoing bytes originate from several sources: - Replies to Enquieries. @@ -814,10 +1334,10 @@ void Vt102Emulation::clearScreenAndSetColumns(int columnCount) void Vt102Emulation::sendString(const char* s , int length) { - if ( length >= 0 ) - emit sendData(s,length); - else - emit sendData(s,strlen(s)); + if ( length >= 0 ) + emit sendData(s,length); + else + emit sendData(s,strlen(s)); } // Replies ----------------------------------------------------------------- -- @@ -828,9 +1348,10 @@ void Vt102Emulation::sendString(const char* s , int length) */ void Vt102Emulation::reportCursorPosition() -{ char tmp[20]; - sprintf(tmp,"\033[%d;%dR",_currentScreen->getCursorY()+1,_currentScreen->getCursorX()+1); - sendString(tmp); +{ + char tmp[20]; + sprintf(tmp,"\033[%d;%dR",_currentScreen->getCursorY()+1,_currentScreen->getCursorX()+1); + sendString(tmp); } /* @@ -843,32 +1364,33 @@ void Vt102Emulation::reportCursorPosition() void Vt102Emulation::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 + // 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 Vt102Emulation::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. + // 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 Vt102Emulation::reportTerminalParms(int p) // DECREPTPARM -{ char tmp[100]; - sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true. - sendString(tmp); +{ + char tmp[100]; + sprintf(tmp,"\033[%d;1;1;112;112;1;0x",p); // not really true. + sendString(tmp); } /*! @@ -876,7 +1398,7 @@ void Vt102Emulation::reportTerminalParms(int p) void Vt102Emulation::reportStatus() { - sendString("\033[0n"); //VT100. Device status report. 0 = Ready. + sendString("\033[0n"); //VT100. Device status report. 0 = Ready. } /*! @@ -886,7 +1408,7 @@ void Vt102Emulation::reportStatus() void Vt102Emulation::reportAnswerBack() { - sendString(ANSWER_BACK); + sendString(ANSWER_BACK); } // Mouse Handling ---------------------------------------------------------- -- @@ -908,18 +1430,19 @@ void Vt102Emulation::reportAnswerBack() */ void Vt102Emulation::sendMouseEvent( int cb, int cx, int cy , int eventType ) -{ char tmp[20]; - if ( 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; +{ + char tmp[20]; + if ( 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; - //Mouse motion handling - if ( (getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1 ) - cb += 0x20; //add 32 to signify motion event + //Mouse motion handling + if ( (getMode(MODE_Mouse1002) || getMode(MODE_Mouse1003)) && eventType == 1 ) + cb += 0x20; //add 32 to signify motion event - sprintf(tmp,"\033[M%c%c%c",cb+0x20,cx+0x20,cy+0x20); - sendString(tmp); + sprintf(tmp,"\033[M%c%c%c",cb+0x20,cx+0x20,cy+0x20); + sendString(tmp); } // Keyboard Handling ------------------------------------------------------- -- @@ -929,13 +1452,13 @@ void Vt102Emulation::sendMouseEvent( int cb, int cx, int cy , int eventType ) void Vt102Emulation::sendText( const QString& text ) { - if (!text.isEmpty()) { - QKeyEvent event(QEvent::KeyPress, - 0, - Qt::NoModifier, - text); - sendKeyEvent(&event); // expose as a big fat keypress event - } + if (!text.isEmpty()) { + QKeyEvent event(QEvent::KeyPress, + 0, + Qt::NoModifier, + text); + sendKeyEvent(&event); // expose as a big fat keypress event + } } @@ -951,12 +1474,11 @@ void Vt102Emulation::sendKeyEvent( QKeyEvent* event ) if ( getMode(MODE_AppScreen)) states |= KeyboardTranslator::AlternateScreenState; // lookup key binding - if ( _keyTranslator ) - { - KeyboardTranslator::Entry entry = _keyTranslator->findEntry( - event->key() , - modifiers, - states ); + if ( _keyTranslator ) { + KeyboardTranslator::Entry entry = _keyTranslator->findEntry( + event->key() , + modifiers, + states ); // send result to terminal QByteArray textToSend; @@ -966,37 +1488,30 @@ void Vt102Emulation::sendKeyEvent( QKeyEvent* event ) // (unless there is an entry defined for this particular combination // in the keyboard modifier) bool wantsAltModifier = entry.modifiers() & entry.modifierMask() & Qt::AltModifier; - bool wantsAnyModifier = entry.state() & entry.stateMask() & KeyboardTranslator::AnyModifierState; + bool wantsAnyModifier = entry.state() & entry.stateMask() & KeyboardTranslator::AnyModifierState; - if ( modifiers & Qt::AltModifier && !(wantsAltModifier || wantsAnyModifier) - && !event->text().isEmpty() ) - { + if ( modifiers & Qt::AltModifier && !(wantsAltModifier || wantsAnyModifier) + && !event->text().isEmpty() ) { textToSend.prepend("\033"); } - if ( entry.command() != KeyboardTranslator::NoCommand ) - { - if (entry.command() & KeyboardTranslator::EraseCommand) - textToSend += getErase(); + if ( entry.command() != KeyboardTranslator::NoCommand ) { + if (entry.command() & KeyboardTranslator::EraseCommand) + textToSend += getErase(); // TODO command handling - } - else if ( !entry.text().isEmpty() ) - { + } else if ( !entry.text().isEmpty() ) { textToSend += _codec->fromUnicode(entry.text(true,modifiers)); - } - else + } else textToSend += _codec->fromUnicode(event->text()); sendData( textToSend.constData() , textToSend.length() ); - } - else - { + } else { // print an error message to the terminal if no key translator has been // set QString translatorError = ("No keyboard translator available. " - "The information needed to convert key presses " - "into characters to send to the terminal " - "is missing."); + "The information needed to convert key presses " + "into characters to send to the terminal " + "is missing."); reset(); receiveData( translatorError.toAscii().constData() , translatorError.count() ); @@ -1011,7 +1526,7 @@ void Vt102Emulation::sendKeyEvent( QKeyEvent* event ) // 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. @@ -1022,7 +1537,7 @@ void Vt102Emulation::sendKeyEvent( QKeyEvent* event ) in the pipeline. It only applies to tokens, which represent plain characters. - This conversion it eventually continued in TerminalDisplay.C, since + This conversion it eventually continued in TerminalDisplay.C, since it might involve VT100 enhanced fonts, which have these particular glyphs allocated in (0x00-0x1f) in their code page. */ @@ -1033,9 +1548,9 @@ void Vt102Emulation::sendKeyEvent( QKeyEvent* event ) unsigned short Vt102Emulation::applyCharset(unsigned short c) { - if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f]; - if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete - return c; + if (CHARSET.graphic && 0x5f <= c && c <= 0x7e) return vt100_graphics[c-0x5f]; + if (CHARSET.pound && c == '#' ) return 0xa3; //This mode is obsolete + return c; } /* @@ -1048,64 +1563,66 @@ unsigned short Vt102Emulation::applyCharset(unsigned short c) void Vt102Emulation::resetCharset(int scrno) { - _charset[scrno].cu_cs = 0; - strncpy(_charset[scrno].charset,"BBBB",4); - _charset[scrno].sa_graphic = false; - _charset[scrno].sa_pound = false; - _charset[scrno].graphic = false; - _charset[scrno].pound = false; + _charset[scrno].cu_cs = 0; + strncpy(_charset[scrno].charset,"BBBB",4); + _charset[scrno].sa_graphic = false; + _charset[scrno].sa_pound = false; + _charset[scrno].graphic = false; + _charset[scrno].pound = false; } void Vt102Emulation::setCharset(int n, int cs) // on both screens. { - _charset[0].charset[n&3] = cs; useCharset(_charset[0].cu_cs); - _charset[1].charset[n&3] = cs; useCharset(_charset[1].cu_cs); + _charset[0].charset[n&3] = cs; + useCharset(_charset[0].cu_cs); + _charset[1].charset[n&3] = cs; + useCharset(_charset[1].cu_cs); } void Vt102Emulation::setAndUseCharset(int n, int cs) { - CHARSET.charset[n&3] = cs; - useCharset(n&3); + CHARSET.charset[n&3] = cs; + useCharset(n&3); } void Vt102Emulation::useCharset(int n) { - CHARSET.cu_cs = n&3; - CHARSET.graphic = (CHARSET.charset[n&3] == '0'); - CHARSET.pound = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete + CHARSET.cu_cs = n&3; + CHARSET.graphic = (CHARSET.charset[n&3] == '0'); + CHARSET.pound = (CHARSET.charset[n&3] == 'A'); //This mode is obsolete } void Vt102Emulation::setDefaultMargins() { - _screen[0]->setDefaultMargins(); - _screen[1]->setDefaultMargins(); + _screen[0]->setDefaultMargins(); + _screen[1]->setDefaultMargins(); } void Vt102Emulation::setMargins(int t, int b) { - _screen[0]->setMargins(t, b); - _screen[1]->setMargins(t, b); + _screen[0]->setMargins(t, b); + _screen[1]->setMargins(t, b); } /*! Save the cursor position and the rendition attribute settings. */ void Vt102Emulation::saveCursor() { - CHARSET.sa_graphic = CHARSET.graphic; - CHARSET.sa_pound = CHARSET.pound; //This mode is obsolete - // we are not clear about these - //sa_charset = charsets[cScreen->_charset]; - //sa_charset_num = cScreen->_charset; - _currentScreen->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; + _currentScreen->saveCursor(); } /*! Restore the cursor position and the rendition attribute settings. */ void Vt102Emulation::restoreCursor() { - CHARSET.graphic = CHARSET.sa_graphic; - CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete - _currentScreen->restoreCursor(); + CHARSET.graphic = CHARSET.sa_graphic; + CHARSET.pound = CHARSET.sa_pound; //This mode is obsolete + _currentScreen->restoreCursor(); } /* ------------------------------------------------------------------------- */ @@ -1130,92 +1647,96 @@ void Vt102Emulation::restoreCursor() void Vt102Emulation::resetModes() { - resetMode(MODE_Mouse1000); saveMode(MODE_Mouse1000); - resetMode(MODE_Mouse1001); saveMode(MODE_Mouse1001); - resetMode(MODE_Mouse1002); saveMode(MODE_Mouse1002); - resetMode(MODE_Mouse1003); saveMode(MODE_Mouse1003); + resetMode(MODE_Mouse1000); + saveMode(MODE_Mouse1000); + resetMode(MODE_Mouse1001); + saveMode(MODE_Mouse1001); + resetMode(MODE_Mouse1002); + saveMode(MODE_Mouse1002); + resetMode(MODE_Mouse1003); + saveMode(MODE_Mouse1003); - resetMode(MODE_AppScreen); saveMode(MODE_AppScreen); - // here come obsolete modes - resetMode(MODE_AppCuKeys); saveMode(MODE_AppCuKeys); - resetMode(MODE_NewLine ); + resetMode(MODE_AppScreen); + saveMode(MODE_AppScreen); + // here come obsolete modes + resetMode(MODE_AppCuKeys); + saveMode(MODE_AppCuKeys); + resetMode(MODE_NewLine ); setMode(MODE_Ansi ); } void Vt102Emulation::setMode(int m) { - _currParm.mode[m] = true; - switch (m) - { + _currParm.mode[m] = true; + switch (m) { case MODE_Mouse1000: case MODE_Mouse1001: case MODE_Mouse1002: case MODE_Mouse1003: - emit programUsesMouseChanged(false); - break; + emit programUsesMouseChanged(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); - } + 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 Vt102Emulation::resetMode(int m) { - _currParm.mode[m] = false; - switch (m) - { - case MODE_Mouse1000 : + _currParm.mode[m] = false; + switch (m) { + case MODE_Mouse1000 : case MODE_Mouse1001 : case MODE_Mouse1002 : case MODE_Mouse1003 : - emit programUsesMouseChanged(true); - break; + emit programUsesMouseChanged(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); - } + case MODE_AppScreen : + _screen[0]->clearSelection(); + setScreen(0); + break; + } + if (m < MODES_SCREEN || m == MODE_NewLine) { + _screen[0]->resetMode(m); + _screen[1]->resetMode(m); + } } void Vt102Emulation::saveMode(int m) { - _saveParm.mode[m] = _currParm.mode[m]; + _saveParm.mode[m] = _currParm.mode[m]; } void Vt102Emulation::restoreMode(int m) { - if (_saveParm.mode[m]) - setMode(m); - else - resetMode(m); + if (_saveParm.mode[m]) + setMode(m); + else + resetMode(m); } bool Vt102Emulation::getMode(int m) { - return _currParm.mode[m]; + return _currParm.mode[m]; } char Vt102Emulation::getErase() const { - KeyboardTranslator::Entry entry = _keyTranslator->findEntry( - Qt::Key_Backspace, - 0, - 0); - if ( entry.text().count() > 0 ) - return entry.text()[0]; - else - return '\b'; + KeyboardTranslator::Entry entry = _keyTranslator->findEntry( + Qt::Key_Backspace, + 0, + 0); + if ( entry.text().count() > 0 ) + return entry.text()[0]; + else + return '\b'; } /* ------------------------------------------------------------------------- */ @@ -1233,26 +1754,26 @@ char Vt102Emulation::getErase() const */ 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]); - } +{ + int i; + for (i = 0; i < len; i++) { + if (s[i] == '\\') + printf("\\\\"); + else if ((s[i]) > 32 && s[i] < 127) + printf("%c",s[i]); + else + printf("\\%04x(hex)",s[i]); + } } -void Vt102Emulation::scan_buffer_report() { - if (ppos == 0 || (ppos == 1 && (pbuf[0] & 0xff) >= 32)) { - return; - } - printf("token: "); - hexdump(pbuf,ppos); - printf("\n"); +void Vt102Emulation::scan_buffer_report() +{ + if (ppos == 0 || (ppos == 1 && (pbuf[0] & 0xff) >= 32)) { + return; + } + printf("token: "); + hexdump(pbuf,ppos); + printf("\n"); } /*! @@ -1261,7 +1782,8 @@ void Vt102Emulation::scan_buffer_report() { void Vt102Emulation::ReportErrorToken() { #ifndef NDEBUG - printf("undecodable "); scan_buffer_report(); + printf("undecodable "); + scan_buffer_report(); #endif } diff --git a/lib/Vt102Emulation.h b/lib/Vt102Emulation.h index 4554c1b..5498f03 100644 --- a/lib/Vt102Emulation.h +++ b/lib/Vt102Emulation.h @@ -1,6 +1,6 @@ /* This file is part of Konsole, an X terminal. - + Copyright (C) 2007 by Robert Knight Copyright (C) 1997,1998 by Lars Doelle @@ -28,7 +28,7 @@ // Standard Library #include -// Qt +// Qt #include #include #include @@ -50,141 +50,139 @@ namespace Konsole { -struct DECpar -{ - bool mode[MODE_total]; +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 +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 }; /** * Provides an xterm compatible terminal emulation based on the DEC VT102 terminal. * A full description of this terminal can be found at http://vt100.net/docs/vt102-ug/ - * - * In addition, various additional xterm escape sequences are supported to provide + * + * In addition, various additional xterm escape sequences are supported to provide * features such as mouse input handling. * See http://rtfm.etla.org/xterm/ctlseq.html for a description of xterm's escape - * sequences. + * sequences. * */ class Vt102Emulation : public Emulation -{ -Q_OBJECT +{ + Q_OBJECT public: - /** Constructs a new emulation */ - Vt102Emulation(); - ~Vt102Emulation(); - - // reimplemented - virtual void clearEntireScreen(); - virtual void reset(); - - // reimplemented - virtual char getErase() const; - -public slots: + /** Constructs a new emulation */ + Vt102Emulation(); + ~Vt102Emulation(); + + // reimplemented + virtual void clearEntireScreen(); + virtual void reset(); + + // reimplemented + virtual char getErase() const; + +public slots: + + // reimplemented + virtual void sendString(const char*,int length = -1); + virtual void sendText(const QString& text); + virtual void sendKeyEvent(QKeyEvent*); + virtual void sendMouseEvent( int buttons, int column, int line , int eventType ); - // reimplemented - virtual void sendString(const char*,int length = -1); - virtual void sendText(const QString& text); - virtual void sendKeyEvent(QKeyEvent*); - virtual void sendMouseEvent( int buttons, int column, int line , int eventType ); - protected: - // reimplemented - virtual void setMode (int mode); - virtual void resetMode (int mode); + // reimplemented + virtual void setMode (int mode); + virtual void resetMode (int mode); + + // reimplemented + virtual void receiveChar(int cc); - // reimplemented - virtual void receiveChar(int cc); - private slots: - - //causes changeTitle() to be emitted for each (int,QString) pair in pendingTitleUpdates - //used to buffer multiple title updates - void updateTitle(); + + //causes changeTitle() to be emitted for each (int,QString) pair in pendingTitleUpdates + //used to buffer multiple title updates + void updateTitle(); private: - 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); + 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 top, int bottom); - //set margins for all screens back to their defaults - void setDefaultMargins(); + void setMargins(int top, int bottom); + //set margins for all screens back to their defaults + void setDefaultMargins(); - // returns true if 'mode' is set or false otherwise - bool getMode (int mode); - // saves the current boolean value of 'mode' - void saveMode (int mode); - // restores the boolean value of 'mode' - void restoreMode(int mode); - // resets all modes - void resetModes(); + // returns true if 'mode' is set or false otherwise + bool getMode (int mode); + // saves the current boolean value of 'mode' + void saveMode (int mode); + // restores the boolean value of 'mode' + void restoreMode(int mode); + // resets all modes + void resetModes(); - void resetToken(); + void resetToken(); #define MAXPBUF 80 - void pushToToken(int cc); - int pbuf[MAXPBUF]; //FIXME: overflow? - int ppos; + 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 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 scan_buffer_report(); //FIXME: rename + void ReportErrorToken(); //FIXME: rename - void tau(int code, int p, int q); - void XtermHack(); + 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 reportTerminalType(); + void reportSecondaryAttributes(); + void reportStatus(); + void reportAnswerBack(); + void reportCursorPosition(); + void reportTerminalParms(int p); - void onScrollLock(); - void scrollLock(const bool lock); + void onScrollLock(); + void scrollLock(const bool lock); - // clears the screen and resizes it to the specified - // number of columns - void clearScreenAndSetColumns(int columnCount); + // clears the screen and resizes it to the specified + // number of columns + void clearScreenAndSetColumns(int columnCount); - CharCodes _charset[2]; + CharCodes _charset[2]; - DECpar _currParm; - DECpar _saveParm; + DECpar _currParm; + DECpar _saveParm; + + //hash table and timer for buffering calls to the session instance + //to update the name of the session + //or window title. + //these calls occur when certain escape sequences are seen in the + //output from the terminal + QHash _pendingTitleUpdates; + QTimer* _titleUpdateTimer; - //hash table and timer for buffering calls to the session instance - //to update the name of the session - //or window title. - //these calls occur when certain escape sequences are seen in the - //output from the terminal - QHash _pendingTitleUpdates; - QTimer* _titleUpdateTimer; - }; } diff --git a/lib/k3process.cpp b/lib/k3process.cpp index 8bbbd66..12b508e 100644 --- a/lib/k3process.cpp +++ b/lib/k3process.cpp @@ -74,28 +74,28 @@ // private data // ////////////////// -class K3ProcessPrivate { +class K3ProcessPrivate +{ public: - K3ProcessPrivate() : - usePty(K3Process::NoCommunication), - addUtmp(false), useShell(false), - pty(0), - priority(0) - { - } + K3ProcessPrivate() : + usePty(K3Process::NoCommunication), + addUtmp(false), useShell(false), + pty(0), + priority(0) { + } - K3Process::Communication usePty; - bool addUtmp : 1; - bool useShell : 1; + K3Process::Communication usePty; + bool addUtmp : 1; + bool useShell : 1; - KPty *pty; + KPty *pty; - int priority; + int priority; - QMap env; - QString wd; - QByteArray shell; - QByteArray executable; + QMap env; + QString wd; + QByteArray shell; + QByteArray executable; }; ///////////////////////////// @@ -103,69 +103,67 @@ public: ///////////////////////////// K3Process::K3Process( QObject* parent ) - : QObject( parent ), - run_mode(NotifyOnExit), - runs(false), - pid_(0), - status(0), - keepPrivs(false), - innot(0), - outnot(0), - errnot(0), - communication(NoCommunication), - input_data(0), - input_sent(0), - input_total(0), - d(new K3ProcessPrivate) + : QObject( parent ), + run_mode(NotifyOnExit), + runs(false), + pid_(0), + status(0), + keepPrivs(false), + innot(0), + outnot(0), + errnot(0), + communication(NoCommunication), + input_data(0), + input_sent(0), + input_total(0), + d(new K3ProcessPrivate) { - K3ProcessController::ref(); - K3ProcessController::instance()->addKProcess(this); + K3ProcessController::ref(); + K3ProcessController::instance()->addKProcess(this); - out[0] = out[1] = -1; - in[0] = in[1] = -1; - err[0] = err[1] = -1; + out[0] = out[1] = -1; + in[0] = in[1] = -1; + err[0] = err[1] = -1; } void K3Process::setEnvironment(const QString &name, const QString &value) { - d->env.insert(name, value); + d->env.insert(name, value); } void K3Process::setWorkingDirectory(const QString &dir) { - d->wd = dir; + d->wd = dir; } void K3Process::setupEnvironment() { - QMap::Iterator it; - for(it = d->env.begin(); it != d->env.end(); ++it) - { - setenv(QFile::encodeName(it.key()).data(), - QFile::encodeName(it.value()).data(), 1); - } - if (!d->wd.isEmpty()) - { - if (-1 == chdir(QFile::encodeName(d->wd).constData())) { - qDebug() << "Can't change directory: " << strerror(errno) << endl; - } - } + QMap::Iterator it; + for (it = d->env.begin(); it != d->env.end(); ++it) { + setenv(QFile::encodeName(it.key()).data(), + QFile::encodeName(it.value()).data(), 1); + } + if (!d->wd.isEmpty()) { + if (-1 == chdir(QFile::encodeName(d->wd).constData())) { + qDebug() << "Can't change directory: " << strerror(errno) << endl; + } + } } void K3Process::setRunPrivileged(bool keepPrivileges) { - keepPrivs = keepPrivileges; + keepPrivs = keepPrivileges; } bool K3Process::runPrivileged() const { - return keepPrivs; + return keepPrivs; } bool @@ -184,126 +182,122 @@ K3Process::setPriority(int prio) K3Process::~K3Process() { - if (run_mode != DontCare) - kill(SIGKILL); - detach(); + if (run_mode != DontCare) + kill(SIGKILL); + detach(); - delete d->pty; - delete d; + delete d->pty; + delete d; - K3ProcessController::instance()->removeKProcess(this); - K3ProcessController::deref(); + K3ProcessController::instance()->removeKProcess(this); + K3ProcessController::deref(); } void K3Process::detach() { - if (runs) { - K3ProcessController::instance()->addProcess(pid_); - runs = false; - pid_ = 0; // close without draining - commClose(); // Clean up open fd's and socket notifiers. - } + if (runs) { + K3ProcessController::instance()->addProcess(pid_); + runs = false; + pid_ = 0; // close without draining + commClose(); // Clean up open fd's and socket notifiers. + } } void K3Process::setBinaryExecutable(const char *filename) { - d->executable = filename; + d->executable = filename; } K3Process &K3Process::operator<<(const QStringList& args) { - QStringList::ConstIterator it = args.begin(); - for ( ; it != args.end() ; ++it ) - arguments.append(QFile::encodeName(*it)); - return *this; + QStringList::ConstIterator it = args.begin(); + for ( ; it != args.end() ; ++it ) + arguments.append(QFile::encodeName(*it)); + return *this; } K3Process &K3Process::operator<<(const QByteArray& arg) { - return operator<< (arg.data()); + return operator<< (arg.data()); } K3Process &K3Process::operator<<(const char* arg) { - arguments.append(arg); - return *this; + arguments.append(arg); + return *this; } K3Process &K3Process::operator<<(const QString& arg) { - arguments.append(QFile::encodeName(arg)); - return *this; + arguments.append(QFile::encodeName(arg)); + return *this; } void K3Process::clearArguments() { - arguments.clear(); + arguments.clear(); } bool K3Process::start(RunMode runmode, Communication comm) { - if (runs) { - qDebug() << "Attempted to start an already running process" << endl; - return false; - } - - uint n = arguments.count(); - if (n == 0) { - qDebug() << "Attempted to start a process without arguments" << endl; - return false; - } - char **arglist; - QByteArray shellCmd; - if (d->useShell) - { - if (d->shell.isEmpty()) { - qDebug() << "Invalid shell specified" << endl; + if (runs) { + qDebug() << "Attempted to start an already running process" << endl; return false; - } + } - for (uint i = 0; i < n; i++) { - shellCmd += arguments[i]; - shellCmd += ' '; // CC: to separate the arguments - } + uint n = arguments.count(); + if (n == 0) { + qDebug() << "Attempted to start a process without arguments" << endl; + return false; + } + char **arglist; + QByteArray shellCmd; + if (d->useShell) { + if (d->shell.isEmpty()) { + qDebug() << "Invalid shell specified" << endl; + return false; + } - arglist = static_cast(malloc( 4 * sizeof(char *))); - arglist[0] = d->shell.data(); - arglist[1] = (char *) "-c"; - arglist[2] = shellCmd.data(); - arglist[3] = 0; - } - else - { - arglist = static_cast(malloc( (n + 1) * sizeof(char *))); - for (uint i = 0; i < n; i++) - arglist[i] = arguments[i].data(); - arglist[n] = 0; - } + for (uint i = 0; i < n; i++) { + shellCmd += arguments[i]; + shellCmd += ' '; // CC: to separate the arguments + } - run_mode = runmode; + arglist = static_cast(malloc( 4 * sizeof(char *))); + arglist[0] = d->shell.data(); + arglist[1] = (char *) "-c"; + arglist[2] = shellCmd.data(); + arglist[3] = 0; + } else { + arglist = static_cast(malloc( (n + 1) * sizeof(char *))); + for (uint i = 0; i < n; i++) + arglist[i] = arguments[i].data(); + arglist[n] = 0; + } - if (!setupCommunication(comm)) - { - qDebug() << "Could not setup Communication!" << endl; - free(arglist); - return false; - } + run_mode = runmode; - // We do this in the parent because if we do it in the child process - // gdb gets confused when the application runs from gdb. + if (!setupCommunication(comm)) { + qDebug() << "Could not setup Communication!" << endl; + free(arglist); + return false; + } + + // We do this in the parent because if we do it in the child process + // gdb gets confused when the application runs from gdb. #ifdef HAVE_INITGROUPS - struct passwd *pw = geteuid() ? 0 : getpwuid(getuid()); + struct passwd *pw = geteuid() ? 0 : getpwuid(getuid()); #endif - int fd[2]; - if (pipe(fd)) - fd[0] = fd[1] = -1; // Pipe failed.. continue + int fd[2]; + if (pipe(fd)) + fd[0] = fd[1] = -1; // Pipe failed.. continue - // we don't use vfork() because - // - it has unclear semantics and is not standardized - // - we do way too much magic in the child - pid_ = fork(); - if (pid_ == 0) { + // we don't use vfork() because + // - it has unclear semantics and is not standardized + // - we do way too much magic in the child + pid_ = fork(); + if (pid_ == 0) { // The child process close(fd[0]); @@ -311,7 +305,7 @@ bool K3Process::start(RunMode runmode, Communication comm) fcntl(fd[1], F_SETFD, FD_CLOEXEC); if (!commSetupDoneC()) - qDebug() << "Could not finish comm setup in child!" << endl; + qDebug() << "Could not finish comm setup in child!" << endl; // reset all signal handlers struct sigaction act; @@ -319,139 +313,129 @@ bool K3Process::start(RunMode runmode, Communication comm) act.sa_handler = SIG_DFL; act.sa_flags = 0; for (int sig = 1; sig < NSIG; sig++) - sigaction(sig, &act, 0L); + sigaction(sig, &act, 0L); if (d->priority) setpriority(PRIO_PROCESS, 0, d->priority); - if (!runPrivileged()) - { - setgid(getgid()); + if (!runPrivileged()) { + setgid(getgid()); #ifdef HAVE_INITGROUPS - if (pw) - initgroups(pw->pw_name, pw->pw_gid); + if (pw) + initgroups(pw->pw_name, pw->pw_gid); #endif - if (geteuid() != getuid()) - setuid(getuid()); - if (geteuid() != getuid()) - _exit(1); + if (geteuid() != getuid()) + setuid(getuid()); + if (geteuid() != getuid()) + _exit(1); } setupEnvironment(); if (runmode == DontCare || runmode == OwnGroup) - setsid(); + setsid(); const char *executable = arglist[0]; if (!d->executable.isEmpty()) - executable = d->executable.data(); + executable = d->executable.data(); execvp(executable, arglist); char resultByte = 1; ssize_t result = write(fd[1], &resultByte, 1); - if (result<0) { - qDebug() << "Write failed with the error code " << result << endl; - } + if (result<0) { + qDebug() << "Write failed with the error code " << result << endl; + } _exit(-1); - } else if (pid_ == -1) { + } else if (pid_ == -1) { // forking failed // commAbort(); pid_ = 0; free(arglist); return false; - } - // the parent continues here - free(arglist); - - if (!commSetupDoneP()) - qDebug() << "Could not finish comm setup in parent!" << endl; - - // Check whether client could be started. - close(fd[1]); - for(;;) - { - char resultByte; - int n = ::read(fd[0], &resultByte, 1); - if (n == 1) - { - // exec() failed - close(fd[0]); - waitpid(pid_, 0, 0); - pid_ = 0; - commClose(); - return false; - } - if (n == -1) - { - if (errno == EINTR) - continue; // Ignore - } - break; // success - } - close(fd[0]); - - runs = true; - switch (runmode) - { - case Block: - for (;;) - { - commClose(); // drain only, unless obsolete reimplementation - if (!runs) - { - // commClose detected data on the process exit notifification pipe - K3ProcessController::instance()->unscheduleCheck(); - if (waitpid(pid_, &status, WNOHANG) != 0) // error finishes, too - { - commClose(); // this time for real (runs is false) - K3ProcessController::instance()->rescheduleCheck(); - break; - } - runs = true; // for next commClose() iteration - } - else - { - // commClose is an obsolete reimplementation and waited until - // all output channels were closed (or it was interrupted). - // there is a chance that it never gets here ... - waitpid(pid_, &status, 0); - runs = false; - break; - } } - // why do we do this? i think this signal should be emitted _only_ - // after the process has successfully run _asynchronously_ --ossi - emit processExited(this); - break; - default: // NotifyOnExit & OwnGroup - input_data = 0; // Discard any data for stdin that might still be there - break; - } - return true; + // the parent continues here + free(arglist); + + if (!commSetupDoneP()) + qDebug() << "Could not finish comm setup in parent!" << endl; + + // Check whether client could be started. + close(fd[1]); + for (;;) { + char resultByte; + int n = ::read(fd[0], &resultByte, 1); + if (n == 1) { + // exec() failed + close(fd[0]); + waitpid(pid_, 0, 0); + pid_ = 0; + commClose(); + return false; + } + if (n == -1) { + if (errno == EINTR) + continue; // Ignore + } + break; // success + } + close(fd[0]); + + runs = true; + switch (runmode) { + case Block: + for (;;) { + commClose(); // drain only, unless obsolete reimplementation + if (!runs) { + // commClose detected data on the process exit notifification pipe + K3ProcessController::instance()->unscheduleCheck(); + if (waitpid(pid_, &status, WNOHANG) != 0) { // error finishes, too + commClose(); // this time for real (runs is false) + K3ProcessController::instance()->rescheduleCheck(); + break; + } + runs = true; // for next commClose() iteration + } else { + // commClose is an obsolete reimplementation and waited until + // all output channels were closed (or it was interrupted). + // there is a chance that it never gets here ... + waitpid(pid_, &status, 0); + runs = false; + break; + } + } + // why do we do this? i think this signal should be emitted _only_ + // after the process has successfully run _asynchronously_ --ossi + emit processExited(this); + break; + default: // NotifyOnExit & OwnGroup + input_data = 0; // Discard any data for stdin that might still be there + break; + } + return true; } bool K3Process::kill(int signo) { - if (runs && pid_ > 0 && !::kill(run_mode == OwnGroup ? -pid_ : pid_, signo)) - return true; - return false; + if (runs && pid_ > 0 && !::kill(run_mode == OwnGroup ? -pid_ : pid_, signo)) + return true; + return false; } bool K3Process::isRunning() const { - return runs; + return runs; } pid_t K3Process::pid() const { - return pid_; + return pid_; } #ifndef timersub @@ -468,193 +452,188 @@ pid_t K3Process::pid() const bool K3Process::wait(int timeout) { - if (!runs) - return true; - -#ifndef __linux__ - struct timeval etv; -#endif - struct timeval tv, *tvp; - if (timeout < 0) - tvp = 0; - else - { -#ifndef __linux__ - gettimeofday(&etv, 0); - etv.tv_sec += timeout; -#else - tv.tv_sec = timeout; - tv.tv_usec = 0; -#endif - tvp = &tv; - } - - int fd = K3ProcessController::instance()->notifierFd(); - for(;;) - { - fd_set fds; - FD_ZERO( &fds ); - FD_SET( fd, &fds ); - -#ifndef __linux__ - if (tvp) - { - gettimeofday(&tv, 0); - timersub(&etv, &tv, &tv); - if (tv.tv_sec < 0) - tv.tv_sec = tv.tv_usec = 0; - } -#endif - - switch( select( fd+1, &fds, 0, 0, tvp ) ) - { - case -1: - if( errno == EINTR ) - break; - // fall through; should happen if tvp->tv_sec < 0 - case 0: - K3ProcessController::instance()->rescheduleCheck(); - return false; - default: - K3ProcessController::instance()->unscheduleCheck(); - if (waitpid(pid_, &status, WNOHANG) != 0) // error finishes, too - { - processHasExited(status); - K3ProcessController::instance()->rescheduleCheck(); + if (!runs) return true; - } + +#ifndef __linux__ + struct timeval etv; +#endif + struct timeval tv, *tvp; + if (timeout < 0) + tvp = 0; + else { +#ifndef __linux__ + gettimeofday(&etv, 0); + etv.tv_sec += timeout; +#else + tv.tv_sec = timeout; + tv.tv_usec = 0; +#endif + tvp = &tv; } - } - return false; + + int fd = K3ProcessController::instance()->notifierFd(); + for (;;) { + fd_set fds; + FD_ZERO( &fds ); + FD_SET( fd, &fds ); + +#ifndef __linux__ + if (tvp) { + gettimeofday(&tv, 0); + timersub(&etv, &tv, &tv); + if (tv.tv_sec < 0) + tv.tv_sec = tv.tv_usec = 0; + } +#endif + + switch ( select( fd+1, &fds, 0, 0, tvp ) ) { + case -1: + if ( errno == EINTR ) + break; + // fall through; should happen if tvp->tv_sec < 0 + case 0: + K3ProcessController::instance()->rescheduleCheck(); + return false; + default: + K3ProcessController::instance()->unscheduleCheck(); + if (waitpid(pid_, &status, WNOHANG) != 0) { // error finishes, too + processHasExited(status); + K3ProcessController::instance()->rescheduleCheck(); + return true; + } + } + } + return false; } bool K3Process::normalExit() const { - return (pid_ != 0) && !runs && WIFEXITED(status); + return (pid_ != 0) && !runs && WIFEXITED(status); } bool K3Process::signalled() const { - return (pid_ != 0) && !runs && WIFSIGNALED(status); + return (pid_ != 0) && !runs && WIFSIGNALED(status); } bool K3Process::coreDumped() const { #ifdef WCOREDUMP - return signalled() && WCOREDUMP(status); + return signalled() && WCOREDUMP(status); #else - return false; + return false; #endif } int K3Process::exitStatus() const { - return WEXITSTATUS(status); + return WEXITSTATUS(status); } int K3Process::exitSignal() const { - return WTERMSIG(status); + return WTERMSIG(status); } bool K3Process::writeStdin(const char *buffer, int buflen) { - // if there is still data pending, writing new data - // to stdout is not allowed (since it could also confuse - // kprocess ...) - if (input_data != 0) - return false; + // if there is still data pending, writing new data + // to stdout is not allowed (since it could also confuse + // kprocess ...) + if (input_data != 0) + return false; - if (communication & Stdin) { - input_data = buffer; - input_sent = 0; - input_total = buflen; - innot->setEnabled(true); - if (input_total) - slotSendData(0); - return true; - } else - return false; + if (communication & Stdin) { + input_data = buffer; + input_sent = 0; + input_total = buflen; + innot->setEnabled(true); + if (input_total) + slotSendData(0); + return true; + } else + return false; } void K3Process::suspend() { - if (outnot) - outnot->setEnabled(false); + if (outnot) + outnot->setEnabled(false); } void K3Process::resume() { - if (outnot) - outnot->setEnabled(true); + if (outnot) + outnot->setEnabled(true); } bool K3Process::closeStdin() { - if (communication & Stdin) { - communication = communication & ~Stdin; - delete innot; - innot = 0; - if (!(d->usePty & Stdin)) - close(in[1]); - in[1] = -1; - return true; - } else - return false; + if (communication & Stdin) { + communication = communication & ~Stdin; + delete innot; + innot = 0; + if (!(d->usePty & Stdin)) + close(in[1]); + in[1] = -1; + return true; + } else + return false; } bool K3Process::closeStdout() { - if (communication & Stdout) { - communication = communication & ~Stdout; - delete outnot; - outnot = 0; - if (!(d->usePty & Stdout)) - close(out[0]); - out[0] = -1; - return true; - } else - return false; + if (communication & Stdout) { + communication = communication & ~Stdout; + delete outnot; + outnot = 0; + if (!(d->usePty & Stdout)) + close(out[0]); + out[0] = -1; + return true; + } else + return false; } bool K3Process::closeStderr() { - if (communication & Stderr) { - communication = communication & ~Stderr; - delete errnot; - errnot = 0; - if (!(d->usePty & Stderr)) - close(err[0]); - err[0] = -1; - return true; - } else - return false; + if (communication & Stderr) { + communication = communication & ~Stderr; + delete errnot; + errnot = 0; + if (!(d->usePty & Stderr)) + close(err[0]); + err[0] = -1; + return true; + } else + return false; } bool K3Process::closePty() { - if (d->pty && d->pty->masterFd() >= 0) { - if (d->addUtmp) - d->pty->logout(); - d->pty->close(); - return true; - } else - return false; + if (d->pty && d->pty->masterFd() >= 0) { + if (d->addUtmp) + d->pty->logout(); + d->pty->close(); + return true; + } else + return false; } void K3Process::closeAll() { - closeStdin(); - closeStdout(); - closeStderr(); - closePty(); + closeStdin(); + closeStdout(); + closeStderr(); + closePty(); } ///////////////////////////// @@ -665,78 +644,75 @@ void K3Process::closeAll() void K3Process::slotChildOutput(int fdno) { - if (!childOutput(fdno)) - closeStdout(); + if (!childOutput(fdno)) + closeStdout(); } void K3Process::slotChildError(int fdno) { - if (!childError(fdno)) - closeStderr(); + if (!childError(fdno)) + closeStderr(); } void K3Process::slotSendData(int) { - if (input_sent == input_total) { - innot->setEnabled(false); - input_data = 0; - emit wroteStdin(this); - } else { - int result = ::write(in[1], input_data+input_sent, input_total-input_sent); - if (result >= 0) - { - input_sent += result; + if (input_sent == input_total) { + innot->setEnabled(false); + input_data = 0; + emit wroteStdin(this); + } else { + int result = ::write(in[1], input_data+input_sent, input_total-input_sent); + if (result >= 0) { + input_sent += result; + } else if ((errno != EAGAIN) && (errno != EINTR)) { + qDebug() << "Error writing to stdin of child process" << endl; + closeStdin(); + } } - else if ((errno != EAGAIN) && (errno != EINTR)) - { - qDebug() << "Error writing to stdin of child process" << endl; - closeStdin(); - } - } } void K3Process::setUseShell(bool useShell, const char *shell) { - d->useShell = useShell; - if (shell && *shell) - d->shell = shell; - else + d->useShell = useShell; + if (shell && *shell) + d->shell = shell; + else // #ifdef NON_FREE // ... as they ship non-POSIX /bin/sh #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__GNU__) && !defined(__DragonFly__) - // Solaris POSIX ... - if (!access( "/usr/xpg4/bin/sh", X_OK )) - d->shell = "/usr/xpg4/bin/sh"; - else - // ... which links here anyway - if (!access( "/bin/ksh", X_OK )) - d->shell = "/bin/ksh"; - else - // dunno, maybe superfluous? - if (!access( "/usr/ucb/sh", X_OK )) - d->shell = "/usr/ucb/sh"; - else + // Solaris POSIX ... + if (!access( "/usr/xpg4/bin/sh", X_OK )) + d->shell = "/usr/xpg4/bin/sh"; + else + // ... which links here anyway + if (!access( "/bin/ksh", X_OK )) + d->shell = "/bin/ksh"; + else + // dunno, maybe superfluous? + if (!access( "/usr/ucb/sh", X_OK )) + d->shell = "/usr/ucb/sh"; + else #endif - d->shell = "/bin/sh"; + d->shell = "/bin/sh"; } void K3Process::setUsePty(Communication usePty, bool addUtmp) { - d->usePty = usePty; - d->addUtmp = addUtmp; - if (usePty) { - if (!d->pty) - d->pty = new KPty; - } else { - delete d->pty; - d->pty = 0; - } + d->usePty = usePty; + d->addUtmp = addUtmp; + if (usePty) { + if (!d->pty) + d->pty = new KPty; + } else { + delete d->pty; + d->pty = 0; + } } KPty *K3Process::pty() const { - return d->pty; + return d->pty; } QString K3Process::quote(const QString &arg) @@ -761,272 +737,267 @@ void K3Process::processHasExited(int state) commClose(); // cleanup communication sockets if (run_mode != DontCare) - emit processExited(this); + emit processExited(this); } int K3Process::childOutput(int fdno) { - if (communication & NoRead) { - int len = -1; - emit receivedStdout(fdno, len); - errno = 0; // Make sure errno doesn't read "EAGAIN" - return len; - } - else - { - char buffer[1025]; - int len; + if (communication & NoRead) { + int len = -1; + emit receivedStdout(fdno, len); + errno = 0; // Make sure errno doesn't read "EAGAIN" + return len; + } else { + char buffer[1025]; + int len; - len = ::read(fdno, buffer, 1024); + len = ::read(fdno, buffer, 1024); - if (len > 0) { - buffer[len] = 0; // Just in case. - emit receivedStdout(this, buffer, len); - } - return len; - } + if (len > 0) { + buffer[len] = 0; // Just in case. + emit receivedStdout(this, buffer, len); + } + return len; + } } int K3Process::childError(int fdno) { - char buffer[1025]; - int len; + char buffer[1025]; + int len; - len = ::read(fdno, buffer, 1024); + len = ::read(fdno, buffer, 1024); - if (len > 0) { - buffer[len] = 0; // Just in case. - emit receivedStderr(this, buffer, len); - } - return len; + if (len > 0) { + buffer[len] = 0; // Just in case. + emit receivedStderr(this, buffer, len); + } + return len; } int K3Process::setupCommunication(Communication comm) { - // PTY stuff // - if (d->usePty) - { - // cannot communicate on both stderr and stdout if they are both on the pty - if (!(~(comm & d->usePty) & (Stdout | Stderr))) { - qWarning() << "Invalid usePty/communication combination (" << d->usePty << "/" << comm << ")" << endl; - return 0; + // PTY stuff // + if (d->usePty) { + // cannot communicate on both stderr and stdout if they are both on the pty + if (!(~(comm & d->usePty) & (Stdout | Stderr))) { + qWarning() << "Invalid usePty/communication combination (" << d->usePty << "/" << comm << ")" << endl; + return 0; + } + if (!d->pty->open()) + return 0; + + int rcomm = comm & d->usePty; + int mfd = d->pty->masterFd(); + if (rcomm & Stdin) + in[1] = mfd; + if (rcomm & Stdout) + out[0] = mfd; + if (rcomm & Stderr) + err[0] = mfd; } - if (!d->pty->open()) - return 0; - int rcomm = comm & d->usePty; - int mfd = d->pty->masterFd(); - if (rcomm & Stdin) - in[1] = mfd; - if (rcomm & Stdout) - out[0] = mfd; - if (rcomm & Stderr) - err[0] = mfd; - } + communication = comm; - communication = comm; - - comm = comm & ~d->usePty; - if (comm & Stdin) { - if (socketpair(AF_UNIX, SOCK_STREAM, 0, in)) - goto fail0; - fcntl(in[0], F_SETFD, FD_CLOEXEC); - fcntl(in[1], F_SETFD, FD_CLOEXEC); - } - if (comm & Stdout) { - if (socketpair(AF_UNIX, SOCK_STREAM, 0, out)) - goto fail1; - fcntl(out[0], F_SETFD, FD_CLOEXEC); - fcntl(out[1], F_SETFD, FD_CLOEXEC); - } - if (comm & Stderr) { - if (socketpair(AF_UNIX, SOCK_STREAM, 0, err)) - goto fail2; - fcntl(err[0], F_SETFD, FD_CLOEXEC); - fcntl(err[1], F_SETFD, FD_CLOEXEC); - } - return 1; // Ok - fail2: - if (comm & Stdout) - { - close(out[0]); - close(out[1]); - out[0] = out[1] = -1; - } - fail1: - if (comm & Stdin) - { - close(in[0]); - close(in[1]); - in[0] = in[1] = -1; - } - fail0: - communication = NoCommunication; - return 0; // Error + comm = comm & ~d->usePty; + if (comm & Stdin) { + if (socketpair(AF_UNIX, SOCK_STREAM, 0, in)) + goto fail0; + fcntl(in[0], F_SETFD, FD_CLOEXEC); + fcntl(in[1], F_SETFD, FD_CLOEXEC); + } + if (comm & Stdout) { + if (socketpair(AF_UNIX, SOCK_STREAM, 0, out)) + goto fail1; + fcntl(out[0], F_SETFD, FD_CLOEXEC); + fcntl(out[1], F_SETFD, FD_CLOEXEC); + } + if (comm & Stderr) { + if (socketpair(AF_UNIX, SOCK_STREAM, 0, err)) + goto fail2; + fcntl(err[0], F_SETFD, FD_CLOEXEC); + fcntl(err[1], F_SETFD, FD_CLOEXEC); + } + return 1; // Ok +fail2: + if (comm & Stdout) { + close(out[0]); + close(out[1]); + out[0] = out[1] = -1; + } +fail1: + if (comm & Stdin) { + close(in[0]); + close(in[1]); + in[0] = in[1] = -1; + } +fail0: + communication = NoCommunication; + return 0; // Error } int K3Process::commSetupDoneP() { - int rcomm = communication & ~d->usePty; - if (rcomm & Stdin) - close(in[0]); - if (rcomm & Stdout) - close(out[1]); - if (rcomm & Stderr) - close(err[1]); - in[0] = out[1] = err[1] = -1; + int rcomm = communication & ~d->usePty; + if (rcomm & Stdin) + close(in[0]); + if (rcomm & Stdout) + close(out[1]); + if (rcomm & Stderr) + close(err[1]); + in[0] = out[1] = err[1] = -1; + + // Don't create socket notifiers if no interactive comm is to be expected + if (run_mode != NotifyOnExit && run_mode != OwnGroup) + return 1; + + if (communication & Stdin) { + fcntl(in[1], F_SETFL, O_NONBLOCK | fcntl(in[1], F_GETFL)); + innot = new QSocketNotifier(in[1], QSocketNotifier::Write, this); + Q_CHECK_PTR(innot); + innot->setEnabled(false); // will be enabled when data has to be sent + QObject::connect(innot, SIGNAL(activated(int)), + this, SLOT(slotSendData(int))); + } + + if (communication & Stdout) { + outnot = new QSocketNotifier(out[0], QSocketNotifier::Read, this); + Q_CHECK_PTR(outnot); + QObject::connect(outnot, SIGNAL(activated(int)), + this, SLOT(slotChildOutput(int))); + if (communication & NoRead) + suspend(); + } + + if (communication & Stderr) { + errnot = new QSocketNotifier(err[0], QSocketNotifier::Read, this ); + Q_CHECK_PTR(errnot); + QObject::connect(errnot, SIGNAL(activated(int)), + this, SLOT(slotChildError(int))); + } - // Don't create socket notifiers if no interactive comm is to be expected - if (run_mode != NotifyOnExit && run_mode != OwnGroup) return 1; - - if (communication & Stdin) { - fcntl(in[1], F_SETFL, O_NONBLOCK | fcntl(in[1], F_GETFL)); - innot = new QSocketNotifier(in[1], QSocketNotifier::Write, this); - Q_CHECK_PTR(innot); - innot->setEnabled(false); // will be enabled when data has to be sent - QObject::connect(innot, SIGNAL(activated(int)), - this, SLOT(slotSendData(int))); - } - - if (communication & Stdout) { - outnot = new QSocketNotifier(out[0], QSocketNotifier::Read, this); - Q_CHECK_PTR(outnot); - QObject::connect(outnot, SIGNAL(activated(int)), - this, SLOT(slotChildOutput(int))); - if (communication & NoRead) - suspend(); - } - - if (communication & Stderr) { - errnot = new QSocketNotifier(err[0], QSocketNotifier::Read, this ); - Q_CHECK_PTR(errnot); - QObject::connect(errnot, SIGNAL(activated(int)), - this, SLOT(slotChildError(int))); - } - - return 1; } int K3Process::commSetupDoneC() { - int ok = 1; - if (d->usePty & Stdin) { - if (dup2(d->pty->slaveFd(), STDIN_FILENO) < 0) ok = 0; - } else if (communication & Stdin) { - if (dup2(in[0], STDIN_FILENO) < 0) ok = 0; - } else { - int null_fd = open( "/dev/null", O_RDONLY ); - if (dup2( null_fd, STDIN_FILENO ) < 0) ok = 0; - close( null_fd ); - } - struct linger so; - memset(&so, 0, sizeof(so)); - if (d->usePty & Stdout) { - if (dup2(d->pty->slaveFd(), STDOUT_FILENO) < 0) ok = 0; - } else if (communication & Stdout) { - if (dup2(out[1], STDOUT_FILENO) < 0 || - setsockopt(out[1], SOL_SOCKET, SO_LINGER, (char *)&so, sizeof(so))) - ok = 0; - if (communication & MergedStderr) { - if (dup2(out[1], STDERR_FILENO) < 0) - ok = 0; + int ok = 1; + if (d->usePty & Stdin) { + if (dup2(d->pty->slaveFd(), STDIN_FILENO) < 0) ok = 0; + } else if (communication & Stdin) { + if (dup2(in[0], STDIN_FILENO) < 0) ok = 0; + } else { + int null_fd = open( "/dev/null", O_RDONLY ); + if (dup2( null_fd, STDIN_FILENO ) < 0) ok = 0; + close( null_fd ); + } + struct linger so; + memset(&so, 0, sizeof(so)); + if (d->usePty & Stdout) { + if (dup2(d->pty->slaveFd(), STDOUT_FILENO) < 0) ok = 0; + } else if (communication & Stdout) { + if (dup2(out[1], STDOUT_FILENO) < 0 || + setsockopt(out[1], SOL_SOCKET, SO_LINGER, (char *)&so, sizeof(so))) + ok = 0; + if (communication & MergedStderr) { + if (dup2(out[1], STDERR_FILENO) < 0) + ok = 0; + } + } + if (d->usePty & Stderr) { + if (dup2(d->pty->slaveFd(), STDERR_FILENO) < 0) ok = 0; + } else if (communication & Stderr) { + if (dup2(err[1], STDERR_FILENO) < 0 || + setsockopt(err[1], SOL_SOCKET, SO_LINGER, (char *)&so, sizeof(so))) + ok = 0; } - } - if (d->usePty & Stderr) { - if (dup2(d->pty->slaveFd(), STDERR_FILENO) < 0) ok = 0; - } else if (communication & Stderr) { - if (dup2(err[1], STDERR_FILENO) < 0 || - setsockopt(err[1], SOL_SOCKET, SO_LINGER, (char *)&so, sizeof(so))) - ok = 0; - } - // don't even think about closing all open fds here or anywhere else + // don't even think about closing all open fds here or anywhere else - // PTY stuff // - if (d->usePty) { - d->pty->setCTty(); - if (d->addUtmp) - d->pty->login(getenv("USER"), getenv("DISPLAY")); - } + // PTY stuff // + if (d->usePty) { + d->pty->setCTty(); + if (d->addUtmp) + d->pty->login(getenv("USER"), getenv("DISPLAY")); + } - return ok; + return ok; } void K3Process::commClose() { - closeStdin(); + closeStdin(); - if (pid_) { // detached, failed, and killed processes have no output. basta. :) - // If both channels are being read we need to make sure that one socket - // buffer doesn't fill up whilst we are waiting for data on the other - // (causing a deadlock). Hence we need to use select. + if (pid_) { // detached, failed, and killed processes have no output. basta. :) + // If both channels are being read we need to make sure that one socket + // buffer doesn't fill up whilst we are waiting for data on the other + // (causing a deadlock). Hence we need to use select. - int notfd = K3ProcessController::instance()->notifierFd(); + int notfd = K3ProcessController::instance()->notifierFd(); - while ((communication & (Stdout | Stderr)) || runs) { - fd_set rfds; - FD_ZERO(&rfds); - struct timeval timeout, *p_timeout; + while ((communication & (Stdout | Stderr)) || runs) { + fd_set rfds; + FD_ZERO(&rfds); + struct timeval timeout, *p_timeout; - int max_fd = 0; - if (communication & Stdout) { - FD_SET(out[0], &rfds); - max_fd = out[0]; - } - if (communication & Stderr) { - FD_SET(err[0], &rfds); - if (err[0] > max_fd) - max_fd = err[0]; - } - if (runs) { - FD_SET(notfd, &rfds); - if (notfd > max_fd) - max_fd = notfd; - // If the process is still running we block until we - // receive data or the process exits. - p_timeout = 0; // no timeout - } else { - // If the process has already exited, we only check - // the available data, we don't wait for more. - timeout.tv_sec = timeout.tv_usec = 0; // timeout immediately - p_timeout = &timeout; - } + int max_fd = 0; + if (communication & Stdout) { + FD_SET(out[0], &rfds); + max_fd = out[0]; + } + if (communication & Stderr) { + FD_SET(err[0], &rfds); + if (err[0] > max_fd) + max_fd = err[0]; + } + if (runs) { + FD_SET(notfd, &rfds); + if (notfd > max_fd) + max_fd = notfd; + // If the process is still running we block until we + // receive data or the process exits. + p_timeout = 0; // no timeout + } else { + // If the process has already exited, we only check + // the available data, we don't wait for more. + timeout.tv_sec = timeout.tv_usec = 0; // timeout immediately + p_timeout = &timeout; + } - int fds_ready = select(max_fd+1, &rfds, 0, 0, p_timeout); - if (fds_ready < 0) { - if (errno == EINTR) - continue; - break; - } else if (!fds_ready) - break; + int fds_ready = select(max_fd+1, &rfds, 0, 0, p_timeout); + if (fds_ready < 0) { + if (errno == EINTR) + continue; + break; + } else if (!fds_ready) + break; - if ((communication & Stdout) && FD_ISSET(out[0], &rfds)) - slotChildOutput(out[0]); + if ((communication & Stdout) && FD_ISSET(out[0], &rfds)) + slotChildOutput(out[0]); - if ((communication & Stderr) && FD_ISSET(err[0], &rfds)) - slotChildError(err[0]); + if ((communication & Stderr) && FD_ISSET(err[0], &rfds)) + slotChildError(err[0]); - if (runs && FD_ISSET(notfd, &rfds)) { - runs = false; // hack: signal potential exit - return; // don't close anything, we will be called again - } + if (runs && FD_ISSET(notfd, &rfds)) { + runs = false; // hack: signal potential exit + return; // don't close anything, we will be called again + } + } } - } - closeStdout(); - closeStderr(); + closeStdout(); + closeStderr(); - closePty(); + closePty(); } @@ -1036,12 +1007,13 @@ void K3Process::commClose() /////////////////////////// K3ShellProcess::K3ShellProcess(const char *shellname): - K3Process(), d(0) + K3Process(), d(0) { - setUseShell( true, shellname ? shellname : getenv("SHELL") ); + setUseShell( true, shellname ? shellname : getenv("SHELL") ); } -K3ShellProcess::~K3ShellProcess() { +K3ShellProcess::~K3ShellProcess() +{ } QString K3ShellProcess::quote(const QString &arg) @@ -1051,7 +1023,7 @@ QString K3ShellProcess::quote(const QString &arg) bool K3ShellProcess::start(RunMode runmode, Communication comm) { - return K3Process::start(runmode, comm); + return K3Process::start(runmode, comm); } diff --git a/lib/k3process.h b/lib/k3process.h index f8388ea..1d0fc72 100644 --- a/lib/k3process.h +++ b/lib/k3process.h @@ -126,722 +126,725 @@ class KPty; **/ class K3Process : public QObject { - Q_OBJECT + Q_OBJECT public: - /** - * Modes in which the communication channels can be opened. - * - * If communication for more than one channel is required, - * the values should be or'ed together, for example to get - * communication with stdout as well as with stdin, you would - * specify @p Stdin | @p Stdout - * - */ - enum CommunicationFlag { - NoCommunication = 0, /**< No communication with the process. */ - Stdin = 1, /**< Connect to write to the process with writeStdin(). */ - Stdout = 2, /**< Connect to read from the process' output. */ - Stderr = 4, /**< Connect to read from the process' stderr. */ - AllOutput = 6, /**< Connects to all output channels. */ - All = 7, /**< Connects to all channels. */ - NoRead = 8, /**< If specified with Stdout, no data is actually read from stdout, + /** + * Modes in which the communication channels can be opened. + * + * If communication for more than one channel is required, + * the values should be or'ed together, for example to get + * communication with stdout as well as with stdin, you would + * specify @p Stdin | @p Stdout + * + */ + enum CommunicationFlag { + NoCommunication = 0, /**< No communication with the process. */ + Stdin = 1, /**< Connect to write to the process with writeStdin(). */ + Stdout = 2, /**< Connect to read from the process' output. */ + Stderr = 4, /**< Connect to read from the process' stderr. */ + AllOutput = 6, /**< Connects to all output channels. */ + All = 7, /**< Connects to all channels. */ + NoRead = 8, /**< If specified with Stdout, no data is actually read from stdout, * only the signal receivedStdout(int fd, int &len) is emitted. */ - CTtyOnly = NoRead, /**< Tells setUsePty() to create a PTY for the process + CTtyOnly = NoRead, /**< Tells setUsePty() to create a PTY for the process * and make it the process' controlling TTY, but does not * redirect any I/O channel to the PTY. */ - MergedStderr = 16 /**< If specified with Stdout, the process' stderr will be + MergedStderr = 16 /**< If specified with Stdout, the process' stderr will be * redirected onto the same file handle as its stdout, i.e., * all error output will be signalled with receivedStdout(). * Don't specify Stderr if you specify MergedStderr. */ - }; + }; - Q_DECLARE_FLAGS(Communication, CommunicationFlag) + Q_DECLARE_FLAGS(Communication, CommunicationFlag) - /** - * Run-modes for a child process. - */ - enum RunMode { - /** - * The application does not receive notifications from the subprocess when - * it is finished or aborted. - */ - DontCare, - /** - * The application is notified when the subprocess dies. - */ - NotifyOnExit, - /** - * The application is suspended until the started process is finished. - */ - Block, - /** - * Same as NotifyOnExit, but the process is run in an own session, - * just like with DontCare. - */ - OwnGroup - }; + /** + * Run-modes for a child process. + */ + enum RunMode { + /** + * The application does not receive notifications from the subprocess when + * it is finished or aborted. + */ + DontCare, + /** + * The application is notified when the subprocess dies. + */ + NotifyOnExit, + /** + * The application is suspended until the started process is finished. + */ + Block, + /** + * Same as NotifyOnExit, but the process is run in an own session, + * just like with DontCare. + */ + OwnGroup + }; - /** - * Constructor - */ - explicit K3Process( QObject* parent=0L ); + /** + * Constructor + */ + explicit K3Process( QObject* parent=0L ); - /** - *Destructor: - * - * If the process is running when the destructor for this class - * is called, the child process is killed with a SIGKILL, but - * only if the run mode is not of type @p DontCare. - * Processes started as @p DontCare keep running anyway. - */ - virtual ~K3Process(); + /** + *Destructor: + * + * If the process is running when the destructor for this class + * is called, the child process is killed with a SIGKILL, but + * only if the run mode is not of type @p DontCare. + * Processes started as @p DontCare keep running anyway. + */ + virtual ~K3Process(); - /** - * Sets the executable and the command line argument list for this process. - * - * For example, doing an "ls -l /usr/local/bin" can be achieved by: - * \code - * K3Process p; - * ... - * p << "ls" << "-l" << "/usr/local/bin" - * \endcode - * - * @param arg the argument to add - * @return a reference to this K3Process - **/ - K3Process &operator<<(const QString& arg); - /** - * Similar to previous method, takes a char *, supposed to be in locale 8 bit already. - */ - K3Process &operator<<(const char * arg); - /** - * Similar to previous method, takes a QByteArray, supposed to be in locale 8 bit already. - * @param arg the argument to add - * @return a reference to this K3Process - */ - K3Process &operator<<(const QByteArray & arg); + /** + * Sets the executable and the command line argument list for this process. + * + * For example, doing an "ls -l /usr/local/bin" can be achieved by: + * \code + * K3Process p; + * ... + * p << "ls" << "-l" << "/usr/local/bin" + * \endcode + * + * @param arg the argument to add + * @return a reference to this K3Process + **/ + K3Process &operator<<(const QString& arg); + /** + * Similar to previous method, takes a char *, supposed to be in locale 8 bit already. + */ + K3Process &operator<<(const char * arg); + /** + * Similar to previous method, takes a QByteArray, supposed to be in locale 8 bit already. + * @param arg the argument to add + * @return a reference to this K3Process + */ + K3Process &operator<<(const QByteArray & arg); - /** - * Sets the executable and the command line argument list for this process, - * in a single method call, or add a list of arguments. - * @param args the arguments to add - * @return a reference to this K3Process - **/ - K3Process &operator<<(const QStringList& args); + /** + * Sets the executable and the command line argument list for this process, + * in a single method call, or add a list of arguments. + * @param args the arguments to add + * @return a reference to this K3Process + **/ + K3Process &operator<<(const QStringList& args); - /** - * Clear a command line argument list that has been set by using - * operator<<. - */ - void clearArguments(); + /** + * Clear a command line argument list that has been set by using + * operator<<. + */ + void clearArguments(); - /** - * Starts the process. - * For a detailed description of the - * various run modes and communication semantics, have a look at the - * general description of the K3Process class. Note that if you use - * setUsePty( Stdout | Stderr, \ ), you cannot use Stdout | Stderr - * here - instead, use Stdout only to receive the mixed output. - * - * The following problems could cause this function to - * return false: - * - * @li The process is already running. - * @li The command line argument list is empty. - * @li The the @p comm parameter is incompatible with the selected pty usage. - * @li The starting of the process failed (could not fork). - * @li The executable was not found. - * - * @param runmode The Run-mode for the process. - * @param comm Specifies which communication channels should be - * established to the child process (stdin/stdout/stderr). By default, - * no communication takes place and the respective communication - * signals will never get emitted. - * - * @return true on success, false on error - * (see above for error conditions) - **/ - virtual bool start(RunMode runmode = NotifyOnExit, - Communication comm = NoCommunication); + /** + * Starts the process. + * For a detailed description of the + * various run modes and communication semantics, have a look at the + * general description of the K3Process class. Note that if you use + * setUsePty( Stdout | Stderr, \ ), you cannot use Stdout | Stderr + * here - instead, use Stdout only to receive the mixed output. + * + * The following problems could cause this function to + * return false: + * + * @li The process is already running. + * @li The command line argument list is empty. + * @li The the @p comm parameter is incompatible with the selected pty usage. + * @li The starting of the process failed (could not fork). + * @li The executable was not found. + * + * @param runmode The Run-mode for the process. + * @param comm Specifies which communication channels should be + * established to the child process (stdin/stdout/stderr). By default, + * no communication takes place and the respective communication + * signals will never get emitted. + * + * @return true on success, false on error + * (see above for error conditions) + **/ + virtual bool start(RunMode runmode = NotifyOnExit, + Communication comm = NoCommunication); - /** - * Stop the process (by sending it a signal). - * - * @param signo The signal to send. The default is SIGTERM. - * @return true if the signal was delivered successfully. - */ - virtual bool kill(int signo = SIGTERM); + /** + * Stop the process (by sending it a signal). + * + * @param signo The signal to send. The default is SIGTERM. + * @return true if the signal was delivered successfully. + */ + virtual bool kill(int signo = SIGTERM); - /** - * Checks whether the process is running. - * @return true if the process is (still) considered to be running - */ - bool isRunning() const; + /** + * Checks whether the process is running. + * @return true if the process is (still) considered to be running + */ + bool isRunning() const; - /** Returns the process id of the process. - * - * If it is called after - * the process has exited, it returns the process id of the last - * child process that was created by this instance of K3Process. - * - * Calling it before any child process has been started by this - * K3Process instance causes pid() to return 0. - * @return the pid of the process or 0 if no process has been started yet. - **/ - pid_t pid() const; + /** Returns the process id of the process. + * + * If it is called after + * the process has exited, it returns the process id of the last + * child process that was created by this instance of K3Process. + * + * Calling it before any child process has been started by this + * K3Process instance causes pid() to return 0. + * @return the pid of the process or 0 if no process has been started yet. + **/ + pid_t pid() const; - /** - * Suspend processing of data from stdout of the child process. - */ - void suspend(); + /** + * Suspend processing of data from stdout of the child process. + */ + void suspend(); - /** - * Resume processing of data from stdout of the child process. - */ - void resume(); + /** + * Resume processing of data from stdout of the child process. + */ + void resume(); - /** - * Suspend execution of the current thread until the child process dies - * or the timeout hits. This function is not recommended for programs - * with a GUI. - * @param timeout timeout in seconds. -1 means wait indefinitely. - * @return true if the process exited, false if the timeout hit. - */ - bool wait(int timeout = -1); + /** + * Suspend execution of the current thread until the child process dies + * or the timeout hits. This function is not recommended for programs + * with a GUI. + * @param timeout timeout in seconds. -1 means wait indefinitely. + * @return true if the process exited, false if the timeout hit. + */ + bool wait(int timeout = -1); - /** - * Checks whether the process exited cleanly. - * - * @return true if the process has already finished and has exited - * "voluntarily", ie: it has not been killed by a signal. - */ - bool normalExit() const; + /** + * Checks whether the process exited cleanly. + * + * @return true if the process has already finished and has exited + * "voluntarily", ie: it has not been killed by a signal. + */ + bool normalExit() const; - /** - * Checks whether the process was killed by a signal. - * - * @return true if the process has already finished and has not exited - * "voluntarily", ie: it has been killed by a signal. - */ - bool signalled() const; + /** + * Checks whether the process was killed by a signal. + * + * @return true if the process has already finished and has not exited + * "voluntarily", ie: it has been killed by a signal. + */ + bool signalled() const; - /** - * Checks whether a killed process dumped core. - * - * @return true if signalled() returns true and the process - * dumped core. Note that on systems that don't define the - * WCOREDUMP macro, the return value is always false. - */ - bool coreDumped() const; + /** + * Checks whether a killed process dumped core. + * + * @return true if signalled() returns true and the process + * dumped core. Note that on systems that don't define the + * WCOREDUMP macro, the return value is always false. + */ + bool coreDumped() const; - /** - * Returns the exit status of the process. - * - * @return the exit status of the process. Note that this value - * is not valid if normalExit() returns false. - */ - int exitStatus() const; + /** + * Returns the exit status of the process. + * + * @return the exit status of the process. Note that this value + * is not valid if normalExit() returns false. + */ + int exitStatus() const; - /** - * Returns the signal the process was killed by. - * - * @return the signal number that caused the process to exit. - * Note that this value is not valid if signalled() returns false. - */ - int exitSignal() const; + /** + * Returns the signal the process was killed by. + * + * @return the signal number that caused the process to exit. + * Note that this value is not valid if signalled() returns false. + */ + int exitSignal() const; - /** - * Transmit data to the child process' stdin. - * - * This function may return false in the following cases: - * - * @li The process is not currently running. - * This implies that you cannot use this function in Block mode. - * - * @li Communication to stdin has not been requested in the start() call. - * - * @li Transmission of data to the child process by a previous call to - * writeStdin() is still in progress. - * - * Please note that the data is sent to the client asynchronously, - * so when this function returns, the data might not have been - * processed by the child process. - * That means that you must not free @p buffer or call writeStdin() - * again until either a wroteStdin() signal indicates that the - * data has been sent or a processExited() signal shows that - * the child process is no longer alive. - * - * If all the data has been sent to the client, the signal - * wroteStdin() will be emitted. - * - * This function does not work when the process is start()ed in Block mode. - * - * @param buffer the buffer to write - * @param buflen the length of the buffer - * @return false if an error has occurred - **/ - bool writeStdin(const char *buffer, int buflen); + /** + * Transmit data to the child process' stdin. + * + * This function may return false in the following cases: + * + * @li The process is not currently running. + * This implies that you cannot use this function in Block mode. + * + * @li Communication to stdin has not been requested in the start() call. + * + * @li Transmission of data to the child process by a previous call to + * writeStdin() is still in progress. + * + * Please note that the data is sent to the client asynchronously, + * so when this function returns, the data might not have been + * processed by the child process. + * That means that you must not free @p buffer or call writeStdin() + * again until either a wroteStdin() signal indicates that the + * data has been sent or a processExited() signal shows that + * the child process is no longer alive. + * + * If all the data has been sent to the client, the signal + * wroteStdin() will be emitted. + * + * This function does not work when the process is start()ed in Block mode. + * + * @param buffer the buffer to write + * @param buflen the length of the buffer + * @return false if an error has occurred + **/ + bool writeStdin(const char *buffer, int buflen); - /** - * Shuts down the Stdin communication link. If no pty is used, this - * causes "EOF" to be indicated on the child's stdin file descriptor. - * - * @return false if no Stdin communication link exists (any more). - */ - bool closeStdin(); + /** + * Shuts down the Stdin communication link. If no pty is used, this + * causes "EOF" to be indicated on the child's stdin file descriptor. + * + * @return false if no Stdin communication link exists (any more). + */ + bool closeStdin(); - /** - * Shuts down the Stdout communication link. If no pty is used, any further - * attempts by the child to write to its stdout file descriptor will cause - * it to receive a SIGPIPE. - * - * @return false if no Stdout communication link exists (any more). - */ - bool closeStdout(); + /** + * Shuts down the Stdout communication link. If no pty is used, any further + * attempts by the child to write to its stdout file descriptor will cause + * it to receive a SIGPIPE. + * + * @return false if no Stdout communication link exists (any more). + */ + bool closeStdout(); - /** - * Shuts down the Stderr communication link. If no pty is used, any further - * attempts by the child to write to its stderr file descriptor will cause - * it to receive a SIGPIPE. - * - * @return false if no Stderr communication link exists (any more). - */ - bool closeStderr(); + /** + * Shuts down the Stderr communication link. If no pty is used, any further + * attempts by the child to write to its stderr file descriptor will cause + * it to receive a SIGPIPE. + * + * @return false if no Stderr communication link exists (any more). + */ + bool closeStderr(); - /** - * Deletes the optional utmp entry and closes the pty. - * - * Make sure to shut down any communication links that are using the pty - * before calling this function. - * - * @return false if the pty is not open (any more). - */ - bool closePty(); + /** + * Deletes the optional utmp entry and closes the pty. + * + * Make sure to shut down any communication links that are using the pty + * before calling this function. + * + * @return false if the pty is not open (any more). + */ + bool closePty(); - /** - * @brief Close stdin, stdout, stderr and the pty - * - * This is the same that calling all close* functions in a row: - * @see closeStdin, @see closeStdout, @see closeStderr and @see closePty - */ - void closeAll(); + /** + * @brief Close stdin, stdout, stderr and the pty + * + * This is the same that calling all close* functions in a row: + * @see closeStdin, @see closeStdout, @see closeStderr and @see closePty + */ + void closeAll(); - /** - * Lets you see what your arguments are for debugging. - * @return the list of arguments - */ - const QList &args() /* const */ { return arguments; } + /** + * Lets you see what your arguments are for debugging. + * @return the list of arguments + */ + const QList &args() { /* const */ + return arguments; + } - /** - * Controls whether the started process should drop any - * setuid/setgid privileges or whether it should keep them. - * Note that this function is mostly a dummy, as the KDE libraries - * currently refuse to run with setuid/setgid privileges. - * - * The default is false: drop privileges - * @param keepPrivileges true to keep the privileges - */ - void setRunPrivileged(bool keepPrivileges); + /** + * Controls whether the started process should drop any + * setuid/setgid privileges or whether it should keep them. + * Note that this function is mostly a dummy, as the KDE libraries + * currently refuse to run with setuid/setgid privileges. + * + * The default is false: drop privileges + * @param keepPrivileges true to keep the privileges + */ + void setRunPrivileged(bool keepPrivileges); - /** - * Returns whether the started process will drop any - * setuid/setgid privileges or whether it will keep them. - * @return true if the process runs privileged - */ - bool runPrivileged() const; + /** + * Returns whether the started process will drop any + * setuid/setgid privileges or whether it will keep them. + * @return true if the process runs privileged + */ + bool runPrivileged() const; - /** - * Adds the variable @p name to the process' environment. - * This function must be called before starting the process. - * @param name the name of the environment variable - * @param value the new value for the environment variable - */ - void setEnvironment(const QString &name, const QString &value); + /** + * Adds the variable @p name to the process' environment. + * This function must be called before starting the process. + * @param name the name of the environment variable + * @param value the new value for the environment variable + */ + void setEnvironment(const QString &name, const QString &value); - /** - * Changes the current working directory (CWD) of the process - * to be started. - * This function must be called before starting the process. - * @param dir the new directory - */ - void setWorkingDirectory(const QString &dir); + /** + * Changes the current working directory (CWD) of the process + * to be started. + * This function must be called before starting the process. + * @param dir the new directory + */ + void setWorkingDirectory(const QString &dir); - /** - * Specify whether to start the command via a shell or directly. - * The default is to start the command directly. - * If @p useShell is true @p shell will be used as shell, or - * if shell is empty, /bin/sh will be used. - * - * When using a shell, the caller should make sure that all filenames etc. - * are properly quoted when passed as argument. - * @see quote() - * @param useShell true if the command should be started via a shell - * @param shell the path to the shell that will execute the process, or - * 0 to use /bin/sh. Use getenv("SHELL") to use the user's - * default shell, but note that doing so is usually a bad idea - * for shell compatibility reasons. - */ - void setUseShell(bool useShell, const char *shell = 0); + /** + * Specify whether to start the command via a shell or directly. + * The default is to start the command directly. + * If @p useShell is true @p shell will be used as shell, or + * if shell is empty, /bin/sh will be used. + * + * When using a shell, the caller should make sure that all filenames etc. + * are properly quoted when passed as argument. + * @see quote() + * @param useShell true if the command should be started via a shell + * @param shell the path to the shell that will execute the process, or + * 0 to use /bin/sh. Use getenv("SHELL") to use the user's + * default shell, but note that doing so is usually a bad idea + * for shell compatibility reasons. + */ + void setUseShell(bool useShell, const char *shell = 0); - /** - * This function can be used to quote an argument string such that - * the shell processes it properly. This is e. g. necessary for - * user-provided file names which may contain spaces or quotes. - * It also prevents expansion of wild cards and environment variables. - * @param arg the argument to quote - * @return the quoted argument - */ - static QString quote(const QString &arg); + /** + * This function can be used to quote an argument string such that + * the shell processes it properly. This is e. g. necessary for + * user-provided file names which may contain spaces or quotes. + * It also prevents expansion of wild cards and environment variables. + * @param arg the argument to quote + * @return the quoted argument + */ + static QString quote(const QString &arg); - /** - * Detaches K3Process from child process. All communication is closed. - * No exit notification is emitted any more for the child process. - * Deleting the K3Process will no longer kill the child process. - * Note that the current process remains the parent process of the - * child process. - */ - void detach(); + /** + * Detaches K3Process from child process. All communication is closed. + * No exit notification is emitted any more for the child process. + * Deleting the K3Process will no longer kill the child process. + * Note that the current process remains the parent process of the + * child process. + */ + void detach(); - /** - * Specify whether to create a pty (pseudo-terminal) for running the - * command. - * This function should be called before starting the process. - * - * @param comm for which stdio handles to use a pty. Note that it is not - * allowed to specify Stdout and Stderr at the same time both here and to - * start (there is only one pty, so they cannot be distinguished). - * @param addUtmp true if a utmp entry should be created for the pty - */ - void setUsePty(Communication comm, bool addUtmp); + /** + * Specify whether to create a pty (pseudo-terminal) for running the + * command. + * This function should be called before starting the process. + * + * @param comm for which stdio handles to use a pty. Note that it is not + * allowed to specify Stdout and Stderr at the same time both here and to + * start (there is only one pty, so they cannot be distinguished). + * @param addUtmp true if a utmp entry should be created for the pty + */ + void setUsePty(Communication comm, bool addUtmp); - /** - * Obtains the pty object used by this process. The return value is - * valid only after setUsePty() was used with a non-zero argument. - * The pty is open only while the process is running. - * @return a pointer to the pty object - */ - KPty *pty() const; + /** + * Obtains the pty object used by this process. The return value is + * valid only after setUsePty() was used with a non-zero argument. + * The pty is open only while the process is running. + * @return a pointer to the pty object + */ + KPty *pty() const; - /** - * More or less intuitive constants for use with setPriority(). - */ - enum { PrioLowest = 20, PrioLow = 10, PrioLower = 5, PrioNormal = 0, - PrioHigher = -5, PrioHigh = -10, PrioHighest = -19 }; + /** + * More or less intuitive constants for use with setPriority(). + */ + enum { PrioLowest = 20, PrioLow = 10, PrioLower = 5, PrioNormal = 0, + PrioHigher = -5, PrioHigh = -10, PrioHighest = -19 + }; - /** - * Sets the scheduling priority of the process. - * @param prio the new priority in the range -20 (high) to 19 (low). - * @return false on error; see setpriority(2) for possible reasons. - */ - bool setPriority(int prio); + /** + * Sets the scheduling priority of the process. + * @param prio the new priority in the range -20 (high) to 19 (low). + * @return false on error; see setpriority(2) for possible reasons. + */ + bool setPriority(int prio); Q_SIGNALS: - /** - * Emitted after the process has terminated when - * the process was run in the @p NotifyOnExit (==default option to - * start() ) or the Block mode. - * @param proc a pointer to the process that has exited - **/ - void processExited(K3Process *proc); + /** + * Emitted after the process has terminated when + * the process was run in the @p NotifyOnExit (==default option to + * start() ) or the Block mode. + * @param proc a pointer to the process that has exited + **/ + void processExited(K3Process *proc); - /** - * Emitted, when output from the child process has - * been received on stdout. - * - * To actually get this signal, the Stdout communication link - * has to be turned on in start(). - * - * @param proc a pointer to the process that has received the output - * @param buffer The data received. - * @param buflen The number of bytes that are available. - * - * You should copy the information contained in @p buffer to your private - * data structures before returning from the slot. - * Example: - * \code - * QString myBuf = QLatin1String(buffer, buflen); - * \endcode - **/ - void receivedStdout(K3Process *proc, char *buffer, int buflen); + /** + * Emitted, when output from the child process has + * been received on stdout. + * + * To actually get this signal, the Stdout communication link + * has to be turned on in start(). + * + * @param proc a pointer to the process that has received the output + * @param buffer The data received. + * @param buflen The number of bytes that are available. + * + * You should copy the information contained in @p buffer to your private + * data structures before returning from the slot. + * Example: + * \code + * QString myBuf = QLatin1String(buffer, buflen); + * \endcode + **/ + void receivedStdout(K3Process *proc, char *buffer, int buflen); - /** - * Emitted when output from the child process has - * been received on stdout. - * - * To actually get this signal, the Stdout communication link - * has to be turned on in start() and the - * NoRead flag must have been passed. - * - * You will need to explicitly call resume() after your call to start() - * to begin processing data from the child process' stdout. This is - * to ensure that this signal is not emitted when no one is connected - * to it, otherwise this signal will not be emitted. - * - * The data still has to be read from file descriptor @p fd. - * @param fd the file descriptor that provides the data - * @param len the number of bytes that have been read from @p fd must - * be written here - **/ - void receivedStdout(int fd, int &len); // KDE4: change, broken API + /** + * Emitted when output from the child process has + * been received on stdout. + * + * To actually get this signal, the Stdout communication link + * has to be turned on in start() and the + * NoRead flag must have been passed. + * + * You will need to explicitly call resume() after your call to start() + * to begin processing data from the child process' stdout. This is + * to ensure that this signal is not emitted when no one is connected + * to it, otherwise this signal will not be emitted. + * + * The data still has to be read from file descriptor @p fd. + * @param fd the file descriptor that provides the data + * @param len the number of bytes that have been read from @p fd must + * be written here + **/ + void receivedStdout(int fd, int &len); // KDE4: change, broken API - /** - * Emitted, when output from the child process has - * been received on stderr. - * - * To actually get this signal, the Stderr communication link - * has to be turned on in start(). - * - * You should copy the information contained in @p buffer to your private - * data structures before returning from the slot. - * - * @param proc a pointer to the process that has received the data - * @param buffer The data received. - * @param buflen The number of bytes that are available. - **/ - void receivedStderr(K3Process *proc, char *buffer, int buflen); + /** + * Emitted, when output from the child process has + * been received on stderr. + * + * To actually get this signal, the Stderr communication link + * has to be turned on in start(). + * + * You should copy the information contained in @p buffer to your private + * data structures before returning from the slot. + * + * @param proc a pointer to the process that has received the data + * @param buffer The data received. + * @param buflen The number of bytes that are available. + **/ + void receivedStderr(K3Process *proc, char *buffer, int buflen); - /** - * Emitted after all the data that has been - * specified by a prior call to writeStdin() has actually been - * written to the child process. - * @param proc a pointer to the process - **/ - void wroteStdin(K3Process *proc); + /** + * Emitted after all the data that has been + * specified by a prior call to writeStdin() has actually been + * written to the child process. + * @param proc a pointer to the process + **/ + void wroteStdin(K3Process *proc); protected Q_SLOTS: - /** - * This slot gets activated when data from the child's stdout arrives. - * It usually calls childOutput(). - * @param fdno the file descriptor for the output - */ - void slotChildOutput(int fdno); + /** + * This slot gets activated when data from the child's stdout arrives. + * It usually calls childOutput(). + * @param fdno the file descriptor for the output + */ + void slotChildOutput(int fdno); - /** - * This slot gets activated when data from the child's stderr arrives. - * It usually calls childError(). - * @param fdno the file descriptor for the output - */ - void slotChildError(int fdno); + /** + * This slot gets activated when data from the child's stderr arrives. + * It usually calls childError(). + * @param fdno the file descriptor for the output + */ + void slotChildError(int fdno); - /** - * Called when another bulk of data can be sent to the child's - * stdin. If there is no more data to be sent to stdin currently - * available, this function must disable the QSocketNotifier innot. - * @param dummy ignore this argument - */ - void slotSendData(int dummy); // KDE 4: remove dummy + /** + * Called when another bulk of data can be sent to the child's + * stdin. If there is no more data to be sent to stdin currently + * available, this function must disable the QSocketNotifier innot. + * @param dummy ignore this argument + */ + void slotSendData(int dummy); // KDE 4: remove dummy protected: - /** - * Sets up the environment according to the data passed via - * setEnvironment() - */ - void setupEnvironment(); + /** + * Sets up the environment according to the data passed via + * setEnvironment() + */ + void setupEnvironment(); - /** - * The list of the process' command line arguments. The first entry - * in this list is the executable itself. - */ - QList arguments; - /** - * How to run the process (Block, NotifyOnExit, DontCare). You should - * not modify this data member directly from derived classes. - */ - RunMode run_mode; - /** - * true if the process is currently running. You should not - * modify this data member directly from derived classes. Please use - * isRunning() for reading the value of this data member since it - * will probably be made private in later versions of K3Process. - */ - bool runs; + /** + * The list of the process' command line arguments. The first entry + * in this list is the executable itself. + */ + QList arguments; + /** + * How to run the process (Block, NotifyOnExit, DontCare). You should + * not modify this data member directly from derived classes. + */ + RunMode run_mode; + /** + * true if the process is currently running. You should not + * modify this data member directly from derived classes. Please use + * isRunning() for reading the value of this data member since it + * will probably be made private in later versions of K3Process. + */ + bool runs; - /** - * The PID of the currently running process. - * You should not modify this data member in derived classes. - * Please use pid() instead of directly accessing this - * member since it will probably be made private in - * later versions of K3Process. - */ - pid_t pid_; + /** + * The PID of the currently running process. + * You should not modify this data member in derived classes. + * Please use pid() instead of directly accessing this + * member since it will probably be made private in + * later versions of K3Process. + */ + pid_t pid_; - /** - * The process' exit status as returned by waitpid(). You should not - * modify the value of this data member from derived classes. You should - * rather use exitStatus() than accessing this data member directly - * since it will probably be made private in further versions of - * K3Process. - */ - int status; + /** + * The process' exit status as returned by waitpid(). You should not + * modify the value of this data member from derived classes. You should + * rather use exitStatus() than accessing this data member directly + * since it will probably be made private in further versions of + * K3Process. + */ + int status; - /** - * If false, the child process' effective uid & gid will be reset to the - * real values. - * @see setRunPrivileged() - */ - bool keepPrivs; + /** + * If false, the child process' effective uid & gid will be reset to the + * real values. + * @see setRunPrivileged() + */ + bool keepPrivs; - /** - * This function is called from start() right before a fork() takes - * place. According to the @p comm parameter this function has to initialize - * the in, out and err data members of K3Process. - * - * This function should return 1 if setting the needed communication channels - * was successful. - * - * The default implementation is to create UNIX STREAM sockets for the - * communication, but you could reimplement this function to establish a - * TCP/IP communication for network communication, for example. - */ - virtual int setupCommunication(Communication comm); + /** + * This function is called from start() right before a fork() takes + * place. According to the @p comm parameter this function has to initialize + * the in, out and err data members of K3Process. + * + * This function should return 1 if setting the needed communication channels + * was successful. + * + * The default implementation is to create UNIX STREAM sockets for the + * communication, but you could reimplement this function to establish a + * TCP/IP communication for network communication, for example. + */ + virtual int setupCommunication(Communication comm); - /** - * Called right after a (successful) fork() on the parent side. This function - * will usually do some communications cleanup, like closing in[0], - * out[1] and out[1]. - * - * Furthermore, it must also create the QSocketNotifiers innot, - * outnot and errnot and connect their Qt signals to the respective - * K3Process slots. - * - * For a more detailed explanation, it is best to have a look at the default - * implementation in kprocess.cpp. - */ - virtual int commSetupDoneP(); + /** + * Called right after a (successful) fork() on the parent side. This function + * will usually do some communications cleanup, like closing in[0], + * out[1] and out[1]. + * + * Furthermore, it must also create the QSocketNotifiers innot, + * outnot and errnot and connect their Qt signals to the respective + * K3Process slots. + * + * For a more detailed explanation, it is best to have a look at the default + * implementation in kprocess.cpp. + */ + virtual int commSetupDoneP(); - /** - * Called right after a (successful) fork(), but before an exec() on the child - * process' side. It usually duplicates the in[0], out[1] and - * err[1] file handles to the respective standard I/O handles. - */ - virtual int commSetupDoneC(); + /** + * Called right after a (successful) fork(), but before an exec() on the child + * process' side. It usually duplicates the in[0], out[1] and + * err[1] file handles to the respective standard I/O handles. + */ + virtual int commSetupDoneC(); - /** - * Immediately called after a successfully started process in NotifyOnExit - * mode has exited. This function normally calls commClose() - * and emits the processExited() signal. - * @param state the exit code of the process as returned by waitpid() - */ - virtual void processHasExited(int state); + /** + * Immediately called after a successfully started process in NotifyOnExit + * mode has exited. This function normally calls commClose() + * and emits the processExited() signal. + * @param state the exit code of the process as returned by waitpid() + */ + virtual void processHasExited(int state); - /** - * Cleans up the communication links to the child after it has exited. - * This function should act upon the values of pid() and runs. - * See the kprocess.cpp source for details. - * @li If pid() returns zero, the communication links should be closed - * only. - * @li if pid() returns non-zero and runs is false, all data - * immediately available from the communication links should be processed - * before closing them. - * @li if pid() returns non-zero and runs is true, the communication - * links should be monitored for data until the file handle returned by - * K3ProcessController::theKProcessController->notifierFd() becomes ready - * for reading - when it triggers, runs should be reset to false, and - * the function should be immediately left without closing anything. - * - * The previous semantics of this function are forward-compatible, but should - * be avoided, as they are prone to race conditions and can cause K3Process - * (and thus the whole program) to lock up under certain circumstances. At the - * end the function closes the communication links in any case. Additionally - * @li if runs is true, the communication links are monitored for data - * until all of them have returned EOF. Note that if any system function is - * interrupted (errno == EINTR) the polling loop should be aborted. - * @li if runs is false, all data immediately available from the - * communication links is processed. - */ - virtual void commClose(); + /** + * Cleans up the communication links to the child after it has exited. + * This function should act upon the values of pid() and runs. + * See the kprocess.cpp source for details. + * @li If pid() returns zero, the communication links should be closed + * only. + * @li if pid() returns non-zero and runs is false, all data + * immediately available from the communication links should be processed + * before closing them. + * @li if pid() returns non-zero and runs is true, the communication + * links should be monitored for data until the file handle returned by + * K3ProcessController::theKProcessController->notifierFd() becomes ready + * for reading - when it triggers, runs should be reset to false, and + * the function should be immediately left without closing anything. + * + * The previous semantics of this function are forward-compatible, but should + * be avoided, as they are prone to race conditions and can cause K3Process + * (and thus the whole program) to lock up under certain circumstances. At the + * end the function closes the communication links in any case. Additionally + * @li if runs is true, the communication links are monitored for data + * until all of them have returned EOF. Note that if any system function is + * interrupted (errno == EINTR) the polling loop should be aborted. + * @li if runs is false, all data immediately available from the + * communication links is processed. + */ + virtual void commClose(); - /* KDE 4 - commClose will be changed to perform cleanup only in all cases * - * If @p notfd is -1, all data immediately available from the - * communication links should be processed. - * If @p notfd is not -1, the communication links should be monitored - * for data until the file handle @p notfd becomes ready for reading. - */ + /* KDE 4 - commClose will be changed to perform cleanup only in all cases * + * If @p notfd is -1, all data immediately available from the + * communication links should be processed. + * If @p notfd is not -1, the communication links should be monitored + * for data until the file handle @p notfd becomes ready for reading. + */ // virtual void commDrain(int notfd); - /** - * Specify the actual executable that should be started (first argument to execve) - * Normally the the first argument is the executable but you can - * override that with this function. - */ - void setBinaryExecutable(const char *filename); + /** + * Specify the actual executable that should be started (first argument to execve) + * Normally the the first argument is the executable but you can + * override that with this function. + */ + void setBinaryExecutable(const char *filename); - /** - * The socket descriptors for stdout. - */ - int out[2]; - /** - * The socket descriptors for stdin. - */ - int in[2]; - /** - * The socket descriptors for stderr. - */ - int err[2]; + /** + * The socket descriptors for stdout. + */ + int out[2]; + /** + * The socket descriptors for stdin. + */ + int in[2]; + /** + * The socket descriptors for stderr. + */ + int err[2]; - /** - * The socket notifier for in[1]. - */ - QSocketNotifier *innot; - /** - * The socket notifier for out[0]. - */ - QSocketNotifier *outnot; - /** - * The socket notifier for err[0]. - */ - QSocketNotifier *errnot; + /** + * The socket notifier for in[1]. + */ + QSocketNotifier *innot; + /** + * The socket notifier for out[0]. + */ + QSocketNotifier *outnot; + /** + * The socket notifier for err[0]. + */ + QSocketNotifier *errnot; - /** - * Lists the communication links that are activated for the child - * process. Should not be modified from derived classes. - */ - Communication communication; + /** + * Lists the communication links that are activated for the child + * process. Should not be modified from derived classes. + */ + Communication communication; - /** - * Called by slotChildOutput() this function copies data arriving from - * the child process' stdout to the respective buffer and emits the signal - * receivedStdout(). - */ - int childOutput(int fdno); + /** + * Called by slotChildOutput() this function copies data arriving from + * the child process' stdout to the respective buffer and emits the signal + * receivedStdout(). + */ + int childOutput(int fdno); - /** - * Called by slotChildError() this function copies data arriving from - * the child process' stderr to the respective buffer and emits the signal - * receivedStderr(). - */ - int childError(int fdno); + /** + * Called by slotChildError() this function copies data arriving from + * the child process' stderr to the respective buffer and emits the signal + * receivedStderr(). + */ + int childError(int fdno); - /** - * The buffer holding the data that has to be sent to the child - */ - const char *input_data; - /** - * The number of bytes already transmitted - */ - int input_sent; - /** - * The total length of input_data - */ - int input_total; + /** + * The buffer holding the data that has to be sent to the child + */ + const char *input_data; + /** + * The number of bytes already transmitted + */ + int input_sent; + /** + * The total length of input_data + */ + int input_total; - /** - * K3ProcessController is a friend of K3Process because it has to have - * access to various data members. - */ - friend class K3ProcessController; + /** + * K3ProcessController is a friend of K3Process because it has to have + * access to various data members. + */ + friend class K3ProcessController; private: - K3ProcessPrivate* const d; + K3ProcessPrivate* const d; }; Q_DECLARE_OPERATORS_FOR_FLAGS(K3Process::Communication) @@ -859,29 +862,29 @@ class K3ShellProcessPrivate; */ class K3ShellProcess : public K3Process { - Q_OBJECT + Q_OBJECT public: - /** - * Constructor - * - * If no shellname is specified, the user's default shell is used. - */ - explicit K3ShellProcess(const char *shellname=0); + /** + * Constructor + * + * If no shellname is specified, the user's default shell is used. + */ + explicit K3ShellProcess(const char *shellname=0); - /** - * Destructor. - */ - ~K3ShellProcess(); + /** + * Destructor. + */ + ~K3ShellProcess(); - virtual bool start(RunMode runmode = NotifyOnExit, - Communication comm = NoCommunication); + virtual bool start(RunMode runmode = NotifyOnExit, + Communication comm = NoCommunication); - static QString quote(const QString &arg); + static QString quote(const QString &arg); private: - K3ShellProcessPrivate* const d; + K3ShellProcessPrivate* const d; }; diff --git a/lib/k3processcontroller.cpp b/lib/k3processcontroller.cpp index f825765..d04586c 100644 --- a/lib/k3processcontroller.cpp +++ b/lib/k3processcontroller.cpp @@ -40,13 +40,11 @@ class K3ProcessController::Private { public: Private() - : needcheck( false ), - notifier( 0 ) - { + : needcheck( false ), + notifier( 0 ) { } - ~Private() - { + ~Private() { delete notifier; } @@ -76,7 +74,7 @@ void K3ProcessController::ref() void K3ProcessController::deref() { Private::refCount--; - if( !Private::refCount ) { + if ( !Private::refCount ) { resetHandlers(); delete Private::instance; Private::instance = 0; @@ -96,44 +94,42 @@ K3ProcessController* K3ProcessController::instance() } K3ProcessController::K3ProcessController() - : d( new Private ) + : d( new Private ) { - if( pipe( d->fd ) ) - { - perror( "pipe" ); - abort(); - } + if ( pipe( d->fd ) ) { + perror( "pipe" ); + abort(); + } - fcntl( d->fd[0], F_SETFL, O_NONBLOCK ); // in case slotDoHousekeeping is called without polling first - fcntl( d->fd[1], F_SETFL, O_NONBLOCK ); // in case it fills up - fcntl( d->fd[0], F_SETFD, FD_CLOEXEC ); - fcntl( d->fd[1], F_SETFD, FD_CLOEXEC ); + fcntl( d->fd[0], F_SETFL, O_NONBLOCK ); // in case slotDoHousekeeping is called without polling first + fcntl( d->fd[1], F_SETFL, O_NONBLOCK ); // in case it fills up + fcntl( d->fd[0], F_SETFD, FD_CLOEXEC ); + fcntl( d->fd[1], F_SETFD, FD_CLOEXEC ); - d->notifier = new QSocketNotifier( d->fd[0], QSocketNotifier::Read ); - d->notifier->setEnabled( true ); - QObject::connect( d->notifier, SIGNAL(activated(int)), - SLOT(slotDoHousekeeping())); + d->notifier = new QSocketNotifier( d->fd[0], QSocketNotifier::Read ); + d->notifier->setEnabled( true ); + QObject::connect( d->notifier, SIGNAL(activated(int)), + SLOT(slotDoHousekeeping())); } K3ProcessController::~K3ProcessController() { #ifndef Q_OS_MAC -/* not sure why, but this is causing lockups */ - close( d->fd[0] ); - close( d->fd[1] ); + /* not sure why, but this is causing lockups */ + close( d->fd[0] ); + close( d->fd[1] ); #else #warning FIXME: why does close() freeze up destruction? #endif - delete d; + delete d; } extern "C" { -static void theReaper( int num ) -{ - K3ProcessController::theSigCHLDHandler( num ); -} + static void theReaper( int num ) { + K3ProcessController::theSigCHLDHandler( num ); + } } #ifdef Q_OS_UNIX @@ -143,59 +139,59 @@ bool K3ProcessController::Private::handlerSet = false; void K3ProcessController::setupHandlers() { - if( Private::handlerSet ) - return; - Private::handlerSet = true; + if ( Private::handlerSet ) + return; + Private::handlerSet = true; #ifdef Q_OS_UNIX - struct sigaction act; - sigemptyset( &act.sa_mask ); + struct sigaction act; + sigemptyset( &act.sa_mask ); - act.sa_handler = SIG_IGN; - act.sa_flags = 0; - sigaction( SIGPIPE, &act, 0L ); + act.sa_handler = SIG_IGN; + act.sa_flags = 0; + sigaction( SIGPIPE, &act, 0L ); - act.sa_handler = theReaper; - act.sa_flags = SA_NOCLDSTOP; - // CC: take care of SunOS which automatically restarts interrupted system - // calls (and thus does not have SA_RESTART) + act.sa_handler = theReaper; + act.sa_flags = SA_NOCLDSTOP; + // CC: take care of SunOS which automatically restarts interrupted system + // calls (and thus does not have SA_RESTART) #ifdef SA_RESTART - act.sa_flags |= SA_RESTART; + act.sa_flags |= SA_RESTART; #endif - sigaction( SIGCHLD, &act, &Private::oldChildHandlerData ); + sigaction( SIGCHLD, &act, &Private::oldChildHandlerData ); - sigaddset( &act.sa_mask, SIGCHLD ); - // Make sure we don't block this signal. gdb tends to do that :-( - sigprocmask( SIG_UNBLOCK, &act.sa_mask, 0 ); + sigaddset( &act.sa_mask, SIGCHLD ); + // Make sure we don't block this signal. gdb tends to do that :-( + sigprocmask( SIG_UNBLOCK, &act.sa_mask, 0 ); #else - //TODO: win32 + //TODO: win32 #endif } void K3ProcessController::resetHandlers() { - if( !Private::handlerSet ) - return; - Private::handlerSet = false; + if ( !Private::handlerSet ) + return; + Private::handlerSet = false; #ifdef Q_OS_UNIX - sigset_t mask, omask; - sigemptyset( &mask ); - sigaddset( &mask, SIGCHLD ); - sigprocmask( SIG_BLOCK, &mask, &omask ); + sigset_t mask, omask; + sigemptyset( &mask ); + sigaddset( &mask, SIGCHLD ); + sigprocmask( SIG_BLOCK, &mask, &omask ); - struct sigaction act; - sigaction( SIGCHLD, &Private::oldChildHandlerData, &act ); - if (act.sa_handler != theReaper) { - sigaction( SIGCHLD, &act, 0 ); - Private::handlerSet = true; - } + struct sigaction act; + sigaction( SIGCHLD, &Private::oldChildHandlerData, &act ); + if (act.sa_handler != theReaper) { + sigaction( SIGCHLD, &act, 0 ); + Private::handlerSet = true; + } - sigprocmask( SIG_SETMASK, &omask, 0 ); + sigprocmask( SIG_SETMASK, &omask, 0 ); #else - //TODO: win32 + //TODO: win32 #endif - // there should be no problem with SIGPIPE staying SIG_IGN + // there should be no problem with SIGPIPE staying SIG_IGN } // the pipe is needed to sync the child reaping with our event processing, @@ -203,143 +199,135 @@ void K3ProcessController::resetHandlers() // generally get harder void K3ProcessController::theSigCHLDHandler( int arg ) { - int saved_errno = errno; + int saved_errno = errno; - char dummy = 0; - ssize_t result = ::write( instance()->d->fd[1], &dummy, 1 ); - if (result < 0) { - qDebug() << "Write failed with the error code " << result << endl; - } + char dummy = 0; + ssize_t result = ::write( instance()->d->fd[1], &dummy, 1 ); + if (result < 0) { + qDebug() << "Write failed with the error code " << result << endl; + } #ifdef Q_OS_UNIX if ( Private::oldChildHandlerData.sa_handler != SIG_IGN && - Private::oldChildHandlerData.sa_handler != SIG_DFL ) { + Private::oldChildHandlerData.sa_handler != SIG_DFL ) { Private::oldChildHandlerData.sa_handler( arg ); // call the old handler } #else - //TODO: win32 + //TODO: win32 #endif - errno = saved_errno; + errno = saved_errno; } int K3ProcessController::notifierFd() const { - return d->fd[0]; + return d->fd[0]; } void K3ProcessController::unscheduleCheck() { - char dummy[16]; // somewhat bigger - just in case several have queued up - if( ::read( d->fd[0], dummy, sizeof(dummy) ) > 0 ) - d->needcheck = true; + char dummy[16]; // somewhat bigger - just in case several have queued up + if ( ::read( d->fd[0], dummy, sizeof(dummy) ) > 0 ) + d->needcheck = true; } void K3ProcessController::rescheduleCheck() { - if( d->needcheck ) - { - d->needcheck = false; - char dummy = 0; - ssize_t result = ::write( d->fd[1], &dummy, 1 ); - if (result < 0) { - qDebug() << "Write failed with the error code " << result << endl; - } + if ( d->needcheck ) { + d->needcheck = false; + char dummy = 0; + ssize_t result = ::write( d->fd[1], &dummy, 1 ); + if (result < 0) { + qDebug() << "Write failed with the error code " << result << endl; + } - } + } } void K3ProcessController::slotDoHousekeeping() { - char dummy[16]; // somewhat bigger - just in case several have queued up - ssize_t result = ::read( d->fd[0], dummy, sizeof(dummy) ); - if (result < 0) { - qDebug() << "Write failed with the error code " << result << endl; - } - - int status; - again: - QList::iterator it( d->kProcessList.begin() ); - QList::iterator eit( d->kProcessList.end() ); - while( it != eit ) - { - K3Process *prc = *it; - if( prc->runs && waitpid( prc->pid_, &status, WNOHANG ) > 0 ) - { - prc->processHasExited( status ); - // the callback can nuke the whole process list and even 'this' - if (!instance()) - return; - goto again; + char dummy[16]; // somewhat bigger - just in case several have queued up + ssize_t result = ::read( d->fd[0], dummy, sizeof(dummy) ); + if (result < 0) { + qDebug() << "Write failed with the error code " << result << endl; + } + + int status; +again: + QList::iterator it( d->kProcessList.begin() ); + QList::iterator eit( d->kProcessList.end() ); + while ( it != eit ) { + K3Process *prc = *it; + if ( prc->runs && waitpid( prc->pid_, &status, WNOHANG ) > 0 ) { + prc->processHasExited( status ); + // the callback can nuke the whole process list and even 'this' + if (!instance()) + return; + goto again; + } + ++it; + } + QList::iterator uit( d->unixProcessList.begin() ); + QList::iterator ueit( d->unixProcessList.end() ); + while ( uit != ueit ) { + if ( waitpid( *uit, 0, WNOHANG ) > 0 ) { + uit = d->unixProcessList.erase( uit ); + deref(); // counterpart to addProcess, can invalidate 'this' + } else + ++uit; } - ++it; - } - QList::iterator uit( d->unixProcessList.begin() ); - QList::iterator ueit( d->unixProcessList.end() ); - while( uit != ueit ) - { - if( waitpid( *uit, 0, WNOHANG ) > 0 ) - { - uit = d->unixProcessList.erase( uit ); - deref(); // counterpart to addProcess, can invalidate 'this' - } else - ++uit; - } } bool K3ProcessController::waitForProcessExit( int timeout ) { #ifdef Q_OS_UNIX - for(;;) - { - struct timeval tv, *tvp; - if (timeout < 0) - tvp = 0; - else - { - tv.tv_sec = timeout; - tv.tv_usec = 0; - tvp = &tv; - } + for (;;) { + struct timeval tv, *tvp; + if (timeout < 0) + tvp = 0; + else { + tv.tv_sec = timeout; + tv.tv_usec = 0; + tvp = &tv; + } - fd_set fds; - FD_ZERO( &fds ); - FD_SET( d->fd[0], &fds ); + fd_set fds; + FD_ZERO( &fds ); + FD_SET( d->fd[0], &fds ); - switch( select( d->fd[0]+1, &fds, 0, 0, tvp ) ) - { - case -1: - if( errno == EINTR ) - continue; - // fall through; should never happen - case 0: - return false; - default: - slotDoHousekeeping(); - return true; + switch ( select( d->fd[0]+1, &fds, 0, 0, tvp ) ) { + case -1: + if ( errno == EINTR ) + continue; + // fall through; should never happen + case 0: + return false; + default: + slotDoHousekeeping(); + return true; + } } - } #else - //TODO: win32 - return false; + //TODO: win32 + return false; #endif } void K3ProcessController::addKProcess( K3Process* p ) { - d->kProcessList.append( p ); + d->kProcessList.append( p ); } void K3ProcessController::removeKProcess( K3Process* p ) { - d->kProcessList.removeAll( p ); + d->kProcessList.removeAll( p ); } void K3ProcessController::addProcess( int pid ) { - d->unixProcessList.append( pid ); - ref(); // make sure we stay around when the K3Process goes away + d->unixProcessList.append( pid ); + ref(); // make sure we stay around when the K3Process goes away } //#include "moc_k3processcontroller.cpp" diff --git a/lib/k3processcontroller.h b/lib/k3processcontroller.h index c077af2..7a76f72 100644 --- a/lib/k3processcontroller.h +++ b/lib/k3processcontroller.h @@ -38,99 +38,99 @@ */ class K3ProcessController : public QObject { - Q_OBJECT + Q_OBJECT public: - /** - * Create an instance if none exists yet. - * Called by KApplication::KApplication() - */ - static void ref(); + /** + * Create an instance if none exists yet. + * Called by KApplication::KApplication() + */ + static void ref(); - /** - * Destroy the instance if one exists and it is not referenced any more. - * Called by KApplication::~KApplication() - */ - static void deref(); + /** + * Destroy the instance if one exists and it is not referenced any more. + * Called by KApplication::~KApplication() + */ + static void deref(); - /** - * Only a single instance of this class is allowed at a time. - * This method provides access to that instance. - */ - static K3ProcessController *instance(); + /** + * Only a single instance of this class is allowed at a time. + * This method provides access to that instance. + */ + static K3ProcessController *instance(); - /** - * Automatically called upon SIGCHLD. Never call it directly. - * If your application (or some library it uses) redirects SIGCHLD, - * the new signal handler (and only it) should call the old handler - * returned by sigaction(). - * @internal - */ - static void theSigCHLDHandler(int signal); // KDE4: private + /** + * Automatically called upon SIGCHLD. Never call it directly. + * If your application (or some library it uses) redirects SIGCHLD, + * the new signal handler (and only it) should call the old handler + * returned by sigaction(). + * @internal + */ + static void theSigCHLDHandler(int signal); // KDE4: private - /** - * Wait for any process to exit and handle their exit without - * starting an event loop. - * This function may cause K3Process to emit any of its signals. - * - * @param timeout the timeout in seconds. -1 means no timeout. - * @return true if a process exited, false - * if no process exited within @p timeout seconds. - */ - bool waitForProcessExit(int timeout); + /** + * Wait for any process to exit and handle their exit without + * starting an event loop. + * This function may cause K3Process to emit any of its signals. + * + * @param timeout the timeout in seconds. -1 means no timeout. + * @return true if a process exited, false + * if no process exited within @p timeout seconds. + */ + bool waitForProcessExit(int timeout); - /** - * Call this function to defer processing of the data that became available - * on notifierFd(). - */ - void unscheduleCheck(); + /** + * Call this function to defer processing of the data that became available + * on notifierFd(). + */ + void unscheduleCheck(); - /** - * This function @em must be called at some point after calling - * unscheduleCheck(). - */ - void rescheduleCheck(); + /** + * This function @em must be called at some point after calling + * unscheduleCheck(). + */ + void rescheduleCheck(); - /* - * Obtain the file descriptor K3ProcessController uses to get notified - * about process exits. select() or poll() on it if you create a custom - * event loop that needs to act upon SIGCHLD. - * @return the file descriptor of the reading end of the notification pipe - */ - int notifierFd() const; + /* + * Obtain the file descriptor K3ProcessController uses to get notified + * about process exits. select() or poll() on it if you create a custom + * event loop that needs to act upon SIGCHLD. + * @return the file descriptor of the reading end of the notification pipe + */ + int notifierFd() const; - /** - * @internal - */ - void addKProcess( K3Process* ); - /** - * @internal - */ - void removeKProcess( K3Process* ); - /** - * @internal - */ - void addProcess( int pid ); + /** + * @internal + */ + void addKProcess( K3Process* ); + /** + * @internal + */ + void removeKProcess( K3Process* ); + /** + * @internal + */ + void addProcess( int pid ); private Q_SLOTS: - void slotDoHousekeeping(); + void slotDoHousekeeping(); private: - friend class I_just_love_gcc; + friend class I_just_love_gcc; - static void setupHandlers(); - static void resetHandlers(); + static void setupHandlers(); + static void resetHandlers(); - // Disallow instantiation - K3ProcessController(); - ~K3ProcessController(); + // Disallow instantiation + K3ProcessController(); + ~K3ProcessController(); - // Disallow assignment and copy-construction - K3ProcessController( const K3ProcessController& ); - K3ProcessController& operator= ( const K3ProcessController& ); + // Disallow assignment and copy-construction + K3ProcessController( const K3ProcessController& ); + K3ProcessController& operator= ( const K3ProcessController& ); - class Private; - Private * const d; + class Private; + Private * const d; }; #endif diff --git a/lib/konsole_wcwidth.cpp b/lib/konsole_wcwidth.cpp index e4ef117..af83eb2 100644 --- a/lib/konsole_wcwidth.cpp +++ b/lib/konsole_wcwidth.cpp @@ -10,28 +10,29 @@ #include "konsole_wcwidth.h" struct interval { - unsigned short first; - unsigned short last; + unsigned short first; + unsigned short last; }; /* auxiliary function for binary search in interval table */ -static int bisearch(quint16 ucs, const struct interval *table, int max) { - int min = 0; - int mid; +static int bisearch(quint16 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; + } - 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; } @@ -67,67 +68,67 @@ static int bisearch(quint16 ucs, const struct interval *table, int max) { int konsole_wcwidth(quint16 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 } - }; + /* 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; + /* 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; + /* 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 */ + /* 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 || + 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) */)); } @@ -142,75 +143,75 @@ int konsole_wcwidth(quint16 ucs) */ int konsole_wcwidth_cjk(quint16 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 } - }; + /* 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; + /* binary search in table of non-spacing characters */ + if (bisearch(ucs, ambiguous, + sizeof(ambiguous) / sizeof(struct interval) - 1)) + return 2; - return konsole_wcwidth(ucs); + return konsole_wcwidth(ucs); } #endif // single byte char: +1, multi byte char: +2 int string_width( const QString &txt ) { - int w = 0; - for ( int i = 0; i < txt.length(); ++i ) - w += konsole_wcwidth( txt[ i ].unicode() ); - return w; + int w = 0; + for ( int i = 0; i < txt.length(); ++i ) + w += konsole_wcwidth( txt[ i ].unicode() ); + return w; } diff --git a/lib/kpty.cpp b/lib/kpty.cpp index fba1976..eef0665 100644 --- a/lib/kpty.cpp +++ b/lib/kpty.cpp @@ -150,7 +150,7 @@ extern "C" { ////////////////// KPtyPrivate::KPtyPrivate(KPty* parent) : - masterFd(-1), slaveFd(-1), ownMaster(true), q_ptr(parent) + masterFd(-1), slaveFd(-1), ownMaster(true), q_ptr(parent) { } @@ -170,12 +170,12 @@ bool KPtyPrivate::chownpty(bool) ///////////////////////////// KPty::KPty() : - d_ptr(new KPtyPrivate(this)) + d_ptr(new KPtyPrivate(this)) { } KPty::KPty(KPtyPrivate *d) : - d_ptr(d) + d_ptr(d) { d_ptr->q_ptr = this; } @@ -188,61 +188,59 @@ KPty::~KPty() bool KPty::open() { - Q_D(KPty); + Q_D(KPty); - if (d->masterFd >= 0) - return true; + if (d->masterFd >= 0) + return true; - d->ownMaster = true; + d->ownMaster = true; - QByteArray ptyName; + QByteArray ptyName; - // Find a master pty that we can open //////////////////////////////// + // Find a master pty that we can open //////////////////////////////// - // Because not all the pty animals are created equal, they want to - // be opened by several different methods. + // Because not all the pty animals are created equal, they want to + // be opened by several different methods. - // We try, as we know them, one by one. + // We try, as we know them, one by one. #ifdef HAVE_OPENPTY - char ptsn[PATH_MAX]; - if (::openpty( &d->masterFd, &d->slaveFd, ptsn, 0, 0)) - { - d->masterFd = -1; - d->slaveFd = -1; - qWarning(175) << "Can't open a pseudo teletype"; - return false; - } - d->ttyName = ptsn; + char ptsn[PATH_MAX]; + if (::openpty( &d->masterFd, &d->slaveFd, ptsn, 0, 0)) { + d->masterFd = -1; + d->slaveFd = -1; + qWarning(175) << "Can't open a pseudo teletype"; + return false; + } + d->ttyName = ptsn; #else #ifdef HAVE__GETPTY // irix - char *ptsn = _getpty(&d->masterFd, O_RDWR|O_NOCTTY, S_IRUSR|S_IWUSR, 0); - if (ptsn) { - d->ttyName = ptsn; - goto grantedpt; - } + char *ptsn = _getpty(&d->masterFd, O_RDWR|O_NOCTTY, S_IRUSR|S_IWUSR, 0); + if (ptsn) { + d->ttyName = ptsn; + goto grantedpt; + } #elif defined(HAVE_PTSNAME) || defined(TIOCGPTN) #ifdef HAVE_POSIX_OPENPT - d->masterFd = ::posix_openpt(O_RDWR|O_NOCTTY); + d->masterFd = ::posix_openpt(O_RDWR|O_NOCTTY); #elif defined(HAVE_GETPT) - d->masterFd = ::getpt(); + d->masterFd = ::getpt(); #elif defined(PTM_DEVICE) - d->masterFd = ::open(PTM_DEVICE, O_RDWR|O_NOCTTY); + d->masterFd = ::open(PTM_DEVICE, O_RDWR|O_NOCTTY); #else # error No method to open a PTY master detected. #endif - if (d->masterFd >= 0) - { + if (d->masterFd >= 0) { #ifdef HAVE_PTSNAME - char *ptsn = ptsname(d->masterFd); - if (ptsn) { - d->ttyName = ptsn; + char *ptsn = ptsname(d->masterFd); + if (ptsn) { + d->ttyName = ptsn; #else int ptyno; if (!ioctl(d->masterFd, TIOCGPTN, &ptyno)) { @@ -251,115 +249,108 @@ bool KPty::open() d->ttyName = buf; #endif #ifdef HAVE_GRANTPT - if (!grantpt(d->masterFd)) - goto grantedpt; + if (!grantpt(d->masterFd)) + goto grantedpt; #else - goto gotpty; + goto gotpty; #endif - } - ::close(d->masterFd); - d->masterFd = -1; - } -#endif // HAVE_PTSNAME || TIOCGPTN - - // Linux device names, FIXME: Trouble on other systems? - for (const char* s3 = "pqrstuvwxyzabcde"; *s3; s3++) - { - for (const char* s4 = "0123456789abcdef"; *s4; s4++) - { - ptyName = QString().sprintf("/dev/pty%c%c", *s3, *s4).toAscii(); - d->ttyName = QString().sprintf("/dev/tty%c%c", *s3, *s4).toAscii(); - - d->masterFd = ::open(ptyName.data(), O_RDWR); - if (d->masterFd >= 0) - { -#ifdef Q_OS_SOLARIS - /* Need to check the process group of the pty. - * If it exists, then the slave pty is in use, - * and we need to get another one. - */ - int pgrp_rtn; - if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) { - ::close(d->masterFd); - d->masterFd = -1; - continue; - } -#endif /* Q_OS_SOLARIS */ - if (!access(d->ttyName.data(),R_OK|W_OK)) // checks availability based on permission bits - { - if (!geteuid()) - { - struct group* p = getgrnam(TTY_GROUP); - if (!p) - p = getgrnam("wheel"); - gid_t gid = p ? p->gr_gid : getgid (); - - if (!chown(d->ttyName.data(), getuid(), gid)) { - chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP); - } - } - goto gotpty; } ::close(d->masterFd); d->masterFd = -1; - } } - } +#endif // HAVE_PTSNAME || TIOCGPTN - qWarning() << "Can't open a pseudo teletype"; - return false; + // Linux device names, FIXME: Trouble on other systems? + for (const char* s3 = "pqrstuvwxyzabcde"; *s3; s3++) { + for (const char* s4 = "0123456789abcdef"; *s4; s4++) { + ptyName = QString().sprintf("/dev/pty%c%c", *s3, *s4).toAscii(); + d->ttyName = QString().sprintf("/dev/tty%c%c", *s3, *s4).toAscii(); - gotpty: - struct stat st; - if (stat(d->ttyName.data(), &st)) - return false; // this just cannot happen ... *cough* Yeah right, I just - // had it happen when pty #349 was allocated. I guess - // there was some sort of leak? I only had a few open. - if (((st.st_uid != getuid()) || - (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) && - !d->chownpty(true)) - { - qWarning() - << "chownpty failed for device " << ptyName << "::" << d->ttyName - << "\nThis means the communication can be eavesdropped." << endl; - } + d->masterFd = ::open(ptyName.data(), O_RDWR); + if (d->masterFd >= 0) { +#ifdef Q_OS_SOLARIS + /* Need to check the process group of the pty. + * If it exists, then the slave pty is in use, + * and we need to get another one. + */ + int pgrp_rtn; + if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) { + ::close(d->masterFd); + d->masterFd = -1; + continue; + } +#endif /* Q_OS_SOLARIS */ + if (!access(d->ttyName.data(),R_OK|W_OK)) { // checks availability based on permission bits + if (!geteuid()) { + struct group* p = getgrnam(TTY_GROUP); + if (!p) + p = getgrnam("wheel"); + gid_t gid = p ? p->gr_gid : getgid (); + + if (!chown(d->ttyName.data(), getuid(), gid)) { + chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP); + } + } + goto gotpty; + } + ::close(d->masterFd); + d->masterFd = -1; + } + } + } + + qWarning() << "Can't open a pseudo teletype"; + return false; + +gotpty: + struct stat st; + if (stat(d->ttyName.data(), &st)) + return false; // this just cannot happen ... *cough* Yeah right, I just + // had it happen when pty #349 was allocated. I guess + // there was some sort of leak? I only had a few open. + if (((st.st_uid != getuid()) || + (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) && + !d->chownpty(true)) { + qWarning() + << "chownpty failed for device " << ptyName << "::" << d->ttyName + << "\nThis means the communication can be eavesdropped." << endl; + } #if defined(HAVE_GRANTPT) || defined(HAVE__GETPTY) - grantedpt: +grantedpt: #endif #ifdef HAVE_REVOKE - revoke(d->ttyName.data()); + revoke(d->ttyName.data()); #endif #ifdef HAVE_UNLOCKPT - unlockpt(d->masterFd); + unlockpt(d->masterFd); #elif defined(TIOCSPTLCK) - int flag = 0; - ioctl(d->masterFd, TIOCSPTLCK, &flag); + int flag = 0; + ioctl(d->masterFd, TIOCSPTLCK, &flag); #endif - d->slaveFd = ::open(d->ttyName.data(), O_RDWR | O_NOCTTY); - if (d->slaveFd < 0) - { - qWarning() << "Can't open slave pseudo teletype"; - ::close(d->masterFd); - d->masterFd = -1; - return false; - } + d->slaveFd = ::open(d->ttyName.data(), O_RDWR | O_NOCTTY); + if (d->slaveFd < 0) { + qWarning() << "Can't open slave pseudo teletype"; + ::close(d->masterFd); + d->masterFd = -1; + return false; + } #if (defined(__svr4__) || defined(__sgi__)) - // Solaris - ioctl(d->slaveFd, I_PUSH, "ptem"); - ioctl(d->slaveFd, I_PUSH, "ldterm"); + // Solaris + ioctl(d->slaveFd, I_PUSH, "ptem"); + ioctl(d->slaveFd, I_PUSH, "ldterm"); #endif #endif /* HAVE_OPENPTY */ - fcntl(d->masterFd, F_SETFD, FD_CLOEXEC); - fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC); + fcntl(d->masterFd, F_SETFD, FD_CLOEXEC); + fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC); - return true; + return true; } void KPty::closeSlave() @@ -374,27 +365,27 @@ void KPty::closeSlave() void KPty::close() { - Q_D(KPty); + Q_D(KPty); - if (d->masterFd < 0) - return; - closeSlave(); - // don't bother resetting unix98 pty, it will go away after closing master anyway. - if (memcmp(d->ttyName.data(), "/dev/pts/", 9)) { - if (!geteuid()) { - struct stat st; - if (!stat(d->ttyName.data(), &st)) { - if (!chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1)) { - chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); - } - } - } else { - fcntl(d->masterFd, F_SETFD, 0); - d->chownpty(false); - } - } - ::close(d->masterFd); - d->masterFd = -1; + if (d->masterFd < 0) + return; + closeSlave(); + // don't bother resetting unix98 pty, it will go away after closing master anyway. + if (memcmp(d->ttyName.data(), "/dev/pts/", 9)) { + if (!geteuid()) { + struct stat st; + if (!stat(d->ttyName.data(), &st)) { + if (!chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1)) { + chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + } + } + } else { + fcntl(d->masterFd, F_SETFD, 0); + d->chownpty(false); + } + } + ::close(d->masterFd); + d->masterFd = -1; } void KPty::setCTty() @@ -441,12 +432,12 @@ void KPty::login(const char *user, const char *remotehost) // note: strncpy without terminators _is_ correct here. man 4 utmp if (user) - strncpy(l_struct.ut_name, user, sizeof(l_struct.ut_name)); + strncpy(l_struct.ut_name, user, sizeof(l_struct.ut_name)); if (remotehost) { - strncpy(l_struct.ut_host, remotehost, sizeof(l_struct.ut_host)); + strncpy(l_struct.ut_host, remotehost, sizeof(l_struct.ut_host)); # ifdef HAVE_STRUCT_UTMP_UT_SYSLEN - l_struct.ut_syslen = qMin(strlen(remotehost), sizeof(l_struct.ut_host)); + l_struct.ut_syslen = qMin(strlen(remotehost), sizeof(l_struct.ut_host)); # endif } @@ -562,10 +553,10 @@ void KPty::logout() } endutxent(); # else - ut->ut_time = time(0); - pututline(ut); - } - endutent(); + ut->ut_time = time(0); + pututline(ut); +} +endutent(); # endif # endif #endif diff --git a/lib/kpty.h b/lib/kpty.h index 8286834..1409add 100644 --- a/lib/kpty.h +++ b/lib/kpty.h @@ -32,156 +32,157 @@ struct termios; * Provides primitives for opening & closing a pseudo TTY pair, assigning the * controlling TTY, utmp registration and setting various terminal attributes. */ -class KPty { +class KPty +{ Q_DECLARE_PRIVATE(KPty) public: - /** - * Constructor - */ - KPty(); + /** + * Constructor + */ + KPty(); - /** - * Destructor: - * - * If the pty is still open, it will be closed. Note, however, that - * an utmp registration is @em not undone. - */ - ~KPty(); + /** + * Destructor: + * + * If the pty is still open, it will be closed. Note, however, that + * an utmp registration is @em not undone. + */ + ~KPty(); - /** - * Create a pty master/slave pair. - * - * @return true if a pty pair was successfully opened - */ - bool open(); + /** + * Create a pty master/slave pair. + * + * @return true if a pty pair was successfully opened + */ + bool open(); - /** - * Close the pty master/slave pair. - */ - void close(); + /** + * Close the pty master/slave pair. + */ + void close(); - /** - * Close the pty slave descriptor. - * - * When creating the pty, KPty also opens the slave and keeps it open. - * Consequently the master will never receive an EOF notification. - * Usually this is the desired behavior, as a closed pty slave can be - * reopened any time - unlike a pipe or socket. However, in some cases - * pipe-alike behavior might be desired. - * - * After this function was called, slaveFd() and setCTty() cannot be - * used. - */ - void closeSlave(); + /** + * Close the pty slave descriptor. + * + * When creating the pty, KPty also opens the slave and keeps it open. + * Consequently the master will never receive an EOF notification. + * Usually this is the desired behavior, as a closed pty slave can be + * reopened any time - unlike a pipe or socket. However, in some cases + * pipe-alike behavior might be desired. + * + * After this function was called, slaveFd() and setCTty() cannot be + * used. + */ + void closeSlave(); - /** - * Creates a new session and process group and makes this pty the - * controlling tty. - */ - void setCTty(); + /** + * Creates a new session and process group and makes this pty the + * controlling tty. + */ + void setCTty(); - /** - * Creates an utmp entry for the tty. - * This function must be called after calling setCTty and - * making this pty the stdin. - * @param user the user to be logged on - * @param remotehost the host from which the login is coming. This is - * @em not the local host. For remote logins it should be the hostname - * of the client. For local logins from inside an X session it should - * be the name of the X display. Otherwise it should be empty. - */ - void login(const char *user = 0, const char *remotehost = 0); + /** + * Creates an utmp entry for the tty. + * This function must be called after calling setCTty and + * making this pty the stdin. + * @param user the user to be logged on + * @param remotehost the host from which the login is coming. This is + * @em not the local host. For remote logins it should be the hostname + * of the client. For local logins from inside an X session it should + * be the name of the X display. Otherwise it should be empty. + */ + void login(const char *user = 0, const char *remotehost = 0); - /** - * Removes the utmp entry for this tty. - */ - void logout(); + /** + * Removes the utmp entry for this tty. + */ + void logout(); - /** - * Wrapper around tcgetattr(3). - * - * This function can be used only while the PTY is open. - * You will need an #include <termios.h> to do anything useful - * with it. - * - * @param ttmode a pointer to a termios structure. - * Note: when declaring ttmode, @c struct @c ::termios must be used - - * without the '::' some version of HP-UX thinks, this declares - * the struct in your class, in your method. - * @return @c true on success, false otherwise - */ - bool tcGetAttr(struct ::termios *ttmode) const; + /** + * Wrapper around tcgetattr(3). + * + * This function can be used only while the PTY is open. + * You will need an #include <termios.h> to do anything useful + * with it. + * + * @param ttmode a pointer to a termios structure. + * Note: when declaring ttmode, @c struct @c ::termios must be used - + * without the '::' some version of HP-UX thinks, this declares + * the struct in your class, in your method. + * @return @c true on success, false otherwise + */ + bool tcGetAttr(struct ::termios *ttmode) const; - /** - * Wrapper around tcsetattr(3) with mode TCSANOW. - * - * This function can be used only while the PTY is open. - * - * @param ttmode a pointer to a termios structure. - * @return @c true on success, false otherwise. Note that success means - * that @em at @em least @em one attribute could be set. - */ - bool tcSetAttr(struct ::termios *ttmode); + /** + * Wrapper around tcsetattr(3) with mode TCSANOW. + * + * This function can be used only while the PTY is open. + * + * @param ttmode a pointer to a termios structure. + * @return @c true on success, false otherwise. Note that success means + * that @em at @em least @em one attribute could be set. + */ + bool tcSetAttr(struct ::termios *ttmode); - /** - * Change the logical (screen) size of the pty. - * The default is 24 lines by 80 columns. - * - * This function can be used only while the PTY is open. - * - * @param lines the number of rows - * @param columns the number of columns - * @return @c true on success, false otherwise - */ - bool setWinSize(int lines, int columns); + /** + * Change the logical (screen) size of the pty. + * The default is 24 lines by 80 columns. + * + * This function can be used only while the PTY is open. + * + * @param lines the number of rows + * @param columns the number of columns + * @return @c true on success, false otherwise + */ + bool setWinSize(int lines, int columns); - /** - * Set whether the pty should echo input. - * - * Echo is on by default. - * If the output of automatically fed (non-interactive) PTY clients - * needs to be parsed, disabling echo often makes it much simpler. - * - * This function can be used only while the PTY is open. - * - * @param echo true if input should be echoed. - * @return @c true on success, false otherwise - */ - bool setEcho(bool echo); + /** + * Set whether the pty should echo input. + * + * Echo is on by default. + * If the output of automatically fed (non-interactive) PTY clients + * needs to be parsed, disabling echo often makes it much simpler. + * + * This function can be used only while the PTY is open. + * + * @param echo true if input should be echoed. + * @return @c true on success, false otherwise + */ + bool setEcho(bool echo); - /** - * @return the name of the slave pty device. - * - * This function should be called only while the pty is open. - */ - const char *ttyName() const; + /** + * @return the name of the slave pty device. + * + * This function should be called only while the pty is open. + */ + const char *ttyName() const; - /** - * @return the file descriptor of the master pty - * - * This function should be called only while the pty is open. - */ - int masterFd() const; + /** + * @return the file descriptor of the master pty + * + * This function should be called only while the pty is open. + */ + int masterFd() const; - /** - * @return the file descriptor of the slave pty - * - * This function should be called only while the pty slave is open. - */ - int slaveFd() const; + /** + * @return the file descriptor of the slave pty + * + * This function should be called only while the pty slave is open. + */ + int slaveFd() const; protected: - /** - * @internal - */ - KPty(KPtyPrivate *d); + /** + * @internal + */ + KPty(KPtyPrivate *d); - /** - * @internal - */ - KPtyPrivate * const d_ptr; + /** + * @internal + */ + KPtyPrivate * const d_ptr; }; #endif diff --git a/lib/qtermwidget.cpp b/lib/qtermwidget.cpp index 5f00d4e..a6a4260 100644 --- a/lib/qtermwidget.cpp +++ b/lib/qtermwidget.cpp @@ -4,18 +4,18 @@ 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 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 "qtermwidget.h" @@ -26,17 +26,16 @@ using namespace Konsole; void *createTermWidget(int startnow, void *parent) -{ - return (void*) new QTermWidget(startnow, (QWidget*)parent); +{ + return (void*) new QTermWidget(startnow, (QWidget*)parent); } -struct TermWidgetImpl -{ +struct TermWidgetImpl { TermWidgetImpl(QWidget* parent = 0); TerminalDisplay *m_terminalDisplay; Session *m_session; - + Session* createSession(); TerminalDisplay* createTerminalDisplay(Session *session, QWidget* parent); }; @@ -57,15 +56,15 @@ Session *TermWidgetImpl::createSession() QStringList args(""); session->setArguments(args); session->setAutoClose(true); - + session->setCodec(QTextCodec::codecForName("UTF-8")); - + session->setFlowControlEnabled(true); session->setHistoryType(HistoryTypeBuffer(1000)); - + session->setDarkBackground(true); - - session->setKeyBindings(""); + + session->setKeyBindings(""); return session; } @@ -73,56 +72,56 @@ TerminalDisplay *TermWidgetImpl::createTerminalDisplay(Session *session, QWidget { // TerminalDisplay* display = new TerminalDisplay(this); TerminalDisplay* display = new TerminalDisplay(parent); - + display->setBellMode(TerminalDisplay::NotifyBell); display->setTerminalSizeHint(true); display->setTripleClickMode(TerminalDisplay::SelectWholeLine); display->setTerminalSizeStartup(true); display->setRandomSeed(session->sessionId() * 31); - + return display; } QTermWidget::QTermWidget(int startnow, QWidget *parent) -:QWidget(parent) + :QWidget(parent) { m_impl = new TermWidgetImpl(this); - + init(); if (startnow && m_impl->m_session) { - m_impl->m_session->run(); + m_impl->m_session->run(); } - + this->setFocus( Qt::OtherFocusReason ); m_impl->m_terminalDisplay->resize(this->size()); - + this->setFocusProxy(m_impl->m_terminalDisplay); } void QTermWidget::startShellProgram() { if ( m_impl->m_session->isRunning() ) - return; - + return; + m_impl->m_session->run(); } void QTermWidget::init() -{ +{ m_impl->m_terminalDisplay->setSize(80, 40); - - QFont font = QApplication::font(); + + QFont font = QApplication::font(); font.setFamily("Monospace"); font.setPointSize(10); font.setStyleHint(QFont::TypeWriter); setTerminalFont(font); - setScrollBarPosition(NoScrollBar); - + setScrollBarPosition(NoScrollBar); + m_impl->m_session->addView(m_impl->m_terminalDisplay); - + connect(m_impl->m_session, SIGNAL(finished()), this, SLOT(sessionFinished())); } @@ -136,15 +135,15 @@ QTermWidget::~QTermWidget() void QTermWidget::setTerminalFont(QFont &font) { if (!m_impl->m_terminalDisplay) - return; + return; m_impl->m_terminalDisplay->setVTFont(font); } void QTermWidget::setShellProgram(const QString &progname) { if (!m_impl->m_session) - return; - m_impl->m_session->setProgram(progname); + return; + m_impl->m_session->setProgram(progname); } void QTermWidget::setWorkingDirectory(const QString& dir) @@ -157,38 +156,38 @@ void QTermWidget::setWorkingDirectory(const QString& dir) void QTermWidget::setArgs(QStringList &args) { if (!m_impl->m_session) - return; - m_impl->m_session->setArguments(args); + return; + m_impl->m_session->setArguments(args); } void QTermWidget::setTextCodec(QTextCodec *codec) { if (!m_impl->m_session) - return; - m_impl->m_session->setCodec(codec); + return; + m_impl->m_session->setCodec(codec); } void QTermWidget::setColorScheme(int scheme) { - switch(scheme) { - case COLOR_SCHEME_WHITE_ON_BLACK: - m_impl->m_terminalDisplay->setColorTable(whiteonblack_color_table); - break; - case COLOR_SCHEME_GREEN_ON_BLACK: - m_impl->m_terminalDisplay->setColorTable(greenonblack_color_table); - break; - case COLOR_SCHEME_BLACK_ON_LIGHT_YELLOW: - m_impl->m_terminalDisplay->setColorTable(blackonlightyellow_color_table); - break; - default: //do nothing - break; + switch (scheme) { + case COLOR_SCHEME_WHITE_ON_BLACK: + m_impl->m_terminalDisplay->setColorTable(whiteonblack_color_table); + break; + case COLOR_SCHEME_GREEN_ON_BLACK: + m_impl->m_terminalDisplay->setColorTable(greenonblack_color_table); + break; + case COLOR_SCHEME_BLACK_ON_LIGHT_YELLOW: + m_impl->m_terminalDisplay->setColorTable(blackonlightyellow_color_table); + break; + default: //do nothing + break; }; } void QTermWidget::setSize(int h, int v) { if (!m_impl->m_terminalDisplay) - return; + return; m_impl->m_terminalDisplay->setSize(h, v); } @@ -197,19 +196,19 @@ void QTermWidget::setHistorySize(int lines) if (lines < 0) m_impl->m_session->setHistoryType(HistoryTypeFile()); else - m_impl->m_session->setHistoryType(HistoryTypeBuffer(lines)); + m_impl->m_session->setHistoryType(HistoryTypeBuffer(lines)); } void QTermWidget::setScrollBarPosition(ScrollBarPosition pos) { if (!m_impl->m_terminalDisplay) - return; + return; m_impl->m_terminalDisplay->setScrollBarPosition((TerminalDisplay::ScrollBarPosition)pos); } void QTermWidget::sendText(QString &text) { - m_impl->m_session->sendText(text); + m_impl->m_session->sendText(text); } void QTermWidget::resizeEvent(QResizeEvent*) @@ -262,9 +261,9 @@ bool QTermWidget::flowControlEnabled(void) void QTermWidget::setFlowControlWarningEnabled(bool enabled) { - if(flowControlEnabled()) { - // Do not show warning label if flow control is disabled - m_impl->m_terminalDisplay->setFlowControlWarningEnabled(enabled); + if (flowControlEnabled()) { + // Do not show warning label if flow control is disabled + m_impl->m_terminalDisplay->setFlowControlWarningEnabled(enabled); } } diff --git a/lib/qtermwidget.h b/lib/qtermwidget.h index 1385d52..e868d07 100644 --- a/lib/qtermwidget.h +++ b/lib/qtermwidget.h @@ -1,21 +1,21 @@ /* Copyright (C) 2008 e_k (e_k@users.sourceforge.net) - + This 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; either version 2 of the License, or (at your option) any later version. - + 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 _Q_TERM_WIDGET #define _Q_TERM_WIDGET @@ -25,16 +25,16 @@ struct TermWidgetImpl; enum COLOR_SCHEME { COLOR_SCHEME_WHITE_ON_BLACK = 1, - COLOR_SCHEME_GREEN_ON_BLACK, - COLOR_SCHEME_BLACK_ON_LIGHT_YELLOW }; + COLOR_SCHEME_GREEN_ON_BLACK, + COLOR_SCHEME_BLACK_ON_LIGHT_YELLOW + }; class QTermWidget : public QWidget { Q_OBJECT public: - - enum ScrollBarPosition - { + + enum ScrollBarPosition { /** Do not show the scroll bar. */ NoScrollBar=0, /** Show the scroll bar on the left side of the display. */ @@ -46,47 +46,47 @@ public: //Creation of widget QTermWidget(int startnow = 1, //start shell programm immediatelly - QWidget *parent = 0); + QWidget *parent = 0); ~QTermWidget(); //start shell program if it was not started in constructor void startShellProgram(); - + //look-n-feel, if you don`t like defaults // Terminal font // Default is application font with family Monospace, size 10 // USE ONLY FIXED-PITCH FONT! // otherwise symbols' position could be incorrect - void setTerminalFont(QFont &font); - + void setTerminalFont(QFont &font); + //environment void setEnvironment(const QStringList& environment); // Shell program, default is /bin/bash void setShellProgram(const QString &progname); - + //working directory void setWorkingDirectory(const QString& dir); // Shell program args, default is none void setArgs(QStringList &args); - + //Text codec, default is UTF-8 void setTextCodec(QTextCodec *codec); //Color scheme, default is white on black void setColorScheme(int scheme); - + //set size void setSize(int h, int v); - - // History size for scrolling + + // History size for scrolling void setHistorySize(int lines); //infinite if lines < 0 // Presence of scrollbar void setScrollBarPosition(ScrollBarPosition); - + // Send some text to terminal void sendText(QString &text); @@ -108,29 +108,29 @@ public: //! Return current key bindings QString keyBindings(); - + signals: void finished(); public slots: // Paste clipboard content to terminal void copyClipboard(); - + // Copies selection to clipboard void pasteClipboard(); /*! Set named key binding for given widget */ void setKeyBindings(const QString & kb); - -protected: + +protected: virtual void resizeEvent(QResizeEvent *); - + protected slots: - void sessionFinished(); - + void sessionFinished(); + private: - void init(); + void init(); TermWidgetImpl *m_impl; }; @@ -140,7 +140,7 @@ private: #ifdef __cplusplus extern "C" #endif -void *createTermWidget(int startnow, void *parent); +void *createTermWidget(int startnow, void *parent); #endif