/[svn]/linuxsampler/trunk/src/shell/CCursor.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/shell/CCursor.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2515 - (show annotations) (download) (as text)
Wed Feb 5 20:45:18 2014 UTC (10 years, 1 month ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 6256 byte(s)
* WIP: Introducing the LSCP shell: for now, providing color
  highlighting while typing (indicating correct part bold white,
  incorrect part red, and turning green when the command is
  complete. The shell application is implemented as thin client,
  that is the parser work is performed on sampler side and the
  shell application is just providing output formatting.
* Bumped version (1.0.0.svn28).

1 /*
2 * LSCP Shell
3 *
4 * Copyright (c) 2014 Christian Schoenebeck
5 *
6 * This program is part of LinuxSampler and released under the same terms.
7 */
8
9 #ifndef CCURSOR_H
10 #define CCURSOR_H
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <iostream>
15 #include <sstream>
16 #include <string>
17
18 #include "TerminalCtrl.h"
19 #include "KeyboardReader.h"
20
21 /**
22 * Writes (and reads) "ANSI escape codes" to/from stdout/stdin to control the
23 * position and appearance of the text input cursor on comand line terminals.
24 *
25 * This is a lite-weight class to prevent a dependency to i.e. libncurses.
26 */
27 class CCursor {
28 public:
29 CCursor() : m_row(-1), m_col(-1) {}
30 virtual ~CCursor() {}
31
32 /**
33 * Returns a CCursor storing the current position of the cursor on screen.
34 * That position can be altered with CCursors methods or restored at any
35 * time by calling restore().
36 */
37 static CCursor now() {
38 CCursor cursor;
39 TerminalSetting setting = TerminalCtrl::now();
40 TerminalCtrl::echoInput(false);
41
42 // Workaround: obviously only one thread can read from stdin, so if
43 // there is already 'KeyboardReader' listening to stdin, then use its
44 // read buffers, otherwise read "directly" from stdin with
45 // 'TerminalCtrl' class.
46 KeyboardReader* reader = KeyboardReader::singleton();
47 if (reader) reader->callback(false); // disable its callback for a moment (so it won't deliver the input to somewhere)
48 setCode("6n");
49 std::string s = (reader) ? reader->popStringToDelimiterSync('R') : TerminalCtrl::getStringToDelimiter('R');
50 if (reader) reader->callback(true); // re-enable its callback
51
52 TerminalCtrl::restore(setting);
53 char c;
54 int row, col;
55 int res = sscanf(s.c_str(), "%c[%d;%d", &c, &row, &col);
56 if (res == 3) {
57 cursor.m_row = row - 1;
58 cursor.m_col = col - 1;
59 }
60 return cursor;
61 }
62
63 /**
64 * Move the cursor on the terminal screen to the location stored in this
65 * CCcursor object.
66 */
67 const CCursor& restore() const {
68 if (!valid()) return *this;
69 std::stringstream ss;
70 ss << m_row+1 << ";" << m_col+1 << "f";
71 setCode(ss.str());
72 return *this;
73 }
74
75 /// Returns false if this object stores an invalid screen position.
76 bool valid() const {
77 return m_row >= 0 && m_col >= 0;
78 }
79
80 /**
81 * Move the cursor on the terminal screen directly to the requested position
82 * given by @a row and @a col.
83 *
84 * @returns CCursor object with new position
85 */
86 CCursor& moveTo(int row, int col) {
87 if (row < 0 || col < 0) return *this;
88 m_row = row;
89 m_col = col;
90 return const_cast<CCursor&>(restore());
91 }
92
93 CCursor& toColumn(int n) {
94 if (n < 0) return *this;
95 m_col = n;
96 return const_cast<CCursor&>(restore());
97 }
98
99 CCursor& toRow(int n) {
100 if (n < 0) return *this;
101 m_row = n;
102 return const_cast<CCursor&>(restore());
103 }
104
105 CCursor& up(int n = 1) {
106 if (n < 1) return *this;
107 std::stringstream ss;
108 ss << n << "A";
109 setCode(ss.str());
110 *this = now();
111 return *this;
112 }
113
114 CCursor& down(int n = 1) {
115 if (n < 1) return *this;
116 std::stringstream ss;
117 ss << n << "B";
118 setCode(ss.str());
119 *this = now();
120 return *this;
121 }
122
123 CCursor& right(int n = 1) {
124 if (n < 1) return *this;
125 std::stringstream ss;
126 ss << n << "C";
127 setCode(ss.str());
128 *this = now();
129 return *this;
130 }
131
132 CCursor& left(int n = 1) {
133 if (n < 1) return *this;
134 std::stringstream ss;
135 ss << n << "D";
136 setCode(ss.str());
137 *this = now();
138 return *this;
139 }
140
141 int column() const {
142 return m_col;
143 }
144
145 int row() const {
146 return m_row;
147 }
148
149 CCursor& hide() {
150 setCode("?25l");
151 return *this;
152 }
153
154 CCursor& show() {
155 setCode("?25h");
156 return *this;
157 }
158
159 // NOTE: not ANSI.SYS!
160 CCursor& lineDown(int n = 1) {
161 if (n < 1) return *this;
162 std::stringstream ss;
163 ss << n << "E";
164 setCode(ss.str());
165 *this = now();
166 return *this;
167 }
168
169 // NOTE: not ANSI.SYS!
170 CCursor& lineUp(int n = 1) {
171 if (n < 1) return *this;
172 std::stringstream ss;
173 ss << n << "F";
174 setCode(ss.str());
175 *this = now();
176 return *this;
177 }
178
179 // NOTE: not ANSI.SYS!
180 CCursor& scrollUp(int nLines = 1) {
181 if (nLines < 1) return *this;
182 std::stringstream ss;
183 ss << nLines << "S";
184 setCode(ss.str());
185 *this = now();
186 return *this;
187 }
188
189 // NOTE: not ANSI.SYS!
190 CCursor& scrollDown(int nLines = 1) {
191 if (nLines < 1) return *this;
192 std::stringstream ss;
193 ss << nLines << "T";
194 setCode(ss.str());
195 *this = now();
196 return *this;
197 }
198
199 CCursor& clearScreen() {
200 restore();
201 setCode("2J");
202 restore(); // allegedly cursor moves to beginning of screen on some systems, so restore
203 return *this;
204 }
205
206 CCursor& clearVerticalToTop() {
207 restore();
208 setCode("1J");
209 return *this;
210 }
211
212 CCursor& clearVerticalToBottom() {
213 restore();
214 setCode("0J");
215 return *this;
216 }
217
218 CCursor& clearLineToRight() {
219 restore();
220 setCode("0K");
221 return *this;
222 }
223
224 CCursor& clearLineToLeft() {
225 restore();
226 setCode("1K");
227 return *this;
228 }
229
230 CCursor& clearLine() {
231 restore();
232 setCode("2K");
233 return *this;
234 }
235
236 //static void save() { setCode("s"); } // barely supported by any terminal
237 //static void restore() { setCode("u"); } // barely supported by any terminal
238 protected:
239 static void setCode(std::string sCode) {
240 std::cout << modStr(sCode) << std::flush;
241 }
242 static std::string modStr(std::string code) {
243 return "\033[" + code;
244 }
245
246 private:
247 int m_row;
248 int m_col;
249 };
250
251 #endif // CCURSOR_H

  ViewVC Help
Powered by ViewVC