Convert from Qt 3 to Qt 4 using qt3to4.
[kdbg.git] / kdbg / ttywnd.cpp
blob3629f3fc7ddf9054ae54b399e1b27062414640d3
1 /*
2 * Copyright Johannes Sixt
3 * This file is licensed under the GNU General Public License Version 2.
4 * See the file COPYING in the toplevel directory of the source directory.
5 */
7 #include <qsocketnotifier.h>
8 #include <q3popupmenu.h>
9 #include "ttywnd.h"
10 #include <kglobalsettings.h>
11 #include <klocale.h>
13 #include "config.h"
14 #include <fcntl.h>
15 #include <unistd.h> /* open, close, etc. */
16 #include <sys/ioctl.h>
17 #include <sys/stat.h>
18 #ifdef HAVE_PTY_H
19 #include <pty.h> /* openpty on Linux */
20 #endif
21 #ifdef HAVE_LIBUTIL_H
22 #include <libutil.h> /* openpty on FreeBSD */
23 #endif
24 #ifdef HAVE_UTIL_H /* openpty on NetBSD, OpenBSD */
25 #include <util.h>
26 #endif
27 #include <errno.h>
29 #include "mydebug.h"
32 STTY::STTY() :
33 QObject(),
34 m_masterfd(-1),
35 m_slavefd(-1),
36 m_outNotifier(0)
38 if (findTTY())
40 ::fcntl(m_masterfd, F_SETFL, O_NDELAY);
41 m_outNotifier = new QSocketNotifier(m_masterfd, QSocketNotifier::Read);
42 connect(m_outNotifier, SIGNAL(activated(int)), SLOT(outReceived(int)));
43 } else {
44 m_slavetty = QString();
48 STTY::~STTY()
50 if (m_outNotifier) {
51 ::close(m_masterfd);
52 if (m_slavefd >= 0)
53 ::close(m_slavefd);
54 delete m_outNotifier;
58 bool STTY::findTTY()
60 m_masterfd = -1;
62 #ifdef HAVE_FUNC_OPENPTY
63 /* use glibc2's openpty */
64 if (m_masterfd < 0)
66 if (::openpty(&m_masterfd, &m_slavefd, 0, 0, 0) == 0) {
67 const char* tname = ::ttyname(m_slavefd);
68 if (tname != 0) {
69 m_slavetty = tname;
70 } else {
71 ::close(m_slavefd);
72 ::close(m_masterfd);
73 m_masterfd = m_slavefd = -1;
77 #endif
79 // resort to BSD-style terminals
80 if (m_masterfd < 0)
82 const char* s3;
83 const char* s4;
85 char ptynam[] = "/dev/ptyxx";
86 char ttynam[] = "/dev/ttyxx";
87 static const char ptyc3[] = "pqrstuvwxyzabcde";
88 static const char ptyc4[] = "0123456789abcdef";
90 // Find a master pty that we can open
91 for (s3 = ptyc3; *s3 != 0 && m_masterfd < 0; s3++)
93 for (s4 = ptyc4; *s4 != 0; s4++)
95 ptynam[8] = ttynam[8] = *s3;
96 ptynam[9] = ttynam[9] = *s4;
97 if ((m_masterfd = ::open(ptynam,O_RDWR)) >= 0)
99 if (::geteuid() == 0 || ::access(ttynam,R_OK|W_OK) == 0)
101 m_slavetty = ttynam;
102 break;
104 ::close(m_masterfd);
105 m_masterfd = -1;
111 return m_masterfd >= 0;
114 void STTY::outReceived(int f)
116 for (;;) {
117 char buf[1024];
118 int n = ::read(f, buf, sizeof(buf));
119 if (n < 0) {
120 if (errno != EAGAIN) { /* this is not an error */
121 // ugh! error! somebody disconnect this signal please!
123 break;
125 emit output(buf, n);
126 if (n == 0)
127 break;
133 TTYWindow::TTYWindow(QWidget* parent) :
134 Q3TextEdit(parent),
135 m_tty(0),
136 m_hPos(0)
138 setFont(KGlobalSettings::fixedFont());
139 setReadOnly(true);
140 setAutoFormatting(AutoNone);
141 setTextFormat(Qt::PlainText);
142 setWordWrap(NoWrap);
145 TTYWindow::~TTYWindow()
147 if (m_tty)
148 deactivate();
152 QString TTYWindow::activate()
154 // allocate a pseudo terminal
155 m_tty = new STTY;
157 QString ttyName = m_tty->slaveTTY();
158 if (ttyName.isEmpty()) {
159 // failed to allocate terminal
160 delete m_tty;
161 m_tty = 0;
162 return QString();
163 } else {
164 connect(m_tty, SIGNAL(output(char*,int)), SLOT(slotAppend(char*,int)));
165 return ttyName;
169 void TTYWindow::deactivate()
171 delete m_tty;
172 m_tty = 0;
176 * Note that it is necessary to track the horizontal position explicitly
177 * since if the user modifies the selected text in the window, the cursor
178 * position changes, too.
180 void TTYWindow::slotAppend(char* buffer, int count)
182 // parse off lines
183 char* start = buffer;
184 while (count > 0) {
185 int len = 0;
186 while (count > 0 && start[len] != '\n' && start[len] != '\r') {
187 --count;
188 ++len;
190 if (len > 0) {
191 QString str = QString::fromLatin1(start, len);
192 // replace text in the last line
193 int para = paragraphs()-1;
194 // this selection is non-empty only after a '\r' that was not
195 // followed by a '\n'
196 setSelection(para, m_hPos, para, m_hPos+len, 1);
197 removeSelectedText(1);
198 insertAt(str, para, m_hPos);
199 m_hPos += len;
200 start += len;
201 len = 0;
203 if (count > 0 && *start == '\r') {
204 ++start;
205 --count;
206 m_hPos = 0;
208 if (count > 0 && *start == '\n') {
209 ++start;
210 --count;
211 append(QString());
212 m_hPos = 0;
217 Q3PopupMenu* TTYWindow::createPopupMenu(const QPoint& pos)
219 Q3PopupMenu* menu = Q3TextEdit::createPopupMenu(pos);
220 menu->insertSeparator();
221 menu->insertItem(i18n("&Clear"), this, SLOT(slotClear()));
222 return menu;
225 void TTYWindow::slotClear()
227 clear();
228 m_hPos = 0;
231 #include "ttywnd.moc"