2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
25 * (c) Copyright 1993, 1994 International Business Machines Corp. *
26 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
27 * (c) Copyright 1993, 1994 Novell, Inc. *
31 #include <X11/Intrinsic.h>
32 #include "TermHeader.h"
33 #include "TermPrimDebug.h"
34 #include "TermPrimPendingTextP.h"
47 PendingTextChunk chunk;
49 fprintf(stderr, "head: %lx\n", list->head);
50 fprintf(stderr, "tail: %lx\n", list->tail);
52 for (chunk = list->head; chunk != list->tail; chunk = chunk->next)
54 fprintf(stderr, "chunk: 0x%lx\n", chunk);
55 fprintf(stderr, " buffer : %c\n", chunk->buffer[0]);
56 fprintf(stderr, " buffLen: %d\n", chunk->buffLen);
57 fprintf(stderr, " bufPtr : %c\n", chunk->bufPtr[0]);
58 fprintf(stderr, " len : %d\n", chunk->len);
59 fprintf(stderr, " next : 0x%lx\n", chunk->next);
60 fprintf(stderr, " prev : 0x%lx\n", chunk->prev);
66 ** Allocate, and initialize a new PendingTextChunk.
72 PendingTextChunk newChunk;
74 Debug('q', fprintf(stderr, ">>mallocChunk() starting\n"));
76 newChunk = (PendingTextChunk) XtMalloc(sizeof(PendingTextChunkRec));
79 return((PendingTextChunk) NULL);
82 newChunk->buffLen = len;
83 newChunk->buffer = (unsigned char *) XtMalloc(newChunk->buffLen);
84 if (!newChunk->buffer)
86 XtFree((char *) newChunk);
87 return((PendingTextChunk) NULL);
91 ** Finish initializing the new chunk.
93 newChunk->bufPtr = newChunk->buffer;
95 newChunk->next = (PendingTextChunk)NULL;
96 newChunk->prev = (PendingTextChunk)NULL;
101 ** Add a new pending text chunk to the end of the list. If possible, reuse
102 ** an existing chunk, else allocate a new one. Return true if successful,
103 ** else return false.
106 _DtTermPrimPendingTextAppendChunk
112 PendingTextChunk newChunk;
114 Debug('q', fprintf(stderr, ">>_DtTermPrimPendingTextAppendChunk() starting\n"));
116 walkPendingText(list);
118 #ifdef RECYCLE_CHUNKS
122 ** There are chunks on the free list, this will
125 newChunk = list->free;
130 ** We have no free chunks.
132 newChunk = mallocChunk(len);
136 return(PendingTextChunk(NULL));
140 ** append the new chunk to the list...
142 list->free = list->free->next;
143 newChunk->next = (PendingTextChunk)NULL;
144 list->tail->next = newChunk;
145 list->tail = newChunk;
147 #else /* RECYCLE_CHUNKS */
149 ** Create a new chunk.
151 newChunk = mallocChunk(len);
155 return((PendingTextChunk)NULL);
157 newChunk->next = list->tail;
158 newChunk->prev = list->tail->prev;
159 list->tail->prev->next = newChunk;
160 list->tail->prev = newChunk;
162 #endif /* RECYCLE_CHUNKS */
166 _DtTermPrimPendingTextReplace
168 PendingTextChunk chunk,
169 unsigned char *buffer,
174 chunk->buffer = (unsigned char *) XtRealloc((char *) chunk->buffer,
176 chunk->buffLen = bufferLen;
177 chunk->bufPtr = chunk->buffer;
178 chunk->len = bufferLen;
179 (void) memmove(chunk->buffer, buffer, bufferLen);
183 ** Remove a pending text chunk from the head of the list, and add it to
187 _DtTermPrimPendingTextRemoveChunk
190 PendingTextChunk chunk
193 Debug('q', fprintf(stderr, ">>_DtTermPrimPendingTextRemoveChunk() starting\n"));
195 walkPendingText(list);
198 ** add the chunk to the free list...
200 /* don't allow removal of either head or tail... */
201 if ((chunk == list->head) || (chunk == list->tail)) {
205 chunk->prev->next = chunk->next;
206 chunk->next->prev = chunk->prev;
207 #ifdef RECYCLE_CHUNKS
209 chunk->next = list->free;
211 #else /* RECYCLE_CHUNKS */
212 XtFree((char *) chunk->buffer);
213 XtFree((char *) chunk);
214 #endif /* RECYCLE_CHUNKS */
217 /* Check to see if there is any pending text in the pending text list...
220 _DtTermPrimPendingTextIsPending
225 if (list->head->next != list->tail) {
232 ** Get a pending text chunk from the head of the list.
235 _DtTermPrimPendingTextGetChunk
240 Debug('q', fprintf(stderr, ">>_DtTermPrimPendingTextGetChunk() starting\n"));
242 walkPendingText(list);
245 if (list->head->next != list->tail) {
246 return(list->head->next);
248 return((PendingTextChunk) 0);
253 ** Flush a pending text list. This function takes the easy way out of
254 ** calling _DtTermPrimPendingTextGetChunk() to get each chunk and
255 ** _DtTermPrimPendingTextRemoveChunk() to remove them.
258 _DtTermPrimPendingTextFlush
263 PendingTextChunk chunk;
265 Debug('q', fprintf(stderr, ">>_DtTermPrimPendingTextFlush() starting\n"));
267 walkPendingText(list);
270 while ((chunk = _DtTermPrimPendingTextGetChunk(list))) {
271 (void) _DtTermPrimPendingTextRemoveChunk(list, chunk);
276 ** Append the supplied text to the pending text list. Return True if
277 ** all text was appended, else return False.
280 _DtTermPrimPendingTextAppend
287 PendingTextChunk newChunk;
288 PendingTextChunk oldTail;
290 Debug('q', fprintf(stderr, ">>_DtTermPrimPendingTextAppend() starting\n"));
292 walkPendingText(list);
295 ** remember this if we are unable to get all the text
298 oldTail = list->tail->prev;
301 ** add a new chunk to the list
305 newChunk = _DtTermPrimPendingTextAppendChunk(list,
306 (len > DEFAULT_CHUNK_BUF_SIZE) ? DEFAULT_CHUNK_BUF_SIZE : len);
310 ** the allocation failed, free up all newly created
311 ** chunks and return...
313 while (oldTail != list->tail->prev)
315 _DtTermPrimPendingTextRemoveChunk(list, list->tail->prev);
320 ** chunk buffers are a fixed size, copy a much as possible
321 ** from 'text' to the chunk buffer, then adjust 'len'...
323 newChunk->len = MIN(len, newChunk->buffLen);
324 (void)memcpy(newChunk->buffer, text, newChunk->len);
325 len -= newChunk->buffLen;
331 ** Write a pending text chunk from the head of the list.
334 _DtTermPrimPendingTextWrite
340 int bytesWritten = 0;
341 PendingTextChunk chunk;
343 Debug('q', fprintf(stderr, ">>_DtTermPrimPendingTextWrite() starting\n"));
345 walkPendingText(list);
347 chunk = list->head->next;
348 Debug('q', fprintf(stderr, ">> len: %3.3d\n", chunk->len));
349 Debug('q', fprintf(stderr, ">> bufPtr: <%*.*s>\n",
350 chunk->len, chunk->len, chunk->bufPtr));
352 bytesWritten = write(fd, chunk->bufPtr, chunk->len <= MAX_PTY_WRITE ?
353 chunk->len : MAX_PTY_WRITE);
355 if (bytesWritten < 0) {
358 fprintf(stderr, "_DtTermPrimPendingTextWrite: write failed\n");
363 if ((chunk->len -= bytesWritten) <= 0) {
365 ** All text in this chunk has been written,
366 ** remove it from the list.
368 _DtTermPrimPendingTextRemoveChunk(list, chunk);
372 ** only some of the text in this chunk was written,
373 ** simply adjust the write pointer...
374 ** (list->head->len was adjusted above)
376 chunk->bufPtr += bytesWritten;
382 _DtTermPrimPendingTextCreate(
388 Debug('q', fprintf(stderr, ">>_DtTermPrimPendingTextCreate() starting\n"));
390 ptr = (PendingText) XtMalloc(sizeof(PendingTextRec));
391 (void) memset(ptr, '\0', sizeof(PendingTextRec));
392 ptr->head = (PendingTextChunk) XtMalloc(sizeof(PendingTextChunkRec));
393 (void) memset(ptr->head, '\0', sizeof(PendingTextChunkRec));
394 ptr->tail = (PendingTextChunk) XtMalloc(sizeof(PendingTextChunkRec));
395 (void) memset(ptr->tail, '\0', sizeof(PendingTextChunkRec));
397 ptr->head->next = ptr->tail;
398 ptr->tail->prev = ptr->head;
401 walkPendingText(ptr);
407 _DtTermPrimPendingTextDestroy(
411 PendingTextChunk chunk;
413 Debug('q', fprintf(stderr, ">>_DtTermPrimPendingTextDestroy() starting\n"));
416 walkPendingText(ptr);
421 ptr->head = ptr->head->next;
423 (void) XtFree((char *) chunk->buffer);
425 (void) XtFree((char *) chunk);
427 (void) XtFree((char *) ptr);