1 /*
2   Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3 
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License, version 2.0,
6   as published by the Free Software Foundation.
7 
8   This program is also distributed with certain software (including
9   but not limited to OpenSSL) that is licensed under separate terms,
10   as designated in a particular file or component or in included license
11   documentation.  The authors of MySQL hereby grant you an additional
12   permission to link the program and your derivative works with the
13   separately licensed software that they have included with MySQL.
14 
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19 
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23 */
24 
25 #include "mysql/harness/vt100.h"
26 
27 #include <string>
28 #include <vector>
29 
30 namespace Vt100 {
31 #define ESC "\x1b"
32 constexpr const char BEL{0x07};
33 constexpr const char CSI[]{ESC "["};  // Control Sequence Introducer
34 constexpr const char OSC[]{ESC "]"};  // Operating system command
35 
reset()36 std::string reset() { return ESC "c"; }
37 
38 template <Vt100::value_type N>
not_num_to_string(Vt100::value_type n)39 static std::string not_num_to_string(Vt100::value_type n) {
40   return (n == N) ? "" : std::to_string(n);
41 }
42 
csi(Csi c,const std::string & s)43 static std::string csi(Csi c, const std::string &s) {
44   return CSI + s + static_cast<char>(c);
45 }
46 
csi(Csi c)47 static std::string csi(Csi c) { return csi(c, ""); }
48 
49 template <Vt100::value_type DEF>
csi_default(Csi c,Vt100::value_type n)50 static std::string csi_default(Csi c, Vt100::value_type n) {
51   return csi(c, not_num_to_string<DEF>(n));
52 }
53 
54 template <Vt100::value_type DEF, size_t N>
csi_default(Csi c,const std::array<Vt100::value_type,N> & fields)55 static std::string csi_default(Csi c,
56                                const std::array<Vt100::value_type, N> &fields) {
57   std::string s;
58   bool is_first = true;
59   for (const auto &field : fields) {
60     if (!is_first) {
61       s += ";";
62     }
63     s += not_num_to_string<DEF>(field);
64     is_first = false;
65   }
66   return csi(c, s);
67 }
68 
cursor_up(Vt100::value_type n)69 std::string cursor_up(Vt100::value_type n) {
70   return csi_default<1>(Csi::CUU, n);
71 }
cursor_down(Vt100::value_type n)72 std::string cursor_down(Vt100::value_type n) {
73   return csi_default<1>(Csi::CUD, n);
74 }
cursor_forward(Vt100::value_type n)75 std::string cursor_forward(Vt100::value_type n) {
76   return csi_default<1>(Csi::CUF, n);
77 }
cursor_back(Vt100::value_type n)78 std::string cursor_back(Vt100::value_type n) {
79   return csi_default<1>(Csi::CUB, n);
80 }
cursor_next_line(Vt100::value_type n)81 std::string cursor_next_line(Vt100::value_type n) {
82   return csi_default<1>(Csi::CNL, n);
83 }
cursor_prev_line(Vt100::value_type n)84 std::string cursor_prev_line(Vt100::value_type n) {
85   return csi_default<1>(Csi::CPL, n);
86 }
cursor_abs_col(Vt100::value_type n)87 std::string cursor_abs_col(Vt100::value_type n) {
88   return csi_default<1>(Csi::CHA, n);
89 }
cursor_abs_row(Vt100::value_type n)90 std::string cursor_abs_row(Vt100::value_type n) {
91   return csi_default<1>(Csi::VPA, n);
92 }
cursor_abs_pos(Vt100::value_type row,Vt100::value_type col)93 std::string cursor_abs_pos(Vt100::value_type row, Vt100::value_type col) {
94   return csi_default<1, 2>(Csi::CUP, {row, col});
95 }
96 
erase_in_display(Vt100::Erase n)97 std::string erase_in_display(Vt100::Erase n) {
98   return csi_default<0>(Csi::ED, static_cast<Vt100::value_type>(n));
99 }
erase_in_line(Vt100::Erase n)100 std::string erase_in_line(Vt100::Erase n) {
101   return csi_default<0>(Csi::EL, static_cast<Vt100::value_type>(n));
102 }
scroll_up(Vt100::value_type n)103 std::string scroll_up(Vt100::value_type n) {
104   return csi_default<1>(Csi::SU, n);
105 }
scroll_down(Vt100::value_type n)106 std::string scroll_down(Vt100::value_type n) {
107   return csi_default<1>(Csi::SD, n);
108 }
save_cursor_pos()109 std::string save_cursor_pos() { return csi(Csi::SC); }
restore_cursor_pos()110 std::string restore_cursor_pos() { return csi(Csi::SR); }
111 
window_title(const std::string & title)112 std::string window_title(const std::string &title) {
113   return OSC + std::to_string(2) + ";" + title + BEL;
114 }
115 
116 /**
117  * VT100, 7-bit colors
118  */
render(Vt100::value_type n)119 static std::string render(Vt100::value_type n) {
120   return csi_default<0>(Csi::SGR, n);
121 }
122 
123 template <Vt100::value_type DEF, size_t N>
render(const std::array<Vt100::value_type,N> & fields)124 static std::string render(const std::array<Vt100::value_type, N> &fields) {
125   return csi_default<DEF>(Csi::SGR, fields);
126 }
127 
render(Render r)128 std::string render(Render r) {
129   return render(static_cast<Vt100::value_type>(r));
130 }
131 
foreground(Color c)132 std::string foreground(Color c) {
133   return render(static_cast<Vt100::value_type>(Render::ForegroundBlack) +
134                 static_cast<Vt100::value_type>(c));
135 }
136 
foreground(const Rgb & rgb)137 std::string foreground(const Rgb &rgb) {
138   return render<65535, 5>(
139       {static_cast<Vt100::value_type>(Render::ForegroundExtended), 2, rgb[0],
140        rgb[1], rgb[2]});
141 }
142 
foreground(uint8_t ndx)143 std::string foreground(uint8_t ndx) {
144   return render<0, 3>(
145       {static_cast<Vt100::value_type>(Render::ForegroundExtended), 5, ndx});
146 }
147 
background(Color c)148 std::string background(Color c) {
149   return render(static_cast<int>(Render::BackgroundBlack) +
150                 static_cast<int>(c));
151 }
152 
background(const Rgb & rgb)153 std::string background(const Rgb &rgb) {
154   return render<65535, 5>(
155       {static_cast<Vt100::value_type>(Render::BackgroundExtended), 2, rgb[0],
156        rgb[1], rgb[2]});
157 }
158 
background(uint8_t ndx)159 std::string background(uint8_t ndx) {
160   return render<0, 3>(
161       {static_cast<Vt100::value_type>(Render::BackgroundExtended), 5, ndx});
162 }
163 
164 }  // namespace Vt100
165