K&R formatting
This commit is contained in:
+279
-266
@@ -39,328 +39,341 @@ 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) {
|
||||
// lastmap_index = index = current = size_t(-1);
|
||||
if (blocksize == 0) {
|
||||
blocksize = ((sizeof(Block) / getpagesize()) + 1) * getpagesize();
|
||||
}
|
||||
: size(0),
|
||||
current(size_t(-1)),
|
||||
index(size_t(-1)),
|
||||
lastmap(0),
|
||||
lastmap_index(size_t(-1)),
|
||||
lastblock(0), ion(-1),
|
||||
length(0)
|
||||
{
|
||||
// lastmap_index = index = current = size_t(-1);
|
||||
if (blocksize == 0) {
|
||||
blocksize = ((sizeof(Block) / getpagesize()) + 1) * getpagesize();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BlockArray::~BlockArray() {
|
||||
setHistorySize(0);
|
||||
assert(!lastblock);
|
||||
}
|
||||
|
||||
size_t BlockArray::append(Block * block) {
|
||||
if (!size) {
|
||||
return size_t(-1);
|
||||
}
|
||||
|
||||
++current;
|
||||
if (current >= size) {
|
||||
current = 0;
|
||||
}
|
||||
|
||||
int rc;
|
||||
rc = lseek(ion, current * blocksize, SEEK_SET);
|
||||
if (rc < 0) {
|
||||
perror("HistoryBuffer::add.seek");
|
||||
BlockArray::~BlockArray()
|
||||
{
|
||||
setHistorySize(0);
|
||||
return size_t(-1);
|
||||
}
|
||||
rc = write(ion, block, blocksize);
|
||||
if (rc < 0) {
|
||||
perror("HistoryBuffer::add.write");
|
||||
setHistorySize(0);
|
||||
return size_t(-1);
|
||||
}
|
||||
|
||||
length++;
|
||||
if (length > size) {
|
||||
length = size;
|
||||
}
|
||||
|
||||
++index;
|
||||
|
||||
delete block;
|
||||
return current;
|
||||
assert(!lastblock);
|
||||
}
|
||||
|
||||
size_t BlockArray::newBlock() {
|
||||
if (!size) {
|
||||
return size_t(-1);
|
||||
}
|
||||
append(lastblock);
|
||||
size_t BlockArray::append(Block * block)
|
||||
{
|
||||
if (!size) {
|
||||
return size_t(-1);
|
||||
}
|
||||
|
||||
lastblock = new Block();
|
||||
return index + 1;
|
||||
++current;
|
||||
if (current >= size) {
|
||||
current = 0;
|
||||
}
|
||||
|
||||
int rc;
|
||||
rc = lseek(ion, current * blocksize, SEEK_SET);
|
||||
if (rc < 0) {
|
||||
perror("HistoryBuffer::add.seek");
|
||||
setHistorySize(0);
|
||||
return size_t(-1);
|
||||
}
|
||||
rc = write(ion, block, blocksize);
|
||||
if (rc < 0) {
|
||||
perror("HistoryBuffer::add.write");
|
||||
setHistorySize(0);
|
||||
return size_t(-1);
|
||||
}
|
||||
|
||||
length++;
|
||||
if (length > size) {
|
||||
length = size;
|
||||
}
|
||||
|
||||
++index;
|
||||
|
||||
delete block;
|
||||
return current;
|
||||
}
|
||||
|
||||
Block * BlockArray::lastBlock() const {
|
||||
return lastblock;
|
||||
size_t BlockArray::newBlock()
|
||||
{
|
||||
if (!size) {
|
||||
return size_t(-1);
|
||||
}
|
||||
append(lastblock);
|
||||
|
||||
lastblock = new Block();
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
bool BlockArray::has(size_t i) const {
|
||||
if (i == index + 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i > index) {
|
||||
return false;
|
||||
}
|
||||
if (index - i >= length) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const Block * BlockArray::at(size_t i) {
|
||||
if (i == index + 1) {
|
||||
Block * BlockArray::lastBlock() const
|
||||
{
|
||||
return lastblock;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == lastmap_index) {
|
||||
return lastmap;
|
||||
}
|
||||
bool BlockArray::has(size_t i) const
|
||||
{
|
||||
if (i == index + 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i > index) {
|
||||
qDebug() << "BlockArray::at() i > index\n";
|
||||
return 0;
|
||||
}
|
||||
if (i > index) {
|
||||
return false;
|
||||
}
|
||||
if (index - i >= length) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const Block * BlockArray::at(size_t i)
|
||||
{
|
||||
if (i == index + 1) {
|
||||
return lastblock;
|
||||
}
|
||||
|
||||
if (i == lastmap_index) {
|
||||
return lastmap;
|
||||
}
|
||||
|
||||
if (i > index) {
|
||||
qDebug() << "BlockArray::at() i > index\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if (index - i >= length) {
|
||||
// kDebug(1211) << "BlockArray::at() index - i >= length\n";
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ;
|
||||
size_t j = i; // (current - (index - i) + (index/size+1)*size) % size ;
|
||||
|
||||
assert(j < size);
|
||||
unmap();
|
||||
assert(j < size);
|
||||
unmap();
|
||||
|
||||
Block * block = (Block *)mmap(0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize);
|
||||
Block * block = (Block *)mmap(0, blocksize, PROT_READ, MAP_PRIVATE, ion, j * blocksize);
|
||||
|
||||
if (block == (Block *)-1) {
|
||||
perror("mmap");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lastmap = block;
|
||||
lastmap_index = i;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void BlockArray::unmap() {
|
||||
if (lastmap) {
|
||||
int res = munmap((char *)lastmap, blocksize);
|
||||
if (res < 0) {
|
||||
perror("munmap");
|
||||
if (block == (Block *)-1) {
|
||||
perror("mmap");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
lastmap = 0;
|
||||
lastmap_index = size_t(-1);
|
||||
|
||||
lastmap = block;
|
||||
lastmap_index = i;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
bool BlockArray::setSize(size_t newsize) {
|
||||
return setHistorySize(newsize * 1024 / blocksize);
|
||||
void BlockArray::unmap()
|
||||
{
|
||||
if (lastmap) {
|
||||
int res = munmap((char *)lastmap, blocksize);
|
||||
if (res < 0) {
|
||||
perror("munmap");
|
||||
}
|
||||
}
|
||||
lastmap = 0;
|
||||
lastmap_index = size_t(-1);
|
||||
}
|
||||
|
||||
bool BlockArray::setHistorySize(size_t newsize) {
|
||||
bool BlockArray::setSize(size_t newsize)
|
||||
{
|
||||
return setHistorySize(newsize * 1024 / blocksize);
|
||||
}
|
||||
|
||||
bool BlockArray::setHistorySize(size_t newsize)
|
||||
{
|
||||
// kDebug(1211) << "setHistorySize " << size << " " << newsize;
|
||||
|
||||
if (size == newsize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unmap();
|
||||
|
||||
if (!newsize) {
|
||||
delete lastblock;
|
||||
lastblock = 0;
|
||||
if (ion >= 0) {
|
||||
close(ion);
|
||||
if (size == newsize) {
|
||||
return false;
|
||||
}
|
||||
ion = -1;
|
||||
current = size_t(-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!size) {
|
||||
FILE * tmp = tmpfile();
|
||||
if (!tmp) {
|
||||
perror("konsole: cannot open temp file.\n");
|
||||
unmap();
|
||||
|
||||
if (!newsize) {
|
||||
delete lastblock;
|
||||
lastblock = 0;
|
||||
if (ion >= 0) {
|
||||
close(ion);
|
||||
}
|
||||
ion = -1;
|
||||
current = size_t(-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!size) {
|
||||
FILE * tmp = tmpfile();
|
||||
if (!tmp) {
|
||||
perror("konsole: cannot open temp file.\n");
|
||||
} else {
|
||||
ion = dup(fileno(tmp));
|
||||
if (ion<0) {
|
||||
perror("konsole: cannot dup temp file.\n");
|
||||
fclose(tmp);
|
||||
}
|
||||
}
|
||||
if (ion < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(!lastblock);
|
||||
|
||||
lastblock = new Block();
|
||||
size = newsize;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newsize > size) {
|
||||
increaseBuffer();
|
||||
size = newsize;
|
||||
return false;
|
||||
} else {
|
||||
ion = dup(fileno(tmp));
|
||||
if (ion<0) {
|
||||
perror("konsole: cannot dup temp file.\n");
|
||||
fclose(tmp);
|
||||
}
|
||||
decreaseBuffer(newsize);
|
||||
ftruncate(ion, length*blocksize);
|
||||
size = newsize;
|
||||
|
||||
return true;
|
||||
}
|
||||
if (ion < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(!lastblock);
|
||||
|
||||
lastblock = new Block();
|
||||
size = newsize;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newsize > size) {
|
||||
increaseBuffer();
|
||||
size = newsize;
|
||||
return false;
|
||||
} else {
|
||||
decreaseBuffer(newsize);
|
||||
ftruncate(ion, length*blocksize);
|
||||
size = newsize;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void moveBlock(FILE * fion, int cursor, int newpos, char * buffer2) {
|
||||
int res = fseek(fion, cursor * blocksize, SEEK_SET);
|
||||
if (res) {
|
||||
perror("fseek");
|
||||
}
|
||||
res = fread(buffer2, blocksize, 1, fion);
|
||||
if (res != 1) {
|
||||
perror("fread");
|
||||
}
|
||||
void moveBlock(FILE * fion, int cursor, int newpos, char * buffer2)
|
||||
{
|
||||
int res = fseek(fion, cursor * blocksize, SEEK_SET);
|
||||
if (res) {
|
||||
perror("fseek");
|
||||
}
|
||||
res = fread(buffer2, blocksize, 1, fion);
|
||||
if (res != 1) {
|
||||
perror("fread");
|
||||
}
|
||||
|
||||
res = fseek(fion, newpos * blocksize, SEEK_SET);
|
||||
if (res) {
|
||||
perror("fseek");
|
||||
}
|
||||
res = fwrite(buffer2, blocksize, 1, fion);
|
||||
if (res != 1) {
|
||||
perror("fwrite");
|
||||
}
|
||||
// printf("moving block %d to %d\n", cursor, newpos);
|
||||
res = fseek(fion, newpos * blocksize, SEEK_SET);
|
||||
if (res) {
|
||||
perror("fseek");
|
||||
}
|
||||
res = fwrite(buffer2, blocksize, 1, fion);
|
||||
if (res != 1) {
|
||||
perror("fwrite");
|
||||
}
|
||||
// printf("moving block %d to %d\n", cursor, newpos);
|
||||
}
|
||||
|
||||
void BlockArray::decreaseBuffer(size_t newsize) {
|
||||
if (index < newsize) { // still fits in whole
|
||||
return;
|
||||
}
|
||||
void BlockArray::decreaseBuffer(size_t newsize)
|
||||
{
|
||||
if (index < newsize) { // still fits in whole
|
||||
return;
|
||||
}
|
||||
|
||||
int offset = (current - (newsize - 1) + size) % size;
|
||||
int offset = (current - (newsize - 1) + size) % size;
|
||||
|
||||
if (!offset) {
|
||||
return;
|
||||
}
|
||||
if (!offset) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The Block constructor could do somthing in future...
|
||||
char * buffer1 = new char[blocksize];
|
||||
// The Block constructor could do somthing in future...
|
||||
char * buffer1 = new char[blocksize];
|
||||
|
||||
FILE * fion = fdopen(dup(ion), "w+b");
|
||||
if (!fion) {
|
||||
delete [] buffer1;
|
||||
perror("fdopen/dup");
|
||||
return;
|
||||
}
|
||||
|
||||
int firstblock;
|
||||
if (current <= newsize) {
|
||||
firstblock = current + 1;
|
||||
} else {
|
||||
firstblock = 0;
|
||||
}
|
||||
|
||||
size_t oldpos;
|
||||
for (size_t i = 0, cursor=firstblock; i < newsize; i++) {
|
||||
oldpos = (size + cursor + offset) % size;
|
||||
moveBlock(fion, oldpos, cursor, buffer1);
|
||||
if (oldpos < newsize) {
|
||||
cursor = oldpos;
|
||||
} else {
|
||||
cursor++;
|
||||
}
|
||||
}
|
||||
|
||||
current = newsize - 1;
|
||||
length = newsize;
|
||||
|
||||
FILE * fion = fdopen(dup(ion), "w+b");
|
||||
if (!fion) {
|
||||
delete [] buffer1;
|
||||
perror("fdopen/dup");
|
||||
return;
|
||||
}
|
||||
|
||||
int firstblock;
|
||||
if (current <= newsize) {
|
||||
firstblock = current + 1;
|
||||
} else {
|
||||
firstblock = 0;
|
||||
}
|
||||
|
||||
size_t oldpos;
|
||||
for (size_t i = 0, cursor=firstblock; i < newsize; i++) {
|
||||
oldpos = (size + cursor + offset) % size;
|
||||
moveBlock(fion, oldpos, cursor, buffer1);
|
||||
if (oldpos < newsize) {
|
||||
cursor = oldpos;
|
||||
} else {
|
||||
cursor++;
|
||||
}
|
||||
}
|
||||
|
||||
current = newsize - 1;
|
||||
length = newsize;
|
||||
|
||||
delete [] buffer1;
|
||||
|
||||
fclose(fion);
|
||||
fclose(fion);
|
||||
|
||||
}
|
||||
|
||||
void BlockArray::increaseBuffer() {
|
||||
if (index < size) { // not even wrapped once
|
||||
return;
|
||||
}
|
||||
void BlockArray::increaseBuffer()
|
||||
{
|
||||
if (index < size) { // not even wrapped once
|
||||
return;
|
||||
}
|
||||
|
||||
int offset = (current + size + 1) % size;
|
||||
if (!offset) { // no moving needed
|
||||
return;
|
||||
}
|
||||
int offset = (current + size + 1) % size;
|
||||
if (!offset) { // no moving needed
|
||||
return;
|
||||
}
|
||||
|
||||
// The Block constructor could do somthing in future...
|
||||
char * buffer1 = new char[blocksize];
|
||||
char * buffer2 = new char[blocksize];
|
||||
// The Block constructor could do somthing in future...
|
||||
char * buffer1 = new char[blocksize];
|
||||
char * buffer2 = new char[blocksize];
|
||||
|
||||
int runs = 1;
|
||||
int bpr = size; // blocks per run
|
||||
int runs = 1;
|
||||
int bpr = size; // blocks per run
|
||||
|
||||
if (size % offset == 0) {
|
||||
bpr = size / offset;
|
||||
runs = offset;
|
||||
}
|
||||
if (size % offset == 0) {
|
||||
bpr = size / offset;
|
||||
runs = offset;
|
||||
}
|
||||
|
||||
FILE * fion = fdopen(dup(ion), "w+b");
|
||||
if (!fion) {
|
||||
perror("fdopen/dup");
|
||||
delete [] buffer1;
|
||||
delete [] buffer2;
|
||||
return;
|
||||
}
|
||||
|
||||
int res;
|
||||
for (int i = 0; i < runs; i++) {
|
||||
// free one block in chain
|
||||
int firstblock = (offset + i) % size;
|
||||
res = fseek(fion, firstblock * blocksize, SEEK_SET);
|
||||
if (res) {
|
||||
perror("fseek");
|
||||
}
|
||||
res = fread(buffer1, blocksize, 1, fion);
|
||||
if (res != 1) {
|
||||
perror("fread");
|
||||
}
|
||||
int newpos = 0;
|
||||
for (int j = 1, cursor=firstblock; j < bpr; j++) {
|
||||
cursor = (cursor + offset) % size;
|
||||
newpos = (cursor - offset + size) % size;
|
||||
moveBlock(fion, cursor, newpos, buffer2);
|
||||
}
|
||||
res = fseek(fion, i * blocksize, SEEK_SET);
|
||||
if (res) {
|
||||
perror("fseek");
|
||||
}
|
||||
res = fwrite(buffer1, blocksize, 1, fion);
|
||||
if (res != 1) {
|
||||
perror("fwrite");
|
||||
}
|
||||
}
|
||||
current = size - 1;
|
||||
length = size;
|
||||
|
||||
FILE * fion = fdopen(dup(ion), "w+b");
|
||||
if (!fion) {
|
||||
perror("fdopen/dup");
|
||||
delete [] buffer1;
|
||||
delete [] buffer2;
|
||||
return;
|
||||
}
|
||||
|
||||
int res;
|
||||
for (int i = 0; i < runs; i++) {
|
||||
// free one block in chain
|
||||
int firstblock = (offset + i) % size;
|
||||
res = fseek(fion, firstblock * blocksize, SEEK_SET);
|
||||
if (res) {
|
||||
perror("fseek");
|
||||
}
|
||||
res = fread(buffer1, blocksize, 1, fion);
|
||||
if (res != 1) {
|
||||
perror("fread");
|
||||
}
|
||||
int newpos = 0;
|
||||
for (int j = 1, cursor=firstblock; j < bpr; j++) {
|
||||
cursor = (cursor + offset) % size;
|
||||
newpos = (cursor - offset + size) % size;
|
||||
moveBlock(fion, cursor, newpos, buffer2);
|
||||
}
|
||||
res = fseek(fion, i * blocksize, SEEK_SET);
|
||||
if (res) {
|
||||
perror("fseek");
|
||||
}
|
||||
res = fwrite(buffer1, blocksize, 1, fion);
|
||||
if (res != 1) {
|
||||
perror("fwrite");
|
||||
}
|
||||
}
|
||||
current = size - 1;
|
||||
length = size;
|
||||
|
||||
delete [] buffer1;
|
||||
delete [] buffer2;
|
||||
|
||||
fclose(fion);
|
||||
fclose(fion);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+72
-70
@@ -30,98 +30,100 @@
|
||||
#define BlockSize (1 << 12)
|
||||
#define ENTRIES ((BlockSize - sizeof(size_t) ) / sizeof(unsigned char))
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
struct Block {
|
||||
Block() {
|
||||
size = 0;
|
||||
}
|
||||
unsigned char data[ENTRIES];
|
||||
size_t size;
|
||||
Block() {
|
||||
size = 0;
|
||||
}
|
||||
unsigned char data[ENTRIES];
|
||||
size_t size;
|
||||
};
|
||||
|
||||
// ///////////////////////////////////////////////////////
|
||||
|
||||
class BlockArray {
|
||||
class BlockArray
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a history file for holding
|
||||
* maximal size blocks. If more blocks
|
||||
* are requested, then it drops earlier
|
||||
* added ones.
|
||||
*/
|
||||
BlockArray();
|
||||
/**
|
||||
* Creates a history file for holding
|
||||
* maximal size blocks. If more blocks
|
||||
* are requested, then it drops earlier
|
||||
* added ones.
|
||||
*/
|
||||
BlockArray();
|
||||
|
||||
/// destructor
|
||||
~BlockArray();
|
||||
/// destructor
|
||||
~BlockArray();
|
||||
|
||||
/**
|
||||
* adds the Block at the end of history.
|
||||
* This may drop other blocks.
|
||||
*
|
||||
* The ownership on the block is transfered.
|
||||
* An unique index number is returned for accessing
|
||||
* it later (if not yet dropped then)
|
||||
*
|
||||
* Note, that the block may be dropped completely
|
||||
* if history is turned off.
|
||||
*/
|
||||
size_t append(Block * block);
|
||||
/**
|
||||
* adds the Block at the end of history.
|
||||
* This may drop other blocks.
|
||||
*
|
||||
* The ownership on the block is transfered.
|
||||
* An unique index number is returned for accessing
|
||||
* it later (if not yet dropped then)
|
||||
*
|
||||
* Note, that the block may be dropped completely
|
||||
* if history is turned off.
|
||||
*/
|
||||
size_t append(Block * block);
|
||||
|
||||
/**
|
||||
* gets the block at the index. Function may return
|
||||
* 0 if the block isn't available any more.
|
||||
*
|
||||
* The returned block is strictly readonly as only
|
||||
* maped in memory - and will be invalid on the next
|
||||
* operation on this class.
|
||||
*/
|
||||
const Block * at(size_t index);
|
||||
/**
|
||||
* gets the block at the index. Function may return
|
||||
* 0 if the block isn't available any more.
|
||||
*
|
||||
* The returned block is strictly readonly as only
|
||||
* maped in memory - and will be invalid on the next
|
||||
* operation on this class.
|
||||
*/
|
||||
const Block * at(size_t index);
|
||||
|
||||
/**
|
||||
* reorders blocks as needed. If newsize is null,
|
||||
* the history is emptied completely. The indices
|
||||
* returned on append won't change their semantic,
|
||||
* but they may not be valid after this call.
|
||||
*/
|
||||
bool setHistorySize(size_t newsize);
|
||||
/**
|
||||
* reorders blocks as needed. If newsize is null,
|
||||
* the history is emptied completely. The indices
|
||||
* returned on append won't change their semantic,
|
||||
* but they may not be valid after this call.
|
||||
*/
|
||||
bool setHistorySize(size_t newsize);
|
||||
|
||||
size_t newBlock();
|
||||
size_t newBlock();
|
||||
|
||||
Block * lastBlock() const;
|
||||
Block * lastBlock() const;
|
||||
|
||||
/**
|
||||
* Convenient function to set the size in KBytes
|
||||
* instead of blocks
|
||||
*/
|
||||
bool setSize(size_t newsize);
|
||||
/**
|
||||
* Convenient function to set the size in KBytes
|
||||
* instead of blocks
|
||||
*/
|
||||
bool setSize(size_t newsize);
|
||||
|
||||
size_t len() const {
|
||||
return length;
|
||||
}
|
||||
size_t len() const {
|
||||
return length;
|
||||
}
|
||||
|
||||
bool has(size_t index) const;
|
||||
bool has(size_t index) const;
|
||||
|
||||
size_t getCurrent() const {
|
||||
return current;
|
||||
}
|
||||
size_t getCurrent() const {
|
||||
return current;
|
||||
}
|
||||
|
||||
private:
|
||||
void unmap();
|
||||
void increaseBuffer();
|
||||
void decreaseBuffer(size_t newsize);
|
||||
void unmap();
|
||||
void increaseBuffer();
|
||||
void decreaseBuffer(size_t newsize);
|
||||
|
||||
size_t size;
|
||||
// current always shows to the last inserted block
|
||||
size_t current;
|
||||
size_t index;
|
||||
size_t size;
|
||||
// current always shows to the last inserted block
|
||||
size_t current;
|
||||
size_t index;
|
||||
|
||||
Block * lastmap;
|
||||
size_t lastmap_index;
|
||||
Block * lastblock;
|
||||
Block * lastmap;
|
||||
size_t lastmap_index;
|
||||
Block * lastblock;
|
||||
|
||||
int ion;
|
||||
size_t length;
|
||||
int ion;
|
||||
size_t length;
|
||||
|
||||
};
|
||||
|
||||
|
||||
+117
-110
@@ -31,7 +31,8 @@
|
||||
// Local
|
||||
#include "CharacterColor.h"
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
typedef unsigned char LineProperty;
|
||||
|
||||
@@ -54,93 +55,98 @@ static const int LINE_DOUBLEHEIGHT = (1 << 2);
|
||||
* value, foreground and background colors and a set of rendition attributes
|
||||
* which specify how it should be drawn.
|
||||
*/
|
||||
class Character {
|
||||
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;
|
||||
/** The foreground color used to draw this character. */
|
||||
CharacterColor foregroundColor;
|
||||
/** The color used to draw this character's background. */
|
||||
CharacterColor backgroundColor;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
inline bool Character::isBold(const ColorEntry * base) const {
|
||||
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);
|
||||
inline bool Character::isBold(const ColorEntry * base) const
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
extern unsigned short vt100_graphics[32];
|
||||
@@ -152,48 +158,49 @@ extern unsigned short vt100_graphics[32];
|
||||
* character ( ushort ) so that it can occupy the same space in
|
||||
* a structure.
|
||||
*/
|
||||
class ExtendedCharTable {
|
||||
class ExtendedCharTable
|
||||
{
|
||||
public:
|
||||
/** Constructs a new character table. */
|
||||
ExtendedCharTable();
|
||||
~ExtendedCharTable();
|
||||
/** Constructs a new character table. */
|
||||
ExtendedCharTable();
|
||||
~ExtendedCharTable();
|
||||
|
||||
/**
|
||||
* Adds a sequences of unicode characters to the table and returns
|
||||
* a hash code which can be used later to look up the sequence
|
||||
* using lookupExtendedChar()
|
||||
*
|
||||
* If the same sequence already exists in the table, the hash
|
||||
* of the existing sequence will be returned.
|
||||
*
|
||||
* @param unicodePoints An array of unicode character points
|
||||
* @param length Length of @p unicodePoints
|
||||
*/
|
||||
ushort createExtendedChar(ushort * unicodePoints , ushort length);
|
||||
/**
|
||||
* Looks up and returns a pointer to a sequence of unicode characters
|
||||
* 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
|
||||
* character sequence.
|
||||
*
|
||||
* @return A unicode character sequence of size @p length.
|
||||
*/
|
||||
ushort * lookupExtendedChar(ushort hash , ushort & length) const;
|
||||
/**
|
||||
* Adds a sequences of unicode characters to the table and returns
|
||||
* a hash code which can be used later to look up the sequence
|
||||
* using lookupExtendedChar()
|
||||
*
|
||||
* If the same sequence already exists in the table, the hash
|
||||
* of the existing sequence will be returned.
|
||||
*
|
||||
* @param unicodePoints An array of unicode character points
|
||||
* @param length Length of @p unicodePoints
|
||||
*/
|
||||
ushort createExtendedChar(ushort * unicodePoints , ushort length);
|
||||
/**
|
||||
* Looks up and returns a pointer to a sequence of unicode characters
|
||||
* 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
|
||||
* character sequence.
|
||||
*
|
||||
* @return A unicode character sequence of size @p length.
|
||||
*/
|
||||
ushort * lookupExtendedChar(ushort hash , ushort & length) const;
|
||||
|
||||
/** The global ExtendedCharTable instance. */
|
||||
static ExtendedCharTable instance;
|
||||
/** The global ExtendedCharTable instance. */
|
||||
static ExtendedCharTable instance;
|
||||
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
|
||||
// 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
|
||||
// in each value is the length of the buffer, followed by the ushorts in the buffer
|
||||
// themselves.
|
||||
QHash<ushort,ushort *> extendedCharTable;
|
||||
// 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
|
||||
// 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
|
||||
// in each value is the length of the buffer, followed by the ushorts in the buffer
|
||||
// themselves.
|
||||
QHash<ushort,ushort *> extendedCharTable;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+172
-165
@@ -28,7 +28,8 @@
|
||||
// Qt
|
||||
#include <QtGui/QColor>
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
/**
|
||||
* An entry in a terminal display's color palette.
|
||||
@@ -43,45 +44,46 @@ namespace Konsole {
|
||||
* display should avoid drawing the background for any characters
|
||||
* using the entry as a background.
|
||||
*/
|
||||
class ColorEntry {
|
||||
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) {}
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/** The color value of this entry for display. */
|
||||
QColor color;
|
||||
/** 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;
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
|
||||
@@ -104,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.
|
||||
@@ -144,153 +146,158 @@ static const ColorEntry base_color_table[TABLE_COLORS] =
|
||||
/**
|
||||
* Describes the color of a single character in the terminal.
|
||||
*/
|
||||
class CharacterColor {
|
||||
friend class Character;
|
||||
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) {
|
||||
case COLOR_SPACE_DEFAULT:
|
||||
_u = co & 1;
|
||||
break;
|
||||
case COLOR_SPACE_SYSTEM:
|
||||
_u = co & 7;
|
||||
_v = (co >> 3) & 1;
|
||||
break;
|
||||
case COLOR_SPACE_256:
|
||||
_u = co & 255;
|
||||
break;
|
||||
case COLOR_SPACE_RGB:
|
||||
_u = co >> 16;
|
||||
_v = co >> 8;
|
||||
_w = co;
|
||||
break;
|
||||
default:
|
||||
_colorSpace = COLOR_SPACE_UNDEFINED;
|
||||
/**
|
||||
* 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;
|
||||
case COLOR_SPACE_SYSTEM:
|
||||
_u = co & 7;
|
||||
_v = (co >> 3) & 1;
|
||||
break;
|
||||
case COLOR_SPACE_256:
|
||||
_u = co & 255;
|
||||
break;
|
||||
case COLOR_SPACE_RGB:
|
||||
_u = co >> 16;
|
||||
_v = co >> 8;
|
||||
_w = co;
|
||||
break;
|
||||
default:
|
||||
_colorSpace = COLOR_SPACE_UNDEFINED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this character color entry is valid.
|
||||
*/
|
||||
bool isValid() {
|
||||
return _colorSpace != COLOR_SPACE_UNDEFINED;
|
||||
}
|
||||
/**
|
||||
* 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();
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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 *reinterpret_cast<const quint32 *>(&a._colorSpace) ==
|
||||
*reinterpret_cast<const quint32 *>(&b._colorSpace);
|
||||
inline bool operator == (const CharacterColor & a, const CharacterColor & b)
|
||||
{
|
||||
return *reinterpret_cast<const quint32 *>(&a._colorSpace) ==
|
||||
*reinterpret_cast<const quint32 *>(&b._colorSpace);
|
||||
}
|
||||
|
||||
inline bool operator != (const CharacterColor & a, const CharacterColor & b) {
|
||||
return *reinterpret_cast<const quint32 *>(&a._colorSpace) !=
|
||||
*reinterpret_cast<const quint32 *>(&b._colorSpace);
|
||||
inline bool operator != (const CharacterColor & a, const CharacterColor & b)
|
||||
{
|
||||
return *reinterpret_cast<const quint32 *>(&a._colorSpace) !=
|
||||
*reinterpret_cast<const quint32 *>(&b._colorSpace);
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
// 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;
|
||||
// 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);
|
||||
// 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) {
|
||||
inline QColor CharacterColor::color(const ColorEntry * base) const
|
||||
{
|
||||
switch (_colorSpace) {
|
||||
case COLOR_SPACE_DEFAULT:
|
||||
return base[_u+0+(_v?BASE_COLORS:0)].color;
|
||||
return base[_u+0+(_v?BASE_COLORS:0)].color;
|
||||
case COLOR_SPACE_SYSTEM:
|
||||
return base[_u+2+(_v?BASE_COLORS:0)].color;
|
||||
return base[_u+2+(_v?BASE_COLORS:0)].color;
|
||||
case COLOR_SPACE_256:
|
||||
return color256(_u,base);
|
||||
return color256(_u,base);
|
||||
case COLOR_SPACE_RGB:
|
||||
return QColor(_u,_v,_w);
|
||||
return QColor(_u,_v,_w);
|
||||
case COLOR_SPACE_UNDEFINED:
|
||||
return QColor();
|
||||
}
|
||||
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;
|
||||
}
|
||||
inline void CharacterColor::toggleIntensive()
|
||||
{
|
||||
if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT) {
|
||||
_v = !_v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+33
-33
@@ -6,45 +6,45 @@
|
||||
using namespace Konsole;
|
||||
|
||||
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
|
||||
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 )
|
||||
// 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
|
||||
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 )
|
||||
};
|
||||
|
||||
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 ),
|
||||
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 )
|
||||
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 ),
|
||||
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 )
|
||||
};
|
||||
|
||||
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)
|
||||
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)
|
||||
};
|
||||
|
||||
|
||||
|
||||
+299
-264
@@ -63,115 +63,128 @@ 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()) );
|
||||
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)) );
|
||||
// listen for mouse status changes
|
||||
connect( this , SIGNAL(programUsesMouseChanged(bool)) ,
|
||||
SLOT(usesMouseChanged(bool)) );
|
||||
}
|
||||
|
||||
bool Emulation::programUsesMouse() const {
|
||||
return _usesMouse;
|
||||
bool Emulation::programUsesMouse() const
|
||||
{
|
||||
return _usesMouse;
|
||||
}
|
||||
|
||||
void Emulation::usesMouseChanged(bool usesMouse) {
|
||||
_usesMouse = usesMouse;
|
||||
void Emulation::usesMouseChanged(bool usesMouse)
|
||||
{
|
||||
_usesMouse = usesMouse;
|
||||
}
|
||||
|
||||
ScreenWindow * Emulation::createWindow() {
|
||||
ScreenWindow * window = new ScreenWindow();
|
||||
window->setScreen(_currentScreen);
|
||||
_windows << window;
|
||||
ScreenWindow * Emulation::createWindow()
|
||||
{
|
||||
ScreenWindow * window = new ScreenWindow();
|
||||
window->setScreen(_currentScreen);
|
||||
_windows << window;
|
||||
|
||||
connect(window , SIGNAL(selectionChanged()),
|
||||
this , SLOT(bufferedUpdate()));
|
||||
connect(window , SIGNAL(selectionChanged()),
|
||||
this , SLOT(bufferedUpdate()));
|
||||
|
||||
connect(this , SIGNAL(outputChanged()),
|
||||
window , SLOT(notifyOutputChanged()) );
|
||||
return window;
|
||||
connect(this , SIGNAL(outputChanged()),
|
||||
window , SLOT(notifyOutputChanged()) );
|
||||
return window;
|
||||
}
|
||||
|
||||
/*!
|
||||
*/
|
||||
|
||||
Emulation::~Emulation() {
|
||||
QListIterator<ScreenWindow *> windowIter(_windows);
|
||||
Emulation::~Emulation()
|
||||
{
|
||||
QListIterator<ScreenWindow *> 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
|
||||
*/
|
||||
|
||||
void Emulation::setScreen(int n) {
|
||||
Screen * old = _currentScreen;
|
||||
_currentScreen = _screen[n&1];
|
||||
if (_currentScreen != old) {
|
||||
old->setBusySelecting(false);
|
||||
void Emulation::setScreen(int n)
|
||||
{
|
||||
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<ScreenWindow *> windowIter(_windows);
|
||||
while ( windowIter.hasNext() ) {
|
||||
windowIter.next()->setScreen(_currentScreen);
|
||||
// tell all windows onto this emulation to switch to the newly active _screen
|
||||
QListIterator<ScreenWindow *> windowIter(_windows);
|
||||
while ( windowIter.hasNext() ) {
|
||||
windowIter.next()->setScreen(_currentScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Emulation::clearHistory() {
|
||||
_screen[0]->setScroll( _screen[0]->getScroll() , false );
|
||||
void Emulation::clearHistory()
|
||||
{
|
||||
_screen[0]->setScroll( _screen[0]->getScroll() , false );
|
||||
}
|
||||
void Emulation::setHistory(const HistoryType & t) {
|
||||
_screen[0]->setScroll(t);
|
||||
void Emulation::setHistory(const HistoryType & t)
|
||||
{
|
||||
_screen[0]->setScroll(t);
|
||||
|
||||
showBulk();
|
||||
showBulk();
|
||||
}
|
||||
|
||||
const HistoryType & Emulation::history() {
|
||||
return _screen[0]->getScroll();
|
||||
const HistoryType & Emulation::history()
|
||||
{
|
||||
return _screen[0]->getScroll();
|
||||
}
|
||||
|
||||
void Emulation::setCodec(const QTextCodec * qtc) {
|
||||
Q_ASSERT( qtc );
|
||||
void Emulation::setCodec(const QTextCodec * 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) {
|
||||
if ( codec == Utf8Codec ) {
|
||||
setCodec( QTextCodec::codecForName("utf8") );
|
||||
} else if ( codec == LocaleCodec ) {
|
||||
setCodec( QTextCodec::codecForLocale() );
|
||||
}
|
||||
void Emulation::setCodec(EmulationCodec codec)
|
||||
{
|
||||
if ( codec == Utf8Codec ) {
|
||||
setCodec( QTextCodec::codecForName("utf8") );
|
||||
} else if ( codec == LocaleCodec ) {
|
||||
setCodec( QTextCodec::codecForLocale() );
|
||||
}
|
||||
}
|
||||
|
||||
void Emulation::setKeyBindings(const QString & name) {
|
||||
_keyTranslator = KeyboardTranslatorManager::instance()->findTranslator(name);
|
||||
void Emulation::setKeyBindings(const QString & name)
|
||||
{
|
||||
_keyTranslator = KeyboardTranslatorManager::instance()->findTranslator(name);
|
||||
}
|
||||
|
||||
QString Emulation::keyBindings() {
|
||||
return _keyTranslator->name();
|
||||
QString Emulation::keyBindings()
|
||||
{
|
||||
return _keyTranslator->name();
|
||||
}
|
||||
|
||||
|
||||
@@ -191,27 +204,27 @@ void Emulation::receiveChar(int c)
|
||||
// process application unicode input to terminal
|
||||
// this is a trivial scanner
|
||||
{
|
||||
c &= 0xff;
|
||||
switch (c) {
|
||||
c &= 0xff;
|
||||
switch (c) {
|
||||
case '\b' :
|
||||
_currentScreen->BackSpace();
|
||||
break;
|
||||
_currentScreen->BackSpace();
|
||||
break;
|
||||
case '\t' :
|
||||
_currentScreen->Tabulate();
|
||||
break;
|
||||
_currentScreen->Tabulate();
|
||||
break;
|
||||
case '\n' :
|
||||
_currentScreen->NewLine();
|
||||
break;
|
||||
_currentScreen->NewLine();
|
||||
break;
|
||||
case '\r' :
|
||||
_currentScreen->Return();
|
||||
break;
|
||||
_currentScreen->Return();
|
||||
break;
|
||||
case 0x07 :
|
||||
emit stateSet(NOTIFYBELL);
|
||||
break;
|
||||
emit stateSet(NOTIFYBELL);
|
||||
break;
|
||||
default :
|
||||
_currentScreen->ShowCharacter(c);
|
||||
break;
|
||||
};
|
||||
_currentScreen->ShowCharacter(c);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@@ -223,25 +236,28 @@ void Emulation::receiveChar(int c)
|
||||
/*!
|
||||
*/
|
||||
|
||||
void Emulation::sendKeyEvent( QKeyEvent * ev ) {
|
||||
emit stateSet(NOTIFYNORMAL);
|
||||
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());
|
||||
}
|
||||
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) {
|
||||
// default implementation does nothing
|
||||
void Emulation::sendString(const char *,int)
|
||||
{
|
||||
// default implementation does nothing
|
||||
}
|
||||
|
||||
void Emulation::sendMouseEvent(int /*buttons*/, int /*column*/, int /*row*/, int /*eventType*/) {
|
||||
// default implementation does nothing
|
||||
void Emulation::sendMouseEvent(int /*buttons*/, int /*column*/, int /*row*/, int /*eventType*/)
|
||||
{
|
||||
// default implementation does nothing
|
||||
}
|
||||
|
||||
// Unblocking, Byte to Unicode translation --------------------------------- --
|
||||
@@ -251,28 +267,29 @@ void Emulation::sendMouseEvent(int /*buttons*/, int /*column*/, int /*row*/, int
|
||||
TODO: Character composition from the old code. See #96536
|
||||
*/
|
||||
|
||||
void Emulation::receiveData(const char * text, int length) {
|
||||
emit stateSet(NOTIFYACTIVITY);
|
||||
void Emulation::receiveData(const char * text, int length)
|
||||
{
|
||||
emit stateSet(NOTIFYACTIVITY);
|
||||
|
||||
bufferedUpdate();
|
||||
bufferedUpdate();
|
||||
|
||||
QString unicodeText = _decoder->toUnicode(text,length);
|
||||
QString unicodeText = _decoder->toUnicode(text,length);
|
||||
|
||||
//send characters to terminal emulator
|
||||
for (int i=0; i<unicodeText.length(); i++) {
|
||||
receiveChar(unicodeText[i].unicode());
|
||||
}
|
||||
|
||||
//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<length; i++) {
|
||||
if (text[i] == '\030') {
|
||||
if ((length-i-1 > 3) && (strncmp(text+i+1, "B00", 3) == 0)) {
|
||||
emit zmodemDetected();
|
||||
}
|
||||
//send characters to terminal emulator
|
||||
for (int i=0; i<unicodeText.length(); i++) {
|
||||
receiveChar(unicodeText[i].unicode());
|
||||
}
|
||||
|
||||
//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<length; i++) {
|
||||
if (text[i] == '\030') {
|
||||
if ((length-i-1 > 3) && (strncmp(text+i+1, "B00", 3) == 0)) {
|
||||
emit zmodemDetected();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//OLDER VERSION
|
||||
@@ -327,62 +344,69 @@ 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::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);
|
||||
|
||||
while (viewIter.hasNext()) {
|
||||
viewIter.next()->setSelection(t);
|
||||
void Emulation::onSelectionBegin(const int x, const int y, const bool columnmode)
|
||||
{
|
||||
if (!connected) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_currentScreen->setSelectionStart( x,y,columnmode);
|
||||
showBulk();
|
||||
}
|
||||
|
||||
void Emulation::testIsSelected(const int x, const int y, bool & selected) {
|
||||
if (!connected) {
|
||||
return;
|
||||
}
|
||||
selected=_currentScreen->isSelected(x,y);
|
||||
void Emulation::onSelectionExtend(const int x, const int y)
|
||||
{
|
||||
if (!connected) {
|
||||
return;
|
||||
}
|
||||
_currentScreen->setSelectionEnd(x,y);
|
||||
showBulk();
|
||||
}
|
||||
|
||||
void Emulation::clearSelection() {
|
||||
if (!connected) {
|
||||
return;
|
||||
}
|
||||
_currentScreen->clearSelection();
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void Emulation::clearSelection()
|
||||
{
|
||||
if (!connected) {
|
||||
return;
|
||||
}
|
||||
_currentScreen->clearSelection();
|
||||
showBulk();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Emulation::writeToStream( TerminalCharacterDecoder * _decoder ,
|
||||
int startLine ,
|
||||
int endLine) {
|
||||
_currentScreen->writeToStream(_decoder,startLine,endLine);
|
||||
int endLine)
|
||||
{
|
||||
_currentScreen->writeToStream(_decoder,startLine,endLine);
|
||||
}
|
||||
|
||||
int Emulation::lineCount() {
|
||||
// sum number of lines currently on _screen plus number of lines in history
|
||||
return _currentScreen->getLines() + _currentScreen->getHistLines();
|
||||
int Emulation::lineCount()
|
||||
{
|
||||
// sum number of lines currently on _screen plus number of lines in history
|
||||
return _currentScreen->getLines() + _currentScreen->getHistLines();
|
||||
}
|
||||
|
||||
// Refreshing -------------------------------------------------------------- --
|
||||
@@ -392,124 +416,135 @@ int Emulation::lineCount() {
|
||||
|
||||
/*!
|
||||
*/
|
||||
void Emulation::showBulk() {
|
||||
_bulkTimer1.stop();
|
||||
_bulkTimer2.stop();
|
||||
void Emulation::showBulk()
|
||||
{
|
||||
_bulkTimer1.stop();
|
||||
_bulkTimer2.stop();
|
||||
|
||||
emit outputChanged();
|
||||
emit outputChanged();
|
||||
|
||||
_currentScreen->resetScrolledLines();
|
||||
_currentScreen->resetDroppedLines();
|
||||
_currentScreen->resetScrolledLines();
|
||||
_currentScreen->resetDroppedLines();
|
||||
}
|
||||
|
||||
void Emulation::bufferedUpdate() {
|
||||
_bulkTimer1.setSingleShot(true);
|
||||
_bulkTimer1.start(BULK_TIMEOUT1);
|
||||
if (!_bulkTimer2.isActive()) {
|
||||
_bulkTimer2.setSingleShot(true);
|
||||
_bulkTimer2.start(BULK_TIMEOUT2);
|
||||
}
|
||||
}
|
||||
|
||||
char Emulation::getErase() const {
|
||||
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 );
|
||||
|
||||
_screen[0]->resizeImage(lines,columns);
|
||||
_screen[1]->resizeImage(lines,columns);
|
||||
|
||||
emit imageSizeChanged(lines,columns);
|
||||
|
||||
bufferedUpdate();
|
||||
}
|
||||
|
||||
QSize Emulation::imageSize() {
|
||||
return QSize(_currentScreen->getColumns(), _currentScreen->getLines());
|
||||
}
|
||||
|
||||
ushort ExtendedCharTable::extendedCharHash(ushort * unicodePoints , ushort length) const {
|
||||
ushort hash = 0;
|
||||
for ( ushort i = 0 ; i < length ; i++ ) {
|
||||
hash = 31*hash + unicodePoints[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
bool ExtendedCharTable::extendedCharMatch(ushort hash , ushort * unicodePoints , ushort length) const {
|
||||
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;
|
||||
}
|
||||
// if the lengths match, each character must be checked. the stored buffer starts at
|
||||
// entry[1]
|
||||
for ( int i = 0 ; i < length ; i++ ) {
|
||||
if ( entry[i+1] != unicodePoints[i] ) {
|
||||
return false;
|
||||
void Emulation::bufferedUpdate()
|
||||
{
|
||||
_bulkTimer1.setSingleShot(true);
|
||||
_bulkTimer1.start(BULK_TIMEOUT1);
|
||||
if (!_bulkTimer2.isActive()) {
|
||||
_bulkTimer2.setSingleShot(true);
|
||||
_bulkTimer2.start(BULK_TIMEOUT2);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
ushort ExtendedCharTable::createExtendedChar(ushort * unicodePoints , ushort length) {
|
||||
// look for this sequence of points in the table
|
||||
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,
|
||||
// return its hash
|
||||
return hash;
|
||||
char Emulation::getErase() const
|
||||
{
|
||||
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 );
|
||||
|
||||
_screen[0]->resizeImage(lines,columns);
|
||||
_screen[1]->resizeImage(lines,columns);
|
||||
|
||||
emit imageSizeChanged(lines,columns);
|
||||
|
||||
bufferedUpdate();
|
||||
}
|
||||
|
||||
QSize Emulation::imageSize()
|
||||
{
|
||||
return QSize(_currentScreen->getColumns(), _currentScreen->getLines());
|
||||
}
|
||||
|
||||
ushort ExtendedCharTable::extendedCharHash(ushort * unicodePoints , ushort length) const
|
||||
{
|
||||
ushort hash = 0;
|
||||
for ( ushort i = 0 ; i < length ; i++ ) {
|
||||
hash = 31*hash + unicodePoints[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
bool ExtendedCharTable::extendedCharMatch(ushort hash , ushort * unicodePoints , ushort length) const
|
||||
{
|
||||
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;
|
||||
}
|
||||
// if the lengths match, each character must be checked. the stored buffer starts at
|
||||
// entry[1]
|
||||
for ( int i = 0 ; i < length ; i++ ) {
|
||||
if ( entry[i+1] != unicodePoints[i] ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
ushort ExtendedCharTable::createExtendedChar(ushort * unicodePoints , ushort length)
|
||||
{
|
||||
// look for this sequence of points in the table
|
||||
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,
|
||||
// return its hash
|
||||
return hash;
|
||||
} 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
|
||||
ushort * buffer = new ushort[length+1];
|
||||
buffer[0] = length;
|
||||
for ( int i = 0 ; i < length ; i++ ) {
|
||||
buffer[i+1] = unicodePoints[i];
|
||||
}
|
||||
|
||||
extendedCharTable.insert(hash,buffer);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
ushort * ExtendedCharTable::lookupExtendedChar(ushort hash , ushort & length) const
|
||||
{
|
||||
// lookup index in table and if found, set the length
|
||||
// argument and return a pointer to the character sequence
|
||||
|
||||
ushort * buffer = extendedCharTable[hash];
|
||||
if ( buffer ) {
|
||||
length = buffer[0];
|
||||
return buffer+1;
|
||||
} else {
|
||||
// if hash is already used by another, different sequence of unicode character
|
||||
// points then try next hash
|
||||
hash++;
|
||||
length = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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];
|
||||
}
|
||||
|
||||
extendedCharTable.insert(hash,buffer);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
ushort * ExtendedCharTable::lookupExtendedChar(ushort hash , ushort & length) const {
|
||||
// lookup index in table and if found, set the length
|
||||
// argument and return a pointer to the character sequence
|
||||
|
||||
ushort * buffer = extendedCharTable[hash];
|
||||
if ( buffer ) {
|
||||
length = buffer[0];
|
||||
return buffer+1;
|
||||
} else {
|
||||
length = 0;
|
||||
return 0;
|
||||
}
|
||||
ExtendedCharTable::ExtendedCharTable()
|
||||
{
|
||||
}
|
||||
|
||||
ExtendedCharTable::ExtendedCharTable() {
|
||||
}
|
||||
ExtendedCharTable::~ExtendedCharTable() {
|
||||
// free all allocated character buffers
|
||||
QHashIterator<ushort,ushort *> iter(extendedCharTable);
|
||||
while ( iter.hasNext() ) {
|
||||
iter.next();
|
||||
delete[] iter.value();
|
||||
}
|
||||
ExtendedCharTable::~ExtendedCharTable()
|
||||
{
|
||||
// free all allocated character buffers
|
||||
QHashIterator<ushort,ushort *> iter(extendedCharTable);
|
||||
while ( iter.hasNext() ) {
|
||||
iter.next();
|
||||
delete[] iter.value();
|
||||
}
|
||||
}
|
||||
|
||||
// global instance
|
||||
|
||||
+296
-294
@@ -36,7 +36,8 @@
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
class KeyboardTranslator;
|
||||
class HistoryType;
|
||||
@@ -51,21 +52,21 @@ class TerminalCharacterDecoder;
|
||||
* These are the values used by Emulation::stateChanged()
|
||||
*/
|
||||
enum {
|
||||
/** The emulation is currently receiving user input. */
|
||||
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
|
||||
* terminal input.
|
||||
*/
|
||||
NOTIFYACTIVITY=2,
|
||||
/** The emulation is currently receiving user input. */
|
||||
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
|
||||
* terminal input.
|
||||
*/
|
||||
NOTIFYACTIVITY=2,
|
||||
|
||||
// unused here?
|
||||
NOTIFYSILENCE=3
|
||||
// unused here?
|
||||
NOTIFYSILENCE=3
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -117,347 +118,348 @@ enum {
|
||||
* how long the emulation has been active/idle for and also respond to
|
||||
* a 'bell' event in different ways.
|
||||
*/
|
||||
class Emulation : public QObject {
|
||||
Q_OBJECT
|
||||
class Emulation : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/** Constructs a new terminal emulation */
|
||||
Emulation();
|
||||
~Emulation();
|
||||
/** 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();
|
||||
/**
|
||||
* 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 size of the screen image which the emulation produces */
|
||||
QSize imageSize();
|
||||
/** Returns the size of the screen image which the emulation produces */
|
||||
QSize imageSize();
|
||||
|
||||
/**
|
||||
* Returns the total number of lines, including those stored in the history.
|
||||
*/
|
||||
int lineCount();
|
||||
/**
|
||||
* Returns the total number of lines, including those stored in the history.
|
||||
*/
|
||||
int lineCount();
|
||||
|
||||
|
||||
/**
|
||||
* 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();
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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 *);
|
||||
/** 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;
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/** TODO Document me */
|
||||
virtual char getErase() const;
|
||||
/** TODO Document me */
|
||||
virtual char getErase() const;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* Copies the current image into the history and clears the screen.
|
||||
*/
|
||||
virtual void clearEntireScreen() =0;
|
||||
|
||||
/** Resets the state of the terminal. */
|
||||
virtual void reset() =0;
|
||||
/** 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;
|
||||
/**
|
||||
* 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);
|
||||
/** 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 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 *);
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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.
|
||||
* <ul>
|
||||
* <li>0 - Set window icon text and session title to @p newTitle</li>
|
||||
* <li>1 - Set window icon text to @p newTitle</li>
|
||||
* <li>2 - Set session title to @p newTitle</li>
|
||||
* <li>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.
|
||||
* </li>
|
||||
* <li>31 - Supposedly treats @p newTitle as a URL and opens it (NOT IMPLEMENTED)</li>
|
||||
* <li>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')</li>
|
||||
* </ul>
|
||||
* @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.
|
||||
* <ul>
|
||||
* <li>0 - Set window icon text and session title to @p newTitle</li>
|
||||
* <li>1 - Set window icon text to @p newTitle</li>
|
||||
* <li>2 - Set session title to @p newTitle</li>
|
||||
* <li>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.
|
||||
* </li>
|
||||
* <li>31 - Supposedly treats @p newTitle as a URL and opens it (NOT IMPLEMENTED)</li>
|
||||
* <li>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')</li>
|
||||
* </ul>
|
||||
* @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;
|
||||
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);
|
||||
/**
|
||||
* Processes an incoming character. See receiveData()
|
||||
* @p ch A unicode character code.
|
||||
*/
|
||||
virtual void receiveChar(int ch);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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
|
||||
enum EmulationCodec {
|
||||
LocaleCodec = 0,
|
||||
Utf8Codec = 1
|
||||
};
|
||||
void setCodec(EmulationCodec codec); // codec number, 0 = locale, 1=utf8
|
||||
|
||||
|
||||
QList<ScreenWindow *> _windows;
|
||||
QList<ScreenWindow *> _windows;
|
||||
|
||||
Screen * _currentScreen; // pointer to the screen which is currently active,
|
||||
// this is one of the elements in the screen[] array
|
||||
Screen * _currentScreen; // pointer to the screen which is currently active,
|
||||
// this is one of the elements in the screen[] array
|
||||
|
||||
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 )
|
||||
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;
|
||||
//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
|
||||
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:
|
||||
|
||||
// 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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
+385
-334
@@ -43,177 +43,195 @@
|
||||
|
||||
using namespace Konsole;
|
||||
|
||||
FilterChain::~FilterChain() {
|
||||
QMutableListIterator<Filter *> iter(*this);
|
||||
FilterChain::~FilterChain()
|
||||
{
|
||||
QMutableListIterator<Filter *> iter(*this);
|
||||
|
||||
while ( iter.hasNext() ) {
|
||||
Filter * filter = iter.next();
|
||||
iter.remove();
|
||||
delete filter;
|
||||
}
|
||||
}
|
||||
|
||||
void FilterChain::addFilter(Filter * filter) {
|
||||
append(filter);
|
||||
}
|
||||
void FilterChain::removeFilter(Filter * filter) {
|
||||
removeAll(filter);
|
||||
}
|
||||
bool FilterChain::containsFilter(Filter * filter) {
|
||||
return contains(filter);
|
||||
}
|
||||
void FilterChain::reset() {
|
||||
QListIterator<Filter *> iter(*this);
|
||||
while (iter.hasNext()) {
|
||||
iter.next()->reset();
|
||||
}
|
||||
}
|
||||
void FilterChain::setBuffer(const QString * buffer , const QList<int>* linePositions) {
|
||||
QListIterator<Filter *> iter(*this);
|
||||
while (iter.hasNext()) {
|
||||
iter.next()->setBuffer(buffer,linePositions);
|
||||
}
|
||||
}
|
||||
void FilterChain::process() {
|
||||
QListIterator<Filter *> iter(*this);
|
||||
while (iter.hasNext()) {
|
||||
iter.next()->process();
|
||||
}
|
||||
}
|
||||
void FilterChain::clear() {
|
||||
QList<Filter *>::clear();
|
||||
}
|
||||
Filter::HotSpot * FilterChain::hotSpotAt(int line , int column) const {
|
||||
QListIterator<Filter *> iter(*this);
|
||||
while (iter.hasNext()) {
|
||||
Filter * filter = iter.next();
|
||||
Filter::HotSpot * spot = filter->hotSpotAt(line,column);
|
||||
if ( spot != 0 ) {
|
||||
return spot;
|
||||
while ( iter.hasNext() ) {
|
||||
Filter * filter = iter.next();
|
||||
iter.remove();
|
||||
delete filter;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QList<Filter::HotSpot *> FilterChain::hotSpots() const {
|
||||
QList<Filter::HotSpot *> list;
|
||||
QListIterator<Filter *> iter(*this);
|
||||
while (iter.hasNext()) {
|
||||
Filter * filter = iter.next();
|
||||
list << filter->hotSpots();
|
||||
}
|
||||
return list;
|
||||
void FilterChain::addFilter(Filter * filter)
|
||||
{
|
||||
append(filter);
|
||||
}
|
||||
void FilterChain::removeFilter(Filter * filter)
|
||||
{
|
||||
removeAll(filter);
|
||||
}
|
||||
bool FilterChain::containsFilter(Filter * filter)
|
||||
{
|
||||
return contains(filter);
|
||||
}
|
||||
void FilterChain::reset()
|
||||
{
|
||||
QListIterator<Filter *> iter(*this);
|
||||
while (iter.hasNext()) {
|
||||
iter.next()->reset();
|
||||
}
|
||||
}
|
||||
void FilterChain::setBuffer(const QString * buffer , const QList<int>* linePositions)
|
||||
{
|
||||
QListIterator<Filter *> iter(*this);
|
||||
while (iter.hasNext()) {
|
||||
iter.next()->setBuffer(buffer,linePositions);
|
||||
}
|
||||
}
|
||||
void FilterChain::process()
|
||||
{
|
||||
QListIterator<Filter *> iter(*this);
|
||||
while (iter.hasNext()) {
|
||||
iter.next()->process();
|
||||
}
|
||||
}
|
||||
void FilterChain::clear()
|
||||
{
|
||||
QList<Filter *>::clear();
|
||||
}
|
||||
Filter::HotSpot * FilterChain::hotSpotAt(int line , int column) const
|
||||
{
|
||||
QListIterator<Filter *> iter(*this);
|
||||
while (iter.hasNext()) {
|
||||
Filter * filter = iter.next();
|
||||
Filter::HotSpot * spot = filter->hotSpotAt(line,column);
|
||||
if ( spot != 0 ) {
|
||||
return spot;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QList<Filter::HotSpot *> FilterChain::hotSpots() const
|
||||
{
|
||||
QList<Filter::HotSpot *> list;
|
||||
QListIterator<Filter *> iter(*this);
|
||||
while (iter.hasNext()) {
|
||||
Filter * filter = iter.next();
|
||||
list << filter->hotSpots();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
//QList<Filter::HotSpot*> FilterChain::hotSpotsAtLine(int line) const;
|
||||
|
||||
TerminalImageFilterChain::TerminalImageFilterChain()
|
||||
: _buffer(0)
|
||||
, _linePositions(0) {
|
||||
: _buffer(0)
|
||||
, _linePositions(0)
|
||||
{
|
||||
}
|
||||
|
||||
TerminalImageFilterChain::~TerminalImageFilterChain() {
|
||||
delete _buffer;
|
||||
delete _linePositions;
|
||||
TerminalImageFilterChain::~TerminalImageFilterChain()
|
||||
{
|
||||
delete _buffer;
|
||||
delete _linePositions;
|
||||
}
|
||||
|
||||
void TerminalImageFilterChain::setImage(const Character * const image , int lines , int columns, const QVector<LineProperty>& lineProperties) {
|
||||
void TerminalImageFilterChain::setImage(const Character * const image , int lines , int columns, const QVector<LineProperty>& lineProperties)
|
||||
{
|
||||
//qDebug("%s %d", __FILE__, __LINE__);
|
||||
if (empty()) {
|
||||
return;
|
||||
}
|
||||
//qDebug("%s %d", __FILE__, __LINE__);
|
||||
|
||||
// reset all filters and hotspots
|
||||
reset();
|
||||
//qDebug("%s %d", __FILE__, __LINE__);
|
||||
|
||||
PlainTextDecoder decoder;
|
||||
decoder.setTrailingWhitespace(false);
|
||||
|
||||
//qDebug("%s %d", __FILE__, __LINE__);
|
||||
// setup new shared buffers for the filters to process on
|
||||
QString * newBuffer = new QString();
|
||||
QList<int>* newLinePositions = new QList<int>();
|
||||
setBuffer( newBuffer , newLinePositions );
|
||||
|
||||
// free the old buffers
|
||||
delete _buffer;
|
||||
delete _linePositions;
|
||||
|
||||
_buffer = newBuffer;
|
||||
_linePositions = newLinePositions;
|
||||
|
||||
QTextStream lineStream(_buffer);
|
||||
decoder.begin(&lineStream);
|
||||
|
||||
for (int i=0 ; i < lines ; i++) {
|
||||
_linePositions->append(_buffer->length());
|
||||
decoder.decodeLine(image + i*columns,columns,LINE_DEFAULT);
|
||||
|
||||
// pretend that each line ends with a newline character.
|
||||
// this prevents a link that occurs at the end of one line
|
||||
// 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.
|
||||
//
|
||||
// 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');
|
||||
if (empty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
decoder.end();
|
||||
//qDebug("%s %d", __FILE__, __LINE__);
|
||||
|
||||
// reset all filters and hotspots
|
||||
reset();
|
||||
//qDebug("%s %d", __FILE__, __LINE__);
|
||||
|
||||
PlainTextDecoder decoder;
|
||||
decoder.setTrailingWhitespace(false);
|
||||
|
||||
//qDebug("%s %d", __FILE__, __LINE__);
|
||||
// setup new shared buffers for the filters to process on
|
||||
QString * newBuffer = new QString();
|
||||
QList<int>* newLinePositions = new QList<int>();
|
||||
setBuffer( newBuffer , newLinePositions );
|
||||
|
||||
// free the old buffers
|
||||
delete _buffer;
|
||||
delete _linePositions;
|
||||
|
||||
_buffer = newBuffer;
|
||||
_linePositions = newLinePositions;
|
||||
|
||||
QTextStream lineStream(_buffer);
|
||||
decoder.begin(&lineStream);
|
||||
|
||||
for (int i=0 ; i < lines ; i++) {
|
||||
_linePositions->append(_buffer->length());
|
||||
decoder.decodeLine(image + i*columns,columns,LINE_DEFAULT);
|
||||
|
||||
// pretend that each line ends with a newline character.
|
||||
// this prevents a link that occurs at the end of one line
|
||||
// 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.
|
||||
//
|
||||
// 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');
|
||||
}
|
||||
}
|
||||
decoder.end();
|
||||
// qDebug("%s %d", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
Filter::Filter() :
|
||||
_linePositions(0),
|
||||
_buffer(0) {
|
||||
_linePositions(0),
|
||||
_buffer(0)
|
||||
{
|
||||
}
|
||||
|
||||
Filter::~Filter() {
|
||||
QListIterator<HotSpot *> iter(_hotspotList);
|
||||
while (iter.hasNext()) {
|
||||
delete iter.next();
|
||||
}
|
||||
}
|
||||
void Filter::reset() {
|
||||
_hotspots.clear();
|
||||
_hotspotList.clear();
|
||||
}
|
||||
|
||||
void Filter::setBuffer(const QString * buffer , const QList<int>* linePositions) {
|
||||
_buffer = buffer;
|
||||
_linePositions = linePositions;
|
||||
}
|
||||
|
||||
void Filter::getLineColumn(int position , int & startLine , int & startColumn) {
|
||||
Q_ASSERT( _linePositions );
|
||||
Q_ASSERT( _buffer );
|
||||
|
||||
|
||||
for (int i = 0 ; i < _linePositions->count() ; i++) {
|
||||
//kDebug() << "line position at " << i << " = " << _linePositions[i];
|
||||
int nextLine = 0;
|
||||
|
||||
if ( i == _linePositions->count()-1 ) {
|
||||
nextLine = _buffer->length() + 1;
|
||||
} else {
|
||||
nextLine = _linePositions->value(i+1);
|
||||
Filter::~Filter()
|
||||
{
|
||||
QListIterator<HotSpot *> iter(_hotspotList);
|
||||
while (iter.hasNext()) {
|
||||
delete iter.next();
|
||||
}
|
||||
}
|
||||
void Filter::reset()
|
||||
{
|
||||
_hotspots.clear();
|
||||
_hotspotList.clear();
|
||||
}
|
||||
|
||||
// kDebug() << "pos - " << position << " line pos(" << i<< ") " << _linePositions->value(i) <<
|
||||
// " next = " << nextLine << " buffer len = " << _buffer->length();
|
||||
void Filter::setBuffer(const QString * buffer , const QList<int>* linePositions)
|
||||
{
|
||||
_buffer = buffer;
|
||||
_linePositions = linePositions;
|
||||
}
|
||||
|
||||
if ( _linePositions->value(i) <= position && position < nextLine ) {
|
||||
startLine = i;
|
||||
startColumn = position - _linePositions->value(i);
|
||||
return;
|
||||
void Filter::getLineColumn(int position , int & startLine , int & startColumn)
|
||||
{
|
||||
Q_ASSERT( _linePositions );
|
||||
Q_ASSERT( _buffer );
|
||||
|
||||
|
||||
for (int i = 0 ; i < _linePositions->count() ; i++) {
|
||||
//kDebug() << "line position at " << i << " = " << _linePositions[i];
|
||||
int nextLine = 0;
|
||||
|
||||
if ( i == _linePositions->count()-1 ) {
|
||||
nextLine = _buffer->length() + 1;
|
||||
} else {
|
||||
nextLine = _linePositions->value(i+1);
|
||||
}
|
||||
|
||||
// kDebug() << "pos - " << position << " line pos(" << i<< ") " << _linePositions->value(i) <<
|
||||
// " next = " << nextLine << " buffer len = " << _buffer->length();
|
||||
|
||||
if ( _linePositions->value(i) <= position && position < nextLine ) {
|
||||
startLine = i;
|
||||
startColumn = position - _linePositions->value(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -223,216 +241,245 @@ void Filter::getLineColumn(int position , int & startLine , int & startColumn) {
|
||||
_buffer.append(text);
|
||||
}*/
|
||||
|
||||
const QString * Filter::buffer() {
|
||||
return _buffer;
|
||||
const QString * Filter::buffer()
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
Filter::HotSpot::~HotSpot() {
|
||||
Filter::HotSpot::~HotSpot()
|
||||
{
|
||||
}
|
||||
void Filter::addHotSpot(HotSpot * spot) {
|
||||
_hotspotList << spot;
|
||||
void Filter::addHotSpot(HotSpot * spot)
|
||||
{
|
||||
_hotspotList << spot;
|
||||
|
||||
for (int line = spot->startLine() ; line <= spot->endLine() ; line++) {
|
||||
_hotspots.insert(line,spot);
|
||||
}
|
||||
}
|
||||
QList<Filter::HotSpot *> Filter::hotSpots() const {
|
||||
return _hotspotList;
|
||||
}
|
||||
QList<Filter::HotSpot *> Filter::hotSpotsAtLine(int line) const {
|
||||
return _hotspots.values(line);
|
||||
}
|
||||
|
||||
Filter::HotSpot * Filter::hotSpotAt(int line , int column) const {
|
||||
QListIterator<HotSpot *> spotIter(_hotspots.values(line));
|
||||
|
||||
while (spotIter.hasNext()) {
|
||||
HotSpot * spot = spotIter.next();
|
||||
|
||||
if ( spot->startLine() == line && spot->startColumn() > column ) {
|
||||
continue;
|
||||
for (int line = spot->startLine() ; line <= spot->endLine() ; line++) {
|
||||
_hotspots.insert(line,spot);
|
||||
}
|
||||
if ( spot->endLine() == line && spot->endColumn() < column ) {
|
||||
continue;
|
||||
}
|
||||
QList<Filter::HotSpot *> Filter::hotSpots() const
|
||||
{
|
||||
return _hotspotList;
|
||||
}
|
||||
QList<Filter::HotSpot *> Filter::hotSpotsAtLine(int line) const
|
||||
{
|
||||
return _hotspots.values(line);
|
||||
}
|
||||
|
||||
Filter::HotSpot * Filter::hotSpotAt(int line , int column) const
|
||||
{
|
||||
QListIterator<HotSpot *> spotIter(_hotspots.values(line));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return spot;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 {
|
||||
return QString();
|
||||
QString Filter::HotSpot::tooltip() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
QList<QAction *> Filter::HotSpot::actions() {
|
||||
return QList<QAction *>();
|
||||
QList<QAction *> Filter::HotSpot::actions()
|
||||
{
|
||||
return QList<QAction *>();
|
||||
}
|
||||
int Filter::HotSpot::startLine() const {
|
||||
return _startLine;
|
||||
int Filter::HotSpot::startLine() const
|
||||
{
|
||||
return _startLine;
|
||||
}
|
||||
int Filter::HotSpot::endLine() const {
|
||||
return _endLine;
|
||||
int Filter::HotSpot::endLine() const
|
||||
{
|
||||
return _endLine;
|
||||
}
|
||||
int Filter::HotSpot::startColumn() const {
|
||||
return _startColumn;
|
||||
int Filter::HotSpot::startColumn() const
|
||||
{
|
||||
return _startColumn;
|
||||
}
|
||||
int Filter::HotSpot::endColumn() const {
|
||||
return _endColumn;
|
||||
int Filter::HotSpot::endColumn() const
|
||||
{
|
||||
return _endColumn;
|
||||
}
|
||||
Filter::HotSpot::Type Filter::HotSpot::type() const {
|
||||
return _type;
|
||||
Filter::HotSpot::Type Filter::HotSpot::type() const
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
void Filter::HotSpot::setType(Type type) {
|
||||
_type = type;
|
||||
void Filter::HotSpot::setType(Type type)
|
||||
{
|
||||
_type = type;
|
||||
}
|
||||
|
||||
RegExpFilter::RegExpFilter() {
|
||||
RegExpFilter::RegExpFilter()
|
||||
{
|
||||
}
|
||||
|
||||
RegExpFilter::HotSpot::HotSpot(int startLine,int startColumn,int endLine,int endColumn)
|
||||
: Filter::HotSpot(startLine,startColumn,endLine,endColumn) {
|
||||
setType(Marker);
|
||||
: Filter::HotSpot(startLine,startColumn,endLine,endColumn)
|
||||
{
|
||||
setType(Marker);
|
||||
}
|
||||
|
||||
void RegExpFilter::HotSpot::activate(QObject *) {
|
||||
void RegExpFilter::HotSpot::activate(QObject *)
|
||||
{
|
||||
}
|
||||
|
||||
void RegExpFilter::HotSpot::setCapturedTexts(const QStringList & texts) {
|
||||
_capturedTexts = texts;
|
||||
void RegExpFilter::HotSpot::setCapturedTexts(const QStringList & texts)
|
||||
{
|
||||
_capturedTexts = texts;
|
||||
}
|
||||
QStringList RegExpFilter::HotSpot::capturedTexts() const {
|
||||
return _capturedTexts;
|
||||
QStringList RegExpFilter::HotSpot::capturedTexts() const
|
||||
{
|
||||
return _capturedTexts;
|
||||
}
|
||||
|
||||
void RegExpFilter::setRegExp(const QRegExp & regExp) {
|
||||
_searchText = regExp;
|
||||
void RegExpFilter::setRegExp(const QRegExp & regExp)
|
||||
{
|
||||
_searchText = regExp;
|
||||
}
|
||||
QRegExp RegExpFilter::regExp() const {
|
||||
return _searchText;
|
||||
QRegExp RegExpFilter::regExp() const
|
||||
{
|
||||
return _searchText;
|
||||
}
|
||||
/*void RegExpFilter::reset(int)
|
||||
{
|
||||
_buffer = QString();
|
||||
}*/
|
||||
void RegExpFilter::process() {
|
||||
int pos = 0;
|
||||
const QString * text = buffer();
|
||||
void RegExpFilter::process()
|
||||
{
|
||||
int pos = 0;
|
||||
const QString * text = buffer();
|
||||
|
||||
Q_ASSERT( text );
|
||||
Q_ASSERT( text );
|
||||
|
||||
// ignore any regular expressions which match an empty string.
|
||||
// otherwise the while loop below will run indefinitely
|
||||
static const QString emptyString("");
|
||||
if ( _searchText.exactMatch(emptyString) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
while(pos >= 0) {
|
||||
pos = _searchText.indexIn(*text,pos);
|
||||
|
||||
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);
|
||||
|
||||
//kDebug() << "start " << startLine << " / " << startColumn;
|
||||
//kDebug() << "end " << endLine << " / " << endColumn;
|
||||
|
||||
RegExpFilter::HotSpot * spot = newHotSpot(startLine,startColumn,
|
||||
endLine,endColumn);
|
||||
spot->setCapturedTexts(_searchText.capturedTexts());
|
||||
|
||||
addHotSpot( spot );
|
||||
pos += _searchText.matchedLength();
|
||||
|
||||
// if matchedLength == 0, the program will get stuck in an infinite loop
|
||||
Q_ASSERT( _searchText.matchedLength() > 0 );
|
||||
// ignore any regular expressions which match an empty string.
|
||||
// otherwise the while loop below will run indefinitely
|
||||
static const QString emptyString("");
|
||||
if ( _searchText.exactMatch(emptyString) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (pos >= 0) {
|
||||
pos = _searchText.indexIn(*text,pos);
|
||||
|
||||
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);
|
||||
|
||||
//kDebug() << "start " << startLine << " / " << startColumn;
|
||||
//kDebug() << "end " << endLine << " / " << endColumn;
|
||||
|
||||
RegExpFilter::HotSpot * spot = newHotSpot(startLine,startColumn,
|
||||
endLine,endColumn);
|
||||
spot->setCapturedTexts(_searchText.capturedTexts());
|
||||
|
||||
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) {
|
||||
return new RegExpFilter::HotSpot(startLine,startColumn,
|
||||
endLine,endColumn);
|
||||
int endLine,int endColumn)
|
||||
{
|
||||
return new RegExpFilter::HotSpot(startLine,startColumn,
|
||||
endLine,endColumn);
|
||||
}
|
||||
RegExpFilter::HotSpot * UrlFilter::newHotSpot(int startLine,int startColumn,int endLine,
|
||||
int endColumn) {
|
||||
return new UrlFilter::HotSpot(startLine,startColumn,
|
||||
endLine,endColumn);
|
||||
int endColumn)
|
||||
{
|
||||
return new UrlFilter::HotSpot(startLine,startColumn,
|
||||
endLine,endColumn);
|
||||
}
|
||||
UrlFilter::HotSpot::HotSpot(int startLine,int startColumn,int endLine,int endColumn)
|
||||
: RegExpFilter::HotSpot(startLine,startColumn,endLine,endColumn)
|
||||
, _urlObject(new FilterObject(this)) {
|
||||
setType(Link);
|
||||
: RegExpFilter::HotSpot(startLine,startColumn,endLine,endColumn)
|
||||
, _urlObject(new FilterObject(this))
|
||||
{
|
||||
setType(Link);
|
||||
}
|
||||
QString UrlFilter::HotSpot::tooltip() const {
|
||||
QString url = capturedTexts().first();
|
||||
QString UrlFilter::HotSpot::tooltip() const
|
||||
{
|
||||
QString url = capturedTexts().first();
|
||||
|
||||
const UrlType kind = urlType();
|
||||
const UrlType kind = urlType();
|
||||
|
||||
if ( kind == StandardUrl ) {
|
||||
return QString();
|
||||
} else if ( kind == Email ) {
|
||||
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) ) {
|
||||
return Email;
|
||||
} else {
|
||||
return Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
void UrlFilter::HotSpot::activate(QObject * object) {
|
||||
QString url = capturedTexts().first();
|
||||
|
||||
const UrlType kind = urlType();
|
||||
|
||||
const QString & actionName = object ? object->objectName() : QString();
|
||||
|
||||
if ( actionName == "copy-action" ) {
|
||||
//kDebug() << "Copying url to clipboard:" << url;
|
||||
|
||||
QApplication::clipboard()->setText(url);
|
||||
return;
|
||||
}
|
||||
|
||||
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("://")) {
|
||||
url.prepend("http://");
|
||||
}
|
||||
return QString();
|
||||
} else if ( kind == Email ) {
|
||||
url.prepend("mailto:");
|
||||
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) ) {
|
||||
return Email;
|
||||
} else {
|
||||
return Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
void UrlFilter::HotSpot::activate(QObject * object)
|
||||
{
|
||||
QString url = capturedTexts().first();
|
||||
|
||||
const UrlType kind = urlType();
|
||||
|
||||
const QString & actionName = object ? object->objectName() : QString();
|
||||
|
||||
if ( actionName == "copy-action" ) {
|
||||
//kDebug() << "Copying url to clipboard:" << url;
|
||||
|
||||
QApplication::clipboard()->setText(url);
|
||||
return;
|
||||
}
|
||||
|
||||
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("://")) {
|
||||
url.prepend("http://");
|
||||
}
|
||||
} 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
|
||||
@@ -450,48 +497,52 @@ 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() {
|
||||
setRegExp( CompleteUrlRegExp );
|
||||
UrlFilter::UrlFilter()
|
||||
{
|
||||
setRegExp( CompleteUrlRegExp );
|
||||
}
|
||||
UrlFilter::HotSpot::~HotSpot() {
|
||||
delete _urlObject;
|
||||
UrlFilter::HotSpot::~HotSpot()
|
||||
{
|
||||
delete _urlObject;
|
||||
}
|
||||
void FilterObject::activated() {
|
||||
_filter->activate(sender());
|
||||
void FilterObject::activated()
|
||||
{
|
||||
_filter->activate(sender());
|
||||
}
|
||||
QList<QAction *> UrlFilter::HotSpot::actions() {
|
||||
QList<QAction *> list;
|
||||
QList<QAction *> UrlFilter::HotSpot::actions()
|
||||
{
|
||||
QList<QAction *> list;
|
||||
|
||||
const UrlType kind = urlType();
|
||||
const UrlType kind = urlType();
|
||||
|
||||
QAction * openAction = new QAction(_urlObject);
|
||||
QAction * copyAction = new QAction(_urlObject);;
|
||||
QAction * openAction = new QAction(_urlObject);
|
||||
QAction * copyAction = new QAction(_urlObject);;
|
||||
|
||||
Q_ASSERT( kind == StandardUrl || kind == Email );
|
||||
Q_ASSERT( kind == StandardUrl || kind == Email );
|
||||
|
||||
if ( kind == StandardUrl ) {
|
||||
openAction->setText(("Open Link"));
|
||||
copyAction->setText(("Copy Link Address"));
|
||||
} else if ( kind == Email ) {
|
||||
openAction->setText(("Send Email To..."));
|
||||
copyAction->setText(("Copy Email Address"));
|
||||
}
|
||||
if ( kind == StandardUrl ) {
|
||||
openAction->setText(("Open Link"));
|
||||
copyAction->setText(("Copy Link Address"));
|
||||
} else if ( kind == Email ) {
|
||||
openAction->setText(("Send Email To..."));
|
||||
copyAction->setText(("Copy Email Address"));
|
||||
}
|
||||
|
||||
// object names are set here so that the hotspot performs the
|
||||
// correct action when activated() is called with the triggered
|
||||
// action passed as a parameter.
|
||||
openAction->setObjectName("open-action");
|
||||
copyAction->setObjectName("copy-action");
|
||||
// object names are set here so that the hotspot performs the
|
||||
// correct action when activated() is called with the triggered
|
||||
// action passed as a parameter.
|
||||
openAction->setObjectName("open-action");
|
||||
copyAction->setObjectName("copy-action");
|
||||
|
||||
QObject::connect( openAction , SIGNAL(triggered()) , _urlObject , SLOT(activated()) );
|
||||
QObject::connect( copyAction , SIGNAL(triggered()) , _urlObject , SLOT(activated()) );
|
||||
QObject::connect( openAction , SIGNAL(triggered()) , _urlObject , SLOT(activated()) );
|
||||
QObject::connect( copyAction , SIGNAL(triggered()) , _urlObject , SLOT(activated()) );
|
||||
|
||||
list << openAction;
|
||||
list << copyAction;
|
||||
list << openAction;
|
||||
list << copyAction;
|
||||
|
||||
return list;
|
||||
return list;
|
||||
}
|
||||
|
||||
//#include "moc_Filter.cpp"
|
||||
|
||||
+233
-223
@@ -33,7 +33,8 @@
|
||||
// Local
|
||||
#include "Character.h"
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
/**
|
||||
* A filter processes blocks of text looking for certain patterns (such as URLs or keywords from a list)
|
||||
@@ -53,131 +54,133 @@ namespace Konsole {
|
||||
* When processing the text they should create instances of Filter::HotSpot subclasses for sections of interest
|
||||
* and add them to the filter's list of hotspots using addHotSpot()
|
||||
*/
|
||||
class Filter {
|
||||
class Filter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Represents an area of text which matched the pattern a particular filter has been looking for.
|
||||
*
|
||||
* Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ),
|
||||
* and an action. When the user performs some activity such as a mouse-click in a hotspot area ( the exact
|
||||
* action will depend on what is displaying the block of text which the filter is processing ), the hotspot's
|
||||
* 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.
|
||||
*/
|
||||
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();
|
||||
* Represents an area of text which matched the pattern a particular filter has been looking for.
|
||||
*
|
||||
* Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ),
|
||||
* and an action. When the user performs some activity such as a mouse-click in a hotspot area ( the exact
|
||||
* action will depend on what is displaying the block of text which the filter is processing ), the hotspot's
|
||||
* 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.
|
||||
*/
|
||||
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();
|
||||
|
||||
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<QAction *> 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;
|
||||
|
||||
protected:
|
||||
/** 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;
|
||||
|
||||
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<QAction *> actions();
|
||||
/** Constructs a new filter. */
|
||||
Filter();
|
||||
virtual ~Filter();
|
||||
|
||||
/** Causes the filter to process the block of text currently in its internal buffer */
|
||||
virtual void process() = 0;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Empties the filters internal buffer and resets the line count back to 0.
|
||||
* All hotspots are deleted.
|
||||
*/
|
||||
virtual QString tooltip() const;
|
||||
void reset();
|
||||
|
||||
protected:
|
||||
/** Sets the type of a hotspot. This should only be set once */
|
||||
void setType(Type type);
|
||||
/** Adds a new line of text to the filter and increments the line count */
|
||||
//void addLine(const QString& string);
|
||||
|
||||
private:
|
||||
int _startLine;
|
||||
int _startColumn;
|
||||
int _endLine;
|
||||
int _endColumn;
|
||||
Type _type;
|
||||
/** Returns the hotspot which covers the given @p line and @p column, or 0 if no hotspot covers that area */
|
||||
HotSpot * hotSpotAt(int line , int column) const;
|
||||
|
||||
};
|
||||
/** Returns the list of hotspots identified by the filter */
|
||||
QList<HotSpot *> hotSpots() const;
|
||||
|
||||
/** Constructs a new filter. */
|
||||
Filter();
|
||||
virtual ~Filter();
|
||||
/** Returns the list of hotspots identified by the filter which occur on a given line */
|
||||
QList<HotSpot *> hotSpotsAtLine(int line) const;
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/** Adds a new line of text to the filter and increments the line count */
|
||||
//void addLine(const QString& string);
|
||||
|
||||
/** Returns the hotspot which covers the given @p line and @p column, or 0 if no hotspot covers that area */
|
||||
HotSpot * hotSpotAt(int line , int column) const;
|
||||
|
||||
/** Returns the list of hotspots identified by the filter */
|
||||
QList<HotSpot *> hotSpots() const;
|
||||
|
||||
/** Returns the list of hotspots identified by the filter which occur on a given line */
|
||||
QList<HotSpot *> hotSpotsAtLine(int line) const;
|
||||
|
||||
/**
|
||||
* TODO: Document me
|
||||
*/
|
||||
void setBuffer(const QString * buffer , const QList<int>* linePositions);
|
||||
/**
|
||||
* TODO: Document me
|
||||
*/
|
||||
void setBuffer(const QString * buffer , const QList<int>* linePositions);
|
||||
|
||||
protected:
|
||||
/** Adds a new hotspot to the list */
|
||||
void addHotSpot(HotSpot *);
|
||||
/** Returns the internal buffer */
|
||||
const QString * buffer();
|
||||
/** Converts a character position within buffer() to a line and column */
|
||||
void getLineColumn(int position , int & startLine , int & startColumn);
|
||||
/** Adds a new hotspot to the list */
|
||||
void addHotSpot(HotSpot *);
|
||||
/** Returns the internal buffer */
|
||||
const QString * buffer();
|
||||
/** Converts a character position within buffer() to a line and column */
|
||||
void getLineColumn(int position , int & startLine , int & startColumn);
|
||||
|
||||
private:
|
||||
QMultiHash<int,HotSpot *> _hotspots;
|
||||
QList<HotSpot *> _hotspotList;
|
||||
QMultiHash<int,HotSpot *> _hotspots;
|
||||
QList<HotSpot *> _hotspotList;
|
||||
|
||||
const QList<int>* _linePositions;
|
||||
const QString * _buffer;
|
||||
const QList<int>* _linePositions;
|
||||
const QString * _buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -187,114 +190,119 @@ private:
|
||||
* Subclasses can reimplement newHotSpot() to return custom hotspot types when matches for the regular expression
|
||||
* are found.
|
||||
*/
|
||||
class RegExpFilter : public Filter {
|
||||
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.
|
||||
*/
|
||||
class HotSpot : public Filter::HotSpot {
|
||||
public:
|
||||
HotSpot(int startLine, int startColumn, int endLine , int endColumn);
|
||||
virtual void activate(QObject * object = 0);
|
||||
/**
|
||||
* Type of hotspot created by RegExpFilter. The capturedTexts() method can be used to find the text
|
||||
* matched by the filter's regular expression.
|
||||
*/
|
||||
class HotSpot : public Filter::HotSpot
|
||||
{
|
||||
public:
|
||||
HotSpot(int startLine, int startColumn, int endLine , int endColumn);
|
||||
virtual void activate(QObject * object = 0);
|
||||
|
||||
/** Sets the captured texts associated with this hotspot */
|
||||
void setCapturedTexts(const QStringList & texts);
|
||||
/** Returns the texts found by the filter when matching the filter's regular expression */
|
||||
QStringList capturedTexts() const;
|
||||
private:
|
||||
QStringList _capturedTexts;
|
||||
};
|
||||
/** Sets the captured texts associated with this hotspot */
|
||||
void setCapturedTexts(const QStringList & texts);
|
||||
/** Returns the texts found by the filter when matching the filter's regular expression */
|
||||
QStringList capturedTexts() const;
|
||||
private:
|
||||
QStringList _capturedTexts;
|
||||
};
|
||||
|
||||
/** Constructs a new regular expression filter */
|
||||
RegExpFilter();
|
||||
/** Constructs a new regular expression filter */
|
||||
RegExpFilter();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void setRegExp(const QRegExp & text);
|
||||
/** Returns the regular expression which the filter searches for in blocks of text */
|
||||
QRegExp regExp() const;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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()
|
||||
*
|
||||
* If regexp matches the empty string, then process() will return immediately
|
||||
* without finding results.
|
||||
*/
|
||||
virtual void process();
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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);
|
||||
/**
|
||||
* 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);
|
||||
|
||||
private:
|
||||
QRegExp _searchText;
|
||||
QRegExp _searchText;
|
||||
};
|
||||
|
||||
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
|
||||
* at the given URL when called.
|
||||
*/
|
||||
class HotSpot : public RegExpFilter::HotSpot {
|
||||
public:
|
||||
HotSpot(int startLine,int startColumn,int endLine,int endColumn);
|
||||
virtual ~HotSpot();
|
||||
|
||||
virtual QList<QAction *> actions();
|
||||
|
||||
/**
|
||||
* Open a web browser at the current URL. The url itself can be determined using
|
||||
* the capturedTexts() method.
|
||||
* Hotspot type created by UrlFilter instances. The activate() method opens a web browser
|
||||
* at the given URL when called.
|
||||
*/
|
||||
virtual void activate(QObject * object = 0);
|
||||
class HotSpot : public RegExpFilter::HotSpot
|
||||
{
|
||||
public:
|
||||
HotSpot(int startLine,int startColumn,int endLine,int endColumn);
|
||||
virtual ~HotSpot();
|
||||
|
||||
virtual QString tooltip() const;
|
||||
private:
|
||||
enum UrlType {
|
||||
StandardUrl,
|
||||
Email,
|
||||
Unknown
|
||||
virtual QList<QAction *> actions();
|
||||
|
||||
/**
|
||||
* Open a web browser at the current URL. The url itself can be determined using
|
||||
* the capturedTexts() method.
|
||||
*/
|
||||
virtual void activate(QObject * object = 0);
|
||||
|
||||
virtual QString tooltip() const;
|
||||
private:
|
||||
enum UrlType {
|
||||
StandardUrl,
|
||||
Email,
|
||||
Unknown
|
||||
};
|
||||
UrlType urlType() const;
|
||||
|
||||
FilterObject * _urlObject;
|
||||
};
|
||||
UrlType urlType() const;
|
||||
|
||||
FilterObject * _urlObject;
|
||||
};
|
||||
|
||||
UrlFilter();
|
||||
UrlFilter();
|
||||
|
||||
protected:
|
||||
virtual RegExpFilter::HotSpot * newHotSpot(int,int,int,int);
|
||||
virtual RegExpFilter::HotSpot * newHotSpot(int,int,int,int);
|
||||
|
||||
private:
|
||||
|
||||
static const QRegExp FullUrlRegExp;
|
||||
static const QRegExp EmailAddressRegExp;
|
||||
static const QRegExp FullUrlRegExp;
|
||||
static const QRegExp EmailAddressRegExp;
|
||||
|
||||
// combined OR of FullUrlRegExp and EmailAddressRegExp
|
||||
static const QRegExp CompleteUrlRegExp;
|
||||
// combined OR of FullUrlRegExp and EmailAddressRegExp
|
||||
static const QRegExp CompleteUrlRegExp;
|
||||
};
|
||||
|
||||
class FilterObject : public QObject {
|
||||
Q_OBJECT
|
||||
class FilterObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FilterObject(Filter::HotSpot * filter) : _filter(filter) {}
|
||||
FilterObject(Filter::HotSpot * filter) : _filter(filter) {}
|
||||
private slots:
|
||||
void activated();
|
||||
void activated();
|
||||
private:
|
||||
Filter::HotSpot * _filter;
|
||||
Filter::HotSpot * _filter;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -314,57 +322,59 @@ private:
|
||||
* The hotSpots() and hotSpotsAtLine() method return all of the hotspots in the text and on
|
||||
* a given line respectively.
|
||||
*/
|
||||
class FilterChain : protected QList<Filter *> {
|
||||
class FilterChain : protected QList<Filter *>
|
||||
{
|
||||
public:
|
||||
virtual ~FilterChain();
|
||||
virtual ~FilterChain();
|
||||
|
||||
/** Adds a new filter to the chain. The chain will delete this filter when it is destroyed */
|
||||
void addFilter(Filter * filter);
|
||||
/** Removes a filter from the chain. The chain will no longer delete the filter when destroyed */
|
||||
void removeFilter(Filter * filter);
|
||||
/** Returns true if the chain contains @p filter */
|
||||
bool containsFilter(Filter * filter);
|
||||
/** Removes all filters from the chain */
|
||||
void clear();
|
||||
/** Adds a new filter to the chain. The chain will delete this filter when it is destroyed */
|
||||
void addFilter(Filter * filter);
|
||||
/** Removes a filter from the chain. The chain will no longer delete the filter when destroyed */
|
||||
void removeFilter(Filter * filter);
|
||||
/** Returns true if the chain contains @p filter */
|
||||
bool containsFilter(Filter * filter);
|
||||
/** Removes all filters from the chain */
|
||||
void clear();
|
||||
|
||||
/** Resets each filter in the chain */
|
||||
void reset();
|
||||
/**
|
||||
* Processes each filter in the chain
|
||||
*/
|
||||
void process();
|
||||
/** Resets each filter in the chain */
|
||||
void reset();
|
||||
/**
|
||||
* 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<int>* linePositions);
|
||||
/** Sets the buffer for each filter in the chain to process. */
|
||||
void setBuffer(const QString * buffer , const QList<int>* 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;
|
||||
/** Returns a list of all the hotspots in all the chain's filters */
|
||||
QList<Filter::HotSpot *> hotSpots() const;
|
||||
/** Returns a list of all hotspots at the given line in all the chain's filters */
|
||||
QList<Filter::HotSpot> hotSpotsAtLine(int line) const;
|
||||
/** 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;
|
||||
/** Returns a list of all the hotspots in all the chain's filters */
|
||||
QList<Filter::HotSpot *> hotSpots() const;
|
||||
/** Returns a list of all hotspots at the given line in all the chain's filters */
|
||||
QList<Filter::HotSpot> hotSpotsAtLine(int line) const;
|
||||
|
||||
};
|
||||
|
||||
/** A filter chain which processes character images from terminal displays */
|
||||
class TerminalImageFilterChain : public FilterChain {
|
||||
class TerminalImageFilterChain : public FilterChain
|
||||
{
|
||||
public:
|
||||
TerminalImageFilterChain();
|
||||
virtual ~TerminalImageFilterChain();
|
||||
TerminalImageFilterChain();
|
||||
virtual ~TerminalImageFilterChain();
|
||||
|
||||
/**
|
||||
* Set the current terminal image to @p image.
|
||||
*
|
||||
* @param image The terminal image
|
||||
* @param lines The number of lines in the terminal image
|
||||
* @param columns The number of columns in the terminal image
|
||||
*/
|
||||
void setImage(const Character * const image , int lines , int columns,
|
||||
const QVector<LineProperty>& lineProperties);
|
||||
/**
|
||||
* Set the current terminal image to @p image.
|
||||
*
|
||||
* @param image The terminal image
|
||||
* @param lines The number of lines in the terminal image
|
||||
* @param columns The number of columns in the terminal image
|
||||
*/
|
||||
void setImage(const Character * const image , int lines , int columns,
|
||||
const QVector<LineProperty>& lineProperties);
|
||||
|
||||
private:
|
||||
QString * _buffer;
|
||||
QList<int>* _linePositions;
|
||||
QString * _buffer;
|
||||
QList<int>* _linePositions;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+412
-345
@@ -84,105 +84,113 @@ FIXME: There is noticeable decrease in speed, also. Perhaps,
|
||||
*/
|
||||
|
||||
HistoryFile::HistoryFile()
|
||||
: ion(-1),
|
||||
length(0),
|
||||
fileMap(0) {
|
||||
if (tmpFile.open()) {
|
||||
tmpFile.setAutoRemove(true);
|
||||
ion = tmpFile.handle();
|
||||
}
|
||||
: ion(-1),
|
||||
length(0),
|
||||
fileMap(0)
|
||||
{
|
||||
if (tmpFile.open()) {
|
||||
tmpFile.setAutoRemove(true);
|
||||
ion = tmpFile.handle();
|
||||
}
|
||||
}
|
||||
|
||||
HistoryFile::~HistoryFile() {
|
||||
if (fileMap) {
|
||||
unmap();
|
||||
}
|
||||
HistoryFile::~HistoryFile()
|
||||
{
|
||||
if (fileMap) {
|
||||
unmap();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Mapping the entire file in will cause problems if the history file becomes exceedingly large,
|
||||
//(ie. larger than available memory). HistoryFile::map() should only map in sections of the file at a time,
|
||||
//to avoid this.
|
||||
void HistoryFile::map() {
|
||||
assert( fileMap == 0 );
|
||||
void HistoryFile::map()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryFile::unmap() {
|
||||
int result = munmap( fileMap , length );
|
||||
assert( result == 0 );
|
||||
|
||||
fileMap = 0;
|
||||
}
|
||||
|
||||
bool HistoryFile::isMapped() {
|
||||
return (fileMap != 0);
|
||||
}
|
||||
|
||||
void HistoryFile::add(const unsigned char * bytes, int len) {
|
||||
if ( fileMap ) {
|
||||
unmap();
|
||||
}
|
||||
|
||||
readWriteBalance++;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if ( fileMap ) {
|
||||
for (int i=0; i<len; i++) {
|
||||
bytes[i]=fileMap[loc+i];
|
||||
//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;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
void HistoryFile::unmap()
|
||||
{
|
||||
int result = munmap( fileMap , length );
|
||||
assert( result == 0 );
|
||||
|
||||
fileMap = 0;
|
||||
}
|
||||
|
||||
bool HistoryFile::isMapped()
|
||||
{
|
||||
return (fileMap != 0);
|
||||
}
|
||||
|
||||
void HistoryFile::add(const unsigned char * bytes, int len)
|
||||
{
|
||||
if ( fileMap ) {
|
||||
unmap();
|
||||
}
|
||||
|
||||
readWriteBalance++;
|
||||
|
||||
int rc = 0;
|
||||
|
||||
if (loc < 0 || len < 0 || loc + len > length) {
|
||||
fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc);
|
||||
}
|
||||
rc = lseek(ion,loc,SEEK_SET);
|
||||
rc = lseek(ion,length,SEEK_SET);
|
||||
if (rc < 0) {
|
||||
perror("HistoryFile::get.seek");
|
||||
return;
|
||||
perror("HistoryFile::add.seek");
|
||||
return;
|
||||
}
|
||||
rc = read(ion,bytes,len);
|
||||
rc = write(ion,bytes,len);
|
||||
if (rc < 0) {
|
||||
perror("HistoryFile::get.read");
|
||||
return;
|
||||
perror("HistoryFile::add.write");
|
||||
return;
|
||||
}
|
||||
}
|
||||
length += rc;
|
||||
}
|
||||
|
||||
int HistoryFile::len() {
|
||||
return length;
|
||||
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();
|
||||
}
|
||||
|
||||
if ( fileMap ) {
|
||||
for (int i=0; i<len; i++) {
|
||||
bytes[i]=fileMap[loc+i];
|
||||
}
|
||||
} else {
|
||||
int rc = 0;
|
||||
|
||||
if (loc < 0 || len < 0 || loc + len > length) {
|
||||
fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc);
|
||||
}
|
||||
rc = lseek(ion,loc,SEEK_SET);
|
||||
if (rc < 0) {
|
||||
perror("HistoryFile::get.seek");
|
||||
return;
|
||||
}
|
||||
rc = read(ion,bytes,len);
|
||||
if (rc < 0) {
|
||||
perror("HistoryFile::get.read");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int HistoryFile::len()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
@@ -190,15 +198,18 @@ int HistoryFile::len() {
|
||||
|
||||
|
||||
HistoryScroll::HistoryScroll(HistoryType * t)
|
||||
: m_histType(t) {
|
||||
: m_histType(t)
|
||||
{
|
||||
}
|
||||
|
||||
HistoryScroll::~HistoryScroll() {
|
||||
delete m_histType;
|
||||
HistoryScroll::~HistoryScroll()
|
||||
{
|
||||
delete m_histType;
|
||||
}
|
||||
|
||||
bool HistoryScroll::hasScroll() {
|
||||
return true;
|
||||
bool HistoryScroll::hasScroll()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// History Scroll File //////////////////////////////////////
|
||||
@@ -215,426 +226,482 @@ bool HistoryScroll::hasScroll() {
|
||||
*/
|
||||
|
||||
HistoryScrollFile::HistoryScrollFile(const QString & logFileName)
|
||||
: HistoryScroll(new HistoryTypeFile(logFileName)),
|
||||
m_logFileName(logFileName) {
|
||||
: HistoryScroll(new HistoryTypeFile(logFileName)),
|
||||
m_logFileName(logFileName)
|
||||
{
|
||||
}
|
||||
|
||||
HistoryScrollFile::~HistoryScrollFile() {
|
||||
HistoryScrollFile::~HistoryScrollFile()
|
||||
{
|
||||
}
|
||||
|
||||
int HistoryScrollFile::getLines() {
|
||||
return index.len() / sizeof(int);
|
||||
int HistoryScrollFile::getLines()
|
||||
{
|
||||
return index.len() / sizeof(int);
|
||||
}
|
||||
|
||||
int HistoryScrollFile::getLineLen(int lineno) {
|
||||
return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(Character);
|
||||
int HistoryScrollFile::getLineLen(int lineno)
|
||||
{
|
||||
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;
|
||||
bool HistoryScrollFile::isWrappedLine(int lineno)
|
||||
{
|
||||
if (lineno>=0 && lineno <= getLines()) {
|
||||
unsigned char flag;
|
||||
lineflags.get((unsigned char *)&flag,sizeof(unsigned char),(lineno)*sizeof(unsigned char));
|
||||
return flag;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int HistoryScrollFile::startOfLine(int lineno) {
|
||||
if (lineno <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (lineno <= getLines()) {
|
||||
int HistoryScrollFile::startOfLine(int lineno)
|
||||
{
|
||||
if (lineno <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (lineno <= getLines()) {
|
||||
|
||||
if (!index.isMapped()) {
|
||||
index.map();
|
||||
if (!index.isMapped()) {
|
||||
index.map();
|
||||
}
|
||||
|
||||
int res;
|
||||
index.get((unsigned char *)&res,sizeof(int),(lineno-1)*sizeof(int));
|
||||
return res;
|
||||
}
|
||||
return cells.len();
|
||||
}
|
||||
|
||||
void HistoryScrollFile::getCells(int lineno, int colno, int count, Character res[])
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
void HistoryScrollFile::addLine(bool previousWrapped)
|
||||
{
|
||||
if (index.isMapped()) {
|
||||
index.unmap();
|
||||
}
|
||||
|
||||
int res;
|
||||
index.get((unsigned char *)&res,sizeof(int),(lineno-1)*sizeof(int));
|
||||
return res;
|
||||
}
|
||||
return cells.len();
|
||||
}
|
||||
|
||||
void HistoryScrollFile::getCells(int lineno, int colno, int count, Character res[]) {
|
||||
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));
|
||||
}
|
||||
|
||||
void HistoryScrollFile::addLine(bool previousWrapped) {
|
||||
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) {
|
||||
setMaxNbLines(maxLineCount);
|
||||
: HistoryScroll(new HistoryTypeBuffer(maxLineCount))
|
||||
,_historyBuffer()
|
||||
,_maxLineCount(0)
|
||||
,_usedLines(0)
|
||||
,_head(0)
|
||||
{
|
||||
setMaxNbLines(maxLineCount);
|
||||
}
|
||||
|
||||
HistoryScrollBuffer::~HistoryScrollBuffer() {
|
||||
delete[] _historyBuffer;
|
||||
HistoryScrollBuffer::~HistoryScrollBuffer()
|
||||
{
|
||||
delete[] _historyBuffer;
|
||||
}
|
||||
|
||||
void HistoryScrollBuffer::addCellsVector(const QVector<Character>& cells) {
|
||||
_head++;
|
||||
if ( _usedLines < _maxLineCount ) {
|
||||
_usedLines++;
|
||||
}
|
||||
void HistoryScrollBuffer::addCellsVector(const QVector<Character>& cells)
|
||||
{
|
||||
_head++;
|
||||
if ( _usedLines < _maxLineCount ) {
|
||||
_usedLines++;
|
||||
}
|
||||
|
||||
if ( _head >= _maxLineCount ) {
|
||||
_head = 0;
|
||||
}
|
||||
if ( _head >= _maxLineCount ) {
|
||||
_head = 0;
|
||||
}
|
||||
|
||||
_historyBuffer[bufferIndex(_usedLines-1)] = cells;
|
||||
_wrappedLine[bufferIndex(_usedLines-1)] = false;
|
||||
_historyBuffer[bufferIndex(_usedLines-1)] = cells;
|
||||
_wrappedLine[bufferIndex(_usedLines-1)] = false;
|
||||
}
|
||||
void HistoryScrollBuffer::addCells(const Character a[], int count) {
|
||||
HistoryLine newLine(count);
|
||||
qCopy(a,a+count,newLine.begin());
|
||||
void HistoryScrollBuffer::addCells(const Character a[], int count)
|
||||
{
|
||||
HistoryLine newLine(count);
|
||||
qCopy(a,a+count,newLine.begin());
|
||||
|
||||
addCellsVector(newLine);
|
||||
addCellsVector(newLine);
|
||||
}
|
||||
|
||||
void HistoryScrollBuffer::addLine(bool previousWrapped) {
|
||||
_wrappedLine[bufferIndex(_usedLines-1)] = previousWrapped;
|
||||
void HistoryScrollBuffer::addLine(bool previousWrapped)
|
||||
{
|
||||
_wrappedLine[bufferIndex(_usedLines-1)] = previousWrapped;
|
||||
}
|
||||
|
||||
int HistoryScrollBuffer::getLines() {
|
||||
return _usedLines;
|
||||
int HistoryScrollBuffer::getLines()
|
||||
{
|
||||
return _usedLines;
|
||||
}
|
||||
|
||||
int HistoryScrollBuffer::getLineLen(int lineNumber) {
|
||||
Q_ASSERT( lineNumber >= 0 && lineNumber < _maxLineCount );
|
||||
int HistoryScrollBuffer::getLineLen(int lineNumber)
|
||||
{
|
||||
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 );
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
void HistoryScrollBuffer::getCells(int lineNumber, int startColumn, int count, Character * buffer)
|
||||
{
|
||||
if ( count == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Q_ASSERT( lineNumber < _maxLineCount );
|
||||
Q_ASSERT( lineNumber < _maxLineCount );
|
||||
|
||||
if (lineNumber >= _usedLines) {
|
||||
memset(buffer, 0, count * sizeof(Character));
|
||||
return;
|
||||
}
|
||||
if (lineNumber >= _usedLines) {
|
||||
memset(buffer, 0, count * sizeof(Character));
|
||||
return;
|
||||
}
|
||||
|
||||
const HistoryLine & line = _historyBuffer[bufferIndex(lineNumber)];
|
||||
const HistoryLine & line = _historyBuffer[bufferIndex(lineNumber)];
|
||||
|
||||
//kDebug() << "startCol " << startColumn;
|
||||
//kDebug() << "line.size() " << line.size();
|
||||
//kDebug() << "count " << count;
|
||||
//kDebug() << "startCol " << startColumn;
|
||||
//kDebug() << "line.size() " << line.size();
|
||||
//kDebug() << "count " << count;
|
||||
|
||||
Q_ASSERT( startColumn <= line.size() - count );
|
||||
Q_ASSERT( startColumn <= line.size() - count );
|
||||
|
||||
memcpy(buffer, line.constData() + startColumn , count * sizeof(Character));
|
||||
memcpy(buffer, line.constData() + startColumn , count * sizeof(Character));
|
||||
}
|
||||
|
||||
void HistoryScrollBuffer::setMaxNbLines(unsigned int lineCount) {
|
||||
HistoryLine * oldBuffer = _historyBuffer;
|
||||
HistoryLine * newBuffer = new HistoryLine[lineCount];
|
||||
void HistoryScrollBuffer::setMaxNbLines(unsigned int lineCount)
|
||||
{
|
||||
HistoryLine * oldBuffer = _historyBuffer;
|
||||
HistoryLine * newBuffer = new HistoryLine[lineCount];
|
||||
|
||||
for ( int i = 0 ; i < qMin(_usedLines,(int)lineCount) ; i++ ) {
|
||||
newBuffer[i] = oldBuffer[bufferIndex(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;
|
||||
_usedLines = qMin(_usedLines,(int)lineCount);
|
||||
_maxLineCount = lineCount;
|
||||
_head = ( _usedLines == _maxLineCount ) ? 0 : _usedLines-1;
|
||||
|
||||
_historyBuffer = newBuffer;
|
||||
delete[] oldBuffer;
|
||||
_historyBuffer = newBuffer;
|
||||
delete[] oldBuffer;
|
||||
|
||||
_wrappedLine.resize(lineCount);
|
||||
_wrappedLine.resize(lineCount);
|
||||
}
|
||||
|
||||
int HistoryScrollBuffer::bufferIndex(int lineNumber) {
|
||||
Q_ASSERT( lineNumber >= 0 );
|
||||
Q_ASSERT( lineNumber < _maxLineCount );
|
||||
Q_ASSERT( (_usedLines == _maxLineCount) || lineNumber <= _head );
|
||||
int HistoryScrollBuffer::bufferIndex(int lineNumber)
|
||||
{
|
||||
Q_ASSERT( lineNumber >= 0 );
|
||||
Q_ASSERT( lineNumber < _maxLineCount );
|
||||
Q_ASSERT( (_usedLines == _maxLineCount) || lineNumber <= _head );
|
||||
|
||||
if ( _usedLines == _maxLineCount ) {
|
||||
return (_head+lineNumber+1) % _maxLineCount;
|
||||
} else {
|
||||
return lineNumber;
|
||||
}
|
||||
if ( _usedLines == _maxLineCount ) {
|
||||
return (_head+lineNumber+1) % _maxLineCount;
|
||||
} else {
|
||||
return lineNumber;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// History Scroll None //////////////////////////////////////
|
||||
|
||||
HistoryScrollNone::HistoryScrollNone()
|
||||
: HistoryScroll(new HistoryTypeNone()) {
|
||||
: HistoryScroll(new HistoryTypeNone())
|
||||
{
|
||||
}
|
||||
|
||||
HistoryScrollNone::~HistoryScrollNone() {
|
||||
HistoryScrollNone::~HistoryScrollNone()
|
||||
{
|
||||
}
|
||||
|
||||
bool HistoryScrollNone::hasScroll() {
|
||||
return false;
|
||||
bool HistoryScrollNone::hasScroll()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int HistoryScrollNone::getLines() {
|
||||
return 0;
|
||||
int HistoryScrollNone::getLines()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HistoryScrollNone::getLineLen(int) {
|
||||
return 0;
|
||||
int HistoryScrollNone::getLineLen(int)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool HistoryScrollNone::isWrappedLine(int /*lineno*/) {
|
||||
return false;
|
||||
bool HistoryScrollNone::isWrappedLine(int /*lineno*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void HistoryScrollNone::getCells(int, int, int, Character []) {
|
||||
void HistoryScrollNone::getCells(int, int, int, Character [])
|
||||
{
|
||||
}
|
||||
|
||||
void HistoryScrollNone::addCells(const Character [], int) {
|
||||
void HistoryScrollNone::addCells(const Character [], int)
|
||||
{
|
||||
}
|
||||
|
||||
void HistoryScrollNone::addLine(bool) {
|
||||
void HistoryScrollNone::addLine(bool)
|
||||
{
|
||||
}
|
||||
|
||||
// History Scroll BlockArray //////////////////////////////////////
|
||||
|
||||
HistoryScrollBlockArray::HistoryScrollBlockArray(size_t size)
|
||||
: HistoryScroll(new HistoryTypeBlockArray(size)) {
|
||||
m_blockArray.setHistorySize(size); // nb. of lines.
|
||||
: HistoryScroll(new HistoryTypeBlockArray(size))
|
||||
{
|
||||
m_blockArray.setHistorySize(size); // nb. of lines.
|
||||
}
|
||||
|
||||
HistoryScrollBlockArray::~HistoryScrollBlockArray() {
|
||||
HistoryScrollBlockArray::~HistoryScrollBlockArray()
|
||||
{
|
||||
}
|
||||
|
||||
int HistoryScrollBlockArray::getLines() {
|
||||
return m_lineLengths.count();
|
||||
int HistoryScrollBlockArray::getLines()
|
||||
{
|
||||
return m_lineLengths.count();
|
||||
}
|
||||
|
||||
int HistoryScrollBlockArray::getLineLen(int lineno) {
|
||||
if ( m_lineLengths.contains(lineno) ) {
|
||||
return m_lineLengths[lineno];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
int HistoryScrollBlockArray::getLineLen(int lineno)
|
||||
{
|
||||
if ( m_lineLengths.contains(lineno) ) {
|
||||
return m_lineLengths[lineno];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool HistoryScrollBlockArray::isWrappedLine(int /*lineno*/) {
|
||||
return false;
|
||||
bool HistoryScrollBlockArray::isWrappedLine(int /*lineno*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void HistoryScrollBlockArray::getCells(int lineno, int colno,
|
||||
int count, Character res[]) {
|
||||
if (!count) {
|
||||
return;
|
||||
}
|
||||
int count, Character res[])
|
||||
{
|
||||
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();
|
||||
void HistoryScrollBlockArray::addCells(const Character a[], int count)
|
||||
{
|
||||
Block * b = m_blockArray.lastBlock();
|
||||
|
||||
if (!b) {
|
||||
return;
|
||||
}
|
||||
if (!b) {
|
||||
return;
|
||||
}
|
||||
|
||||
// put cells in block's data
|
||||
assert((count * sizeof(Character)) < ENTRIES);
|
||||
// put cells in block's data
|
||||
assert((count * sizeof(Character)) < ENTRIES);
|
||||
|
||||
memset(b->data, 0, ENTRIES);
|
||||
memset(b->data, 0, ENTRIES);
|
||||
|
||||
memcpy(b->data, a, count * sizeof(Character));
|
||||
b->size = count * sizeof(Character);
|
||||
memcpy(b->data, a, count * sizeof(Character));
|
||||
b->size = count * sizeof(Character);
|
||||
|
||||
size_t res = m_blockArray.newBlock();
|
||||
assert (res > 0);
|
||||
Q_UNUSED( res );
|
||||
size_t res = m_blockArray.newBlock();
|
||||
assert (res > 0);
|
||||
Q_UNUSED( res );
|
||||
|
||||
m_lineLengths.insert(m_blockArray.getCurrent(), count);
|
||||
m_lineLengths.insert(m_blockArray.getCurrent(), count);
|
||||
}
|
||||
|
||||
void HistoryScrollBlockArray::addLine(bool) {
|
||||
void HistoryScrollBlockArray::addLine(bool)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// History Types
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
HistoryType::HistoryType() {
|
||||
HistoryType::HistoryType()
|
||||
{
|
||||
}
|
||||
|
||||
HistoryType::~HistoryType() {
|
||||
HistoryType::~HistoryType()
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
HistoryTypeNone::HistoryTypeNone() {
|
||||
HistoryTypeNone::HistoryTypeNone()
|
||||
{
|
||||
}
|
||||
|
||||
bool HistoryTypeNone::isEnabled() const {
|
||||
return false;
|
||||
bool HistoryTypeNone::isEnabled() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HistoryScroll * HistoryTypeNone::scroll(HistoryScroll * old) const {
|
||||
delete old;
|
||||
return new HistoryScrollNone();
|
||||
HistoryScroll * HistoryTypeNone::scroll(HistoryScroll * old) const
|
||||
{
|
||||
delete old;
|
||||
return new HistoryScrollNone();
|
||||
}
|
||||
|
||||
int HistoryTypeNone::maximumLineCount() const {
|
||||
return 0;
|
||||
int HistoryTypeNone::maximumLineCount() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
HistoryTypeBlockArray::HistoryTypeBlockArray(size_t size)
|
||||
: m_size(size) {
|
||||
: m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
bool HistoryTypeBlockArray::isEnabled() const {
|
||||
return true;
|
||||
bool HistoryTypeBlockArray::isEnabled() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int HistoryTypeBlockArray::maximumLineCount() const {
|
||||
return m_size;
|
||||
int HistoryTypeBlockArray::maximumLineCount() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
HistoryScroll * HistoryTypeBlockArray::scroll(HistoryScroll * old) const {
|
||||
delete old;
|
||||
return new HistoryScrollBlockArray(m_size);
|
||||
HistoryScroll * HistoryTypeBlockArray::scroll(HistoryScroll * old) const
|
||||
{
|
||||
delete old;
|
||||
return new HistoryScrollBlockArray(m_size);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
HistoryTypeBuffer::HistoryTypeBuffer(unsigned int nbLines)
|
||||
: m_nbLines(nbLines) {
|
||||
: m_nbLines(nbLines)
|
||||
{
|
||||
}
|
||||
|
||||
bool HistoryTypeBuffer::isEnabled() const {
|
||||
return true;
|
||||
bool HistoryTypeBuffer::isEnabled() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int HistoryTypeBuffer::maximumLineCount() const {
|
||||
return m_nbLines;
|
||||
int HistoryTypeBuffer::maximumLineCount() const
|
||||
{
|
||||
return m_nbLines;
|
||||
}
|
||||
|
||||
HistoryScroll * HistoryTypeBuffer::scroll(HistoryScroll * old) const {
|
||||
if (old) {
|
||||
HistoryScrollBuffer * oldBuffer = dynamic_cast<HistoryScrollBuffer *>(old);
|
||||
if (oldBuffer) {
|
||||
oldBuffer->setMaxNbLines(m_nbLines);
|
||||
return oldBuffer;
|
||||
}
|
||||
HistoryScroll * HistoryTypeBuffer::scroll(HistoryScroll * old) const
|
||||
{
|
||||
if (old) {
|
||||
HistoryScrollBuffer * oldBuffer = dynamic_cast<HistoryScrollBuffer *>(old);
|
||||
if (oldBuffer) {
|
||||
oldBuffer->setMaxNbLines(m_nbLines);
|
||||
return oldBuffer;
|
||||
}
|
||||
|
||||
HistoryScroll * newScroll = new HistoryScrollBuffer(m_nbLines);
|
||||
int lines = old->getLines();
|
||||
int startLine = 0;
|
||||
if (lines > (int) m_nbLines) {
|
||||
startLine = lines - m_nbLines;
|
||||
}
|
||||
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;
|
||||
bool HistoryTypeFile::isEnabled() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const QString & HistoryTypeFile::getFileName() const {
|
||||
return m_fileName;
|
||||
const QString & HistoryTypeFile::getFileName() const
|
||||
{
|
||||
return m_fileName;
|
||||
}
|
||||
|
||||
HistoryScroll * HistoryTypeFile::scroll(HistoryScroll * old) const {
|
||||
if (dynamic_cast<HistoryFile *>(old)) {
|
||||
return old; // Unchanged.
|
||||
}
|
||||
|
||||
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));
|
||||
HistoryScroll * HistoryTypeFile::scroll(HistoryScroll * old) const
|
||||
{
|
||||
if (dynamic_cast<HistoryFile *>(old)) {
|
||||
return old; // Unchanged.
|
||||
}
|
||||
}
|
||||
|
||||
delete old;
|
||||
return newScroll;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
delete old;
|
||||
return newScroll;
|
||||
}
|
||||
|
||||
int HistoryTypeFile::maximumLineCount() const {
|
||||
return 0;
|
||||
int HistoryTypeFile::maximumLineCount() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
+175
-163
@@ -32,46 +32,48 @@
|
||||
#include "BlockArray.h"
|
||||
#include "Character.h"
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
#if 1
|
||||
/*
|
||||
An extendable tmpfile(1) based buffer.
|
||||
*/
|
||||
|
||||
class HistoryFile {
|
||||
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;
|
||||
//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;
|
||||
//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;
|
||||
//when readWriteBalance goes below this threshold, the file will be mmap'ed automatically
|
||||
static const int MAP_THRESHOLD = -1000;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -82,47 +84,48 @@ private:
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class HistoryType;
|
||||
|
||||
class HistoryScroll {
|
||||
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<Character>& 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<Character>& 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;
|
||||
|
||||
};
|
||||
|
||||
@@ -132,69 +135,71 @@ protected:
|
||||
// File-based history (e.g. file log, no limitation in length)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class HistoryScrollFile : public HistoryScroll {
|
||||
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)
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Buffer-based history (limited to a fixed nb of lines)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class HistoryScrollBuffer : public HistoryScroll {
|
||||
class HistoryScrollBuffer : public HistoryScroll
|
||||
{
|
||||
public:
|
||||
typedef QVector<Character> HistoryLine;
|
||||
typedef QVector<Character> 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<Character>& cells);
|
||||
virtual void addLine(bool previousWrapped=false);
|
||||
virtual void addCells(const Character a[], int count);
|
||||
virtual void addCellsVector(const QVector<Character>& 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;
|
||||
HistoryLine * _historyBuffer;
|
||||
QBitArray _wrappedLine;
|
||||
int _maxLineCount;
|
||||
int _usedLines;
|
||||
int _head;
|
||||
|
||||
//QVector<histline*> m_histBuffer;
|
||||
//QBitArray m_wrappedLine;
|
||||
//unsigned int m_maxNbLines;
|
||||
//unsigned int m_nbLines;
|
||||
//unsigned int m_arrayIndex;
|
||||
//bool m_buffFilled;
|
||||
//QVector<histline*> m_histBuffer;
|
||||
//QBitArray m_wrappedLine;
|
||||
//unsigned int m_maxNbLines;
|
||||
//unsigned int m_nbLines;
|
||||
//unsigned int m_arrayIndex;
|
||||
//bool m_buffFilled;
|
||||
};
|
||||
|
||||
/*class HistoryScrollBufferV2 : public HistoryScroll
|
||||
@@ -216,122 +221,129 @@ public:
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Nothing-based history (no history :-)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class HistoryScrollNone : public HistoryScroll {
|
||||
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);
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// BlockArray-based history
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class HistoryScrollBlockArray : public HistoryScroll {
|
||||
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<int,size_t> m_lineLengths;
|
||||
BlockArray m_blockArray;
|
||||
QHash<int,size_t> m_lineLengths;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// History type
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
class HistoryType {
|
||||
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 {
|
||||
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 {
|
||||
class HistoryTypeBlockArray : public HistoryType
|
||||
{
|
||||
public:
|
||||
HistoryTypeBlockArray(size_t size);
|
||||
HistoryTypeBlockArray(size_t size);
|
||||
|
||||
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;
|
||||
|
||||
protected:
|
||||
size_t m_size;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
#if 1
|
||||
class HistoryTypeFile : public HistoryType {
|
||||
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 {
|
||||
class HistoryTypeBuffer : public HistoryType
|
||||
{
|
||||
public:
|
||||
HistoryTypeBuffer(unsigned int nbLines);
|
||||
HistoryTypeBuffer(unsigned int nbLines);
|
||||
|
||||
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;
|
||||
|
||||
protected:
|
||||
unsigned int m_nbLines;
|
||||
unsigned int m_nbLines;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+690
-641
File diff suppressed because it is too large
Load Diff
+429
-406
@@ -40,13 +40,14 @@ typedef void (*CleanUpFunction)();
|
||||
* Helper class for K_GLOBAL_STATIC to clean up the object on library unload or application
|
||||
* shutdown.
|
||||
*/
|
||||
class CleanUpGlobalStatic {
|
||||
class CleanUpGlobalStatic
|
||||
{
|
||||
public:
|
||||
CleanUpFunction func;
|
||||
CleanUpFunction func;
|
||||
|
||||
inline ~CleanUpGlobalStatic() {
|
||||
func();
|
||||
}
|
||||
inline ~CleanUpGlobalStatic() {
|
||||
func();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -111,7 +112,8 @@ static struct K_GLOBAL_STATIC_STRUCT_NAME(NAME) \
|
||||
class QIODevice;
|
||||
class QTextStream;
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
/**
|
||||
* A convertor which maps between key sequences pressed by the user and the
|
||||
@@ -126,265 +128,267 @@ namespace Konsole {
|
||||
* (Shift,Ctrl,Alt,Meta etc.) and state flags which indicate the state
|
||||
* which the terminal must be in for the key sequence to apply.
|
||||
*/
|
||||
class KeyboardTranslator {
|
||||
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.
|
||||
*
|
||||
* This enum describes the states which may be associated with with a particular
|
||||
* entry in the keyboard translation entry.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
AnsiState = 2,
|
||||
/**
|
||||
* TODO More documentation
|
||||
*/
|
||||
CursorKeysState = 4,
|
||||
/**
|
||||
* Indicates that the alternate screen ( typically used by interactive programs
|
||||
* such as screen or vim ) is active
|
||||
*/
|
||||
AlternateScreenState = 8,
|
||||
/** Indicates that any of the modifier keys is active. */
|
||||
AnyModifierState = 16
|
||||
};
|
||||
Q_DECLARE_FLAGS(States,State)
|
||||
|
||||
/**
|
||||
* This enum describes commands which are associated with particular key sequences.
|
||||
*/
|
||||
enum Command {
|
||||
/** Indicates that no command is associated with this command sequence */
|
||||
NoCommand = 0,
|
||||
/** TODO Document me */
|
||||
SendCommand = 1,
|
||||
/** Scroll the terminal display up one page */
|
||||
ScrollPageUpCommand = 2,
|
||||
/** Scroll the terminal display down one page */
|
||||
ScrollPageDownCommand = 4,
|
||||
/** Scroll the terminal display up one line */
|
||||
ScrollLineUpCommand = 8,
|
||||
/** Scroll the terminal display down one line */
|
||||
ScrollLineDownCommand = 16,
|
||||
/** Toggles scroll lock mode */
|
||||
ScrollLockCommand = 32,
|
||||
/** Echos the operating system specific erase character. */
|
||||
EraseCommand = 64
|
||||
};
|
||||
Q_DECLARE_FLAGS(Commands,Command)
|
||||
|
||||
/**
|
||||
* Represents an association between a key sequence pressed by the user
|
||||
* and the character sequence and commands associated with it for a particular
|
||||
* KeyboardTranslator.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
bool isNull() const;
|
||||
|
||||
/** Returns the commands associated with this entry */
|
||||
Command command() const;
|
||||
/** Sets the command associated with this entry. */
|
||||
void setCommand(Command command);
|
||||
|
||||
/**
|
||||
* Returns the character sequence associated with this entry, optionally replacing
|
||||
* wildcard '*' characters with numbers to indicate the keyboard modifiers being pressed.
|
||||
* 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.
|
||||
*
|
||||
* TODO: The numbers used to replace '*' characters are taken from the Konsole/KDE 3 code.
|
||||
* 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.
|
||||
*
|
||||
* @param modifiers The keyboard modifiers being pressed.
|
||||
* This enum describes the states which may be associated with with a particular
|
||||
* entry in the keyboard translation entry.
|
||||
*/
|
||||
QByteArray text(bool expandWildCards = false,
|
||||
Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;
|
||||
|
||||
/** Sets the character sequence associated with this entry */
|
||||
void setText(const QByteArray & text);
|
||||
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
|
||||
*/
|
||||
AnsiState = 2,
|
||||
/**
|
||||
* TODO More documentation
|
||||
*/
|
||||
CursorKeysState = 4,
|
||||
/**
|
||||
* Indicates that the alternate screen ( typically used by interactive programs
|
||||
* such as screen or vim ) is active
|
||||
*/
|
||||
AlternateScreenState = 8,
|
||||
/** Indicates that any of the modifier keys is active. */
|
||||
AnyModifierState = 16
|
||||
};
|
||||
Q_DECLARE_FLAGS(States,State)
|
||||
|
||||
/**
|
||||
* Returns the character sequence associated with this entry,
|
||||
* with any non-printable characters replaced with escape sequences.
|
||||
* This enum describes commands which are associated with particular key sequences.
|
||||
*/
|
||||
enum Command {
|
||||
/** Indicates that no command is associated with this command sequence */
|
||||
NoCommand = 0,
|
||||
/** TODO Document me */
|
||||
SendCommand = 1,
|
||||
/** Scroll the terminal display up one page */
|
||||
ScrollPageUpCommand = 2,
|
||||
/** Scroll the terminal display down one page */
|
||||
ScrollPageDownCommand = 4,
|
||||
/** Scroll the terminal display up one line */
|
||||
ScrollLineUpCommand = 8,
|
||||
/** Scroll the terminal display down one line */
|
||||
ScrollLineDownCommand = 16,
|
||||
/** Toggles scroll lock mode */
|
||||
ScrollLockCommand = 32,
|
||||
/** Echos the operating system specific erase character. */
|
||||
EraseCommand = 64
|
||||
};
|
||||
Q_DECLARE_FLAGS(Commands,Command)
|
||||
|
||||
/**
|
||||
* Represents an association between a key sequence pressed by the user
|
||||
* and the character sequence and commands associated with it for a particular
|
||||
* KeyboardTranslator.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
bool isNull() const;
|
||||
|
||||
/** Returns the commands associated with this entry */
|
||||
Command command() const;
|
||||
/** Sets the command associated with this entry. */
|
||||
void setCommand(Command command);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @param modifiers The keyboard modifiers being pressed.
|
||||
*/
|
||||
QByteArray text(bool expandWildCards = false,
|
||||
Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;
|
||||
|
||||
/** 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.
|
||||
*
|
||||
* eg. \\E for Escape, \\t for tab, \\n for new line.
|
||||
*
|
||||
* @param expandWildCards See text()
|
||||
* @param modifiers See text()
|
||||
*/
|
||||
QByteArray escapedText(bool expandWildCards = false,
|
||||
Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;
|
||||
|
||||
/** Returns the character code ( from the Qt::Key enum ) associated with this entry */
|
||||
int keyCode() const;
|
||||
/** 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.
|
||||
* 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.
|
||||
*/
|
||||
Qt::KeyboardModifiers modifiers() const;
|
||||
|
||||
/** Returns the keyboard modifiers which are valid in this entry. See modifiers() */
|
||||
Qt::KeyboardModifiers modifierMask() const;
|
||||
|
||||
/** See modifiers() */
|
||||
void setModifiers( Qt::KeyboardModifiers modifiers );
|
||||
/** 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
|
||||
* 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.
|
||||
*/
|
||||
States state() const;
|
||||
|
||||
/** Returns the state flags which are valid in this entry. See state() */
|
||||
States stateMask() const;
|
||||
|
||||
/** See state() */
|
||||
void setState( States state );
|
||||
/** See stateMask() */
|
||||
void setStateMask( States mask );
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
QString conditionToString() const;
|
||||
|
||||
/**
|
||||
* Returns this entry's result ( ie. its command or character sequence )
|
||||
* as a string.
|
||||
*
|
||||
* @param expandWildCards See text()
|
||||
* @param modifiers See text()
|
||||
*/
|
||||
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 ,
|
||||
States flags ) const;
|
||||
|
||||
bool operator==(const Entry & rhs) const;
|
||||
|
||||
private:
|
||||
void insertModifier( QString & item , int modifier ) const;
|
||||
void insertState( QString & item , int state ) const;
|
||||
QByteArray unescape(const QByteArray & text) const;
|
||||
|
||||
int _keyCode;
|
||||
Qt::KeyboardModifiers _modifiers;
|
||||
Qt::KeyboardModifiers _modifierMask;
|
||||
States _state;
|
||||
States _stateMask;
|
||||
|
||||
Command _command;
|
||||
QByteArray _text;
|
||||
};
|
||||
|
||||
/** 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 */
|
||||
QString name() const;
|
||||
|
||||
/** Sets the name of this keyboard translator */
|
||||
void setName(const QString & name);
|
||||
|
||||
/** Returns the descriptive name of this keyboard translator */
|
||||
QString description() const;
|
||||
|
||||
/** Sets the descriptive name of this keyboard translator */
|
||||
void setDescription(const QString & description);
|
||||
|
||||
/**
|
||||
* Looks for an entry in this keyboard translator which matches the given
|
||||
* key code, keyboard modifiers and state flags.
|
||||
*
|
||||
* eg. \\E for Escape, \\t for tab, \\n for new line.
|
||||
* Returns the matching entry if found or a null Entry otherwise ( ie.
|
||||
* entry.isNull() will return true )
|
||||
*
|
||||
* @param expandWildCards See text()
|
||||
* @param modifiers See text()
|
||||
* @param keyCode A key code from the Qt::Key enum
|
||||
* @param modifiers A combination of modifiers
|
||||
* @param state Optional flags which specify the current state of the terminal
|
||||
*/
|
||||
QByteArray escapedText(bool expandWildCards = false,
|
||||
Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;
|
||||
|
||||
/** Returns the character code ( from the Qt::Key enum ) associated with this entry */
|
||||
int keyCode() const;
|
||||
/** Sets the character code associated with this entry */
|
||||
void setKeyCode(int keyCode);
|
||||
Entry findEntry(int keyCode ,
|
||||
Qt::KeyboardModifiers modifiers ,
|
||||
States state = NoState) const;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Adds an entry to this keyboard translator's table. Entries can be looked up according
|
||||
* to their key sequence using findEntry()
|
||||
*/
|
||||
Qt::KeyboardModifiers modifiers() const;
|
||||
|
||||
/** Returns the keyboard modifiers which are valid in this entry. See modifiers() */
|
||||
Qt::KeyboardModifiers modifierMask() const;
|
||||
|
||||
/** See modifiers() */
|
||||
void setModifiers( Qt::KeyboardModifiers modifiers );
|
||||
/** See modifierMask() and modifiers() */
|
||||
void setModifierMask( Qt::KeyboardModifiers modifiers );
|
||||
void addEntry(const Entry & entry);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Replaces an entry in the translator. If the @p existing entry is null,
|
||||
* then this is equivalent to calling addEntry(@p replacement)
|
||||
*/
|
||||
States state() const;
|
||||
|
||||
/** Returns the state flags which are valid in this entry. See state() */
|
||||
States stateMask() const;
|
||||
|
||||
/** See state() */
|
||||
void setState( States state );
|
||||
/** See stateMask() */
|
||||
void setStateMask( States mask );
|
||||
void replaceEntry(const Entry & existing , const Entry & replacement);
|
||||
|
||||
/**
|
||||
* Returns the key code and modifiers associated with this entry
|
||||
* as a QKeySequence
|
||||
* Removes an entry from the table.
|
||||
*/
|
||||
//QKeySequence keySequence() const;
|
||||
void removeEntry(const Entry & entry);
|
||||
|
||||
/**
|
||||
* Returns this entry's conditions ( ie. its key code, modifier and state criteria )
|
||||
* as a string.
|
||||
*/
|
||||
QString conditionToString() const;
|
||||
|
||||
/**
|
||||
* Returns this entry's result ( ie. its command or character sequence )
|
||||
* as a string.
|
||||
*
|
||||
* @param expandWildCards See text()
|
||||
* @param modifiers See text()
|
||||
*/
|
||||
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 ,
|
||||
States flags ) const;
|
||||
|
||||
bool operator==(const Entry & rhs) const;
|
||||
|
||||
private:
|
||||
void insertModifier( QString & item , int modifier ) const;
|
||||
void insertState( QString & item , int state ) const;
|
||||
QByteArray unescape(const QByteArray & text) const;
|
||||
|
||||
int _keyCode;
|
||||
Qt::KeyboardModifiers _modifiers;
|
||||
Qt::KeyboardModifiers _modifierMask;
|
||||
States _state;
|
||||
States _stateMask;
|
||||
|
||||
Command _command;
|
||||
QByteArray _text;
|
||||
};
|
||||
|
||||
/** 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 */
|
||||
QString name() const;
|
||||
|
||||
/** Sets the name of this keyboard translator */
|
||||
void setName(const QString & name);
|
||||
|
||||
/** Returns the descriptive name of this keyboard translator */
|
||||
QString description() const;
|
||||
|
||||
/** Sets the descriptive name of this keyboard translator */
|
||||
void setDescription(const QString & description);
|
||||
|
||||
/**
|
||||
* 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 )
|
||||
*
|
||||
* @param keyCode A key code from the Qt::Key enum
|
||||
* @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 ,
|
||||
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()
|
||||
*/
|
||||
void addEntry(const Entry & entry);
|
||||
|
||||
/**
|
||||
* Replaces an entry in the translator. If the @p existing entry is null,
|
||||
* then this is equivalent to calling addEntry(@p replacement)
|
||||
*/
|
||||
void replaceEntry(const Entry & existing , const Entry & replacement);
|
||||
|
||||
/**
|
||||
* Removes an entry from the table.
|
||||
*/
|
||||
void removeEntry(const Entry & entry);
|
||||
|
||||
/** Returns a list of all entries in the translator. */
|
||||
QList<Entry> entries() const;
|
||||
/** Returns a list of all entries in the translator. */
|
||||
QList<Entry> entries() const;
|
||||
|
||||
private:
|
||||
|
||||
QHash<int,Entry> _entries; // entries in this keyboard translation,
|
||||
// entries are indexed according to
|
||||
// their keycode
|
||||
QString _name;
|
||||
QString _description;
|
||||
QHash<int,Entry> _entries; // entries in this keyboard translation,
|
||||
// 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)
|
||||
@@ -417,230 +421,249 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardTranslator::Commands)
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
class KeyboardTranslatorReader {
|
||||
class KeyboardTranslatorReader
|
||||
{
|
||||
public:
|
||||
/** Constructs a new reader which parses the given @p source */
|
||||
KeyboardTranslatorReader( QIODevice * source );
|
||||
/** Constructs a new reader which parses the given @p source */
|
||||
KeyboardTranslatorReader( QIODevice * source );
|
||||
|
||||
/**
|
||||
* Returns the description text.
|
||||
* TODO: More documentation
|
||||
*/
|
||||
QString description() const;
|
||||
/**
|
||||
* 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();
|
||||
/** 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();
|
||||
|
||||
/**
|
||||
* Returns true if an error occurred whilst parsing the input or
|
||||
* false if no error occurred.
|
||||
*/
|
||||
bool parseError();
|
||||
/**
|
||||
* Returns true if an error occurred whilst parsing the input or
|
||||
* false if no error occurred.
|
||||
*/
|
||||
bool parseError();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
static KeyboardTranslator::Entry createEntry( const QString & condition ,
|
||||
const QString & result );
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
static KeyboardTranslator::Entry createEntry( const QString & condition ,
|
||||
const QString & result );
|
||||
private:
|
||||
struct Token {
|
||||
enum Type {
|
||||
TitleKeyword,
|
||||
TitleText,
|
||||
KeyKeyword,
|
||||
KeySequence,
|
||||
Command,
|
||||
OutputText
|
||||
struct Token {
|
||||
enum Type {
|
||||
TitleKeyword,
|
||||
TitleText,
|
||||
KeyKeyword,
|
||||
KeySequence,
|
||||
Command,
|
||||
OutputText
|
||||
};
|
||||
Type type;
|
||||
QString text;
|
||||
};
|
||||
Type type;
|
||||
QString text;
|
||||
};
|
||||
QList<Token> tokenize(const QString &);
|
||||
void readNext();
|
||||
bool decodeSequence(const QString & ,
|
||||
int & keyCode,
|
||||
Qt::KeyboardModifiers & modifiers,
|
||||
Qt::KeyboardModifiers & modifierMask,
|
||||
KeyboardTranslator::States & state,
|
||||
KeyboardTranslator::States & stateFlags);
|
||||
QList<Token> tokenize(const QString &);
|
||||
void readNext();
|
||||
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 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);
|
||||
|
||||
QIODevice * _source;
|
||||
QString _description;
|
||||
KeyboardTranslator::Entry _nextEntry;
|
||||
bool _hasNext;
|
||||
QIODevice * _source;
|
||||
QString _description;
|
||||
KeyboardTranslator::Entry _nextEntry;
|
||||
bool _hasNext;
|
||||
};
|
||||
|
||||
/** Writes a keyboard translation to disk. */
|
||||
class KeyboardTranslatorWriter {
|
||||
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();
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void writeHeader( const QString & description );
|
||||
/** Writes a translator entry. */
|
||||
void writeEntry( const KeyboardTranslator::Entry & entry );
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
private:
|
||||
QIODevice * _destination;
|
||||
QTextStream * _writer;
|
||||
QIODevice * _destination;
|
||||
QTextStream * _writer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Manages the keyboard translations available for use by terminal sessions,
|
||||
* see KeyboardTranslator.
|
||||
*/
|
||||
class KeyboardTranslatorManager {
|
||||
class KeyboardTranslatorManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs a new KeyboardTranslatorManager and loads the list of
|
||||
* available keyboard translations.
|
||||
*
|
||||
* The keyboard translations themselves are not loaded until they are
|
||||
* first requested via a call to findTranslator()
|
||||
*/
|
||||
KeyboardTranslatorManager();
|
||||
~KeyboardTranslatorManager();
|
||||
/**
|
||||
* Constructs a new KeyboardTranslatorManager and loads the list of
|
||||
* available keyboard translations.
|
||||
*
|
||||
* The keyboard translations themselves are not loaded until they are
|
||||
* first requested via a call to findTranslator()
|
||||
*/
|
||||
KeyboardTranslatorManager();
|
||||
~KeyboardTranslatorManager();
|
||||
|
||||
/**
|
||||
* Adds a new translator. If a translator with the same name
|
||||
* already exists, it will be replaced by the new translator.
|
||||
*
|
||||
* TODO: More documentation.
|
||||
*/
|
||||
void addTranslator(KeyboardTranslator * translator);
|
||||
/**
|
||||
* Adds a new translator. If a translator with the same name
|
||||
* already exists, it will be replaced by the new translator.
|
||||
*
|
||||
* TODO: More documentation.
|
||||
*/
|
||||
void addTranslator(KeyboardTranslator * translator);
|
||||
|
||||
/**
|
||||
* Deletes a translator. Returns true on successful deletion or false otherwise.
|
||||
*
|
||||
* TODO: More documentation
|
||||
*/
|
||||
bool deleteTranslator(const QString & name);
|
||||
/**
|
||||
* Deletes a translator. Returns true on successful deletion or false otherwise.
|
||||
*
|
||||
* TODO: More documentation
|
||||
*/
|
||||
bool deleteTranslator(const QString & name);
|
||||
|
||||
/** Returns the default translator for Konsole. */
|
||||
const KeyboardTranslator * defaultTranslator();
|
||||
/** 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.
|
||||
*/
|
||||
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
|
||||
* translators is started.
|
||||
*/
|
||||
QList<QString> allTranslators();
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
* translators is started.
|
||||
*/
|
||||
QList<QString> allTranslators();
|
||||
|
||||
/** Returns the global KeyboardTranslatorManager instance. */
|
||||
static KeyboardTranslatorManager * instance();
|
||||
/** Returns the global KeyboardTranslatorManager instance. */
|
||||
static KeyboardTranslatorManager * instance();
|
||||
|
||||
private:
|
||||
static const char * defaultTranslatorText;
|
||||
static const char * defaultTranslatorText;
|
||||
|
||||
void findTranslators(); // locate the available translators
|
||||
KeyboardTranslator * loadTranslator(const QString & name); // loads the translator
|
||||
// with the given name
|
||||
KeyboardTranslator * loadTranslator(QIODevice * device,const QString & name);
|
||||
void findTranslators(); // locate the available translators
|
||||
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);
|
||||
bool saveTranslator(const KeyboardTranslator * translator);
|
||||
QString findTranslatorPath(const QString & name);
|
||||
|
||||
QHash<QString,KeyboardTranslator *> _translators; // maps translator-name -> KeyboardTranslator
|
||||
// instance
|
||||
bool _haveLoadedAll;
|
||||
QHash<QString,KeyboardTranslator *> _translators; // maps translator-name -> KeyboardTranslator
|
||||
// instance
|
||||
bool _haveLoadedAll;
|
||||
};
|
||||
|
||||
inline int KeyboardTranslator::Entry::keyCode() const {
|
||||
return _keyCode;
|
||||
inline int KeyboardTranslator::Entry::keyCode() const
|
||||
{
|
||||
return _keyCode;
|
||||
}
|
||||
inline void KeyboardTranslator::Entry::setKeyCode(int keyCode) {
|
||||
_keyCode = keyCode;
|
||||
inline void KeyboardTranslator::Entry::setKeyCode(int keyCode)
|
||||
{
|
||||
_keyCode = keyCode;
|
||||
}
|
||||
|
||||
inline void KeyboardTranslator::Entry::setModifiers( Qt::KeyboardModifiers modifier ) {
|
||||
_modifiers = modifier;
|
||||
inline void KeyboardTranslator::Entry::setModifiers( Qt::KeyboardModifiers modifier )
|
||||
{
|
||||
_modifiers = modifier;
|
||||
}
|
||||
inline Qt::KeyboardModifiers KeyboardTranslator::Entry::modifiers() const {
|
||||
return _modifiers;
|
||||
inline Qt::KeyboardModifiers KeyboardTranslator::Entry::modifiers() const
|
||||
{
|
||||
return _modifiers;
|
||||
}
|
||||
|
||||
inline void KeyboardTranslator::Entry::setModifierMask( Qt::KeyboardModifiers mask ) {
|
||||
_modifierMask = mask;
|
||||
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 {
|
||||
return ( *this == Entry() );
|
||||
inline bool KeyboardTranslator::Entry::isNull() const
|
||||
{
|
||||
return ( *this == Entry() );
|
||||
}
|
||||
|
||||
inline void KeyboardTranslator::Entry::setCommand( Command command ) {
|
||||
_command = command;
|
||||
inline void KeyboardTranslator::Entry::setCommand( 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 void KeyboardTranslator::Entry::setText( const QByteArray & text )
|
||||
{
|
||||
_text = unescape(text);
|
||||
}
|
||||
inline int oneOrZero(int value) {
|
||||
return value ? 1 : 0;
|
||||
inline int oneOrZero(int value)
|
||||
{
|
||||
return value ? 1 : 0;
|
||||
}
|
||||
inline QByteArray KeyboardTranslator::Entry::text(bool expandWildCards,Qt::KeyboardModifiers modifiers) const {
|
||||
QByteArray expandedText = _text;
|
||||
inline QByteArray KeyboardTranslator::Entry::text(bool expandWildCards,Qt::KeyboardModifiers modifiers) const
|
||||
{
|
||||
QByteArray expandedText = _text;
|
||||
|
||||
if (expandWildCards) {
|
||||
int modifierValue = 1;
|
||||
modifierValue += oneOrZero(modifiers & Qt::ShiftModifier);
|
||||
modifierValue += oneOrZero(modifiers & Qt::AltModifier) << 1;
|
||||
modifierValue += oneOrZero(modifiers & Qt::ControlModifier) << 2;
|
||||
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++) {
|
||||
if (expandedText[i] == '*') {
|
||||
expandedText[i] = '0' + modifierValue;
|
||||
}
|
||||
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;
|
||||
inline void KeyboardTranslator::Entry::setState( States 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;
|
||||
inline void KeyboardTranslator::Entry::setStateMask( States stateMask )
|
||||
{
|
||||
_stateMask = stateMask;
|
||||
}
|
||||
inline KeyboardTranslator::States KeyboardTranslator::Entry::stateMask() const {
|
||||
return _stateMask;
|
||||
inline KeyboardTranslator::States KeyboardTranslator::Entry::stateMask() const
|
||||
{
|
||||
return _stateMask;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-16
@@ -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
|
||||
};
|
||||
|
||||
+206
-187
@@ -41,103 +41,111 @@
|
||||
|
||||
using namespace Konsole;
|
||||
|
||||
void Pty::donePty() {
|
||||
emit done(exitStatus());
|
||||
void Pty::donePty()
|
||||
{
|
||||
emit done(exitStatus());
|
||||
}
|
||||
|
||||
void Pty::setWindowSize(int lines, int cols) {
|
||||
_windowColumns = cols;
|
||||
_windowLines = lines;
|
||||
void Pty::setWindowSize(int lines, int cols)
|
||||
{
|
||||
_windowColumns = cols;
|
||||
_windowLines = lines;
|
||||
|
||||
if (pty()->masterFd() >= 0) {
|
||||
pty()->setWinSize(lines, cols);
|
||||
}
|
||||
}
|
||||
QSize Pty::windowSize() const {
|
||||
return QSize(_windowColumns,_windowLines);
|
||||
}
|
||||
|
||||
void Pty::setXonXoff(bool 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()->masterFd() >= 0) {
|
||||
pty()->setWinSize(lines, cols);
|
||||
}
|
||||
if (!pty()->tcSetAttr(&ttmode)) {
|
||||
qWarning("Unable to set terminal attributes.");
|
||||
}
|
||||
}
|
||||
}
|
||||
QSize Pty::windowSize() const
|
||||
{
|
||||
return QSize(_windowColumns,_windowLines);
|
||||
}
|
||||
|
||||
void Pty::setUtf8Mode(bool enable) {
|
||||
void Pty::setXonXoff(bool 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()->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()->tcSetAttr(&ttmode)) {
|
||||
qWarning("Unable to set terminal attributes.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Pty::setErase(char erase) {
|
||||
_eraseChar = erase;
|
||||
void Pty::setErase(char erase)
|
||||
{
|
||||
_eraseChar = erase;
|
||||
|
||||
if (pty()->masterFd() >= 0) {
|
||||
struct ::termios ttmode;
|
||||
if (pty()->masterFd() >= 0) {
|
||||
struct ::termios ttmode;
|
||||
|
||||
pty()->tcGetAttr(&ttmode);
|
||||
pty()->tcGetAttr(&ttmode);
|
||||
|
||||
ttmode.c_cc[VERASE] = erase;
|
||||
ttmode.c_cc[VERASE] = erase;
|
||||
|
||||
if (!pty()->tcSetAttr(&ttmode)) {
|
||||
qWarning("Unable to set terminal attributes.");
|
||||
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];
|
||||
}
|
||||
char Pty::erase() const
|
||||
{
|
||||
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<QString> iter(environment);
|
||||
while (iter.hasNext()) {
|
||||
QString pair = iter.next();
|
||||
void Pty::addEnvironmentVariables(const QStringList & environment)
|
||||
{
|
||||
QListIterator<QString> iter(environment);
|
||||
while (iter.hasNext()) {
|
||||
QString pair = iter.next();
|
||||
|
||||
// split on the first '=' character
|
||||
int pos = pair.indexOf('=');
|
||||
// split on the first '=' character
|
||||
int pos = pair.indexOf('=');
|
||||
|
||||
if ( pos >= 0 ) {
|
||||
QString variable = pair.left(pos);
|
||||
QString value = pair.mid(pos+1);
|
||||
if ( pos >= 0 ) {
|
||||
QString variable = pair.left(pos);
|
||||
QString value = pair.mid(pos+1);
|
||||
|
||||
//kDebug() << "Setting environment pair" << variable <<
|
||||
// " set to " << value;
|
||||
//kDebug() << "Setting environment pair" << variable <<
|
||||
// " set to " << value;
|
||||
|
||||
setEnvironment(variable,value);
|
||||
setEnvironment(variable,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Pty::start(const QString & program,
|
||||
@@ -147,163 +155,174 @@ int Pty::start(const QString & program,
|
||||
bool addToUtmp
|
||||
// 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();
|
||||
pty()->open();
|
||||
|
||||
struct ::termios ttmode;
|
||||
pty()->tcGetAttr(&ttmode);
|
||||
if (!_xonXoff) {
|
||||
ttmode.c_iflag &= ~(IXOFF | IXON);
|
||||
} else {
|
||||
ttmode.c_iflag |= (IXOFF | IXON);
|
||||
}
|
||||
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 (_eraseChar != 0) {
|
||||
ttmode.c_cc[VERASE] = _eraseChar;
|
||||
}
|
||||
|
||||
if (!pty()->tcSetAttr(&ttmode)) {
|
||||
qWarning("Unable to set terminal attributes.");
|
||||
}
|
||||
if (!pty()->tcSetAttr(&ttmode)) {
|
||||
qWarning("Unable to set terminal attributes.");
|
||||
}
|
||||
|
||||
pty()->setWinSize(_windowLines, _windowColumns);
|
||||
pty()->setWinSize(_windowLines, _windowColumns);
|
||||
|
||||
if ( K3Process::start(NotifyOnExit, (Communication) (Stdin | Stdout)) == false ) {
|
||||
return -1;
|
||||
}
|
||||
if ( K3Process::start(NotifyOnExit, (Communication) (Stdin | Stdout)) == false ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
resume(); // Start...
|
||||
return 0;
|
||||
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));
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
Pty::Pty()
|
||||
: _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;
|
||||
: _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;
|
||||
|
||||
setUsePty(All, false); // utmp will be overridden later
|
||||
setUsePty(All, false); // utmp will be overridden later
|
||||
}
|
||||
|
||||
Pty::~Pty() {
|
||||
delete _pty;
|
||||
Pty::~Pty()
|
||||
{
|
||||
delete _pty;
|
||||
}
|
||||
|
||||
void Pty::writeReady() {
|
||||
_pendingSendJobs.erase(_pendingSendJobs.begin());
|
||||
_bufferFull = false;
|
||||
doSendJobs();
|
||||
}
|
||||
|
||||
void Pty::doSendJobs() {
|
||||
if(_pendingSendJobs.isEmpty()) {
|
||||
emit bufferEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void Pty::sendData(const char * s, int len) {
|
||||
appendSendJob(s,len);
|
||||
if (!_bufferFull) {
|
||||
void Pty::writeReady()
|
||||
{
|
||||
_pendingSendJobs.erase(_pendingSendJobs.begin());
|
||||
_bufferFull = false;
|
||||
doSendJobs();
|
||||
}
|
||||
}
|
||||
|
||||
void Pty::dataReceived(K3Process *,char * buf, int len) {
|
||||
emit receivedData(buf,len);
|
||||
void Pty::doSendJobs()
|
||||
{
|
||||
if (_pendingSendJobs.isEmpty()) {
|
||||
emit bufferEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
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::lockPty(bool lock) {
|
||||
if (lock) {
|
||||
suspend();
|
||||
} else {
|
||||
resume();
|
||||
}
|
||||
void Pty::appendSendJob(const char * s, int len)
|
||||
{
|
||||
_pendingSendJobs.append(SendJob(s,len));
|
||||
}
|
||||
|
||||
int Pty::foregroundProcessGroup() const {
|
||||
int pid = tcgetpgrp(pty()->masterFd());
|
||||
void Pty::sendData(const char * s, int len)
|
||||
{
|
||||
appendSendJob(s,len);
|
||||
if (!_bufferFull) {
|
||||
doSendJobs();
|
||||
}
|
||||
}
|
||||
|
||||
if ( pid != -1 ) {
|
||||
return pid;
|
||||
}
|
||||
void Pty::dataReceived(K3Process *,char * buf, int len)
|
||||
{
|
||||
emit receivedData(buf,len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
void Pty::lockPty(bool lock)
|
||||
{
|
||||
if (lock) {
|
||||
suspend();
|
||||
} else {
|
||||
resume();
|
||||
}
|
||||
}
|
||||
|
||||
int Pty::foregroundProcessGroup() const
|
||||
{
|
||||
int pid = tcgetpgrp(pty()->masterFd());
|
||||
|
||||
if ( pid != -1 ) {
|
||||
return pid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//#include "moc_Pty.cpp"
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
#include "k3process.h"
|
||||
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
/**
|
||||
* The Pty class is used to start the terminal process,
|
||||
@@ -49,196 +50,198 @@ namespace Konsole {
|
||||
* To start the terminal process, call the start() method
|
||||
* with the program name and appropriate arguments.
|
||||
*/
|
||||
class Pty: public K3Process {
|
||||
Q_OBJECT
|
||||
class Pty: public K3Process
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
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
|
||||
* name of the program to start and appropriate arguments.
|
||||
*/
|
||||
Pty();
|
||||
~Pty();
|
||||
/**
|
||||
* 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
|
||||
* name of the program to start and appropriate arguments.
|
||||
*/
|
||||
Pty();
|
||||
~Pty();
|
||||
|
||||
/**
|
||||
* Starts the terminal process.
|
||||
*
|
||||
* Returns 0 if the process was started successfully or non-zero
|
||||
* otherwise.
|
||||
*
|
||||
* @param program Path to the program to start
|
||||
* @param arguments Arguments to pass to the program being started
|
||||
* @param environment A list of key=value pairs which will be added
|
||||
* to the environment for the new process. At the very least this
|
||||
* should include an assignment for the TERM environment variable.
|
||||
* @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
|
||||
* environment variable in the process's environment.
|
||||
* @param dbusSession Specifies the value of the KONSOLE_DBUS_SESSION
|
||||
* environment variable in the process's environment.
|
||||
*/
|
||||
int start( const QString & program,
|
||||
const QStringList & arguments,
|
||||
const QStringList & environment,
|
||||
ulong winid,
|
||||
bool addToUtmp
|
||||
/**
|
||||
* Starts the terminal process.
|
||||
*
|
||||
* Returns 0 if the process was started successfully or non-zero
|
||||
* otherwise.
|
||||
*
|
||||
* @param program Path to the program to start
|
||||
* @param arguments Arguments to pass to the program being started
|
||||
* @param environment A list of key=value pairs which will be added
|
||||
* to the environment for the new process. At the very least this
|
||||
* should include an assignment for the TERM environment variable.
|
||||
* @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
|
||||
* environment variable in the process's environment.
|
||||
* @param dbusSession Specifies the value of the KONSOLE_DBUS_SESSION
|
||||
* environment variable in the process's environment.
|
||||
*/
|
||||
int start( const QString & program,
|
||||
const QStringList & arguments,
|
||||
const QStringList & environment,
|
||||
ulong winid,
|
||||
bool addToUtmp
|
||||
// const QString& dbusService,
|
||||
// const QString& dbusSession
|
||||
);
|
||||
);
|
||||
|
||||
/** TODO: Document me */
|
||||
void setWriteable(bool writeable);
|
||||
/** TODO: Document me */
|
||||
void setWriteable(bool writeable);
|
||||
|
||||
/**
|
||||
* Enables or disables Xon/Xoff flow control.
|
||||
*/
|
||||
void setXonXoff(bool on);
|
||||
/**
|
||||
* Enables or disables Xon/Xoff flow control.
|
||||
*/
|
||||
void setXonXoff(bool on);
|
||||
|
||||
/**
|
||||
* Sets the size of the window (in lines and columns of characters)
|
||||
* used by this teletype.
|
||||
*/
|
||||
void setWindowSize(int lines, int cols);
|
||||
/**
|
||||
* 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;
|
||||
/** Returns the size of the window used by this teletype. See setWindowSize() */
|
||||
QSize windowSize() const;
|
||||
|
||||
/** TODO Document me */
|
||||
void setErase(char erase);
|
||||
/** TODO Document me */
|
||||
void setErase(char erase);
|
||||
|
||||
/** */
|
||||
char erase() const;
|
||||
/** */
|
||||
char erase() const;
|
||||
|
||||
/**
|
||||
* Returns the process id of the teletype's current foreground
|
||||
* process. This is the process which is currently reading
|
||||
* input sent to the terminal via. sendData()
|
||||
*
|
||||
* If there is a problem reading the foreground process group,
|
||||
* 0 will be returned.
|
||||
*/
|
||||
int foregroundProcessGroup() const;
|
||||
/**
|
||||
* Returns the process id of the teletype's current foreground
|
||||
* process. This is the process which is currently reading
|
||||
* input sent to the terminal via. sendData()
|
||||
*
|
||||
* If there is a problem reading the foreground process group,
|
||||
* 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;
|
||||
}
|
||||
/**
|
||||
* Returns whether the buffer used to send data to the
|
||||
* terminal process is full.
|
||||
*/
|
||||
bool bufferFull() const {
|
||||
return _bufferFull;
|
||||
}
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
* Put the pty into UTF-8 mode on systems which support it.
|
||||
*/
|
||||
void setUtf8Mode(bool on);
|
||||
/**
|
||||
* Put the pty into UTF-8 mode on systems which support it.
|
||||
*/
|
||||
void setUtf8Mode(bool on);
|
||||
|
||||
/**
|
||||
* Suspend or resume processing of data from the standard
|
||||
* output of the terminal process.
|
||||
*
|
||||
* See K3Process::suspend() and K3Process::resume()
|
||||
*
|
||||
* @param lock If true, processing of output is suspended,
|
||||
* otherwise processing is resumed.
|
||||
*/
|
||||
void lockPty(bool lock);
|
||||
/**
|
||||
* Suspend or resume processing of data from the standard
|
||||
* output of the terminal process.
|
||||
*
|
||||
* See K3Process::suspend() and K3Process::resume()
|
||||
*
|
||||
* @param lock If true, processing of output is suspended,
|
||||
* otherwise processing is resumed.
|
||||
*/
|
||||
void lockPty(bool lock);
|
||||
|
||||
/**
|
||||
* Sends data to the process currently controlling the
|
||||
* teletype ( whose id is returned by foregroundProcessGroup() )
|
||||
*
|
||||
* @param buffer Pointer to the data to send.
|
||||
* @param length Length of @p buffer.
|
||||
*/
|
||||
void sendData(const char * buffer, int length);
|
||||
/**
|
||||
* Sends data to the process currently controlling the
|
||||
* teletype ( whose id is returned by foregroundProcessGroup() )
|
||||
*
|
||||
* @param buffer Pointer to the data to send.
|
||||
* @param length Length of @p buffer.
|
||||
*/
|
||||
void sendData(const char * buffer, int length);
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
* Emitted when the terminal process terminates.
|
||||
*
|
||||
* @param exitCode The status code which the process exited with.
|
||||
*/
|
||||
void done(int exitCode);
|
||||
/**
|
||||
* Emitted when the terminal process terminates.
|
||||
*
|
||||
* @param exitCode The status code which the process exited with.
|
||||
*/
|
||||
void done(int exitCode);
|
||||
|
||||
/**
|
||||
* Emitted when a new block of data is received from
|
||||
* the teletype.
|
||||
*
|
||||
* @param buffer Pointer to the data received.
|
||||
* @param length Length of @p buffer
|
||||
*/
|
||||
void receivedData(const char * buffer, int length);
|
||||
/**
|
||||
* Emitted when a new block of data is received from
|
||||
* the teletype.
|
||||
*
|
||||
* @param buffer Pointer to the data received.
|
||||
* @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();
|
||||
/**
|
||||
* 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:
|
||||
|
||||
// called when terminal process exits
|
||||
void donePty();
|
||||
// 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
|
||||
void doSendJobs();
|
||||
// called when the terminal process is ready to
|
||||
// receive more data
|
||||
void writeReady();
|
||||
// called when terminal process exits
|
||||
void donePty();
|
||||
// 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
|
||||
void doSendJobs();
|
||||
// called when the terminal process is ready to
|
||||
// receive more data
|
||||
void writeReady();
|
||||
|
||||
private:
|
||||
// takes a list of key=value pairs and adds them
|
||||
// to the environment for the process
|
||||
void addEnvironmentVariables(const QStringList & environment);
|
||||
// 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
|
||||
// terminal process
|
||||
void appendSendJob(const char * buffer, int length);
|
||||
// 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<char> buffer;
|
||||
};
|
||||
const char * data() const {
|
||||
return buffer.constData();
|
||||
}
|
||||
int length() const {
|
||||
return buffer.size();
|
||||
}
|
||||
private:
|
||||
QVector<char> buffer;
|
||||
};
|
||||
|
||||
QList<SendJob> _pendingSendJobs;
|
||||
bool _bufferFull;
|
||||
QList<SendJob> _pendingSendJobs;
|
||||
bool _bufferFull;
|
||||
|
||||
int _windowColumns;
|
||||
int _windowLines;
|
||||
char _eraseChar;
|
||||
bool _xonXoff;
|
||||
bool _utf8;
|
||||
KPty * _pty;
|
||||
int _windowColumns;
|
||||
int _windowLines;
|
||||
char _eraseChar;
|
||||
bool _xonXoff;
|
||||
bool _utf8;
|
||||
KPty * _pty;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+1020
-936
File diff suppressed because it is too large
Load Diff
+536
-534
File diff suppressed because it is too large
Load Diff
+181
-150
@@ -31,62 +31,68 @@
|
||||
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;
|
||||
}
|
||||
void ScreenWindow::setScreen(Screen * screen) {
|
||||
Q_ASSERT( screen );
|
||||
|
||||
_screen = screen;
|
||||
}
|
||||
|
||||
Screen * ScreenWindow::screen() const {
|
||||
return _screen;
|
||||
}
|
||||
|
||||
Character * ScreenWindow::getImage() {
|
||||
// reallocate internal buffer if the window size has changed
|
||||
int size = windowLines() * windowColumns();
|
||||
if (_windowBuffer == 0 || _windowBufferSize != size) {
|
||||
ScreenWindow::~ScreenWindow()
|
||||
{
|
||||
delete[] _windowBuffer;
|
||||
_windowBufferSize = size;
|
||||
_windowBuffer = new Character[size];
|
||||
_bufferNeedsUpdate = true;
|
||||
}
|
||||
}
|
||||
void ScreenWindow::setScreen(Screen * screen)
|
||||
{
|
||||
Q_ASSERT( screen );
|
||||
|
||||
if (!_bufferNeedsUpdate) {
|
||||
return _windowBuffer;
|
||||
}
|
||||
|
||||
_screen->getImage(_windowBuffer,size,
|
||||
currentLine(),endWindowLine());
|
||||
|
||||
// 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;
|
||||
_screen = screen;
|
||||
}
|
||||
|
||||
void ScreenWindow::fillUnusedArea() {
|
||||
int screenEndLine = _screen->getHistLines() + _screen->getLines() - 1;
|
||||
int windowEndLine = currentLine() + windowLines() - 1;
|
||||
Screen * ScreenWindow::screen() const
|
||||
{
|
||||
return _screen;
|
||||
}
|
||||
|
||||
int unusedLines = windowEndLine - screenEndLine;
|
||||
int charsToFill = unusedLines * windowColumns();
|
||||
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;
|
||||
}
|
||||
|
||||
Screen::fillWithDefaultChar(_windowBuffer + _windowBufferSize - charsToFill,charsToFill);
|
||||
if (!_bufferNeedsUpdate) {
|
||||
return _windowBuffer;
|
||||
}
|
||||
|
||||
_screen->getImage(_windowBuffer,size,
|
||||
currentLine(),endWindowLine());
|
||||
|
||||
// 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 unusedLines = windowEndLine - screenEndLine;
|
||||
int charsToFill = unusedLines * windowColumns();
|
||||
|
||||
Screen::fillWithDefaultChar(_windowBuffer + _windowBufferSize - charsToFill,charsToFill);
|
||||
}
|
||||
|
||||
// return the index of the line at the end of this window, or if this window
|
||||
@@ -96,166 +102,191 @@ void ScreenWindow::fillUnusedArea() {
|
||||
// when passing a line number to a Screen method, the line number should
|
||||
// never be more than endWindowLine()
|
||||
//
|
||||
int ScreenWindow::endWindowLine() const {
|
||||
return qMin(currentLine() + windowLines() - 1,
|
||||
lineCount() - 1);
|
||||
int ScreenWindow::endWindowLine() const
|
||||
{
|
||||
return qMin(currentLine() + windowLines() - 1,
|
||||
lineCount() - 1);
|
||||
}
|
||||
QVector<LineProperty> ScreenWindow::getLineProperties() {
|
||||
QVector<LineProperty> result = _screen->getLineProperties(currentLine(),endWindowLine());
|
||||
QVector<LineProperty> ScreenWindow::getLineProperties()
|
||||
{
|
||||
QVector<LineProperty> result = _screen->getLineProperties(currentLine(),endWindowLine());
|
||||
|
||||
if (result.count() != windowLines()) {
|
||||
result.resize(windowLines());
|
||||
}
|
||||
if (result.count() != windowLines()) {
|
||||
result.resize(windowLines());
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
QString ScreenWindow::selectedText( bool preserveLineBreaks ) const {
|
||||
return _screen->selectedText( preserveLineBreaks );
|
||||
QString ScreenWindow::selectedText( bool preserveLineBreaks ) const
|
||||
{
|
||||
return _screen->selectedText( preserveLineBreaks );
|
||||
}
|
||||
|
||||
void ScreenWindow::getSelectionStart( int & column , int & line ) {
|
||||
_screen->getSelectionStart(column,line);
|
||||
line -= currentLine();
|
||||
void ScreenWindow::getSelectionStart( int & column , int & line )
|
||||
{
|
||||
_screen->getSelectionStart(column,line);
|
||||
line -= currentLine();
|
||||
}
|
||||
void ScreenWindow::getSelectionEnd( int & column , int & line ) {
|
||||
_screen->getSelectionEnd(column,line);
|
||||
line -= currentLine();
|
||||
void ScreenWindow::getSelectionEnd( int & column , int & line )
|
||||
{
|
||||
_screen->getSelectionEnd(column,line);
|
||||
line -= currentLine();
|
||||
}
|
||||
void ScreenWindow::setSelectionStart( int column , int line , bool columnMode ) {
|
||||
_screen->setSelectionStart( column , qMin(line + currentLine(),endWindowLine()) , columnMode);
|
||||
void ScreenWindow::setSelectionStart( int column , int line , bool columnMode )
|
||||
{
|
||||
_screen->setSelectionStart( column , qMin(line + currentLine(),endWindowLine()) , columnMode);
|
||||
|
||||
_bufferNeedsUpdate = true;
|
||||
emit selectionChanged();
|
||||
_bufferNeedsUpdate = true;
|
||||
emit selectionChanged();
|
||||
}
|
||||
|
||||
void ScreenWindow::setSelectionEnd( int column , int line ) {
|
||||
_screen->setSelectionEnd( column , qMin(line + currentLine(),endWindowLine()) );
|
||||
void ScreenWindow::setSelectionEnd( int column , int line )
|
||||
{
|
||||
_screen->setSelectionEnd( column , qMin(line + currentLine(),endWindowLine()) );
|
||||
|
||||
_bufferNeedsUpdate = true;
|
||||
emit selectionChanged();
|
||||
_bufferNeedsUpdate = true;
|
||||
emit selectionChanged();
|
||||
}
|
||||
|
||||
bool ScreenWindow::isSelected( int column , int line ) {
|
||||
return _screen->isSelected( column , qMin(line + currentLine(),endWindowLine()) );
|
||||
bool ScreenWindow::isSelected( int column , int line )
|
||||
{
|
||||
return _screen->isSelected( column , qMin(line + currentLine(),endWindowLine()) );
|
||||
}
|
||||
|
||||
void ScreenWindow::clearSelection() {
|
||||
_screen->clearSelection();
|
||||
void ScreenWindow::clearSelection()
|
||||
{
|
||||
_screen->clearSelection();
|
||||
|
||||
emit selectionChanged();
|
||||
emit selectionChanged();
|
||||
}
|
||||
|
||||
void ScreenWindow::setWindowLines(int lines) {
|
||||
Q_ASSERT(lines > 0);
|
||||
_windowLines = lines;
|
||||
void ScreenWindow::setWindowLines(int lines)
|
||||
{
|
||||
Q_ASSERT(lines > 0);
|
||||
_windowLines = lines;
|
||||
}
|
||||
int ScreenWindow::windowLines() const {
|
||||
return _windowLines;
|
||||
int ScreenWindow::windowLines() const
|
||||
{
|
||||
return _windowLines;
|
||||
}
|
||||
|
||||
int ScreenWindow::windowColumns() const {
|
||||
return _screen->getColumns();
|
||||
int ScreenWindow::windowColumns() const
|
||||
{
|
||||
return _screen->getColumns();
|
||||
}
|
||||
|
||||
int ScreenWindow::lineCount() const {
|
||||
return _screen->getHistLines() + _screen->getLines();
|
||||
int ScreenWindow::lineCount() const
|
||||
{
|
||||
return _screen->getHistLines() + _screen->getLines();
|
||||
}
|
||||
|
||||
int ScreenWindow::columnCount() const {
|
||||
return _screen->getColumns();
|
||||
int ScreenWindow::columnCount() const
|
||||
{
|
||||
return _screen->getColumns();
|
||||
}
|
||||
|
||||
QPoint ScreenWindow::cursorPosition() const {
|
||||
QPoint position;
|
||||
QPoint ScreenWindow::cursorPosition() const
|
||||
{
|
||||
QPoint position;
|
||||
|
||||
position.setX( _screen->getCursorX() );
|
||||
position.setY( _screen->getCursorY() );
|
||||
position.setX( _screen->getCursorX() );
|
||||
position.setY( _screen->getCursorY() );
|
||||
|
||||
return position;
|
||||
return position;
|
||||
}
|
||||
|
||||
int ScreenWindow::currentLine() const {
|
||||
return qBound(0,_currentLine,lineCount()-windowLines());
|
||||
int ScreenWindow::currentLine() const
|
||||
{
|
||||
return qBound(0,_currentLine,lineCount()-windowLines());
|
||||
}
|
||||
|
||||
void ScreenWindow::scrollBy( RelativeScrollMode mode , int amount ) {
|
||||
if ( mode == ScrollLines ) {
|
||||
scrollTo( currentLine() + amount );
|
||||
} else if ( mode == ScrollPages ) {
|
||||
scrollTo( currentLine() + amount * ( windowLines() / 2 ) );
|
||||
}
|
||||
void ScreenWindow::scrollBy( RelativeScrollMode mode , int amount )
|
||||
{
|
||||
if ( mode == ScrollLines ) {
|
||||
scrollTo( currentLine() + amount );
|
||||
} else if ( mode == ScrollPages ) {
|
||||
scrollTo( currentLine() + amount * ( windowLines() / 2 ) );
|
||||
}
|
||||
}
|
||||
|
||||
bool ScreenWindow::atEndOfOutput() const {
|
||||
return currentLine() == (lineCount()-windowLines());
|
||||
bool ScreenWindow::atEndOfOutput() const
|
||||
{
|
||||
return currentLine() == (lineCount()-windowLines());
|
||||
}
|
||||
|
||||
void ScreenWindow::scrollTo( int line ) {
|
||||
int maxCurrentLineNumber = lineCount() - windowLines();
|
||||
line = qBound(0,line,maxCurrentLineNumber);
|
||||
void ScreenWindow::scrollTo( int line )
|
||||
{
|
||||
int maxCurrentLineNumber = lineCount() - windowLines();
|
||||
line = qBound(0,line,maxCurrentLineNumber);
|
||||
|
||||
const int delta = line - _currentLine;
|
||||
_currentLine = line;
|
||||
const int delta = line - _currentLine;
|
||||
_currentLine = line;
|
||||
|
||||
// keep track of number of lines scrolled by,
|
||||
// this can be reset by calling resetScrollCount()
|
||||
_scrollCount += delta;
|
||||
// keep track of number of lines scrolled by,
|
||||
// this can be reset by calling resetScrollCount()
|
||||
_scrollCount += delta;
|
||||
|
||||
_bufferNeedsUpdate = true;
|
||||
_bufferNeedsUpdate = true;
|
||||
|
||||
emit scrolled(_currentLine);
|
||||
emit scrolled(_currentLine);
|
||||
}
|
||||
|
||||
void ScreenWindow::setTrackOutput(bool trackOutput) {
|
||||
_trackOutput = trackOutput;
|
||||
void ScreenWindow::setTrackOutput(bool trackOutput)
|
||||
{
|
||||
_trackOutput = trackOutput;
|
||||
}
|
||||
|
||||
bool ScreenWindow::trackOutput() const {
|
||||
return _trackOutput;
|
||||
bool ScreenWindow::trackOutput() const
|
||||
{
|
||||
return _trackOutput;
|
||||
}
|
||||
|
||||
int ScreenWindow::scrollCount() const {
|
||||
return _scrollCount;
|
||||
int ScreenWindow::scrollCount() const
|
||||
{
|
||||
return _scrollCount;
|
||||
}
|
||||
|
||||
void ScreenWindow::resetScrollCount() {
|
||||
_scrollCount = 0;
|
||||
void ScreenWindow::resetScrollCount()
|
||||
{
|
||||
_scrollCount = 0;
|
||||
}
|
||||
|
||||
QRect ScreenWindow::scrollRegion() const {
|
||||
bool equalToScreenSize = windowLines() == _screen->getLines();
|
||||
QRect ScreenWindow::scrollRegion() const
|
||||
{
|
||||
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 ) {
|
||||
_scrollCount -= _screen->scrolledLines();
|
||||
_currentLine = qMax(0,_screen->getHistLines() - (windowLines()-_screen->getLines()));
|
||||
} 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
|
||||
// be adjusted - otherwise the output will scroll
|
||||
_currentLine = qMax(0,_currentLine -
|
||||
_screen->droppedLines());
|
||||
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 ) {
|
||||
_scrollCount -= _screen->scrolledLines();
|
||||
_currentLine = qMax(0,_screen->getHistLines() - (windowLines()-_screen->getLines()));
|
||||
} 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
|
||||
// be adjusted - otherwise the output will scroll
|
||||
_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() );
|
||||
}
|
||||
// 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"
|
||||
|
||||
+171
-169
@@ -30,7 +30,8 @@
|
||||
// Konsole
|
||||
#include "Character.h"
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
class Screen;
|
||||
|
||||
@@ -50,203 +51,204 @@ class Screen;
|
||||
* be called. This in turn will update the window's position and emit the outputChanged() signal
|
||||
* if necessary.
|
||||
*/
|
||||
class ScreenWindow : public QObject {
|
||||
Q_OBJECT
|
||||
class ScreenWindow : public QObject
|
||||
{
|
||||
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().
|
||||
*
|
||||
* You should not call this constructor directly, instead use the Emulation::createWindow() method
|
||||
* to create a window on the emulation which you wish to view. This allows the emulation
|
||||
* to notify the window when the associated screen has changed and synchronize selection updates
|
||||
* between all views on a session.
|
||||
*/
|
||||
ScreenWindow(QObject * parent = 0);
|
||||
virtual ~ScreenWindow();
|
||||
/**
|
||||
* Constructs a new screen window with the given parent.
|
||||
* A screen must be specified by calling setScreen() before calling getImage() or getLineProperties().
|
||||
*
|
||||
* You should not call this constructor directly, instead use the Emulation::createWindow() method
|
||||
* to create a window on the emulation which you wish to view. This allows the emulation
|
||||
* to notify the window when the associated screen has changed and synchronize selection updates
|
||||
* between all views on a session.
|
||||
*/
|
||||
ScreenWindow(QObject * parent = 0);
|
||||
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;
|
||||
/** 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.
|
||||
*
|
||||
* The buffer is managed by the ScreenWindow instance and does not need to be
|
||||
* deleted by the caller.
|
||||
*/
|
||||
Character * getImage();
|
||||
/**
|
||||
* Returns the image of characters which are currently visible through this window
|
||||
* onto the screen.
|
||||
*
|
||||
* The buffer is managed by the ScreenWindow instance and does not need to be
|
||||
* deleted by the caller.
|
||||
*/
|
||||
Character * getImage();
|
||||
|
||||
/**
|
||||
* Returns the line attributes associated with the lines of characters which
|
||||
* are currently visible through this window
|
||||
*/
|
||||
QVector<LineProperty> getLineProperties();
|
||||
/**
|
||||
* Returns the line attributes associated with the lines of characters which
|
||||
* are currently visible through this window
|
||||
*/
|
||||
QVector<LineProperty> getLineProperties();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
int scrollCount() const;
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
int scrollCount() const;
|
||||
|
||||
/**
|
||||
* Resets the count of scrolled lines returned by scrollCount()
|
||||
*/
|
||||
void resetScrollCount();
|
||||
/**
|
||||
* Resets the count of scrolled lines returned by scrollCount()
|
||||
*/
|
||||
void resetScrollCount();
|
||||
|
||||
/**
|
||||
* 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,
|
||||
* but allows views to optimise rendering.
|
||||
*/
|
||||
QRect scrollRegion() const;
|
||||
/**
|
||||
* 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,
|
||||
* but allows views to optimise rendering.
|
||||
*/
|
||||
QRect scrollRegion() const;
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
/**
|
||||
* Sets the end of the selection to the given @p line and @p column within
|
||||
* the window.
|
||||
*/
|
||||
void setSelectionEnd( int column , int line );
|
||||
/**
|
||||
* Retrieves the start of the selection within the window.
|
||||
*/
|
||||
void getSelectionStart( int & column , int & line );
|
||||
/**
|
||||
* Retrieves the end of the selection within the window.
|
||||
*/
|
||||
void getSelectionEnd( int & column , int & line );
|
||||
/**
|
||||
* 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 start of the selection to the given @p line and @p column within
|
||||
* the window.
|
||||
*/
|
||||
void setSelectionStart( int column , int line , bool columnMode );
|
||||
/**
|
||||
* Sets the end of the selection to the given @p line and @p column within
|
||||
* the window.
|
||||
*/
|
||||
void setSelectionEnd( int column , int line );
|
||||
/**
|
||||
* Retrieves the start of the selection within the window.
|
||||
*/
|
||||
void getSelectionStart( int & column , int & line );
|
||||
/**
|
||||
* Retrieves the end of the selection within the window.
|
||||
*/
|
||||
void getSelectionEnd( int & column , int & line );
|
||||
/**
|
||||
* 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);
|
||||
/** Returns the number of lines in the window */
|
||||
int windowLines() const;
|
||||
/** Returns the number of columns in the window */
|
||||
int windowColumns() const;
|
||||
/** 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 */
|
||||
int columnCount() const;
|
||||
/** Returns the total number of lines in the screen */
|
||||
int lineCount() const;
|
||||
/** Returns the total number of columns in the screen */
|
||||
int columnCount() const;
|
||||
|
||||
/** Returns the index of the line which is currently at the top of this window */
|
||||
int currentLine() const;
|
||||
/** Returns the index of the line which is currently at the top of this window */
|
||||
int currentLine() const;
|
||||
|
||||
/**
|
||||
* Returns the position of the cursor
|
||||
* within the window.
|
||||
*/
|
||||
QPoint cursorPosition() const;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
bool atEndOfOutput() const;
|
||||
/**
|
||||
* Convenience method. Returns true if the window is currently at the bottom
|
||||
* of the screen.
|
||||
*/
|
||||
bool atEndOfOutput() const;
|
||||
|
||||
/** Scrolls the window so that @p line is at the top of the window */
|
||||
void scrollTo( int line );
|
||||
/** Scrolls the window so that @p line is at the top of the window */
|
||||
void scrollTo( int line );
|
||||
|
||||
enum RelativeScrollMode {
|
||||
ScrollLines,
|
||||
ScrollPages
|
||||
};
|
||||
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.
|
||||
* @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 );
|
||||
/**
|
||||
* 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.
|
||||
* @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
|
||||
* 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()
|
||||
*/
|
||||
bool trackOutput() const;
|
||||
/**
|
||||
* 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
|
||||
* 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()
|
||||
*/
|
||||
bool trackOutput() const;
|
||||
|
||||
/**
|
||||
* Returns the text which is currently selected.
|
||||
*
|
||||
* @param preserveLineBreaks See Screen::selectedText()
|
||||
*/
|
||||
QString selectedText( bool preserveLineBreaks ) const;
|
||||
/**
|
||||
* Returns the text which is currently selected.
|
||||
*
|
||||
* @param preserveLineBreaks See Screen::selectedText()
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void notifyOutputChanged();
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void notifyOutputChanged();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Emitted when the contents of the associated terminal screen ( see screen() ) changes.
|
||||
*/
|
||||
void outputChanged();
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Emitted when the selection is changed.
|
||||
*/
|
||||
void selectionChanged();
|
||||
/**
|
||||
* Emitted when the selection is changed.
|
||||
*/
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
int endWindowLine() const;
|
||||
void fillUnusedArea();
|
||||
int endWindowLine() const;
|
||||
void fillUnusedArea();
|
||||
|
||||
Screen * _screen; // see setScreen() , screen()
|
||||
Character * _windowBuffer;
|
||||
int _windowBufferSize;
|
||||
bool _bufferNeedsUpdate;
|
||||
Screen * _screen; // see setScreen() , screen()
|
||||
Character * _windowBuffer;
|
||||
int _windowBufferSize;
|
||||
bool _bufferNeedsUpdate;
|
||||
|
||||
int _windowLines;
|
||||
int _currentLine; // see scrollTo() , currentLine()
|
||||
bool _trackOutput; // see setTrackOutput() , trackOutput()
|
||||
int _scrollCount; // count of lines which the window has been scrolled by since
|
||||
// the last call to resetScrollCount()
|
||||
int _windowLines;
|
||||
int _currentLine; // see scrollTo() , currentLine()
|
||||
bool _trackOutput; // see setTrackOutput() , trackOutput()
|
||||
int _scrollCount; // count of lines which the window has been scrolled by since
|
||||
// the last call to resetScrollCount()
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+685
-611
File diff suppressed because it is too large
Load Diff
+452
-449
File diff suppressed because it is too large
Load Diff
+103
-93
@@ -32,71 +32,80 @@ using namespace Konsole;
|
||||
// function copied from kdelibs/kio/kio/kurlcompletion.cpp
|
||||
static bool expandEnv(QString & text);
|
||||
|
||||
ShellCommand::ShellCommand(const QString & fullCommand) {
|
||||
bool inQuotes = false;
|
||||
ShellCommand::ShellCommand(const QString & fullCommand)
|
||||
{
|
||||
bool inQuotes = false;
|
||||
|
||||
QString builder;
|
||||
QString builder;
|
||||
|
||||
for ( int i = 0 ; i < fullCommand.count() ; i++ ) {
|
||||
QChar ch = fullCommand[i];
|
||||
for ( int i = 0 ; i < fullCommand.count() ; i++ ) {
|
||||
QChar ch = fullCommand[i];
|
||||
|
||||
const bool isLastChar = ( i == fullCommand.count() - 1 );
|
||||
const bool isQuote = ( ch == '\'' || ch == '\"' );
|
||||
const bool isLastChar = ( i == fullCommand.count() - 1 );
|
||||
const bool isQuote = ( ch == '\'' || ch == '\"' );
|
||||
|
||||
if ( !isLastChar && isQuote ) {
|
||||
inQuotes = !inQuotes;
|
||||
} else {
|
||||
if ( (!ch.isSpace() || inQuotes) && !isQuote ) {
|
||||
builder.append(ch);
|
||||
}
|
||||
if ( !isLastChar && isQuote ) {
|
||||
inQuotes = !inQuotes;
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ShellCommand::ShellCommand(const QString & command , const QStringList & arguments) {
|
||||
_arguments = arguments;
|
||||
ShellCommand::ShellCommand(const QString & command , const QStringList & arguments)
|
||||
{
|
||||
_arguments = arguments;
|
||||
|
||||
if ( !_arguments.isEmpty() ) {
|
||||
_arguments[0] == command;
|
||||
}
|
||||
if ( !_arguments.isEmpty() ) {
|
||||
_arguments[0] == command;
|
||||
}
|
||||
}
|
||||
QString ShellCommand::fullCommand() const {
|
||||
return _arguments.join(QChar(' '));
|
||||
QString ShellCommand::fullCommand() const
|
||||
{
|
||||
return _arguments.join(QChar(' '));
|
||||
}
|
||||
QString ShellCommand::command() const {
|
||||
if ( !_arguments.isEmpty() ) {
|
||||
return _arguments[0];
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
QString ShellCommand::command() const
|
||||
{
|
||||
if ( !_arguments.isEmpty() ) {
|
||||
return _arguments[0];
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
QStringList ShellCommand::arguments() const {
|
||||
return _arguments;
|
||||
QStringList ShellCommand::arguments() const
|
||||
{
|
||||
return _arguments;
|
||||
}
|
||||
bool ShellCommand::isRootCommand() const {
|
||||
Q_ASSERT(0); // not implemented yet
|
||||
return false;
|
||||
bool ShellCommand::isRootCommand() const
|
||||
{
|
||||
Q_ASSERT(0); // not implemented yet
|
||||
return false;
|
||||
}
|
||||
bool ShellCommand::isAvailable() const {
|
||||
Q_ASSERT(0); // not implemented yet
|
||||
return false;
|
||||
bool ShellCommand::isAvailable() const
|
||||
{
|
||||
Q_ASSERT(0); // not implemented yet
|
||||
return false;
|
||||
}
|
||||
QStringList ShellCommand::expand(const QStringList & items) {
|
||||
QStringList result;
|
||||
QStringList ShellCommand::expand(const QStringList & items)
|
||||
{
|
||||
QStringList result;
|
||||
|
||||
foreach( QString item , items )
|
||||
result << expand(item);
|
||||
foreach( QString item , items )
|
||||
result << expand(item);
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
QString ShellCommand::expand(const QString & text) {
|
||||
QString result = text;
|
||||
expandEnv(result);
|
||||
return result;
|
||||
QString ShellCommand::expand(const QString & text)
|
||||
{
|
||||
QString result = text;
|
||||
expandEnv(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -105,55 +114,56 @@ QString ShellCommand::expand(const QString & text) {
|
||||
* Expand environment variables in text. Escaped '$' characters are ignored.
|
||||
* Return true if any variables were expanded
|
||||
*/
|
||||
static bool expandEnv( QString & text ) {
|
||||
// Find all environment variables beginning with '$'
|
||||
//
|
||||
int pos = 0;
|
||||
|
||||
bool expanded = false;
|
||||
|
||||
while ( (pos = text.indexOf(QLatin1Char('$'), pos)) != -1 ) {
|
||||
|
||||
// Skip escaped '$'
|
||||
static bool expandEnv( QString & text )
|
||||
{
|
||||
// Find all environment variables beginning with '$'
|
||||
//
|
||||
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 );
|
||||
int pos = 0;
|
||||
|
||||
if ( pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2) ) {
|
||||
pos2 = pos_tmp;
|
||||
}
|
||||
bool expanded = false;
|
||||
|
||||
if ( pos2 == -1 ) {
|
||||
pos2 = text.length();
|
||||
}
|
||||
while ( (pos = text.indexOf(QLatin1Char('$'), pos)) != -1 ) {
|
||||
|
||||
// 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;
|
||||
// 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 );
|
||||
|
||||
return expanded;
|
||||
if ( pos2 == -1 || (pos_tmp != -1 && pos_tmp < pos2) ) {
|
||||
pos2 = pos_tmp;
|
||||
}
|
||||
|
||||
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()) );
|
||||
|
||||
if ( !value.isEmpty() ) {
|
||||
expanded = true;
|
||||
text.replace( pos, len, value );
|
||||
pos = pos + value.length();
|
||||
} else {
|
||||
pos = pos2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expanded;
|
||||
}
|
||||
|
||||
+31
-29
@@ -25,7 +25,8 @@
|
||||
// Qt
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
/**
|
||||
* A class to parse and extract information about shell commands.
|
||||
@@ -48,42 +49,43 @@ namespace Konsole {
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
class ShellCommand {
|
||||
class ShellCommand
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs a ShellCommand from a command line.
|
||||
*
|
||||
* @param fullCommand The command line to parse.
|
||||
*/
|
||||
ShellCommand(const QString & fullCommand);
|
||||
/**
|
||||
* Constructs a ShellCommand with the specified @p command and @p arguments.
|
||||
*/
|
||||
ShellCommand(const QString & command , const QStringList & arguments);
|
||||
/**
|
||||
* Constructs a ShellCommand from a command line.
|
||||
*
|
||||
* @param fullCommand The command line to parse.
|
||||
*/
|
||||
ShellCommand(const QString & fullCommand);
|
||||
/**
|
||||
* Constructs a ShellCommand with the specified @p command and @p arguments.
|
||||
*/
|
||||
ShellCommand(const QString & command , const QStringList & arguments);
|
||||
|
||||
/** Returns the command. */
|
||||
QString command() const;
|
||||
/** Returns the arguments. */
|
||||
QStringList arguments() const;
|
||||
/** Returns the command. */
|
||||
QString command() const;
|
||||
/** Returns the arguments. */
|
||||
QStringList arguments() const;
|
||||
|
||||
/**
|
||||
* Returns the full command line.
|
||||
*/
|
||||
QString fullCommand() const;
|
||||
/**
|
||||
* Returns the full command line.
|
||||
*/
|
||||
QString fullCommand() const;
|
||||
|
||||
/** Returns true if this is a root command. */
|
||||
bool isRootCommand() const;
|
||||
/** Returns true if the program specified by @p command() exists. */
|
||||
bool isAvailable() const;
|
||||
/** Returns true if this is a root command. */
|
||||
bool isRootCommand() const;
|
||||
/** Returns true if the program specified by @p command() exists. */
|
||||
bool isAvailable() const;
|
||||
|
||||
/** Expands environment variables in @p text .*/
|
||||
static QString expand(const QString & text);
|
||||
/** Expands environment variables in @p text .*/
|
||||
static QString expand(const QString & text);
|
||||
|
||||
/** Expands environment variables in each string in @p list. */
|
||||
static QStringList expand(const QStringList & items);
|
||||
/** Expands environment variables in each string in @p list. */
|
||||
static QStringList expand(const QStringList & items);
|
||||
|
||||
private:
|
||||
QStringList _arguments;
|
||||
QStringList _arguments;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+132
-119
@@ -31,181 +31,194 @@
|
||||
using namespace Konsole;
|
||||
|
||||
PlainTextDecoder::PlainTextDecoder()
|
||||
: _output(0)
|
||||
, _includeTrailingWhitespace(true) {
|
||||
: _output(0)
|
||||
, _includeTrailingWhitespace(true)
|
||||
{
|
||||
|
||||
}
|
||||
void PlainTextDecoder::setTrailingWhitespace(bool enable) {
|
||||
_includeTrailingWhitespace = enable;
|
||||
void PlainTextDecoder::setTrailingWhitespace(bool enable)
|
||||
{
|
||||
_includeTrailingWhitespace = enable;
|
||||
}
|
||||
bool PlainTextDecoder::trailingWhitespace() const {
|
||||
return _includeTrailingWhitespace;
|
||||
bool PlainTextDecoder::trailingWhitespace() const
|
||||
{
|
||||
return _includeTrailingWhitespace;
|
||||
}
|
||||
void PlainTextDecoder::begin(QTextStream * output) {
|
||||
_output = output;
|
||||
void PlainTextDecoder::begin(QTextStream * output)
|
||||
{
|
||||
_output = output;
|
||||
}
|
||||
void PlainTextDecoder::end() {
|
||||
_output = 0;
|
||||
void PlainTextDecoder::end()
|
||||
{
|
||||
_output = 0;
|
||||
}
|
||||
void PlainTextDecoder::decodeLine(const Character * const characters, int count, LineProperty /*properties*/
|
||||
) {
|
||||
Q_ASSERT( _output );
|
||||
)
|
||||
{
|
||||
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;
|
||||
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 ( characters[i].character != ' ' ) {
|
||||
break;
|
||||
} else {
|
||||
outputCount--;
|
||||
}
|
||||
// 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 ( characters[i].character != ' ' ) {
|
||||
break;
|
||||
} else {
|
||||
outputCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<outputCount; i++) {
|
||||
plainText.append( QChar(characters[i].character) );
|
||||
}
|
||||
for (int i=0; i<outputCount; i++) {
|
||||
plainText.append( QChar(characters[i].character) );
|
||||
}
|
||||
|
||||
*_output << plainText;
|
||||
*_output << plainText;
|
||||
}
|
||||
|
||||
HTMLDecoder::HTMLDecoder() :
|
||||
_output(0)
|
||||
,_colorTable(base_color_table)
|
||||
,_innerSpanOpen(false)
|
||||
,_lastRendition(DEFAULT_RENDITION) {
|
||||
_output(0)
|
||||
,_colorTable(base_color_table)
|
||||
,_innerSpanOpen(false)
|
||||
,_lastRendition(DEFAULT_RENDITION)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void HTMLDecoder::begin(QTextStream * output) {
|
||||
_output = output;
|
||||
void HTMLDecoder::begin(QTextStream * output)
|
||||
{
|
||||
_output = output;
|
||||
|
||||
QString text;
|
||||
QString text;
|
||||
|
||||
//open monospace span
|
||||
openSpan(text,"font-family:monospace");
|
||||
//open monospace span
|
||||
openSpan(text,"font-family:monospace");
|
||||
|
||||
*output << text;
|
||||
*output << text;
|
||||
}
|
||||
|
||||
void HTMLDecoder::end() {
|
||||
Q_ASSERT( _output );
|
||||
void HTMLDecoder::end()
|
||||
{
|
||||
Q_ASSERT( _output );
|
||||
|
||||
QString text;
|
||||
QString text;
|
||||
|
||||
closeSpan(text);
|
||||
closeSpan(text);
|
||||
|
||||
*_output << text;
|
||||
*_output << text;
|
||||
|
||||
_output = 0;
|
||||
_output = 0;
|
||||
|
||||
}
|
||||
|
||||
//TODO: Support for LineProperty (mainly double width , double height)
|
||||
void HTMLDecoder::decodeLine(const Character * const characters, int count, LineProperty /*properties*/
|
||||
) {
|
||||
Q_ASSERT( _output );
|
||||
)
|
||||
{
|
||||
Q_ASSERT( _output );
|
||||
|
||||
QString text;
|
||||
QString text;
|
||||
|
||||
int spaceCount = 0;
|
||||
int spaceCount = 0;
|
||||
|
||||
for (int i=0; i<count; i++) {
|
||||
QChar ch(characters[i].character);
|
||||
for (int i=0; i<count; i++) {
|
||||
QChar ch(characters[i].character);
|
||||
|
||||
//check if appearance of character is different from previous char
|
||||
if ( characters[i].rendition != _lastRendition ||
|
||||
characters[i].foregroundColor != _lastForeColor ||
|
||||
characters[i].backgroundColor != _lastBackColor ) {
|
||||
if ( _innerSpanOpen ) {
|
||||
closeSpan(text);
|
||||
}
|
||||
//check if appearance of character is different from previous char
|
||||
if ( characters[i].rendition != _lastRendition ||
|
||||
characters[i].foregroundColor != _lastForeColor ||
|
||||
characters[i].backgroundColor != _lastBackColor ) {
|
||||
if ( _innerSpanOpen ) {
|
||||
closeSpan(text);
|
||||
}
|
||||
|
||||
_lastRendition = characters[i].rendition;
|
||||
_lastForeColor = characters[i].foregroundColor;
|
||||
_lastBackColor = characters[i].backgroundColor;
|
||||
_lastRendition = characters[i].rendition;
|
||||
_lastForeColor = characters[i].foregroundColor;
|
||||
_lastBackColor = characters[i].backgroundColor;
|
||||
|
||||
//build up style string
|
||||
QString style;
|
||||
//build up style string
|
||||
QString style;
|
||||
|
||||
if ( _lastRendition & RE_BOLD ||
|
||||
(_colorTable && characters[i].isBold(_colorTable)) ) {
|
||||
style.append("font-weight:bold;");
|
||||
}
|
||||
if ( _lastRendition & RE_BOLD ||
|
||||
(_colorTable && characters[i].isBold(_colorTable)) ) {
|
||||
style.append("font-weight:bold;");
|
||||
}
|
||||
|
||||
|
||||
if ( _lastRendition & RE_UNDERLINE ) {
|
||||
style.append("font-decoration:underline;");
|
||||
}
|
||||
if ( _lastRendition & RE_UNDERLINE ) {
|
||||
style.append("font-decoration:underline;");
|
||||
}
|
||||
|
||||
//colours - a colour table must have been defined first
|
||||
if ( _colorTable ) {
|
||||
style.append( QString("color:%1;").arg(_lastForeColor.color(_colorTable).name() ) );
|
||||
//colours - a colour table must have been defined first
|
||||
if ( _colorTable ) {
|
||||
style.append( QString("color:%1;").arg(_lastForeColor.color(_colorTable).name() ) );
|
||||
|
||||
if (!characters[i].isTransparent(_colorTable)) {
|
||||
style.append( QString("background-color:%1;").arg(_lastBackColor.color(_colorTable).name() ) );
|
||||
if (!characters[i].isTransparent(_colorTable)) {
|
||||
style.append( QString("background-color:%1;").arg(_lastBackColor.color(_colorTable).name() ) );
|
||||
}
|
||||
}
|
||||
|
||||
//open the span with the current style
|
||||
openSpan(text,style);
|
||||
_innerSpanOpen = true;
|
||||
}
|
||||
|
||||
//handle whitespace
|
||||
if (ch.isSpace()) {
|
||||
spaceCount++;
|
||||
} else {
|
||||
spaceCount = 0;
|
||||
}
|
||||
|
||||
|
||||
//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
|
||||
}
|
||||
}
|
||||
|
||||
//open the span with the current style
|
||||
openSpan(text,style);
|
||||
_innerSpanOpen = true;
|
||||
}
|
||||
|
||||
//handle whitespace
|
||||
if (ch.isSpace()) {
|
||||
spaceCount++;
|
||||
} else {
|
||||
spaceCount = 0;
|
||||
//close any remaining open inner spans
|
||||
if ( _innerSpanOpen ) {
|
||||
closeSpan(text);
|
||||
}
|
||||
|
||||
//start new line
|
||||
text.append("<br>");
|
||||
|
||||
//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("<br>");
|
||||
|
||||
*_output << text;
|
||||
*_output << text;
|
||||
}
|
||||
|
||||
void HTMLDecoder::openSpan(QString & text , const QString & style) {
|
||||
text.append( QString("<span style=\"%1\">").arg(style) );
|
||||
void HTMLDecoder::openSpan(QString & text , const QString & style)
|
||||
{
|
||||
text.append( QString("<span style=\"%1\">").arg(style) );
|
||||
}
|
||||
|
||||
void HTMLDecoder::closeSpan(QString & text) {
|
||||
text.append("</span>");
|
||||
void HTMLDecoder::closeSpan(QString & text)
|
||||
{
|
||||
text.append("</span>");
|
||||
}
|
||||
|
||||
void HTMLDecoder::setColorTable(const ColorEntry * table) {
|
||||
_colorTable = table;
|
||||
void HTMLDecoder::setColorTable(const ColorEntry * table)
|
||||
{
|
||||
_colorTable = table;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
|
||||
class QTextStream;
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
/**
|
||||
* Base class for terminal character decoders
|
||||
@@ -39,94 +40,97 @@ namespace Konsole {
|
||||
* Derived classes may produce either plain text with no other colour or appearance information, or
|
||||
* they may produce text which incorporates these additional properties.
|
||||
*/
|
||||
class TerminalCharacterDecoder {
|
||||
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;
|
||||
/** 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;
|
||||
};
|
||||
|
||||
/**
|
||||
* A terminal character decoder which produces plain text, ignoring colours and other appearance-related
|
||||
* properties of the original characters.
|
||||
*/
|
||||
class PlainTextDecoder : public TerminalCharacterDecoder {
|
||||
class PlainTextDecoder : public TerminalCharacterDecoder
|
||||
{
|
||||
public:
|
||||
PlainTextDecoder();
|
||||
PlainTextDecoder();
|
||||
|
||||
/**
|
||||
* Set whether trailing whitespace at the end of lines should be included
|
||||
* in the output.
|
||||
* Defaults to true.
|
||||
*/
|
||||
void setTrailingWhitespace(bool enable);
|
||||
/**
|
||||
* Returns whether trailing whitespace at the end of lines is included
|
||||
* in the output.
|
||||
*/
|
||||
bool trailingWhitespace() const;
|
||||
/**
|
||||
* Set whether trailing whitespace at the end of lines should be included
|
||||
* in the output.
|
||||
* Defaults to true.
|
||||
*/
|
||||
void setTrailingWhitespace(bool enable);
|
||||
/**
|
||||
* Returns whether trailing whitespace at the end of lines is included
|
||||
* in the output.
|
||||
*/
|
||||
bool trailingWhitespace() const;
|
||||
|
||||
virtual void begin(QTextStream * output);
|
||||
virtual void end();
|
||||
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;
|
||||
QTextStream * _output;
|
||||
bool _includeTrailingWhitespace;
|
||||
};
|
||||
|
||||
/**
|
||||
* A terminal character decoder which produces pretty HTML markup
|
||||
*/
|
||||
class HTMLDecoder : public TerminalCharacterDecoder {
|
||||
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 );
|
||||
/**
|
||||
* 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 decodeLine(const Character * const characters,
|
||||
int count,
|
||||
LineProperty properties);
|
||||
|
||||
virtual void begin(QTextStream * output);
|
||||
virtual void end();
|
||||
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;
|
||||
QTextStream * _output;
|
||||
const ColorEntry * _colorTable;
|
||||
bool _innerSpanOpen;
|
||||
quint8 _lastRendition;
|
||||
CharacterColor _lastForeColor;
|
||||
CharacterColor _lastBackColor;
|
||||
|
||||
};
|
||||
|
||||
|
||||
+2079
-1986
File diff suppressed because it is too large
Load Diff
+614
-612
File diff suppressed because it is too large
Load Diff
+1023
-981
File diff suppressed because it is too large
Load Diff
+87
-85
@@ -47,20 +47,21 @@
|
||||
#define MODE_Ansi (MODES_SCREEN+7)
|
||||
#define MODE_total (MODES_SCREEN+8)
|
||||
|
||||
namespace Konsole {
|
||||
namespace Konsole
|
||||
{
|
||||
|
||||
struct DECpar {
|
||||
bool mode[MODE_total];
|
||||
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
|
||||
// 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
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -73,113 +74,114 @@ struct CharCodes {
|
||||
* sequences.
|
||||
*
|
||||
*/
|
||||
class Vt102Emulation : public Emulation {
|
||||
Q_OBJECT
|
||||
class Vt102Emulation : public Emulation
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/** Constructs a new emulation */
|
||||
Vt102Emulation();
|
||||
~Vt102Emulation();
|
||||
/** Constructs a new emulation */
|
||||
Vt102Emulation();
|
||||
~Vt102Emulation();
|
||||
|
||||
// reimplemented
|
||||
virtual void clearEntireScreen();
|
||||
virtual void reset();
|
||||
// reimplemented
|
||||
virtual void clearEntireScreen();
|
||||
virtual void reset();
|
||||
|
||||
// reimplemented
|
||||
virtual char getErase() const;
|
||||
// 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<int,QString> _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<int,QString> _pendingTitleUpdates;
|
||||
QTimer * _titleUpdateTimer;
|
||||
|
||||
};
|
||||
|
||||
|
||||
+808
-756
File diff suppressed because it is too large
Load Diff
+648
-646
File diff suppressed because it is too large
Load Diff
+198
-181
@@ -35,94 +35,100 @@
|
||||
|
||||
#include <QtCore/QSocketNotifier>
|
||||
|
||||
class K3ProcessController::Private {
|
||||
class K3ProcessController::Private
|
||||
{
|
||||
public:
|
||||
Private()
|
||||
: needcheck( false ),
|
||||
notifier( 0 ) {
|
||||
}
|
||||
Private()
|
||||
: needcheck( false ),
|
||||
notifier( 0 ) {
|
||||
}
|
||||
|
||||
~Private() {
|
||||
delete notifier;
|
||||
}
|
||||
~Private() {
|
||||
delete notifier;
|
||||
}
|
||||
|
||||
int fd[2];
|
||||
bool needcheck;
|
||||
QSocketNotifier * notifier;
|
||||
QList<K3Process *> kProcessList;
|
||||
QList<int> unixProcessList;
|
||||
static struct sigaction oldChildHandlerData;
|
||||
static bool handlerSet;
|
||||
static int refCount;
|
||||
static K3ProcessController * instance;
|
||||
int fd[2];
|
||||
bool needcheck;
|
||||
QSocketNotifier * notifier;
|
||||
QList<K3Process *> kProcessList;
|
||||
QList<int> unixProcessList;
|
||||
static struct sigaction oldChildHandlerData;
|
||||
static bool handlerSet;
|
||||
static int refCount;
|
||||
static K3ProcessController * instance;
|
||||
};
|
||||
|
||||
K3ProcessController * K3ProcessController::Private::instance = 0;
|
||||
int K3ProcessController::Private::refCount = 0;
|
||||
|
||||
void K3ProcessController::ref() {
|
||||
if ( !Private::refCount ) {
|
||||
Private::instance = new K3ProcessController;
|
||||
setupHandlers();
|
||||
}
|
||||
Private::refCount++;
|
||||
void K3ProcessController::ref()
|
||||
{
|
||||
if ( !Private::refCount ) {
|
||||
Private::instance = new K3ProcessController;
|
||||
setupHandlers();
|
||||
}
|
||||
Private::refCount++;
|
||||
}
|
||||
|
||||
void K3ProcessController::deref() {
|
||||
Private::refCount--;
|
||||
if( !Private::refCount ) {
|
||||
resetHandlers();
|
||||
delete Private::instance;
|
||||
Private::instance = 0;
|
||||
}
|
||||
void K3ProcessController::deref()
|
||||
{
|
||||
Private::refCount--;
|
||||
if ( !Private::refCount ) {
|
||||
resetHandlers();
|
||||
delete Private::instance;
|
||||
Private::instance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
K3ProcessController * K3ProcessController::instance() {
|
||||
/*
|
||||
* there were no safety guards in previous revisions, is that ok?
|
||||
if ( !Private::instance ) {
|
||||
ref();
|
||||
}
|
||||
*/
|
||||
K3ProcessController * K3ProcessController::instance()
|
||||
{
|
||||
/*
|
||||
* there were no safety guards in previous revisions, is that ok?
|
||||
if ( !Private::instance ) {
|
||||
ref();
|
||||
}
|
||||
*/
|
||||
|
||||
return Private::instance;
|
||||
return Private::instance;
|
||||
}
|
||||
|
||||
K3ProcessController::K3ProcessController()
|
||||
: d( new Private ) {
|
||||
if( pipe( d->fd ) ) {
|
||||
perror( "pipe" );
|
||||
abort();
|
||||
}
|
||||
: d( new Private )
|
||||
{
|
||||
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() {
|
||||
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
|
||||
@@ -130,182 +136,193 @@ struct sigaction K3ProcessController::Private::oldChildHandlerData;
|
||||
#endif
|
||||
bool K3ProcessController::Private::handlerSet = false;
|
||||
|
||||
void K3ProcessController::setupHandlers() {
|
||||
if( Private::handlerSet ) {
|
||||
return;
|
||||
}
|
||||
Private::handlerSet = true;
|
||||
void K3ProcessController::setupHandlers()
|
||||
{
|
||||
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;
|
||||
void K3ProcessController::resetHandlers()
|
||||
{
|
||||
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,
|
||||
// as otherwise there are race conditions, locking requirements, and things
|
||||
// generally get harder
|
||||
void K3ProcessController::theSigCHLDHandler( int arg ) {
|
||||
int saved_errno = errno;
|
||||
void K3ProcessController::theSigCHLDHandler( int arg )
|
||||
{
|
||||
int saved_errno = errno;
|
||||
|
||||
char dummy = 0;
|
||||
::write( instance()->d->fd[1], &dummy, 1 );
|
||||
char dummy = 0;
|
||||
::write( instance()->d->fd[1], &dummy, 1 );
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
if ( Private::oldChildHandlerData.sa_handler != SIG_IGN &&
|
||||
Private::oldChildHandlerData.sa_handler != SIG_DFL ) {
|
||||
Private::oldChildHandlerData.sa_handler( arg ); // call the old handler
|
||||
}
|
||||
if ( Private::oldChildHandlerData.sa_handler != SIG_IGN &&
|
||||
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];
|
||||
int K3ProcessController::notifierFd() const
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
K3ProcessController::rescheduleCheck() {
|
||||
if( d->needcheck ) {
|
||||
d->needcheck = false;
|
||||
char dummy = 0;
|
||||
::write( d->fd[1], &dummy, 1 );
|
||||
}
|
||||
K3ProcessController::rescheduleCheck()
|
||||
{
|
||||
if ( d->needcheck ) {
|
||||
d->needcheck = false;
|
||||
char dummy = 0;
|
||||
::write( d->fd[1], &dummy, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
void K3ProcessController::slotDoHousekeeping() {
|
||||
char dummy[16]; // somewhat bigger - just in case several have queued up
|
||||
::read( d->fd[0], dummy, sizeof(dummy) );
|
||||
void K3ProcessController::slotDoHousekeeping()
|
||||
{
|
||||
char dummy[16]; // somewhat bigger - just in case several have queued up
|
||||
::read( d->fd[0], dummy, sizeof(dummy) );
|
||||
|
||||
int status;
|
||||
int status;
|
||||
again:
|
||||
QList<K3Process *>::iterator it( d->kProcessList.begin() );
|
||||
QList<K3Process *>::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;
|
||||
QList<K3Process *>::iterator it( d->kProcessList.begin() );
|
||||
QList<K3Process *>::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;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
QList<int>::iterator uit( d->unixProcessList.begin() );
|
||||
QList<int>::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;
|
||||
QList<int>::iterator uit( d->unixProcessList.begin() );
|
||||
QList<int>::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 ) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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 );
|
||||
|
||||
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;
|
||||
}
|
||||
// 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 );
|
||||
void K3ProcessController::addKProcess( K3Process * p )
|
||||
{
|
||||
d->kProcessList.append( p );
|
||||
}
|
||||
|
||||
void K3ProcessController::removeKProcess( K3Process * p ) {
|
||||
d->kProcessList.removeAll( p );
|
||||
void K3ProcessController::removeKProcess( K3Process * 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
|
||||
void K3ProcessController::addProcess( int pid )
|
||||
{
|
||||
d->unixProcessList.append( pid );
|
||||
ref(); // make sure we stay around when the K3Process goes away
|
||||
}
|
||||
|
||||
//#include "moc_k3processcontroller.cpp"
|
||||
|
||||
+77
-76
@@ -36,100 +36,101 @@
|
||||
*
|
||||
* This class takes care of the actual (UN*X) signal handling.
|
||||
*/
|
||||
class K3ProcessController : public QObject {
|
||||
Q_OBJECT
|
||||
class K3ProcessController : public QObject
|
||||
{
|
||||
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
|
||||
|
||||
+150
-146
@@ -10,30 +10,31 @@
|
||||
#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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,71 +68,72 @@ static int bisearch(quint16 ucs, const struct interval * table, int max) {
|
||||
* in ISO 10646.
|
||||
*/
|
||||
|
||||
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 }
|
||||
};
|
||||
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 }
|
||||
};
|
||||
|
||||
/* 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) */));
|
||||
}
|
||||
|
||||
@@ -144,77 +146,79 @@ int konsole_wcwidth(quint16 ucs) {
|
||||
* encodings who want to migrate to UCS. It is not otherwise
|
||||
* recommended for general use.
|
||||
*/
|
||||
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 }
|
||||
};
|
||||
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 }
|
||||
};
|
||||
|
||||
/* 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 string_width( const QString & txt )
|
||||
{
|
||||
int w = 0;
|
||||
for ( int i = 0; i < txt.length(); ++i ) {
|
||||
w += konsole_wcwidth( txt[ i ].unicode() );
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
+289
-271
@@ -148,13 +148,15 @@ extern "C" {
|
||||
//////////////////
|
||||
|
||||
KPtyPrivate::KPtyPrivate() :
|
||||
masterFd(-1), slaveFd(-1) {
|
||||
masterFd(-1), slaveFd(-1)
|
||||
{
|
||||
}
|
||||
|
||||
bool KPtyPrivate::chownpty(bool) {
|
||||
bool KPtyPrivate::chownpty(bool)
|
||||
{
|
||||
// return !QProcess::execute(KStandardDirs::findExe("kgrantpty"),
|
||||
// QStringList() << (grant?"--grant":"--revoke") << QString::number(masterFd));
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
@@ -162,388 +164,397 @@ bool KPtyPrivate::chownpty(bool) {
|
||||
/////////////////////////////
|
||||
|
||||
KPty::KPty() :
|
||||
d_ptr(new KPtyPrivate) {
|
||||
d_ptr->q_ptr = this;
|
||||
d_ptr(new KPtyPrivate)
|
||||
{
|
||||
d_ptr->q_ptr = this;
|
||||
}
|
||||
|
||||
KPty::KPty(KPtyPrivate * d) :
|
||||
d_ptr(d) {
|
||||
d_ptr->q_ptr = this;
|
||||
d_ptr(d)
|
||||
{
|
||||
d_ptr->q_ptr = this;
|
||||
}
|
||||
|
||||
KPty::~KPty() {
|
||||
close();
|
||||
delete d_ptr;
|
||||
KPty::~KPty()
|
||||
{
|
||||
close();
|
||||
delete d_ptr;
|
||||
}
|
||||
|
||||
bool KPty::open() {
|
||||
Q_D(KPty);
|
||||
bool KPty::open()
|
||||
{
|
||||
Q_D(KPty);
|
||||
|
||||
if (d->masterFd >= 0) {
|
||||
return true;
|
||||
}
|
||||
if (d->masterFd >= 0) {
|
||||
return 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)) {
|
||||
d->ttyName = QByteArray("/dev/pts/") + QByteArray::number(ptyno);
|
||||
int ptyno;
|
||||
if (!ioctl(d->masterFd, TIOCGPTN, &ptyno)) {
|
||||
d->ttyName = QByteArray("/dev/pts/") + QByteArray::number(ptyno);
|
||||
#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 ();
|
||||
|
||||
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();
|
||||
|
||||
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 ();
|
||||
|
||||
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()
|
||||
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__GETPTY) || defined (HAVE_GRANTPT)
|
||||
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() {
|
||||
Q_D(KPty);
|
||||
void KPty::closeSlave()
|
||||
{
|
||||
Q_D(KPty);
|
||||
|
||||
if (d->slaveFd < 0) {
|
||||
return;
|
||||
}
|
||||
::close(d->slaveFd);
|
||||
d->slaveFd = -1;
|
||||
}
|
||||
|
||||
void KPty::close() {
|
||||
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)) {
|
||||
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);
|
||||
if (d->slaveFd < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
::close(d->masterFd);
|
||||
d->masterFd = -1;
|
||||
::close(d->slaveFd);
|
||||
d->slaveFd = -1;
|
||||
}
|
||||
|
||||
void KPty::setCTty() {
|
||||
Q_D(KPty);
|
||||
void KPty::close()
|
||||
{
|
||||
Q_D(KPty);
|
||||
|
||||
// Setup job control //////////////////////////////////
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Become session leader, process group leader,
|
||||
// and get rid of the old controlling terminal.
|
||||
setsid();
|
||||
void KPty::setCTty()
|
||||
{
|
||||
Q_D(KPty);
|
||||
|
||||
// make our slave pty the new controlling terminal.
|
||||
// Setup job control //////////////////////////////////
|
||||
|
||||
// Become session leader, process group leader,
|
||||
// and get rid of the old controlling terminal.
|
||||
setsid();
|
||||
|
||||
// make our slave pty the new controlling terminal.
|
||||
#ifdef TIOCSCTTY
|
||||
ioctl(d->slaveFd, TIOCSCTTY, 0);
|
||||
ioctl(d->slaveFd, TIOCSCTTY, 0);
|
||||
#else
|
||||
// __svr4__ hack: the first tty opened after setsid() becomes controlling tty
|
||||
::close(::open(d->ttyName, O_WRONLY, 0));
|
||||
// __svr4__ hack: the first tty opened after setsid() becomes controlling tty
|
||||
::close(::open(d->ttyName, O_WRONLY, 0));
|
||||
#endif
|
||||
|
||||
// make our new process group the foreground group on the pty
|
||||
int pgrp = getpid();
|
||||
// make our new process group the foreground group on the pty
|
||||
int pgrp = getpid();
|
||||
#if defined(_POSIX_VERSION) || defined(__svr4__)
|
||||
tcsetpgrp(d->slaveFd, pgrp);
|
||||
tcsetpgrp(d->slaveFd, pgrp);
|
||||
#elif defined(TIOCSPGRP)
|
||||
ioctl(d->slaveFd, TIOCSPGRP, (char *)&pgrp);
|
||||
ioctl(d->slaveFd, TIOCSPGRP, (char *)&pgrp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void KPty::login(const char * user, const char * remotehost) {
|
||||
void KPty::login(const char * user, const char * remotehost)
|
||||
{
|
||||
#ifdef HAVE_UTEMPTER
|
||||
Q_D(KPty);
|
||||
Q_D(KPty);
|
||||
|
||||
addToUtmp(d->ttyName, remotehost, d->masterFd);
|
||||
Q_UNUSED(user);
|
||||
addToUtmp(d->ttyName, remotehost, d->masterFd);
|
||||
Q_UNUSED(user);
|
||||
#else
|
||||
# ifdef HAVE_UTMPX
|
||||
struct utmpx l_struct;
|
||||
struct utmpx l_struct;
|
||||
# else
|
||||
struct utmp l_struct;
|
||||
struct utmp l_struct;
|
||||
# endif
|
||||
memset(&l_struct, 0, sizeof(l_struct));
|
||||
// note: strncpy without terminators _is_ correct here. man 4 utmp
|
||||
memset(&l_struct, 0, sizeof(l_struct));
|
||||
// note: strncpy without terminators _is_ correct here. man 4 utmp
|
||||
|
||||
if (user) {
|
||||
strncpy(l_struct.ut_name, user, sizeof(l_struct.ut_name));
|
||||
}
|
||||
if (user) {
|
||||
strncpy(l_struct.ut_name, user, sizeof(l_struct.ut_name));
|
||||
}
|
||||
|
||||
if (remotehost) {
|
||||
strncpy(l_struct.ut_host, remotehost, sizeof(l_struct.ut_host));
|
||||
if (remotehost) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
# ifndef __GLIBC__
|
||||
Q_D(KPty);
|
||||
const char * str_ptr = d->ttyName.data();
|
||||
if (!memcmp(str_ptr, "/dev/", 5)) {
|
||||
str_ptr += 5;
|
||||
}
|
||||
strncpy(l_struct.ut_line, str_ptr, sizeof(l_struct.ut_line));
|
||||
Q_D(KPty);
|
||||
const char * str_ptr = d->ttyName.data();
|
||||
if (!memcmp(str_ptr, "/dev/", 5)) {
|
||||
str_ptr += 5;
|
||||
}
|
||||
strncpy(l_struct.ut_line, str_ptr, sizeof(l_struct.ut_line));
|
||||
# ifdef HAVE_STRUCT_UTMP_UT_ID
|
||||
strncpy(l_struct.ut_id,
|
||||
str_ptr + strlen(str_ptr) - sizeof(l_struct.ut_id),
|
||||
sizeof(l_struct.ut_id));
|
||||
strncpy(l_struct.ut_id,
|
||||
str_ptr + strlen(str_ptr) - sizeof(l_struct.ut_id),
|
||||
sizeof(l_struct.ut_id));
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_UTMPX
|
||||
gettimeofday(&l_struct.ut_tv, 0);
|
||||
gettimeofday(&l_struct.ut_tv, 0);
|
||||
# else
|
||||
l_struct.ut_time = time(0);
|
||||
l_struct.ut_time = time(0);
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_LOGIN
|
||||
# ifdef HAVE_LOGINX
|
||||
::loginx(&l_struct);
|
||||
::loginx(&l_struct);
|
||||
# else
|
||||
::login(&l_struct);
|
||||
::login(&l_struct);
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAVE_STRUCT_UTMP_UT_TYPE
|
||||
l_struct.ut_type = USER_PROCESS;
|
||||
l_struct.ut_type = USER_PROCESS;
|
||||
# endif
|
||||
# ifdef HAVE_STRUCT_UTMP_UT_PID
|
||||
l_struct.ut_pid = getpid();
|
||||
l_struct.ut_pid = getpid();
|
||||
# ifdef HAVE_STRUCT_UTMP_UT_SESSION
|
||||
l_struct.ut_session = getsid(0);
|
||||
l_struct.ut_session = getsid(0);
|
||||
# endif
|
||||
# endif
|
||||
# ifdef HAVE_UTMPX
|
||||
utmpxname(_PATH_UTMPX);
|
||||
setutxent();
|
||||
pututxline(&l_struct);
|
||||
endutxent();
|
||||
updwtmpx(_PATH_WTMPX, &l_struct);
|
||||
utmpxname(_PATH_UTMPX);
|
||||
setutxent();
|
||||
pututxline(&l_struct);
|
||||
endutxent();
|
||||
updwtmpx(_PATH_WTMPX, &l_struct);
|
||||
# else
|
||||
utmpname(_PATH_UTMP);
|
||||
setutent();
|
||||
pututline(&l_struct);
|
||||
endutent();
|
||||
updwtmp(_PATH_WTMP, &l_struct);
|
||||
utmpname(_PATH_UTMP);
|
||||
setutent();
|
||||
pututline(&l_struct);
|
||||
endutent();
|
||||
updwtmp(_PATH_WTMP, &l_struct);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void KPty::logout() {
|
||||
void KPty::logout()
|
||||
{
|
||||
#ifdef HAVE_UTEMPTER
|
||||
Q_D(KPty);
|
||||
Q_D(KPty);
|
||||
|
||||
removeLineFromUtmp(d->ttyName, d->masterFd);
|
||||
removeLineFromUtmp(d->ttyName, d->masterFd);
|
||||
#else
|
||||
Q_D(KPty);
|
||||
Q_D(KPty);
|
||||
|
||||
const char * str_ptr = d->ttyName.data();
|
||||
if (!memcmp(str_ptr, "/dev/", 5)) {
|
||||
str_ptr += 5;
|
||||
}
|
||||
# ifdef __GLIBC__
|
||||
else {
|
||||
const char * sl_ptr = strrchr(str_ptr, '/');
|
||||
if (sl_ptr) {
|
||||
str_ptr = sl_ptr + 1;
|
||||
const char * str_ptr = d->ttyName.data();
|
||||
if (!memcmp(str_ptr, "/dev/", 5)) {
|
||||
str_ptr += 5;
|
||||
}
|
||||
# ifdef __GLIBC__
|
||||
else {
|
||||
const char * sl_ptr = strrchr(str_ptr, '/');
|
||||
if (sl_ptr) {
|
||||
str_ptr = sl_ptr + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
# ifdef HAVE_LOGIN
|
||||
# ifdef HAVE_LOGINX
|
||||
::logoutx(str_ptr, 0, DEAD_PROCESS);
|
||||
::logoutx(str_ptr, 0, DEAD_PROCESS);
|
||||
# else
|
||||
::logout(str_ptr);
|
||||
::logout(str_ptr);
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAVE_UTMPX
|
||||
struct utmpx l_struct, *ut;
|
||||
struct utmpx l_struct, *ut;
|
||||
# else
|
||||
struct utmp l_struct, *ut;
|
||||
struct utmp l_struct, *ut;
|
||||
# endif
|
||||
memset(&l_struct, 0, sizeof(l_struct));
|
||||
memset(&l_struct, 0, sizeof(l_struct));
|
||||
|
||||
strncpy(l_struct.ut_line, str_ptr, sizeof(l_struct.ut_line));
|
||||
strncpy(l_struct.ut_line, str_ptr, sizeof(l_struct.ut_line));
|
||||
|
||||
# ifdef HAVE_UTMPX
|
||||
utmpxname(_PATH_UTMPX);
|
||||
setutxent();
|
||||
if ((ut = getutxline(&l_struct))) {
|
||||
utmpxname(_PATH_UTMPX);
|
||||
setutxent();
|
||||
if ((ut = getutxline(&l_struct))) {
|
||||
# else
|
||||
utmpname(_PATH_UTMP);
|
||||
setutent();
|
||||
if ((ut = getutline(&l_struct))) {
|
||||
utmpname(_PATH_UTMP);
|
||||
setutent();
|
||||
if ((ut = getutline(&l_struct))) {
|
||||
# endif
|
||||
memset(ut->ut_name, 0, sizeof(*ut->ut_name));
|
||||
memset(ut->ut_host, 0, sizeof(*ut->ut_host));
|
||||
memset(ut->ut_name, 0, sizeof(*ut->ut_name));
|
||||
memset(ut->ut_host, 0, sizeof(*ut->ut_host));
|
||||
# ifdef HAVE_STRUCT_UTMP_UT_SYSLEN
|
||||
ut->ut_syslen = 0;
|
||||
ut->ut_syslen = 0;
|
||||
# endif
|
||||
# ifdef HAVE_STRUCT_UTMP_UT_TYPE
|
||||
ut->ut_type = DEAD_PROCESS;
|
||||
ut->ut_type = DEAD_PROCESS;
|
||||
# endif
|
||||
# ifdef HAVE_UTMPX
|
||||
gettimeofday(ut->ut_tv, 0);
|
||||
pututxline(ut);
|
||||
}
|
||||
endutxent();
|
||||
gettimeofday(ut->ut_tv, 0);
|
||||
pututxline(ut);
|
||||
}
|
||||
endutxent();
|
||||
# else
|
||||
ut->ut_time = time(0);
|
||||
pututline(ut);
|
||||
ut->ut_time = time(0);
|
||||
pututline(ut);
|
||||
}
|
||||
endutent();
|
||||
# endif
|
||||
@@ -554,55 +565,62 @@ endutent();
|
||||
// XXX Supposedly, tc[gs]etattr do not work with the master on Solaris.
|
||||
// Please verify.
|
||||
|
||||
bool KPty::tcGetAttr(struct ::termios * ttmode) const {
|
||||
Q_D(const KPty);
|
||||
bool KPty::tcGetAttr(struct ::termios * ttmode) const
|
||||
{
|
||||
Q_D(const KPty);
|
||||
|
||||
return _tcgetattr(d->masterFd, ttmode) == 0;
|
||||
return _tcgetattr(d->masterFd, ttmode) == 0;
|
||||
}
|
||||
|
||||
bool KPty::tcSetAttr(struct ::termios * ttmode) {
|
||||
Q_D(KPty);
|
||||
bool KPty::tcSetAttr(struct ::termios * ttmode)
|
||||
{
|
||||
Q_D(KPty);
|
||||
|
||||
return _tcsetattr(d->masterFd, ttmode) == 0;
|
||||
return _tcsetattr(d->masterFd, ttmode) == 0;
|
||||
}
|
||||
|
||||
bool KPty::setWinSize(int lines, int columns) {
|
||||
Q_D(KPty);
|
||||
bool KPty::setWinSize(int lines, int columns)
|
||||
{
|
||||
Q_D(KPty);
|
||||
|
||||
struct winsize winSize;
|
||||
memset(&winSize, 0, sizeof(winSize));
|
||||
winSize.ws_row = (unsigned short)lines;
|
||||
winSize.ws_col = (unsigned short)columns;
|
||||
return ioctl(d->masterFd, TIOCSWINSZ, (char *)&winSize) == 0;
|
||||
struct winsize winSize;
|
||||
memset(&winSize, 0, sizeof(winSize));
|
||||
winSize.ws_row = (unsigned short)lines;
|
||||
winSize.ws_col = (unsigned short)columns;
|
||||
return ioctl(d->masterFd, TIOCSWINSZ, (char *)&winSize) == 0;
|
||||
}
|
||||
|
||||
bool KPty::setEcho(bool echo) {
|
||||
struct ::termios ttmode;
|
||||
if (!tcGetAttr(&ttmode)) {
|
||||
return false;
|
||||
}
|
||||
if (!echo) {
|
||||
ttmode.c_lflag &= ~ECHO;
|
||||
} else {
|
||||
ttmode.c_lflag |= ECHO;
|
||||
}
|
||||
return tcSetAttr(&ttmode);
|
||||
bool KPty::setEcho(bool echo)
|
||||
{
|
||||
struct ::termios ttmode;
|
||||
if (!tcGetAttr(&ttmode)) {
|
||||
return false;
|
||||
}
|
||||
if (!echo) {
|
||||
ttmode.c_lflag &= ~ECHO;
|
||||
} else {
|
||||
ttmode.c_lflag |= ECHO;
|
||||
}
|
||||
return tcSetAttr(&ttmode);
|
||||
}
|
||||
|
||||
const char * KPty::ttyName() const {
|
||||
Q_D(const KPty);
|
||||
const char * KPty::ttyName() const
|
||||
{
|
||||
Q_D(const KPty);
|
||||
|
||||
return d->ttyName.data();
|
||||
return d->ttyName.data();
|
||||
}
|
||||
|
||||
int KPty::masterFd() const {
|
||||
Q_D(const KPty);
|
||||
int KPty::masterFd() const
|
||||
{
|
||||
Q_D(const KPty);
|
||||
|
||||
return d->masterFd;
|
||||
return d->masterFd;
|
||||
}
|
||||
|
||||
int KPty::slaveFd() const {
|
||||
Q_D(const KPty);
|
||||
int KPty::slaveFd() const
|
||||
{
|
||||
Q_D(const KPty);
|
||||
|
||||
return d->slaveFd;
|
||||
return d->slaveFd;
|
||||
}
|
||||
|
||||
+131
-130
@@ -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 {
|
||||
Q_DECLARE_PRIVATE(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
|
||||
|
||||
+7
-7
@@ -28,17 +28,17 @@
|
||||
#include <QtCore/QByteArray>
|
||||
|
||||
struct KPtyPrivate {
|
||||
Q_DECLARE_PUBLIC(KPty)
|
||||
Q_DECLARE_PUBLIC(KPty)
|
||||
|
||||
KPtyPrivate();
|
||||
bool chownpty(bool grant);
|
||||
KPtyPrivate();
|
||||
bool chownpty(bool grant);
|
||||
|
||||
int masterFd;
|
||||
int slaveFd;
|
||||
int masterFd;
|
||||
int slaveFd;
|
||||
|
||||
QByteArray ttyName;
|
||||
QByteArray ttyName;
|
||||
|
||||
KPty * q_ptr;
|
||||
KPty * q_ptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+199
-169
@@ -24,252 +24,282 @@
|
||||
|
||||
using namespace Konsole;
|
||||
|
||||
void * createTermWidget(int startnow, void * parent) {
|
||||
return (void *) new QTermWidget(startnow, (QWidget *)parent);
|
||||
void * createTermWidget(int startnow, void * parent)
|
||||
{
|
||||
return (void *) new QTermWidget(startnow, (QWidget *)parent);
|
||||
}
|
||||
|
||||
struct TermWidgetImpl {
|
||||
TermWidgetImpl(QWidget * parent = 0);
|
||||
TermWidgetImpl(QWidget * parent = 0);
|
||||
|
||||
TerminalDisplay * m_terminalDisplay;
|
||||
Session * m_session;
|
||||
TerminalDisplay * m_terminalDisplay;
|
||||
Session * m_session;
|
||||
|
||||
Session * createSession();
|
||||
TerminalDisplay * createTerminalDisplay(Session * session, QWidget * parent);
|
||||
Session * createSession();
|
||||
TerminalDisplay * createTerminalDisplay(Session * session, QWidget * parent);
|
||||
};
|
||||
|
||||
TermWidgetImpl::TermWidgetImpl(QWidget * parent) {
|
||||
this->m_session = createSession();
|
||||
this->m_terminalDisplay = createTerminalDisplay(this->m_session, parent);
|
||||
TermWidgetImpl::TermWidgetImpl(QWidget * parent)
|
||||
{
|
||||
this->m_session = createSession();
|
||||
this->m_terminalDisplay = createTerminalDisplay(this->m_session, parent);
|
||||
}
|
||||
|
||||
|
||||
Session * TermWidgetImpl::createSession() {
|
||||
Session * session = new Session();
|
||||
QStringList env("");
|
||||
env.push_front("TERM=xterm");
|
||||
session->setEnvironment(env);
|
||||
session->setTitle(Session::NameRole, "QTermWidget");
|
||||
session->setProgram("/bin/bash");
|
||||
QStringList args("");
|
||||
session->setArguments(args);
|
||||
session->setAutoClose(true);
|
||||
Session * TermWidgetImpl::createSession()
|
||||
{
|
||||
Session * session = new Session();
|
||||
QStringList env("");
|
||||
env.push_front("TERM=xterm");
|
||||
session->setEnvironment(env);
|
||||
session->setTitle(Session::NameRole, "QTermWidget");
|
||||
session->setProgram("/bin/bash");
|
||||
QStringList args("");
|
||||
session->setArguments(args);
|
||||
session->setAutoClose(true);
|
||||
|
||||
session->setCodec(QTextCodec::codecForName("UTF-8"));
|
||||
session->setCodec(QTextCodec::codecForName("UTF-8"));
|
||||
|
||||
session->setFlowControlEnabled(true);
|
||||
session->setHistoryType(HistoryTypeBuffer(1000));
|
||||
session->setFlowControlEnabled(true);
|
||||
session->setHistoryType(HistoryTypeBuffer(1000));
|
||||
|
||||
session->setDarkBackground(true);
|
||||
session->setDarkBackground(true);
|
||||
|
||||
session->setKeyBindings("");
|
||||
return session;
|
||||
session->setKeyBindings("");
|
||||
return session;
|
||||
}
|
||||
|
||||
TerminalDisplay * TermWidgetImpl::createTerminalDisplay(Session * session, QWidget * parent) {
|
||||
TerminalDisplay * TermWidgetImpl::createTerminalDisplay(Session * session, QWidget * parent)
|
||||
{
|
||||
// TerminalDisplay* display = new TerminalDisplay(this);
|
||||
TerminalDisplay * display = new TerminalDisplay(parent);
|
||||
TerminalDisplay * display = new TerminalDisplay(parent);
|
||||
|
||||
display->setBellMode(TerminalDisplay::NotifyBell);
|
||||
display->setTerminalSizeHint(true);
|
||||
display->setTripleClickMode(TerminalDisplay::SelectWholeLine);
|
||||
display->setTerminalSizeStartup(true);
|
||||
display->setBellMode(TerminalDisplay::NotifyBell);
|
||||
display->setTerminalSizeHint(true);
|
||||
display->setTripleClickMode(TerminalDisplay::SelectWholeLine);
|
||||
display->setTerminalSizeStartup(true);
|
||||
|
||||
display->setRandomSeed(session->sessionId() * 31);
|
||||
display->setRandomSeed(session->sessionId() * 31);
|
||||
|
||||
return display;
|
||||
return display;
|
||||
}
|
||||
|
||||
|
||||
QTermWidget::QTermWidget(int startnow, QWidget * parent)
|
||||
:QWidget(parent) {
|
||||
m_impl = new TermWidgetImpl(this);
|
||||
:QWidget(parent)
|
||||
{
|
||||
m_impl = new TermWidgetImpl(this);
|
||||
|
||||
init();
|
||||
init();
|
||||
|
||||
if (startnow && m_impl->m_session) {
|
||||
m_impl->m_session->run();
|
||||
}
|
||||
|
||||
this->setFocus( Qt::OtherFocusReason );
|
||||
m_impl->m_terminalDisplay->resize(this->size());
|
||||
|
||||
this->setFocusProxy(m_impl->m_terminalDisplay);
|
||||
connect(m_impl->m_terminalDisplay, SIGNAL(copyAvailable(bool)),this, SLOT(selectionChanged(bool)));
|
||||
}
|
||||
|
||||
void QTermWidget::selectionChanged(bool textSelected)
|
||||
{
|
||||
emit copyAvailable(textSelected);
|
||||
}
|
||||
|
||||
int QTermWidget::getShellPID()
|
||||
{
|
||||
return m_impl->m_session->processId();
|
||||
}
|
||||
|
||||
void QTermWidget::changeDir(const QString & dir)
|
||||
{
|
||||
/*
|
||||
this is a very hackish way of trying to determine if the shell is in
|
||||
the foreground before attempting to change the directory. It may not
|
||||
be portable to anything other than Linux.
|
||||
*/
|
||||
QString strCmd;
|
||||
strCmd.setNum(getShellPID());
|
||||
strCmd.prepend("ps -j ");
|
||||
strCmd.append(" | tail -1 | awk '{ print $5 }' | grep -q \\+");
|
||||
int retval = system(strCmd.toStdString().c_str());
|
||||
|
||||
if (!retval) {
|
||||
QString cmd = "cd " + dir + "\n";
|
||||
sendText(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
QSize QTermWidget::sizeHint() const
|
||||
{
|
||||
QSize size = m_impl->m_terminalDisplay->sizeHint();
|
||||
size.rheight() = 150;
|
||||
return size;
|
||||
}
|
||||
|
||||
void QTermWidget::startShellProgram()
|
||||
{
|
||||
if ( m_impl->m_session->isRunning() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (startnow && m_impl->m_session) {
|
||||
m_impl->m_session->run();
|
||||
}
|
||||
|
||||
this->setFocus( Qt::OtherFocusReason );
|
||||
m_impl->m_terminalDisplay->resize(this->size());
|
||||
|
||||
this->setFocusProxy(m_impl->m_terminalDisplay);
|
||||
connect(m_impl->m_terminalDisplay, SIGNAL(copyAvailable(bool)),this, SLOT(selectionChanged(bool)));
|
||||
}
|
||||
|
||||
void QTermWidget::selectionChanged(bool textSelected) {
|
||||
emit copyAvailable(textSelected);
|
||||
}
|
||||
void QTermWidget::init()
|
||||
{
|
||||
m_impl->m_terminalDisplay->setSize(80, 40);
|
||||
|
||||
int QTermWidget::getShellPID() {
|
||||
return m_impl->m_session->processId();
|
||||
}
|
||||
QFont font = QApplication::font();
|
||||
font.setFamily("Monospace");
|
||||
font.setPointSize(10);
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
setTerminalFont(font);
|
||||
setScrollBarPosition(NoScrollBar);
|
||||
|
||||
void QTermWidget::changeDir(const QString & dir) {
|
||||
/*
|
||||
this is a very hackish way of trying to determine if the shell is in
|
||||
the foreground before attempting to change the directory. It may not
|
||||
be portable to anything other than Linux.
|
||||
*/
|
||||
QString strCmd;
|
||||
strCmd.setNum(getShellPID());
|
||||
strCmd.prepend("ps -j ");
|
||||
strCmd.append(" | tail -1 | awk '{ print $5 }' | grep -q \\+");
|
||||
int retval = system(strCmd.toStdString().c_str());
|
||||
m_impl->m_session->addView(m_impl->m_terminalDisplay);
|
||||
|
||||
if (!retval) {
|
||||
QString cmd = "cd " + dir + "\n";
|
||||
sendText(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
QSize QTermWidget::sizeHint() const {
|
||||
QSize size = m_impl->m_terminalDisplay->sizeHint();
|
||||
size.rheight() = 150;
|
||||
return size;
|
||||
}
|
||||
|
||||
void QTermWidget::startShellProgram() {
|
||||
if ( m_impl->m_session->isRunning() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_impl->m_session->run();
|
||||
}
|
||||
|
||||
void QTermWidget::init() {
|
||||
m_impl->m_terminalDisplay->setSize(80, 40);
|
||||
|
||||
QFont font = QApplication::font();
|
||||
font.setFamily("Monospace");
|
||||
font.setPointSize(10);
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
setTerminalFont(font);
|
||||
setScrollBarPosition(NoScrollBar);
|
||||
|
||||
m_impl->m_session->addView(m_impl->m_terminalDisplay);
|
||||
|
||||
connect(m_impl->m_session, SIGNAL(finished()), this, SLOT(sessionFinished()));
|
||||
connect(m_impl->m_session, SIGNAL(finished()), this, SLOT(sessionFinished()));
|
||||
}
|
||||
|
||||
|
||||
QTermWidget::~QTermWidget() {
|
||||
emit destroyed();
|
||||
QTermWidget::~QTermWidget()
|
||||
{
|
||||
emit destroyed();
|
||||
}
|
||||
|
||||
|
||||
void QTermWidget::setTerminalFont(QFont & font) {
|
||||
if (!m_impl->m_terminalDisplay) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_terminalDisplay->setVTFont(font);
|
||||
void QTermWidget::setTerminalFont(QFont & font)
|
||||
{
|
||||
if (!m_impl->m_terminalDisplay) {
|
||||
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);
|
||||
void QTermWidget::setShellProgram(const QString & progname)
|
||||
{
|
||||
if (!m_impl->m_session) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_session->setProgram(progname);
|
||||
}
|
||||
|
||||
void QTermWidget::setWorkingDirectory(const QString & dir) {
|
||||
if (!m_impl->m_session) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_session->setInitialWorkingDirectory(dir);
|
||||
void QTermWidget::setWorkingDirectory(const QString & dir)
|
||||
{
|
||||
if (!m_impl->m_session) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_session->setInitialWorkingDirectory(dir);
|
||||
}
|
||||
|
||||
void QTermWidget::setArgs(QStringList & args) {
|
||||
if (!m_impl->m_session) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_session->setArguments(args);
|
||||
void QTermWidget::setArgs(QStringList & args)
|
||||
{
|
||||
if (!m_impl->m_session) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_session->setArguments(args);
|
||||
}
|
||||
|
||||
void QTermWidget::setTextCodec(QTextCodec * codec) {
|
||||
if (!m_impl->m_session) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_session->setCodec(codec);
|
||||
void QTermWidget::setTextCodec(QTextCodec * codec)
|
||||
{
|
||||
if (!m_impl->m_session) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_session->setCodec(codec);
|
||||
}
|
||||
|
||||
void QTermWidget::setColorScheme(int scheme) {
|
||||
switch(scheme) {
|
||||
void QTermWidget::setColorScheme(int scheme)
|
||||
{
|
||||
switch (scheme) {
|
||||
case COLOR_SCHEME_WHITE_ON_BLACK:
|
||||
m_impl->m_terminalDisplay->setColorTable(whiteonblack_color_table);
|
||||
break;
|
||||
m_impl->m_terminalDisplay->setColorTable(whiteonblack_color_table);
|
||||
break;
|
||||
case COLOR_SCHEME_GREEN_ON_BLACK:
|
||||
m_impl->m_terminalDisplay->setColorTable(greenonblack_color_table);
|
||||
break;
|
||||
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;
|
||||
m_impl->m_terminalDisplay->setColorTable(blackonlightyellow_color_table);
|
||||
break;
|
||||
default: //do nothing
|
||||
break;
|
||||
};
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void QTermWidget::setSize(int h, int v) {
|
||||
if (!m_impl->m_terminalDisplay) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_terminalDisplay->setSize(h, v);
|
||||
void QTermWidget::setSize(int h, int v)
|
||||
{
|
||||
if (!m_impl->m_terminalDisplay) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_terminalDisplay->setSize(h, v);
|
||||
}
|
||||
|
||||
void QTermWidget::setHistorySize(int lines) {
|
||||
if (lines < 0) {
|
||||
m_impl->m_session->setHistoryType(HistoryTypeFile());
|
||||
} else {
|
||||
m_impl->m_session->setHistoryType(HistoryTypeBuffer(lines));
|
||||
}
|
||||
void QTermWidget::setHistorySize(int lines)
|
||||
{
|
||||
if (lines < 0) {
|
||||
m_impl->m_session->setHistoryType(HistoryTypeFile());
|
||||
} else {
|
||||
m_impl->m_session->setHistoryType(HistoryTypeBuffer(lines));
|
||||
}
|
||||
}
|
||||
|
||||
void QTermWidget::setScrollBarPosition(ScrollBarPosition pos) {
|
||||
if (!m_impl->m_terminalDisplay) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_terminalDisplay->setScrollBarPosition((TerminalDisplay::ScrollBarPosition)pos);
|
||||
void QTermWidget::setScrollBarPosition(ScrollBarPosition pos)
|
||||
{
|
||||
if (!m_impl->m_terminalDisplay) {
|
||||
return;
|
||||
}
|
||||
m_impl->m_terminalDisplay->setScrollBarPosition((TerminalDisplay::ScrollBarPosition)pos);
|
||||
}
|
||||
|
||||
void QTermWidget::sendText(QString & text) {
|
||||
m_impl->m_session->sendText(text);
|
||||
void QTermWidget::sendText(QString & text)
|
||||
{
|
||||
m_impl->m_session->sendText(text);
|
||||
}
|
||||
|
||||
void QTermWidget::resizeEvent(QResizeEvent *) {
|
||||
void QTermWidget::resizeEvent(QResizeEvent *)
|
||||
{
|
||||
//qDebug("global window resizing...with %d %d", this->size().width(), this->size().height());
|
||||
m_impl->m_terminalDisplay->resize(this->size());
|
||||
m_impl->m_terminalDisplay->resize(this->size());
|
||||
}
|
||||
|
||||
|
||||
void QTermWidget::sessionFinished() {
|
||||
emit finished();
|
||||
void QTermWidget::sessionFinished()
|
||||
{
|
||||
emit finished();
|
||||
}
|
||||
|
||||
|
||||
void QTermWidget::copyClipboard() {
|
||||
m_impl->m_terminalDisplay->copyClipboard();
|
||||
void QTermWidget::copyClipboard()
|
||||
{
|
||||
m_impl->m_terminalDisplay->copyClipboard();
|
||||
}
|
||||
|
||||
void QTermWidget::pasteClipboard() {
|
||||
m_impl->m_terminalDisplay->pasteClipboard();
|
||||
void QTermWidget::pasteClipboard()
|
||||
{
|
||||
m_impl->m_terminalDisplay->pasteClipboard();
|
||||
}
|
||||
|
||||
void QTermWidget::setFlowControlEnabled(bool enabled) {
|
||||
m_impl->m_session->setFlowControlEnabled(enabled);
|
||||
void QTermWidget::setFlowControlEnabled(bool enabled)
|
||||
{
|
||||
m_impl->m_session->setFlowControlEnabled(enabled);
|
||||
}
|
||||
|
||||
bool QTermWidget::flowControlEnabled(void) {
|
||||
return m_impl->m_session->flowControlEnabled();
|
||||
bool QTermWidget::flowControlEnabled(void)
|
||||
{
|
||||
return m_impl->m_session->flowControlEnabled();
|
||||
}
|
||||
|
||||
void QTermWidget::setFlowControlWarningEnabled(bool enabled) {
|
||||
if(flowControlEnabled()) {
|
||||
// Do not show warning label if flow control is disabled
|
||||
m_impl->m_terminalDisplay->setFlowControlWarningEnabled(enabled);
|
||||
}
|
||||
void QTermWidget::setFlowControlWarningEnabled(bool enabled)
|
||||
{
|
||||
if (flowControlEnabled()) {
|
||||
// Do not show warning label if flow control is disabled
|
||||
m_impl->m_terminalDisplay->setFlowControlWarningEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void QTermWidget::setEnvironment(const QStringList & environment) {
|
||||
m_impl->m_session->setEnvironment(environment);
|
||||
void QTermWidget::setEnvironment(const QStringList & environment)
|
||||
{
|
||||
m_impl->m_session->setEnvironment(environment);
|
||||
}
|
||||
|
||||
+67
-66
@@ -29,106 +29,107 @@ enum COLOR_SCHEME { COLOR_SCHEME_WHITE_ON_BLACK = 1,
|
||||
COLOR_SCHEME_BLACK_ON_LIGHT_YELLOW
|
||||
};
|
||||
|
||||
class QTermWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
class QTermWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum ScrollBarPosition {
|
||||
/** Do not show the scroll bar. */
|
||||
NoScrollBar=0,
|
||||
/** Show the scroll bar on the left side of the display. */
|
||||
ScrollBarLeft=1,
|
||||
/** Show the scroll bar on the right side of the display. */
|
||||
ScrollBarRight=2
|
||||
};
|
||||
enum ScrollBarPosition {
|
||||
/** Do not show the scroll bar. */
|
||||
NoScrollBar=0,
|
||||
/** Show the scroll bar on the left side of the display. */
|
||||
ScrollBarLeft=1,
|
||||
/** Show the scroll bar on the right side of the display. */
|
||||
ScrollBarRight=2
|
||||
};
|
||||
|
||||
|
||||
//Creation of widget
|
||||
QTermWidget(int startnow = 1, //start shell programm immediatelly
|
||||
QWidget * parent = 0);
|
||||
~QTermWidget();
|
||||
//Creation of widget
|
||||
QTermWidget(int startnow = 1, //start shell programm immediatelly
|
||||
QWidget * parent = 0);
|
||||
~QTermWidget();
|
||||
|
||||
//Initial size
|
||||
QSize sizeHint() const;
|
||||
//Initial size
|
||||
QSize sizeHint() const;
|
||||
|
||||
//start shell program if it was not started in constructor
|
||||
void startShellProgram();
|
||||
//start shell program if it was not started in constructor
|
||||
void startShellProgram();
|
||||
|
||||
int getShellPID();
|
||||
int getShellPID();
|
||||
|
||||
void changeDir(const QString & dir);
|
||||
void changeDir(const QString & dir);
|
||||
|
||||
//look-n-feel, if you don`t like defaults
|
||||
//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);
|
||||
// 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);
|
||||
|
||||
//environment
|
||||
void setEnvironment(const QStringList & environment);
|
||||
//environment
|
||||
void setEnvironment(const QStringList & environment);
|
||||
|
||||
// Shell program, default is /bin/bash
|
||||
void setShellProgram(const QString & progname);
|
||||
// Shell program, default is /bin/bash
|
||||
void setShellProgram(const QString & progname);
|
||||
|
||||
//working directory
|
||||
void setWorkingDirectory(const QString & dir);
|
||||
//working directory
|
||||
void setWorkingDirectory(const QString & dir);
|
||||
|
||||
// Shell program args, default is none
|
||||
void setArgs(QStringList & args);
|
||||
// Shell program args, default is none
|
||||
void setArgs(QStringList & args);
|
||||
|
||||
//Text codec, default is UTF-8
|
||||
void setTextCodec(QTextCodec * codec);
|
||||
//Text codec, default is UTF-8
|
||||
void setTextCodec(QTextCodec * codec);
|
||||
|
||||
//Color scheme, default is white on black
|
||||
void setColorScheme(int scheme);
|
||||
//Color scheme, default is white on black
|
||||
void setColorScheme(int scheme);
|
||||
|
||||
//set size
|
||||
void setSize(int h, int v);
|
||||
//set size
|
||||
void setSize(int h, int v);
|
||||
|
||||
// History size for scrolling
|
||||
void setHistorySize(int lines); //infinite if lines < 0
|
||||
// History size for scrolling
|
||||
void setHistorySize(int lines); //infinite if lines < 0
|
||||
|
||||
// Presence of scrollbar
|
||||
void setScrollBarPosition(ScrollBarPosition);
|
||||
// Presence of scrollbar
|
||||
void setScrollBarPosition(ScrollBarPosition);
|
||||
|
||||
// Send some text to terminal
|
||||
void sendText(QString & text);
|
||||
// Send some text to terminal
|
||||
void sendText(QString & text);
|
||||
|
||||
// Sets whether flow control is enabled
|
||||
void setFlowControlEnabled(bool enabled);
|
||||
// Sets whether flow control is enabled
|
||||
void setFlowControlEnabled(bool enabled);
|
||||
|
||||
// Returns whether flow control is enabled
|
||||
bool flowControlEnabled(void);
|
||||
// Returns whether flow control is enabled
|
||||
bool flowControlEnabled(void);
|
||||
|
||||
/**
|
||||
* Sets whether the flow control warning box should be shown
|
||||
* when the flow control stop key (Ctrl+S) is pressed.
|
||||
*/
|
||||
void setFlowControlWarningEnabled(bool enabled);
|
||||
/**
|
||||
* Sets whether the flow control warning box should be shown
|
||||
* when the flow control stop key (Ctrl+S) is pressed.
|
||||
*/
|
||||
void setFlowControlWarningEnabled(bool enabled);
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
void copyAvailable(bool);
|
||||
void finished();
|
||||
void copyAvailable(bool);
|
||||
|
||||
public slots:
|
||||
// Paste clipboard content to terminal
|
||||
void copyClipboard();
|
||||
// Paste clipboard content to terminal
|
||||
void copyClipboard();
|
||||
|
||||
// Copies selection to clipboard
|
||||
void pasteClipboard();
|
||||
// Copies selection to clipboard
|
||||
void pasteClipboard();
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *);
|
||||
virtual void resizeEvent(QResizeEvent *);
|
||||
|
||||
protected slots:
|
||||
void sessionFinished();
|
||||
void selectionChanged(bool textSelected);
|
||||
void sessionFinished();
|
||||
void selectionChanged(bool textSelected);
|
||||
|
||||
private:
|
||||
void init();
|
||||
TermWidgetImpl * m_impl;
|
||||
void init();
|
||||
TermWidgetImpl * m_impl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user