~ubuntu-branches/debian/squeeze/openttd/squeeze

« back to all changes in this revision

Viewing changes to src/osk_gui.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jordi Mallach, Matthijs Kooijman, Jordi Mallach
  • Date: 2009-04-15 18:22:10 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090415182210-22ktb8kdbp2tf3bm
[ Matthijs Kooijman ]
* New upstream release.
* Remove Debian specific desktop file, upstream provides one now. 
* Add debian/watch file.

[ Jordi Mallach ]
* Bump Standards-Version to 3.8.1, with no changes required.
* Move to debhelper compat 7. Bump Build-Depends accordingly.
* Use dh_prep.
* Add "set -e" to config script.
* Remove a few extra doc files that get installed by upstream Makefile.
* Add more complete copyright information.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: osk_gui.cpp 15723 2009-03-15 15:12:06Z rubidium $ */
 
2
 
 
3
/** @file osk_gui.cpp The On Screen Keyboard GUI */
 
4
 
 
5
#include "stdafx.h"
 
6
#include "string_func.h"
 
7
#include "strings_func.h"
 
8
#include "debug.h"
 
9
#include "window_func.h"
 
10
#include "gfx_func.h"
 
11
#include "querystring_gui.h"
 
12
 
 
13
#include "table/sprites.h"
 
14
#include "table/strings.h"
 
15
 
 
16
enum OskWidgets {
 
17
        OSK_WIDGET_TEXT = 3,
 
18
        OSK_WIDGET_CANCEL = 5,
 
19
        OSK_WIDGET_OK,
 
20
        OSK_WIDGET_BACKSPACE,
 
21
        OSK_WIDGET_SPECIAL,
 
22
        OSK_WIDGET_CAPS,
 
23
        OSK_WIDGET_SHIFT,
 
24
        OSK_WIDGET_SPACE,
 
25
        OSK_WIDGET_LEFT,
 
26
        OSK_WIDGET_RIGHT,
 
27
        OSK_WIDGET_LETTERS
 
28
};
 
29
 
 
30
char _keyboard_opt[2][OSK_KEYBOARD_ENTRIES * 4 + 1];
 
31
static WChar _keyboard[2][OSK_KEYBOARD_ENTRIES];
 
32
 
 
33
enum {
 
34
        KEYS_NONE,
 
35
        KEYS_SHIFT,
 
36
        KEYS_CAPS
 
37
};
 
38
static byte _keystate = KEYS_NONE;
 
39
 
 
40
struct OskWindow : public Window {
 
41
        StringID caption;      ///< the caption for this window.
 
42
        QueryString *qs;       ///< text-input
 
43
        int text_btn;          ///< widget number of parent's text field
 
44
        int ok_btn;            ///< widget number of parent's ok button (=0 when ok shouldn't be passed on)
 
45
        int cancel_btn;        ///< widget number of parent's cancel button (=0 when cancel shouldn't be passed on; text will be reverted to original)
 
46
        Textbuf *text;         ///< pointer to parent's textbuffer (to update caret position)
 
47
        char *orig_str_buf;    ///< Original string.
 
48
 
 
49
        OskWindow(const WindowDesc *desc, QueryStringBaseWindow *parent, int button, int cancel, int ok) : Window(desc)
 
50
        {
 
51
                this->parent = parent;
 
52
                assert(parent != NULL);
 
53
 
 
54
                this->caption = (parent->widget[button].data != STR_NULL) ? parent->widget[button].data : parent->caption;
 
55
 
 
56
                this->qs         = parent;
 
57
                this->text_btn   = button;
 
58
                this->cancel_btn = cancel;
 
59
                this->ok_btn     = ok;
 
60
                this->text       = &parent->text;
 
61
 
 
62
                /* make a copy in case we need to reset later */
 
63
                this->orig_str_buf = strdup(this->qs->text.buf);
 
64
 
 
65
                /* Not needed by default. */
 
66
                this->DisableWidget(OSK_WIDGET_SPECIAL);
 
67
 
 
68
                this->FindWindowPlacementAndResize(desc);
 
69
        }
 
70
 
 
71
        ~OskWindow()
 
72
        {
 
73
                free(this->orig_str_buf);
 
74
        }
 
75
 
 
76
        /**
 
77
         * Only show valid characters; do not show characters that would
 
78
         * only insert a space when we have a spacebar to do that or
 
79
         * characters that are not allowed to be entered.
 
80
         */
 
81
        void ChangeOskDiabledState(bool shift)
 
82
        {
 
83
                for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
 
84
                        this->SetWidgetDisabledState(OSK_WIDGET_LETTERS + i,
 
85
                                        !IsValidChar(_keyboard[shift][i], this->qs->afilter) || _keyboard[shift][i] == ' ');
 
86
                }
 
87
                this->SetWidgetDisabledState(OSK_WIDGET_SPACE, !IsValidChar(' ', this->qs->afilter));
 
88
        }
 
89
 
 
90
        virtual void OnPaint()
 
91
        {
 
92
                bool shift = HasBit(_keystate, KEYS_CAPS) ^ HasBit(_keystate, KEYS_SHIFT);
 
93
 
 
94
                this->LowerWidget(OSK_WIDGET_TEXT);
 
95
                this->SetWidgetLoweredState(OSK_WIDGET_SHIFT, HasBit(_keystate, KEYS_SHIFT));
 
96
                this->SetWidgetLoweredState(OSK_WIDGET_CAPS, HasBit(_keystate, KEYS_CAPS));
 
97
 
 
98
                this->ChangeOskDiabledState(shift);
 
99
 
 
100
                SetDParam(0, this->caption);
 
101
                this->DrawWidgets();
 
102
 
 
103
                for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
 
104
                        DrawCharCentered(_keyboard[shift][i],
 
105
                                this->widget[OSK_WIDGET_LETTERS + i].left + 8,
 
106
                                this->widget[OSK_WIDGET_LETTERS + i].top + 3,
 
107
                                TC_BLACK);
 
108
                }
 
109
 
 
110
                this->qs->DrawEditBox(this, OSK_WIDGET_TEXT);
 
111
        }
 
112
 
 
113
        virtual void OnClick(Point pt, int widget)
 
114
        {
 
115
                /* clicked a letter */
 
116
                if (widget >= OSK_WIDGET_LETTERS) {
 
117
                        bool shift = HasBit(_keystate, KEYS_CAPS) ^ HasBit(_keystate, KEYS_SHIFT);
 
118
 
 
119
                        WChar c = _keyboard[shift][widget - OSK_WIDGET_LETTERS];
 
120
 
 
121
                        if (!IsValidChar(c, this->qs->afilter)) return;
 
122
 
 
123
                        if (InsertTextBufferChar(&this->qs->text, c)) this->InvalidateParent();
 
124
 
 
125
                        if (HasBit(_keystate, KEYS_SHIFT)) {
 
126
                                ToggleBit(_keystate, KEYS_SHIFT);
 
127
                                this->widget[OSK_WIDGET_SHIFT].colour = HasBit(_keystate, KEYS_SHIFT) ? COLOUR_WHITE : COLOUR_GREY;
 
128
                                this->SetDirty();
 
129
                        }
 
130
                        return;
 
131
                }
 
132
 
 
133
                switch (widget) {
 
134
                        case OSK_WIDGET_TEXT:
 
135
                                /* Find the edit box of the parent window and give focus to that */
 
136
                                for (uint i = 0; i < this->parent->widget_count; i++) {
 
137
                                        Widget &wi = this->parent->widget[i];
 
138
                                        if (wi.type == WWT_EDITBOX) {
 
139
                                                this->parent->focused_widget = &wi;
 
140
                                                break;
 
141
                                        }
 
142
                                }
 
143
 
 
144
                                /* Give focus to parent window */
 
145
                                SetFocusedWindow(this->parent);
 
146
 
 
147
                                break;
 
148
 
 
149
                        case OSK_WIDGET_BACKSPACE:
 
150
                                if (DeleteTextBufferChar(&this->qs->text, WKC_BACKSPACE)) this->InvalidateParent();
 
151
                                break;
 
152
 
 
153
                        case OSK_WIDGET_SPECIAL:
 
154
                                /*
 
155
                                 * Anything device specific can go here.
 
156
                                 * The button itself is hidden by default, and when you need it you
 
157
                                 * can not hide it in the create event.
 
158
                                 */
 
159
                                break;
 
160
 
 
161
                        case OSK_WIDGET_CAPS:
 
162
                                ToggleBit(_keystate, KEYS_CAPS);
 
163
                                this->SetDirty();
 
164
                                break;
 
165
 
 
166
                        case OSK_WIDGET_SHIFT:
 
167
                                ToggleBit(_keystate, KEYS_SHIFT);
 
168
                                this->SetDirty();
 
169
                                break;
 
170
 
 
171
                        case OSK_WIDGET_SPACE:
 
172
                                if (InsertTextBufferChar(&this->qs->text, ' ')) this->InvalidateParent();
 
173
                                break;
 
174
 
 
175
                        case OSK_WIDGET_LEFT:
 
176
                                if (MoveTextBufferPos(&this->qs->text, WKC_LEFT)) this->InvalidateParent();
 
177
                                break;
 
178
 
 
179
                        case OSK_WIDGET_RIGHT:
 
180
                                if (MoveTextBufferPos(&this->qs->text, WKC_RIGHT)) this->InvalidateParent();
 
181
                                break;
 
182
 
 
183
                        case OSK_WIDGET_OK:
 
184
                                if (this->qs->orig == NULL || strcmp(this->qs->text.buf, this->qs->orig) != 0) {
 
185
                                        /* pass information by simulating a button press on parent window */
 
186
                                        if (this->ok_btn != 0) {
 
187
                                                this->parent->OnClick(pt, this->ok_btn);
 
188
                                                /* Window gets deleted when the parent window removes itself. */
 
189
                                                return;
 
190
                                        }
 
191
                                }
 
192
                                delete this;
 
193
                                break;
 
194
 
 
195
                        case OSK_WIDGET_CANCEL:
 
196
                                if (this->cancel_btn != 0) { // pass a cancel event to the parent window
 
197
                                        this->parent->OnClick(pt, this->cancel_btn);
 
198
                                        /* Window gets deleted when the parent window removes itself. */
 
199
                                        return;
 
200
                                } else { // or reset to original string
 
201
                                        strcpy(qs->text.buf, this->orig_str_buf);
 
202
                                        UpdateTextBufferSize(&qs->text);
 
203
                                        MoveTextBufferPos(&qs->text, WKC_END);
 
204
                                        this->InvalidateParent();
 
205
                                        delete this;
 
206
                                }
 
207
                                break;
 
208
                }
 
209
        }
 
210
 
 
211
        void InvalidateParent()
 
212
        {
 
213
                QueryStringBaseWindow *w = dynamic_cast<QueryStringBaseWindow*>(this->parent);
 
214
                if (w != NULL) w->OnOSKInput(this->text_btn);
 
215
 
 
216
                this->InvalidateWidget(OSK_WIDGET_TEXT);
 
217
                if (this->parent != NULL) this->parent->InvalidateWidget(this->text_btn);
 
218
        }
 
219
 
 
220
        virtual void OnMouseLoop()
 
221
        {
 
222
                this->qs->HandleEditBox(this, OSK_WIDGET_TEXT);
 
223
                /* make the caret of the parent window also blink */
 
224
                this->parent->InvalidateWidget(this->text_btn);
 
225
        }
 
226
 
 
227
        virtual void OnInvalidateData(int)
 
228
        {
 
229
                this->InvalidateWidget(OSK_WIDGET_TEXT);
 
230
        }
 
231
};
 
232
 
 
233
static const Widget _osk_widgets[] = {
 
234
{      WWT_EMPTY, RESIZE_NONE,  COLOUR_GREY,     0,     0,     0,     0, 0x0,               STR_NULL},
 
235
{    WWT_CAPTION, RESIZE_NONE,  COLOUR_GREY,     0,   255,     0,    13, STR_012D,          STR_NULL},
 
236
{      WWT_PANEL, RESIZE_NONE,  COLOUR_GREY,     0,   255,    14,    29, 0x0,               STR_NULL},
 
237
{    WWT_EDITBOX, RESIZE_NONE,  COLOUR_GREY,     2,   253,    16,    27, 0x0,               STR_NULL},
 
238
 
 
239
{      WWT_PANEL, RESIZE_NONE,  COLOUR_GREY,     0,   255,    30,   139, 0x0,               STR_NULL},
 
240
 
 
241
{    WWT_TEXTBTN, RESIZE_NONE,  COLOUR_GREY,     3,   108,    35,    46, STR_012E_CANCEL,   STR_NULL},
 
242
{    WWT_TEXTBTN, RESIZE_NONE,  COLOUR_GREY,   111,   216,    35,    46, STR_012F_OK,       STR_NULL},
 
243
{ WWT_PUSHIMGBTN, RESIZE_NONE,  COLOUR_GREY,   219,   252,    35,    46, SPR_OSK_BACKSPACE, STR_NULL},
 
244
 
 
245
{ WWT_PUSHIMGBTN, RESIZE_NONE,  COLOUR_GREY,     3,    27,    67,    82, SPR_OSK_SPECIAL,   STR_NULL},
 
246
{     WWT_IMGBTN, RESIZE_NONE,  COLOUR_GREY,     3,    36,    85,   100, SPR_OSK_CAPS,      STR_NULL},
 
247
{     WWT_IMGBTN, RESIZE_NONE,  COLOUR_GREY,     3,    27,   103,   118, SPR_OSK_SHIFT,     STR_NULL},
 
248
 
 
249
{ WWT_PUSHTXTBTN, RESIZE_NONE,  COLOUR_GREY,    75,   189,   121,   136, STR_EMPTY,         STR_NULL},
 
250
 
 
251
{ WWT_PUSHIMGBTN, RESIZE_NONE,  COLOUR_GREY,   219,   234,   121,   136, SPR_OSK_LEFT,      STR_NULL},
 
252
{ WWT_PUSHIMGBTN, RESIZE_NONE,  COLOUR_GREY,   237,   252,   121,   136, SPR_OSK_RIGHT,     STR_NULL},
 
253
 
 
254
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,     3,    18,    49,    64, 0x0,    STR_NULL},
 
255
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    21,    36,    49,    64, 0x0,    STR_NULL},
 
256
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    39,    54,    49,    64, 0x0,    STR_NULL},
 
257
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    57,    72,    49,    64, 0x0,    STR_NULL},
 
258
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    75,    90,    49,    64, 0x0,    STR_NULL},
 
259
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    93,   108,    49,    64, 0x0,    STR_NULL},
 
260
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   111,   126,    49,    64, 0x0,    STR_NULL},
 
261
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   129,   144,    49,    64, 0x0,    STR_NULL},
 
262
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   147,   162,    49,    64, 0x0,    STR_NULL},
 
263
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   165,   180,    49,    64, 0x0,    STR_NULL},
 
264
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   183,   198,    49,    64, 0x0,    STR_NULL},
 
265
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   201,   216,    49,    64, 0x0,    STR_NULL},
 
266
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   219,   234,    49,    64, 0x0,    STR_NULL},
 
267
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   237,   252,    49,    64, 0x0,    STR_NULL},
 
268
 
 
269
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    30,    45,    67,    82, 0x0,    STR_NULL},
 
270
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    48,    63,    67,    82, 0x0,    STR_NULL},
 
271
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    66,    81,    67,    82, 0x0,    STR_NULL},
 
272
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    84,    99,    67,    82, 0x0,    STR_NULL},
 
273
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   102,   117,    67,    82, 0x0,    STR_NULL},
 
274
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   120,   135,    67,    82, 0x0,    STR_NULL},
 
275
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   138,   153,    67,    82, 0x0,    STR_NULL},
 
276
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   156,   171,    67,    82, 0x0,    STR_NULL},
 
277
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   174,   189,    67,    82, 0x0,    STR_NULL},
 
278
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   192,   207,    67,    82, 0x0,    STR_NULL},
 
279
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   210,   225,    67,    82, 0x0,    STR_NULL},
 
280
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   228,   243,    67,    82, 0x0,    STR_NULL},
 
281
 
 
282
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    39,    54,    85,   100, 0x0,    STR_NULL},
 
283
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    57,    72,    85,   100, 0x0,    STR_NULL},
 
284
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    75,    90,    85,   100, 0x0,    STR_NULL},
 
285
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    93,   108,    85,   100, 0x0,    STR_NULL},
 
286
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   111,   126,    85,   100, 0x0,    STR_NULL},
 
287
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   129,   144,    85,   100, 0x0,    STR_NULL},
 
288
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   147,   162,    85,   100, 0x0,    STR_NULL},
 
289
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   165,   180,    85,   100, 0x0,    STR_NULL},
 
290
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   183,   198,    85,   100, 0x0,    STR_NULL},
 
291
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   201,   216,    85,   100, 0x0,    STR_NULL},
 
292
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   219,   234,    85,   100, 0x0,    STR_NULL},
 
293
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   237,   252,    85,   100, 0x0,    STR_NULL},
 
294
 
 
295
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    30,    45,   103,   118, 0x0,    STR_NULL},
 
296
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    48,    63,   103,   118, 0x0,    STR_NULL},
 
297
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    66,    81,   103,   118, 0x0,    STR_NULL},
 
298
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,    84,    99,   103,   118, 0x0,    STR_NULL},
 
299
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   102,   117,   103,   118, 0x0,    STR_NULL},
 
300
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   120,   135,   103,   118, 0x0,    STR_NULL},
 
301
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   138,   153,   103,   118, 0x0,    STR_NULL},
 
302
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   156,   171,   103,   118, 0x0,    STR_NULL},
 
303
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   174,   189,   103,   118, 0x0,    STR_NULL},
 
304
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   192,   207,   103,   118, 0x0,    STR_NULL},
 
305
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   210,   225,   103,   118, 0x0,    STR_NULL},
 
306
{    WWT_PUSHBTN, RESIZE_NONE,  COLOUR_GREY,   228,   243,   103,   118, 0x0,    STR_NULL},
 
307
 
 
308
{   WIDGETS_END},
 
309
};
 
310
 
 
311
static const WindowDesc _osk_desc(
 
312
        WDP_CENTER, WDP_CENTER, 256, 140, 256, 140,
 
313
        WC_OSK, WC_NONE,
 
314
        WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
 
315
        _osk_widgets
 
316
);
 
317
 
 
318
/**
 
319
 * Retrieve keyboard layout from language string or (if set) config file.
 
320
 * Also check for invalid characters.
 
321
 */
 
322
void GetKeyboardLayout()
 
323
{
 
324
        char keyboard[2][OSK_KEYBOARD_ENTRIES * 4 + 1];
 
325
        char errormark[2][OSK_KEYBOARD_ENTRIES + 1]; // used for marking invalid chars
 
326
        bool has_error = false; // true when an invalid char is detected
 
327
 
 
328
        if (StrEmpty(_keyboard_opt[0])) {
 
329
                GetString(keyboard[0], STR_OSK_KEYBOARD_LAYOUT, lastof(keyboard[0]));
 
330
        } else {
 
331
                strecpy(keyboard[0], _keyboard_opt[0], lastof(keyboard[0]));
 
332
        }
 
333
 
 
334
        if (StrEmpty(_keyboard_opt[1])) {
 
335
                GetString(keyboard[1], STR_OSK_KEYBOARD_LAYOUT_CAPS, lastof(keyboard[1]));
 
336
        } else {
 
337
                strecpy(keyboard[1], _keyboard_opt[1], lastof(keyboard[1]));
 
338
        }
 
339
 
 
340
        for (uint j = 0; j < 2; j++) {
 
341
                const char *kbd = keyboard[j];
 
342
                bool ended = false;
 
343
                for (uint i = 0; i < OSK_KEYBOARD_ENTRIES; i++) {
 
344
                        _keyboard[j][i] = Utf8Consume(&kbd);
 
345
 
 
346
                        /* Be lenient when the last characters are missing (is quite normal) */
 
347
                        if (_keyboard[j][i] == '\0' || ended) {
 
348
                                ended = true;
 
349
                                _keyboard[j][i] = ' ';
 
350
                                continue;
 
351
                        }
 
352
 
 
353
                        if (IsPrintable(_keyboard[j][i])) {
 
354
                                errormark[j][i] = ' ';
 
355
                        } else {
 
356
                                has_error = true;
 
357
                                errormark[j][i] = '^';
 
358
                                _keyboard[j][i] = ' ';
 
359
                        }
 
360
                }
 
361
        }
 
362
 
 
363
        if (has_error) {
 
364
                ShowInfoF("The keyboard layout you selected contains invalid chars. Please check those chars marked with ^.");
 
365
                ShowInfoF("Normal keyboard:  %s", keyboard[0]);
 
366
                ShowInfoF("                  %s", errormark[0]);
 
367
                ShowInfoF("Caps Lock:        %s", keyboard[1]);
 
368
                ShowInfoF("                  %s", errormark[1]);
 
369
        }
 
370
}
 
371
 
 
372
/**
 
373
 * Show the on-screen keyboard (osk) associated with a given textbox
 
374
 * @param parent pointer to the Window where this keyboard originated from
 
375
 * @param q      querystr_d pointer to the query string of the parent, which is
 
376
 *               shared for both windows
 
377
 * @param button widget number of parent's textbox
 
378
 * @param cancel widget number of parent's cancel button (0 if cancel events
 
379
 *               should not be passed)
 
380
 * @param ok     widget number of parent's ok button  (0 if ok events should not
 
381
 *               be passed)
 
382
 */
 
383
void ShowOnScreenKeyboard(QueryStringBaseWindow *parent, int button, int cancel, int ok)
 
384
{
 
385
        DeleteWindowById(WC_OSK, 0);
 
386
 
 
387
        GetKeyboardLayout();
 
388
        new OskWindow(&_osk_desc, parent, button, cancel, ok);
 
389
}