--- a/mcabber/mcabber/screen.c Mon Jan 30 18:46:15 2017 +0100
+++ b/mcabber/mcabber/screen.c Wed Jul 22 19:25:22 2015 +0200
@@ -95,6 +95,9 @@
static void spellcheck(char *, char *);
#endif
+static void open_chat_window(void);
+static void clear_inputline(void);
+
static GHashTable *winbufhash;
typedef struct {
@@ -4175,7 +4178,8 @@
static inline void refresh_inputline(void)
{
#if defined(WITH_ENCHANT) || defined(WITH_ASPELL)
- if (settings_opt_get_int("spell_enable")) {
+ if (settings_opt_get_int("spell_enable") &&
+ (chatmode || !settings_opt_get_int("vi_mode"))) {
memset(maskLine, 0, INPUTLINE_LENGTH+1);
spellcheck(inputLine, maskLine);
}
@@ -4426,12 +4430,53 @@
#endif
}
+static void scr_process_vi_arrow_key(int key)
+{
+ const char *l;
+ char mask[INPUTLINE_LENGTH+1] = "/roster search ";
+ size_t cmd_len = strlen(mask);
+ size_t str_len = strlen(inputLine) - 1;
+
+ switch (inputLine[0]) {
+ case ':':
+ inputLine[0] = '/';
+ if (key == KEY_UP)
+ l = scr_cmdhisto_prev(inputLine, ptr_inputline - inputLine);
+ else
+ l = scr_cmdhisto_next(inputLine, ptr_inputline - inputLine);
+ if (l)
+ strcpy(inputLine, l);
+ inputLine[0] = ':';
+ break;
+ case '/':
+ if (cmd_len + str_len > INPUTLINE_LENGTH)
+ return;
+
+ memcpy(mask + cmd_len, inputLine + 1, str_len + 1);
+ if (key == KEY_UP)
+ l = scr_cmdhisto_prev(mask, ptr_inputline - inputLine + cmd_len - 1);
+ else
+ l = scr_cmdhisto_next(mask, ptr_inputline - inputLine + cmd_len - 1);
+ if (l)
+ strcpy(inputLine + 1, l + cmd_len);
+ break;
+ default:
+ if (key == KEY_UP)
+ process_command(mkcmdstr("roster up"), TRUE);
+ else
+ process_command(mkcmdstr("roster down"), TRUE);
+ break;
+ }
+}
+
// scr_process_key(key)
// Handle the pressed key, in the command line (bottom).
void scr_process_key(keycode kcode)
{
int key = kcode.value;
int display_char = FALSE;
+ int vi_completion = FALSE;
+ static int ex_or_search_mode = FALSE;
lock_chatstate = FALSE;
@@ -4448,6 +4493,253 @@
key = ERR; // Do not process any further
}
+ if (settings_opt_get_int("vi_mode") && !chatmode) {
+ int got_cmd_prefix = FALSE;
+ int unrecognized = FALSE;
+ static char search_cmd[INPUTLINE_LENGTH+1] = "/roster search ";
+
+ if (key == KEY_UP || key == KEY_DOWN) {
+ scr_process_vi_arrow_key(key);
+ key = ERR; // Do not process any further
+ } else if (ex_or_search_mode) {
+ switch (key) {
+ case 27: // Escape
+ clear_inputline();
+ ex_or_search_mode = FALSE;
+ break;
+ case 9: // Tab
+ case 353: // Shift-Tab
+ if (inputLine[0] == ':') {
+ inputLine[0] = '/';
+ vi_completion = TRUE;
+ }
+ break;
+ case 13: // Enter
+ case 343: // Enter on Maemo
+ switch (inputLine[0]) {
+ case ':':
+ {
+ char *p = strchr(inputLine, 0);
+
+ while (*--p == ' ' && p > inputLine)
+ *p = 0;
+ }
+ if (!strcmp(inputLine, ":x") ||
+ !strcmp(inputLine, ":q") ||
+ !strcmp(inputLine, ":wq"))
+ strcpy(inputLine, ":quit");
+ if (isdigit((int)(unsigned char)inputLine[1]) &&
+ strlen(inputLine) <= 9) {
+ process_command(mkcmdstr("roster top"), TRUE);
+ memcpy(inputLine + 13, inputLine + 1, 10);
+ memcpy(inputLine + 1, "roster down ", 12);
+ }
+ inputLine[0] = '/';
+ process_command(inputLine, TRUE);
+ scr_cmdhisto_addline(inputLine);
+ break;
+ case '/':
+ {
+ size_t cmd_len = sizeof("/roster search ") - 1;
+ size_t str_len = strlen(inputLine) - 1;
+
+ if (cmd_len + str_len > INPUTLINE_LENGTH)
+ return;
+
+ memcpy(search_cmd + cmd_len, inputLine + 1,
+ str_len + 1);
+ }
+ process_command(search_cmd, TRUE);
+ scr_cmdhisto_addline(search_cmd);
+ break;
+ }
+ ex_or_search_mode = FALSE;
+ break;
+ }
+ } else if (key >= '0' && key <= '9') {
+ got_cmd_prefix = TRUE;
+ } else {
+ switch (key) {
+ case '/':
+ case ':':
+ ex_or_search_mode = TRUE;
+ break;
+ case ' ':
+ process_command(mkcmdstr("group toggle"), TRUE);
+ break;
+ case '!':
+ {
+ const char *bjid = buddy_getjid(BUDDATA(current_buddy));
+
+ if (bjid) {
+ guint type = buddy_gettype(BUDDATA(current_buddy));
+ guint prio = buddy_getuiprio(BUDDATA(current_buddy));
+
+ if (type & ROSTER_TYPE_ROOM &&
+ prio < ROSTER_UI_PRIO_MUC_HL_MESSAGE) {
+ roster_setuiprio(bjid, FALSE,
+ ROSTER_UI_PRIO_MUC_HL_MESSAGE, prio_set);
+ roster_msg_setflag(bjid, FALSE, TRUE);
+ } else if (type & ROSTER_TYPE_USER &&
+ prio < ROSTER_UI_PRIO_ATTENTION_MESSAGE) {
+ roster_setuiprio(bjid, FALSE,
+ ROSTER_UI_PRIO_ATTENTION_MESSAGE, prio_set);
+ roster_msg_setflag(bjid, FALSE, TRUE);
+ } else {
+ roster_msg_setflag(bjid, FALSE, FALSE);
+ }
+ scr_update_roster();
+ }
+ }
+ break;
+ case '#':
+ {
+ const char *bjid = buddy_getjid(BUDDATA(current_buddy));
+
+ if (bjid) {
+ unsigned short bflags = buddy_getflags(BUDDATA(current_buddy));
+
+ if (bflags & ROSTER_FLAG_MSG)
+ roster_msg_setflag(bjid, FALSE, FALSE);
+ else
+ roster_msg_setflag(bjid, FALSE, TRUE);
+
+ scr_update_roster();
+ }
+ }
+ break;
+ case '\'':
+ if (inputLine[0] == '\'')
+ process_command(mkcmdstr("roster alternate"), TRUE);
+ else
+ got_cmd_prefix = TRUE;
+ break;
+ case 'A':
+ process_command(mkcmdstr("roster unread_first"), TRUE);
+ break;
+ case 'a':
+ process_command(mkcmdstr("roster unread_next"), TRUE);
+ break;
+ case 'F':
+ process_command(mkcmdstr("roster group_prev"), TRUE);
+ break;
+ case 'f':
+ process_command(mkcmdstr("roster group_next"), TRUE);
+ break;
+ case 'G':
+ process_command(mkcmdstr("roster bottom"), TRUE);
+ break;
+ case 'g':
+ if (inputLine[0] == 'g')
+ process_command(mkcmdstr("roster top"), TRUE);
+ else {
+ clear_inputline();
+ got_cmd_prefix = TRUE;
+ }
+ break;
+ case 'i':
+ open_chat_window();
+ break;
+ case 'j':
+ if (isdigit((int)(unsigned char)inputLine[0]) &&
+ strlen(inputLine) <= 9) {
+ char down_cmd[32] = "/roster down ";
+
+ strcat(down_cmd, inputLine);
+ process_command(down_cmd, TRUE);
+ } else
+ process_command(mkcmdstr("roster down"), TRUE);
+ break;
+ case 'k':
+ if (isdigit((int)(unsigned char)inputLine[0]) &&
+ strlen(inputLine) <= 9) {
+ char up_cmd[32] = "/roster up ";
+
+ strcat(up_cmd, inputLine);
+ process_command(up_cmd, TRUE);
+ } else
+ process_command(mkcmdstr("roster up "), TRUE);
+ break;
+ case 'M':
+ if (inputLine[0] == 'z') {
+ GSList *groups = compl_list(ROSTER_TYPE_GROUP);
+ GSList *g;
+
+ for (g = groups; g; g = g_slist_next(g)) {
+ char fold_cmd[128] = "/group fold ";
+ size_t cmd_len = strlen(fold_cmd);
+ size_t grp_len = strlen(g->data);
+
+ if (cmd_len + grp_len + 1 > sizeof(fold_cmd))
+ continue;
+ memcpy(fold_cmd + cmd_len, g->data, grp_len + 1);
+ process_command(fold_cmd, TRUE);
+ g_free(g->data);
+ }
+ g_slist_free(groups);
+ } else
+ unrecognized = TRUE;
+ break;
+ case 'n':
+ process_command(search_cmd, TRUE);
+ break;
+ case 'O':
+ process_command(mkcmdstr("roster unread_first"), TRUE);
+ open_chat_window();
+ break;
+ case 'o':
+ process_command(mkcmdstr("roster unread_next"), TRUE);
+ open_chat_window();
+ break;
+ case 'R':
+ if (inputLine[0] == 'z') {
+ GSList *groups = compl_list(ROSTER_TYPE_GROUP);
+ GSList *g;
+
+ for (g = groups; g; g = g_slist_next(g)) {
+ char fold_cmd[128] = "/group unfold ";
+ size_t cmd_len = strlen(fold_cmd);
+ size_t grp_len = strlen(g->data);
+
+ if (cmd_len + grp_len + 1 > sizeof(fold_cmd))
+ continue;
+ memcpy(fold_cmd + cmd_len, g->data, grp_len + 1);
+ process_command(fold_cmd, TRUE);
+ g_free(g->data);
+ }
+ g_slist_free(groups);
+ } else
+ unrecognized = TRUE;
+ break;
+ case 'Z':
+ if (inputLine[0] == 'Z')
+ process_command(mkcmdstr("quit"), TRUE);
+ else {
+ clear_inputline();
+ got_cmd_prefix = TRUE;
+ }
+ break;
+ case 'z':
+ clear_inputline();
+ got_cmd_prefix = TRUE;
+ break;
+ case 13: // Enter
+ case 343: // Enter on Maemo
+ break;
+ default:
+ unrecognized = TRUE;
+ break;
+ }
+ cmdhisto_cur = NULL;
+ }
+ if (!ex_or_search_mode && !got_cmd_prefix) {
+ clear_inputline();
+ if (!unrecognized)
+ key = ERR; // Do not process any further
+ }
+ lock_chatstate = TRUE;
+ }
+
if (kcode.utf8) {
if (key != ERR && !kcode.mcode)
display_char = TRUE;
@@ -4513,8 +4805,13 @@
if (completion_started && key != 9 && key != 353 && key != KEY_RESIZE)
scr_end_current_completion();
+ else if (vi_completion)
+ inputLine[0] = ':';
refresh_inputline();
+ if (ex_or_search_mode && inputLine[0] != ':' && inputLine[0] != '/')
+ ex_or_search_mode = FALSE;
+
if (!lock_chatstate) {
// Set chat state to composing (1) if the user is currently composing,
// i.e. not an empty line and not a command line.
@@ -4693,4 +4990,19 @@
}
#endif
+static void open_chat_window(void)
+{
+ last_activity_buddy = current_buddy;
+ scr_check_auto_away(TRUE);
+ scr_set_chatmode(TRUE);
+ scr_show_buddy_window();
+}
+
+static void clear_inputline(void)
+{
+ ptr_inputline = inputLine;
+ *ptr_inputline = 0;
+ inputline_offset = 0;
+}
+
/* vim: set et cindent cinoptions=>2\:2(0 ts=2 sw=2: For Vim users... */