Extend key code handling
This commit is contained in:
parent
583b19c6e4
commit
ec57f2d806
204
src/sdtui.c
204
src/sdtui.c
@ -41,27 +41,39 @@
|
|||||||
#include "stardict.h"
|
#include "stardict.h"
|
||||||
|
|
||||||
|
|
||||||
#define KEY_SOH 1 /**< Ctrl-A */
|
#define KEY_SOH 1 //!< Ctrl-A
|
||||||
#define KEY_ENQ 5 /**< Ctrl-E */
|
#define KEY_STX 2 //!< Ctrl-B
|
||||||
#define KEY_VT 11 /**< Ctrl-K */
|
#define KEY_ENQ 5 //!< Ctrl-E
|
||||||
#define KEY_FF 12 /**< Ctrl-L */
|
#define KEY_ACK 6 //!< Ctrl-F
|
||||||
#define KEY_NAK 21 /**< Ctrl-U */
|
#define KEY_VT 11 //!< Ctrl-K
|
||||||
#define KEY_ETB 23 /**< Ctrl-W */
|
#define KEY_FF 12 //!< Ctrl-L
|
||||||
|
#define KEY_SO 14 //!< Ctrl-N
|
||||||
|
#define KEY_DLE 16 //!< Ctrl-P
|
||||||
|
#define KEY_NAK 21 //!< Ctrl-U
|
||||||
|
#define KEY_ETB 23 //!< Ctrl-W
|
||||||
|
|
||||||
#define KEY_RETURN 13 /**< Enter */
|
#define KEY_RETURN 13 //!< Enter
|
||||||
#define KEY_ESCAPE 27 /**< Esc */
|
#define KEY_ESCAPE 27 //!< Esc
|
||||||
|
|
||||||
// These codes may or may not work, depending on the terminal
|
typedef enum {
|
||||||
// They lie above KEY_MAX, originally discovered on gnome-terminal
|
TERMINAL_UNKNOWN, //!< No extra handling
|
||||||
#define KEY_CTRL_UP 565
|
TERMINAL_XTERM, //!< xterm and VTE extra keycodes
|
||||||
#define KEY_CTRL_DOWN 524
|
TERMINAL_RXVT //!< rxvt extra keycodes
|
||||||
#define KEY_CTRL_LEFT 544
|
} TerminalType; //!< Type of the terminal
|
||||||
#define KEY_CTRL_RIGHT 559
|
|
||||||
|
|
||||||
#define KEY_ALT_UP 563
|
typedef enum {
|
||||||
#define KEY_ALT_DOWN 522
|
KEY_NOT_RECOGNISED, //!< Not recognised
|
||||||
#define KEY_ALT_LEFT 542
|
|
||||||
#define KEY_ALT_RIGHT 557
|
KEY_CTRL_UP, //!< Ctrl + Up arrow
|
||||||
|
KEY_CTRL_DOWN, //!< Ctrl + Down arrow
|
||||||
|
KEY_CTRL_LEFT, //!< Ctrl + Left arrow
|
||||||
|
KEY_CTRL_RIGHT, //!< Ctrl + Right arrow
|
||||||
|
|
||||||
|
KEY_ALT_UP, //!< Alt + Up arrow
|
||||||
|
KEY_ALT_DOWN, //!< Alt + Down arrow
|
||||||
|
KEY_ALT_LEFT, //!< Alt + Left arrow
|
||||||
|
KEY_ALT_RIGHT //!< Alt + Right arrow
|
||||||
|
} ExtraKeyCode; //!< Translated key codes above KEY_MAX
|
||||||
|
|
||||||
#define _(x) x /**< Fake gettext, for now. */
|
#define _(x) x /**< Fake gettext, for now. */
|
||||||
|
|
||||||
@ -87,6 +99,58 @@ struct curses_event
|
|||||||
MEVENT mouse;
|
MEVENT mouse;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Translate key codes above KEY_MAX returned from ncurses into something
|
||||||
|
* meaningful, based on the terminal type. The values have been obtained
|
||||||
|
* experimentally. Some keycodes make ncurses return KEY_ESCAPE, even
|
||||||
|
* depending on actual terminal settings, thus this is not reliable at all.
|
||||||
|
* xterm/VTE seems to behave nicely, though.
|
||||||
|
*/
|
||||||
|
static guint
|
||||||
|
translate_extra_keycode (wchar_t code, TerminalType terminal)
|
||||||
|
{
|
||||||
|
switch (terminal)
|
||||||
|
{
|
||||||
|
case TERMINAL_XTERM:
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case 565: return KEY_CTRL_UP;
|
||||||
|
case 524: return KEY_CTRL_DOWN;
|
||||||
|
case 544: return KEY_CTRL_LEFT;
|
||||||
|
case 559: return KEY_CTRL_RIGHT;
|
||||||
|
|
||||||
|
case 563: return KEY_ALT_UP;
|
||||||
|
case 522: return KEY_ALT_DOWN;
|
||||||
|
case 542: return KEY_ALT_LEFT;
|
||||||
|
case 557: return KEY_ALT_RIGHT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TERMINAL_RXVT:
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case 521: return KEY_CTRL_UP;
|
||||||
|
case 514: return KEY_CTRL_DOWN;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TERMINAL_UNKNOWN:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return KEY_NOT_RECOGNISED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the type of the terminal based on the TERM environment variable. */
|
||||||
|
static TerminalType
|
||||||
|
get_terminal_type (void)
|
||||||
|
{
|
||||||
|
const gchar *term = g_getenv ("TERM");
|
||||||
|
if (!term) return TERMINAL_UNKNOWN;
|
||||||
|
|
||||||
|
gchar term_copy[strcspn (term, "-") + 1];
|
||||||
|
g_strlcpy (term_copy, term, sizeof term_copy);
|
||||||
|
if (!strcmp (term_copy, "xterm")) return TERMINAL_XTERM;
|
||||||
|
if (!strcmp (term_copy, "rxvt")) return TERMINAL_RXVT;
|
||||||
|
return TERMINAL_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
// --- Application -------------------------------------------------------------
|
// --- Application -------------------------------------------------------------
|
||||||
|
|
||||||
/** Data relating to one entry within the dictionary. */
|
/** Data relating to one entry within the dictionary. */
|
||||||
@ -103,22 +167,23 @@ struct view_entry
|
|||||||
|
|
||||||
struct application
|
struct application
|
||||||
{
|
{
|
||||||
GIConv utf8_to_wchar; //!< utf-8 -> wchar_t conversion
|
TerminalType terminal_type; //!< Type of the terminal
|
||||||
GIConv wchar_to_utf8; //!< wchar_t -> utf-8 conversion
|
GIConv utf8_to_wchar; //!< utf-8 -> wchar_t conversion
|
||||||
|
GIConv wchar_to_utf8; //!< wchar_t -> utf-8 conversion
|
||||||
|
|
||||||
StardictDict *dict; //!< The current dictionary
|
StardictDict * dict; //!< The current dictionary
|
||||||
|
|
||||||
guint32 top_position; //!< Index of the topmost dict. entry
|
guint32 top_position; //!< Index of the topmost dict. entry
|
||||||
guint top_offset; //!< Offset into the top entry
|
guint top_offset; //!< Offset into the top entry
|
||||||
guint selected; //!< Offset to the selected definition
|
guint selected; //!< Offset to the selected definition
|
||||||
GPtrArray *entries; //!< ViewEntry's within the view
|
GPtrArray * entries; //!< ViewEntry's within the view
|
||||||
|
|
||||||
gchar *search_label; //!< Text of the "Search" label
|
gchar * search_label; //!< Text of the "Search" label
|
||||||
GArray *input; //!< The current search input
|
GArray * input; //!< The current search input
|
||||||
guint input_pos; //!< Cursor position within input
|
guint input_pos; //!< Cursor position within input
|
||||||
gboolean input_confirmed; //!< Input has been confirmed
|
gboolean input_confirmed; //!< Input has been confirmed
|
||||||
|
|
||||||
gfloat division; //!< Position of the division column
|
gfloat division; //!< Position of the division column
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -232,6 +297,8 @@ app_init (Application *self, const gchar *filename)
|
|||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->terminal_type = get_terminal_type ();
|
||||||
|
|
||||||
self->top_position = 0;
|
self->top_position = 0;
|
||||||
self->top_offset = 0;
|
self->top_offset = 0;
|
||||||
self->selected = 0;
|
self->selected = 0;
|
||||||
@ -584,17 +651,49 @@ app_search_for_entry (Application *self)
|
|||||||
app_redraw_view (self);
|
app_redraw_view (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SAVE_CURSOR \
|
||||||
|
int last_x, last_y; \
|
||||||
|
getyx (stdscr, last_y, last_x);
|
||||||
|
|
||||||
|
#define RESTORE_CURSOR \
|
||||||
|
move (last_y, last_x); \
|
||||||
|
refresh ();
|
||||||
|
|
||||||
|
/** Process input above KEY_MAX. */
|
||||||
|
static gboolean
|
||||||
|
app_process_extra_code (Application *self, CursesEvent *event)
|
||||||
|
{
|
||||||
|
SAVE_CURSOR
|
||||||
|
switch (translate_extra_keycode (event->code, self->terminal_type))
|
||||||
|
{
|
||||||
|
case KEY_CTRL_UP:
|
||||||
|
app_one_entry_up (self);
|
||||||
|
RESTORE_CURSOR
|
||||||
|
break;
|
||||||
|
case KEY_CTRL_DOWN:
|
||||||
|
app_one_entry_down (self);
|
||||||
|
RESTORE_CURSOR
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_ALT_LEFT:
|
||||||
|
self->division = (app_get_left_column_width (self) - 1.) / COLS;
|
||||||
|
app_redraw_view (self);
|
||||||
|
RESTORE_CURSOR
|
||||||
|
break;
|
||||||
|
case KEY_ALT_RIGHT:
|
||||||
|
self->division = (app_get_left_column_width (self) + 1.) / COLS;
|
||||||
|
app_redraw_view (self);
|
||||||
|
RESTORE_CURSOR
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/** Process input that's not a character. */
|
/** Process input that's not a character. */
|
||||||
static gboolean
|
static gboolean
|
||||||
app_process_nonchar_code (Application *self, CursesEvent *event)
|
app_process_nonchar_code (Application *self, CursesEvent *event)
|
||||||
{
|
{
|
||||||
int last_x, last_y;
|
SAVE_CURSOR
|
||||||
getyx (stdscr, last_y, last_x);
|
|
||||||
|
|
||||||
#define RESTORE_CURSOR \
|
|
||||||
move (last_y, last_x); \
|
|
||||||
refresh ();
|
|
||||||
|
|
||||||
switch (event->code)
|
switch (event->code)
|
||||||
{
|
{
|
||||||
case KEY_RESIZE:
|
case KEY_RESIZE:
|
||||||
@ -627,26 +726,6 @@ app_process_nonchar_code (Application *self, CursesEvent *event)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEY_CTRL_UP:
|
|
||||||
app_one_entry_up (self);
|
|
||||||
RESTORE_CURSOR
|
|
||||||
break;
|
|
||||||
case KEY_CTRL_DOWN:
|
|
||||||
app_one_entry_down (self);
|
|
||||||
RESTORE_CURSOR
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KEY_ALT_LEFT:
|
|
||||||
self->division = (app_get_left_column_width (self) - 1.) / COLS;
|
|
||||||
app_redraw_view (self);
|
|
||||||
RESTORE_CURSOR
|
|
||||||
break;
|
|
||||||
case KEY_ALT_RIGHT:
|
|
||||||
self->division = (app_get_left_column_width (self) + 1.) / COLS;
|
|
||||||
app_redraw_view (self);
|
|
||||||
RESTORE_CURSOR
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
if (self->selected > 0)
|
if (self->selected > 0)
|
||||||
{
|
{
|
||||||
@ -717,6 +796,9 @@ app_process_nonchar_code (Application *self, CursesEvent *event)
|
|||||||
app_redraw_top (self);
|
app_redraw_top (self);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return app_process_extra_code (self, event);
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -741,6 +823,14 @@ app_process_curses_event (Application *self, CursesEvent *event)
|
|||||||
clear ();
|
clear ();
|
||||||
app_redraw (self);
|
app_redraw (self);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case KEY_STX: // Ctrl-B -- back
|
||||||
|
case KEY_ACK: // Ctrl-F -- forward
|
||||||
|
case KEY_DLE: // Ctrl-P -- previous
|
||||||
|
case KEY_SO: // Ctrl-N -- next
|
||||||
|
// TODO map this to something useful
|
||||||
|
break;
|
||||||
|
|
||||||
case KEY_SOH: // Ctrl-A -- move to the start of line
|
case KEY_SOH: // Ctrl-A -- move to the start of line
|
||||||
self->input_pos = 0;
|
self->input_pos = 0;
|
||||||
app_redraw_top (self);
|
app_redraw_top (self);
|
||||||
|
Loading…
Reference in New Issue
Block a user