2 # include "osx_messagebox.h"
3 #elif defined(unix) && defined(HAVE_GTK2)
11 typedef short int16_t;
13 typedef long long int64_t;
14 typedef unsigned short uint16_t;
15 typedef unsigned int uint32_t;
16 typedef unsigned long long uint64_t;
19 typedef int32_t VIndex
;
20 typedef int32_t Ordinal
;
26 #include "keybindings.h"
27 #include "KeybindingScreen.h"
39 InterfaceKey start
, end
;
42 const BindingGroup groups
[] = {
43 {"General" , INTERFACEKEY_NONE
, WORLDKEY_START
-1},
44 {"World" , WORLDKEY_START
, ADVENTURERKEY_START
-1},
45 {"Adventurer" , ADVENTURERKEY_START
, EMBARKKEY_START
-1},
46 {"Dwarf mode" , DWARFMAINKEY_START
, MILITIAKEY_START
-1},
47 {"Embark" , EMBARKKEY_START
, BUILDINGKEY_START
-1},
48 {"Building" , BUILDINGKEY_START
, WORKSHOPKEY_START
-1},
49 {"Workshop" , WORKSHOPKEY_START
, PILEZONEKEY_START
-1},
50 {"Pilezone" , PILEZONEKEY_START
, STOCKORDERKEY_START
-1},
51 {"Stockorder" , STOCKORDERKEY_START
, DWARFMAINKEY_START
-1},
52 {"Militia" , MILITIAKEY_START
, INTERFACEKEY_STRING_A000
-1},
53 {"Text entry" , INTERFACEKEY_STRING_A000
, INTERFACEKEY_STRING_A255
}
56 KeybindingScreen::KeybindingScreen() {
57 gview
.addscreen(this, INTERFACE_PUSH_AT_BACK
, NULL
); // HACK
60 main
.add("Macros", sel_macros
);
61 for (int i
= 0; i
< ARRSZ(groups
); i
++)
62 main
.set(i
+2, groups
[i
].name
, sel_first_group
+ i
);
63 main
.set(ARRSZ(groups
)+3, "Save and exit", sel_save_exit
);
64 main
.add("Exit, discard changes when DF quits", sel_just_exit
);
65 enabler
.flag
|= ENABLERFLAG_RENDER
;
68 void KeybindingScreen::feed(set
<InterfaceKey
> &input
) {
69 enabler
.flag
|=ENABLERFLAG_RENDER
;
70 if (input
.count(INTERFACEKEY_KEYBINDING_COMPLETE
)) {
71 list
<RegisteredKey
> keys
= enabler
.getRegisteredKey();
72 if (keys
.size() == 0) {
73 puts("No keys registered ?!");
77 list
<RegisteredKey
> keys
= enabler
.getRegisteredKey();
78 for (list
<RegisteredKey
>::iterator it
= keys
.begin(); it
!= keys
.end(); ++it
) {
81 case type_button
: display
= "Mouse button: "; break;
82 case type_key
: display
= "By position: "; break;
83 case type_unicode
: display
= "By letter: "; break;
85 keyRegister
.add(display
+ it
->display
, it
->type
);
88 } else if (input
.count(INTERFACEKEY_STANDARDSCROLL_PAGEUP
) ||
89 input
.count(INTERFACEKEY_STANDARDSCROLL_PAGEDOWN
) ||
90 input
.count(INTERFACEKEY_STANDARDSCROLL_UP
) ||
91 input
.count(INTERFACEKEY_STANDARDSCROLL_DOWN
)) {
93 case mode_main
: main
.feed(input
); break;
94 case mode_keyL
: keyL
.feed(input
); reset_keyR(); break;
95 case mode_keyR
: keyR
.feed(input
); break;
96 case mode_macro
: macro
.feed(input
); break;
97 case mode_register
: keyRegister
.feed(input
); break;
99 } else if (mode
== mode_keyL
&& input
.count(INTERFACEKEY_STANDARDSCROLL_RIGHT
))
101 else if (mode
== mode_main
&& input
.count(INTERFACEKEY_STANDARDSCROLL_RIGHT
)) {
102 if (main
.get_selection() == sel_macros
) enter_macros();
103 if (main
.get_selection() >= sel_first_group
)
104 enter_key(main
.get_selection() - sel_first_group
);
105 } else if (mode
== mode_keyR
&& input
.count(INTERFACEKEY_STANDARDSCROLL_LEFT
))
107 else if ((mode
== mode_keyL
|| mode
== mode_macro
) && input
.count(INTERFACEKEY_STANDARDSCROLL_LEFT
))
109 else if (input
.count(INTERFACEKEY_STRING_A000
)) { // Backspace: Delete something.
112 if (macro
.get_selection() != "") {
113 enabler
.delete_macro(macro
.get_selection());
114 macro
.del_selection();
116 macro
.add("No macros!", "");
120 keyR_selector sel
= keyR
.get_selection();
121 if (sel
.sel
== sel_event
) {
122 enabler
.remove_key(keyL
.get_selection(), sel
.event
);
127 } else if (input
.count(INTERFACEKEY_SELECT
)) {
130 if (main
.get_selection() == sel_macros
) { // Macros
132 } else if (main
.get_selection() == sel_save_exit
) { // Save and exit
133 enabler
.save_keybindings();
134 breakdownlevel
= INTERFACE_BREAKDOWN_STOPSCREEN
;
136 } else if (main
.get_selection() == sel_just_exit
) { // Just exit
137 breakdownlevel
= INTERFACE_BREAKDOWN_STOPSCREEN
;
139 } else { // Some key-binding group
140 enter_key(main
.get_selection() - sel_first_group
);
144 InterfaceKey key
= keyL
.get_selection();
145 switch (keyR
.get_selection().sel
) {
147 enabler
.register_key();
148 mode
= mode_register
;
151 enabler
.key_repeat(key
, REPEAT_NOT
);
155 enabler
.key_repeat(key
, REPEAT_SLOW
);
159 enabler
.key_repeat(key
, REPEAT_FAST
);
165 enabler
.bindRegisteredKey(keyRegister
.get_selection(), keyL
.get_selection());
170 } else if (input
.count(INTERFACEKEY_LEAVESCREEN
) || input
.count(INTERFACEKEY_OPTIONS
)) {
171 if (mode
== mode_register
)
178 void KeybindingScreen::logic() {
179 if (mode
== mode_register
)
180 enabler
.flag
|=ENABLERFLAG_RENDER
;
183 void KeybindingScreen::enter_macros() {
186 list
<string
> macros
= enabler
.list_macros();
187 for (list
<string
>::iterator it
= macros
.begin(); it
!= macros
.end(); ++it
)
190 macro
.add("No macros!", "");
193 void KeybindingScreen::enter_key(int group
) {
196 for (InterfaceKey i
= groups
[group
].start
; i
<= groups
[group
].end
; i
++) {
197 if (i
!= INTERFACEKEY_NONE
)
198 keyL
.add(enabler
.GetBindingTextDisplay(i
), i
);
203 void KeybindingScreen::reset_keyR() {
204 int lastpos
= keyR
.get_pos();
206 struct keyR_selector sel
;
208 keyR
.add("Add binding", sel
);
209 InterfaceKey key
= keyL
.get_selection();
210 list
<EventMatch
> matchers
= enabler
.list_keys(key
);
211 Repeat rep
= enabler
.key_repeat(key
);
212 sel
.sel
= sel_rep_none
;
213 keyR
.set(2, "Don't repeat", sel
);
214 if (rep
== REPEAT_NOT
) keyR
.set_color(2, 4, 0);
215 sel
.sel
= sel_rep_slow
;
216 keyR
.set(3, "Delayed repeat", sel
);
217 if (rep
== REPEAT_SLOW
) keyR
.set_color(3, 4, 0);
218 sel
.sel
= sel_rep_fast
;
219 keyR
.set(4, "Immediate repeat", sel
);
220 if (rep
== REPEAT_FAST
) keyR
.set_color(4, 4, 0);
222 for (list
<EventMatch
>::iterator it
= matchers
.begin(); it
!= matchers
.end(); ++it
, ++i
) {
226 desc
<< "By letter: ";
227 if (it
->unicode
< 256 && isgraph(it
->unicode
)) // Is it printable?
228 desc
<< (char)it
->unicode
;
230 desc
<< "U+" << hex
<< uppercase
<< it
->unicode
;
233 desc
<< "By position: " << translate_mod(it
->mod
) << sdlNames
.left
[it
->key
];
236 desc
<< "Mouse: " << (int)it
->button
;
241 keyR
.set(i
, desc
.str(), sel
);
243 keyR
.set_pos(lastpos
);
246 void KeybindingScreen::render_macro() {
247 drawborder("Macros");
249 gps
.changecolor(4,0,1);
250 gps
.addst("Select a macro, then press " + enabler
.GetKeyDisplay(INTERFACEKEY_STRING_A000
) + " to delete.");
251 macro
.render(6, init
.display
.grid_x
-2, 5, init
.display
.grid_y
-2);
254 void KeybindingScreen::render_key() {
255 if (enabler
.is_registering()) {
256 gps
.changecolor(4,0,1);
257 drawborder("Keybinding - currently registering new key");
259 drawborder("Keybinding");
261 gps
.changecolor(4,0,1);
262 gps
.addst("Select a binding, then press " + enabler
.GetKeyDisplay(INTERFACEKEY_STRING_A000
) + " to delete.");
263 keyL
.render(6, init
.display
.grid_x
/2 - 1, 5, init
.display
.grid_y
-2);
264 if (mode
== mode_keyL
|| mode
== mode_register
)
268 keyR
.render(init
.display
.grid_x
/2 + 1, init
.display
.grid_x
-2, 5, init
.display
.grid_y
-2);
271 void KeybindingScreen::render_register() {
272 int x1
= init
.display
.grid_x
/ 2 - 20,
273 x2
= init
.display
.grid_x
/ 2 + 20,
274 y1
= init
.display
.grid_y
/ 2 - 1,
275 y2
= init
.display
.grid_y
/ 2 + 1;
276 if (!enabler
.is_registering()) {
277 y2
= y1
+ keyRegister
.size() + 1;
279 gps
.erasescreen_rect(x1
, x2
, y1
, y2
);
280 gps
.changecolor(1,1,1);
281 for (int x
= x1
; x
<= x2
; x
++) {
282 gps
.locate(y1
, x
); gps
.addchar(' ');
283 gps
.locate(y2
, x
); gps
.addchar(' ');
285 for (int y
= y1
+ 1; y
< y2
; y
++) {
286 gps
.locate(y
, x1
); gps
.addchar(' ');
287 gps
.locate(y
, x2
); gps
.addchar(' ');
289 if (enabler
.is_registering()) {
290 gps
.changecolor(7,0,1);
291 gps
.locate(y1
+1, x1
+2);
292 gps
.addst(translate_mod(getModState()));
294 keyRegister
.render(x1
+1, x2
-1, y1
+1, y2
-1);
295 gps
.locate(y2
, x1
+2);
296 gps
.changecolor(7,1,1);
297 gps
.addst("Select binding, or press space to abort");
301 // Render the main menu
302 void KeybindingScreen::render_main() {
303 drawborder("Key binding & macro center");
304 main
.render(6, init
.display
.grid_x
- 3, 3, init
.display
.grid_y
- 4);
307 void KeybindingScreen::render() {
309 case mode_main
: render_main(); break;
310 case mode_keyL
: case mode_keyR
: render_key(); break;
311 case mode_macro
: render_macro(); break;
319 void KeybindingScreen::help() {
323 MacroScreenLoad::MacroScreenLoad() {
324 list
<string
> macros
= enabler
.list_macros();
326 if (!macros
.size()) {
327 menu
.add("No macros!", "");
330 height
= macros
.size();
332 for (list
<string
>::iterator it
= macros
.begin(); it
!= macros
.end(); ++it
) {
333 if (it
->length() > width
) width
= it
->length();
336 enabler
.flag
|= ENABLERFLAG_RENDER
;
338 // gps.renewscreen();
341 void MacroScreenLoad::feed(set
<InterfaceKey
> &input
) {
342 enabler
.flag
|=ENABLERFLAG_RENDER
;
343 if (input
.count(INTERFACEKEY_SELECT
)) {
344 string id
= menu
.get_selection();
345 if (id
!= "") enabler
.load_macro(id
);
346 breakdownlevel
= INTERFACE_BREAKDOWN_STOPSCREEN
;
348 } else if (input
.count(INTERFACEKEY_LEAVESCREEN
)) {
349 breakdownlevel
= INTERFACE_BREAKDOWN_STOPSCREEN
;
354 if (input
.count(INTERFACEKEY_OPTIONS
)) {
355 breakdownlevel
= INTERFACE_BREAKDOWN_STOPSCREEN
;
359 void MacroScreenLoad::logic() {
362 void MacroScreenLoad::render() {
363 if (parent
) parent
->render();
364 const int x1
= MAX(init
.display
.grid_x
/2 - ((width
+ 2) / 2), 0);
365 const int x2
= MIN(x1
+width
+1, init
.display
.grid_x
-1);
366 const int y1
= MAX(init
.display
.grid_y
/2 - ((height
+ 2) / 2), 0);
367 const int y2
= MIN(y1
+ height
+ 1, init
.display
.grid_y
-1);
368 gps
.changecolor(0,3,1);
369 gps
.draw_border(x1
, x2
, y1
, y2
);
370 menu
.render(x1
+1, x2
-1, y1
+1, y2
-1);
371 // gps.renewscreen();
374 MacroScreenSave::MacroScreenSave() {
375 enabler
.flag
|= ENABLERFLAG_RENDER
;
378 void MacroScreenSave::logic() {
381 void MacroScreenSave::feed(set
<InterfaceKey
> &input
) {
382 enabler
.flag
|=ENABLERFLAG_RENDER
;
384 if (input
.count(INTERFACEKEY_SELECT
)) {
385 string n
= id
.get_text();
387 enabler
.save_macro(n
);
388 breakdownlevel
= INTERFACE_BREAKDOWN_STOPSCREEN
;
391 if (input
.count(INTERFACEKEY_OPTIONS
)) {
392 breakdownlevel
= INTERFACE_BREAKDOWN_STOPSCREEN
;
396 void MacroScreenSave::render() {
397 if (parent
) parent
->render();
399 x2
= init
.display
.grid_x
-4,
400 y1
= init
.display
.grid_y
/2-1,
401 y2
= init
.display
.grid_y
/2+1;
402 gps
.changecolor(0,3,1);
403 gps
.draw_border(x1
, x2
, y1
, y2
);
404 id
.render(x1
+1,x2
-1,y1
+1,y2
-1);
405 // gps.renewscreen();