diff --git a/src/apps/terminal/BasicTerminalBuffer.cpp b/src/apps/terminal/BasicTerminalBuffer.cpp index f5bcd6199a..dfbb54e28d 100644 --- a/src/apps/terminal/BasicTerminalBuffer.cpp +++ b/src/apps/terminal/BasicTerminalBuffer.cpp @@ -431,48 +431,31 @@ BasicTerminalBuffer::FindWord(const TermPos& pos, TermPos start(x, 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 - // previous line, if it soft-breaks. - y--; - if ((line = _HistoryLineAt(y, lineBuffer)) == NULL - || !line->softBreak || line->length == 0) { - break; - } - x = line->length - 1; - } - if (x > 0 && IS_WIDTH(line->cells[x - 1].attributes)) - x--; - - if (classifier->Classify(line->cells[x].character) != type) + for (;;) { + TermPos previousPos = start; + if (!_PreviousLinePos(lineBuffer, line, previousPos) + || classifier->Classify(line->cells[previousPos.x].character) + != type) { break; + } - start.SetTo(x, y); + start = previousPos; } // find the end - x = end.x; - y = end.y; - line = _HistoryLineAt(y, lineBuffer); + line = _HistoryLineAt(end.y, lineBuffer); - while (true) { - if (x >= line->length) { - // Hit the end of the line -- if it soft-breaks continue with the - // next line. - if (!line->softBreak) - break; - y++; - x = 0; - if ((line = _HistoryLineAt(y, lineBuffer)) == NULL) - break; - } - - if (classifier->Classify(line->cells[x].character) != type) + for (;;) { + TermPos nextPos = end; + if (!_NormalizeLinePos(lineBuffer, line, nextPos)) break; - x += IS_WIDTH(line->cells[x].attributes) ? FULL_WIDTH : HALF_WIDTH; - end.SetTo(x, y); + if (classifier->Classify(line->cells[nextPos.x].character) != type) + break; + + nextPos.x += IS_WIDTH(line->cells[nextPos.x].attributes) + ? FULL_WIDTH : HALF_WIDTH; + end = nextPos; } _start = start; @@ -481,6 +464,34 @@ BasicTerminalBuffer::FindWord(const TermPos& pos, } +bool +BasicTerminalBuffer::PreviousLinePos(TermPos& pos) const +{ + TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth); + TerminalLine* line = _HistoryLineAt(pos.y, lineBuffer); + if (line == NULL || pos.x < 0 || pos.x >= fWidth) + return false; + + return _PreviousLinePos(lineBuffer, line, pos); +} + + +bool +BasicTerminalBuffer::NextLinePos(TermPos& pos, bool normalize) const +{ + TerminalLine* lineBuffer = ALLOC_LINE_ON_STACK(fWidth); + TerminalLine* line = _HistoryLineAt(pos.y, lineBuffer); + if (line == NULL || pos.x < 0 || pos.x > fWidth) + return false; + + if (!_NormalizeLinePos(lineBuffer, line, pos)) + return false; + + pos.x += IS_WIDTH(line->cells[pos.x].attributes) ? FULL_WIDTH : HALF_WIDTH; + return !normalize || _NormalizeLinePos(lineBuffer, line, pos); +} + + int32 BasicTerminalBuffer::LineLength(int32 index) const { @@ -1692,6 +1703,46 @@ BasicTerminalBuffer::_NextChar(TermPos& pos, UTF8Char& c) const } +bool +BasicTerminalBuffer::_PreviousLinePos(TerminalLine* lineBuffer, + TerminalLine*& line, TermPos& pos) const +{ + if (--pos.x < 0) { + // Hit the beginning of the line -- continue at the end of the + // previous line, if it soft-breaks. + pos.y--; + if ((line = _HistoryLineAt(pos.y, lineBuffer)) == NULL + || !line->softBreak || line->length == 0) { + return false; + } + pos.x = line->length - 1; + } + if (pos.x > 0 && IS_WIDTH(line->cells[pos.x - 1].attributes)) + pos.x--; + + return true; +} + + +bool +BasicTerminalBuffer::_NormalizeLinePos(TerminalLine* lineBuffer, + TerminalLine*& line, TermPos& pos) const +{ + if (pos.x < line->length) + return true; + + // Hit the end of the line -- if it soft-breaks continue with the + // next line. + if (!line->softBreak) + return false; + + pos.y++; + pos.x = 0; + line = _HistoryLineAt(pos.y, lineBuffer); + return line != NULL; +} + + #ifdef USE_DEBUG_SNAPSHOTS void diff --git a/src/apps/terminal/BasicTerminalBuffer.h b/src/apps/terminal/BasicTerminalBuffer.h index ed30bb09f2..757984f6b2 100644 --- a/src/apps/terminal/BasicTerminalBuffer.h +++ b/src/apps/terminal/BasicTerminalBuffer.h @@ -107,6 +107,14 @@ public: int32 LineLength(int32 index) const; int32 GetLineColor(int32 index) const; + bool PreviousLinePos(TermPos& pos) const; + bool NextLinePos(TermPos& pos, bool normalize) const; + // normalize specifies that the returned + // position must be a valid position, i.e. + // actually point to a character (as opposed + // to just pointing to the position after a + // character). + bool Find(const char* pattern, const TermPos& start, bool forward, bool caseSensitive, bool matchWord, TermPos& matchStart, @@ -205,6 +213,11 @@ protected: bool _PreviousChar(TermPos& pos, UTF8Char& c) const; bool _NextChar(TermPos& pos, UTF8Char& c) const; + bool _PreviousLinePos(TerminalLine* lineBuffer, + TerminalLine*& line, TermPos& pos) const; + bool _NormalizeLinePos(TerminalLine* lineBuffer, + TerminalLine*& line, TermPos& pos) const; + protected: // screen width/height int32 fWidth;