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
Log Message:
implement dot-repetition

File Contents

# User Rev Content
1 sf-pippijn 1.1 #include "deliantra/sender.h"
2    
3     #include "dclient/input_handler.h"
4 sf-pippijn 1.6 #include "dclient/render_glyph.h"
5 sf-pippijn 1.1 #include "dclient/widgets.h"
6 sf-pippijn 1.3 #include "dclient/widgets/inventory.h"
7 sf-pippijn 1.1 #include "dclient/widgets/map.h"
8 sf-pippijn 1.3 #include "dclient/widgets/query.h"
9     #include "dclient/widgets/stats.h"
10 sf-pippijn 1.1
11 sf-pippijn 1.8 #include <ndk/application.hh>
12     #include <ndk/color.hh>
13 sf-pippijn 1.1
14     #include <curses.h>
15    
16 sf-pippijn 1.8 #include <ev.h>
17    
18 sf-pippijn 1.1 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 sf-pippijn 1.3 resize,
69     maximise,
70 sf-pippijn 1.1 input_mode,
71    
72     apply,
73     take,
74    
75 sf-kernelpanic 1.13 repeat,
76    
77 sf-pippijn 1.1 COUNT
78     };
79    
80    
81     struct input_handler::pimpl
82     : sender
83     {
84 sf-pippijn 1.8 pimpl (communicator &comm, widgets &ui);
85 sf-pippijn 1.1
86 sf-pippijn 1.7 void perform (ndk::panel *sender, action cmd, action arg = action::none);
87 sf-pippijn 1.1
88 sf-pippijn 1.3 ndk::event::result on_kbd_common (ndk::keyboard const &ev);
89     ndk::event::result on_kbd_map (ndk::keyboard const &ev);
90 sf-pippijn 1.1
91     void on_command (std::string const &cmd);
92 sf-pippijn 1.8 void stdin_read_cb (ev::io &w, int revents);
93 sf-pippijn 1.1
94     widgets &ui;
95     std::string esc;
96 sf-kernelpanic 1.13 std::string last_cmd;
97 sf-pippijn 1.8 ev::io stdin_watcher;
98 sf-pippijn 1.1 flags state;
99     };
100    
101 sf-pippijn 1.8 input_handler::pimpl::pimpl (communicator &comm, widgets &ui)
102 sf-pippijn 1.1 : sender (comm)
103     , ui (ui)
104     , state (flags::none)
105     {
106 sf-pippijn 1.3 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 sf-pippijn 1.8
120     stdin_watcher.set (STDIN_FILENO, ev::READ);
121     stdin_watcher.set<pimpl, &pimpl::stdin_read_cb> (this);
122     stdin_watcher.start ();
123 sf-pippijn 1.1 }
124    
125     void
126 sf-pippijn 1.7 input_handler::pimpl::perform (ndk::panel *sender, action cmd, action arg)
127 sf-pippijn 1.1 {
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 sf-pippijn 1.10 ev_break (EV_DEFAULT_UC_ EVBREAK_ALL);
173 sf-pippijn 1.1 break;
174    
175     case action::redraw:
176     redrawwin (stdscr);
177     break;
178    
179 sf-pippijn 1.3 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 sf-pippijn 1.1 case action::input_mode:
192 sf-pippijn 1.3 ui.input->visualize ();
193     ui.input->focus ();
194 sf-pippijn 1.1 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 sf-kernelpanic 1.13 case action::repeat:
206     if (!last_cmd.empty())
207     send ("command", last_cmd);
208     break;
209    
210 sf-pippijn 1.1 // never happens
211     case action::COUNT:
212     abort ();
213     }
214     }
215    
216     ndk::event::result
217 sf-pippijn 1.3 input_handler::pimpl::on_kbd_common (ndk::keyboard const &ev)
218 sf-pippijn 1.1 {
219     switch (ev.code ())
220     {
221     case ndk::key::error:
222 sf-pippijn 1.12 throw std::runtime_error ("ERR");
223 sf-pippijn 1.1
224 sf-pippijn 1.3 // 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 sf-pippijn 1.1 // moving
253     case 'j':
254     case '2':
255     case ndk::key::down:
256 sf-pippijn 1.3 perform (ev.sender (), action::south);
257 sf-pippijn 1.1 return ndk::event::accepted;
258     case 'k':
259     case '8':
260     case ndk::key::up:
261 sf-pippijn 1.3 perform (ev.sender (), action::north);
262 sf-pippijn 1.1 return ndk::event::accepted;
263     case 'h':
264     case '4':
265     case ndk::key::left:
266 sf-pippijn 1.3 perform (ev.sender (), action::west);
267 sf-pippijn 1.1 return ndk::event::accepted;
268     case 'l':
269     case '6':
270     case ndk::key::right:
271 sf-pippijn 1.3 perform (ev.sender (), action::east);
272 sf-pippijn 1.1 return ndk::event::accepted;
273     case '7':
274     case ndk::key::home:
275 sf-pippijn 1.3 perform (ev.sender (), action::northwest);
276 sf-pippijn 1.1 return ndk::event::accepted;
277     case '9':
278     case ndk::key::pg_up:
279 sf-pippijn 1.3 perform (ev.sender (), action::northeast);
280 sf-pippijn 1.1 return ndk::event::accepted;
281     case '5':
282     case ndk::key::numpad_center:
283 sf-pippijn 1.3 perform (ev.sender (), action::stay_fire);
284 sf-pippijn 1.1 return ndk::event::accepted;
285     case '1':
286     case ndk::key::end:
287 sf-pippijn 1.3 perform (ev.sender (), action::southwest);
288 sf-pippijn 1.1 return ndk::event::accepted;
289     case '3':
290     case ndk::key::pg_dn:
291 sf-pippijn 1.3 perform (ev.sender (), action::southeast);
292 sf-pippijn 1.1 return ndk::event::accepted;
293    
294     case ' ':
295 sf-pippijn 1.3 perform (ev.sender (), action::apply);
296 sf-pippijn 1.1 return ndk::event::accepted;
297     case ',':
298 sf-pippijn 1.3 perform (ev.sender (), action::take);
299 sf-pippijn 1.1 return ndk::event::accepted;
300 sf-kernelpanic 1.13 case '.':
301     perform (ev.sender (), action::repeat);
302     return ndk::event::accepted;
303 sf-pippijn 1.1 case ndk::key::enter:
304     case 'i':
305 sf-pippijn 1.3 perform (ev.sender (), action::input_mode);
306 sf-pippijn 1.1 return ndk::event::accepted;
307     case 'c':
308 sf-pippijn 1.3 ui.input->set_text ("chat ");
309     perform (ev.sender (), action::input_mode);
310 sf-pippijn 1.1 return ndk::event::accepted;
311     case '"':
312 sf-pippijn 1.3 ui.input->set_text ("say ");
313     perform (ev.sender (), action::input_mode);
314 sf-pippijn 1.1 return ndk::event::accepted;
315     case '\'':
316 sf-pippijn 1.3 ui.input->set_text ("tell ");
317     perform (ev.sender (), action::input_mode);
318 sf-pippijn 1.1 return ndk::event::accepted;
319    
320     // firing
321     case 'J':
322     case ndk::key::shift_down:
323 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::south);
324 sf-pippijn 1.1 return ndk::event::accepted;
325     case 'K':
326     case ndk::key::shift_up:
327 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::north);
328 sf-pippijn 1.1 return ndk::event::accepted;
329     case 'H':
330     case ndk::key::shift_left:
331 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::west);
332 sf-pippijn 1.1 return ndk::event::accepted;
333     case 'L':
334     case ndk::key::shift_right:
335 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::east);
336 sf-pippijn 1.1 return ndk::event::accepted;
337     case ndk::key::shift_home:
338 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::northwest);
339 sf-pippijn 1.1 return ndk::event::accepted;
340     case ndk::key::shift_pg_up:
341 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::northeast);
342 sf-pippijn 1.1 return ndk::event::accepted;
343     case ndk::key::shift_end:
344 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::southwest);
345 sf-pippijn 1.1 return ndk::event::accepted;
346     case ndk::key::shift_pg_dn:
347 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::southeast);
348 sf-pippijn 1.1 return ndk::event::accepted;
349    
350     // running
351     //case 'J':
352     case ndk::key::ctrl_down:
353 sf-pippijn 1.3 perform (ev.sender (), action::run, action::south);
354 sf-pippijn 1.1 return ndk::event::accepted;
355     //case 'K':
356     case ndk::key::ctrl_up:
357 sf-pippijn 1.3 perform (ev.sender (), action::run, action::north);
358 sf-pippijn 1.1 return ndk::event::accepted;
359     //case 'H':
360     case ndk::key::ctrl_left:
361 sf-pippijn 1.3 perform (ev.sender (), action::run, action::west);
362 sf-pippijn 1.1 return ndk::event::accepted;
363     //case 'L':
364     case ndk::key::ctrl_right:
365 sf-pippijn 1.3 perform (ev.sender (), action::run, action::east);
366 sf-pippijn 1.1 return ndk::event::accepted;
367     case ndk::key::ctrl_home:
368 sf-pippijn 1.3 perform (ev.sender (), action::run, action::northwest);
369 sf-pippijn 1.1 return ndk::event::accepted;
370     case ndk::key::ctrl_pg_up:
371 sf-pippijn 1.3 perform (ev.sender (), action::run, action::northeast);
372 sf-pippijn 1.1 return ndk::event::accepted;
373     case ndk::key::ctrl_end:
374 sf-pippijn 1.3 perform (ev.sender (), action::run, action::southwest);
375 sf-pippijn 1.1 return ndk::event::accepted;
376     case ndk::key::ctrl_pg_dn:
377 sf-pippijn 1.3 perform (ev.sender (), action::run, action::southeast);
378 sf-pippijn 1.1 return ndk::event::accepted;
379    
380 sf-pippijn 1.5 case ndk::key::ctrl_l:
381 sf-pippijn 1.4 case ndk::key::F10:
382     case ndk::key::resize:
383 sf-pippijn 1.1 case ndk::key::tab:
384     return ndk::event::ignored;
385    
386     case ndk::key::unknown:
387 sf-pippijn 1.3 return ndk::event::ignored;
388 sf-pippijn 1.1
389     default:
390     if (getenv ("DCLIENT_FATAL"))
391     throw ev.code ();
392     else
393     {
394 sf-pippijn 1.6 ui.info->add_text (ndi_color (3, 0), "unknown keycode: 0%03o\n", ev.code ());
395 sf-pippijn 1.3 ui.info->visualize ();
396     return ndk::event::ignored;
397 sf-pippijn 1.1 }
398     }
399     }
400    
401     void
402     input_handler::pimpl::on_command (std::string const &cmd)
403     {
404 sf-pippijn 1.8 ui.input->set_text ("");
405    
406 sf-pippijn 1.3 if (!cmd.empty ())
407 sf-kernelpanic 1.13 {
408     send ("command", cmd);
409     last_cmd = cmd;
410     }
411 sf-pippijn 1.8 else
412     {
413     ui.map->focus ();
414     ui.input->hide ();
415     ndk::app->cursor_off (); // FIXME: should be done automatically
416     }
417     }
418 sf-pippijn 1.1
419 sf-pippijn 1.8 void
420     input_handler::pimpl::stdin_read_cb (ev::io &w, int revents)
421     {
422     ndk::app->process (getch ());
423 sf-pippijn 1.1 }
424    
425    
426 sf-pippijn 1.8 input_handler::input_handler (communicator &comm, widgets &ui)
427     : impl (new pimpl (comm, ui))
428 sf-pippijn 1.1 {
429     }
430    
431     input_handler::~input_handler ()
432     {
433     delete impl;
434     }