ptydata.c revision 894e0ac8
1894e0ac8Smrg/* $XTermId: ptydata.c,v 1.104 2014/05/26 14:46:18 tom Exp $ */ 2d522f475Smrg 30bd37d32Smrg/* 4894e0ac8Smrg * Copyright 1999-2013,2014 by Thomas E. Dickey 50bd37d32Smrg * 60bd37d32Smrg * All Rights Reserved 70bd37d32Smrg * 80bd37d32Smrg * Permission is hereby granted, free of charge, to any person obtaining a 90bd37d32Smrg * copy of this software and associated documentation files (the 100bd37d32Smrg * "Software"), to deal in the Software without restriction, including 110bd37d32Smrg * without limitation the rights to use, copy, modify, merge, publish, 120bd37d32Smrg * distribute, sublicense, and/or sell copies of the Software, and to 130bd37d32Smrg * permit persons to whom the Software is furnished to do so, subject to 140bd37d32Smrg * the following conditions: 150bd37d32Smrg * 160bd37d32Smrg * The above copyright notice and this permission notice shall be included 170bd37d32Smrg * in all copies or substantial portions of the Software. 180bd37d32Smrg * 190bd37d32Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 200bd37d32Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 210bd37d32Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 220bd37d32Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 230bd37d32Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 240bd37d32Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 250bd37d32Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 260bd37d32Smrg * 270bd37d32Smrg * Except as contained in this notice, the name(s) of the above copyright 280bd37d32Smrg * holders shall not be used in advertising or otherwise to promote the 290bd37d32Smrg * sale, use or other dealings in this Software without prior written 300bd37d32Smrg * authorization. 310bd37d32Smrg */ 32d522f475Smrg 33d522f475Smrg#include <data.h> 34d522f475Smrg 35d522f475Smrg#if OPT_WIDE_CHARS 36d522f475Smrg#include <menu.h> 37d522f475Smrg#endif 38d522f475Smrg 39d522f475Smrg/* 40d522f475Smrg * Check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX 41d522f475Smrg * systems are broken and return EWOULDBLOCK when they should return EAGAIN. 42d522f475Smrg * Note that this macro may evaluate its argument more than once. 43d522f475Smrg */ 44d522f475Smrg#if defined(EAGAIN) && defined(EWOULDBLOCK) 45d522f475Smrg#define E_TEST(err) ((err) == EAGAIN || (err) == EWOULDBLOCK) 46d522f475Smrg#else 47d522f475Smrg#ifdef EAGAIN 48d522f475Smrg#define E_TEST(err) ((err) == EAGAIN) 49d522f475Smrg#else 50d522f475Smrg#define E_TEST(err) ((err) == EWOULDBLOCK) 51d522f475Smrg#endif 52d522f475Smrg#endif 53d522f475Smrg 54d522f475Smrg#if OPT_WIDE_CHARS 55d522f475Smrg/* 56d522f475Smrg * Convert the 8-bit codes in data->buffer[] into Unicode in data->utf_data. 57d522f475Smrg * The number of bytes converted will be nonzero iff there is data. 58d522f475Smrg */ 59d522f475SmrgBool 60894e0ac8SmrgdecodeUtf8(TScreen *screen, PtyData *data) 61d522f475Smrg{ 62d522f475Smrg int i; 6320d2c4d2Smrg int length = (int) (data->last - data->next); 64d522f475Smrg int utf_count = 0; 65956cc18dSsnj unsigned utf_char = 0; 66d522f475Smrg 67d522f475Smrg data->utf_size = 0; 68d522f475Smrg for (i = 0; i < length; i++) { 69d522f475Smrg unsigned c = data->next[i]; 70d522f475Smrg 71d522f475Smrg /* Combine UTF-8 into Unicode */ 72d522f475Smrg if (c < 0x80) { 73d522f475Smrg /* We received an ASCII character */ 74d522f475Smrg if (utf_count > 0) { 75d522f475Smrg data->utf_data = UCS_REPL; /* prev. sequence incomplete */ 76a1f3da82Smrg data->utf_size = i; 77d522f475Smrg } else { 78956cc18dSsnj data->utf_data = (IChar) c; 79d522f475Smrg data->utf_size = 1; 80d522f475Smrg } 81d522f475Smrg break; 82d522f475Smrg } else if (c < 0xc0) { 83d522f475Smrg /* We received a continuation byte */ 84d522f475Smrg if (utf_count < 1) { 85d522f475Smrg /* 86d522f475Smrg * We received a continuation byte before receiving a sequence 87d522f475Smrg * state. Or an attempt to use a C1 control string. Either 88894e0ac8Smrg * way, it is mapped to the replacement character, unless 89894e0ac8Smrg * allowed by optional feature. 90d522f475Smrg */ 91894e0ac8Smrg data->utf_data = (IChar) (screen->c1_printable ? c : UCS_REPL); 92d522f475Smrg data->utf_size = (i + 1); 93d522f475Smrg break; 94d522f475Smrg } else { 95d522f475Smrg /* Check for overlong UTF-8 sequences for which a shorter 96d522f475Smrg * encoding would exist and replace them with UCS_REPL. 97d522f475Smrg * An overlong UTF-8 sequence can have any of the following 98d522f475Smrg * forms: 99d522f475Smrg * 1100000x 10xxxxxx 100d522f475Smrg * 11100000 100xxxxx 10xxxxxx 101d522f475Smrg * 11110000 1000xxxx 10xxxxxx 10xxxxxx 102d522f475Smrg * 11111000 10000xxx 10xxxxxx 10xxxxxx 10xxxxxx 103d522f475Smrg * 11111100 100000xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 104d522f475Smrg */ 105d522f475Smrg if (!utf_char && !((c & 0x7f) >> (7 - utf_count))) { 106d522f475Smrg utf_char = UCS_REPL; 107d522f475Smrg } 108d522f475Smrg utf_char <<= 6; 109d522f475Smrg utf_char |= (c & 0x3f); 110d522f475Smrg if ((utf_char >= 0xd800 && 111d522f475Smrg utf_char <= 0xdfff) || 112d522f475Smrg (utf_char == 0xfffe) || 113d522f475Smrg (utf_char == HIDDEN_CHAR)) { 114d522f475Smrg utf_char = UCS_REPL; 115d522f475Smrg } 116d522f475Smrg utf_count--; 117d522f475Smrg if (utf_count == 0) { 118956cc18dSsnj#if !OPT_WIDER_ICHAR 119d522f475Smrg /* characters outside UCS-2 become UCS_REPL */ 120d522f475Smrg if (utf_char > 0xffff) { 121d522f475Smrg TRACE(("using replacement for %#x\n", utf_char)); 122d522f475Smrg utf_char = UCS_REPL; 123d522f475Smrg } 124956cc18dSsnj#endif 125956cc18dSsnj data->utf_data = (IChar) utf_char; 126d522f475Smrg data->utf_size = (i + 1); 127d522f475Smrg break; 128d522f475Smrg } 129d522f475Smrg } 130d522f475Smrg } else { 131d522f475Smrg /* We received a sequence start byte */ 132d522f475Smrg if (utf_count > 0) { 133d522f475Smrg data->utf_data = UCS_REPL; /* prev. sequence incomplete */ 134d522f475Smrg data->utf_size = (i + 1); 135d522f475Smrg break; 136d522f475Smrg } 137d522f475Smrg if (c < 0xe0) { 138d522f475Smrg utf_count = 1; 139d522f475Smrg utf_char = (c & 0x1f); 140a1f3da82Smrg if (!(c & 0x1e)) { 141d522f475Smrg utf_char = UCS_REPL; /* overlong sequence */ 142a1f3da82Smrg } 143d522f475Smrg } else if (c < 0xf0) { 144d522f475Smrg utf_count = 2; 145d522f475Smrg utf_char = (c & 0x0f); 146d522f475Smrg } else if (c < 0xf8) { 147d522f475Smrg utf_count = 3; 148d522f475Smrg utf_char = (c & 0x07); 149d522f475Smrg } else if (c < 0xfc) { 150d522f475Smrg utf_count = 4; 151d522f475Smrg utf_char = (c & 0x03); 152d522f475Smrg } else if (c < 0xfe) { 153d522f475Smrg utf_count = 5; 154d522f475Smrg utf_char = (c & 0x01); 155d522f475Smrg } else { 156d522f475Smrg data->utf_data = UCS_REPL; 157d522f475Smrg data->utf_size = (i + 1); 158d522f475Smrg break; 159d522f475Smrg } 160d522f475Smrg } 161d522f475Smrg } 162d522f475Smrg#if OPT_TRACE > 1 163d522f475Smrg TRACE(("UTF-8 char %04X [%d..%d]\n", 164d522f475Smrg data->utf_data, 165894e0ac8Smrg (int) (data->next - data->buffer), 166894e0ac8Smrg (int) (data->next - data->buffer + data->utf_size - 1))); 167d522f475Smrg#endif 168d522f475Smrg 169d522f475Smrg return (data->utf_size != 0); 170d522f475Smrg} 171d522f475Smrg#endif 172d522f475Smrg 173d522f475Smrgint 174894e0ac8SmrgreadPtyData(XtermWidget xw, PtySelect * select_mask, PtyData *data) 175d522f475Smrg{ 17620d2c4d2Smrg TScreen *screen = TScreenOf(xw); 177d522f475Smrg int size = 0; 178d522f475Smrg 179d522f475Smrg#ifdef VMS 180d522f475Smrg if (*select_mask & pty_mask) { 18120d2c4d2Smrg trimPtyData(xw, data); 182d522f475Smrg if (read_queue.flink != 0) { 183d522f475Smrg size = tt_read(data->next); 184d522f475Smrg if (size == 0) { 185d522f475Smrg Panic("input: read returned zero\n", 0); 186d522f475Smrg } 187d522f475Smrg } else { 188d522f475Smrg sys$hiber(); 189d522f475Smrg } 190d522f475Smrg } 191d522f475Smrg#else /* !VMS */ 192d522f475Smrg if (FD_ISSET(screen->respond, select_mask)) { 193956cc18dSsnj int save_err; 19420d2c4d2Smrg trimPtyData(xw, data); 195d522f475Smrg 19620d2c4d2Smrg size = (int) read(screen->respond, (char *) data->last, (size_t) FRG_SIZE); 197956cc18dSsnj save_err = errno; 198d522f475Smrg#if (defined(i386) && defined(SVR4) && defined(sun)) || defined(__CYGWIN__) 199956cc18dSsnj /* 200956cc18dSsnj * Yes, I know this is a majorly f*ugly hack, however it seems to 201956cc18dSsnj * be necessary for Solaris x86. DWH 11/15/94 202956cc18dSsnj * Dunno why though.. 203956cc18dSsnj * (and now CYGWIN, alanh@xfree86.org 08/15/01 204956cc18dSsnj */ 205956cc18dSsnj if (size <= 0) { 206956cc18dSsnj if (save_err == EIO || save_err == 0) 2070bd37d32Smrg NormalExit(); 208956cc18dSsnj else if (!E_TEST(save_err)) 209956cc18dSsnj Panic("input: read returned unexpected error (%d)\n", save_err); 210956cc18dSsnj size = 0; 211956cc18dSsnj } 212956cc18dSsnj#else /* !f*ugly */ 213956cc18dSsnj if (size < 0) { 214956cc18dSsnj if (save_err == EIO) 2150bd37d32Smrg NormalExit(); 216956cc18dSsnj else if (!E_TEST(save_err)) 217956cc18dSsnj Panic("input: read returned unexpected error (%d)\n", save_err); 218d522f475Smrg size = 0; 219d522f475Smrg } else if (size == 0) { 2200bd37d32Smrg#if defined(__FreeBSD__) 2210bd37d32Smrg NormalExit(); 222d522f475Smrg#else 223d522f475Smrg Panic("input: read returned zero\n", 0); 224d522f475Smrg#endif 225d522f475Smrg } 226956cc18dSsnj#endif /* f*ugly */ 227d522f475Smrg } 228d522f475Smrg#endif /* VMS */ 229d522f475Smrg 230d522f475Smrg if (size) { 231d522f475Smrg#if OPT_TRACE 232d522f475Smrg int i; 233d522f475Smrg 234d522f475Smrg TRACE(("read %d bytes from pty\n", size)); 235d522f475Smrg for (i = 0; i < size; i++) { 236d522f475Smrg if (!(i % 16)) 237d522f475Smrg TRACE(("%s", i ? "\n " : "READ")); 238d522f475Smrg TRACE((" %02X", data->last[i])); 239d522f475Smrg } 240d522f475Smrg TRACE(("\n")); 241d522f475Smrg#endif 242d522f475Smrg data->last += size; 243d522f475Smrg#ifdef ALLOWLOGGING 24420d2c4d2Smrg TScreenOf(term)->logstart = VTbuffer->next; 245d522f475Smrg#endif 246d522f475Smrg } 247d522f475Smrg 248d522f475Smrg return (size); 249d522f475Smrg} 250d522f475Smrg 251d522f475Smrg/* 252d522f475Smrg * Return the next value from the input buffer. Note that morePtyData() is 253d522f475Smrg * always called before this function, so we can do the UTF-8 input conversion 254d522f475Smrg * in that function and simply return the result here. 255d522f475Smrg */ 256d522f475Smrg#if OPT_WIDE_CHARS 257d522f475SmrgIChar 258894e0ac8SmrgnextPtyData(TScreen *screen, PtyData *data) 259d522f475Smrg{ 260d522f475Smrg IChar result; 261d522f475Smrg if (screen->utf8_inparse) { 262d522f475Smrg result = skipPtyData(data); 263d522f475Smrg } else { 264d522f475Smrg result = *((data)->next++); 265956cc18dSsnj if (!screen->output_eight_bits) { 266956cc18dSsnj result = (IChar) (result & 0x7f); 267956cc18dSsnj } 268d522f475Smrg } 269d522f475Smrg TRACE2(("nextPtyData returns %#x\n", result)); 270d522f475Smrg return result; 271d522f475Smrg} 272d522f475Smrg 273d522f475Smrg/* 274d522f475Smrg * Simply return the data and skip past it. 275d522f475Smrg */ 276d522f475SmrgIChar 277894e0ac8SmrgskipPtyData(PtyData *data) 278d522f475Smrg{ 279d522f475Smrg IChar result = data->utf_data; 280d522f475Smrg 281d522f475Smrg data->next += data->utf_size; 282d522f475Smrg data->utf_size = 0; 283d522f475Smrg 284d522f475Smrg return result; 285d522f475Smrg} 286d522f475Smrg#endif 287d522f475Smrg 288d522f475Smrg#if OPT_WIDE_CHARS 289d522f475Smrg/* 290d522f475Smrg * Called when UTF-8 mode has been turned on/off. 291d522f475Smrg */ 292d522f475Smrgvoid 293894e0ac8SmrgswitchPtyData(TScreen *screen, int flag) 294d522f475Smrg{ 295d522f475Smrg if (screen->utf8_mode != flag) { 296d522f475Smrg screen->utf8_mode = flag; 297956cc18dSsnj screen->utf8_inparse = (Boolean) (flag != 0); 298d522f475Smrg 299d522f475Smrg TRACE(("turning UTF-8 mode %s\n", BtoS(flag))); 300d522f475Smrg update_font_utf8_mode(); 301d522f475Smrg } 302d522f475Smrg} 303d522f475Smrg#endif 304d522f475Smrg 305d522f475Smrg/* 306d522f475Smrg * Allocate a buffer. 307d522f475Smrg */ 308d522f475Smrgvoid 309894e0ac8SmrginitPtyData(PtyData **result) 310d522f475Smrg{ 311d522f475Smrg PtyData *data; 312d522f475Smrg 313d522f475Smrg TRACE(("initPtyData given minBufSize %d, maxBufSize %d\n", 314d522f475Smrg FRG_SIZE, BUF_SIZE)); 315d522f475Smrg 316d522f475Smrg if (FRG_SIZE < 64) 317d522f475Smrg FRG_SIZE = 64; 318d522f475Smrg if (BUF_SIZE < FRG_SIZE) 319d522f475Smrg BUF_SIZE = FRG_SIZE; 320d522f475Smrg if (BUF_SIZE % FRG_SIZE) 321d522f475Smrg BUF_SIZE = BUF_SIZE + FRG_SIZE - (BUF_SIZE % FRG_SIZE); 322d522f475Smrg 323d522f475Smrg TRACE(("initPtyData using minBufSize %d, maxBufSize %d\n", 324d522f475Smrg FRG_SIZE, BUF_SIZE)); 325d522f475Smrg 326a1f3da82Smrg data = TypeXtMallocX(PtyData, (BUF_SIZE + FRG_SIZE)); 327d522f475Smrg 328d522f475Smrg memset(data, 0, sizeof(*data)); 329d522f475Smrg data->next = data->buffer; 330d522f475Smrg data->last = data->buffer; 331d522f475Smrg *result = data; 332d522f475Smrg} 333d522f475Smrg 334d522f475Smrg/* 33520d2c4d2Smrg * Initialize a buffer for the caller, using its data in 'next'. 336d522f475Smrg */ 337d522f475Smrg#if OPT_WIDE_CHARS 338d522f475SmrgPtyData * 339894e0ac8SmrgfakePtyData(PtyData *result, Char *next, Char *last) 340d522f475Smrg{ 341d522f475Smrg PtyData *data = result; 342d522f475Smrg 343d522f475Smrg memset(data, 0, sizeof(*data)); 344d522f475Smrg data->next = next; 345d522f475Smrg data->last = last; 346d522f475Smrg 347d522f475Smrg return data; 348d522f475Smrg} 349d522f475Smrg#endif 350d522f475Smrg 351d522f475Smrg/* 352d522f475Smrg * Remove used data by shifting the buffer down, to make room for more data, 353d522f475Smrg * e.g., a continuation-read. 354d522f475Smrg */ 355d522f475Smrgvoid 356894e0ac8SmrgtrimPtyData(XtermWidget xw GCC_UNUSED, PtyData *data) 357d522f475Smrg{ 358d522f475Smrg int i; 359d522f475Smrg 36020d2c4d2Smrg FlushLog(xw); 361d522f475Smrg 362d522f475Smrg if (data->next != data->buffer) { 36320d2c4d2Smrg int n = (int) (data->last - data->next); 364d522f475Smrg 365d522f475Smrg TRACE(("shifting buffer down by %d\n", n)); 366d522f475Smrg for (i = 0; i < n; ++i) { 367d522f475Smrg data->buffer[i] = data->next[i]; 368d522f475Smrg } 369d522f475Smrg data->next = data->buffer; 370d522f475Smrg data->last = data->next + n; 371d522f475Smrg } 372d522f475Smrg 373d522f475Smrg} 374d522f475Smrg 375d522f475Smrg/* 376d522f475Smrg * Insert new data into the input buffer so the next calls to morePtyData() 377d522f475Smrg * and nextPtyData() will return that. 378d522f475Smrg */ 379d522f475Smrgvoid 380894e0ac8SmrgfillPtyData(XtermWidget xw, PtyData *data, const char *value, int length) 381d522f475Smrg{ 382d522f475Smrg int size; 383d522f475Smrg int n; 384d522f475Smrg 385d522f475Smrg /* remove the used portion of the buffer */ 38620d2c4d2Smrg trimPtyData(xw, data); 387d522f475Smrg 388d522f475Smrg VTbuffer->last += length; 38920d2c4d2Smrg size = (int) (VTbuffer->last - VTbuffer->next); 390d522f475Smrg 391d522f475Smrg /* shift the unused portion up to make room */ 392d522f475Smrg for (n = size; n >= length; --n) 393d522f475Smrg VTbuffer->next[n] = VTbuffer->next[n - length]; 394d522f475Smrg 395d522f475Smrg /* insert the new bytes to interpret */ 396d522f475Smrg for (n = 0; n < length; n++) 397d522f475Smrg VTbuffer->next[n] = CharOf(value[n]); 398d522f475Smrg} 399d522f475Smrg 400d522f475Smrg#if OPT_WIDE_CHARS 401d522f475SmrgChar * 402894e0ac8SmrgconvertToUTF8(Char *lp, unsigned c) 403d522f475Smrg{ 40420d2c4d2Smrg#define CH(n) (Char)((c) >> ((n) * 8)) 40520d2c4d2Smrg if (c < 0x80) { 40620d2c4d2Smrg /* 0******* */ 40720d2c4d2Smrg *lp++ = (Char) CH(0); 40820d2c4d2Smrg } else if (c < 0x800) { 40920d2c4d2Smrg /* 110***** 10****** */ 41020d2c4d2Smrg *lp++ = (Char) (0xc0 | (CH(0) >> 6) | ((CH(1) & 0x07) << 2)); 41120d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(0) & 0x3f)); 41220d2c4d2Smrg } else if (c < 0x00010000) { 41320d2c4d2Smrg /* 1110**** 10****** 10****** */ 41420d2c4d2Smrg *lp++ = (Char) (0xe0 | ((int) (CH(1) & 0xf0) >> 4)); 41520d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2)); 41620d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(0) & 0x3f)); 41720d2c4d2Smrg } else if (c < 0x00200000) { 41820d2c4d2Smrg *lp++ = (Char) (0xf0 | ((int) (CH(2) & 0x1f) >> 2)); 41920d2c4d2Smrg *lp++ = (Char) (0x80 | 42020d2c4d2Smrg ((int) (CH(1) & 0xf0) >> 4) | 42120d2c4d2Smrg ((int) (CH(2) & 0x03) << 4)); 42220d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2)); 42320d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(0) & 0x3f)); 42420d2c4d2Smrg } else if (c < 0x04000000) { 42520d2c4d2Smrg *lp++ = (Char) (0xf8 | (CH(3) & 0x03)); 42620d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(2) >> 2)); 42720d2c4d2Smrg *lp++ = (Char) (0x80 | 42820d2c4d2Smrg ((int) (CH(1) & 0xf0) >> 4) | 42920d2c4d2Smrg ((int) (CH(2) & 0x03) << 4)); 43020d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2)); 43120d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(0) & 0x3f)); 43220d2c4d2Smrg } else { 43320d2c4d2Smrg *lp++ = (Char) (0xfc | ((int) (CH(3) & 0x40) >> 6)); 43420d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(3) & 0x3f)); 43520d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(2) >> 2)); 43620d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(1) >> 4) | ((CH(2) & 0x03) << 4)); 43720d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2)); 43820d2c4d2Smrg *lp++ = (Char) (0x80 | (CH(0) & 0x3f)); 439d522f475Smrg } 440d522f475Smrg return lp; 44120d2c4d2Smrg#undef CH 442d522f475Smrg} 443d522f475Smrg 444d522f475Smrg/* 445d522f475Smrg * Write data back to the PTY 446d522f475Smrg */ 447d522f475Smrgvoid 448894e0ac8SmrgwritePtyData(int f, IChar *d, unsigned len) 449d522f475Smrg{ 450d522f475Smrg unsigned n = (len << 1); 451d522f475Smrg 452d522f475Smrg if (VTbuffer->write_len <= len) { 453d522f475Smrg VTbuffer->write_len = n; 454d522f475Smrg VTbuffer->write_buf = (Char *) XtRealloc((char *) 455d522f475Smrg VTbuffer->write_buf, VTbuffer->write_len); 456d522f475Smrg } 457d522f475Smrg 458d522f475Smrg for (n = 0; n < len; n++) 459956cc18dSsnj VTbuffer->write_buf[n] = (Char) d[n]; 460d522f475Smrg 461d522f475Smrg TRACE(("writePtyData %d:%s\n", n, 462956cc18dSsnj visibleChars(VTbuffer->write_buf, n))); 463d522f475Smrg v_write(f, VTbuffer->write_buf, n); 464d522f475Smrg} 465d522f475Smrg#endif /* OPT_WIDE_CHARS */ 466d522f475Smrg 467d522f475Smrg#ifdef NO_LEAKS 468d522f475Smrgvoid 469d522f475Smrgnoleaks_ptydata(void) 470d522f475Smrg{ 471d522f475Smrg if (VTbuffer != 0) { 472d522f475Smrg#if OPT_WIDE_CHARS 473d522f475Smrg if (VTbuffer->write_buf != 0) 474d522f475Smrg free(VTbuffer->write_buf); 475d522f475Smrg#endif 476d522f475Smrg free(VTbuffer); 477d522f475Smrg VTbuffer = 0; 478d522f475Smrg } 479d522f475Smrg} 480d522f475Smrg#endif 481