alsamixer: Replaced hardcoded keys by binding arrays

This commit is a preparation for making keybindings configurable.

The hardcoded keys in the switch statements of mixer_widget.c,
textbox.c, proc_files.c and card_select.c have been replaced by
command enums. The command that shall be executed is looked up in
the arrays `mixer_bindings` and `textbox_bindings`.

The channel_mask enum has been made public, since LEFT and RIGHT are
used as command arguments in bindings.c.

Signed-off-by: Benjamin Abendroth <braph93@gmx.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
braph 2019-09-26 22:27:25 +02:00 committed by Jaroslav Kysela
parent 706a64c7a0
commit 6e9e84ba60
8 changed files with 296 additions and 207 deletions

View file

@ -3,6 +3,7 @@ LDADD = @CURSESLIB@
bin_PROGRAMS = alsamixer
alsamixer_SOURCES = card_select.c card_select.h \
bindings.c bindings.h \
cli.c \
colors.c colors.h \
device_name.c device_name.h \

132
alsamixer/bindings.c Normal file
View file

@ -0,0 +1,132 @@
#include "bindings.h"
#include "mixer_widget.h"
#define CNTRL(C) (C%32)
uint8_t textbox_bindings[KEY_MAX] = {
['\n'] = CMD_TEXTBOX_CLOSE,
['\r'] = CMD_TEXTBOX_CLOSE,
[27] = CMD_TEXTBOX_CLOSE,
[KEY_CANCEL] = CMD_TEXTBOX_CLOSE,
[KEY_ENTER] = CMD_TEXTBOX_CLOSE,
[KEY_CLOSE] = CMD_TEXTBOX_CLOSE,
[KEY_EXIT] = CMD_TEXTBOX_CLOSE,
[KEY_DOWN] = CMD_TEXTBOX_DOWN,
[KEY_SF] = CMD_TEXTBOX_DOWN,
['J'] = CMD_TEXTBOX_DOWN,
['j'] = CMD_TEXTBOX_DOWN,
['X'] = CMD_TEXTBOX_DOWN,
['x'] = CMD_TEXTBOX_DOWN,
[KEY_UP] = CMD_TEXTBOX_UP,
[KEY_SR] = CMD_TEXTBOX_UP,
['K'] = CMD_TEXTBOX_UP,
['k'] = CMD_TEXTBOX_UP,
['W'] = CMD_TEXTBOX_UP,
['w'] = CMD_TEXTBOX_UP,
[KEY_LEFT] = CMD_TEXTBOX_LEFT,
['H'] = CMD_TEXTBOX_LEFT,
['h'] = CMD_TEXTBOX_LEFT,
['P'] = CMD_TEXTBOX_LEFT,
['p'] = CMD_TEXTBOX_LEFT,
[KEY_RIGHT] = CMD_TEXTBOX_RIGHT,
['L'] = CMD_TEXTBOX_RIGHT,
['l'] = CMD_TEXTBOX_RIGHT,
['N'] = CMD_TEXTBOX_RIGHT,
['n'] = CMD_TEXTBOX_RIGHT,
[KEY_NPAGE] = CMD_TEXTBOX_PAGE_DOWN,
[' '] = CMD_TEXTBOX_PAGE_DOWN,
[KEY_PPAGE] = CMD_TEXTBOX_PAGE_UP,
[KEY_BACKSPACE] = CMD_TEXTBOX_PAGE_UP,
['B'] = CMD_TEXTBOX_PAGE_UP,
['b'] = CMD_TEXTBOX_PAGE_UP,
[KEY_HOME] = CMD_TEXTBOX_TOP,
[KEY_BEG] = CMD_TEXTBOX_TOP,
[KEY_LL] = CMD_TEXTBOX_BOTTOM,
[KEY_END] = CMD_TEXTBOX_BOTTOM,
['\t'] = CMD_TEXTBOX_PAGE_RIGHT,
[KEY_BTAB] = CMD_TEXTBOX_PAGE_LEFT,
};
command_enum mixer_bindings[] = {
[27] = CMD_MIXER_CLOSE,
[KEY_CANCEL] = CMD_MIXER_CLOSE,
[KEY_F(10)] = CMD_MIXER_CLOSE,
[KEY_F(1)] = CMD_MIXER_HELP,
[KEY_HELP] = CMD_MIXER_HELP,
['H'] = CMD_MIXER_HELP,
['h'] = CMD_MIXER_HELP,
['?'] = CMD_MIXER_HELP,
[KEY_F(2)] = CMD_MIXER_SYSTEM_INFORMATION,
['/'] = CMD_MIXER_SYSTEM_INFORMATION,
[KEY_F(3)] = CMD_WITH_ARG(CMD_MIXER_SET_VIEW_MODE, VIEW_MODE_PLAYBACK),
[KEY_F(4)] = CMD_WITH_ARG(CMD_MIXER_SET_VIEW_MODE, VIEW_MODE_CAPTURE),
[KEY_F(5)] = CMD_WITH_ARG(CMD_MIXER_SET_VIEW_MODE, VIEW_MODE_ALL),
['\t'] = CMD_MIXER_TOGGLE_VIEW_MODE,
[KEY_F(6)] = CMD_MIXER_SELECT_CARD,
['S'] = CMD_MIXER_SELECT_CARD,
['s'] = CMD_MIXER_SELECT_CARD,
[KEY_REFRESH] = CMD_MIXER_REFRESH,
[CNTRL('L')] = CMD_MIXER_REFRESH,
['L'] = CMD_MIXER_REFRESH,
['l'] = CMD_MIXER_REFRESH,
[KEY_LEFT] = CMD_WITH_ARG(CMD_MIXER_PREVIOUS, 1),
['p'] = CMD_WITH_ARG(CMD_MIXER_PREVIOUS, 1),
['P'] = CMD_WITH_ARG(CMD_MIXER_PREVIOUS, 1),
[KEY_RIGHT] = CMD_WITH_ARG(CMD_MIXER_NEXT, 1),
['N'] = CMD_WITH_ARG(CMD_MIXER_NEXT, 1),
['n'] = CMD_WITH_ARG(CMD_MIXER_NEXT, 1),
[KEY_PPAGE] = CMD_WITH_ARG(CMD_MIXER_CONTROL_UP, 5),
[KEY_NPAGE] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN, 5),
[KEY_LL] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 0),
[KEY_END] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 0),
['0'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 0),
['1'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 10),
['2'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 20),
['3'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 30),
['4'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 40),
['5'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 50),
['6'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 60),
['7'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 70),
['8'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 80),
['9'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 90),
#if 0
[KEY_BEG] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 100),
[KEY_HELP] = CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT, 100),
#endif
[KEY_UP] = CMD_WITH_ARG(CMD_MIXER_CONTROL_UP, 1),
['+'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_UP, 1),
['K'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_UP, 1),
['k'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_UP, 1),
['W'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_UP, 1),
['w'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_UP, 1),
[KEY_DOWN] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN, 1),
['-'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN, 1),
['J'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN, 1),
['j'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN, 1),
['X'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN, 1),
['x'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN, 1),
['Q'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_UP_LEFT, 1),
['q'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_UP_LEFT, 1),
['Y'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN_LEFT, 1),
['y'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN_LEFT, 1),
['Z'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN_LEFT, 1),
['z'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN_LEFT, 1),
['E'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_UP_RIGHT, 1),
['e'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_UP_RIGHT, 1),
['C'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN_RIGHT, 1),
['c'] = CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN_RIGHT, 1),
['M'] = CMD_WITH_ARG(CMD_MIXER_TOGGLE_MUTE, LEFT|RIGHT),
['m'] = CMD_WITH_ARG(CMD_MIXER_TOGGLE_MUTE, LEFT|RIGHT),
['<'] = CMD_WITH_ARG(CMD_MIXER_TOGGLE_MUTE, LEFT),
[','] = CMD_WITH_ARG(CMD_MIXER_TOGGLE_MUTE, LEFT),
['>'] = CMD_WITH_ARG(CMD_MIXER_TOGGLE_MUTE, RIGHT),
['.'] = CMD_WITH_ARG(CMD_MIXER_TOGGLE_MUTE, RIGHT),
[' '] = CMD_WITH_ARG(CMD_MIXER_TOGGLE_CAPTURE, LEFT|RIGHT),
[KEY_IC] = CMD_WITH_ARG(CMD_MIXER_TOGGLE_CAPTURE, LEFT),
[';'] = CMD_WITH_ARG(CMD_MIXER_TOGGLE_CAPTURE, LEFT),
[KEY_DC] = CMD_WITH_ARG(CMD_MIXER_TOGGLE_CAPTURE, RIGHT),
['\''] = CMD_WITH_ARG(CMD_MIXER_TOGGLE_CAPTURE, RIGHT),
['B'] = CMD_MIXER_BALANCE_CONTROL,
['b'] = CMD_MIXER_BALANCE_CONTROL,
['='] = CMD_MIXER_BALANCE_CONTROL,
};

76
alsamixer/bindings.h Normal file
View file

@ -0,0 +1,76 @@
#ifndef BINDINGS_H_INCLUDED
#define BINDINGS_H_INCLUDED
#include CURSESINC
#include <menu.h>
#include <stdint.h>
/* Commands are stored in an uint16_t and may take an unsigned numeric argument.
* The command itself is stored in the lower 7 bits, the argument is stored
* in the higher 9 bits.
*
* The value `0` is used for no (unbound) command. */
typedef uint16_t command_enum;
extern command_enum mixer_bindings[KEY_MAX];
/* No need for a 16bit type, since textbox commands don't take arguments */
extern uint8_t textbox_bindings[KEY_MAX];
#define CMD_WITH_ARG(CMD, ARG) \
((CMD) + ((ARG) << 9))
#define CMD_GET_COMMAND(CMD) \
((CMD) & 0x1FF)
#define CMD_GET_ARGUMENT(CMD) \
((CMD) >> 9)
enum mixer_command {
// `CMD % 4` should produce the channel mask
CMD_MIXER_CONTROL_DOWN_LEFT = 1,
CMD_MIXER_CONTROL_DOWN_RIGHT,
CMD_MIXER_CONTROL_DOWN,
CMD_MIXER_CONTROL_UP_LEFT = 5,
CMD_MIXER_CONTROL_UP_RIGHT,
CMD_MIXER_CONTROL_UP,
CMD_MIXER_CONTROL_SET_PERCENT_LEFT = 9,
CMD_MIXER_CONTROL_SET_PERCENT_RIGHT,
CMD_MIXER_CONTROL_SET_PERCENT,
// Keep those in the same order as displayed on screen
CMD_MIXER_HELP,
CMD_MIXER_SYSTEM_INFORMATION,
CMD_MIXER_SELECT_CARD,
CMD_MIXER_CLOSE,
CMD_MIXER_TOGGLE_VIEW_MODE,
CMD_MIXER_SET_VIEW_MODE,
CMD_MIXER_PREVIOUS,
CMD_MIXER_NEXT,
CMD_MIXER_FOCUS_CONTROL,
CMD_MIXER_TOGGLE_MUTE,
CMD_MIXER_TOGGLE_CAPTURE,
CMD_MIXER_BALANCE_CONTROL,
CMD_MIXER_REFRESH
};
enum textbox_command {
/* Since these commands are also used by the menu widget we make use of
* the menu_driver() request constants.
* KEY_MAX is substracted so the value fits in 8 bits. */
CMD_TEXTBOX___MIN_MENU_COMMAND = MIN_MENU_COMMAND - KEY_MAX,
CMD_TEXTBOX_TOP = REQ_FIRST_ITEM - KEY_MAX,
CMD_TEXTBOX_BOTTOM = REQ_LAST_ITEM - KEY_MAX,
CMD_TEXTBOX_LEFT = REQ_LEFT_ITEM - KEY_MAX,
CMD_TEXTBOX_RIGHT = REQ_RIGHT_ITEM - KEY_MAX,
CMD_TEXTBOX_UP = REQ_UP_ITEM - KEY_MAX,
CMD_TEXTBOX_DOWN = REQ_DOWN_ITEM - KEY_MAX,
CMD_TEXTBOX_PAGE_DOWN = REQ_SCR_DPAGE - KEY_MAX,
CMD_TEXTBOX_PAGE_UP = REQ_SCR_UPAGE - KEY_MAX,
CMD_TEXTBOX___MAX_MENU_COMMAND = MAX_MENU_COMMAND - KEY_MAX,
CMD_TEXTBOX_PAGE_LEFT,
CMD_TEXTBOX_PAGE_RIGHT,
CMD_TEXTBOX_CLOSE,
};
#endif

View file

@ -31,6 +31,7 @@
#include "mixer_widget.h"
#include "device_name.h"
#include "card_select.h"
#include "bindings.h"
struct card {
struct card *next;
@ -61,25 +62,12 @@ static void on_key_enter(void)
static void on_menu_key(int key)
{
static const struct {
int key;
int request;
} key_map[] = {
{ KEY_DOWN, REQ_DOWN_ITEM },
{ KEY_UP, REQ_UP_ITEM },
{ KEY_HOME, REQ_FIRST_ITEM },
{ KEY_NPAGE, REQ_SCR_DPAGE },
{ KEY_PPAGE, REQ_SCR_UPAGE },
{ KEY_BEG, REQ_FIRST_ITEM },
{ KEY_END, REQ_LAST_ITEM },
};
unsigned int i;
for (i = 0; i < ARRAY_SIZE(key_map); ++i)
if (key_map[i].key == key) {
menu_driver(menu, key_map[i].request);
break;
}
if (key < ARRAY_SIZE(textbox_bindings)) {
key = textbox_bindings[key];
if (key >= CMD_TEXTBOX___MIN_MENU_COMMAND &&
key <= CMD_TEXTBOX___MAX_MENU_COMMAND)
menu_driver(menu, key + KEY_MAX);
}
}
static void on_handle_key(int key)

View file

@ -37,6 +37,7 @@
#include "mixer_controls.h"
#include "mixer_display.h"
#include "mixer_widget.h"
#include "bindings.h"
snd_mixer_t *mixer;
char *mixer_device_name;
@ -53,11 +54,6 @@ unsigned int current_control_flags;
bool control_values_changed;
bool controls_changed;
enum channel_mask {
LEFT = 1,
RIGHT = 2,
};
static int elem_callback(snd_mixer_elem_t *elem, unsigned int mask)
{
if (mask == SND_CTL_EVENT_MASK_REMOVE) {
@ -468,145 +464,74 @@ static void balance_volumes(void)
static void on_handle_key(int key)
{
switch (key) {
case 27:
case KEY_CANCEL:
case KEY_F(10):
int arg;
command_enum cmd;
if (key < ARRAY_SIZE(mixer_bindings))
cmd = mixer_bindings[key];
else
return;
arg = CMD_GET_ARGUMENT(cmd);
cmd = CMD_GET_COMMAND(cmd);
switch (cmd) {
case CMD_MIXER_CONTROL_DOWN_LEFT:
case CMD_MIXER_CONTROL_DOWN_RIGHT:
case CMD_MIXER_CONTROL_DOWN:
arg = (-arg);
case CMD_MIXER_CONTROL_UP_LEFT:
case CMD_MIXER_CONTROL_UP_RIGHT:
case CMD_MIXER_CONTROL_UP:
change_control_relative(arg, cmd % 4);
break;
case CMD_MIXER_CONTROL_SET_PERCENT_LEFT:
case CMD_MIXER_CONTROL_SET_PERCENT_RIGHT:
case CMD_MIXER_CONTROL_SET_PERCENT:
change_control_to_percent(arg, cmd % 4);
break;
case CMD_MIXER_CLOSE:
mixer_widget.close();
break;
case KEY_F(1):
case KEY_HELP:
case 'H':
case 'h':
case '?':
case CMD_MIXER_HELP:
show_help();
break;
case KEY_F(2):
case '/':
case CMD_MIXER_SYSTEM_INFORMATION:
create_proc_files_list();
break;
case KEY_F(3):
set_view_mode(VIEW_MODE_PLAYBACK);
case CMD_MIXER_TOGGLE_VIEW_MODE:
arg = (view_mode + 1) % VIEW_MODE_COUNT;
case CMD_MIXER_SET_VIEW_MODE:
set_view_mode((enum view_mode)(arg));
break;
case KEY_F(4):
set_view_mode(VIEW_MODE_CAPTURE);
break;
case KEY_F(5):
set_view_mode(VIEW_MODE_ALL);
break;
case '\t':
set_view_mode((enum view_mode)((view_mode + 1) % VIEW_MODE_COUNT));
break;
case KEY_F(6):
case 'S':
case 's':
case CMD_MIXER_SELECT_CARD:
create_card_select_list();
break;
case KEY_REFRESH:
case 12:
case 'L':
case 'l':
case CMD_MIXER_REFRESH:
clearok(mixer_widget.window, TRUE);
display_controls();
break;
case KEY_LEFT:
case 'P':
case 'p':
if (focus_control_index > 0) {
--focus_control_index;
refocus_control();
}
case CMD_MIXER_PREVIOUS:
arg = (-arg);
case CMD_MIXER_NEXT:
arg = focus_control_index + arg;
case CMD_MIXER_FOCUS_CONTROL:
focus_control_index = arg;
if (focus_control_index < 0)
focus_control_index = 0;
else if (focus_control_index >= controls_count)
focus_control_index = controls_count - 1;
refocus_control();
break;
case KEY_RIGHT:
case 'N':
case 'n':
if (focus_control_index < controls_count - 1) {
++focus_control_index;
refocus_control();
}
case CMD_MIXER_TOGGLE_MUTE:
toggle_mute(arg);
break;
case KEY_PPAGE:
change_control_relative(5, LEFT | RIGHT);
case CMD_MIXER_TOGGLE_CAPTURE:
toggle_capture(arg);
break;
case KEY_NPAGE:
change_control_relative(-5, LEFT | RIGHT);
break;
#if 0
case KEY_BEG:
case KEY_HOME:
change_control_to_percent(100, LEFT | RIGHT);
break;
#endif
case KEY_LL:
case KEY_END:
change_control_to_percent(0, LEFT | RIGHT);
break;
case KEY_UP:
case '+':
case 'K':
case 'k':
case 'W':
case 'w':
change_control_relative(1, LEFT | RIGHT);
break;
case KEY_DOWN:
case '-':
case 'J':
case 'j':
case 'X':
case 'x':
change_control_relative(-1, LEFT | RIGHT);
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
change_control_to_percent((key - '0') * 10, LEFT | RIGHT);
break;
case 'Q':
case 'q':
change_control_relative(1, LEFT);
break;
case 'Y':
case 'y':
case 'Z':
case 'z':
change_control_relative(-1, LEFT);
break;
case 'E':
case 'e':
change_control_relative(1, RIGHT);
break;
case 'C':
case 'c':
change_control_relative(-1, RIGHT);
break;
case 'M':
case 'm':
toggle_mute(LEFT | RIGHT);
break;
case 'B':
case 'b':
case '=':
case CMD_MIXER_BALANCE_CONTROL:
balance_volumes();
break;
case '<':
case ',':
toggle_mute(LEFT);
break;
case '>':
case '.':
toggle_mute(RIGHT);
break;
case ' ':
toggle_capture(LEFT | RIGHT);
break;
case KEY_IC:
case ';':
toggle_capture(LEFT);
break;
case KEY_DC:
case '\'':
toggle_capture(RIGHT);
break;
}
}

View file

@ -12,6 +12,11 @@ enum view_mode {
VIEW_MODE_COUNT,
};
enum channel_mask {
LEFT = 1,
RIGHT = 2,
};
extern snd_mixer_t *mixer;
extern char *mixer_device_name;
extern bool unplugged;

View file

@ -28,6 +28,7 @@
#include "widget.h"
#include "textbox.h"
#include "proc_files.h"
#include "bindings.h"
static struct widget proc_widget;
static ITEM *items[7];
@ -36,25 +37,12 @@ static MENU *menu;
static void on_menu_key(int key)
{
static const struct {
int key;
int request;
} key_map[] = {
{ KEY_DOWN, REQ_DOWN_ITEM },
{ KEY_UP, REQ_UP_ITEM },
{ KEY_HOME, REQ_FIRST_ITEM },
{ KEY_NPAGE, REQ_SCR_DPAGE },
{ KEY_PPAGE, REQ_SCR_UPAGE },
{ KEY_BEG, REQ_FIRST_ITEM },
{ KEY_END, REQ_LAST_ITEM },
};
unsigned int i;
for (i = 0; i < ARRAY_SIZE(key_map); ++i)
if (key_map[i].key == key) {
menu_driver(menu, key_map[i].request);
break;
}
if (key < ARRAY_SIZE(textbox_bindings)) {
key = textbox_bindings[key];
if (key >= CMD_TEXTBOX___MIN_MENU_COMMAND &&
key <= CMD_TEXTBOX___MAX_MENU_COMMAND)
menu_driver(menu, key + KEY_MAX);
}
}
static void on_handle_key(int key)

View file

@ -32,6 +32,7 @@
#include "colors.h"
#include "widget.h"
#include "textbox.h"
#include "bindings.h"
#define MAX_FILE_SIZE 1048576
@ -251,68 +252,41 @@ static void move_y(int delta)
static void on_handle_key(int key)
{
switch (key) {
case 10:
case 13:
case 27:
case KEY_CANCEL:
case KEY_ENTER:
case KEY_CLOSE:
case KEY_EXIT:
if (key >= ARRAY_SIZE(textbox_bindings))
return;
switch (textbox_bindings[key]) {
case CMD_TEXTBOX_CLOSE:
text_widget.close();
break;
case KEY_DOWN:
case KEY_SF:
case 'J':
case 'j':
case 'X':
case 'x':
case CMD_TEXTBOX_DOWN:
move_y(1);
break;
case KEY_UP:
case KEY_SR:
case 'K':
case 'k':
case 'W':
case 'w':
case CMD_TEXTBOX_UP:
move_y(-1);
break;
case KEY_LEFT:
case 'H':
case 'h':
case 'P':
case 'p':
case CMD_TEXTBOX_LEFT:
move_x(-1);
break;
case KEY_RIGHT:
case 'L':
case 'l':
case 'N':
case 'n':
case CMD_TEXTBOX_RIGHT:
move_x(1);
break;
case KEY_NPAGE:
case ' ':
case CMD_TEXTBOX_PAGE_DOWN:
move_y(text_box_y);
break;
case KEY_PPAGE:
case KEY_BACKSPACE:
case 'B':
case 'b':
case CMD_TEXTBOX_PAGE_UP:
move_y(-text_box_y);
break;
case KEY_HOME:
case KEY_BEG:
case CMD_TEXTBOX_TOP:
move_x(-max_scroll_x);
break;
case KEY_LL:
case KEY_END:
case CMD_TEXTBOX_BOTTOM:
move_x(max_scroll_x);
break;
case '\t':
case CMD_TEXTBOX_PAGE_RIGHT:
move_x(8);
break;
case KEY_BTAB:
case CMD_TEXTBOX_PAGE_LEFT:
move_x(-8);
break;
}