TermView::Draw():

* Apparently Draw() can be invoked with new view bounds in effect before the
  FrameResized() hook has been invoked (I suppose that's not really kosher).
  Since TermView updates the terminal dimensions in FrameResized() and relied
  on the update rect passed to Draw() to translate to positions within the
  limits, an on-stack buffer could overflow, leading to #2851. Now we clamp
  the translated positions to terminal size.
* Draw the background areas right of the last column and below the last row
  explicitly instead of drawing an additional non-existing partial
  character/row.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35587 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2010-02-23 15:39:30 +00:00
parent 28eaa574fd
commit f6cace5aa2

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2009, Haiku, Inc.
* Copyright 2001-2010, Haiku, Inc.
* Copyright 2003-2004 Kian Duffy, myob@users.sourceforge.net
* Parts Copyright 1998-1999 Kazuho Okui and Takashi Murai.
* All rights reserved. Distributed under the terms of the MIT license.
@ -13,7 +13,6 @@
*/
#include "TermView.h"
#include <ctype.h>
@ -1090,55 +1089,80 @@ TermView::Draw(BRect updateRect)
// }
// }
int32 x1 = (int32)(updateRect.left) / fFontWidth;
int32 x2 = (int32)(updateRect.right) / fFontWidth;
int32 x1 = (int32)updateRect.left / fFontWidth;
int32 x2 = std::min((int)updateRect.right / fFontWidth, fColumns - 1);
int32 firstVisible = _LineAt(0);
int32 y1 = _LineAt(updateRect.top);
int32 y2 = _LineAt(updateRect.bottom);
int32 y2 = std::min(_LineAt(updateRect.bottom), (int32)fRows - 1);
//debug_printf("TermView::Draw(): (%ld, %ld) - (%ld, %ld), top: %f, fontHeight: %d, scrollOffset: %f\n",
//x1, y1, x2, y2, updateRect.top, fFontHeight, fScrollOffset);
for (int32 j = y1; j <= y2; j++) {
int32 k = x1;
char buf[fColumns * 4 + 1];
// clear the area to the right of the line ends
if (y1 <= y2) {
float clearLeft = fColumns * fFontWidth;
if (clearLeft < updateRect.right) {
BRect rect(clearLeft, updateRect.top, updateRect.right,
updateRect.bottom);
SetHighColor(fTextBackColor);
FillRect(rect);
}
}
if (fVisibleTextBuffer->IsFullWidthChar(j - firstVisible, k))
k--;
// clear the area below the last line
if (y2 == fRows - 1) {
float clearTop = _LineOffset(fRows);
if (clearTop < updateRect.bottom) {
BRect rect(updateRect.left, clearTop, updateRect.right,
updateRect.bottom);
SetHighColor(fTextBackColor);
FillRect(rect);
}
}
if (k < 0)
k = 0;
// draw the affected line parts
if (x1 <= x2) {
for (int32 j = y1; j <= y2; j++) {
int32 k = x1;
char buf[fColumns * 4 + 1];
for (int32 i = k; i <= x2;) {
int32 lastColumn = x2;
bool insideSelection = _CheckSelectedRegion(j, i, lastColumn);
uint16 attr;
int32 count = fVisibleTextBuffer->GetString(j - firstVisible, i,
lastColumn, buf, attr);
if (fVisibleTextBuffer->IsFullWidthChar(j - firstVisible, k))
k--;
if (k < 0)
k = 0;
for (int32 i = k; i <= x2;) {
int32 lastColumn = x2;
bool insideSelection = _CheckSelectedRegion(j, i, lastColumn);
uint16 attr;
int32 count = fVisibleTextBuffer->GetString(j - firstVisible, i,
lastColumn, buf, attr);
//debug_printf(" fVisibleTextBuffer->GetString(%ld, %ld, %ld) -> (%ld, \"%.*s\"), selected: %d\n",
//j - firstVisible, i, lastColumn, count, (int)count, buf, insideSelection);
if (count == 0) {
BRect rect(fFontWidth * i, _LineOffset(j),
fFontWidth * (lastColumn + 1) - 1, 0);
rect.bottom = rect.top + fFontHeight - 1;
if (count == 0) {
BRect rect(fFontWidth * i, _LineOffset(j),
fFontWidth * (lastColumn + 1) - 1, 0);
rect.bottom = rect.top + fFontHeight - 1;
SetHighColor(insideSelection ? fSelectBackColor
: fTextBackColor);
FillRect(rect);
SetHighColor(insideSelection ? fSelectBackColor
: fTextBackColor);
FillRect(rect);
i = lastColumn + 1;
continue;
i = lastColumn + 1;
continue;
}
if (IS_WIDTH(attr))
count = 2;
_DrawLinePart(fFontWidth * i, (int32)_LineOffset(j),
attr, buf, count, insideSelection, false, this);
i += count;
}
if (IS_WIDTH(attr))
count = 2;
_DrawLinePart(fFontWidth * i, (int32)_LineOffset(j),
attr, buf, count, insideSelection, false, this);
i += count;
}
}