4 Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
6 The Free Software Foundation, Inc.
10 Andrew Borodin <aborodin@vmail.ru>, 2012
12 This file is part of the Midnight Commander.
14 The Midnight Commander is free software: you can redistribute it
15 and/or modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation, either version 3 of the License,
17 or (at your option) any later version.
19 The Midnight Commander is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 * \brief Source: learn keys module
36 #include "lib/global.h"
38 #include "lib/tty/tty.h"
39 #include "lib/tty/key.h"
40 #include "lib/mcconfig.h"
41 #include "lib/strescape.h"
42 #include "lib/strutil.h"
43 #include "lib/util.h" /* convert_controls() */
44 #include "lib/widget.h"
49 /*** global variables ****************************************************************************/
51 /*** file scope macro definitions ****************************************************************/
61 /*** file scope type declarations ****************************************************************/
71 /*** file scope variables ************************************************************************/
73 static Dlg_head
*learn_dlg
;
74 static const char *learn_title
= N_("Learn keys");
76 static learnkey_t
*learnkeys
= NULL
;
77 static int learn_total
;
79 static gboolean learnchanged
= FALSE
;
81 /*** file scope functions ************************************************************************/
82 /* --------------------------------------------------------------------------------------------- */
85 learn_button (WButton
* button
, int action
)
92 d
= create_message (D_ERROR
, _("Teach me a key"),
93 _("Please press the %s\n"
94 "and then wait until this message disappears.\n\n"
95 "Then, press it again to see if OK appears\n"
96 "next to its button.\n\n"
97 "If you want to escape, press a single Escape key\n"
98 "and wait as well."), _(key_name_conv_tab
[action
- B_USER
].longname
));
100 if (learnkeys
[action
- B_USER
].sequence
!= NULL
)
102 g_free (learnkeys
[action
- B_USER
].sequence
);
103 learnkeys
[action
- B_USER
].sequence
= NULL
;
109 /* Esc hides the dialog and do not allow definitions of
112 gboolean seq_ok
= FALSE
;
114 if (*seq
!= '\0' && strcmp (seq
, "\\e") != 0 && strcmp (seq
, "\\e\\e") != 0
115 && strcmp (seq
, "^m") != 0 && strcmp (seq
, "^i") != 0
116 && (seq
[1] != '\0' || *seq
< ' ' || *seq
> '~'))
119 learnkeys
[action
- B_USER
].sequence
= seq
;
120 seq
= convert_controls (seq
);
121 seq_ok
= define_sequence (key_name_conv_tab
[action
- B_USER
].code
, seq
, MCKEY_NOACTION
);
125 message (D_NORMAL
, _("Cannot accept this key"), _("You have entered \"%s\""), seq
);
133 dlg_select_widget (learnkeys
[action
- B_USER
].button
);
135 return 0; /* Do not kill learn_dlg */
138 /* --------------------------------------------------------------------------------------------- */
141 learn_move (gboolean right
)
145 totalcols
= (learn_total
- 1) / ROWS
+ 1;
146 for (i
= 0; i
< learn_total
; i
++)
147 if (learnkeys
[i
].button
== WIDGET (learn_dlg
->current
->data
))
151 if (i
< learn_total
- ROWS
)
160 else if (i
+ (totalcols
- 1) * ROWS
>= learn_total
)
161 i
+= (totalcols
- 2) * ROWS
;
163 i
+= (totalcols
- 1) * ROWS
;
165 dlg_select_widget (learnkeys
[i
].button
);
172 /* --------------------------------------------------------------------------------------------- */
175 learn_check_key (int c
)
179 for (i
= 0; i
< learn_total
; i
++)
181 if (key_name_conv_tab
[i
].code
!= c
|| learnkeys
[i
].ok
)
184 dlg_select_widget (learnkeys
[i
].button
);
185 /* TRANSLATORS: This label appears near learned keys. Keep it short. */
186 label_set_text ((WLabel
*) learnkeys
[i
].label
, _("OK"));
187 learnkeys
[i
].ok
= TRUE
;
189 if (learnok
>= learn_total
)
191 learn_dlg
->ret_value
= B_CANCEL
;
194 if (query_dialog (learn_title
,
196 ("It seems that all your keys already\n"
197 "work fine. That's great."), D_ERROR
, 2,
198 _("&Save"), _("&Discard")) == 0)
199 learn_dlg
->ret_value
= B_ENTER
;
203 message (D_ERROR
, learn_title
,
205 ("Great! You have a complete terminal database!\n"
206 "All your keys work well."));
208 dlg_stop (learn_dlg
);
217 return learn_move (FALSE
);
220 return learn_move (TRUE
);
222 dlg_one_down (learn_dlg
);
225 dlg_one_up (learn_dlg
);
229 /* Prevent from disappearing if a non-defined sequence is pressed
230 and contains a button hotkey. Only recognize hotkeys with ALT. */
231 return (c
< 255 && g_ascii_isalnum (c
));
234 /* --------------------------------------------------------------------------------------------- */
237 learn_callback (Dlg_head
* h
, Widget
* sender
, dlg_msg_t msg
, int parm
, void *data
)
242 return learn_check_key (parm
) ? MSG_HANDLED
: MSG_NOT_HANDLED
;
245 return default_dlg_callback (h
, sender
, msg
, parm
, data
);
249 /* --------------------------------------------------------------------------------------------- */
254 const int dlg_width
= 78;
255 const int dlg_height
= 23;
259 int ret_cmd
, flags
, y
, x
;
261 } learn_but
[BUTTONS
] =
264 {B_CANCEL
, NORMAL_BUTTON
, 0, 39, N_("&Cancel")},
265 {B_ENTER
, DEFPUSH_BUTTON
, 0, 25, N_("&Save")}
270 const key_code_name_t
*key
;
271 char buffer
[BUF_TINY
];
274 static gboolean i18n_flag
= FALSE
;
277 learn_title
= _(learn_title
);
281 learn_but
[0].text
= _(learn_but
[0].text
);
282 learn_but
[0].x
= dlg_width
/ 2 + 4;
284 learn_but
[1].text
= _(learn_but
[1].text
);
285 learn_but
[1].x
= dlg_width
/ 2 - (str_term_width1 (learn_but
[1].text
) + 9);
286 #endif /* ENABLE_NLS */
291 create_dlg (TRUE
, 0, 0, dlg_height
, dlg_width
, dialog_colors
, learn_callback
, NULL
,
292 "[Learn keys]", learn_title
, DLG_CENTER
| DLG_REVERSE
);
294 for (i
= 0; i
< BUTTONS
; i
++)
295 add_widget (learn_dlg
,
296 button_new (dlg_height
- 3 + learn_but
[i
].y
, learn_but
[i
].x
,
297 learn_but
[i
].ret_cmd
, learn_but
[i
].flags
, _(learn_but
[i
].text
), 0));
301 for (key
= key_name_conv_tab
, j
= 0;
302 key
->name
!= NULL
&& strcmp (key
->name
, "kpleft") != 0; key
++, j
++)
304 learnkeys
= g_new (learnkey_t
, j
);
305 x
+= ((j
- 1) / ROWS
) * COLSHIFT
;
309 learnchanged
= FALSE
;
310 for (i
= j
- 1, key
= key_name_conv_tab
+ j
- 1; i
>= 0; i
--, key
--)
312 learnkeys
[i
].ok
= FALSE
;
313 learnkeys
[i
].sequence
= NULL
;
314 g_snprintf (buffer
, sizeof (buffer
), "%-16s", _(key
->longname
));
315 learnkeys
[i
].button
=
316 WIDGET (button_new (y
, x
, B_USER
+ i
, NARROW_BUTTON
, buffer
, learn_button
));
317 add_widget (learn_dlg
, learnkeys
[i
].button
);
318 learnkeys
[i
].label
= WIDGET (label_new (y
, x
+ 19, ""));
319 add_widget (learn_dlg
, learnkeys
[i
].label
);
329 add_widget (learn_dlg
,
330 label_new (UY
+ 14, 5,
331 _("Press all the keys mentioned here. After you have done it, check\n"
332 "which keys are not marked with OK. Press space on the missing\n"
333 "key, or click with the mouse to define it. Move around with Tab.")));
336 /* --------------------------------------------------------------------------------------------- */
341 destroy_dlg (learn_dlg
);
345 /* --------------------------------------------------------------------------------------------- */
352 gboolean profile_changed
= FALSE
;
354 section
= g_strconcat ("terminal:", getenv ("TERM"), (char *) NULL
);
356 for (i
= 0; i
< learn_total
; i
++)
357 if (learnkeys
[i
].sequence
!= NULL
)
361 esc_str
= strutils_escape (learnkeys
[i
].sequence
, -1, ";\\", TRUE
);
362 mc_config_set_string_raw_value (mc_main_config
, section
, key_name_conv_tab
[i
].name
,
366 profile_changed
= TRUE
;
369 /* On the one hand no good idea to save the complete setup but
370 * without 'Auto save setup' the new key-definitions will not be
371 * saved unless the user does an 'Options/Save Setup'.
372 * On the other hand a save-button that does not save anything to
373 * disk is much worse.
376 mc_config_save_file (mc_main_config
, NULL
);
381 /* --------------------------------------------------------------------------------------------- */
382 /*** public functions ****************************************************************************/
383 /* --------------------------------------------------------------------------------------------- */
388 int save_old_esc_mode
= old_esc_mode
;
389 gboolean save_alternate_plus_minus
= mc_global
.tty
.alternate_plus_minus
;
392 /* old_esc_mode cannot work in learn keys dialog */
395 /* don't translate KP_ADD, KP_SUBTRACT and
396 KP_MULTIPLY to '+', '-' and '*' in
398 mc_global
.tty
.alternate_plus_minus
= TRUE
;
399 application_keypad_mode ();
402 result
= run_dlg (learn_dlg
);
404 old_esc_mode
= save_old_esc_mode
;
405 mc_global
.tty
.alternate_plus_minus
= save_alternate_plus_minus
;
407 if (!mc_global
.tty
.alternate_plus_minus
)
408 numeric_keypad_mode ();
410 if (result
== B_ENTER
)
416 /* --------------------------------------------------------------------------------------------- */