Mercurial > octave-nkf
comparison gui/src/terminal/KPtyDevice.h @ 13647:ac3d9480292d
Renamed file.
author | Jacob Dawid <jacob.dawid@googlemail.com> |
---|---|
date | Tue, 23 Aug 2011 18:22:27 +0200 |
parents | gui/src/terminal/kptydevice.h@2e1f54803758 |
children | 9b74f97919e1 |
comparison
equal
deleted
inserted
replaced
13646:2e1f54803758 | 13647:ac3d9480292d |
---|---|
1 /* This file is part of the KDE libraries | |
2 | |
3 Copyright (C) 2007 Oswald Buddenhagen <ossi@kde.org> | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public License | |
16 along with this library; see the file COPYING.LIB. If not, write to | |
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
18 Boston, MA 02110-1301, USA. | |
19 */ | |
20 | |
21 #ifndef kptydev_h | |
22 #define kptydev_h | |
23 | |
24 struct KPtyDevicePrivate; | |
25 | |
26 #include "KPty.h" | |
27 #include <QtCore/QIODevice> | |
28 #include <QSocketNotifier> | |
29 | |
30 #define Q_DECLARE_PRIVATE_MI(Class, SuperClass) \ | |
31 inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(SuperClass::d_ptr); } \ | |
32 inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(SuperClass::d_ptr); } \ | |
33 friend class Class##Private; | |
34 | |
35 /** | |
36 * Encapsulates KPty into a QIODevice, so it can be used with Q*Stream, etc. | |
37 */ | |
38 class KPtyDevice:public QIODevice, public KPty | |
39 { | |
40 Q_OBJECT Q_DECLARE_PRIVATE_MI (KPtyDevice, KPty) public: | |
41 | |
42 /** | |
43 * Constructor | |
44 */ | |
45 KPtyDevice (QObject * parent = 0); | |
46 | |
47 /** | |
48 * Destructor: | |
49 * | |
50 * If the pty is still open, it will be closed. Note, however, that | |
51 * an utmp registration is @em not undone. | |
52 */ | |
53 virtual ~ KPtyDevice (); | |
54 | |
55 /** | |
56 * Create a pty master/slave pair. | |
57 * | |
58 * @return true if a pty pair was successfully opened | |
59 */ | |
60 virtual bool open (OpenMode mode = ReadWrite | Unbuffered); | |
61 | |
62 /** | |
63 * Open using an existing pty master. The ownership of the fd | |
64 * remains with the caller, i.e., close() will not close the fd. | |
65 * | |
66 * This is useful if you wish to attach a secondary "controller" to an | |
67 * existing pty device such as a terminal widget. | |
68 * Note that you will need to use setSuspended() on both devices to | |
69 * control which one gets the incoming data from the pty. | |
70 * | |
71 * @param fd an open pty master file descriptor. | |
72 * @param mode the device mode to open the pty with. | |
73 * @return true if a pty pair was successfully opened | |
74 */ | |
75 bool open (int fd, OpenMode mode = ReadWrite | Unbuffered); | |
76 | |
77 /** | |
78 * Close the pty master/slave pair. | |
79 */ | |
80 virtual void close (); | |
81 | |
82 /** | |
83 * @reimp | |
84 */ | |
85 bool canReadLine () const; | |
86 | |
87 /** | |
88 * @reimp | |
89 */ | |
90 bool atEnd () const; | |
91 | |
92 /** | |
93 * @reimp | |
94 */ | |
95 qint64 bytesAvailable () const; | |
96 | |
97 /** | |
98 * @reimp | |
99 */ | |
100 qint64 bytesToWrite () const; | |
101 | |
102 protected: | |
103 virtual qint64 readData (char *data, qint64 maxSize); | |
104 virtual qint64 readLineData (char *data, qint64 maxSize); | |
105 virtual qint64 writeData (const char *data, qint64 maxSize); | |
106 | |
107 private: | |
108 Q_PRIVATE_SLOT (d_func (), bool _k_canRead ()) | |
109 Q_PRIVATE_SLOT (d_func (), bool _k_canWrite ())}; | |
110 | |
111 #define KMAXINT ((int)(~0U >> 1)) | |
112 | |
113 ///////////////////////////////////////////////////// | |
114 // Helper. Remove when QRingBuffer becomes public. // | |
115 ///////////////////////////////////////////////////// | |
116 | |
117 #include <QtCore/qbytearray.h> | |
118 #include <QtCore/qlinkedlist.h> | |
119 | |
120 #define CHUNKSIZE 4096 | |
121 | |
122 class KRingBuffer | |
123 { | |
124 public: | |
125 KRingBuffer () | |
126 { | |
127 clear (); | |
128 } | |
129 | |
130 void clear () | |
131 { | |
132 buffers.clear (); | |
133 QByteArray tmp; | |
134 tmp.resize (CHUNKSIZE); | |
135 buffers << tmp; | |
136 head = tail = 0; | |
137 totalSize = 0; | |
138 } | |
139 | |
140 inline bool isEmpty () const | |
141 { | |
142 return buffers.count () == 1 && !tail; | |
143 } | |
144 | |
145 inline int size () const | |
146 { | |
147 return totalSize; | |
148 } | |
149 | |
150 inline int readSize () const | |
151 { | |
152 return (buffers.count () == 1 ? tail : buffers.first ().size ()) - head; | |
153 } | |
154 | |
155 inline const char *readPointer () const | |
156 { | |
157 Q_ASSERT (totalSize > 0); | |
158 return buffers.first ().constData () + head; | |
159 } | |
160 | |
161 void free (int bytes) | |
162 { | |
163 totalSize -= bytes; | |
164 Q_ASSERT (totalSize >= 0); | |
165 | |
166 forever | |
167 { | |
168 int nbs = readSize (); | |
169 | |
170 if (bytes < nbs) | |
171 { | |
172 head += bytes; | |
173 if (head == tail && buffers.count () == 1) | |
174 { | |
175 buffers.first ().resize (CHUNKSIZE); | |
176 head = tail = 0; | |
177 } | |
178 break; | |
179 } | |
180 | |
181 bytes -= nbs; | |
182 if (buffers.count () == 1) | |
183 { | |
184 buffers.first ().resize (CHUNKSIZE); | |
185 head = tail = 0; | |
186 break; | |
187 } | |
188 | |
189 buffers.removeFirst (); | |
190 head = 0; | |
191 } | |
192 } | |
193 | |
194 char *reserve (int bytes) | |
195 { | |
196 totalSize += bytes; | |
197 | |
198 char *ptr; | |
199 if (tail + bytes <= buffers.last ().size ()) | |
200 { | |
201 ptr = buffers.last ().data () + tail; | |
202 tail += bytes; | |
203 } | |
204 else | |
205 { | |
206 buffers.last ().resize (tail); | |
207 QByteArray tmp; | |
208 tmp.resize (qMax (CHUNKSIZE, bytes)); | |
209 ptr = tmp.data (); | |
210 buffers << tmp; | |
211 tail = bytes; | |
212 } | |
213 return ptr; | |
214 } | |
215 | |
216 // release a trailing part of the last reservation | |
217 inline void unreserve (int bytes) | |
218 { | |
219 totalSize -= bytes; | |
220 tail -= bytes; | |
221 } | |
222 | |
223 inline void write (const char *data, int len) | |
224 { | |
225 memcpy (reserve (len), data, len); | |
226 } | |
227 | |
228 // Find the first occurrence of c and return the index after it. | |
229 // If c is not found until maxLength, maxLength is returned, provided | |
230 // it is smaller than the buffer size. Otherwise -1 is returned. | |
231 int indexAfter (char c, int maxLength = KMAXINT) const | |
232 { | |
233 int index = 0; | |
234 int start = head; | |
235 QLinkedList < QByteArray >::ConstIterator it = buffers.begin (); | |
236 forever | |
237 { | |
238 if (!maxLength) | |
239 return index; | |
240 if (index == size ()) | |
241 return -1; | |
242 const QByteArray & buf = *it; | |
243 ++it; | |
244 int len = qMin ((it == buffers.end ()? tail : buf.size ()) - start, | |
245 maxLength); | |
246 const char *ptr = buf.data () + start; | |
247 if (const char *rptr = (const char *)memchr (ptr, c, len)) | |
248 return index + (rptr - ptr) + 1; | |
249 index += len; | |
250 maxLength -= len; | |
251 start = 0; | |
252 } | |
253 } | |
254 | |
255 inline int lineSize (int maxLength = KMAXINT) const | |
256 { | |
257 return indexAfter ('\n', maxLength); | |
258 } | |
259 | |
260 inline bool canReadLine () const | |
261 { | |
262 return lineSize () != -1; | |
263 } | |
264 | |
265 int read (char *data, int maxLength) | |
266 { | |
267 int bytesToRead = qMin (size (), maxLength); | |
268 int readSoFar = 0; | |
269 while (readSoFar < bytesToRead) | |
270 { | |
271 const char *ptr = readPointer (); | |
272 int bs = qMin (bytesToRead - readSoFar, readSize ()); | |
273 memcpy (data + readSoFar, ptr, bs); | |
274 readSoFar += bs; | |
275 free (bs); | |
276 } | |
277 return readSoFar; | |
278 } | |
279 | |
280 int readLine (char *data, int maxLength) | |
281 { | |
282 return read (data, lineSize (qMin (maxLength, size ()))); | |
283 } | |
284 | |
285 private: | |
286 QLinkedList < QByteArray > buffers; | |
287 int head, tail; | |
288 int totalSize; | |
289 }; | |
290 | |
291 struct KPtyDevicePrivate:public KPtyPrivate | |
292 { | |
293 Q_DECLARE_PUBLIC (KPtyDevice) | |
294 KPtyDevicePrivate (KPty * parent):KPtyPrivate (parent), | |
295 emittedReadyRead (false), emittedBytesWritten (false), | |
296 readNotifier (0), writeNotifier (0) | |
297 { | |
298 } | |
299 | |
300 bool _k_canRead (); | |
301 bool _k_canWrite (); | |
302 | |
303 bool doWait (int msecs, bool reading); | |
304 void finishOpen (QIODevice::OpenMode mode); | |
305 | |
306 bool emittedReadyRead; | |
307 bool emittedBytesWritten; | |
308 QSocketNotifier *readNotifier; | |
309 QSocketNotifier *writeNotifier; | |
310 KRingBuffer readBuffer; | |
311 KRingBuffer writeBuffer; | |
312 }; | |
313 | |
314 #endif |