Skip to content

Commit c757578

Browse files
committed
platform: Properly check if it is necessary to copy data in DisplayBuffer::screenWrite
1 parent 5a9d715 commit c757578

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

source/platform/dispbuff.cpp

+14-5
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,22 @@ void DisplayBuffer::setCaretPosition(int x, int y) noexcept
8282

8383
void DisplayBuffer::screenWrite(int x, int y, TScreenCell *buf, int len) noexcept
8484
{
85-
if (inBounds(x, y) && len)
85+
if (inBounds(x, y) && len > 0)
8686
{
8787
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));
92101

93102
setDirty(x, y, len);
94103
screenTouched = true;

0 commit comments

Comments
 (0)