@@ -82,13 +82,22 @@ void DisplayBuffer::setCaretPosition(int x, int y) noexcept
82
82
83
83
void DisplayBuffer::screenWrite (int x, int y, TScreenCell *buf, int len) noexcept
84
84
{
85
- if (inBounds (x, y) && len)
85
+ if (inBounds (x, y) && len > 0 )
86
86
{
87
87
len = min (len, size.x - x);
88
- // Since 'buffer' is used as 'TScreen::screenBuffer' and is written to
89
- // directly, we can avoid a copy operation in most cases.
90
- if (buf < buffer.data () || buf >= buffer.data () + buffer.size ())
91
- memcpy (&buffer[y*size.x + x], buf, len*sizeof (TScreenCell));
88
+ TScreenCell *dst = &buffer[y*size.x + x];
89
+ // Since 'buffer' is also used as 'TScreen::screenBuffer' and is
90
+ // directly written into by 'TView::writeView', we can avoid a copy
91
+ // operation in most cases because the data is already there.
92
+ if (buf == dst)
93
+ ; // No need to copy anything.
94
+ // But since 'TScreen::screenBuffer' is public, it is also possible
95
+ // (theoretically) that the source and destination regions overlap each
96
+ // other. Turbo Vision does not do this, but handle this case anyway.
97
+ else if (max (buf, dst) <= min (&buf[len], &dst[len]))
98
+ memmove (dst, buf, len*sizeof (TScreenCell)); // Copy between overlapping regions.
99
+ else
100
+ memcpy (dst, buf, len*sizeof (TScreenCell));
92
101
93
102
setDirty (x, y, len);
94
103
screenTouched = true ;
0 commit comments