diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2011-07-26 18:50:29 +0200 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2011-07-26 18:50:29 +0200 |
commit | e0781f0390291e264e6dd9c17beae1342e87f9a2 (patch) | |
tree | aac2f19ab7e527180952db15867d8daaa23c4a91 /src/core | |
parent | 2fec84314433c2b7152c6c47b1172a621257fe6f (diff) | |
download | weechat-e0781f0390291e264e6dd9c17beae1342e87f9a2.zip |
core: add mouse support (task #5435), free cursor movement, hook_focus, fix bugs with key "^" (bug #32072, bug #21381), fix bugs with bar windows, completion and /buffer
New features and bugs fixed:
- mouse support: new command /mouse, new option weechat.look.mouse, new key context "mouse"
- free movement of cursor: new command /cursor, new key context "cursor"
- new hook_focus (used by cursor and mouse)
- info "cursor_mode"
- bugs fixed with key "^"
- allow plugin name in /buffer name
- fix bugs with bar windows: do not create bar windows for hidden bars
- fix completion bug when two words for completion are equal but with different case
- automatic scroll direction in /bar scroll (x/y is now optional)
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/wee-command.c | 316 | ||||
-rw-r--r-- | src/core/wee-completion.c | 46 | ||||
-rw-r--r-- | src/core/wee-config.c | 7 | ||||
-rw-r--r-- | src/core/wee-config.h | 1 | ||||
-rw-r--r-- | src/core/wee-hook.c | 169 | ||||
-rw-r--r-- | src/core/wee-hook.h | 55 | ||||
-rw-r--r-- | src/core/wee-string.c | 87 | ||||
-rw-r--r-- | src/core/wee-string.h | 5 |
8 files changed, 618 insertions, 68 deletions
diff --git a/src/core/wee-command.c b/src/core/wee-command.c index 24c886190..02de535df 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -55,6 +55,7 @@ #include "../gui/gui-buffer.h" #include "../gui/gui-chat.h" #include "../gui/gui-color.h" +#include "../gui/gui-cursor.h" #include "../gui/gui-filter.h" #include "../gui/gui-history.h" #include "../gui/gui-hotlist.h" @@ -62,6 +63,7 @@ #include "../gui/gui-key.h" #include "../gui/gui-layout.h" #include "../gui/gui-main.h" +#include "../gui/gui-mouse.h" #include "../gui/gui-window.h" #include "../plugins/plugin.h" #include "../plugins/plugin-config.h" @@ -499,7 +501,7 @@ COMMAND_CALLBACK(buffer) { struct t_gui_buffer *ptr_buffer, *weechat_buffer; long number, number1, number2; - char *error, *value, *pos, *str_number1, *pos_number2; + char *error, *value, *pos, *str_number1, *pos_number2, *plugin_name; int i, target_buffer; /* make C compiler happy */ @@ -897,7 +899,19 @@ COMMAND_CALLBACK(buffer) else { ptr_buffer = NULL; - ptr_buffer = gui_buffer_search_by_partial_name (NULL, argv_eol[1]); + pos = strchr (argv_eol[1], '.'); + if (pos) + { + plugin_name = string_strndup (argv_eol[1], pos - argv_eol[1]); + if (plugin_name) + { + ptr_buffer = gui_buffer_search_by_partial_name (plugin_name, + pos + 1); + free (plugin_name); + } + } + if (!ptr_buffer) + ptr_buffer = gui_buffer_search_by_partial_name (NULL, argv_eol[1]); if (ptr_buffer) { gui_window_switch_to_buffer (gui_current_window, ptr_buffer, 1); @@ -1099,6 +1113,89 @@ COMMAND_CALLBACK(command) } /* + * command_cursor: free movement of cursor on screen + */ + +COMMAND_CALLBACK(cursor) +{ + char *pos, *str_x, *error; + int x, y; + + /* make C compiler happy */ + (void) data; + (void) buffer; + (void) argv_eol; + + if (argc == 1) + { + gui_cursor_mode_toggle (); + return WEECHAT_RC_OK; + } + + if (string_strcasecmp (argv[1], "go") == 0) + { + if (argc > 2) + { + pos = strchr (argv[2], ','); + if (pos) + { + str_x = string_strndup (argv[2], pos - argv[2]); + pos++; + if (str_x) + { + error = NULL; + x = (int) strtol (str_x, &error, 10); + if (error && !error[0]) + { + error = NULL; + y = (int) strtol (pos, &error, 10); + if (error && !error[0]) + { + gui_cursor_move_xy (x, y); + } + } + } + } + else + gui_cursor_move_area (argv[2]); + } + return WEECHAT_RC_OK; + } + + if (string_strcasecmp (argv[1], "move") == 0) + { + if (argc > 2) + { + if (string_strcasecmp (argv[2], "up") == 0) + gui_cursor_move_add_xy (0, -1); + else if (string_strcasecmp (argv[2], "down") == 0) + gui_cursor_move_add_xy (0, 1); + else if (string_strcasecmp (argv[2], "left") == 0) + gui_cursor_move_add_xy (-1, 0); + else if (string_strcasecmp (argv[2], "right") == 0) + gui_cursor_move_add_xy (1, 0); + else if (string_strcasecmp (argv[2], "area_up") == 0) + gui_cursor_move_area_add_xy (0, -1); + else if (string_strcasecmp (argv[2], "area_down") == 0) + gui_cursor_move_area_add_xy (0, 1); + else if (string_strcasecmp (argv[2], "area_left") == 0) + gui_cursor_move_area_add_xy (-1, 0); + else if (string_strcasecmp (argv[2], "area_right") == 0) + gui_cursor_move_area_add_xy (1, 0); + } + return WEECHAT_RC_OK; + } + + if (string_strcasecmp (argv[1], "stop") == 0) + { + gui_cursor_mode_toggle (); + return WEECHAT_RC_OK; + } + + return WEECHAT_RC_OK; +} + +/* * command_debug: control debug for core/plugins */ @@ -1153,6 +1250,10 @@ COMMAND_CALLBACK(debug) { gui_color_dump (buffer); } + else if (string_strcasecmp (argv[1], "cursor") == 0) + { + gui_cursor_debug_toggle (); + } else if (string_strcasecmp (argv[1], "hdata") == 0) { if ((argc > 2) && (string_strcasecmp (argv[2], "free") == 0)) @@ -1168,6 +1269,10 @@ COMMAND_CALLBACK(debug) { debug_memory (); } + else if (string_strcasecmp (argv[1], "mouse") == 0) + { + gui_mouse_debug_toggle (); + } else if (string_strcasecmp (argv[1], "tags") == 0) { gui_chat_display_tags ^= 1; @@ -2178,9 +2283,9 @@ COMMAND_CALLBACK(input) else if (string_strcasecmp (argv[1], "hotlist_clear") == 0) gui_input_hotlist_clear (buffer); else if (string_strcasecmp (argv[1], "grab_key") == 0) - gui_input_grab_key (buffer); + gui_input_grab_key (buffer, (argc > 2) ? argv[2] : NULL); else if (string_strcasecmp (argv[1], "grab_key_command") == 0) - gui_input_grab_key_command (buffer); + gui_input_grab_key_command (buffer, (argc > 2) ? argv[2] : NULL); else if (string_strcasecmp (argv[1], "scroll_unread") == 0) gui_input_scroll_unread (buffer); else if (string_strcasecmp (argv[1], "set_unread") == 0) @@ -2213,25 +2318,12 @@ void command_key_display (struct t_gui_key *key, struct t_gui_key *default_key) { char *expanded_name; - char str_spaces[20 + 1]; - int length_screen, num_spaces; expanded_name = gui_key_get_expanded_name (key->key); - str_spaces[0] = '\0'; - length_screen = utf8_strlen_screen ((expanded_name) ? - expanded_name : key->key); - num_spaces = 20 - length_screen; - if (num_spaces > 0) - { - memset (str_spaces, ' ', num_spaces); - str_spaces[num_spaces] = '\0'; - } - if (default_key) { - gui_chat_printf (NULL, " %s%s%s => %s%s %s(%s%s %s%s)", - str_spaces, + gui_chat_printf (NULL, " %s%s => %s%s %s(%s%s %s%s)", (expanded_name) ? expanded_name : key->key, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT), @@ -2244,8 +2336,7 @@ command_key_display (struct t_gui_key *key, struct t_gui_key *default_key) } else { - gui_chat_printf (NULL, " %s%s%s => %s%s", - str_spaces, + gui_chat_printf (NULL, " %s%s => %s%s", (expanded_name) ? expanded_name : key->key, GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS), GUI_COLOR(GUI_COLOR_CHAT), @@ -2311,7 +2402,8 @@ command_key_display_listdiff (int context) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, - _("Key bindings added or redefined (%d) for " + /* TRANSLATORS: first "%d" is number of keys */ + _("%d key bindings added or redefined for " "context \"%s\":"), count_added, _(gui_key_context_string[context])); @@ -2340,7 +2432,8 @@ command_key_display_listdiff (int context) { gui_chat_printf (NULL, ""); gui_chat_printf (NULL, - _("Key bindings deleted (%d) for context \"%s\":"), + /* TRANSLATORS: first "%d" is number of keys */ + _("%d key bindings deleted for context \"%s\":"), count_deleted, _(gui_key_context_string[context])); for (ptr_default_key = gui_default_keys[context]; ptr_default_key; @@ -2357,6 +2450,7 @@ command_key_display_listdiff (int context) /* display a message if all key bindings are default bindings */ if ((count_added == 0) && (count_deleted == 0)) { + gui_chat_printf (NULL, ""); gui_chat_printf (NULL, _("No key binding added, redefined or removed " "for context \"%s\""), @@ -2480,8 +2574,9 @@ COMMAND_CALLBACK(key) { command_key_display_list (_("No key binding defined for " "context \"%s\""), - _("Key bindings (%d) for " - "context \"%s\":"), + /* TRANSLATORS: first "%d" is number of keys */ + _("%d key bindings for context " + "\"%s\":"), i, gui_keys[i], gui_keys_count[i]); } } @@ -2512,7 +2607,8 @@ COMMAND_CALLBACK(key) { command_key_display_list (_("No default key binding for " "context \"%s\""), - _("Default key bindings (%d) for " + /* TRANSLATORS: first "%d" is number of keys */ + _("%d default key bindings for " "context \"%s\":"), i, gui_default_keys[i], @@ -2940,6 +3036,96 @@ COMMAND_CALLBACK(layout) } /* + * command_mouse_timer_cb: callback for mouse timer + */ + +int +command_mouse_timer_cb (void *data, int remaining_calls) +{ + /* make C compiler happy */ + (void) data; + (void) remaining_calls; + + if (gui_mouse_enabled) + gui_mouse_disable (); + else + gui_mouse_enable (); + + return WEECHAT_RC_OK; +} + +/* + * command_mouse_timer: timer for toggling mouse + */ + +void +command_mouse_timer (const char *delay) +{ + long seconds; + char *error; + + error = NULL; + seconds = strtol (delay, &error, 10); + if (error && !error[0] && (seconds > 0)) + { + hook_timer (NULL, seconds * 1000, 0, 1, &command_mouse_timer_cb, NULL); + } +} + +/* + * command_mouse: mouse control + */ + +COMMAND_CALLBACK(mouse) +{ + /* make C compiler happy */ + (void) data; + (void) buffer; + (void) argv_eol; + + if (argc == 1) + { + gui_mouse_display_state (); + return WEECHAT_RC_OK; + } + + if (string_strcasecmp (argv[1], "enable") == 0) + { + gui_mouse_enable (); + if (argc > 2) + command_mouse_timer (argv[2]); + return WEECHAT_RC_OK; + } + + if (string_strcasecmp (argv[1], "disable") == 0) + { + gui_mouse_disable (); + if (argc > 2) + command_mouse_timer (argv[2]); + return WEECHAT_RC_OK; + } + + if (string_strcasecmp (argv[1], "toggle") == 0) + { + if (gui_mouse_enabled) + gui_mouse_disable (); + else + gui_mouse_enable (); + if (argc > 2) + command_mouse_timer (argv[2]); + return WEECHAT_RC_OK; + } + + if (string_strcasecmp (argv[1], "grab") == 0) + { + gui_mouse_grab_init (); + return WEECHAT_RC_OK; + } + + return WEECHAT_RC_OK; +} + +/* * command_mute: execute a command mute */ @@ -4900,10 +5086,10 @@ command_init () " scroll: scroll bar\n" " buffer: name of buffer to scroll ('*' " "means current buffer, you should use '*' for root bars)\n" - " scroll_value: value for scroll: 'x' or 'y', followed by " - "'+', '-', 'b' (beginning) or 'e' (end), value (for +/-), " - "and optional %% (to scroll by %% of width/height, " - "otherwise value is number of chars)\n\n" + " scroll_value: value for scroll: 'x' or 'y' (optional), " + "followed by '+', '-', 'b' (beginning) or 'e' (end), " + "value (for +/-), and optional % (to scroll by % of " + "width/height, otherwise value is number of chars)\n\n" "Examples:\n" " create a bar with time, buffer number + name, and completion:\n" " /bar add mybar root bottom 1 0 [time],buffer_number+:+buffer_name,completion\n" @@ -5035,12 +5221,37 @@ command_init () "added if not found at beginning of command)"), "%(plugins_names)|" PLUGIN_CORE " %(plugins_commands)", &command_command, NULL); + hook_command (NULL, "cursor", + N_("free movement of cursor on screen to execute actions on " + "specific areas of screen"), + N_("go chat|<bar>|<x>,<y>" + " || move up|down|left|right|area_up|area_down|area_left|" + "area_right" + " || stop"), + N_(" go: move cursor to chat area, a bar (using bar name) " + "or coordinates \"x,y\"\n" + "move: move cursor with direction\n" + "stop: stop cursor mode\n\n" + "Without argument, this command toggles cursor mode.\n\n" + "When mouse is enabled (see /help mouse), by default a " + "middle click will start cursor mode at this point.\n\n" + "Examples:\n" + " go to nicklist:\n" + " /cursor go nicklist\n" + " go to coordinates x=10, y=5:\n" + " /cursor go 10,5"), + "go %(cursor_areas)" + " || move up|down|left|right|area_up|area_down|area_left|" + "area_right" + " || stop", + &command_cursor, NULL); hook_command (NULL, "debug", N_("control debug for core/plugins"), N_("list" " || set <plugin> <level>" " || dump [<plugin>]" - " || buffer|color|infolists|memory|tags|term|windows" + " || buffer|color|cursor|infolists|memory|mouse|tags|" + "term|windows" " || hdata [free]"), N_(" list: list plugins with debug levels\n" " set: set debug level for plugin\n" @@ -5051,10 +5262,12 @@ command_init () " buffer: dump buffer content with hexadecimal values " "in log file\n" " color: display infos about current color pairs\n" + " cursor: toggle debug for cursor mode\n" " hdata: display infos about hdata (with free: remove " "all hdata in memory)\n" "infolists: display infos about infolists\n" " memory: display infos about memory usage\n" + " mouse: toggle debug for mouse\n" " tags: display tags for lines\n" " term: display infos about terminal\n" " windows: display windows tree"), @@ -5063,9 +5276,11 @@ command_init () " || dump %(plugins_names)|core" " || buffer" " || color" + " || cursor" " || hdata free" " || infolists" " || memory" + " || mouse" " || tags" " || term" " || windows", @@ -5208,9 +5423,11 @@ command_init () "visited buffer\n" " jump_next_visited_buffer: jump to next visited buffer\n" " hotlist_clear: clear hotlist\n" - " grab_key: grab a key\n" + " grab_key: grab a key (optional argument: delay for end " + "of grab, default is 500 milliseconds)\n" " grab_key_command: grab a key with its associated " - "command\n" + "command (optional argument: delay for end of grab, " + "default is 500 milliseconds)\n" " scroll_unread: scroll to unread marker\n" " set_unread: set unread marker for all buffers\n" " set_unread_current_buffer: set unread marker for " @@ -5272,6 +5489,14 @@ command_init () "When binding a command to a key, it is recommended to " "use key alt+k (or Esc then k), and then press the key " "to bind: this will insert key code in command line.\n\n" + "For context \"mouse\" (possible in context \"cursor\" " + "too), key has format: \"@area:key\" where area can be:\n" + " *: any area on screen\n" + " chat: chat area\n" + " bar(*): any bar\n" + " bar(xxx): bar \"xxx\"\n" + " item(*): any bar item\n" + " item(xxx): bar item \"xxx\"\n\n" "Examples:\n" " key alt-x to toggle nicklist bar:\n" " /key bind meta-x /bar toggle nicklist\n" @@ -5280,7 +5505,11 @@ command_init () " restore default binding for key alt-r:\n" " /key reset meta-r\n" " key \"tab\" to stop search in buffer:\n" - " /key bindctxt search ctrl-I /input search_stop"), + " /key bindctxt search ctrl-I /input search_stop\n" + " middle button of mouse on a nick to retrieve info on " + "nick:\n" + " /key bindctxt mouse @item(buffer_nicklist):button3 " + "/msg nickserv info ${nick}"), "list %(keys_contexts)" " || listdefault %(keys_contexts)" " || listdiff %(keys_contexts)" @@ -5290,7 +5519,7 @@ command_init () " || unbindctxt %(keys_contexts) %(keys_codes)" " || reset %(keys_codes_for_reset)" " || resetctxt %(keys_contexts) %(keys_codes_for_reset)" - " || resetall" + " || resetall %- %(keys_contexts)" " || missing %(keys_contexts)", &command_key, NULL); hook_command (NULL, "layout", @@ -5307,6 +5536,25 @@ command_init () "Without argument, this command displays saved layout."), "save|apply|reset buffers|windows", &command_layout, NULL); + hook_command (NULL, "mouse", + N_("mouse control"), + N_("enable|disable|toggle [<delay>]"), + N_(" enable: enable mouse\n" + "disable: disable mouse\n" + " toggle: toggle mouse\n" + " delay: delay (in seconds) after which initial mouse " + "state is restored (useful to temporarily disable mouse)\n\n" + "To enable/disable mouse at startup, use:\n" + " /set weechat.look.mouse on/off\n\n" + "Examples:\n" + " enable mouse:\n" + " /mouse enable\n" + " toggle mouse for 5 seconds:\n" + " /mouse toggle 5"), + "enable" + " || disable" + " || toggle", + &command_mouse, NULL); hook_command (NULL, "mute", N_("execute a command silently"), N_("[-current | -buffer <name> | -all] command"), diff --git a/src/core/wee-completion.c b/src/core/wee-completion.c index 49cdf9a91..7879fa4da 100644 --- a/src/core/wee-completion.c +++ b/src/core/wee-completion.c @@ -45,11 +45,13 @@ #include "../plugins/plugin.h" #include "../gui/gui-completion.h" #include "../gui/gui-bar.h" +#include "../gui/gui-bar-window.h" #include "../gui/gui-buffer.h" #include "../gui/gui-color.h" #include "../gui/gui-filter.h" #include "../gui/gui-key.h" #include "../gui/gui-nicklist.h" +#include "../gui/gui-window.h" /* @@ -1226,6 +1228,47 @@ completion_list_add_keys_codes_for_reset_cb (void *data, } /* + * completion_list_add_cursor_areas_cb: add areas for free cursor movement + * ("chat" and bar names) + */ + +int +completion_list_add_cursor_areas_cb (void *data, + const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + struct t_gui_bar_window *ptr_bar_win; + struct t_gui_bar *ptr_bar; + + /* make C compiler happy */ + (void) data; + (void) completion_item; + (void) buffer; + + /* add "chat" for chat area */ + gui_completion_list_add (completion, "chat", 0, WEECHAT_LIST_POS_SORT); + + /* add bar windows (of current window) */ + for (ptr_bar_win = gui_current_window->bar_windows; ptr_bar_win; + ptr_bar_win = ptr_bar_win->next_bar_window) + { + gui_completion_list_add (completion, ptr_bar_win->bar->name, + 0, WEECHAT_LIST_POS_SORT); + } + for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar) + { + if (ptr_bar->bar_window) + { + gui_completion_list_add (completion, ptr_bar->name, + 0, WEECHAT_LIST_POS_SORT); + } + } + + return WEECHAT_RC_OK; +} + +/* * completion_init: add hooks for completions done by WeeChat core */ @@ -1311,4 +1354,7 @@ completion_init () N_("key codes that can be reset (keys added, redefined " "or removed)"), &completion_list_add_keys_codes_for_reset_cb, NULL); + hook_completion (NULL, "cursor_areas", + N_("areas (\"chat\" or bar name) for free cursor movement"), + &completion_list_add_cursor_areas_cb, NULL); } diff --git a/src/core/wee-config.c b/src/core/wee-config.c index da8de105b..92e552528 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -56,6 +56,7 @@ #include "../gui/gui-layout.h" #include "../gui/gui-line.h" #include "../gui/gui-main.h" +#include "../gui/gui-mouse.h" #include "../gui/gui-nicklist.h" #include "../gui/gui-window.h" #include "../plugins/plugin.h" @@ -108,6 +109,7 @@ struct t_config_option *config_look_input_undo_max; struct t_config_option *config_look_item_time_format; struct t_config_option *config_look_jump_current_to_previous_buffer; struct t_config_option *config_look_jump_previous_buffer_when_closing; +struct t_config_option *config_look_mouse; struct t_config_option *config_look_nickmode; struct t_config_option *config_look_nickmode_empty; struct t_config_option *config_look_paste_max_lines; @@ -1794,6 +1796,11 @@ config_weechat_init_options () N_("jump to previously visited buffer when closing a buffer (if " "disabled, then jump to buffer number - 1)"), NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); + config_look_mouse = config_file_new_option ( + weechat_config_file, ptr_section, + "mouse", "boolean", + N_("enable mouse support at startup (to enable it now, see /help mouse)"), + NULL, 0, 0, "off", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); config_look_nickmode = config_file_new_option ( weechat_config_file, ptr_section, "nickmode", "boolean", diff --git a/src/core/wee-config.h b/src/core/wee-config.h index c09544a1a..a617e8f98 100644 --- a/src/core/wee-config.h +++ b/src/core/wee-config.h @@ -133,6 +133,7 @@ extern struct t_config_option *config_look_input_undo_max; extern struct t_config_option *config_look_item_time_format; extern struct t_config_option *config_look_jump_current_to_previous_buffer; extern struct t_config_option *config_look_jump_previous_buffer_when_closing; +extern struct t_config_option *config_look_mouse; extern struct t_config_option *config_look_nickmode; extern struct t_config_option *config_look_nickmode_empty; extern struct t_config_option *config_look_paste_max_lines; diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c index 9cb6404a9..89005dea7 100644 --- a/src/core/wee-hook.c +++ b/src/core/wee-hook.c @@ -49,9 +49,13 @@ #include "wee-utf8.h" #include "wee-util.h" #include "../gui/gui-chat.h" +#include "../gui/gui-bar.h" +#include "../gui/gui-bar-window.h" #include "../gui/gui-color.h" #include "../gui/gui-completion.h" +#include "../gui/gui-cursor.h" #include "../gui/gui-line.h" +#include "../gui/gui-window.h" #include "../plugins/plugin.h" @@ -2744,6 +2748,150 @@ hook_hdata_get (struct t_weechat_plugin *plugin, const char *hdata_name) } /* + * hook_focus: hook a focus + */ + +struct t_hook * +hook_focus (struct t_weechat_plugin *plugin, const char *area, + t_hook_callback_focus *callback, void *callback_data) +{ + struct t_hook *new_hook; + struct t_hook_focus *new_hook_focus; + int priority; + const char *ptr_area; + + if (!area || !area[0] || !callback) + return NULL; + + new_hook = malloc (sizeof (*new_hook)); + if (!new_hook) + return NULL; + new_hook_focus = malloc (sizeof (*new_hook_focus)); + if (!new_hook_focus) + { + free (new_hook); + return NULL; + } + + hook_get_priority_and_name (area, &priority, &ptr_area); + hook_init_data (new_hook, plugin, HOOK_TYPE_FOCUS, priority, + callback_data); + + new_hook->hook_data = new_hook_focus; + new_hook_focus->callback = callback; + new_hook_focus->area = strdup ((ptr_area) ? ptr_area : area); + + hook_add_to_list (new_hook); + + return new_hook; +} + +/* + * hook_focus_hashtable_map_cb: add keys of a hashtable into another + */ + +void +hook_focus_hashtable_map_cb (void *data, struct t_hashtable *hashtable, + const void *key, const void *value) +{ + struct t_hashtable *hashtable1; + + /* make C compiler happy */ + (void) hashtable; + + hashtable1 = (struct t_hashtable *)data; + + if (hashtable1 && key && value) + hashtable_set (hashtable1, (const char *)key, (const char *)value); +} + +/* + * hook_focus_get_data: get data for focus on (x,y) on screen + */ + +struct t_hashtable * +hook_focus_get_data (struct t_gui_cursor_info *cursor_info) +{ + struct t_hook *ptr_hook, *next_hook; + struct t_hashtable *hash_info, *hash_info2; + char str_value[64]; + + hook_exec_start (); + + hash_info = hashtable_new (8, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, + NULL); + if (!hash_info) + return NULL; + + /* fill hash_info with values from cursor_info */ + snprintf (str_value, sizeof (str_value), "%d", cursor_info->x); + hashtable_set (hash_info, "_x", str_value); + snprintf (str_value, sizeof (str_value), "%d", cursor_info->y); + hashtable_set (hash_info, "_y", str_value); + snprintf (str_value, sizeof (str_value), + "0x%lx", (long unsigned int)cursor_info->window); + hashtable_set (hash_info, "_window", str_value); + snprintf (str_value, sizeof (str_value), + "0x%lx", + (cursor_info->window) ? + (long unsigned int)((cursor_info->window)->buffer) : 0); + hashtable_set (hash_info, "_buffer", str_value); + hashtable_set (hash_info, "_bar_name", + (cursor_info->bar_window) ? + ((cursor_info->bar_window)->bar)->name : NULL); + hashtable_set (hash_info, "_bar_item_name", + cursor_info->bar_item); + snprintf (str_value, sizeof (str_value), + "%d", cursor_info->item_line); + hashtable_set (hash_info, "_item_line", str_value); + snprintf (str_value, sizeof (str_value), + "%d", cursor_info->item_col); + hashtable_set (hash_info, "_item_col", str_value); + + ptr_hook = weechat_hooks[HOOK_TYPE_FOCUS]; + while (ptr_hook) + { + next_hook = ptr_hook->next_hook; + + if (!ptr_hook->deleted + && !ptr_hook->running + && ((cursor_info->chat + && (strcmp (HOOK_FOCUS(ptr_hook, area), "chat") == 0)) + || (cursor_info->bar_item + && (strcmp (HOOK_FOCUS(ptr_hook, area), cursor_info->bar_item) == 0)))) + { + ptr_hook->running = 1; + hash_info2 = (HOOK_FOCUS(ptr_hook, callback)) + (ptr_hook->callback_data, hash_info); + ptr_hook->running = 0; + + if (hash_info2) + { + if (hash_info2 != hash_info) + { + /* + * add keys of hashtable2 into hashtable and destroy + * hashtable2 + */ + hashtable_map (hash_info2, &hook_focus_hashtable_map_cb, + hash_info); + hashtable_free (hash_info2); + } + } + } + + ptr_hook = next_hook; + } + + hook_exec_end (); + + return hash_info; +} + +/* * unhook: unhook something */ @@ -2933,6 +3081,10 @@ unhook (struct t_hook *hook) if (HOOK_HDATA(hook, description)) free (HOOK_HDATA(hook, description)); break; + case HOOK_TYPE_FOCUS: + if (HOOK_FOCUS(hook, area)) + free (HOOK_FOCUS(hook, area)); + break; case HOOK_NUM_TYPES: /* * this constant is used to count types only, @@ -3372,6 +3524,15 @@ hook_add_to_infolist_type (struct t_infolist *infolist, int type, return 0; } break; + case HOOK_TYPE_FOCUS: + if (!ptr_hook->deleted) + { + if (!infolist_new_var_pointer (ptr_item, "callback", HOOK_FOCUS(ptr_hook, callback))) + return 0; + if (!infolist_new_var_string (ptr_item, "area", HOOK_FOCUS(ptr_hook, area))) + return 0; + } + break; case HOOK_NUM_TYPES: /* * this constant is used to count types only, @@ -3671,6 +3832,14 @@ hook_print_log () log_printf (" description . . . . . : '%s'", HOOK_HDATA(ptr_hook, description)); } break; + case HOOK_TYPE_FOCUS: + if (!ptr_hook->deleted) + { + log_printf (" focus data:"); + log_printf (" callback. . . . . . . : 0x%lx", HOOK_FOCUS(ptr_hook, callback)); + log_printf (" area. . . . . . . . . : '%s'", HOOK_FOCUS(ptr_hook, area)); + } + break; case HOOK_NUM_TYPES: /* * this constant is used to count types only, diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h index 054976259..65df6e7d0 100644 --- a/src/core/wee-hook.h +++ b/src/core/wee-hook.h @@ -24,9 +24,12 @@ #include <gnutls/gnutls.h> #endif +struct t_gui_bar; struct t_gui_buffer; struct t_gui_line; struct t_gui_completion; +struct t_gui_cursor_info; +struct t_gui_window; struct t_weelist; struct t_hashtable; struct t_infolist; @@ -51,6 +54,7 @@ enum t_hook_type HOOK_TYPE_INFO_HASHTABLE, /* get some info as hashtable */ HOOK_TYPE_INFOLIST, /* get some info as infolist */ HOOK_TYPE_HDATA, /* get hdata pointer */ + HOOK_TYPE_FOCUS, /* focus event (mouse/key) */ /* number of hook types */ HOOK_NUM_TYPES, }; @@ -91,6 +95,7 @@ enum t_hook_type #define HOOK_INFO_HASHTABLE(hook, var) (((struct t_hook_info_hashtable *)hook->hook_data)->var) #define HOOK_INFOLIST(hook, var) (((struct t_hook_infolist *)hook->hook_data)->var) #define HOOK_HDATA(hook, var) (((struct t_hook_hdata *)hook->hook_data)->var) +#define HOOK_FOCUS(hook, var) (((struct t_hook_focus *)hook->hook_data)->var) struct t_hook { @@ -374,6 +379,17 @@ struct t_hook_hdata char *description; /* description */ }; +/* hook focus */ + +typedef struct t_hashtable *(t_hook_callback_focus)(void *data, + struct t_hashtable *info); + +struct t_hook_focus +{ + t_hook_callback_focus *callback; /* focus callback */ + char *area; /* "chat" or bar item name */ +}; + /* hook variables */ extern struct t_hook *weechat_hooks[]; @@ -521,43 +537,14 @@ extern struct t_hook *hook_hdata (struct t_weechat_plugin *plugin, void *callback_data); extern struct t_hdata *hook_hdata_get (struct t_weechat_plugin *plugin, const char *hdata_name); +extern struct t_hook *hook_focus (struct t_weechat_plugin *plugin, + const char *area, + t_hook_callback_focus *callback, + void *callback_data); +extern struct t_hashtable *hook_focus_get_data (struct t_gui_cursor_info *cursor_info); extern void unhook (struct t_hook *hook); extern void unhook_all_plugin (struct t_weechat_plugin *plugin); extern void unhook_all (); -extern struct t_hdata *hook_hdata_hook_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_command_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_command_run_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_timer_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_fd_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_process_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_connect_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_print_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_signal_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_hsignal_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_config_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_completion_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_modifier_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_info_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_info_hashtable_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_infolist_cb (void *data, - const char *hdata_name); -extern struct t_hdata *hook_hdata_hook_hdata_cb (void *data, - const char *hdata_name); extern int hook_add_to_infolist (struct t_infolist *infolist, const char *arguments); extern void hook_print_log (); diff --git a/src/core/wee-string.c b/src/core/wee-string.c index 1a8dd090f..6d1270221 100644 --- a/src/core/wee-string.c +++ b/src/core/wee-string.c @@ -54,6 +54,7 @@ #include "weechat.h" #include "wee-string.h" #include "wee-config.h" +#include "wee-hashtable.h" #include "wee-utf8.h" #include "../gui/gui-color.h" @@ -1602,3 +1603,89 @@ string_input_for_buffer (const char *string) /* string is a command */ return NULL; } + +/* + * string_replace_with_hashtable: replace ${codes} with value from hashtable + * "errors" is set with number of keys not found + * in hashtable + */ + +char * +string_replace_with_hashtable (const char *string, + struct t_hashtable *hashtable, + int *errors) +{ + int length, length_value, index_string, index_result; + char *result, *key; + const char *pos_end_name, *ptr_value; + + *errors = 0; + + if (!string) + return NULL; + + if (!hashtable) + return strdup (string); + + length = strlen (string) + 1; + result = malloc (length); + if (result) + { + index_string = 0; + index_result = 0; + while (string[index_string]) + { + if ((string[index_string] == '\\') + && (string[index_string + 1] == '$')) + { + index_string++; + result[index_result++] = string[index_string++]; + } + else if ((string[index_string] == '$') + && (string[index_string + 1] == '{')) + { + pos_end_name = strchr (string + index_string + 2, '}'); + if (pos_end_name) + { + key = string_strndup (string + index_string + 2, + pos_end_name - (string + index_string + 2)); + if (key) + { + ptr_value = (const char *)hashtable_get (hashtable, key); + if (ptr_value) + { + length_value = strlen (ptr_value); + length += length_value; + result = realloc (result, length); + if (!result) + { + free (key); + return NULL; + } + strcpy (result + index_result, ptr_value); + index_result += length_value; + index_string += pos_end_name - string - + index_string + 1; + } + else + { + result[index_result++] = string[index_string++]; + (*errors)++; + } + + free (key); + } + else + result[index_result++] = string[index_string++]; + } + else + result[index_result++] = string[index_string++]; + } + else + result[index_result++] = string[index_string++]; + } + result[index_result] = '\0'; + } + + return result; +} diff --git a/src/core/wee-string.h b/src/core/wee-string.h index 8b4465256..48832408f 100644 --- a/src/core/wee-string.h +++ b/src/core/wee-string.h @@ -22,6 +22,8 @@ #include <regex.h> +struct t_hashtable; + extern char *string_strndup (const char *string, int length); extern void string_tolower (char *string); extern void string_toupper (char *string); @@ -66,5 +68,8 @@ extern void string_encode_base64 (const char *from, int length, char *to); extern int string_decode_base64 (const char *from, char *to); extern int string_is_command_char (const char *string); extern const char *string_input_for_buffer (const char *string); +extern char *string_replace_with_hashtable (const char *string, + struct t_hashtable *hashtable, + int *errors); #endif /* __WEECHAT_STRING_H */ |