Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

CSC112 Spring 2016 Examples

2370 views
1
#include <iostream>
2
#include <unistd.h>
3
#include <termios.h>
4
#include <sys/ioctl.h>
5
#include <stdlib.h>
6
#include <sys/poll.h>
7
#include "keystream.h"
8
9
//our lone default instance
10
KeyStream kin;
11
12
13
//this is a low level character buffer, it uses read
14
class ttyinbuf : public std::streambuf
15
{
16
public:
17
ttyinbuf()
18
{
19
//we initially start with no available input
20
setg(&buf, &buf, &buf);
21
}
22
23
24
protected:
25
virtual int underflow()
26
{
27
//read a single character
28
read(STDIN_FILENO, &buf, 1);
29
30
//make the character available
31
setg(&buf, &buf, &buf + 1);
32
}
33
34
35
private:
36
char buf;
37
};
38
39
40
//constructor & Destructor
41
KeyStream::KeyStream()
42
{
43
//set up our buffer to be stdin
44
this->rdbuf(new ttyinbuf);
45
46
//get the original termios
47
tcgetattr(STDIN_FILENO, &_originalTermios);
48
49
//the default state is cooked!
50
cookedMode();
51
}
52
53
54
KeyStream::~KeyStream()
55
{
56
//restore the original tty state
57
tcsetattr(STDIN_FILENO, TCSAFLUSH, &_originalTermios);
58
}
59
60
61
//macro modes
62
void
63
KeyStream::cookedMode()
64
{
65
_echo=true;
66
_special=true;
67
_signal=true;
68
_canonical=true;
69
setTermiosFlags();
70
}
71
72
73
void
74
KeyStream::rawMode()
75
{
76
_echo=false;
77
_special=false;
78
_signal=false;
79
_canonical=false;
80
setTermiosFlags();
81
}
82
83
84
void
85
KeyStream::cbreakMode()
86
{
87
_echo=false;
88
_canonical=false;
89
_signal=true;
90
_special=true;
91
setTermiosFlags();
92
}
93
94
95
//specific status flags
96
bool
97
KeyStream::echo()
98
{
99
return _echo;
100
}
101
102
103
void
104
KeyStream::echo(bool flag)
105
{
106
_echo = flag;
107
setTermiosFlags();
108
}
109
110
111
bool
112
KeyStream::canonical()
113
{
114
return _canonical;
115
}
116
117
118
void
119
KeyStream::canonical(bool flag)
120
{
121
_canonical = flag;
122
setTermiosFlags();
123
}
124
125
126
bool
127
KeyStream::signal()
128
{
129
return _signal;
130
}
131
132
133
void
134
KeyStream::signal(bool flag)
135
{
136
_signal = flag;
137
setTermiosFlags();
138
}
139
140
141
bool
142
KeyStream::special()
143
{
144
return _special;
145
}
146
147
148
void
149
KeyStream::special(bool flag)
150
{
151
_special = flag;
152
setTermiosFlags();
153
}
154
155
//extensions to the normal IO stuff
156
keycode
157
KeyStream::getKey()
158
{
159
keycode result=0x00;
160
char c;
161
162
//we may be getting more than one character!
163
c=get(); //get a character
164
result = c;
165
166
//if this is not an escape sequence, go ahead and return it
167
if(c != 0x1b || !hasInput()) {
168
return result;
169
}
170
171
//ok, so we have an escape sequence going!, get the second character
172
c = get(); //get the next character in the sequence
173
result = result << 8 | c; //add it to the result code
174
175
//If this is not one of our known sequences, then we
176
//stop here. (We also stop if there is nothing else to do)
177
if(!hasInput() || (c != 0x5b && c != 0x4f)) {
178
return result;
179
}
180
181
//still here? Let there be a third!
182
c = get();
183
result = result << 8 | c;
184
185
//now, there is only one known situation in which we have a fourth.
186
//look for it!
187
if(!hasInput() | !(c & 0x30)) {
188
return result;
189
}
190
191
//ok, 4, but that's it. NO MORE
192
c = get();
193
result = result << 8 | c;
194
195
return result;
196
}
197
198
199
bool
200
KeyStream::hasInput()
201
{
202
struct pollfd fds;
203
int pres;
204
205
fds.fd=STDIN_FILENO;
206
fds.events=POLLIN;
207
pres = poll(&fds, 1, 70);
208
209
return pres==1;
210
}
211
212
213
void
214
KeyStream::setTermiosFlags()
215
{
216
struct termios t;
217
218
//get the current termios
219
if(tcgetattr(STDIN_FILENO, &t) == -1) {
220
return; //TODO Exception Handling
221
}
222
223
224
//echo handling
225
if(_echo) {
226
//set the ECHO flag
227
t.c_lflag |= ECHO;
228
} else {
229
//clear the ECHO flag
230
t.c_lflag &= ~ECHO;
231
}
232
233
//canonical handling
234
if(_canonical) {
235
t.c_lflag |= ICANON;
236
t.c_iflag |= ICRNL;
237
} else {
238
t.c_lflag &= ~ICANON;
239
t.c_iflag &= ~ICRNL;
240
}
241
242
//singal handling
243
if(_signal) {
244
t.c_lflag |= ISIG | IEXTEN;
245
} else {
246
t.c_lflag &= ~(ISIG | IEXTEN);
247
}
248
249
250
//special processing handling
251
if(_special) {
252
t.c_iflag |= BRKINT | INPCK | IGNBRK | ISTRIP | IGNCR | IXON | INLCR | PARMRK;
253
//t.c_oflag |= OPOST;
254
} else {
255
t.c_iflag &= ~(BRKINT | INPCK | IGNBRK | ISTRIP | IGNCR | IXON | INLCR | PARMRK);
256
//t.c_oflag &= ~OPOST;
257
}
258
259
t.c_cc[VMIN] = 1;
260
t.c_cc[VTIME] = 0;
261
262
//set the ttye info
263
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t) == -1)
264
return; //TODO exception handling
265
}
266
267