diff options
author | Ken Moore <moorekou@gmail.com> | 2016-03-12 23:13:14 -0500 |
---|---|---|
committer | Ken Moore <moorekou@gmail.com> | 2016-03-12 23:13:14 -0500 |
commit | a8a5a405ecc1b4c73e82502f0c6d426a4cc298a5 (patch) | |
tree | 7d4d656c8c19529e071ce08fc7d0a7500865c08f | |
parent | Merge pull request #204 from rezso/master (diff) | |
download | lumina-a8a5a405ecc1b4c73e82502f0c6d426a4cc298a5.tar.gz lumina-a8a5a405ecc1b4c73e82502f0c6d426a4cc298a5.tar.bz2 lumina-a8a5a405ecc1b4c73e82502f0c6d426a4cc298a5.zip |
Add some more work on moving ANSI cursor control codes over to the widget.
4 files changed, 93 insertions, 14 deletions
diff --git a/desktop-utilities/lumina-terminal/TerminalWidget.cpp b/desktop-utilities/lumina-terminal/TerminalWidget.cpp index 1756d0b1..c08c9d81 100644 --- a/desktop-utilities/lumina-terminal/TerminalWidget.cpp +++ b/desktop-utilities/lumina-terminal/TerminalWidget.cpp @@ -40,21 +40,90 @@ void TerminalWidget::aboutToClose(){ } // ================== +// PRIVATE +// ================== +void TerminalWidget::applyData(QByteArray data){ + //Quick global replacement (this widget reads both as newlines) + data = data.replace("\r\n","\n"); + //Iterate through the data and apply it when possible + for(int i=0; i<data.size(); i++){ + if( data.at(i)=='\b' ){ + //Simple Backspace + this->textCursor().deletePreviousChar(); + + }else if( data.at(i)=='\x1B' ){ + //ANSI Control Code start + //Look for the end of the code + int end = -1; + for(int j=1; j<(data.size()-i) && end<0; j++){ + if(QChar(data.at(i+j)).isLetter()){ end = j; } + } + if(end<0){ return; } //skip everything else - no end to code found + applyANSI(data.mid(i, end)); + i+=end; //move the final loop along - already handled these bytes + + }else{ + //Plaintext character - just add it here + this->insertPlainText( QChar(data.at(i)) ); + } + + } //end loop over data +} + +void TerminalWidget::applyANSI(QByteArray code){ + //Note: the first byte is often the "[" character + //CURSOR MOVEMENT + if( code.endsWith("A") ){ //Move Up + int num = 1; + if(code.size()>2){ num = code.mid(1, code.size()-2).toInt(); } //everything in the middle + this->textCursor().movePosition(QTextCursor::Up, QTextCursor::MoveAnchor, num); + }else if(code.endsWith("B")){ //Move Down + int num = 1; + if(code.size()>2){ num = code.mid(1, code.size()-2).toInt(); } //everything in the middle + this->textCursor().movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, num); + }else if(code.endsWith("C")){ //Move Forward + int num = 1; + if(code.size()>2){ num = code.mid(1, code.size()-2).toInt(); } //everything in the middle + this->textCursor().movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, num); + }else if(code.endsWith("D")){ //Move Back + int num = 1; + if(code.size()>2){ num = code.mid(1, code.size()-2).toInt(); } //everything in the middle + this->textCursor().movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, num); + }else if(code.endsWith("E")){ //Move Next/down Lines (go to beginning) + int num = 1; + if(code.size()>2){ num = code.mid(1, code.size()-2).toInt(); } //everything in the middle + this->textCursor().movePosition(QTextCursor::NextRow, QTextCursor::MoveAnchor, num); + }else if(code.endsWith("F")){ //Move Previous/up Lines (go to beginning) + int num = 1; + if(code.size()>2){ num = code.mid(1, code.size()-2).toInt(); } //everything in the middle + this->textCursor().movePosition(QTextCursor::PreviousRow, QTextCursor::MoveAnchor, num); + }else if(code.endsWith("G")){ //Move to specific column + int num = 1; + if(code.size()>2){ num = code.mid(1, code.size()-2).toInt(); } //everything in the middle + this->textCursor().setPosition(num); + }else if(code.endsWith("H")){ //Move to specific position (row/column) + int mid = code.indexOf(";"); + if(mid>0){ + int numR, numC; numR = numC = 1; + if(mid >=3){ numR = code.mid(1,mid-1).toInt(); } + if(mid < code.size()-1){ numC = code.mid(mid+1,code.size()-mid-1).toInt(); } + //this->textCursor().setPosition( + qDebug() << "Set Text Position (absolute):" << "Row:" << numR << "Col:" << numC; + // TO-DO + } + }else if(code.endsWith("J")){ //ED - Erase Display + + } +} + +// ================== // PRIVATE SLOTS // ================== void TerminalWidget::UpdateText(){ //read the data from the process //qDebug() << "UpdateText"; if(!PROC->isOpen()){ return; } - QByteArray buffer = PROC->readTTY(); - QString text = QString(buffer); - text.replace("\r\n","\n"); - //Special Cursor handling - while(text.startsWith("\b")){ - this->textCursor().deletePreviousChar(); - text = text.remove(0,1); - } - this->insertPlainText(text); + applyData(PROC->readTTY()); //adjust the scrollbar as needed this->verticalScrollBar()->setValue(this->verticalScrollBar()->maximum()); } diff --git a/desktop-utilities/lumina-terminal/TerminalWidget.h b/desktop-utilities/lumina-terminal/TerminalWidget.h index 49b255ff..18f0054f 100644 --- a/desktop-utilities/lumina-terminal/TerminalWidget.h +++ b/desktop-utilities/lumina-terminal/TerminalWidget.h @@ -25,9 +25,11 @@ public: private: TTYProcess *PROC; - //QProcess *PROC; QSocketNotifier *sn; + + void applyData(QByteArray data); //overall data parsing + void applyANSI(QByteArray code); //individual code application private slots: void UpdateText(); diff --git a/desktop-utilities/lumina-terminal/TtyProcess.cpp b/desktop-utilities/lumina-terminal/TtyProcess.cpp index 15094f64..8121b365 100644 --- a/desktop-utilities/lumina-terminal/TtyProcess.cpp +++ b/desktop-utilities/lumina-terminal/TtyProcess.cpp @@ -75,7 +75,10 @@ void TTYProcess::writeQtKey(int key){ ba.append("\x1b[D\x1b[K"); break; case Qt::Key_Left: + ba.append("\x1b[D"); + break; case Qt::Key_Right: + ba.append("\x1b[C"); break; case Qt::Key_Up: ba.append("\x1b[A"); @@ -150,7 +153,7 @@ QByteArray TTYProcess::CleanANSI(QByteArray raw, bool &incomplete){ index = raw.indexOf("\x1B]"); } - // GENERIC ANSI CODES + // GENERIC ANSI CODES ((Make sure the output is not cut off in the middle of a code) index = raw.indexOf("\x1B["); while(index>=0){ //CURSOR MOVEMENT @@ -162,10 +165,8 @@ QByteArray TTYProcess::CleanANSI(QByteArray raw, bool &incomplete){ end = i; //found the end of the control code } } - raw = raw.remove(index, 1+end); //control character +1 byte - index = raw.indexOf("\x1B["); + index = raw.indexOf("\x1B[",index+1); //now find the next one } - //qDebug() << " - Removed Color Codes:" << raw; // SYSTEM BELL index = raw.indexOf("\x07"); diff --git a/desktop-utilities/lumina-terminal/TtyProcess.h b/desktop-utilities/lumina-terminal/TtyProcess.h index 04f294a2..b1703fb7 100644 --- a/desktop-utilities/lumina-terminal/TtyProcess.h +++ b/desktop-utilities/lumina-terminal/TtyProcess.h @@ -9,6 +9,13 @@ // to be used for terminal-like apps (shells) which directly modify the terminal output // rather than stick to input/output channels for communication. //=========================================== +// IMPLEMENTATION NOTE +//====================== +// The process requires/uses ANSI control codes (\x1B[<something>) for special operations +// such as moving the cursor, erasing characters, etc.. +// It is recommended that you pair this class with the graphical "TerminalWidget.h" class +// or some other ANSI-compatible display widget. +//=========================================== #ifndef _LUMINA_DESKTOP_UTILITIES_TERMINAL_TTY_PROCESS_WIDGET_H #define _LUMINA_DESKTOP_UTILITIES_TERMINAL_TTY_PROCESS_WIDGET_H |