Line.h 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Noncopyable.h>
  8. #include <AK/String.h>
  9. #include <AK/Vector.h>
  10. #include <LibVT/Attribute.h>
  11. #include <LibVT/Position.h>
  12. #include <LibVT/XtermColors.h>
  13. namespace VT {
  14. class Line {
  15. AK_MAKE_NONCOPYABLE(Line);
  16. AK_MAKE_NONMOVABLE(Line);
  17. public:
  18. explicit Line(size_t length);
  19. ~Line();
  20. struct Cell {
  21. u32 code_point { ' ' };
  22. Attribute attribute;
  23. bool operator!=(Cell const& other) const { return code_point != other.code_point || attribute != other.attribute; }
  24. };
  25. const Attribute& attribute_at(size_t index) const { return m_cells[index].attribute; }
  26. Attribute& attribute_at(size_t index) { return m_cells[index].attribute; }
  27. Cell& cell_at(size_t index) { return m_cells[index]; }
  28. const Cell& cell_at(size_t index) const { return m_cells[index]; }
  29. void clear(const Attribute& attribute = Attribute())
  30. {
  31. m_terminated_at.clear();
  32. clear_range(0, m_cells.size() - 1, attribute);
  33. }
  34. void clear_range(size_t first_column, size_t last_column, const Attribute& attribute = Attribute());
  35. bool has_only_one_background_color() const;
  36. bool is_empty() const
  37. {
  38. return !any_of(m_cells.begin(), m_cells.end(), [](auto& cell) { return cell != Cell(); });
  39. }
  40. size_t length() const
  41. {
  42. return m_cells.size();
  43. }
  44. void set_length(size_t);
  45. void rewrap(size_t new_length, Line* next_line, CursorPosition* cursor, bool cursor_is_on_next_line = true);
  46. u32 code_point(size_t index) const
  47. {
  48. return m_cells[index].code_point;
  49. }
  50. void set_code_point(size_t index, u32 code_point)
  51. {
  52. if (m_terminated_at.has_value()) {
  53. if (index > *m_terminated_at) {
  54. m_terminated_at = index + 1;
  55. }
  56. }
  57. m_cells[index].code_point = code_point;
  58. }
  59. bool is_dirty() const { return m_dirty; }
  60. void set_dirty(bool b) { m_dirty = b; }
  61. Optional<u16> termination_column() const { return m_terminated_at; }
  62. void set_terminated(u16 column) { m_terminated_at = column; }
  63. private:
  64. void take_cells_from_next_line(size_t new_length, Line* next_line, bool cursor_is_on_next_line, CursorPosition* cursor);
  65. void push_cells_into_next_line(size_t new_length, Line* next_line, bool cursor_is_on_next_line, CursorPosition* cursor);
  66. Vector<Cell> m_cells;
  67. bool m_dirty { false };
  68. // Note: The alignment is 8, so this member lives in the padding (that already existed before it was introduced)
  69. [[no_unique_address]] Optional<u16> m_terminated_at;
  70. };
  71. }