1 //
2 // Copyright(C) 2005-2014 Simon Howard
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 
15 #include <stdlib.h>
16 #include <string.h>
17 
18 #include "doomkeys.h"
19 #include "m_misc.h"
20 
21 #include "txt_keyinput.h"
22 #include "txt_gui.h"
23 #include "txt_io.h"
24 #include "txt_label.h"
25 #include "txt_utf8.h"
26 #include "txt_window.h"
27 
28 #define KEY_INPUT_WIDTH 8
29 
KeyPressCallback(txt_window_t * window,int key,TXT_UNCAST_ARG (key_input))30 static int KeyPressCallback(txt_window_t *window, int key,
31                             TXT_UNCAST_ARG(key_input))
32 {
33     TXT_CAST_ARG(txt_key_input_t, key_input);
34 
35     if (key != KEY_ESCAPE)
36     {
37         // Got the key press. Save to the variable and close the window.
38 
39         *key_input->variable = key;
40 
41         if (key_input->check_conflicts)
42         {
43             TXT_EmitSignal(key_input, "set");
44         }
45 
46         TXT_CloseWindow(window);
47 
48         // Return to normal input mode now that we have the key.
49         TXT_SetInputMode(TXT_INPUT_NORMAL);
50 
51         return 1;
52     }
53     else
54     {
55         return 0;
56     }
57 }
58 
ReleaseGrab(TXT_UNCAST_ARG (window),TXT_UNCAST_ARG (unused))59 static void ReleaseGrab(TXT_UNCAST_ARG(window), TXT_UNCAST_ARG(unused))
60 {
61     // SDL2-TODO: Needed?
62     // SDL_WM_GrabInput(SDL_GRAB_OFF);
63 }
64 
OpenPromptWindow(txt_key_input_t * key_input)65 static void OpenPromptWindow(txt_key_input_t *key_input)
66 {
67     txt_window_t *window;
68 
69     // Silently update when the shift button is held down.
70 
71     key_input->check_conflicts = !TXT_GetModifierState(TXT_MOD_SHIFT);
72 
73     window = TXT_MessageBox(NULL, "Press the new key...");
74 
75     TXT_SetKeyListener(window, KeyPressCallback, key_input);
76 
77     // Switch to raw input mode while we're grabbing the key.
78     TXT_SetInputMode(TXT_INPUT_RAW);
79 
80     // Grab input while reading the key.  On Windows Mobile
81     // handheld devices, the hardware keypresses are only
82     // detected when input is grabbed.
83 
84     // SDL2-TODO: Needed?
85     //SDL_WM_GrabInput(SDL_GRAB_ON);
86     TXT_SignalConnect(window, "closed", ReleaseGrab, NULL);
87 }
88 
TXT_KeyInputSizeCalc(TXT_UNCAST_ARG (key_input))89 static void TXT_KeyInputSizeCalc(TXT_UNCAST_ARG(key_input))
90 {
91     TXT_CAST_ARG(txt_key_input_t, key_input);
92 
93     // All keyinputs are the same size.
94 
95     key_input->widget.w = KEY_INPUT_WIDTH;
96     key_input->widget.h = 1;
97 }
98 
99 
TXT_KeyInputDrawer(TXT_UNCAST_ARG (key_input))100 static void TXT_KeyInputDrawer(TXT_UNCAST_ARG(key_input))
101 {
102     TXT_CAST_ARG(txt_key_input_t, key_input);
103     char buf[20];
104     int i;
105 
106     if (*key_input->variable == 0)
107     {
108         M_StringCopy(buf, "(none)", sizeof(buf));
109     }
110     else
111     {
112         TXT_GetKeyDescription(*key_input->variable, buf, sizeof(buf));
113     }
114 
115     TXT_SetWidgetBG(key_input);
116     TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
117 
118     TXT_DrawString(buf);
119 
120     for (i = TXT_UTF8_Strlen(buf); i < KEY_INPUT_WIDTH; ++i)
121     {
122         TXT_DrawString(" ");
123     }
124 }
125 
TXT_KeyInputDestructor(TXT_UNCAST_ARG (key_input))126 static void TXT_KeyInputDestructor(TXT_UNCAST_ARG(key_input))
127 {
128 }
129 
TXT_KeyInputKeyPress(TXT_UNCAST_ARG (key_input),int key)130 static int TXT_KeyInputKeyPress(TXT_UNCAST_ARG(key_input), int key)
131 {
132     TXT_CAST_ARG(txt_key_input_t, key_input);
133 
134     if (key == KEY_ENTER)
135     {
136         // Open a window to prompt for the new key press
137 
138         OpenPromptWindow(key_input);
139 
140         return 1;
141     }
142 
143     if (key == KEY_BACKSPACE || key == KEY_DEL)
144     {
145         *key_input->variable = 0;
146     }
147 
148     return 0;
149 }
150 
TXT_KeyInputMousePress(TXT_UNCAST_ARG (widget),int x,int y,int b)151 static void TXT_KeyInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b)
152 {
153     TXT_CAST_ARG(txt_key_input_t, widget);
154 
155     // Clicking is like pressing enter
156 
157     if (b == TXT_MOUSE_LEFT)
158     {
159         TXT_KeyInputKeyPress(widget, KEY_ENTER);
160     }
161 }
162 
163 txt_widget_class_t txt_key_input_class =
164 {
165     TXT_AlwaysSelectable,
166     TXT_KeyInputSizeCalc,
167     TXT_KeyInputDrawer,
168     TXT_KeyInputKeyPress,
169     TXT_KeyInputDestructor,
170     TXT_KeyInputMousePress,
171     NULL,
172 };
173 
TXT_NewKeyInput(int * variable)174 txt_key_input_t *TXT_NewKeyInput(int *variable)
175 {
176     txt_key_input_t *key_input;
177 
178     key_input = malloc(sizeof(txt_key_input_t));
179 
180     TXT_InitWidget(key_input, &txt_key_input_class);
181     key_input->variable = variable;
182 
183     return key_input;
184 }
185 
186