3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
6 #include <qsocketnotifier.h>
7 #include <qpopupmenu.h>
10 #include <kglobalsettings.h>
21 #include <unistd.h> /* open, close, etc. */
23 #ifdef HAVE_SYS_IOCTL_H
24 #include <sys/ioctl.h>
26 #ifdef HAVE_SYS_STAT_H
30 #include <pty.h> /* openpty */
45 ::fcntl(m_masterfd
, F_SETFL
, O_NDELAY
);
46 m_outNotifier
= new QSocketNotifier(m_masterfd
, QSocketNotifier::Read
);
47 connect(m_outNotifier
, SIGNAL(activated(int)), SLOT(outReceived(int)));
49 m_slavetty
= QString();
67 #ifdef HAVE_FUNC_OPENPTY
68 /* use glibc2's openpty */
71 if (::openpty(&m_masterfd
, &m_slavefd
, 0, 0, 0) == 0) {
72 const char* tname
= ::ttyname(m_slavefd
);
78 m_masterfd
= m_slavefd
= -1;
84 // resort to BSD-style terminals
90 char ptynam
[] = "/dev/ptyxx";
91 char ttynam
[] = "/dev/ttyxx";
92 static const char ptyc3
[] = "pqrstuvwxyzabcde";
93 static const char ptyc4
[] = "0123456789abcdef";
95 // Find a master pty that we can open
96 for (s3
= ptyc3
; *s3
!= 0 && m_masterfd
< 0; s3
++)
98 for (s4
= ptyc4
; *s4
!= 0; s4
++)
100 ptynam
[8] = ttynam
[8] = *s3
;
101 ptynam
[9] = ttynam
[9] = *s4
;
102 if ((m_masterfd
= ::open(ptynam
,O_RDWR
)) >= 0)
104 if (::geteuid() == 0 || ::access(ttynam
,R_OK
|W_OK
) == 0)
116 return m_masterfd
>= 0;
119 void STTY::outReceived(int f
)
123 int n
= ::read(f
, buf
, sizeof(buf
));
125 if (errno
!= EAGAIN
) { /* this is not an error */
126 // ugh! error! somebody disconnect this signal please!
128 TRACE(QString().sprintf("error reading tty: %d", e
));
140 TTYWindow::TTYWindow(QWidget
* parent
, const char* name
) :
141 KTextView(parent
, name
),
145 setFont(kapp
->fixedFont
);
147 setFont(KGlobalSettings::fixedFont());
150 setFocusPolicy(StrongFocus
);
152 // create a context menu
153 m_popmenu
= new QPopupMenu
;
154 m_popmenu
->insertItem(i18n("&Clear"), this, SLOT(clear()));
157 TTYWindow::~TTYWindow()
164 QString
TTYWindow::activate()
166 // allocate a pseudo terminal
169 QString ttyName
= m_tty
->slaveTTY();
170 if (ttyName
.isEmpty()) {
171 // failed to allocate terminal
176 connect(m_tty
, SIGNAL(output(char*,int)), SLOT(slotAppend(char*,int)));
181 void TTYWindow::deactivate()
187 void TTYWindow::slotAppend(char* buffer
, int count
)
189 // is last line visible?
190 bool bottomVisible
= lastRowVisible() == m_texts
.size()-1;
193 char* start
= buffer
;
196 while (count
> 0 && start
[len
] != '\n') {
202 QString
str(start
, len
+1);
204 QString str
= QString::fromLatin1(start
, len
);
207 str
= m_texts
[m_texts
.size()-1] + str
;
208 replaceLine(m_texts
.size()-1, str
);
212 if (count
> 0 && *start
== '\n') {
213 insertLine(QString());
219 // if last row was visible, scroll down to make it visible again
221 setTopCell(m_texts
.size()-1);
224 void TTYWindow::clear()
227 m_width
= 300; m_height
= 14; /* Same as in KTextView::KTextView */
228 insertLine(QString());
231 void TTYWindow::mousePressEvent(QMouseEvent
* mouseEvent
)
233 // Check if right button was clicked.
234 if (mouseEvent
->button() == RightButton
)
236 if (m_popmenu
->isVisible()) {
239 m_popmenu
->popup(mapToGlobal(mouseEvent
->pos()));
242 QWidget::mousePressEvent(mouseEvent
);
246 #include "ttywnd.moc"