# HG changeset patch # User Jacob Dawid # Date 1327923514 -3600 # Node ID 8dfa333f1130582f782a0c03aa5fe42cb50183c0 # Parent 556f8f40112ef284ae68dc10eefe45dcf95419fd Removed complete terminal code, since everything moved to qterminal. * gui/src/terminal: Removed completely. * octave-gui.pro.in: Removed because it is not used. * octave-gui.pro: Removed entries for terminal files. diff -r 556f8f40112e -r 8dfa333f1130 gui/octave-gui.pro --- a/gui/octave-gui.pro Mon Jan 30 01:54:18 2012 +0100 +++ b/gui/octave-gui.pro Mon Jan 30 12:38:34 2012 +0100 @@ -41,7 +41,7 @@ } # Includepaths and libraries to link against: -INCLUDEPATH += src src/terminal src/backend qterminal/libqterminal qirc/libqirc \ +INCLUDEPATH += src src/backend qterminal/libqterminal qirc/libqirc \ $$system(mkoctfile -p INCFLAGS) INCFLAGS += $$system(mkoctfile -p INCFLAGS) mac { @@ -95,13 +95,6 @@ SOURCES += } -win32 { -SOURCES += \ - src/WinTerminalView.cpp \ - src/terminal/win32/QConsole.cpp \ - src/terminal/win32/QConsoleColors.cpp -} - HEADERS += \ src/lexer/lexeroctavegui.h \ src/MainWindow.h \ @@ -124,14 +117,6 @@ HEADERS += } -win32 { -HEADERS += \ - src/WinTerminalView.h \ - src/terminal/win32/QConsole.h \ - src/terminal/win32/QConsoleColors.h -INCLUDEPATH += src/terminal/win32 -} - FORMS += \ src/SettingsDialog.ui \ src/WelcomeWizard.ui diff -r 556f8f40112e -r 8dfa333f1130 gui/octave-gui.pro.in --- a/gui/octave-gui.pro.in Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -# OctaveGUI - A graphical user interface for Octave -# Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - - -# Basic settings: -QT += core gui webkit network # Qt modules -TEMPLATE = app # Build as application -TARGET = octave-gui # Name of the target binary - -DESTDIR = bin # Destination of the output -UI_DIR = ui-files # Folder for ui files -MOC_DIR = moc-files # Folder for moc files -OBJECTS_DIR = object-files # Folder for object files - -TRANSLATIONS += languages/generic.ts \ - languages/de-de.ts \ - languages/pt-br.ts \ - languages/es-es.ts \ - languages/ru-ru.ts \ - languages/uk-ua.ts # Available translations -LIBS += -lqscintilla2 $$system(%mkoctfile% -p LIBS) $$system(%mkoctfile% -p OCTAVE_LIBS) - -mac { - CONFIG -= app_bundle -} - -# Includepaths and libraries to link against: -INCLUDEPATH += src src/terminal src/qirc src/backend \ - $$system(%mkoctfile% -p INCFLAGS) -INCFLAGS += $$system(%mkoctfile% -p INCFLAGS) -mac { - INCFLAGS += -I/opt/local-native/include -} - -LFLAGS += $$system(%mkoctfile% -p LFLAGS) \ - $$system(%mkoctfile% -p OCTAVE_LIBS) \ - $$system(%mkoctfile% -p LIBS) -mac { - LFLAGS += -L/opt/local-native/lib -} - -unix { - QMAKE_LFLAGS += -lutil -} - -win32 { - QMAKE_LFLAGS += --enable-auto-import -} - -QMAKE_LFLAGS += $$LFLAGS $$system(%mkoctfile% -p RLD_FLAG) -QMAKE_CXXFLAGS += $$INCFLAGS - -# Files associated with the project: -SOURCES +=\ - src/lexer/lexeroctavegui.cpp \ - src/MainWindow.cpp \ - src/WorkspaceView.cpp \ - src/HistoryDockWidget.cpp \ - src/FilesDockWidget.cpp \ - src/FileEditorMdiSubWindow.cpp \ - src/BrowserWidget.cpp \ - src/ImageViewerMdiSubWindow.cpp \ - src/irc/IRCWidget.cpp \ - src/SettingsDialog.cpp \ - src/OctaveGUI.cpp \ - src/ResourceManager.cpp \ - src/CommandLineParser.cpp \ - src/backend/OctaveCallbackThread.cpp \ - src/backend/OctaveLink.cpp \ - src/backend/OctaveMainThread.cpp \ - src/irc/IRCClientImpl.cpp \ - src/terminal/TerminalEmulation.cpp \ - src/backend/ReadlineAdapter.cpp \ - src/TerminalView.cpp \ - src/TerminalHighlighter.cpp \ - src/WelcomeWizard.cpp - -unix { -SOURCES +=\ - src/terminal/LinuxTerminalEmulation.cpp \ - src/terminal/KPty.cpp \ - src/terminal/KPtyDevice.cpp -} - -HEADERS += \ - src/lexer/lexeroctavegui.h \ - src/MainWindow.h \ - src/WorkspaceView.h \ - src/HistoryDockWidget.h \ - src/FilesDockWidget.h \ - src/FileEditorMdiSubWindow.h \ - src/BrowserWidget.h \ - src/ImageViewerMdiSubWindow.h \ - src/irc/IRCWidget.h \ - src/SettingsDialog.h \ - src/ResourceManager.h \ - src/CommandLineParser.h \ - src/backend/OctaveCallbackThread.h \ - src/backend/OctaveLink.h \ - src/backend/OctaveMainThread.h \ - src/irc/IRCClientInterface.h \ - src/irc/IRCClientImpl.h \ - src/terminal/TerminalEmulation.h \ - src/backend/ReadlineAdapter.h \ - src/TerminalView.h \ - src/TerminalHighlighter.h \ - src/WelcomeWizard.h - -unix { -HEADERS += \ - src/terminal/LinuxTerminalEmulation.h \ - src/terminal/KPtyDevice.h \ - src/terminal/KPty.h -} - -FORMS += \ - src/SettingsDialog.ui \ - src/WelcomeWizard.ui diff -r 556f8f40112e -r 8dfa333f1130 gui/src/MainWindow.cpp --- a/gui/src/MainWindow.cpp Mon Jan 30 01:54:18 2012 +0100 +++ b/gui/src/MainWindow.cpp Mon Jan 30 12:38:34 2012 +0100 @@ -27,7 +27,7 @@ #include "ImageViewerMdiSubWindow.h" #include "SettingsDialog.h" -#define VERSION_STRING "Octave GUI (0.8.5)" +#define VERSION_STRING "Octave GUI (0.8.7)" MainWindow::MainWindow (QWidget * parent):QMainWindow (parent) { diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/KPty.cpp --- a/gui/src/terminal/KPty.cpp Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,657 +0,0 @@ -/* - - This file is part of the KDE libraries - Copyright (C) 2002 Waldo Bastian - Copyright (C) 2002-2003,2007-2008 Oswald Buddenhagen - Copyright (C) 2010 KDE e.V. - Author Adriaan de Groot - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - - -#include "KPty.h" - -#include - -#define TTY_GROUP "tty" - -#ifndef PATH_MAX -#ifdef MAXPATHLEN -#define PATH_MAX MAXPATHLEN -#else -#define PATH_MAX 1024 -#endif -#endif - -/////////////////////// -// private functions // -/////////////////////// - -////////////////// -// private data // -////////////////// - -KPtyPrivate::KPtyPrivate (KPty * parent): -masterFd (-1), -slaveFd (-1), -ownMaster (true), -q_ptr (parent) -{ -} - -KPtyPrivate::~KPtyPrivate () -{ -} - -#ifndef HAVE_OPENPTY -bool -KPtyPrivate::chownpty (bool grant) -{ - return !QProcess::execute (KStandardDirs::findExe ("kgrantpty"), - QStringList () << (grant ? "--grant" : - "--revoke") << QString:: - number (masterFd)); -} -#endif - -///////////////////////////// -// public member functions // -///////////////////////////// - -KPty::KPty (): -d_ptr (new KPtyPrivate (this)) -{ -} - -KPty::KPty (KPtyPrivate * d): -d_ptr (d) -{ - d_ptr->q_ptr = this; -} - -KPty::~KPty () -{ - close (); - delete d_ptr; -} - -bool -KPty::open () -{ - Q_D (KPty); - - if (d->masterFd >= 0) - return true; - - d->ownMaster = true; - - QByteArray ptyName; - - // 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. - - // 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; - //kWarning(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; - } - -#elif defined(HAVE_PTSNAME) || defined(TIOCGPTN) - -#ifdef HAVE_POSIX_OPENPT - d->masterFd =::posix_openpt (O_RDWR | O_NOCTTY); -#elif defined(HAVE_GETPT) - d->masterFd =::getpt (); -#elif defined(PTM_DEVICE) - //d->masterFd = KDE_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) - { -#ifdef HAVE_PTSNAME - char *ptsn = ptsname (d->masterFd); - if (ptsn) - { - d->ttyName = ptsn; -#else - int ptyno; - if (!ioctl (d->masterFd, TIOCGPTN, &ptyno)) - { - char buf[32]; - sprintf (buf, "/dev/pts/%d", ptyno); - d->ttyName = buf; -#endif -#ifdef HAVE_GRANTPT - if (!grantpt (d->masterFd)) - goto grantedpt; -#else - 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; - } - } - } - - //kWarning(175) << "Can't open a pseudo teletype"; - return false; - -gotpty: - KDE_struct_stat st; - if (KDE_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)) - { - - /*kWarning(175) - << "chownpty failed for device " << ptyName << "::" << d->ttyName - << "\nThis means the communication can be eavesdropped." << endl; - */ - } - -grantedpt: - -#ifdef HAVE_REVOKE - revoke (d->ttyName.data ()); -#endif - -#ifdef HAVE_UNLOCKPT - unlockpt (d->masterFd); -#elif defined(TIOCSPTLCK) - int flag = 0; - ioctl (d->masterFd, TIOCSPTLCK, &flag); -#endif - - d->slaveFd =::open (d->ttyName.data (), O_RDWR | O_NOCTTY); - if (d->slaveFd < 0) - { - //kWarning(175) << "Can't open slave pseudo teletype"; - ::close (d->masterFd); - d->masterFd = -1; - return false; - } - -#if (defined(__svr4__) || defined(__sgi__) || defined(Q_OS_SOLARIS)) - // Solaris uses STREAMS for terminal handling. It is possible - // for the pty handling modules to be left off the stream; in that - // case push them on. ioctl(fd, I_FIND, ...) is documented to return - // 1 if the module is on the stream already. - { - static const char *pt = "ptem"; - static const char *ld = "ldterm"; - if (ioctl (d->slaveFd, I_FIND, pt) == 0) - ioctl (d->slaveFd, I_PUSH, pt); - if (ioctl (d->slaveFd, I_FIND, ld) == 0) - ioctl (d->slaveFd, I_PUSH, ld); - } -#endif - -#endif /* HAVE_OPENPTY */ - - fcntl (d->masterFd, F_SETFD, FD_CLOEXEC); - fcntl (d->slaveFd, F_SETFD, FD_CLOEXEC); - - return true; -} - -bool -KPty::open (int fd) -{ -#if !defined(HAVE_PTSNAME) && !defined(TIOCGPTN) - //kWarning(175) << "Unsupported attempt to open pty with fd" << fd; - return false; -#else - Q_D (KPty); - - if (d->masterFd >= 0) - { - //kWarning(175) << "Attempting to open an already open pty"; - return false; - } - - d->ownMaster = false; - -#ifdef HAVE_PTSNAME - char *ptsn = ptsname (fd); - if (ptsn) - { - d->ttyName = ptsn; -#else - int ptyno; - if (!ioctl (fd, TIOCGPTN, &ptyno)) - { - char buf[32]; - sprintf (buf, "/dev/pts/%d", ptyno); - d->ttyName = buf; -#endif - } - else - { - //kWarning(175) << "Failed to determine pty slave device for fd" << fd; - return false; - } - - d->masterFd = fd; - if (!openSlave ()) - { - d->masterFd = -1; - return false; - } - - return true; -#endif -} - -void -KPty::closeSlave () -{ - Q_D (KPty); - - if (d->slaveFd < 0) - return; - ::close (d->slaveFd); - d->slaveFd = -1; -} - -bool -KPty::openSlave () -{ - Q_D (KPty); - - if (d->slaveFd >= 0) - return true; - if (d->masterFd < 0) - { - //kWarning(175) << "Attempting to open pty slave while master is closed"; - return false; - } - d->slaveFd =::open (d->ttyName.data (), O_RDWR | O_NOCTTY); - if (d->slaveFd < 0) - { - //kWarning(175) << "Can't open slave pseudo teletype"; - return false; - } - fcntl (d->slaveFd, F_SETFD, FD_CLOEXEC); - return true; -} - -void -KPty::close () -{ - Q_D (KPty); - - if (d->masterFd < 0) - return; - closeSlave (); - if (d->ownMaster) - { -#ifndef HAVE_OPENPTY - // 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); - } - } -#endif - ::close (d->masterFd); - } - d->masterFd = -1; -} - -void -KPty::setCTty () -{ - Q_D (KPty); - - // 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); -#else - // __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 (); -#if defined(_POSIX_VERSION) || defined(__svr4__) - tcsetpgrp (d->slaveFd, pgrp); -#elif defined(TIOCSPGRP) - ioctl (d->slaveFd, TIOCSPGRP, (char *) &pgrp); -#endif -} - -void -KPty::login (const char *user, const char *remotehost) -{ -#ifdef HAVE_UTEMPTER - Q_D (KPty); - - addToUtmp (d->ttyName, remotehost, d->masterFd); - Q_UNUSED (user); -#else -#ifdef HAVE_UTMPX - struct utmpx l_struct; -#else - struct utmp l_struct; -#endif - 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 (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)); -#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)); -#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)); -#endif -#endif - -#ifdef HAVE_UTMPX - //gettimeofday(&l_struct.ut_tv, 0); - gettimeofday ((struct timeval *) &l_struct.ut_tv, 0); -#else - l_struct.ut_time = time (0); -#endif - -#ifdef HAVE_LOGIN -#ifdef HAVE_LOGINX - ::loginx (&l_struct); -#else - ::login (&l_struct); -#endif -#else -#ifdef HAVE_STRUCT_UTMP_UT_TYPE - l_struct.ut_type = USER_PROCESS; -#endif -#ifdef HAVE_STRUCT_UTMP_UT_PID - l_struct.ut_pid = getpid (); -#ifdef HAVE_STRUCT_UTMP_UT_SESSION - l_struct.ut_session = getsid (0); -#endif -#endif -#ifdef HAVE_UTMPX - 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); -#endif -#endif -#endif -} - -void -KPty::logout () -{ -#ifdef HAVE_UTEMPTER - Q_D (KPty); - - removeLineFromUtmp (d->ttyName, d->masterFd); -#else - 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; - } -#endif -#ifdef HAVE_LOGIN -#ifdef HAVE_LOGINX - ::logoutx (str_ptr, 0, DEAD_PROCESS); -#else - ::logout (str_ptr); -#endif -#else -#ifdef HAVE_UTMPX - struct utmpx l_struct, *ut; -#else - struct utmp l_struct, *ut; -#endif - memset (&l_struct, 0, sizeof (l_struct)); - - strncpy (l_struct.ut_line, str_ptr, sizeof (l_struct.ut_line)); - -#ifdef HAVE_UTMPX - utmpxname (_PATH_UTMPX); - setutxent (); - if ((ut = getutxline (&l_struct))) - { -#else - 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)); -#ifdef HAVE_STRUCT_UTMP_UT_SYSLEN - ut->ut_syslen = 0; -#endif -#ifdef HAVE_STRUCT_UTMP_UT_TYPE - ut->ut_type = DEAD_PROCESS; -#endif -#ifdef HAVE_UTMPX - //gettimeofday(&(ut->ut_tv), 0); - gettimeofday ((struct timeval *) &(ut->ut_tv), 0); - pututxline (ut); - } - endutxent (); -#else - ut->ut_time = time (0); - pututline (ut); - } - endutent (); -#endif -#endif -#endif -} - -bool -KPty::tcGetAttr (struct::termios * ttmode) const -{ - Q_D (const KPty); - -#ifdef Q_OS_SOLARIS - if (_tcgetattr (d->slaveFd, ttmode) == 0) - return true; -#endif - return _tcgetattr (d->masterFd, ttmode) == 0; -} - -bool -KPty::tcSetAttr (struct::termios * ttmode) -{ - Q_D (KPty); - -#ifdef Q_OS_SOLARIS - if (_tcsetattr (d->slaveFd, ttmode) == 0) - return true; -#endif - return _tcsetattr (d->masterFd, ttmode) == 0; -} - -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; -} - -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); - - return d->ttyName.data (); -} - -int -KPty::masterFd () const -{ - Q_D (const KPty); - - return d->masterFd; -} - -int -KPty::slaveFd () const -{ - Q_D (const KPty); - - return d->slaveFd; -} diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/KPty.h --- a/gui/src/terminal/KPty.h Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,347 +0,0 @@ -/* This file is part of the KDE libraries - - Copyright (C) 2003,2007 Oswald Buddenhagen - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef kpty_h -#define kpty_h - -#ifdef __APPLE__ -#ifndef Q_OS_MAC -#define Q_OS_MAC -#endif -#endif - -#if defined(Q_OS_MAC) -#define HAVE_UTIL_H -#define HAVE_UTMPX -#define _UTMPX_COMPAT -#define HAVE_PTSNAME -#define HAVE_SYS_TIME_H -#else -#define HAVE_PTY_H -#endif - -#define HAVE_OPENPTY - -#include - -#ifdef __sgi -#define __svr4__ -#endif - -#ifdef __osf__ -#define _OSF_SOURCE -#include -#endif - -#ifdef _AIX -#define _ALL_SOURCE -#endif - -// __USE_XOPEN isn't defined by default in ICC -// (needed for ptsname(), grantpt() and unlockpt()) -#ifdef __INTEL_COMPILER -#ifndef __USE_XOPEN -#define __USE_XOPEN -#endif -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(HAVE_PTY_H) -#include -#endif - -#ifdef HAVE_LIBUTIL_H -#include -#elif defined(HAVE_UTIL_H) -#include -#endif - -#define HAVE_UTMPX -#define _UTMPX_COMPAT - -#ifdef HAVE_UTEMPTER -extern "C" -{ -#include -} -#else -#include -#ifdef HAVE_UTMPX -#include -#endif -#if !defined(_PATH_UTMPX) && defined(_UTMPX_FILE) -#define _PATH_UTMPX _UTMPX_FILE -#endif -#if !defined(_PATH_WTMPX) && defined(_WTMPX_FILE) -#define _PATH_WTMPX _WTMPX_FILE -#endif -#endif - -/* for HP-UX (some versions) the extern C is needed, and for other - platforms it doesn't hurt */ -extern "C" -{ -#include -#if defined(HAVE_TERMIO_H) -#include // struct winsize on some systems -#endif -} - -#if defined (_HPUX_SOURCE) -#define _TERMIOS_INCLUDED -#include -#endif - -#ifdef HAVE_SYS_STROPTS_H -#include // Defines I_PUSH -#define _NEW_TTY_CTRL -#endif - -#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__bsdi__) || defined(__APPLE__) || defined (__DragonFly__) -#define _tcgetattr(fd, ttmode) ioctl(fd, TIOCGETA, (char *)ttmode) -#else -#if defined(_HPUX_SOURCE) || defined(__Lynx__) || defined (__CYGWIN__) || defined(__sun) -#define _tcgetattr(fd, ttmode) tcgetattr(fd, ttmode) -#else -#define _tcgetattr(fd, ttmode) ioctl(fd, TCGETS, (char *)ttmode) -#endif -#endif - -#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || defined (__bsdi__) || defined(__APPLE__) || defined (__DragonFly__) -#define _tcsetattr(fd, ttmode) ioctl(fd, TIOCSETA, (char *)ttmode) -#else -#if defined(_HPUX_SOURCE) || defined(__CYGWIN__) || defined(__sun) -#define _tcsetattr(fd, ttmode) tcsetattr(fd, TCSANOW, ttmode) -#else -#define _tcsetattr(fd, ttmode) ioctl(fd, TCSETS, (char *)ttmode) -#endif -#endif - -#include -#include - -class KPty; -struct KPtyPrivate -{ - Q_DECLARE_PUBLIC (KPty) KPtyPrivate (KPty * parent); - virtual ~ KPtyPrivate (); - bool chownpty (bool grant); - - int masterFd; - int slaveFd; - bool ownMaster:1; - - QByteArray ttyName; - - KPty *q_ptr; -}; - -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) public: - - /** - * Constructor - */ - 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 (); - - /** - * Open using an existing pty master. - * - * @param fd an open pty master file descriptor. - * The ownership of the fd remains with the caller; - * it will not be automatically closed at any point. - * @return true if a pty pair was successfully opened - */ - bool open (int fd); - - /** - * 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 (); - - /** - * Open the pty slave descriptor. - * - * This undoes the effect of closeSlave(). - * - * @return true if the pty slave was successfully opened - */ - bool openSlave (); - - /** - * 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); - - /** - * 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 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); - - /** - * 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 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; - -protected: - /** - * @internal - */ - KPty (KPtyPrivate * d); - - /** - * @internal - */ - KPtyPrivate *const d_ptr; -}; - -#endif diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/KPtyDevice.cpp --- a/gui/src/terminal/KPtyDevice.cpp Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,456 +0,0 @@ -/* - - This file is part of the KDE libraries - Copyright (C) 2007 Oswald Buddenhagen - Copyright (C) 2010 KDE e.V. - Author Adriaan de Groot - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - - -#include "KPtyDevice.h" -#define i18n - -#include - -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_FILIO_H -#include -#endif -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#if defined(Q_OS_FREEBSD) || defined(Q_OS_MAC) - // "the other end's output queue size" - kinda braindead, huh? -#define PTY_BYTES_AVAILABLE TIOCOUTQ -#elif defined(TIOCINQ) - // "our end's input queue size" -#define PTY_BYTES_AVAILABLE TIOCINQ -#else - // likewise. more generic ioctl (theoretically) -#define PTY_BYTES_AVAILABLE FIONREAD -#endif - -////////////////// -// private data // -////////////////// - -// Lifted from Qt. I don't think they would mind. ;) -// Re-lift again from Qt whenever a proper replacement for pthread_once appears -static void -qt_ignore_sigpipe () -{ - static QBasicAtomicInt atom = Q_BASIC_ATOMIC_INITIALIZER (0); - if (atom.testAndSetRelaxed (0, 1)) - { - struct sigaction noaction; - memset (&noaction, 0, sizeof (noaction)); - noaction.sa_handler = SIG_IGN; - sigaction (SIGPIPE, &noaction, 0); - } -} - -#define NO_INTR(ret,func) do { ret = func; } while (ret < 0 && errno == EINTR) - -bool -KPtyDevicePrivate::_k_canRead () -{ - Q_Q (KPtyDevice); - qint64 readBytes = 0; - -#ifdef Q_OS_IRIX // this should use a config define, but how to check it? - size_t available; -#else - int available; -#endif - if (!::ioctl (q->masterFd (), PTY_BYTES_AVAILABLE, (char *) &available)) - { -#ifdef Q_OS_SOLARIS - // A Pty is a STREAMS module, and those can be activated - // with 0 bytes available. This happens either when ^C is - // pressed, or when an application does an explicit write(a,b,0) - // which happens in experiments fairly often. When 0 bytes are - // available, you must read those 0 bytes to clear the STREAMS - // module, but we don't want to hit the !readBytes case further down. - if (!available) - { - char c; - // Read the 0-byte STREAMS message - NO_INTR (readBytes, read (q->masterFd (), &c, 0)); - // Should return 0 bytes read; -1 is error - if (readBytes < 0) - { - readNotifier->setEnabled (false); - emit q->readEof (); - return false; - } - return true; - } -#endif - - char *ptr = readBuffer.reserve (available); -#ifdef Q_OS_SOLARIS - // Even if available > 0, it is possible for read() - // to return 0 on Solaris, due to 0-byte writes in the stream. - // Ignore them and keep reading until we hit *some* data. - // In Solaris it is possible to have 15 bytes available - // and to (say) get 0, 0, 6, 0 and 9 bytes in subsequent reads. - // Because the stream is set to O_NONBLOCK in finishOpen(), - // an EOF read will return -1. - readBytes = 0; - while (!readBytes) -#endif - // Useless block braces except in Solaris - { - NO_INTR (readBytes, read (q->masterFd (), ptr, available)); - } - if (readBytes < 0) - { - readBuffer.unreserve (available); - q->setErrorString (i18n ("Error reading from PTY")); - return false; - } - readBuffer.unreserve (available - readBytes); // *should* be a no-op - } - - if (!readBytes) - { - readNotifier->setEnabled (false); - emit q->readEof (); - return false; - } - else - { - if (!emittedReadyRead) - { - emittedReadyRead = true; - emit q->readyRead (); - emittedReadyRead = false; - } - return true; - } -} - -bool -KPtyDevicePrivate::_k_canWrite () -{ - Q_Q (KPtyDevice); - - writeNotifier->setEnabled (false); - if (writeBuffer.isEmpty ()) - return false; - - qt_ignore_sigpipe (); - int wroteBytes; - NO_INTR (wroteBytes, - write (q->masterFd (), - writeBuffer.readPointer (), writeBuffer.readSize ())); - if (wroteBytes < 0) - { - q->setErrorString (i18n ("Error writing to PTY")); - return false; - } - writeBuffer.free (wroteBytes); - - if (!emittedBytesWritten) - { - emittedBytesWritten = true; - emit q->bytesWritten (wroteBytes); - emittedBytesWritten = false; - } - - if (!writeBuffer.isEmpty ()) - writeNotifier->setEnabled (true); - return true; -} - -#ifndef timeradd -// Lifted from GLIBC -#define timeradd(a, b, result) \ - do { \ - (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ - if ((result)->tv_usec >= 1000000) { \ - ++(result)->tv_sec; \ - (result)->tv_usec -= 1000000; \ - } \ - } while (0) -#define timersub(a, b, result) \ - do { \ - (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ - if ((result)->tv_usec < 0) { \ - --(result)->tv_sec; \ - (result)->tv_usec += 1000000; \ - } \ - } while (0) -#endif - -bool -KPtyDevicePrivate::doWait (int msecs, bool reading) -{ - Q_Q (KPtyDevice); -#ifndef __linux__ - struct timeval etv; -#endif - struct timeval tv, *tvp; - - if (msecs < 0) - tvp = 0; - else - { - tv.tv_sec = msecs / 1000; - tv.tv_usec = (msecs % 1000) * 1000; -#ifndef __linux__ - gettimeofday (&etv, 0); - timeradd (&tv, &etv, &etv); -#endif - tvp = &tv; - } - - while (reading ? readNotifier->isEnabled () : !writeBuffer.isEmpty ()) - { - fd_set rfds; - fd_set wfds; - - FD_ZERO (&rfds); - FD_ZERO (&wfds); - - if (readNotifier->isEnabled ()) - FD_SET (q->masterFd (), &rfds); - if (!writeBuffer.isEmpty ()) - FD_SET (q->masterFd (), &wfds); - -#ifndef __linux__ - if (tvp) - { - gettimeofday (&tv, 0); - timersub (&etv, &tv, &tv); - if (tv.tv_sec < 0) - tv.tv_sec = tv.tv_usec = 0; - } -#endif - - switch (select (q->masterFd () + 1, &rfds, &wfds, 0, tvp)) - { - case -1: - if (errno == EINTR) - break; - return false; - case 0: - q->setErrorString (i18n ("PTY operation timed out")); - return false; - default: - if (FD_ISSET (q->masterFd (), &rfds)) - { - bool canRead = _k_canRead (); - if (reading && canRead) - return true; - } - if (FD_ISSET (q->masterFd (), &wfds)) - { - bool canWrite = _k_canWrite (); - if (!reading) - return canWrite; - } - break; - } - } - return false; -} - -void -KPtyDevicePrivate::finishOpen (QIODevice::OpenMode mode) -{ - Q_Q (KPtyDevice); - - q->QIODevice::open (mode); - fcntl (q->masterFd (), F_SETFL, O_NONBLOCK); - readBuffer.clear (); - readNotifier = - new QSocketNotifier (q->masterFd (), QSocketNotifier::Read, q); - writeNotifier = - new QSocketNotifier (q->masterFd (), QSocketNotifier::Write, q); - QObject::connect (readNotifier, SIGNAL (activated (int)), q, - SLOT (_k_canRead ())); - QObject::connect (writeNotifier, SIGNAL (activated (int)), q, - SLOT (_k_canWrite ())); - readNotifier->setEnabled (true); -} - -///////////////////////////// -// public member functions // -///////////////////////////// - -KPtyDevice::KPtyDevice (QObject * parent): -QIODevice (parent), KPty (new KPtyDevicePrivate (this)) -{ -} - -KPtyDevice::~KPtyDevice () -{ - close (); -} - -bool -KPtyDevice::open (OpenMode mode) -{ - Q_D (KPtyDevice); - - if (masterFd () >= 0) - return true; - - if (!KPty::open ()) - { - setErrorString (i18n ("Error opening PTY")); - return false; - } - - d->finishOpen (mode); - - return true; -} - -bool -KPtyDevice::open (int fd, OpenMode mode) -{ - Q_D (KPtyDevice); - - if (!KPty::open (fd)) - { - setErrorString (i18n ("Error opening PTY")); - return false; - } - - d->finishOpen (mode); - - return true; -} - -void -KPtyDevice::close () -{ - Q_D (KPtyDevice); - - if (masterFd () < 0) - return; - - delete d->readNotifier; - delete d->writeNotifier; - - QIODevice::close (); - - KPty::close (); -} - -bool -KPtyDevice::isSequential () const -{ - return true; -} - -bool -KPtyDevice::canReadLine () const -{ - Q_D (const KPtyDevice); - return QIODevice::canReadLine () || d->readBuffer.canReadLine (); -} - -bool -KPtyDevice::atEnd () const -{ - Q_D (const KPtyDevice); - return QIODevice::atEnd () && d->readBuffer.isEmpty (); -} - -qint64 -KPtyDevice::bytesAvailable () const -{ - Q_D (const KPtyDevice); - return QIODevice::bytesAvailable () + d->readBuffer.size (); -} - -qint64 -KPtyDevice::bytesToWrite () const -{ - Q_D (const KPtyDevice); - return d->writeBuffer.size (); -} - -bool -KPtyDevice::waitForReadyRead (int msecs) -{ - Q_D (KPtyDevice); - return d->doWait (msecs, true); -} - -bool -KPtyDevice::waitForBytesWritten (int msecs) -{ - Q_D (KPtyDevice); - return d->doWait (msecs, false); -} - -void -KPtyDevice::setSuspended (bool suspended) -{ - Q_D (KPtyDevice); - d->readNotifier->setEnabled (!suspended); -} - -bool -KPtyDevice::isSuspended () const -{ - Q_D (const KPtyDevice); - return !d->readNotifier->isEnabled (); -} - -// protected -qint64 -KPtyDevice::readData (char *data, qint64 maxlen) -{ - Q_D (KPtyDevice); - return d->readBuffer.read (data, (int) qMin < qint64 > (maxlen, KMAXINT)); -} - -// protected -qint64 -KPtyDevice::readLineData (char *data, qint64 maxlen) -{ - Q_D (KPtyDevice); - return d->readBuffer.readLine (data, - (int) qMin < qint64 > (maxlen, KMAXINT)); -} - -// protected -qint64 -KPtyDevice::writeData (const char *data, qint64 len) -{ - Q_D (KPtyDevice); - Q_ASSERT (len <= KMAXINT); - - d->writeBuffer.write (data, len); - d->writeNotifier->setEnabled (true); - return len; -} - diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/KPtyDevice.h --- a/gui/src/terminal/KPtyDevice.h Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,356 +0,0 @@ -/* This file is part of the KDE libraries - - Copyright (C) 2007 Oswald Buddenhagen - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef kptydev_h -#define kptydev_h - -struct KPtyPrivate; -struct KPtyDevicePrivate; - -#include "KPty.h" -#include -#include - -#define Q_DECLARE_PRIVATE_MI(Class, SuperClass) \ - inline Class##Private* d_func() { return reinterpret_cast(SuperClass::d_ptr); } \ - inline const Class##Private* d_func() const { return reinterpret_cast(SuperClass::d_ptr); } \ - friend class Class##Private; - -/** - * Encapsulates KPty into a QIODevice, so it can be used with Q*Stream, etc. - */ -class KPtyDevice:public QIODevice, public KPty -{ //krazy:exclude=dpointer (via macro) -Q_OBJECT Q_DECLARE_PRIVATE_MI (KPtyDevice, KPty) public: - - /** - * Constructor - */ - KPtyDevice (QObject * parent = 0); - - /** - * Destructor: - * - * If the pty is still open, it will be closed. Note, however, that - * an utmp registration is @em not undone. - */ - virtual ~ KPtyDevice (); - - /** - * Create a pty master/slave pair. - * - * @return true if a pty pair was successfully opened - */ - virtual bool open (OpenMode mode = ReadWrite | Unbuffered); - - /** - * Open using an existing pty master. The ownership of the fd - * remains with the caller, i.e., close() will not close the fd. - * - * This is useful if you wish to attach a secondary "controller" to an - * existing pty device such as a terminal widget. - * Note that you will need to use setSuspended() on both devices to - * control which one gets the incoming data from the pty. - * - * @param fd an open pty master file descriptor. - * @param mode the device mode to open the pty with. - * @return true if a pty pair was successfully opened - */ - bool open (int fd, OpenMode mode = ReadWrite | Unbuffered); - - /** - * Close the pty master/slave pair. - */ - virtual void close (); - - /** - * Sets whether the KPtyDevice monitors the pty for incoming data. - * - * When the KPtyDevice is suspended, it will no longer attempt to buffer - * data that becomes available from the pty and it will not emit any - * signals. - * - * Do not use on closed ptys. - * After a call to open(), the pty is not suspended. If you need to - * ensure that no data is read, call this function before the main loop - * is entered again (i.e., immediately after opening the pty). - */ - void setSuspended (bool suspended); - - /** - * Returns true if the KPtyDevice is not monitoring the pty for incoming - * data. - * - * Do not use on closed ptys. - * - * See setSuspended() - */ - bool isSuspended () const; - - /** - * @return always true - */ - virtual bool isSequential () const; - - /** - * @reimp - */ - bool canReadLine () const; - - /** - * @reimp - */ - bool atEnd () const; - - /** - * @reimp - */ - qint64 bytesAvailable () const; - - /** - * @reimp - */ - qint64 bytesToWrite () const; - - bool waitForBytesWritten (int msecs = -1); - bool waitForReadyRead (int msecs = -1); - - - Q_SIGNALS: - /** - * Emitted when EOF is read from the PTY. - * - * Data may still remain in the buffers. - */ - void readEof (); - -protected: - virtual qint64 readData (char *data, qint64 maxSize); - virtual qint64 readLineData (char *data, qint64 maxSize); - virtual qint64 writeData (const char *data, qint64 maxSize); - -private: - Q_PRIVATE_SLOT (d_func (), bool _k_canRead ()) - Q_PRIVATE_SLOT (d_func (), bool _k_canWrite ())}; - -#define KMAXINT ((int)(~0U >> 1)) - -///////////////////////////////////////////////////// -// Helper. Remove when QRingBuffer becomes public. // -///////////////////////////////////////////////////// - -#include -#include - -#define CHUNKSIZE 4096 - -class KRingBuffer -{ -public: - KRingBuffer () - { - clear (); - } - - void clear () - { - buffers.clear (); - QByteArray tmp; - tmp.resize (CHUNKSIZE); - buffers << tmp; - head = tail = 0; - totalSize = 0; - } - - inline bool isEmpty () const - { - return buffers.count () == 1 && !tail; - } - - inline int size () const - { - return totalSize; - } - - inline int readSize () const - { - return (buffers.count () == 1 ? tail : buffers.first ().size ()) - head; - } - - inline const char *readPointer () const - { - Q_ASSERT (totalSize > 0); - return buffers.first ().constData () + head; - } - - void free (int bytes) - { - totalSize -= bytes; - Q_ASSERT (totalSize >= 0); - - forever - { - int nbs = readSize (); - - if (bytes < nbs) - { - head += bytes; - if (head == tail && buffers.count () == 1) - { - buffers.first ().resize (CHUNKSIZE); - head = tail = 0; - } - break; - } - - bytes -= nbs; - if (buffers.count () == 1) - { - buffers.first ().resize (CHUNKSIZE); - head = tail = 0; - break; - } - - buffers.removeFirst (); - head = 0; - } - } - - char *reserve (int bytes) - { - totalSize += bytes; - - char *ptr; - if (tail + bytes <= buffers.last ().size ()) - { - ptr = buffers.last ().data () + tail; - tail += bytes; - } - else - { - buffers.last ().resize (tail); - QByteArray tmp; - tmp.resize (qMax (CHUNKSIZE, bytes)); - ptr = tmp.data (); - buffers << tmp; - tail = bytes; - } - return ptr; - } - - // release a trailing part of the last reservation - inline void unreserve (int bytes) - { - totalSize -= bytes; - tail -= bytes; - } - - inline void write (const char *data, int len) - { - memcpy (reserve (len), data, len); - } - - // Find the first occurrence of c and return the index after it. - // If c is not found until maxLength, maxLength is returned, provided - // it is smaller than the buffer size. Otherwise -1 is returned. - int indexAfter (char c, int maxLength = KMAXINT) const - { - int index = 0; - int start = head; - QLinkedList < QByteArray >::ConstIterator it = buffers.begin (); - forever - { - if (!maxLength) - return index; - if (index == size ()) - return -1; - const QByteArray & buf = *it; - ++it; - int len = qMin ((it == buffers.end ()? tail : buf.size ()) - start, - maxLength); - const char *ptr = buf.data () + start; - if (const char *rptr = (const char *)memchr (ptr, c, len)) - return index + (rptr - ptr) + 1; - index += len; - maxLength -= len; - start = 0; - } - } - - inline int lineSize (int maxLength = KMAXINT) const - { - return indexAfter ('\n', maxLength); - } - - inline bool canReadLine () const - { - return lineSize () != -1; - } - - int read (char *data, int maxLength) - { - int bytesToRead = qMin (size (), maxLength); - int readSoFar = 0; - while (readSoFar < bytesToRead) - { - const char *ptr = readPointer (); - int bs = qMin (bytesToRead - readSoFar, readSize ()); - memcpy (data + readSoFar, ptr, bs); - readSoFar += bs; - free (bs); - } - return readSoFar; - } - - int readLine (char *data, int maxLength) - { - return read (data, lineSize (qMin (maxLength, size ()))); - } - -private: - QLinkedList < QByteArray > buffers; - int head, tail; - int totalSize; -}; - -struct KPtyDevicePrivate:public KPtyPrivate -{ - Q_DECLARE_PUBLIC (KPtyDevice) - KPtyDevicePrivate (KPty * parent):KPtyPrivate (parent), - emittedReadyRead (false), emittedBytesWritten (false), - readNotifier (0), writeNotifier (0) - { - } - - bool _k_canRead (); - bool _k_canWrite (); - - bool doWait (int msecs, bool reading); - void finishOpen (QIODevice::OpenMode mode); - - bool emittedReadyRead; - bool emittedBytesWritten; - QSocketNotifier *readNotifier; - QSocketNotifier *writeNotifier; - KRingBuffer readBuffer; - KRingBuffer writeBuffer; -}; - -#endif diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/LinuxTerminalEmulation.cpp --- a/gui/src/terminal/LinuxTerminalEmulation.cpp Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,253 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - - -#include "LinuxTerminalEmulation.h" - -LinuxTerminalEmulation::LinuxTerminalEmulation () - : TerminalEmulation () -{ - int fdm, fds; - openpty (&fdm, &fds, 0, 0, 0); - - dup2 (fds, STDIN_FILENO); - dup2 (fds, STDOUT_FILENO); - dup2 (fds, STDERR_FILENO); - - m_pty = new KPtyDevice (); - m_pty->open (fdm); - connect (m_pty, SIGNAL(readyRead ()), - this, SLOT (handleReadyRead ())); -} - -LinuxTerminalEmulation::~LinuxTerminalEmulation () -{ - m_pty->close (); -} - -void LinuxTerminalEmulation::processKeyEvent (QKeyEvent *keyEvent) -{ - switch (keyEvent->key ()) - { - case Qt::Key_PageUp: - //if (verticalScrollBar ()) - // verticalScrollBar ()->setValue (verticalScrollBar ()->value () - 10); - return; - case Qt::Key_PageDown: - //if (verticalScrollBar ()) - // verticalScrollBar ()->setValue (verticalScrollBar ()->value () + 10); - return; - - case Qt::Key_Up: - m_pty->write ("\033OA"); - break; - - case Qt::Key_Down: - m_pty->write ("\033OB"); - break; - - case Qt::Key_Right: - m_pty->write ("\033OC"); - break; - - case Qt::Key_Left: - m_pty->write ("\033OF"); - break; - - case Qt::Key_C: - if (keyEvent->modifiers() & Qt::ControlModifier) - { - // TODO: Lookup and implement Control + C. - } - else - { - m_pty->write (keyEvent->text ().toAscii ()); - } - break; - - case Qt::Key_V: - if (keyEvent->modifiers() & Qt::ControlModifier) - { - // TODO: Lookup and implement Control + V. - } - else - { - m_pty->write (keyEvent->text ().toAscii ()); - } - break; - - case Qt::Key_D: - if (keyEvent->modifiers() & Qt::ControlModifier) - { - // Do not send EOT, because this will crash - // the program. - } - else - { - m_pty->write (keyEvent->text ().toAscii ()); - } - break; - - default: - m_pty->write (keyEvent->text ().toAscii ()); - break; - } - keyEvent->accept (); -} - -void -LinuxTerminalEmulation::transmitText (const QString &text) -{ - m_pty->write (text.toLocal8Bit ()); -} - -void -LinuxTerminalEmulation::handleReadyRead () -{ - QByteArray data = m_pty->readAll (); - - data.replace("\033[K", ""); - data.replace("\033[9", ""); - data.replace("\033[A", ""); - data.replace("\033[B", ""); - data.replace("\033[C", ""); - data.replace("\033[D", ""); - data.replace("\033[1", ""); - data.replace("\033[H", ""); - data.replace("\033[2J", ""); - int position; - QTextCursor tc = m_terminal->textCursor (); - tc.beginEditBlock (); - - // Decode data into cursor actions. - foreach(QChar character, data) - { - unsigned short unicode = character.unicode (); - switch (unicode) - { - case 0: // Null (NUL) - qDebug ("NUL"); - break; - case 1: // Start Of Heading (SOH) - qDebug ("SOH"); - break; - case 2: // Start Of Text (STX) - qDebug ("STX"); - break; - case 3: // End Of Text (ETX) - qDebug ("ETX"); - break; - case 4: // End Of Transmission (EOT) - qDebug ("EOT"); - break; - case 5: // Enquiry (ENQ) - qDebug ("ENQ"); - break; - case 6: // Acknowledgement (ACK) - qDebug ("ACK"); - break; - case 7: // Bell (BEL) - m_terminal->bell (); - break; - case 8: // Backspace (BS) - tc.deletePreviousChar (); - break; - case 9: // Horizontal Tab (HT) - qDebug ("HT"); - break; - case 10: // Line Feed (LF) - position = tc.position (); - tc.movePosition (QTextCursor::EndOfLine); - tc.insertText ("\n"); - tc.setPosition (position); - tc.movePosition (QTextCursor::Down); - break; - case 11: // Vertical Tab (VT) - qDebug ("VT"); - break; - case 12: // Form Feed (FF) - qDebug ("FF"); - break; - case 13: // Carriage Return (CR) - tc.movePosition (QTextCursor::StartOfLine, QTextCursor::KeepAnchor); - break; - case 14: // Shift Out (SO) - qDebug ("SO"); - break; - case 15: // Shift In (SI) - qDebug ("SI"); - break; - case 16: // Data Link Escape (DLE) - qDebug ("DLE"); - break; - case 17: // Device Control 1 (DC1, XON) - qDebug ("DC1"); - break; - case 18: // Device Control 2 (DC2) - qDebug ("DC2"); - break; - case 19: // Device Control 3 (DC3, XOFF) - qDebug ("DC3"); - break; - case 20: // Device Control 4 (DC4) - qDebug ("DC4"); - break; - case 21: // Negative Acknowledgement (NAK) - qDebug ("NAK"); - break; - case 22: // Synchronous Idle (SYN) - qDebug ("SYN"); - break; - case 23: // End Of Transmission Block (ETB) - qDebug ("ETB"); - break; - case 24: // Cancel (CAN) - qDebug ("CAN"); - break; - case 25: // End of Medium (EM) - qDebug ("EM"); - break; - case 26: // Substitute (SUB) - qDebug ("SUB"); - break; - case 27: // Escape (ESC) - qDebug ("ESC"); - break; - case 28: // File Separator (FS) - qDebug ("FS"); - break; - case 29: // Group Separator (GS) - qDebug ("GS"); - break; - case 30: // Record Separator (RS) - qDebug ("RS"); - break; - case 31: // Unit Separator (US) - qDebug ("US"); - break; - case 127: // Delete (DEL) - qDebug ("DEL"); - break; - default: - tc.insertText (character); - break; - } - } - - tc.endEditBlock (); - m_terminal->setTextCursor (tc); -} diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/LinuxTerminalEmulation.h --- a/gui/src/terminal/LinuxTerminalEmulation.h Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#ifndef LINUXTERMINALEMULATION_H -#define LINUXTERMINALEMULATION_H - -#include "TerminalEmulation.h" -#include "KPtyDevice.h" - -/** - * @class LinuxTerminalEmulation - * Implements the terminal emulation on Linux and Unix as well as Unix-like - * systems, like MacOSX. - */ -class LinuxTerminalEmulation : public TerminalEmulation -{ - Q_OBJECT -public: - LinuxTerminalEmulation (); - ~LinuxTerminalEmulation (); - - /** @reimp */ - void processKeyEvent (QKeyEvent *keyEvent); - - /** @reimp */ - void transmitText (const QString &text); - -private slots: - void handleReadyRead (); - -private: - /** KPtyDevice from the Konsole sources. */ - KPtyDevice *m_pty; -}; - -#endif // LINUXTERMINALEMULATION_H diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/TerminalEmulation.cpp --- a/gui/src/terminal/TerminalEmulation.cpp Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "TerminalEmulation.h" - -#ifdef Q_OS_UNIX - #include "LinuxTerminalEmulation.h" -#endif - -TerminalEmulation *TerminalEmulation::newTerminalEmulation (Terminal *terminal) -{ -#ifdef Q_OS_UNIX - TerminalEmulation *terminalEmulation = new LinuxTerminalEmulation (); - terminalEmulation->m_terminal = terminal; - return terminalEmulation; -#endif -#ifdef Q_OS_WIN - // TODO: Implement on Windows. - return 0; -#endif -} - -TerminalEmulation::TerminalEmulation () - : QObject () -{ -} diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/TerminalEmulation.h --- a/gui/src/terminal/TerminalEmulation.h Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#ifndef TERMINALEMULATION_H -#define TERMINALEMULATION_H - -#include -#include -#include -#include - -/** - * @class Terminal - * Interface for a terminal. This is the counterpart for the terminal - * emulation and must be implemented by the view part. It defines a basic set - * of actions that must be supported by the view part. - */ -class Terminal -{ - public: - /** Queries the current text cursor. - * @return The current text cursor. */ - virtual QTextCursor textCursor () = 0; - - /** Sets the given text cursor. - * @param cursor New text cursor to set. */ - virtual void setTextCursor (const QTextCursor& cursor) = 0; - - /** Called whenever the bell has been activated. */ - virtual void bell () = 0; -}; - -/** - * @class TerminalEmulation - * Interface for any terminal emulation. It's the counterpart to the Terminal. - */ -class TerminalEmulation : public QObject -{ - Q_OBJECT -public: - /** Produces a new terminal emulation for a specific terminal. - * @param terminal The terminal associated with the emulation - * @return Terminal emulation. */ - static TerminalEmulation *newTerminalEmulation (Terminal *terminal); - - TerminalEmulation (); - virtual ~TerminalEmulation () {} - - /** Processes an incoming key event. - * @param keyEvent Key event to process. */ - virtual void processKeyEvent (QKeyEvent *keyEvent) = 0; - - /** Transmit a block of text straight to the terminal emulation. - * @param text Text to be transmitted. */ - virtual void transmitText (const QString& text) = 0; -protected: - /** The terminal this terminal emulation is connected to. */ - Terminal *m_terminal; -}; - -#endif // TERMINALEMULATION_H diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/win32/QConsole --- a/gui/src/terminal/win32/QConsole Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -#include "QConsole.h" diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/win32/QConsole.cpp --- a/gui/src/terminal/win32/QConsole.cpp Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,873 +0,0 @@ -/* - -Copyright (C) 2011 Michael Goffioul. - -This file is part of QConsole. - -Foobar is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -QConsole is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include "QConsole.h" -#include "QConsoleColors.h" - -// Uncomment to log activity to LOGFILENAME -// #define DEBUG_QCONSOLE -#define LOGFILENAME "QConsole.log" -// Uncomment to create hidden console window -#define HIDDEN_CONSOLE - -////////////////////////////////////////////////////////////////////////////// - -class QConsoleView : public QWidget -{ -public: - QConsoleView (QConsole* parent = 0) : QWidget (parent), q (parent) { } - ~QConsoleView (void) { } - -protected: - void paintEvent (QPaintEvent* event) { q->viewPaintEvent (this, event); } - void resizeEvent (QResizeEvent* event) { q->viewResizeEvent (this, event); } - -private: - QConsole* q; -}; - -////////////////////////////////////////////////////////////////////////////// - -class QConsoleThread : public QThread -{ -public: - QConsoleThread (QConsole* console) : QThread (console), q (console) { } - -protected: - void run (void) - { q->start (); } - -private: - QConsole* q; -}; - -////////////////////////////////////////////////////////////////////////////// - -class QConsolePrivate -{ - friend class QConsole; - -public: - QConsolePrivate (QConsole* parent, const QString& cmd = QString ()); - ~QConsolePrivate (void); - - void updateConsoleSize (bool sync = false); - void syncConsoleParameters (void); - void grabConsoleBuffer (CHAR_INFO* buf = 0); - void updateScrollBar (void); - void setScrollValue (int value); - void updateConsoleView (bool grab = true); - void monitorConsole (void); - void startCommand (void); - void sendConsoleText (const QString& s); - - void log (const char* fmt, ...); - - void closeStandardIO (int fd, DWORD stdHandleId, const char* name); - void setupStandardIO (DWORD stdHandleId, int fd, const char* name, - const char* devName); - -private: - QConsole* q; - -private: - QFont m_font; - QColor m_backgroundColor; - QString m_command; - QConsoleColors m_colors; - bool m_inWheelEvent; - QString m_title; - - QSize m_charSize; - QSize m_bufferSize; - QRect m_consoleRect; - QPoint m_cursorPos; - - HANDLE m_stdOut; - HWND m_consoleWindow; - CHAR_INFO* m_buffer; - CHAR_INFO* m_tmpBuffer; - HANDLE m_process; - - QConsoleView* m_consoleView; - QScrollBar* m_scrollBar; - QTimer* m_consoleWatcher; - QConsoleThread *m_consoleThread; -}; - -////////////////////////////////////////////////////////////////////////////// - -QConsolePrivate::QConsolePrivate (QConsole* parent, const QString& cmd) - : q (parent), m_command (cmd), m_process (NULL), m_inWheelEvent (false) -{ - log (NULL); - - // Possibly detach from any existing console - log ("Detaching from existing console (if any)...\n"); - FreeConsole (); - log ("Closing standard IO...\n"); - closeStandardIO (0, STD_INPUT_HANDLE, "STDIN"); - closeStandardIO (1, STD_OUTPUT_HANDLE, "STDOUT"); - closeStandardIO (2, STD_ERROR_HANDLE, "STDERR"); - -#ifdef HIDDEN_CONSOLE - HWINSTA hOrigSta, hNewSta; - - // Create new (hidden) console - hOrigSta = GetProcessWindowStation (); - hNewSta = CreateWindowStation (NULL, 0, GENERIC_ALL, NULL); - log ("Current Windows station: %p.\nNew Windows station: %p.\n", hOrigSta, - hNewSta); - if (! SetProcessWindowStation (hNewSta)) - log ("Failed to switch to new Windows station.\n"); -#endif - if (! AllocConsole ()) - log ("Failed to create new console.\n"); -#ifdef HIDDEN_CONSOLE - if (! SetProcessWindowStation (hOrigSta)) - log ("Failed to restore original Windows station.\n"); - if (! CloseWindowStation (hNewSta)) - log ("Failed to close new Windows station.\n"); -#endif - - log ("New (hidden) console created.\n"); - - setupStandardIO (STD_INPUT_HANDLE, 0, "STDIN", "CONIN$"); - setupStandardIO (STD_OUTPUT_HANDLE, 1, "STDOUT", "CONOUT$"); - setupStandardIO (STD_ERROR_HANDLE, 2, "STDERR", "CONOUT$"); - - log ("Standard input/output/error set up.\n"); - - *stdin = *(fdopen (0, "rb")); - *stdout = *(fdopen (1, "wb")); - *stderr = *(fdopen (2, "wb")); - - log ("POSIX standard streams created.\n"); - - setvbuf (stdin, NULL, _IONBF, 0); - setvbuf (stdout, NULL, _IONBF, 0); - setvbuf (stderr, NULL, _IONBF, 0); - - log ("POSIX standard stream buffers adjusted.\n"); - - HANDLE hStdOut = GetStdHandle (STD_OUTPUT_HANDLE); - - log ("Console allocated: hStdOut: %p\n", hStdOut); - - m_stdOut = hStdOut; - m_consoleWindow = GetConsoleWindow (); - - // In case the console window hasn't been created hidden... - ShowWindow (m_consoleWindow, SW_HIDE); - - CONSOLE_SCREEN_BUFFER_INFO sbi; - - GetConsoleScreenBufferInfo (hStdOut, &sbi); - m_bufferSize = QSize (sbi.dwSize.X, qMax (sbi.dwSize.Y, (SHORT)500)); - m_consoleRect = QRect (sbi.srWindow.Left, sbi.srWindow.Top, - sbi.srWindow.Right - sbi.srWindow.Left + 1, - sbi.srWindow.Bottom - sbi.srWindow.Top + 1); - m_cursorPos = QPoint (sbi.dwCursorPosition.X, sbi.dwCursorPosition.Y); - - log ("Initial console parameters:\n"); - log (" buffer size: %d x %d\n", m_bufferSize.width (), - m_bufferSize.height ()); - log (" window: (%d, %d) -> (%d, %d) [%d x %d]\n", - m_consoleRect.left (), m_consoleRect.top (), - m_consoleRect.right (), m_consoleRect.bottom (), - m_consoleRect.width (), m_consoleRect.height ()); - - wchar_t titleBuf[260]; - GetConsoleTitleW (titleBuf, sizeof (titleBuf)); - q->setWindowTitle (QString::fromWCharArray (titleBuf)); - - m_font.setFamily ("Lucida Console"); - m_font.setPointSize (9); - m_font.setStyleHint (QFont::TypeWriter); - m_backgroundColor = Qt::black; - - m_buffer = m_tmpBuffer = 0; - - m_consoleView = new QConsoleView (parent); - m_scrollBar = new QScrollBar (Qt::Vertical, parent); - - QHBoxLayout* l = new QHBoxLayout (parent); - l->setContentsMargins (0, 0, 0, 0); - l->setSpacing (0); - l->addWidget (m_consoleView, 1); - l->addWidget (m_scrollBar, 0); - - m_consoleView->setPalette (QPalette (m_backgroundColor)); - m_consoleView->setAutoFillBackground (true); - m_consoleView->setFont (m_font); - parent->setFocusPolicy (Qt::StrongFocus); - parent->winId (); - - updateScrollBar (); - - m_consoleWatcher = new QTimer (parent); - m_consoleWatcher->setInterval (10); - m_consoleWatcher->setSingleShot (false); - - QObject::connect (m_scrollBar, SIGNAL (valueChanged (int)), - q, SLOT (scrollValueChanged (int))); - QObject::connect (m_consoleWatcher, SIGNAL (timeout (void)), - q, SLOT (monitorConsole (void))); - - m_consoleWatcher->start (); - - if (m_command.isEmpty ()) - m_consoleThread = 0; - else - { - m_consoleThread = new QConsoleThread (q); - QObject::connect (m_consoleThread, SIGNAL (finished (void)), - q, SIGNAL (terminated (void))); - m_consoleThread->start (); - } -} - -////////////////////////////////////////////////////////////////////////////// - -QConsolePrivate::~QConsolePrivate (void) -{ - if (m_consoleThread && m_consoleThread->isRunning () && m_process) - { - TerminateProcess (m_process, (UINT)-1); - m_consoleThread->wait (); - } - if (m_buffer) - delete [] m_buffer; - if (m_tmpBuffer) - delete [] m_tmpBuffer; -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::setupStandardIO (DWORD stdHandleId, int targetFd, - const char* name, const char* devName) -{ - log ("Opening %s...\n", devName); - - int fd = open (devName, _O_RDWR | _O_BINARY); - - if (fd != -1) - { - if (fd != targetFd) - { - log ("Opened %s is not at target file descriptor %d, " - "duplicating...\n", name, targetFd); - if (dup2 (fd, targetFd) == -1) - log ("Failed to duplicate file descriptor: errno=%d.\n", errno); - if (close (fd) == -1) - log ("Failed to close original file descriptor: errno=%d.\n", - errno); - } - else - log ("%s opened and assigned to file descriptor %d.\n", devName, fd); - if (! SetStdHandle (stdHandleId, (HANDLE) _get_osfhandle (targetFd))) - log ("Failed to re-assign %s: error=%08x.\n", name, GetLastError ()); - } - else - log ("Failed to open %s: errno=%d.\n", devName, errno); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::closeStandardIO (int fd, DWORD stdHandleId, - const char* name) -{ - if (close (fd) == -1) - log ("Failed to close file descriptor %d: errno=%d.\n", fd, errno); - if (! CloseHandle (GetStdHandle (stdHandleId))) - log ("Failed to close Win32 %s: error=%08x.\n", name, GetLastError ()); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::log (const char* fmt, ...) -{ -#ifdef DEBUG_QCONSOLE - if (fmt) - { - va_list l; - FILE* flog = fopen (LOGFILENAME, "ab"); - - va_start (l, fmt); - vfprintf (flog, fmt, l); - va_end (l); - fclose (flog); - } - else - { - // Special case to re-initialize the log file - FILE* flog = fopen (LOGFILENAME, "w"); - fclose (flog); - } -#endif -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::updateConsoleSize (bool sync) -{ - QFontMetrics fm (m_font); - QSize winSize = m_consoleView->size (); - - m_charSize.rwidth () = fm.maxWidth (); - m_charSize.rheight () = fm.lineSpacing (); - - m_consoleRect.setWidth (winSize.width () / fm.maxWidth ()); - m_consoleRect.setHeight (winSize.height () / fm.lineSpacing ()); - - m_bufferSize.rwidth () = m_consoleRect.width (); - m_bufferSize.rheight () = qMax (m_bufferSize.height (), - m_consoleRect.height ()); - - m_consoleRect.moveLeft (0); - if (m_consoleRect.bottom () >= m_bufferSize.height ()) - m_consoleRect.moveTop (m_bufferSize.height () - m_consoleRect.height ()); - - log ("Console resized:\n"); - log (" widget size: %d x %d\n", winSize.width (), winSize.height ()); - log (" buffer size: %d x %d\n", m_bufferSize.width (), - m_bufferSize.height ()); - log (" window: (%d, %d) -> (%d, %d) [%d x %d]\n", - m_consoleRect.left (), m_consoleRect.top (), - m_consoleRect.right (), m_consoleRect.bottom (), - m_consoleRect.width (), m_consoleRect.height ()); - - if (sync) - syncConsoleParameters (); - - updateScrollBar (); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::syncConsoleParameters (void) -{ - CONSOLE_SCREEN_BUFFER_INFO sbi; - HANDLE hStdOut = m_stdOut; - - GetConsoleScreenBufferInfo (hStdOut, &sbi); - - COORD bs; - SMALL_RECT sr; - - bs.X = sbi.dwSize.X; - bs.Y = m_bufferSize.height (); - sr.Left = sbi.srWindow.Left; - sr.Right = sbi.srWindow.Right; - sr.Top = m_consoleRect.top (); - sr.Bottom = m_consoleRect.bottom (); - - if (bs.Y > sbi.dwSize.Y) - { - SetConsoleScreenBufferSize (hStdOut, bs); - SetConsoleWindowInfo (hStdOut, TRUE, &sr); - } - else - { - SetConsoleWindowInfo (hStdOut, TRUE, &sr); - SetConsoleScreenBufferSize (hStdOut, bs); - } - - bs.X = m_bufferSize.width (); - sr.Left = m_consoleRect.left (); - sr.Right = m_consoleRect.right (); - - if (bs.X > sbi.dwSize.X) - { - SetConsoleScreenBufferSize (hStdOut, bs); - SetConsoleWindowInfo (hStdOut, TRUE, &sr); - } - else - { - SetConsoleWindowInfo (hStdOut, TRUE, &sr); - SetConsoleScreenBufferSize (hStdOut, bs); - } - - log ("Sync'ing console parameters:\n"); - log (" buffer size: %d x %d\n", bs.X, bs.Y); - log (" window: (%d, %d) -> (%d, %d)\n", - sr.Left, sr.Top, sr.Right, sr.Bottom); - - if (m_buffer) - delete [] m_buffer; - if (m_tmpBuffer) - delete [] m_tmpBuffer; - - int bufSize = m_consoleRect.width () * m_consoleRect.height (); - - m_buffer = new CHAR_INFO[bufSize]; - m_tmpBuffer = new CHAR_INFO[bufSize]; -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::grabConsoleBuffer (CHAR_INFO* buf) -{ - COORD bs, bc; - SMALL_RECT r; - - bs.X = m_consoleRect.width (); - bs.Y = m_consoleRect.height (); - bc.X = 0; - bc.Y = 0; - - r.Left = m_consoleRect.left (); - r.Top = m_consoleRect.top (); - r.Right = m_consoleRect.right (); - r.Bottom = m_consoleRect.bottom (); - - if (! ReadConsoleOutput (m_stdOut, (buf ? buf : m_buffer), bs, bc, &r)) - qCritical ("cannot read console output"); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::updateScrollBar (void) -{ - m_scrollBar->setMinimum (0); - if (m_bufferSize.height () > m_consoleRect.height ()) - m_scrollBar->setMaximum (m_bufferSize.height () - m_consoleRect.height ()); - else - m_scrollBar->setMaximum (0); - m_scrollBar->setSingleStep (1); - m_scrollBar->setPageStep (m_consoleRect.height ()); - m_scrollBar->setValue (m_consoleRect.top ()); - - log ("Scrollbar parameters updated: %d/%d/%d/%d\n", - m_scrollBar->minimum (), m_scrollBar->maximum (), - m_scrollBar->singleStep (), m_scrollBar->pageStep ()); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::setScrollValue (int value) -{ - if (value == m_consoleRect.top ()) - return; - - SMALL_RECT r; - HANDLE hStdOut = m_stdOut; - - if (value + m_consoleRect.height () > m_bufferSize.height ()) - value = m_bufferSize.height () - m_consoleRect.height (); - - r.Left = m_consoleRect.left (); - r.Top = value; - r.Right = m_consoleRect.right (); - r.Bottom = value + m_consoleRect.height () - 1; - - log ("Scrolling window: (%d, %d) -> (%d, %d) [%d x %d]\n", - r.Left, r.Top, r.Right, r.Bottom, - r.Right - r.Left + 1, r.Bottom - r.Top + 1); - - if (SetConsoleWindowInfo (hStdOut, TRUE, &r)) - { - m_consoleRect.moveTop (value); - updateConsoleView (); - } -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::updateConsoleView (bool grab) -{ - if (grab) - grabConsoleBuffer (); - m_consoleView->update (); - m_consoleWatcher->start (); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::monitorConsole (void) -{ - CONSOLE_SCREEN_BUFFER_INFO sbi; - HANDLE hStdOut = GetStdHandle (STD_OUTPUT_HANDLE); - - static wchar_t titleBuf[260]; - - GetConsoleTitleW (titleBuf, sizeof (titleBuf)); - QString title = QString::fromWCharArray (titleBuf); - - if (title != m_title) - { - q->setWindowTitle (title); - emit q->titleChanged (title); - } - - if (GetConsoleScreenBufferInfo (hStdOut, &sbi)) - { - if (m_bufferSize.width () != sbi.dwSize.X - || m_bufferSize.height () != sbi.dwSize.Y) - { - // Buffer size changed - m_bufferSize.rwidth () = sbi.dwSize.X; - m_bufferSize.rheight () = sbi.dwSize.Y; - updateScrollBar (); - } - - if (m_cursorPos.x () != sbi.dwCursorPosition.X - || m_cursorPos.y () != sbi.dwCursorPosition.Y) - { - // Cursor position changed - m_consoleView->update - ((m_cursorPos.x () - sbi.srWindow.Left) * m_charSize.width (), - (m_cursorPos.y () - sbi.srWindow.Top) * m_charSize.height (), - m_charSize.width (), m_charSize.height ()); - m_cursorPos.rx () = sbi.dwCursorPosition.X; - m_cursorPos.ry () = sbi.dwCursorPosition.Y; - m_consoleView->update - ((m_cursorPos.x () - sbi.srWindow.Left) * m_charSize.width (), - (m_cursorPos.y () - sbi.srWindow.Top) * m_charSize.height (), - m_charSize.width (), m_charSize.height ()); - } - - if (m_consoleRect.left () != sbi.srWindow.Left - || m_consoleRect.right () != sbi.srWindow.Right - || m_consoleRect.top () != sbi.srWindow.Top - || m_consoleRect.bottom () != sbi.srWindow.Bottom) - { - // Console window changed - m_consoleRect = QRect (sbi.srWindow.Left, sbi.srWindow.Top, - sbi.srWindow.Right - sbi.srWindow.Left + 1, - sbi.srWindow.Bottom - sbi.srWindow.Top + 1); - updateScrollBar (); - updateConsoleView (); - return; - } - - if (m_tmpBuffer && m_buffer) - { - grabConsoleBuffer (m_tmpBuffer); - if (memcmp (m_tmpBuffer, m_buffer, - sizeof (CHAR_INFO) * m_consoleRect.width () * - m_consoleRect.height ())) - { - // FIXME: compute the area to update based on the - // difference between the 2 buffers. - qSwap (m_buffer, m_tmpBuffer); - updateConsoleView (false); - } - } - } -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::startCommand (void) -{ - if (! m_command.isEmpty ()) - { - STARTUPINFO si; - PROCESS_INFORMATION pi; - - ZeroMemory (&si, sizeof (si)); - si.cb = sizeof (si); - ZeroMemory (&pi, sizeof (pi)); - - if (CreateProcessW (NULL, - (LPWSTR)m_command.unicode (), - NULL, - NULL, - TRUE, - 0, - NULL, - NULL, - &si, - &pi)) - { - CloseHandle (pi.hThread); - m_process = pi.hProcess; - WaitForSingleObject (m_process, INFINITE); - CloseHandle (m_process); - m_process = NULL; - } - } -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsolePrivate::sendConsoleText (const QString& s) -{ - // Send the string in chunks of 512 characters. Each character is - // translated into an equivalent keypress event. - -#define TEXT_CHUNK_SIZE 512 - - int len = s.length (); - INPUT_RECORD events[TEXT_CHUNK_SIZE]; - DWORD nEvents = 0, written; - HANDLE hStdIn = GetStdHandle (STD_INPUT_HANDLE); - - ZeroMemory (events, sizeof (events)); - - for (int i = 0; i < len; i++) - { - QChar c = s.at (i); - - if (c == L'\r' || c == L'\n') - { - if (c == L'\r' && i < (len - 1) && s.at (i+1) == L'\n') - i++; - if (nEvents) - { - WriteConsoleInput (hStdIn, events, nEvents, &written); - nEvents = 0; - ZeroMemory (events, sizeof (events)); - } - PostMessage (m_consoleWindow, WM_KEYDOWN, VK_RETURN, 0x001C0001); - PostMessage (m_consoleWindow, WM_KEYDOWN, VK_RETURN, 0xC01C0001); - } - else - { - events[nEvents].EventType = KEY_EVENT; - events[nEvents].Event.KeyEvent.bKeyDown = TRUE; - events[nEvents].Event.KeyEvent.wRepeatCount = 1; - events[nEvents].Event.KeyEvent.wVirtualKeyCode = - LOBYTE (VkKeyScan (c.unicode ())); - events[nEvents].Event.KeyEvent.wVirtualScanCode = 0; - events[nEvents].Event.KeyEvent.uChar.UnicodeChar = c.unicode (); - events[nEvents].Event.KeyEvent.dwControlKeyState = 0; - nEvents++; - } - - if (nEvents == TEXT_CHUNK_SIZE - || (nEvents > 0 && i == (len - 1))) - { - WriteConsoleInput (hStdIn, events, nEvents, &written); - nEvents = 0; - ZeroMemory (events, sizeof (events)); - } - } -} - -////////////////////////////////////////////////////////////////////////////// - -QConsole::QConsole (QWidget* parent) - : d (new QConsolePrivate (this)) -{ -} - -////////////////////////////////////////////////////////////////////////////// - -QConsole::QConsole (const QString& cmd, QWidget* parent) - : d (new QConsolePrivate (this, cmd)) -{ -} - -////////////////////////////////////////////////////////////////////////////// - -QConsole::~QConsole (void) -{ - delete d; -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsole::viewResizeEvent (QConsoleView*, QResizeEvent*) -{ - d->updateConsoleSize (true); - d->grabConsoleBuffer (); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsole::viewPaintEvent (QConsoleView* w, QPaintEvent* event) -{ - QPainter p (w); - int cw = d->m_charSize.width (), ch = d->m_charSize.height (); - int ascent, stride, cx1, cy1, cx2, cy2, x, y; - WORD attr = 0; - QString s; - bool hasChar = false; - - QRect updateRect = event->rect (); - - cx1 = updateRect.left () / cw; - cy1 = updateRect.top () / ch; - cx2 = qMin (d->m_consoleRect.width () - 1, updateRect.right () / cw); - cy2 = qMin (d->m_consoleRect.height () - 1, updateRect.bottom () / ch); - - if (cx1 > d->m_consoleRect.width () - 1 - || cy1 > d->m_consoleRect.height () - 1) - return; - - p.setFont (d->m_font); - p.setPen (Qt::black); - - ascent = p.fontMetrics ().ascent (); - stride = d->m_consoleRect.width (); - - s.reserve (cx2 - cx1 + 1); - y = ascent + cy1 * ch;; - - for (int j = cy1; j <= cy2; j++, y += ch) - { - // Reset string buffer and starting X coordinate - s.clear (); - hasChar = false; - x = cx1 * cw; - - for (int i = cx1; i <= cx2; i++) - { - CHAR_INFO* ci = &(d->m_buffer[stride*j+i]); - - if ((ci->Attributes & 0x00ff) != attr) - { - // Character attributes changed - if (! s.isEmpty ()) - { - // String buffer not empty -> draw it - if (hasChar || (attr & 0x00f0)) - { - if (attr & 0x00f0) - p.fillRect (x, y-ascent, s.length () * cw, ch, - p.brush ()); - p.drawText (x, y, s); - } - x += (s.length () * cw); - s.clear (); - hasChar = false; - } - // Update current pen and store current attributes - // FIXME: what about background? - attr = (ci->Attributes & 0x00ff); - p.setPen (d->m_colors[attr & 0x000f]); - p.setBrush (d->m_colors[(attr >> 4) & 0x000f]); - } - - // Append current character to the string buffer - s.append (ci->Char.UnicodeChar); - if (ci->Char.UnicodeChar != L' ') - hasChar = true; - } - - if (! s.isEmpty () && (hasChar || (attr & 0x00f0))) - { - // Line end reached, but string buffer not empty -> draw it - // No need to update s or x, they will be reset on the next - // for-loop iteration - if (attr & 0x00f0) - p.fillRect (x, y-ascent, s.length () * cw, ch, p.brush ()); - p.drawText (x, y, s); - } - } - - // Draw cursor - p.setCompositionMode (QPainter::RasterOp_SourceXorDestination); - p.fillRect ((d->m_cursorPos.x () - d->m_consoleRect.x ()) * cw, - (d->m_cursorPos.y () - d->m_consoleRect.y ()) * ch, - cw, ch, d->m_colors[7]); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsole::wheelEvent (QWheelEvent* event) -{ - if (! d->m_inWheelEvent) - { - // Forward to the scrollbar (avoid recursion) - d->m_inWheelEvent = true; - QApplication::sendEvent (d->m_scrollBar, event); - d->m_inWheelEvent = false; - } -} - -////////////////////////////////////////////////////////////////////////////// - -bool QConsole::winEvent (MSG* msg, long* result) -{ - switch (msg->message) - { - case WM_KEYDOWN: - case WM_KEYUP: - //case WM_CHAR: - // Forward Win32 message to the console window - PostMessage (d->m_consoleWindow, - msg->message, - msg->wParam, - msg->lParam); - result = 0; - return true; - default: - return false; - } -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsole::scrollValueChanged (int value) -{ - d->setScrollValue (value); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsole::monitorConsole (void) -{ - d->monitorConsole (); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsole::focusInEvent (QFocusEvent* event) -{ - QWidget::focusInEvent (event); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsole::start (void) -{ - d->startCommand (); -} - -////////////////////////////////////////////////////////////////////////////// - -void QConsole::sendText (const QString& s) -{ - d->sendConsoleText (s); -} diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/win32/QConsole.h --- a/gui/src/terminal/win32/QConsole.h Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* - -Copyright (C) 2011 Michael Goffioul. - -This file is part of QConsole. - -Foobar is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -QConsole is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . - -*/ - -#ifndef __QConsole_h__ -#define __QConsole_h__ 1 - -#include - -class QFocusEvent; -class QKeyEvent; -class QPaintEvent; -class QResizeEvent; -class QWheelEvent; - -class QConsolePrivate; -class QConsoleThread; -class QConsoleView; - -////////////////////////////////////////////////////////////////////////////// - -class QConsole : public QWidget -{ - Q_OBJECT - friend class QConsolePrivate; - friend class QConsoleThread; - friend class QConsoleView; - -public: - QConsole (QWidget* parent = 0); - QConsole (const QString& cmd, QWidget* parent = 0); - ~QConsole (void); - - void sendText (const QString& s); - -signals: - void terminated (void); - void titleChanged (const QString&); - -protected: - void viewPaintEvent (QConsoleView*, QPaintEvent*); - void viewResizeEvent (QConsoleView*, QResizeEvent*); - void wheelEvent (QWheelEvent*); - void focusInEvent (QFocusEvent*); - bool winEvent (MSG*, long*); - virtual void start (void); - -private slots: - void scrollValueChanged (int value); - void monitorConsole (void); - -private: - QConsolePrivate* d; -}; - -////////////////////////////////////////////////////////////////////////////// - -#endif // __QConsole_h__ diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/win32/QConsoleColors.cpp --- a/gui/src/terminal/win32/QConsoleColors.cpp Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - -Copyright (C) 2011 Michael Goffioul. - -This file is part of QConsole. - -Foobar is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -QConsole is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . - -*/ - -#define WIN32_LEAN_AND_MEAN -#include - -#include "QConsoleColors.h" - -////////////////////////////////////////////////////////////////////////////// - -QConsoleColors::QConsoleColors (void) - : QMap () -{ - (*this)[0] = Qt::black; - (*this)[1] = Qt::darkBlue; - (*this)[2] = Qt::darkGreen; - (*this)[3] = Qt::darkCyan; - (*this)[4] = Qt::darkRed; - (*this)[5] = Qt::darkMagenta; - (*this)[6] = Qt::darkYellow; - (*this)[7] = Qt::lightGray; - (*this)[8] = Qt::darkGray; - (*this)[9] = Qt::blue; - (*this)[10] = Qt::green; - (*this)[11] = Qt::cyan; - (*this)[12] = Qt::red; - (*this)[13] = Qt::magenta; - (*this)[14] = Qt::yellow; - (*this)[15] = Qt::white; -} diff -r 556f8f40112e -r 8dfa333f1130 gui/src/terminal/win32/QConsoleColors.h --- a/gui/src/terminal/win32/QConsoleColors.h Mon Jan 30 01:54:18 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - -Copyright (C) 2011 Michael Goffioul. - -This file is part of QConsole. - -Foobar is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -QConsole is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar. If not, see . - -*/ - -#ifndef __QConsoleColors_h__ -#define __QConsoleColors_h__ 1 - -#include -#include - -////////////////////////////////////////////////////////////////////////////// - -class QConsoleColors : public QMap -{ -public: - QConsoleColors (void); -}; - -////////////////////////////////////////////////////////////////////////////// - -#endif // __QConsoleColors_h__