diff --git a/src/apps/terminal/BasicTerminalBuffer.cpp b/src/apps/terminal/BasicTerminalBuffer.cpp index f21124de47..f5bcd6199a 100644 --- a/src/apps/terminal/BasicTerminalBuffer.cpp +++ b/src/apps/terminal/BasicTerminalBuffer.cpp @@ -429,7 +429,8 @@ BasicTerminalBuffer::FindWord(const TermPos& pos, // find the beginning TermPos start(x, y); - TermPos end(x + (IS_WIDTH(line->cells[x].attributes) ? 2 : 1), y); + TermPos end(x + (IS_WIDTH(line->cells[x].attributes) + ? FULL_WIDTH : HALF_WIDTH), y); while (true) { if (--x < 0) { // Hit the beginning of the line -- continue at the end of the @@ -470,7 +471,7 @@ BasicTerminalBuffer::FindWord(const TermPos& pos, if (classifier->Classify(line->cells[x].character) != type) break; - x += IS_WIDTH(line->cells[x].attributes) ? 2 : 1; + x += IS_WIDTH(line->cells[x].attributes) ? FULL_WIDTH : HALF_WIDTH; end.SetTo(x, y); } @@ -606,14 +607,13 @@ BasicTerminalBuffer::Find(const char* _pattern, const TermPos& start, void -BasicTerminalBuffer::InsertChar(UTF8Char c, uint32 width) +BasicTerminalBuffer::InsertChar(UTF8Char c) { //debug_printf("BasicTerminalBuffer::InsertChar('%.*s' (%d), %#lx)\n", //(int)c.ByteCount(), c.bytes, c.bytes[0], attributes); - if ((int32)width == FULL_WIDTH) - fAttributes |= A_WIDTH; + int32 width = c.IsFullWidth() ? FULL_WIDTH : HALF_WIDTH; - if (fSoftWrappedCursor || fCursor.x + (int32)width > fWidth) + if (fSoftWrappedCursor || (fCursor.x + width) > fWidth) _SoftBreakLine(); else _PadLineToCursor(); @@ -625,7 +625,8 @@ BasicTerminalBuffer::InsertChar(UTF8Char c, uint32 width) TerminalLine* line = _LineAt(fCursor.y); line->cells[fCursor.x].character = c; - line->cells[fCursor.x].attributes = fAttributes; + line->cells[fCursor.x].attributes + = fAttributes | (width == FULL_WIDTH ? A_WIDTH : 0); if (line->length < fCursor.x + width) line->length = fCursor.x + width; @@ -645,10 +646,13 @@ BasicTerminalBuffer::InsertChar(UTF8Char c, uint32 width) void -BasicTerminalBuffer::FillScreen(UTF8Char c, uint32 width, uint32 attributes) +BasicTerminalBuffer::FillScreen(UTF8Char c, uint32 attributes) { - if ((int32)width == FULL_WIDTH) + uint32 width = HALF_WIDTH; + if (c.IsFullWidth()) { attributes |= A_WIDTH; + width = FULL_WIDTH; + } fSoftWrappedCursor = false; @@ -1724,7 +1728,9 @@ BasicTerminalBuffer::MakeLinesSnapshots(time_t timeStamp, const char* fileName) fprintf(fileOut, "%02" B_PRId16 ":%02" B_PRId16 ":%08" B_PRIx32 ":\n", i, line->length, line->attributes); for (int j = 0; j < line->length; j++) - fprintf(fileOut, "%c", line->cells[j].character.bytes[0]); + if (line->cells[j].character.bytes[0] != 0) + fwrite(line->cells[j].character.bytes, 1, + line->cells[j].character.ByteCount(), fileOut); fprintf(fileOut, "\n"); for (int s = 28; s >= 0; s -= 4) { @@ -1762,7 +1768,8 @@ BasicTerminalBuffer::StartStopDebugCapture() struct tm* ts = gmtime(&timeStamp); str << ts->tm_hour << ts->tm_min << ts->tm_sec; str << ".Capture.log"; - fCaptureFile = open(str.String(), O_CREAT | O_WRONLY); + fCaptureFile = open(str.String(), O_CREAT | O_WRONLY, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); } diff --git a/src/apps/terminal/BasicTerminalBuffer.h b/src/apps/terminal/BasicTerminalBuffer.h index 2dca366872..ed30bb09f2 100644 --- a/src/apps/terminal/BasicTerminalBuffer.h +++ b/src/apps/terminal/BasicTerminalBuffer.h @@ -122,13 +122,8 @@ public: void CaptureChar(char ch); // insert chars/lines - inline void InsertChar(UTF8Char c); - void InsertChar(UTF8Char c, uint32 width); - inline void InsertChar(const char* c); - inline void InsertChar(const char* c, int32 length); - inline void InsertChar(const char* c, int32 length, - uint32 width); - void FillScreen(UTF8Char c, uint32 width, uint32 attr); + void InsertChar(UTF8Char c); + void FillScreen(UTF8Char c, uint32 attr); void InsertCR(); void InsertLF(); @@ -273,34 +268,6 @@ BasicTerminalBuffer::SetAttributes(uint32 attributes) } -void -BasicTerminalBuffer::InsertChar(UTF8Char c) -{ - return InsertChar(c, 1); -} - - -void -BasicTerminalBuffer::InsertChar(const char* c) -{ - return InsertChar(UTF8Char(c), 1); -} - - -void -BasicTerminalBuffer::InsertChar(const char* c, int32 length) -{ - return InsertChar(UTF8Char(c, length), 1); -} - - -void -BasicTerminalBuffer::InsertChar(const char* c, int32 length, uint32 width) -{ - return InsertChar(UTF8Char(c, length), width); -} - - void BasicTerminalBuffer::EraseChars(int32 numChars) { diff --git a/src/apps/terminal/TermConst.h b/src/apps/terminal/TermConst.h index 0471b1cc8e..942d9215d8 100644 --- a/src/apps/terminal/TermConst.h +++ b/src/apps/terminal/TermConst.h @@ -159,8 +159,10 @@ enum { static const int32 DEFAULT = -1; // Font Width -static const int HALF_WIDTH = 1; -static const int FULL_WIDTH = 2; +enum { + HALF_WIDTH = 1, + FULL_WIDTH = 2 +}; #define M_UTF8 -1 diff --git a/src/apps/terminal/TermParse.cpp b/src/apps/terminal/TermParse.cpp index ece385aa1e..86b0653e82 100644 --- a/src/apps/terminal/TermParse.cpp +++ b/src/apps/terminal/TermParse.cpp @@ -481,7 +481,7 @@ TermParse::EscParse() dstbuf, &dstLen, &dummyState, '?'); } - fBuffer->InsertChar(dstbuf, dstLen, width); + fBuffer->InsertChar(UTF8Char(dstbuf, dstLen)); break; case CASE_PRINT_CS96: @@ -493,7 +493,7 @@ TermParse::EscParse() dstLen = sizeof(dstbuf); convert_to_utf8(B_EUC_CONVERSION, cbuf, &srcLen, dstbuf, &dstLen, &dummyState, '?'); - fBuffer->InsertChar(dstbuf, dstLen); + fBuffer->InsertChar(UTF8Char(dstbuf, dstLen)); break; case CASE_LF: @@ -511,7 +511,7 @@ TermParse::EscParse() dstLen = sizeof(dstbuf); convert_to_utf8(currentEncoding, cbuf, &srcLen, dstbuf, &dstLen, &dummyState, '?'); - fBuffer->InsertChar(dstbuf, dstLen); + fBuffer->InsertChar(UTF8Char(dstbuf, dstLen)); break; case CASE_SJIS_INSTRING: @@ -523,7 +523,7 @@ TermParse::EscParse() dstLen = sizeof(dstbuf); convert_to_utf8(currentEncoding, cbuf, &srcLen, dstbuf, &dstLen, &dummyState, '?'); - fBuffer->InsertChar(dstbuf, dstLen); + fBuffer->InsertChar(UTF8Char(dstbuf, dstLen)); break; case CASE_UTF8_2BYTE: @@ -534,7 +534,7 @@ TermParse::EscParse() cbuf[1] = c; cbuf[2] = '\0'; - fBuffer->InsertChar(cbuf, 2); + fBuffer->InsertChar(UTF8Char(cbuf, 2)); break; case CASE_UTF8_3BYTE: @@ -549,7 +549,7 @@ TermParse::EscParse() break; cbuf[2] = c; cbuf[3] = '\0'; - fBuffer->InsertChar(cbuf, 3); + fBuffer->InsertChar(UTF8Char(cbuf, 3)); break; case CASE_MBCS: @@ -1029,7 +1029,7 @@ TermParse::EscParse() case CASE_DECALN: /* DECALN */ - fBuffer->FillScreen(UTF8Char('E'), 1, 0); + fBuffer->FillScreen(UTF8Char('E'), 0); parsestate = groundtable; break; diff --git a/src/apps/terminal/TermView.cpp b/src/apps/terminal/TermView.cpp index 17d2d428c7..89faf10feb 100644 --- a/src/apps/terminal/TermView.cpp +++ b/src/apps/terminal/TermView.cpp @@ -498,8 +498,9 @@ TermView::_ConvertFromTerminal(const TermPos &pos) inline void TermView::_InvalidateTextRect(int32 x1, int32 y1, int32 x2, int32 y2) { + // assume the worst case with full-width characters - invalidate 2 cells BRect rect(x1 * fFontWidth, _LineOffset(y1), - (x2 + 1) * fFontWidth - 1, _LineOffset(y2 + 1) - 1); + (x2 + 1) * fFontWidth * 2 - 1, _LineOffset(y2 + 1) - 1); //debug_printf("Invalidate((%f, %f) - (%f, %f))\n", rect.left, rect.top, //rect.right, rect.bottom); Invalidate(rect); @@ -1030,12 +1031,8 @@ TermView::_DrawCursor() if (fVisibleTextBuffer->GetChar(fCursor.y - firstVisible, fCursor.x, character, attr) == A_CHAR && (fCursorStyle == BLOCK_CURSOR || !cursorVisible)) { - int32 width; - if (IS_WIDTH(attr)) - width = 2; - else - width = 1; + int32 width = IS_WIDTH(attr) ? FULL_WIDTH : HALF_WIDTH; char buffer[5]; int32 bytes = UTF8Char::ByteCount(character.bytes[0]); memcpy(buffer, character.bytes, bytes); @@ -1064,6 +1061,9 @@ TermView::_DrawCursor() SetHighColor(rgb_back); } + if (IS_WIDTH(attr) && fCursorStyle != IBEAM_CURSOR) + rect.right += fFontWidth; + FillRect(rect); } } @@ -1287,8 +1287,13 @@ TermView::Draw(BRect updateRect) continue; } + // Note: full-width characters GetString()-ed always + // with count 1, so this hardcoding is safe. From the other + // side - drawing the whole string with one call render the + // characters not aligned to cells grid - that looks much more + // inaccurate for full-width strings than for half-width ones. if (IS_WIDTH(attr)) - count = 2; + count = FULL_WIDTH; _DrawLinePart(fFontWidth * i, (int32)_LineOffset(j), attr, buf, count, insideSelection, false, this); diff --git a/src/apps/terminal/UTF8Char.h b/src/apps/terminal/UTF8Char.h index 1e911b81c7..ffac26da80 100644 --- a/src/apps/terminal/UTF8Char.h +++ b/src/apps/terminal/UTF8Char.h @@ -65,7 +65,13 @@ struct UTF8Char { bool IsFullWidth() const { - // TODO: Implement! + switch (BUnicodeChar::EastAsianWidth(BUnicodeChar::FromUTF8(bytes))) { + case B_UNICODE_EA_FULLWIDTH: + case B_UNICODE_EA_WIDE: + return true; + default: + break; + } return false; }