ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/backend/ndk/keymap.cpp
Revision: 1.6
Committed: Sun Oct 24 20:31:51 2010 UTC (15 years, 11 months ago) by sf-pippijn
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +2 -2 lines
Log Message:
use EV and plain sockets instead of asio

File Contents

# Content
1 #include "ndk/keymap.hh"
2 #include "ndk/events.hh"
3
4 #include "adt/string.h"
5
6 #include <unordered_map>
7 #include <stdexcept>
8
9 using ndk::key;
10
11 typedef std::unordered_map<std::string, key> escape_map;
12
13 static escape_map const urxvt_keymap = {
14 { "\033[A", key::up },
15 { "\033[B", key::down },
16 { "\033[C", key::right },
17 { "\033[D", key::left },
18
19 { "\033[a", key::shift_up },
20 { "\033[b", key::shift_down },
21 { "\033[c", key::shift_right },
22 { "\033[d", key::shift_left },
23
24 { "\033Oa", key::ctrl_up },
25 { "\033Ob", key::ctrl_down },
26 { "\033Oc", key::ctrl_right },
27 { "\033Od", key::ctrl_left },
28
29 { "\033[3~", key::dc },
30
31 { "\033[5~", key::pg_up },
32 { "\033[6~", key::pg_dn },
33 { "\033[7~", key::home },
34 { "\033[8~", key::end },
35
36 { "\033[11~", key::F1 },
37 { "\033[12~", key::F2 },
38 { "\033[13~", key::F3 },
39 { "\033[14~", key::F4 },
40 { "\033[15~", key::F5 },
41 { "\033[17~", key::F6 },
42 { "\033[18~", key::F7 },
43 { "\033[19~", key::F8 },
44 { "\033[20~", key::F9 },
45 { "\033[21~", key::F10 },
46 { "\033[23~", key::F11 },
47 { "\033[24~", key::F12 },
48
49 { "\033Oq", key::shift_end },
50 { "\033Or", key::shift_down },
51 { "\033Os", key::shift_pg_dn },
52 { "\033Ot", key::shift_left },
53 { "\033Ov", key::shift_right },
54 { "\033Ow", key::shift_home },
55 { "\033Ox", key::shift_up },
56 { "\033Oy", key::shift_pg_up },
57
58 { "\033[5$", key::shift_pg_up },
59 { "\033[6$", key::shift_pg_dn },
60 { "\033[7$", key::shift_home },
61 { "\033[8$", key::shift_end },
62
63 { "\033[5^", key::ctrl_pg_up },
64 { "\033[6^", key::ctrl_pg_dn },
65 { "\033[7^", key::ctrl_home },
66 { "\033[8^", key::ctrl_end },
67 };
68
69 static escape_map const xterm_keymap = {
70 { "\033[A", key::up },
71 { "\033[B", key::down },
72 { "\033[C", key::right },
73 { "\033[D", key::left },
74
75 { "\033OA", key::up },
76 { "\033OB", key::down },
77 { "\033OC", key::right },
78 { "\033OD", key::left },
79
80 { "\033[1;2A", key::shift_up },
81 { "\033[1;2B", key::shift_down },
82 { "\033[1;2C", key::shift_right },
83 { "\033[1;2D", key::shift_left },
84
85 { "\033[1;5A", key::ctrl_up },
86 { "\033[1;5B", key::ctrl_down },
87 { "\033[1;5C", key::ctrl_right },
88 { "\033[1;5D", key::ctrl_left },
89
90 { "\033[3~", key::dc },
91
92 { "\033[5~", key::pg_up },
93 { "\033[6~", key::pg_dn },
94 { "\033[H", key::home },
95 { "\033[F", key::end },
96
97 { "\033OE", key::numpad_center },
98
99 { "\033OP", key::F1 },
100 { "\033OQ", key::F2 },
101 { "\033OR", key::F3 },
102 { "\033OS", key::F4 },
103 { "\033[15~", key::F5 },
104 { "\033[17~", key::F6 },
105 { "\033[18~", key::F7 },
106 { "\033[19~", key::F8 },
107 { "\033[20~", key::F9 },
108 { "\033[21~", key::F10 },
109 { "\033[23~", key::F11 },
110 { "\033[24~", key::F12 },
111
112 { "\033Oq", key::shift_end },
113 { "\033Or", key::shift_down },
114 { "\033Os", key::shift_pg_dn },
115 { "\033Ot", key::shift_left },
116 { "\033Ov", key::shift_right },
117 { "\033Ow", key::shift_home },
118 { "\033Ox", key::shift_up },
119 { "\033Oy", key::shift_pg_up },
120
121 { "\033[5;2~", key::shift_pg_up },
122 { "\033[6;2~", key::shift_pg_dn },
123 { "\033[1;2H", key::shift_home },
124 { "\033[1;2F", key::shift_end },
125
126 { "\033[5;5~", key::ctrl_pg_up },
127 { "\033[6;5~", key::ctrl_pg_dn },
128 { "\033[1;5H", key::ctrl_home },
129 { "\033[1;5F", key::ctrl_end },
130 };
131
132 static escape_map const fallback_keymap = xterm_keymap;
133
134 #include <fstream>
135 #include <iomanip>
136 static std::ofstream logs ("curses.log");
137
138 static escape_map const &
139 select_keymap ()
140 {
141 if (char const *const term = getenv ("TERM"))
142 {
143 logs << "TERM=" << term << std::endl;
144 if (!strncmp (term, "rxvt"))
145 return urxvt_keymap;
146
147 if (!strncmp (term, "xterm"))
148 return xterm_keymap;
149 }
150 else
151 logs << "TERM unknown" << std::endl;
152
153 return fallback_keymap;
154 }
155
156 static escape_map const &keymap = select_keymap ();
157
158
159 static bool
160 is_terminator (int const ch)
161 {
162 switch (ch)
163 {
164 case '^':
165 case '~':
166 case '$':
167 case 'a' ... 'z':
168 case 'A' ... 'Z':
169 return true;
170 default:
171 return false;
172 }
173 }
174
175 static std::string
176 escape (std::string const &s)
177 {
178 std::string res;
179 res.reserve (s.size () + 2 * 4);
180
181 foreach (char ch, s)
182 #if 0
183 if (isprint (ch))
184 res += s;
185 else
186 #endif
187 {
188 char buf[5];
189 snprintf (buf, sizeof buf, "\\%03o", ch);
190 res += buf;
191 }
192
193 return res;
194 }
195
196 bool
197 ndk::has_keymap ()
198 {
199 return &keymap != &fallback_keymap;
200 }
201
202 ndk::key
203 ndk::parsekey (std::string &esc, int const ch)
204 {
205 key code = key::unknown;
206
207 logs << "chr: \\" << std::oct << std::setfill ('0') << std::setw (3) << ch << std::dec;
208 #if 0
209 logs << "\nERR: \\" << std::oct << std::setfill ('0') << std::setw (3) << ERR << std::dec;
210 logs << "\nchr == ERR: " << std::boolalpha << (ch == ERR);
211 logs.flush ();
212 #endif
213
214 if (ch == '\033' || !esc.empty ())
215 {
216 code = key::intermediate;
217 esc += ch;
218 logs << ", esc: " << escape (esc);
219 if (!strncmp (esc, "\033[M"))
220 {
221 if (esc.length () == 6)
222 code = key::mouse;
223 }
224 else if (ch != '[' && ch != 'O' && is_terminator (ch))
225 {
226 escape_map::const_iterator found = keymap.find (esc);
227 if (found != keymap.end ())
228 {
229 code = found->second;
230 logs << "\ngot: " << std::oct << std::setfill ('0') << std::setw (3) << int (code) << std::dec;
231 }
232 else
233 {
234 code = key::unknown;
235 logs << "\nunknown escape sequence: " << escape (esc);
236 //throw std::runtime_error ("unknown escape sequence: " + escape (esc));
237 }
238 // finished
239 esc.clear ();
240 }
241 }
242 else if (ch == ERR)
243 code = key::error;
244 else if (ch == '\177') // XXX: special case: are there more?
245 code = key::backspace;
246 else
247 code = key (ch);
248
249 logs << std::endl;
250
251 return code;
252 }
253
254 ndk::mouse
255 ndk::getmouse (std::string &esc)
256 {
257 MEVENT mev { };
258 if (is_keypad (stdscr))
259 {
260 return_val_unless (getmouse (&mev) == OK, { mev });
261 }
262 else
263 {
264 unsigned char const button = esc[3];
265 unsigned char const x = esc[4];
266 unsigned char const y = esc[5];
267
268 mev.x = x - 33;
269 mev.y = y - 33;
270
271 mev.bstate |= (button == 32) * BUTTON1_CLICKED;
272 mev.bstate |= (button == 33) * BUTTON2_CLICKED;
273 mev.bstate |= (button == 34) * BUTTON3_CLICKED;
274
275 esc.clear ();
276 }
277
278 return { mev };
279 }