diff options
| -rw-r--r-- | src/sdtui.c | 204 | 
1 files changed, 147 insertions, 57 deletions
| diff --git a/src/sdtui.c b/src/sdtui.c index e2a5739..f576276 100644 --- a/src/sdtui.c +++ b/src/sdtui.c @@ -41,27 +41,39 @@  #include "stardict.h" -#define KEY_SOH      1                 /**< Ctrl-A */ -#define KEY_ENQ      5                 /**< Ctrl-E */ -#define KEY_VT      11                 /**< Ctrl-K */ -#define KEY_FF      12                 /**< Ctrl-L */ -#define KEY_NAK     21                 /**< Ctrl-U */ -#define KEY_ETB     23                 /**< Ctrl-W */ +#define KEY_SOH      1                 //!< Ctrl-A +#define KEY_STX      2                 //!< Ctrl-B +#define KEY_ENQ      5                 //!< Ctrl-E +#define KEY_ACK      6                 //!< Ctrl-F +#define KEY_VT      11                 //!< Ctrl-K +#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_ESCAPE  27                 /**< Esc    */ +#define KEY_RETURN  13                 //!< Enter +#define KEY_ESCAPE  27                 //!< Esc -// These codes may or may not work, depending on the terminal -// They lie above KEY_MAX, originally discovered on gnome-terminal -#define KEY_CTRL_UP     565 -#define KEY_CTRL_DOWN   524 -#define KEY_CTRL_LEFT   544 -#define KEY_CTRL_RIGHT  559 +typedef enum { +	TERMINAL_UNKNOWN,                  //!< No extra handling +	TERMINAL_XTERM,                    //!< xterm and VTE extra keycodes +	TERMINAL_RXVT                      //!< rxvt extra keycodes +} TerminalType;                        //!< Type of the terminal -#define KEY_ALT_UP      563 -#define KEY_ALT_DOWN    522 -#define KEY_ALT_LEFT    542 -#define KEY_ALT_RIGHT   557 +typedef enum { +	KEY_NOT_RECOGNISED,                //!< Not recognised + +	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. */ @@ -87,6 +99,58 @@ struct curses_event  	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 -------------------------------------------------------------  /** Data relating to one entry within the dictionary. */ @@ -103,22 +167,23 @@ struct view_entry  struct application  { -	GIConv utf8_to_wchar;               //!< utf-8 -> wchar_t conversion -	GIConv wchar_to_utf8;               //!< wchar_t -> utf-8 conversion +	TerminalType    terminal_type;      //!< Type of the terminal +	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 -	guint top_offset;                   //!< Offset into the top entry -	guint selected;                     //!< Offset to the selected definition -	GPtrArray *entries;                 //!< ViewEntry's within the view +	guint32         top_position;       //!< Index of the topmost dict. entry +	guint           top_offset;         //!< Offset into the top entry +	guint           selected;           //!< Offset to the selected definition +	GPtrArray     * entries;            //!< ViewEntry's within the view -	gchar *search_label;                //!< Text of the "Search" label -	GArray *input;                      //!< The current search input -	guint input_pos;                    //!< Cursor position within input -	gboolean input_confirmed;           //!< Input has been confirmed +	gchar         * search_label;       //!< Text of the "Search" label +	GArray        * input;              //!< The current search input +	guint           input_pos;          //!< Cursor position within input +	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);  	} +	self->terminal_type = get_terminal_type (); +  	self->top_position = 0;  	self->top_offset = 0;  	self->selected = 0; @@ -584,17 +651,49 @@ app_search_for_entry (Application *self)  	app_redraw_view (self);  } -/** Process input that's not a character. */ +#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_nonchar_code (Application *self, CursesEvent *event) +app_process_extra_code (Application *self, CursesEvent *event)  { -	int last_x, last_y; -	getyx (stdscr, last_y, last_x); +	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; -	#define RESTORE_CURSOR      \ -		move (last_y, last_x);  \ -		refresh (); +	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. */ +static gboolean +app_process_nonchar_code (Application *self, CursesEvent *event) +{ +	SAVE_CURSOR  	switch (event->code)  	{  	case KEY_RESIZE: @@ -627,26 +726,6 @@ app_process_nonchar_code (Application *self, CursesEvent *event)  		}  		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:  		if (self->selected > 0)  		{ @@ -717,6 +796,9 @@ app_process_nonchar_code (Application *self, CursesEvent *event)  			app_redraw_top (self);  		}  		break; + +	default: +		return app_process_extra_code (self, event);  	}  	return TRUE;  } @@ -741,6 +823,14 @@ app_process_curses_event (Application *self, CursesEvent *event)  		clear ();  		app_redraw (self);  		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  		self->input_pos = 0;  		app_redraw_top (self); | 
