aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/include/arch/video/vga/text.hpp
blob: 665dc1cd7f0879e96aae18eb30238228af2596ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#ifndef TEACHOS_ARCH_X86_64_VIDEO_VGA_TEXT_HPP
#define TEACHOS_ARCH_X86_64_VIDEO_VGA_TEXT_HPP

#include <cstdint>
#include <string_view>
#include <type_traits>

namespace teachos::arch::video::vga::text
{
  auto constexpr DEFAULT_VGA_TEXT_BUFFER_ADDRESS = 0xB8000;

  /**
   * @brief The colors available in the standard VGA text mode.
   */
  enum struct color : std::uint8_t
  {
    black,   ///< Equivalent to HTML color \#000000.
    blue,    ///< Equivalent to HTML color \#0000AA.
    green,   ///< Equivalent to HTML color \#00AA00.
    cyan,    ///< Equivalent to HTML color \#00AAAA.
    red,     ///< Equivalent to HTML color \#AA0000.
    purple,  ///< Equivalent to HTML color \#AA00AA.
    brown,   ///< Equivalent to HTML color \#AA5500.
    gray,    ///< Equivalent to HTML color \#AAAAAA.
  };

  /**
   * @brief The foreground color modification flag.
   */
  enum struct foreground_flag : bool
  {
    none,     ///< Apply no flag e.g., keep color as is.
    intense,  ///< Make the color more intense (usually brighter).
  };

  /**
   * @brief The background color modification flag.
   */
  enum struct background_flag : bool
  {
    none,             ///< Apply no flag e.g., keep color as is.
    blink_or_bright,  ///< Make the cell blink or more intense, dependent on the VGA configuration.
  };

  /**
   * @brief The VGA text mode attribute.
   *
   * @note In the text mode of VGA, every code point being presented is followed by an attribute description. This
   * allows for the modification of how the relevant "cell" is presented.
   *
   * @see vga::text::foreground_flag
   * @see vga::text::background_flag
   */
  struct attribute
  {
    color foreground_color : 3;                ///< The foreground color of the cell, e.g. the color of the code point.
    enum foreground_flag foreground_flag : 1;  ///< The foreground color modification flag of the cell.
    color bacground_color : 3;                 ///< The background color of the cell.
    enum background_flag background_flag : 1;  ///< The background color modification flag of the cell.
  };

  static_assert(sizeof(attribute) == 1, "The VGA text mode attribute must fit inside a single byte.");

  /**
   * @brief Commonly used VGA text mode attributes.
   */
  namespace common_attributes
  {
    /**
     * @brief Make the affected cell display with a gray foreground and black background.
     */
    [[maybe_unused]] auto constexpr gray_on_black =
        attribute{color::gray, foreground_flag::none, color::black, background_flag::none};

    /**
     * @brief Make the affected cell display with a green foreground and black background.
     */
    [[maybe_unused]] auto constexpr green_on_black =
        attribute{color::green, foreground_flag::none, color::black, background_flag::none};

    /**
     * @brief Make the affected cell display with a white (gray + intense) foreground and red background.
     */
    [[maybe_unused]] auto constexpr white_on_red =
        attribute{color::gray, foreground_flag::intense, color::red, background_flag::none};
  }  // namespace common_attributes

  /**
   * @brief Clear the VGA text mode buffer.
   *
   * @note This function also resets the text mode buffer pointer.
   *
   * @param attribute The attribute to "clear" the screen with.
   */
  auto clear(attribute attribute = common_attributes::gray_on_black) -> void;

  /**
   * @brief Enable or disable the VGA text mode cursor.
   *
   * @param enabled Whether or not to enable the cursors.
   */
  auto cursor(bool enabled) -> void;

  /**
   * @brief Move the cursor to a new line, scrolling the buffer if necessary.
   */
  auto newline() -> void;

  /**
   * @brief Write a string of code points to the VGA text buffer.
   *
   * @note This function also updates the text mode buffer pointer.
   *
   * @param code_points A string of (8-bit) code points to write to the VGA text mode buffer.
   * @param attribute The attribute to apply to the written sequence of code points.
   * @see vga::text::attribute
   */
  auto write(std::string_view code_points, attribute attribute) -> void;

  /**
   * @brief Write a single character to the VGA text buffer.
   *
   * @note This function also updates the text mode buffer pointer.
   *
   * @param code_point A code point to write to the VGA text mode buffer.
   * @param attribute The attribute to apply to the written sequence of code points.
   * @see vga::text::attribute
   */
  auto write_char(char code_point, attribute attribute) -> void;

  template<typename T>
  concept Integral = std::is_integral_v<T>;

  /**
   * @brief Write a integral value to the VGA text buffer.
   *
   * @note This function also updates the text mode buffer pointer.
   *
   * @param value A integral value to write to the VGA text mode buffer.
   * @param attribute The attribute to apply to the written sequence of code points.
   * @see vga::text::attribute
   */
  template<Integral T>
  auto write_number(T value, attribute attribute) -> void
  {
    T current_value = value;
    T divisor = 1;

    while (current_value > 9)
    {
      divisor *= 10;
      current_value = current_value / 10;
    }

    current_value = value;
    while (divisor > 0)
    {
      uint8_t quotient = current_value / divisor;
      char ascii_digit = quotient + '0';

      write_char(ascii_digit, attribute);
      current_value %= divisor;
      divisor /= 10;
    }
  }
}  // namespace teachos::arch::video::vga::text

#endif