ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/frontend/client/input_handler.cpp
Revision: 1.13
Committed: Tue May 3 18:25:11 2011 UTC (15 years, 5 months ago) by sf-kernelpanic
Branch: MAIN
CVS Tags: HEAD
Changes since 1.12: +15 -1 lines
Error occurred while calculating annotation data.
Log Message:
implement dot-repetition

File Contents

# Content
1 #include "deliantra/sender.h"
2
3 #include "dclient/input_handler.h"
4 #include "dclient/render_glyph.h"
5 #include "dclient/widgets.h"
6 #include "dclient/widgets/inventory.h"
7 #include "dclient/widgets/map.h"
8 #include "dclient/widgets/query.h"
9 #include "dclient/widgets/stats.h"
10
11 #include <ndk/application.hh>
12 #include <ndk/color.hh>
13
14 #include <curses.h>
15
16 #include <ev.h>
17
18 typedef unsigned long flags_t;
19
20 enum class flags
21 : flags_t
22 {
23 none,
24 firing = 1 << 0,
25 running = 1 << 1,
26
27 COUNT
28 };
29
30 static flags &
31 operator += (flags &lhs, flags rhs)
32 {
33 return lhs = flags (flags_t (lhs) | flags_t (rhs));
34 }
35
36 static flags &
37 operator -= (flags &lhs, flags rhs)
38 {
39 return lhs = flags (flags_t (lhs) & ~flags_t (rhs));
40 }
41
42 static bool
43 operator & (flags lhs, flags rhs)
44 {
45 return flags_t (lhs) & flags_t (rhs);
46 }
47
48
49 enum class action
50 {
51 none,
52
53 north,
54 northeast,
55 east,
56 southeast,
57 south,
58 southwest,
59 west,
60 northwest,
61
62 run,
63 fire,
64 stay_fire,
65
66 quit,
67 redraw,
68 resize,
69 maximise,
70 input_mode,
71
72 apply,
73 take,
74
75 repeat,
76
77 COUNT
78 };
79
80
81 struct input_handler::pimpl
82 : sender
83 {
84 pimpl (communicator &comm, widgets &ui);
85
86 void perform (ndk::panel *sender, action cmd, action arg = action::none);
87
88 ndk::event::result on_kbd_common (ndk::keyboard const &ev);
89 ndk::event::result on_kbd_map (ndk::keyboard const &ev);
90
91 void on_command (std::string const &cmd);
92 void stdin_read_cb (ev::io &w, int revents);
93
94 widgets &ui;
95 std::string esc;
96 std::string last_cmd;
97 ev::io stdin_watcher;
98 flags state;
99 };
100
101 input_handler::pimpl::pimpl (communicator &comm, widgets &ui)
102 : sender (comm)
103 , ui (ui)
104 , state (flags::none)
105 {
106 auto kbd_common = ndk::slot (&pimpl::on_kbd_common, this);
107
108 ui.map->events ()->on_keyboard (kbd_common);
109 ui.info->events ()->on_keyboard (kbd_common);
110 ui.stats->events ()->on_keyboard (kbd_common);
111 ui.inventory->events ()->on_keyboard (kbd_common);
112 ui.container->events ()->on_keyboard (kbd_common);
113 ui.invmenu->events ()->on_keyboard (kbd_common);
114 ui.query->events ()->on_keyboard (kbd_common);
115
116 ui.map->events ()->on_keyboard (ndk::slot (&pimpl::on_kbd_map, this));
117
118 ui.input->on_commit () = ndk::slot (&pimpl::on_command, this);
119
120 stdin_watcher.set (STDIN_FILENO, ev::READ);
121 stdin_watcher.set<pimpl, &pimpl::stdin_read_cb> (this);
122 stdin_watcher.start ();
123 }
124
125 void
126 input_handler::pimpl::perform (ndk::panel *sender, action cmd, action arg)
127 {
128 if (state & flags::running)
129 {
130 send ("command", "run_stop");
131 state -= flags::running;
132 }
133 if (state & flags::firing)
134 {
135 send ("command", "fire_stop");
136 state -= flags::firing;
137 }
138
139 switch (cmd)
140 {
141 case action::none:
142 break;
143
144 // direction commands
145 case action::north: send ("command", "north" ); break;
146 case action::northeast: send ("command", "northeast"); break;
147 case action::east: send ("command", "east" ); break;
148 case action::southeast: send ("command", "southeast"); break;
149 case action::south: send ("command", "south" ); break;
150 case action::southwest: send ("command", "southwest"); break;
151 case action::west: send ("command", "west" ); break;
152 case action::northwest: send ("command", "northwest"); break;
153
154 // running
155 case action::run:
156 send ("command", "run ", int (arg));
157 state += flags::running;
158 break;
159
160 // firing
161 case action::fire:
162 send ("command", "fire ", int (arg));
163 state += flags::firing;
164 break;
165
166 case action::stay_fire:
167 send ("command", "stay fire");
168 break;
169
170 // control commands
171 case action::quit:
172 ev_break (EV_DEFAULT_UC_ EVBREAK_ALL);
173 break;
174
175 case action::redraw:
176 redrawwin (stdscr);
177 break;
178
179 case action::resize:
180 ui.resize ();
181 break;
182
183 case action::maximise:
184 if (ui.maximised)
185 ui.maximised = nullptr;
186 else
187 ui.maximised = sender;
188 perform (sender, action::resize);
189 break;
190
191 case action::input_mode:
192 ui.input->visualize ();
193 ui.input->focus ();
194 break;
195
196 // action commands
197 case action::apply:
198 send ("command", "apply");
199 break;
200
201 case action::take:
202 send ("command", "take");
203 break;
204
205 case action::repeat:
206 if (!last_cmd.empty())
207 send ("command", last_cmd);
208 break;
209
210 // never happens
211 case action::COUNT:
212 abort ();
213 }
214 }
215
216 ndk::event::result
217 input_handler::pimpl::on_kbd_common (ndk::keyboard const &ev)
218 {
219 switch (ev.code ())
220 {
221 case ndk::key::error:
222 throw std::runtime_error ("ERR");
223
224 // control actions
225 case ndk::key::ctrl_d:
226 case 'q':
227 perform (ev.sender (), action::quit);
228 return ndk::event::accepted;
229
230 case ndk::key::ctrl_l:
231 perform (ev.sender (), action::redraw);
232 return ndk::event::accepted;
233
234 case ndk::key::resize:
235 perform (ev.sender (), action::resize);
236 return ndk::event::accepted;
237
238 case ndk::key::F10:
239 perform (ev.sender (), action::maximise);
240 return ndk::event::accepted;
241
242 default:
243 return ndk::event::ignored;
244 }
245 }
246
247 ndk::event::result
248 input_handler::pimpl::on_kbd_map (ndk::keyboard const &ev)
249 {
250 switch (ev.code ())
251 {
252 // moving
253 case 'j':
254 case '2':
255 case ndk::key::down:
256 perform (ev.sender (), action::south);
257 return ndk::event::accepted;
258 case 'k':
259 case '8':
260 case ndk::key::up:
261 perform (ev.sender (), action::north);
262 return ndk::event::accepted;
263 case 'h':
264 case '4':
265 case ndk::key::left:
266 perform (ev.sender (), action::west);
267 return ndk::event::accepted;
268 case 'l':
269 case '6':
270 case ndk::key::right:
271 perform (ev.sender (), action::east);
272 return ndk::event::accepted;
273 case '7':
274 case ndk::key::home:
275 perform (ev.sender (), action::northwest);
276 return ndk::event::accepted;
277 case '9':
278 case ndk::key::pg_up:
279 perform (ev.sender (), action::northeast);
280 return ndk::event::accepted;
281 case '5':
282 case ndk::key::numpad_center:
283 perform (ev.sender (), action::stay_fire);
284 return ndk::event::accepted;
285 case '1':
286 case ndk::key::end:
287 perform (ev.sender (), action::southwest);
288 return ndk::event::accepted;
289 case '3':
290 case ndk::key::pg_dn:
291 perform (ev.sender (), action::southeast);
292 return ndk::event::accepted;
293
294 case ' ':
295 perform (ev.sender (), action::apply);
296 return ndk::event::accepted;
297 case ',':
298 perform (ev.sender (), action::take);
299 return ndk::event::accepted;
300 case '.':
301 perform (ev.sender (), action::repeat);
302 return ndk::event::accepted;
303 case ndk::key::enter:
304 case 'i':
305 perform (ev.sender (), action::input_mode);
306 return ndk::event::accepted;
307 case 'c':
308 ui.input->set_text ("chat ");
309 perform (ev.sender (), action::input_mode);
310 return ndk::event::accepted;
311 case '"':
312 ui.input->set_text ("say ");
313 perform (ev.sender (), action::input_mode);
314 return ndk::event::accepted;
315 case '\'':
316 ui.input->set_text ("tell ");
317 perform (ev.sender (), action::input_mode);
318 return ndk::event::accepted;
319
320 // firing
321 case 'J':
322 case ndk::key::shift_down:
323 perform (ev.sender (), action::fire, action::south);
324 return ndk::event::accepted;
325 case 'K':
326 case ndk::key::shift_up:
327 perform (ev.sender (), action::fire, action::north);
328 return ndk::event::accepted;
329 case 'H':
330 case ndk::key::shift_left:
331 perform (ev.sender (), action::fire, action::west);
332 return ndk::event::accepted;
333 case 'L':
334 case ndk::key::shift_right:
335 perform (ev.sender (), action::fire, action::east);
336 return ndk::event::accepted;
337 case ndk::key::shift_home:
338 perform (ev.sender (), action::fire, action::northwest);
339 return ndk::event::accepted;
340 case ndk::key::shift_pg_up:
341 perform (ev.sender (), action::fire, action::northeast);
342 return ndk::event::accepted;
343 case ndk::key::shift_end:
344 perform (ev.sender (), action::fire, action::southwest);
345 return ndk::event::accepted;
346 case ndk::key::shift_pg_dn:
347 perform (ev.sender (), action::fire, action::southeast);
348 return ndk::event::accepted;
349
350 // running
351 //case 'J':
352 case ndk::key::ctrl_down:
353 perform (ev.sender (), action::run, action::south);
354 return ndk::event::accepted;
355 //case 'K':
356 case ndk::key::ctrl_up:
357 perform (ev.sender (), action::run, action::north);
358 return ndk::event::accepted;
359 //case 'H':
360 case ndk::key::ctrl_left:
361 perform (ev.sender (), action::run, action::west);
362 return ndk::event::accepted;
363 //case 'L':
364 case ndk::key::ctrl_right:
365 perform (ev.sender (), action::run, action::east);
366 return ndk::event::accepted;
367 case ndk::key::ctrl_home:
368 perform (ev.sender (), action::run, action::northwest);
369 return ndk::event::accepted;
370 case ndk::key::ctrl_pg_up:
371 perform (ev.sender (), action::run, action::northeast);
372 return ndk::event::accepted;
373 case ndk::key::ctrl_end:
374 perform (ev.sender (), action::run, action::southwest);
375 return ndk::event::accepted;
376 case ndk::key::ctrl_pg_dn:
377 perform (ev.sender (), action::run, action::southeast);
378 return ndk::event::accepted;
379
380 case ndk::key::ctrl_l:
381 case ndk::key::F10:
382 case ndk::key::resize:
383 case ndk::key::tab:
384 return ndk::event::ignored;
385
386 case ndk::key::unknown:
387 return ndk::event::ignored;
388
389 default:
390 if (getenv ("DCLIENT_FATAL"))
391 throw ev.code ();
392 else
393 {
394 ui.info->add_text (ndi_color (3, 0), "unknown keycode: 0%03o\n", ev.code ());
395 ui.info->visualize ();
396 return ndk::event::ignored;
397 }
398 }
399 }
400
401 void
402 input_handler::pimpl::on_command (std::string const &cmd)
403 {
404 ui.input->set_text ("");
405
406 if (!cmd.empty ())
407 {
408 send ("command", cmd);
409 last_cmd = cmd;
410 }
411 else
412 {
413 ui.map->focus ();
414 ui.input->hide ();
415 ndk::app->cursor_off (); // FIXME: should be done automatically
416 }
417 }
418
419 void
420 input_handler::pimpl::stdin_read_cb (ev::io &w, int revents)
421 {
422 ndk::app->process (getch ());
423 }
424
425
426 input_handler::input_handler (communicator &comm, widgets &ui)
427 : impl (new pimpl (comm, ui))
428 {
429 }
430
431 input_handler::~input_handler ()
432 {
433 delete impl;
434 }