ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/frontend/client/input_handler.cpp
Revision: 1.10
Committed: Sun Oct 24 21:48:59 2010 UTC (16 years ago) by sf-pippijn
Branch: MAIN
Changes since 1.9: +1 -1 lines
Log Message:
use unchecked ev default loop retrieval function

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