ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/backend/ndk/keymap.cpp
Revision: 1.3
Committed: Mon Oct 18 14:11:48 2010 UTC (16 years ago) by sf-pippijn
Branch: MAIN
Changes since 1.2: +13 -5 lines
Log Message:
check and log but do not die when ncurses stuff fails

File Contents

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