source: ogBrowser-Git/qtermwidget/lib/kptydevice.h @ ffbf8ac

jenkinsmain
Last change on this file since ffbf8ac was 64efc22, checked in by Vadim Troshchinskiy <vtroshchinskiy@…>, 19 months ago

Update qtermwidget to modern version

  • Property mode set to 100644
File size: 9.1 KB
Line 
1/*
2 * This file is a part of QTerminal - http://gitorious.org/qterminal
3 *
4 * This file was un-linked from KDE and modified
5 * by Maxim Bourmistrov <maxim@unixconn.com>
6 *
7 */
8
9/* This file is part of the KDE libraries
10
11    Copyright (C) 2007 Oswald Buddenhagen <ossi@kde.org>
12
13    This library is free software; you can redistribute it and/or
14    modify it under the terms of the GNU Library General Public
15    License as published by the Free Software Foundation; either
16    version 2 of the License, or (at your option) any later version.
17
18    This library is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    Library General Public License for more details.
22
23    You should have received a copy of the GNU Library General Public License
24    along with this library; see the file COPYING.LIB.  If not, write to
25    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26    Boston, MA 02110-1301, USA.
27*/
28
29#ifndef kptydev_h
30#define kptydev_h
31
32#include "kpty_p.h"
33
34#include <QIODevice>
35
36#define KMAXINT ((int)(~0U >> 1))
37
38struct KPtyDevicePrivate;
39class QSocketNotifier;
40
41#define Q_DECLARE_PRIVATE_MI(Class, SuperClass) \
42    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(SuperClass::d_ptr); } \
43    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(SuperClass::d_ptr); } \
44    friend struct Class##Private;
45
46/**
47 * Encapsulates KPty into a QIODevice, so it can be used with Q*Stream, etc.
48 */
49class KPtyDevice : public QIODevice, public KPty {
50    Q_OBJECT
51    Q_DECLARE_PRIVATE_MI(KPtyDevice, KPty)
52
53public:
54
55    /**
56     * Constructor
57     */
58    KPtyDevice(QObject *parent = nullptr);
59
60    /**
61     * Destructor:
62     *
63     *  If the pty is still open, it will be closed. Note, however, that
64     *  an utmp registration is @em not undone.
65     */
66    ~KPtyDevice() override;
67
68    /**
69     * Create a pty master/slave pair.
70     *
71     * @return true if a pty pair was successfully opened
72     */
73    bool open(OpenMode mode = ReadWrite | Unbuffered) override;
74
75    /**
76     * Open using an existing pty master. The ownership of the fd
77     * remains with the caller, i.e., close() will not close the fd.
78     *
79     * This is useful if you wish to attach a secondary "controller" to an
80     * existing pty device such as a terminal widget.
81     * Note that you will need to use setSuspended() on both devices to
82     * control which one gets the incoming data from the pty.
83     *
84     * @param fd an open pty master file descriptor.
85     * @param mode the device mode to open the pty with.
86     * @return true if a pty pair was successfully opened
87     */
88    bool open(int fd, OpenMode mode = ReadWrite | Unbuffered);
89
90    /**
91     * Close the pty master/slave pair.
92     */
93    void close() override;
94
95    /**
96     * Sets whether the KPtyDevice monitors the pty for incoming data.
97     *
98     * When the KPtyDevice is suspended, it will no longer attempt to buffer
99     * data that becomes available from the pty and it will not emit any
100     * signals.
101     *
102     * Do not use on closed ptys.
103     * After a call to open(), the pty is not suspended. If you need to
104     * ensure that no data is read, call this function before the main loop
105     * is entered again (i.e., immediately after opening the pty).
106     */
107    void setSuspended(bool suspended);
108
109    /**
110     * Returns true if the KPtyDevice is not monitoring the pty for incoming
111     * data.
112     *
113     * Do not use on closed ptys.
114     *
115     * See setSuspended()
116     */
117    bool isSuspended() const;
118
119    /**
120     * @return always true
121     */
122    bool isSequential() const override;
123
124    /**
125     * @reimp
126     */
127    bool canReadLine() const override;
128
129    /**
130     * @reimp
131     */
132    bool atEnd() const override;
133
134    /**
135     * @reimp
136     */
137    qint64 bytesAvailable() const override;
138
139    /**
140     * @reimp
141     */
142    qint64 bytesToWrite() const override;
143
144    bool waitForBytesWritten(int msecs = -1) override;
145    bool waitForReadyRead(int msecs = -1) override;
146
147
148Q_SIGNALS:
149    /**
150     * Emitted when EOF is read from the PTY.
151     *
152     * Data may still remain in the buffers.
153     */
154    void readEof();
155
156protected:
157    qint64 readData(char *data, qint64 maxSize) override;
158    qint64 readLineData(char *data, qint64 maxSize) override;
159    qint64 writeData(const char *data, qint64 maxSize) override;
160
161private:
162    Q_PRIVATE_SLOT(d_func(), bool _k_canRead())
163    Q_PRIVATE_SLOT(d_func(), bool _k_canWrite())
164};
165
166/////////////////////////////////////////////////////
167// Helper. Remove when QRingBuffer becomes public. //
168/////////////////////////////////////////////////////
169
170#include <QByteArray>
171#include <list>
172
173#define CHUNKSIZE 4096
174
175class KRingBuffer
176{
177public:
178    KRingBuffer()
179    {
180        clear();
181    }
182
183    void clear()
184    {
185        buffers.clear();
186        QByteArray tmp;
187        tmp.resize(CHUNKSIZE);
188        buffers.push_back(tmp);
189        head = tail = 0;
190        totalSize = 0;
191    }
192
193    inline bool isEmpty() const
194    {
195        return buffers.size() == 1 && !tail;
196    }
197
198    inline int size() const
199    {
200        return totalSize;
201    }
202
203    inline int readSize() const
204    {
205        return (buffers.size() == 1 ? tail : buffers.front().size()) - head;
206    }
207
208    inline const char *readPointer() const
209    {
210        Q_ASSERT(totalSize > 0);
211        return buffers.front().constData() + head;
212    }
213
214    void free(int bytes)
215    {
216        totalSize -= bytes;
217        Q_ASSERT(totalSize >= 0);
218
219        forever {
220            int nbs = readSize();
221
222            if (bytes < nbs) {
223                head += bytes;
224                if (head == tail && buffers.size() == 1) {
225                    buffers.front().resize(CHUNKSIZE);
226                    head = tail = 0;
227                }
228                break;
229            }
230
231            bytes -= nbs;
232            if (buffers.size() == 1) {
233                buffers.front().resize(CHUNKSIZE);
234                head = tail = 0;
235                break;
236            }
237
238            buffers.pop_front();
239            head = 0;
240        }
241    }
242
243    char *reserve(int bytes)
244    {
245        totalSize += bytes;
246
247        char *ptr;
248        if (tail + bytes <= buffers.back().size()) {
249            ptr = buffers.back().data() + tail;
250            tail += bytes;
251        } else {
252            buffers.back().resize(tail);
253            QByteArray tmp;
254            tmp.resize(qMax(CHUNKSIZE, bytes));
255            ptr = tmp.data();
256            buffers.push_back(tmp);
257            tail = bytes;
258        }
259        return ptr;
260    }
261
262    // release a trailing part of the last reservation
263    inline void unreserve(int bytes)
264    {
265        totalSize -= bytes;
266        tail -= bytes;
267    }
268
269    inline void write(const char *data, int len)
270    {
271        memcpy(reserve(len), data, len);
272    }
273
274    // Find the first occurrence of c and return the index after it.
275    // If c is not found until maxLength, maxLength is returned, provided
276    // it is smaller than the buffer size. Otherwise -1 is returned.
277    int indexAfter(char c, int maxLength = KMAXINT) const
278    {
279        int index = 0;
280        int start = head;
281        std::list<QByteArray>::const_iterator it = buffers.cbegin();
282        forever {
283            if (!maxLength)
284                return index;
285            if (index == size())
286                return -1;
287            const QByteArray &buf = *it;
288            ++it;
289            int len = qMin((it == buffers.cend() ? tail : buf.size()) - start,
290                           maxLength);
291            const char *ptr = buf.data() + start;
292            if (const char *rptr = (const char *)memchr(ptr, c, len))
293                return index + (rptr - ptr) + 1;
294            index += len;
295            maxLength -= len;
296            start = 0;
297        }
298    }
299
300    inline int lineSize(int maxLength = KMAXINT) const
301    {
302        return indexAfter('\n', maxLength);
303    }
304
305    inline bool canReadLine() const
306    {
307        return lineSize() != -1;
308    }
309
310    int read(char *data, int maxLength)
311    {
312        int bytesToRead = qMin(size(), maxLength);
313        int readSoFar = 0;
314        while (readSoFar < bytesToRead) {
315            const char *ptr = readPointer();
316            int bs = qMin(bytesToRead - readSoFar, readSize());
317            memcpy(data + readSoFar, ptr, bs);
318            readSoFar += bs;
319            free(bs);
320        }
321        return readSoFar;
322    }
323
324    int readLine(char *data, int maxLength)
325    {
326        return read(data, lineSize(qMin(maxLength, size())));
327    }
328
329private:
330    std::list<QByteArray> buffers;
331    int head, tail;
332    int totalSize;
333};
334
335struct KPtyDevicePrivate : public KPtyPrivate {
336
337    Q_DECLARE_PUBLIC(KPtyDevice)
338
339    KPtyDevicePrivate(KPty* parent) :
340        KPtyPrivate(parent),
341        emittedReadyRead(false), emittedBytesWritten(false),
342        readNotifier(nullptr), writeNotifier(nullptr)
343    {
344    }
345
346    bool _k_canRead();
347    bool _k_canWrite();
348
349    bool doWait(int msecs, bool reading);
350    void finishOpen(QIODevice::OpenMode mode);
351
352    bool emittedReadyRead;
353    bool emittedBytesWritten;
354    QSocketNotifier *readNotifier;
355    QSocketNotifier *writeNotifier;
356    KRingBuffer readBuffer;
357    KRingBuffer writeBuffer;
358};
359
360#endif
361
Note: See TracBrowser for help on using the repository browser.