| // Copyright 2022 The Pigweed Authors | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not | 
 | // use this file except in compliance with the License. You may obtain a copy of | 
 | // the License at | 
 | // | 
 | //     https://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | 
 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | 
 | // License for the specific language governing permissions and limitations under | 
 | // the License. | 
 |  | 
 | #include "text_buffer.h" | 
 |  | 
 | using pw::color::color_rgb565_t; | 
 | using pw::geometry::Vector2; | 
 |  | 
 | namespace { | 
 | constexpr int kMaxColIdx = kNumCharsWide - 1; | 
 | constexpr int kMaxRowIdx = kNumRows - 1; | 
 |  | 
 | static_assert(kNumRows > 1, "Text buffer too small"); | 
 | }  // namespace | 
 |  | 
 | void TextBuffer::InsertNewline() { | 
 |   if (cursor_.y == kMaxRowIdx) { | 
 |     ScrollUp(); | 
 |   } else { | 
 |     cursor_.y++; | 
 |   } | 
 |   cursor_.x = 0; | 
 | } | 
 |  | 
 | pw::Result<TextBuffer::Char> TextBuffer::GetChar(Vector2<int> loc) const { | 
 |   if (loc.x < 0 || static_cast<size_t>(loc.x) > kMaxColIdx || loc.y < 0 || | 
 |       static_cast<size_t>(loc.y) > kMaxRowIdx) { | 
 |     return pw::Status::OutOfRange(); | 
 |   } | 
 |   return text_rows_[loc.y].chars[loc.x]; | 
 | } | 
 |  | 
 | void TextBuffer::DrawCharacter(const Char& ch) { | 
 |   if (ch.ch == '\n') { | 
 |     InsertNewline(); | 
 |     cursor_.x = 0; | 
 |     return; | 
 |   } | 
 |  | 
 |   if (character_wrap_enabled_ && cursor_.x > kMaxColIdx) { | 
 |     InsertNewline(); | 
 |   } | 
 |  | 
 |   if (cursor_.x > kMaxColIdx) { | 
 |     // The current line has grown too long. | 
 |     return; | 
 |   } | 
 |  | 
 |   PW_ASSERT(cursor_.x >= 0 && cursor_.y >= 0); | 
 |   PW_ASSERT(cursor_.y <= kMaxRowIdx); | 
 |   PW_ASSERT(cursor_.x <= kMaxColIdx); | 
 |  | 
 |   text_rows_[cursor_.y].chars[cursor_.x] = ch; | 
 |  | 
 |   cursor_.x++; | 
 | } | 
 |  | 
 | void TextBuffer::ScrollUp() { | 
 |   for (size_t r = 0; r < kMaxRowIdx; r++) { | 
 |     text_rows_[r] = text_rows_[r + 1]; | 
 |   } | 
 |   text_rows_.back().Clear(); | 
 | } |