*
* $Id$
*
- * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2009-2013, MinGW.org Project
+ * Written by Keith Marshall <keith@users.osdn.me>
+ * Copyright (C) 2009-2013, 2020, MinGW.org Project
*
*
* Implementation of GUI specific API extensions, providing support
*/
#define DMH_PTY_MIN_BUFSIZ 4096
#define DMH_PTY_MAX_BUFSIZ 32768
+#define DMH_PTY_GUARDBYTES 1
class dmhTypePTY
{
{
/* An explicit '\r' in the data stream should return the
* caret to the start of the current PHYSICAL line in the
- * EDITTEXT display
- *
- * FIXME: must implement this; ignore, (and discount), it
- * for now.
+ * EDITTEXT display.
+ */
+ char *mark = caret;
+ while( (mark > console_buffer) && (*--mark != '\n') )
+ caret = mark;
+
+ /* The '\r' character isn't actually written to the
+ * output buffer; discount it.
*/
--retval;
}
{
/* Helper method for appending a single character to the PTY "device"
* buffer; this will allocate an expanding buffer, (up to the maximum
- * specified size limit), as may be required.
+ * specified size limit, with reservation of sufficient guard bytes to
+ * ensure that output may be safely terminated), as may be required.
*/
size_t offset;
- if( (offset = caret - console_buffer) >= max )
+ const size_t guarded_max = max - DMH_PTY_GUARDBYTES;
+ if( (offset = caret - console_buffer) >= guarded_max )
{
/* The current "device" buffer is full; compute a new size, for
* possible buffer expansion.
caret = (console_buffer = newbuf) + offset;
}
}
- if( offset >= max )
+ if( offset >= guarded_max )
{
/* The buffer has reached its maximum permitted size, (or there
* was insufficient free memory to expand it), and there still
/* ...then copy it, and all following lines, to the start of the
* buffer, so deleting the FIRST logical line, and thus free up
* an equivalent amount of space at the end.
+ *
+ * Note: we might get away with a single memcpy() of the entire
+ * portion of the buffer, from the SECOND line onward, backwards
+ * to overwrite the FIRST line, but that would entail copying of
+ * overlapping memory regions, which is technically described as
+ * causing undefined behaviour; to avoid any possible problems,
+ * we identify a block size equal to the space occupied by the
+ * first line...
*/
- for( caret = console_buffer; mark < endptr; )
- *caret++ = *mark++;
+ size_t residual = caret - mark;
+ size_t block_size = mark - (caret = console_buffer);
+ while( residual >= block_size )
+ {
+ /* ...then copy the residual, in chunks of that size, (so that
+ * there is never any overlap), until we reduce the residual to
+ * less than the block size...
+ */
+ memcpy( caret, mark, block_size );
+ residual -= block_size; caret = mark; mark += block_size;
+ }
+ if( residual > 0 )
+ {
+ /* ...finishing up by copying any lesser sized final residual,
+ * and leaving the caret at the start of the space so freed.
+ */
+ memcpy( caret, mark, residual );
+ caret += residual;
+ }
}
}
/* Finally, store the current character into the "device" buffer, and
* to the buffered collection.
*/
msglen += vsprintf( (msgbuf = newbuf) + msglen, fmt, argv );
+ return newlen - 1;
}
}
else if( (msgbuf = (char *)(malloc( newlen ))) != NULL )
mode = code | (mode & ~DMH_SEVERITY_MASK);
return dispatch_message( vsprintf( msgbuf, fmt, argv ) );
}
+ /* If we get to here, then no message was dispatched; the
+ * effective message length should be returned as zero.
+ */
+ return 0;
}
static inline HWND last_active_popup( HWND owner )