diff options
author | Ken Moore <moorekou@gmail.com> | 2016-04-11 16:28:13 -0400 |
---|---|---|
committer | Ken Moore <moorekou@gmail.com> | 2016-04-11 16:28:13 -0400 |
commit | e36db04274e700c154e26e7c459c36329afb2c42 (patch) | |
tree | fc8eff3481acd4f7bd0ffabf16fd0231e767af57 | |
parent | Ensure that the current audio volume gets saved to the local file on session ... (diff) | |
download | lumina-e36db04274e700c154e26e7c459c36329afb2c42.tar.gz lumina-e36db04274e700c154e26e7c459c36329afb2c42.tar.bz2 lumina-e36db04274e700c154e26e7c459c36329afb2c42.zip |
Get more of the terminal working. Now all the special xterm stuff is getting trimmed out.
-rw-r--r-- | desktop-utilities/lumina-terminal/TermWindow.cpp | 18 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TermWindow.h | 4 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TerminalWidget.cpp | 87 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TerminalWidget.h | 1 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TrayIcon.cpp | 2 | ||||
-rw-r--r-- | desktop-utilities/lumina-terminal/TtyProcess.cpp | 21 |
6 files changed, 105 insertions, 28 deletions
diff --git a/desktop-utilities/lumina-terminal/TermWindow.cpp b/desktop-utilities/lumina-terminal/TermWindow.cpp index 4fc7fab5..6dfab80a 100644 --- a/desktop-utilities/lumina-terminal/TermWindow.cpp +++ b/desktop-utilities/lumina-terminal/TermWindow.cpp @@ -17,8 +17,9 @@ // =============== // PUBLIC // =============== -TermWindow::TermWindow() : QWidget(0, Qt::Window | Qt::BypassWindowManagerHint){//, ui(new Ui::TermWindow){ +TermWindow::TermWindow(QSettings *set) : QWidget(0, Qt::Window | Qt::BypassWindowManagerHint){//, ui(new Ui::TermWindow){ CLOSING = false; //internal flag + settings = set; //Create the Window this->setLayout(new QVBoxLayout()); this->setCursor(Qt::SplitVCursor); @@ -49,6 +50,13 @@ TermWindow::TermWindow() : QWidget(0, Qt::Window | Qt::BypassWindowManagerHint){ //Now set the defaults screennum = 0; //default value setTopOfScreen(true); //default value + if(settings->contains("lastSize")){ + //qDebug() << "Re-use last size:" << settings->value("lastSize").toSize(); + this->resize( settings->value("lastSize").toSize() ); + CalculateGeom(); + //qDebug() << "After size:" << this->size(); + } + //this->resize(this->width(),300); //this->setMinimumSize(20, 300); @@ -96,11 +104,12 @@ void TermWindow::setTopOfScreen(bool ontop){ // PUBLIC SLOTS // ======================= void TermWindow::ShowWindow(){ + if(animRunning>=0){ return; } //something running + animRunning = 1; this->hide(); QApplication::processEvents(); CalculateGeom(); //Now setup the animation - animRunning = 1; ANIM->setEndValue(this->geometry()); if(onTop){ //use top edge ANIM->setStartValue( QRect(this->x(), this->y(), this->width(), 0) ); //same location - no height @@ -108,10 +117,12 @@ void TermWindow::ShowWindow(){ ANIM->setStartValue( QRect(this->x(), this->geometry().bottom(), this->width(), 0) ); //same location - no height } this->show(); + qDebug() << "Start Animation" << ANIM->startValue() << ANIM->endValue(); ANIM->start(); } void TermWindow::HideWindow(){ + if(animRunning>=0){ return; } //something running //Now setup the animation //Note: Do *not* use the private settings/variables because it may be changing right now - use the current geometry *ONLY* animRunning = 0; @@ -128,6 +139,7 @@ void TermWindow::HideWindow(){ } void TermWindow::CloseWindow(){ + if(animRunning>=0){ return; } //something running //Now setup the animation animRunning = 2; ANIM->setStartValue(this->geometry()); @@ -153,6 +165,7 @@ void TermWindow::ReShowWindow(){ // PRIVATE // ======================= void TermWindow::CalculateGeom(){ + //qDebug() << "Calculating Geom:" << this->size(); QDesktopWidget *desk = QApplication::desktop(); if(desk->screenCount() <= screennum){ screennum = desk->primaryScreen(); } //invalid screen detected //Now align the window with the proper screen edge @@ -253,4 +266,5 @@ void TermWindow::mouseMoveEvent(QMouseEvent *ev){ geom.setTop(ev->globalPos().y()); this->setGeometry(geom); } + settings->setValue("lastSize",this->geometry().size()); }
\ No newline at end of file diff --git a/desktop-utilities/lumina-terminal/TermWindow.h b/desktop-utilities/lumina-terminal/TermWindow.h index ae40928f..135da0ef 100644 --- a/desktop-utilities/lumina-terminal/TermWindow.h +++ b/desktop-utilities/lumina-terminal/TermWindow.h @@ -13,11 +13,12 @@ #include <QDir> #include <QShortcut> #include <QMouseEvent> +#include <QSettings> class TermWindow : public QWidget{ Q_OBJECT public: - TermWindow(); + TermWindow(QSettings *set); ~TermWindow(); void cleanup(); //called right before the window is closed @@ -34,6 +35,7 @@ public slots: private: QTabWidget *tabWidget; + QSettings *settings; QShortcut *hideS, *closeS, *newTabS, *closeTabS; int screennum; bool onTop, CLOSING; diff --git a/desktop-utilities/lumina-terminal/TerminalWidget.cpp b/desktop-utilities/lumina-terminal/TerminalWidget.cpp index b16dd6ba..9023b222 100644 --- a/desktop-utilities/lumina-terminal/TerminalWidget.cpp +++ b/desktop-utilities/lumina-terminal/TerminalWidget.cpp @@ -10,14 +10,24 @@ #include <QDebug> #include <QApplication> #include <QScrollBar> +#include <QTextBlock> + +//Special control code ending symbols (aside from letters) +//QByteArray CC_END_SYMBOLS("@"); TerminalWidget::TerminalWidget(QWidget *parent, QString dir) : QTextEdit(parent){ //Setup the text widget this->setLineWrapMode(QTextEdit::WidgetWidth); + this->setAcceptRichText(false); + //this->setOverwriteMode(true); //this->setStyleSheet(""); DEFFMT = this->textCursor().charFormat(); //save the default structure for later CFMT = this->textCursor().charFormat(); //current format - + QFontDatabase FDB; + QStringList fonts = FDB.families(QFontDatabase::Latin); + for(int i=0; i<fonts.length(); i++){ + if(FDB.isFixedPitch(fonts[i])){ this->setFont(QFont(fonts[i])); qDebug() << "Using Font:" << fonts[i]; break; } + } //Create/open the TTY port PROC = new TTYProcess(this); qDebug() << "Open new TTY"; @@ -43,34 +53,56 @@ void TerminalWidget::aboutToClose(){ // ================== // PRIVATE // ================== +void TerminalWidget::InsertText(QString txt){ + //qDebug() << "Insert Text:" << txt << "Cursor Pos:" << this->textCursor().position() << "Column:" << this->textCursor().columnNumber(); + QTextCursor cur(this->textCursor()); + cur.setCharFormat(CFMT); + cur.insertText( txt, CFMT); + this->textCursor().swap(cur); +} + void TerminalWidget::applyData(QByteArray data){ //Iterate through the data and apply it when possible + QByteArray chars; + qDebug() << "Data:" << data; for(int i=0; i<data.size(); i++){ if( data.at(i)=='\b' ){ + //Flush current text buffer to widget + if(!chars.isEmpty()){ + chars.chop(1); + //InsertText(chars); chars.clear(); + }else{ + this->textCursor().deletePreviousChar(); + } //Simple cursor backward 1 (NOT backspace in this context!!) - this->moveCursor(QTextCursor::Left, QTextCursor::MoveAnchor); + //this->moveCursor(QTextCursor::Left, QTextCursor::MoveAnchor); }else if( data.at(i)=='\x1B' ){ + //Flush current text buffer to widget + if(!chars.isEmpty()){ InsertText(chars); chars.clear(); } //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(QChar(data.at(i+j)).isLetter() || data.at(i+j)=='@' ){ end = j; } } if(end<0){ return; } //skip everything else - no end to code found applyANSI(data.mid(i+1, end)); + //qDebug() << "Code:" << data.mid(i+1, end) << "Next Char:" << data[i+end+2]; i+=end; //move the final loop along - already handled these bytes - }else if( data.at(i) != '\r' ) { + }else if( data.at(i) != '\r' ){ //Special Check: if inserting text within a line, clear the rest of this line first if(i==0 && this->textCursor().position() < this->document()->characterCount()-1){ applyANSI("[K"); } + chars.append(data.at(i)); //Plaintext character - just add it here //qDebug() << "Insert Text:" << data.at(i) << CFMT.foreground().color() << CFMT.background().color(); - this->textCursor().insertText( QChar(data.at(i)), CFMT ); + //qDebug() << " " << this->currentCharFormat().foreground().color() << this->currentCharFormat().background().color(); + //this->textCursor().insertText( QChar(data.at(i)), CFMT ); } - } //end loop over data + if(!chars.isEmpty()){ InsertText(chars); } } void TerminalWidget::applyANSI(QByteArray code){ @@ -112,17 +144,29 @@ void TerminalWidget::applyANSI(QByteArray code){ 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 + if(mid >=3){ numR = code.mid(1,mid-1).toInt()/this->fontMetrics().lineSpacing(); } + if(mid < code.size()-1){ numC = code.mid(mid+1,code.size()-mid-2).toInt(); } + qDebug() << "Set Text Position (absolute):" << "Code:" << code << "Row:" << numR << "Col:" << numC; + qDebug() << " - Current Pos:" << this->textCursor().position() << "Line Count:" << this->document()->lineCount(); + //if(!this->textCursor().movePosition(QTextCursor::Start, QTextCursor::MoveAnchor,1) ){ qDebug() << "Could not go to start"; } + QTextCursor cur(this->textCursor()); + cur.setPosition(0, QTextCursor::MoveAnchor); //go to start of document + qDebug() << " - Pos After Start Move:" << cur.position(); + if( !cur.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, numR) ){ qDebug() << "Could not go to row:" << numR; } + qDebug() << " - Pos After Down Move:" << cur.position(); + if( !cur.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, numC) ){ qDebug() << "Could not go to col:" << numC; } + /*this->textCursor().setPosition( this->document()->findBlockByLineNumber(numR).position() ); + qDebug() << " - Pos After Row Move:" << this->textCursor().position(); + if( !this->textCursor().movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, numC) ){ qDebug() << "Could not go to col:" << numC; }*/ + qDebug() << " - Ending Pos:" << cur.position(); + this->setTextCursor(cur); } // DISPLAY CLEAR CODES }else if(code.endsWith("J")){ //ED - Erase Display int num = 0; if(code.size()>2){ num = code.mid(1, code.size()-2).toInt(); } //everything in the middle + //qDebug() << "Erase Display:" << num; if(num==1){ //Clear from cursor to beginning of screen for(int i=this->textCursor().position(); i>=0; i--){ @@ -130,6 +174,7 @@ void TerminalWidget::applyANSI(QByteArray code){ } }else if(num==2){ //Clear the whole screen + qDebug() << "Clear Screen:" << this->document()->lineCount(); this->clear(); }else{ //Clear from cursor to end of screen @@ -165,10 +210,10 @@ void TerminalWidget::applyANSI(QByteArray code){ } //SCROLL MOVEMENT CODES - }else if(code.endsWith("S")){ // SU - Scrolll Up - + }else if(code.endsWith("S")){ // SU - Scroll Up + qDebug() << "Scroll Up:" << code; }else if(code.endsWith("T")){ // SD - Scroll Down - + qDebug() << "Scroll Down:" << code; // GRAPHICS RENDERING }else if(code.endsWith("m")){ @@ -185,13 +230,20 @@ void TerminalWidget::applyANSI(QByteArray code){ end = code.size()-1; if(end>start){ applyANSIColor(code.mid(start, end-start).toInt());} else{ applyANSIColor(0); } + + + // GRAPHICS MODES + }else if(code.endsWith("h")){ + + }else if(code.endsWith("l")){ + + }else{ + qDebug() << "Unhandled Control Code:" << code; } - - } void TerminalWidget::applyANSIColor(int code){ - qDebug() << "Apply Color code:" << code; + //qDebug() << "Apply Color code:" << code; if(code <=0){ CFMT = DEFFMT; } //Reset back to default else if(code==1){ CFMT.setFontWeight(75); } //BOLD font else if(code==2){ CFMT.setFontWeight(25); } //Faint font (smaller than normal by a bit) @@ -229,6 +281,7 @@ QBrush brush = CFMT.background(); color.setAlpha(255); //fully opaque brush.setColor(color); CFMT.setForeground( brush ); + this->setTextColor(color); //just in case the format is not used } else if(code>=40 && code<=49){ //Set the font color diff --git a/desktop-utilities/lumina-terminal/TerminalWidget.h b/desktop-utilities/lumina-terminal/TerminalWidget.h index 6fe660a7..f0c84013 100644 --- a/desktop-utilities/lumina-terminal/TerminalWidget.h +++ b/desktop-utilities/lumina-terminal/TerminalWidget.h @@ -28,6 +28,7 @@ private: QTextCharFormat DEFFMT, CFMT; //default/current text format //Incoming Data parsing + void InsertText(QString); void applyData(QByteArray data); //overall data parsing void applyANSI(QByteArray code); //individual code application void applyANSIColor(int code); //Add the designated color code to the CFMT structure diff --git a/desktop-utilities/lumina-terminal/TrayIcon.cpp b/desktop-utilities/lumina-terminal/TrayIcon.cpp index 14ea24b4..4519e5e5 100644 --- a/desktop-utilities/lumina-terminal/TrayIcon.cpp +++ b/desktop-utilities/lumina-terminal/TrayIcon.cpp @@ -17,7 +17,7 @@ TrayIcon::TrayIcon() : QSystemTrayIcon(){ this->setContextMenu(new QMenu()); ScreenMenu = new QMenu(); connect(ScreenMenu, SIGNAL(triggered(QAction*)), this, SLOT(ChangeScreen(QAction*)) ); - TERM = new TermWindow(); + TERM = new TermWindow(settings); //Load the current settings TERM->setTopOfScreen(settings->value("TopOfScreen",true).toBool()); TERM->setCurrentScreen(settings->value("OnScreen",0).toInt()); diff --git a/desktop-utilities/lumina-terminal/TtyProcess.cpp b/desktop-utilities/lumina-terminal/TtyProcess.cpp index ec0a6309..7a68a7d1 100644 --- a/desktop-utilities/lumina-terminal/TtyProcess.cpp +++ b/desktop-utilities/lumina-terminal/TtyProcess.cpp @@ -1,6 +1,7 @@ #include "TtyProcess.h" #include <QDir> +#include <QProcessEnvironment> TTYProcess::TTYProcess(QObject *parent) : QObject(parent){ childProc = 0; @@ -16,6 +17,13 @@ TTYProcess::~TTYProcess(){ bool TTYProcess::startTTY(QString prog, QStringList args, QString workdir){ if(workdir=="~"){ workdir = QDir::homePath(); } QDir::setCurrent(workdir); + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + setenv("TERM","lumina-terminal",1); + setenv("TERMCAP","",1); //see /etc/termcap as well + QStringList filter = env.keys().filter("XTERM"); + for(int i=0; i<filter.length(); i++){ unsetenv(filter[i].toLocal8Bit().data()); } + //if(env.contains("TERM")){ unsetenv("TERM"); } + //else if(env.contains //Turn the program/arguments into C-compatible arrays char cprog[prog.length()]; strcpy(cprog, prog.toLocal8Bit().data()); char *cargs[args.length()+2]; @@ -77,9 +85,9 @@ QByteArray TTYProcess::readTTY(){ if(sn==0){ return BA; } //not setup yet char buffer[64]; ssize_t rtot = read(sn->socket(),&buffer,64); - buffer[rtot]='\0'; + //buffer[rtot]='\0'; BA = QByteArray(buffer, rtot); - qDebug() << " - Got Data:" << BA; + //qDebug() << " - Got Data:" << BA; if(!fragBA.isEmpty()){ //Have a leftover fragment, include this too BA = BA.prepend(fragBA); @@ -93,7 +101,6 @@ QByteArray TTYProcess::readTTY(){ return readTTY(); }else{ //qDebug() << "Read Data:" << BA; - qDebug() << ".."; //Crashes when the debug line is removed - not sure why.... return BA; } } @@ -134,7 +141,7 @@ QByteArray TTYProcess::CleanANSI(QByteArray raw, bool &incomplete){ } // GENERIC ANSI CODES ((Make sure the output is not cut off in the middle of a code) - index = raw.indexOf("\x1B["); + index = raw.indexOf("\x1B"); while(index>=0){ //CURSOR MOVEMENT int end = 0; @@ -145,7 +152,7 @@ QByteArray TTYProcess::CleanANSI(QByteArray raw, bool &incomplete){ end = i; //found the end of the control code } } - index = raw.indexOf("\x1B[",index+1); //now find the next one + index = raw.indexOf("\x1B",index+1); //now find the next one } // SYSTEM BELL @@ -165,7 +172,7 @@ pid_t TTYProcess::LaunchProcess(int& fd, char *prog, char **child_args){ //Returns: -1 for errors, positive value (file descriptor) for the master side of the TTY to watch //First open/setup a new pseudo-terminal file/device on the system (master side) - fd = posix_openpt(O_RDWR); //open read/write + fd = posix_openpt(O_RDWR | O_NOCTTY); //open read/write if(fd<0){ return -1; } //could not create pseudo-terminal int rc = grantpt(fd); //set permissions if(rc!=0){ return -1; } @@ -175,7 +182,7 @@ pid_t TTYProcess::LaunchProcess(int& fd, char *prog, char **child_args){ pid_t PID = fork(); if(PID==0){ //SLAVE/child - int fds = ::open(ptsname(fd), O_RDWR); //open slave side read/write + int fds = ::open(ptsname(fd), O_RDWR | O_NOCTTY); //open slave side read/write ::close(fd); //close the master side from the slave thread //Adjust the slave side mode to RAW |