/[svn]/linuxsampler/trunk/src/shell/TerminalCtrl.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/shell/TerminalCtrl.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3054 - (show annotations) (download)
Thu Dec 15 12:47:45 2016 UTC (7 years, 4 months ago) by schoenebeck
File size: 4984 byte(s)
* Fixed numerous compiler warnings.
* Bumped version (2.0.0.svn32).

1 /*
2 * LSCP Shell
3 *
4 * Copyright (c) 2014 - 2016 Christian Schoenebeck
5 *
6 * This program is part of LinuxSampler and released under the same terms.
7 */
8
9 #include "TerminalCtrl.h"
10
11 #include <unistd.h>
12 #include <termios.h>
13 #include <string.h>
14 #include <map>
15 #include <assert.h>
16 #include <sys/ioctl.h>
17 #include <stdio.h>
18 #include "../common/Mutex.h"
19
20 using namespace LinuxSampler;
21
22 ///////////////////////////////////////////////////////////////////////////
23 // class 'TerminalSetting'
24
25 static Mutex g_mutexReferences;
26 static std::map<void*,int> g_terminalSettingReferences;
27
28 static termios* _newTermios() {
29 termios* p = new termios;
30 LockGuard lock(g_mutexReferences);
31 g_terminalSettingReferences[p] = 1;
32 return p;
33 }
34
35 static void _releaseTermiosRef(void* p) {
36 if (!p) return;
37 LockGuard lock(g_mutexReferences);
38 std::map<void*,int>::iterator it = g_terminalSettingReferences.find(p);
39 assert(it != g_terminalSettingReferences.end());
40 assert(it->second > 0);
41 it->second--;
42 if (!it->second) {
43 g_terminalSettingReferences.erase(it);
44 delete (termios*) p;
45 }
46 }
47
48 static termios* _bumpTermiosRef(void* p) {
49 if (!p) return NULL;
50 LockGuard lock(g_mutexReferences);
51 std::map<void*,int>::iterator it = g_terminalSettingReferences.find(p);
52 assert(it != g_terminalSettingReferences.end());
53 assert(it->second > 0);
54 it->second++;
55 return (termios*) p;
56 }
57
58 TerminalSetting::TerminalSetting() : p(NULL) {
59 }
60
61 TerminalSetting::TerminalSetting(const TerminalSetting& ts) : p(_bumpTermiosRef(ts.p)) {
62 }
63
64 TerminalSetting::~TerminalSetting() {
65 _releaseTermiosRef(p);
66 }
67
68 bool TerminalSetting::valid() const {
69 return p != NULL;
70 }
71
72 ///////////////////////////////////////////////////////////////////////////
73 // class 'TerminalCtrl'
74
75 static termios g_defaults;
76
77 static void _saveDefaults() {
78 static bool done = false;
79 if (done) return;
80 if (tcgetattr(0, &g_defaults) < 0) return;
81 done = true;
82 }
83
84 int TerminalCtrl::reset() {
85 _saveDefaults();
86 if (tcsetattr(0, TCSANOW, &g_defaults) < 0) return -1;
87 return 0; // success
88 }
89
90 int TerminalCtrl::restore(const TerminalSetting& setting) {
91 _saveDefaults();
92 termios* s = (termios*) setting.p;
93 if (tcsetattr(0, TCSADRAIN, s) < 0) return -1;
94 return 0; // success
95 }
96
97 TerminalSetting TerminalCtrl::now() {
98 _saveDefaults();
99 TerminalSetting setting;
100 if (!setting.p) setting.p = _newTermios();
101 if (tcgetattr(0, (termios*) setting.p) < 0)
102 return TerminalSetting(); // error, return invalid setting
103 return setting; // success
104 }
105
106 int TerminalCtrl::echoInput(bool b) {
107 _saveDefaults();
108 termios settings = {};
109 if (tcgetattr(0, &settings) < 0) return -1;
110 if (b) {
111 settings.c_lflag |= ECHO;
112 if (tcsetattr(0, TCSADRAIN, &settings) < 0) return -1;
113 } else {
114 settings.c_lflag &= ~ECHO;
115 if (tcsetattr(0, TCSANOW, &settings) < 0) return -1;
116 }
117 return 0; // success
118 }
119
120 int TerminalCtrl::immediateInput(bool b) {
121 _saveDefaults();
122 termios settings = {};
123 if (tcgetattr(0, &settings) < 0) return -1;
124 if (b) {
125 settings.c_lflag &= ~ICANON;
126 settings.c_cc[VMIN] = 0;
127 settings.c_cc[VTIME] = 0;
128 if (tcsetattr(0, TCSANOW, &settings) < 0) return -1;
129 } else {
130 settings.c_lflag |= ICANON;
131 if (tcsetattr(0, TCSADRAIN, &settings) < 0) return -1;
132 }
133 return 0; // success
134 }
135
136 std::vector<char> TerminalCtrl::getChars(int max, int blockUntilMin, int burstDeciSeconds) {
137 _saveDefaults();
138 std::vector<char> v;
139
140 TerminalSetting original = now();
141 if (!original.valid()) return v;
142
143 termios setting = *(termios*)original.p; // copy
144 setting.c_lflag &= ~ICANON;
145 setting.c_cc[VMIN] = blockUntilMin;
146 setting.c_cc[VTIME] = burstDeciSeconds;
147 if (tcsetattr(0, TCSANOW, &setting) < 0) return v;
148 v.resize(max);
149 const int n = (int)read(0, &v[0], max);
150 if (n != max) v.resize(n < 0 ? 0 : n);
151
152 restore(original);
153 return v;
154 }
155
156 std::vector<char> TerminalCtrl::getCharsToDelimiter(char delimiter, bool includeDelimiter) {
157 _saveDefaults();
158 std::vector<char> result;
159 while (true) {
160 std::vector<char> v = getChars(1, 1);
161 if (v.empty()) break;
162 if (v[0] == delimiter && !includeDelimiter) break;
163 result.push_back(v[0]);
164 if (v[0] == delimiter) break;
165 }
166 return result;
167 }
168
169 std::string TerminalCtrl::getStringToDelimiter(char delimiter, bool includeDelimiter) {
170 _saveDefaults();
171 std::string s;
172 std::vector<char> v = getCharsToDelimiter(delimiter, includeDelimiter);
173 if (v.empty()) return s;
174 v.push_back(0);
175 int n = (int)strlen(&v[0]);
176 s.resize(n);
177 memcpy(&s[0], &v[0], n);
178 return s;
179 }
180
181 int TerminalCtrl::columns() {
182 struct winsize w;
183 ioctl(0, TIOCGWINSZ, &w);
184 return w.ws_col;
185 }
186
187 int TerminalCtrl::rows() {
188 struct winsize w;
189 ioctl(0, TIOCGWINSZ, &w);
190 return w.ws_row;
191 }

  ViewVC Help
Powered by ViewVC