summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSebastien Helleu <flashcode@flashtux.org>2011-07-26 18:50:29 +0200
committerSebastien Helleu <flashcode@flashtux.org>2011-07-26 18:50:29 +0200
commite0781f0390291e264e6dd9c17beae1342e87f9a2 (patch)
treeaac2f19ab7e527180952db15867d8daaa23c4a91 /src
parent2fec84314433c2b7152c6c47b1172a621257fe6f (diff)
downloadweechat-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')
-rw-r--r--src/core/wee-command.c316
-rw-r--r--src/core/wee-completion.c46
-rw-r--r--src/core/wee-config.c7
-rw-r--r--src/core/wee-config.h1
-rw-r--r--src/core/wee-hook.c169
-rw-r--r--src/core/wee-hook.h55
-rw-r--r--src/core/wee-string.c87
-rw-r--r--src/core/wee-string.h5
-rw-r--r--src/gui/CMakeLists.txt2
-rw-r--r--src/gui/Makefile.am4
-rw-r--r--src/gui/curses/CMakeLists.txt3
-rw-r--r--src/gui/curses/Makefile.am4
-rw-r--r--src/gui/curses/gui-curses-bar-window.c71
-rw-r--r--src/gui/curses/gui-curses-chat.c2
-rw-r--r--src/gui/curses/gui-curses-key.c355
-rw-r--r--src/gui/curses/gui-curses-main.c17
-rw-r--r--src/gui/curses/gui-curses-mouse.c243
-rw-r--r--src/gui/curses/gui-curses-window.c18
-rw-r--r--src/gui/gtk/CMakeLists.txt1
-rw-r--r--src/gui/gtk/Makefile.am1
-rw-r--r--src/gui/gtk/gui-gtk-mouse.c94
-rw-r--r--src/gui/gtk/gui-gtk-window.c10
-rw-r--r--src/gui/gui-bar-item.c346
-rw-r--r--src/gui/gui-bar-item.h12
-rw-r--r--src/gui/gui-bar-window.c509
-rw-r--r--src/gui/gui-bar-window.h37
-rw-r--r--src/gui/gui-bar.c194
-rw-r--r--src/gui/gui-bar.h4
-rw-r--r--src/gui/gui-color.c2
-rw-r--r--src/gui/gui-color.h2
-rw-r--r--src/gui/gui-completion.c2
-rw-r--r--src/gui/gui-cursor.c337
-rw-r--r--src/gui/gui-cursor.h54
-rw-r--r--src/gui/gui-input.c46
-rw-r--r--src/gui/gui-input.h6
-rw-r--r--src/gui/gui-key.c340
-rw-r--r--src/gui/gui-key.h7
-rw-r--r--src/gui/gui-mouse.c74
-rw-r--r--src/gui/gui-mouse.h47
-rw-r--r--src/gui/gui-window.c31
-rw-r--r--src/gui/gui-window.h5
-rw-r--r--src/plugins/irc/irc-bar-item.c45
-rw-r--r--src/plugins/plugin-api.c10
-rw-r--r--src/plugins/plugin.c1
-rw-r--r--src/plugins/scripts/lua/weechat-lua-api.c71
-rw-r--r--src/plugins/scripts/perl/weechat-perl-api.c67
-rw-r--r--src/plugins/scripts/python/weechat-python-api.c176
-rw-r--r--src/plugins/scripts/ruby/weechat-ruby-api.c73
-rw-r--r--src/plugins/scripts/script-api.c37
-rw-r--r--src/plugins/scripts/script-api.h7
-rw-r--r--src/plugins/scripts/tcl/weechat-tcl-api.c71
-rw-r--r--src/plugins/weechat-plugin.h10
52 files changed, 3497 insertions, 637 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 */
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index ebbfcac48..11c792738 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -24,6 +24,7 @@ gui-bar-window.c gui-bar-window.h
gui-buffer.c gui-buffer.h
gui-chat.c gui-chat.h
gui-color.c gui-color.h
+gui-cursor.c gui-cursor.h
gui-filter.c gui-filter.h
gui-completion.c gui-completion.h
gui-history.c gui-history.h
@@ -33,6 +34,7 @@ gui-key.c gui-key.h
gui-layout.c gui-layout.h
gui-line.c gui-line.h
gui-main.h
+gui-mouse.c gui-mouse.h
gui-nicklist.c gui-nicklist.h
gui-window.c gui-window.h)
diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am
index 443bc9968..a53637c35 100644
--- a/src/gui/Makefile.am
+++ b/src/gui/Makefile.am
@@ -33,6 +33,8 @@ lib_weechat_gui_common_a_SOURCES = gui-bar.c \
gui-chat.h \
gui-color.c \
gui-color.h \
+ gui-cursor.c \
+ gui-cursor.h \
gui-completion.c \
gui-completion.h \
gui-filter.c \
@@ -50,6 +52,8 @@ lib_weechat_gui_common_a_SOURCES = gui-bar.c \
gui-line.c \
gui-line.h \
gui-main.h \
+ gui-mouse.c \
+ gui-mouse.h \
gui-nicklist.c \
gui-nicklist.h \
gui-window.c \
diff --git a/src/gui/curses/CMakeLists.txt b/src/gui/curses/CMakeLists.txt
index 85007323a..8362df107 100644
--- a/src/gui/curses/CMakeLists.txt
+++ b/src/gui/curses/CMakeLists.txt
@@ -30,6 +30,7 @@ gui-curses-chat.c
gui-curses-color.c
gui-curses-key.c
gui-curses-main.c
+gui-curses-mouse.c
gui-curses-term.c
gui-curses-window.c)
@@ -68,6 +69,8 @@ IF(LIBINTL_LIBRARY)
LIST(APPEND EXTRA_LIBS ${LIBINTL_LIBRARY})
ENDIF(LIBINTL_LIBRARY)
+LIST(APPEND EXTRA_LIBS "m")
+
ADD_EXECUTABLE(${EXECUTABLE} ${WEECHAT_CURSES_SRC})
INCLUDE_DIRECTORIES(.. ../../core ../../plugins)
diff --git a/src/gui/curses/Makefile.am b/src/gui/curses/Makefile.am
index 61ac1f2ec..1bc15cf98 100644
--- a/src/gui/curses/Makefile.am
+++ b/src/gui/curses/Makefile.am
@@ -30,13 +30,15 @@ weechat_curses_LDADD = ./../../core/lib_weechat_core.a \
$(PLUGINS_LFLAGS) \
$(NCURSES_LFLAGS) \
$(GCRYPT_LFLAGS) \
- $(GNUTLS_LFLAGS)
+ $(GNUTLS_LFLAGS) \
+ -lm
weechat_curses_SOURCES = gui-curses-bar-window.c \
gui-curses-chat.c \
gui-curses-color.c \
gui-curses-key.c \
gui-curses-main.c \
+ gui-curses-mouse.c \
gui-curses-term.c \
gui-curses-window.c \
gui-curses.h
diff --git a/src/gui/curses/gui-curses-bar-window.c b/src/gui/curses/gui-curses-bar-window.c
index d96f925fb..ced409c64 100644
--- a/src/gui/curses/gui-curses-bar-window.c
+++ b/src/gui/curses/gui-curses-bar-window.c
@@ -39,6 +39,7 @@
#include "../gui-bar-window.h"
#include "../gui-chat.h"
#include "../gui-color.h"
+#include "../gui-cursor.h"
#include "../gui-window.h"
#include "gui-curses.h"
@@ -89,6 +90,9 @@ gui_bar_window_objects_free (struct t_gui_bar_window *bar_window)
void
gui_bar_window_create_win (struct t_gui_bar_window *bar_window)
{
+ if (CONFIG_BOOLEAN(bar_window->bar->options[GUI_BAR_OPTION_HIDDEN]))
+ return;
+
if (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar)
{
delwin (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar);
@@ -152,14 +156,15 @@ gui_bar_window_print_string (struct t_gui_bar_window *bar_window,
int *x, int *y,
const char *string,
int reset_color_before_display,
- int hide_chars_if_scrolling)
+ int hide_chars_if_scrolling,
+ int *index_item, int *index_subitem, int *index_line)
{
int x_with_hidden, size_on_screen, low_char, hidden;
char utf_char[16], *next_char, *output;
if (!string || !string[0])
return 1;
-
+
wmove (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, *y, *x);
if (reset_color_before_display)
@@ -239,6 +244,40 @@ gui_bar_window_print_string (struct t_gui_bar_window *bar_window,
bar_window->cursor_x += bar_window->x;
bar_window->cursor_y += bar_window->y;
break;
+ case GUI_COLOR_BAR_START_ITEM:
+ string += 2;
+ if (*index_item < 0)
+ {
+ *index_item = 0;
+ *index_subitem = 0;
+ }
+ else
+ {
+ (*index_subitem)++;
+ if (*index_subitem >= bar_window->items_subcount[*index_item])
+ {
+ (*index_item)++;
+ *index_subitem = 0;
+ }
+ }
+ *index_line = 0;
+ gui_bar_window_coords_add (bar_window,
+ (*index_item >= bar_window->items_count) ? -1 : *index_item,
+ (*index_item >= bar_window->items_count) ? -1 : *index_subitem,
+ *index_line,
+ *x + bar_window->x,
+ *y + bar_window->y);
+ break;
+ case GUI_COLOR_BAR_START_LINE_ITEM:
+ string += 2;
+ (*index_line)++;
+ gui_bar_window_coords_add (bar_window,
+ *index_item,
+ *index_subitem,
+ *index_line,
+ *x + bar_window->x,
+ *y + bar_window->y);
+ break;
default:
string++;
break;
@@ -353,10 +392,11 @@ gui_bar_window_draw (struct t_gui_bar_window *bar_window,
int length_screen_before_cursor, length_screen_after_cursor;
int diff, max_length, optimal_number_of_lines;
int some_data_not_displayed, separator_horizontal, separator_vertical;
+ int index_item, index_subitem, index_line;
if (!gui_init_ok)
return;
-
+
if (!str_start_input[0])
{
snprintf (str_start_input, sizeof (str_start_input), "%c%c%c",
@@ -384,6 +424,12 @@ gui_bar_window_draw (struct t_gui_bar_window *bar_window,
bar_window->cursor_x = -1;
bar_window->cursor_y = -1;
+ /* remove coords */
+ gui_bar_window_coords_free (bar_window);
+ index_item = -1;
+ index_subitem = -1;
+ index_line = 0;
+
filling = gui_bar_get_filling (bar_window->bar);
content = gui_bar_window_content_get_with_filling (bar_window, window);
@@ -547,7 +593,10 @@ gui_bar_window_draw (struct t_gui_bar_window *bar_window,
{
if (!gui_bar_window_print_string (bar_window, filling,
&x, &y,
- items[line], 1, 1))
+ items[line], 1, 1,
+ &index_item,
+ &index_subitem,
+ &index_line))
{
some_data_not_displayed = 1;
}
@@ -571,7 +620,10 @@ gui_bar_window_draw (struct t_gui_bar_window *bar_window,
while (x < bar_window->width)
{
gui_bar_window_print_string (bar_window, filling,
- &x, &y, " ", 0, 0);
+ &x, &y, " ", 0, 0,
+ &index_item,
+ &index_subitem,
+ &index_line);
}
}
@@ -618,7 +670,7 @@ gui_bar_window_draw (struct t_gui_bar_window *bar_window,
CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_FG]),
CONFIG_COLOR(bar_window->bar->options[GUI_BAR_OPTION_COLOR_BG]));
}
-
+
/*
* move cursor if it was asked in an item content (input_text does that
* to move cursor in user input text)
@@ -632,7 +684,12 @@ gui_bar_window_draw (struct t_gui_bar_window *bar_window,
x = bar_window->width - 2;
wmove (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar, y, x);
wrefresh (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar);
- move (bar_window->cursor_y, bar_window->cursor_x);
+ if (!gui_cursor_mode)
+ {
+ gui_window_cursor_x = bar_window->cursor_x;
+ gui_window_cursor_y = bar_window->cursor_y;
+ move (bar_window->cursor_y, bar_window->cursor_x);
+ }
}
else
wnoutrefresh (GUI_BAR_WINDOW_OBJECTS(bar_window)->win_bar);
diff --git a/src/gui/curses/gui-curses-chat.c b/src/gui/curses/gui-curses-chat.c
index 6c380f051..b295abe61 100644
--- a/src/gui/curses/gui-curses-chat.c
+++ b/src/gui/curses/gui-curses-chat.c
@@ -209,6 +209,8 @@ gui_chat_string_next_char (struct t_gui_window *window,
case GUI_COLOR_BAR_START_INPUT_CHAR:
case GUI_COLOR_BAR_START_INPUT_HIDDEN_CHAR:
case GUI_COLOR_BAR_MOVE_CURSOR_CHAR:
+ case GUI_COLOR_BAR_START_ITEM:
+ case GUI_COLOR_BAR_START_LINE_ITEM:
string++;
break;
}
diff --git a/src/gui/curses/gui-curses-key.c b/src/gui/curses/gui-curses-key.c
index 731a66ee5..d1b7c222c 100644
--- a/src/gui/curses/gui-curses-key.c
+++ b/src/gui/curses/gui-curses-key.c
@@ -40,8 +40,10 @@
#include "../gui-key.h"
#include "../gui-buffer.h"
#include "../gui-color.h"
-#include "../gui-input.h"
+#include "../gui-cursor.h"
#include "../gui-completion.h"
+#include "../gui-input.h"
+#include "../gui-mouse.h"
#include "../gui-window.h"
#include "gui-curses.h"
@@ -79,145 +81,193 @@ gui_key_default_bindings (int context)
int i;
char key_str[32], command[32];
- switch (context)
+ if (context == GUI_KEY_CONTEXT_DEFAULT)
{
- case GUI_KEY_CONTEXT_DEFAULT:
- BIND(/* RC */ "ctrl-M", "/input return");
- BIND(/* RC */ "ctrl-J", "/input return");
- BIND(/* tab */ "ctrl-I", "/input complete_next");
- BIND(/* s-tab */ "meta2-Z", "/input complete_previous");
- BIND(/* ^R */ "ctrl-R", "/input search_text");
- BIND(/* basckpace */ "ctrl-H", "/input delete_previous_char");
- BIND(/* basckpace */ "ctrl-?", "/input delete_previous_char");
- BIND(/* ^_ */ "ctrl-_", "/input undo");
- BIND(/* m-_ */ "meta-_", "/input redo");
- BIND(/* del */ "meta2-3~", "/input delete_next_char");
- BIND(/* ^D */ "ctrl-D", "/input delete_next_char");
- BIND(/* ^W */ "ctrl-W", "/input delete_previous_word");
- BIND(/* ^X */ "ctrl-X", "/input switch_active_buffer");
- BIND(/* m-d */ "meta-d", "/input delete_next_word");
- BIND(/* ^K */ "ctrl-K", "/input delete_end_of_line");
- BIND(/* m-r */ "meta-r", "/input delete_line");
- BIND(/* ^T */ "ctrl-T", "/input transpose_chars");
- BIND(/* ^U */ "ctrl-U", "/input delete_beginning_of_line");
- BIND(/* ^Y */ "ctrl-Y", "/input clipboard_paste");
- BIND(/* home */ "meta2-1~", "/input move_beginning_of_line");
- BIND(/* home */ "meta2-H", "/input move_beginning_of_line");
- BIND(/* home */ "meta2-7~", "/input move_beginning_of_line");
- BIND(/* home */ "meta-OH", "/input move_beginning_of_line");
- BIND(/* ^A */ "ctrl-A", "/input move_beginning_of_line");
- BIND(/* end */ "meta2-4~", "/input move_end_of_line");
- BIND(/* end */ "meta2-F", "/input move_end_of_line");
- BIND(/* end */ "meta2-8~", "/input move_end_of_line");
- BIND(/* end */ "meta-OF", "/input move_end_of_line");
- BIND(/* ^E */ "ctrl-E", "/input move_end_of_line");
- BIND(/* left */ "meta2-D", "/input move_previous_char");
- BIND(/* ^B */ "ctrl-B", "/input move_previous_char");
- BIND(/* right */ "meta2-C", "/input move_next_char");
- BIND(/* ^F */ "ctrl-F", "/input move_next_char");
- BIND(/* m-b */ "meta-b", "/input move_previous_word");
- BIND(/* ^left */ "meta-Od", "/input move_previous_word");
- BIND(/* ^left */ "meta-OD", "/input move_previous_word");
- BIND(/* m-f */ "meta-f", "/input move_next_word");
- BIND(/* ^right */ "meta-Oc", "/input move_next_word");
- BIND(/* ^right */ "meta-OC", "/input move_next_word");
- BIND(/* up */ "meta2-A", "/input history_previous");
- BIND(/* down */ "meta2-B", "/input history_next");
- BIND(/* ^up */ "meta-Oa", "/input history_global_previous");
- BIND(/* ^up */ "meta-OA", "/input history_global_previous");
- BIND(/* ^up */ "meta2-1;5A", "/input history_global_previous");
- BIND(/* ^down */ "meta-Ob", "/input history_global_next");
- BIND(/* ^down */ "meta-OB", "/input history_global_next");
- BIND(/* ^down */ "meta2-1;5B", "/input history_global_next");
- BIND(/* m-a */ "meta-a", "/input jump_smart");
- BIND(/* m-j,m-l */ "meta-jmeta-l", "/input jump_last_buffer");
- BIND(/* m-j,m-r */ "meta-jmeta-r", "/server raw");
- BIND(/* m-j,m-s */ "meta-jmeta-s", "/server jump");
- BIND(/* m-h */ "meta-h", "/input hotlist_clear");
- BIND(/* m-k */ "meta-k", "/input grab_key_command");
- BIND(/* m-u */ "meta-u", "/input scroll_unread");
- BIND(/* ^S^U */ "ctrl-Sctrl-U", "/input set_unread");
- BIND(/* ^Cb */ "ctrl-Cb", "/input insert \\x02");
- BIND(/* ^Cc */ "ctrl-Cc", "/input insert \\x03");
- BIND(/* ^Ci */ "ctrl-Ci", "/input insert \\x1D");
- BIND(/* ^Co */ "ctrl-Co", "/input insert \\x0F");
- BIND(/* ^Cr */ "ctrl-Cr", "/input insert \\x12");
- BIND(/* ^Cu */ "ctrl-Cu", "/input insert \\x15");
- BIND(/* m-right */ "meta-meta2-C", "/buffer +1");
- BIND(/* m-right */ "meta2-1;3C", "/buffer +1");
- BIND(/* m-down */ "meta-meta2-B", "/buffer +1");
- BIND(/* m-down */ "meta2-1;3B", "/buffer +1");
- BIND(/* F6 */ "meta2-17~", "/buffer +1");
- BIND(/* ^N */ "ctrl-N", "/buffer +1");
- BIND(/* m-left */ "meta-meta2-D", "/buffer -1");
- BIND(/* m-left */ "meta2-1;3D", "/buffer -1");
- BIND(/* m-up */ "meta-meta2-A", "/buffer -1");
- BIND(/* m-up */ "meta2-1;3A", "/buffer -1");
- BIND(/* F5 */ "meta2-15~", "/buffer -1");
- BIND(/* ^P */ "ctrl-P", "/buffer -1");
- BIND(/* pgup */ "meta2-5~", "/window page_up");
- BIND(/* pgup */ "meta2-I", "/window page_up");
- BIND(/* pgdn */ "meta2-6~", "/window page_down");
- BIND(/* pgdn */ "meta2-G", "/window page_down");
- BIND(/* m-pgup */ "meta-meta2-5~", "/window scroll_up");
- BIND(/* m-pgup */ "meta2-5;3~", "/window scroll_up");
- BIND(/* m-pgdn */ "meta-meta2-6~", "/window scroll_down");
- BIND(/* m-pgdn */ "meta2-6;3~", "/window scroll_down");
- BIND(/* m-home */ "meta-meta2-1~", "/window scroll_top");
- BIND(/* m-home */ "meta-meta2-7~", "/window scroll_top");
- BIND(/* m-end */ "meta-meta2-4~", "/window scroll_bottom");
- BIND(/* m-end */ "meta-meta2-8~", "/window scroll_bottom");
- BIND(/* m-n */ "meta-n", "/window scroll_next_highlight");
- BIND(/* m-p */ "meta-p", "/window scroll_previous_highlight");
- BIND(/* F9 */ "meta2-20~", "/bar scroll title * x-50%");
- BIND(/* F10 */ "meta2-21~", "/bar scroll title * x+50%");
- BIND(/* F11 */ "meta2-23~", "/bar scroll nicklist * y-100%");
- BIND(/* F12 */ "meta2-24~", "/bar scroll nicklist * y+100%");
- BIND(/* m-F11 */ "meta-meta2-23~", "/bar scroll nicklist * yb");
- BIND(/* m-F12 */ "meta-meta2-24~", "/bar scroll nicklist * ye");
- BIND(/* ^L */ "ctrl-L", "/window refresh");
- BIND(/* F7 */ "meta2-18~", "/window -1");
- BIND(/* F8 */ "meta2-19~", "/window +1");
- BIND(/* m-w,m-up */ "meta-wmeta-meta2-A", "/window up");
- BIND(/* m-w,m-up */ "meta-wmeta2-1;3A", "/window up");
- BIND(/* m-w,m-down */ "meta-wmeta-meta2-B", "/window down");
- BIND(/* m-w,m-down */ "meta-wmeta2-1;3B", "/window down");
- BIND(/* m-w,m-right */ "meta-wmeta-meta2-C", "/window right");
- BIND(/* m-w,m-right */ "meta-wmeta2-1;3C", "/window right");
- BIND(/* m-w,m-left */ "meta-wmeta-meta2-D", "/window left");
- BIND(/* m-w,m-left */ "meta-wmeta2-1;3D", "/window left");
- BIND(/* m-w,m-b */ "meta-wmeta-b", "/window balance");
- BIND(/* m-w,m-s */ "meta-wmeta-s", "/window swap");
- BIND(/* m-z */ "meta-z", "/window zoom");
- BIND(/* m-= */ "meta-=", "/filter toggle");
- BIND(/* m-0 */ "meta-0", "/buffer *10");
- BIND(/* m-1 */ "meta-1", "/buffer *1");
- BIND(/* m-2 */ "meta-2", "/buffer *2");
- BIND(/* m-3 */ "meta-3", "/buffer *3");
- BIND(/* m-4 */ "meta-4", "/buffer *4");
- BIND(/* m-5 */ "meta-5", "/buffer *5");
- BIND(/* m-6 */ "meta-6", "/buffer *6");
- BIND(/* m-7 */ "meta-7", "/buffer *7");
- BIND(/* m-8 */ "meta-8", "/buffer *8");
- BIND(/* m-9 */ "meta-9", "/buffer *9");
- BIND(/* m-< */ "meta-<", "/input jump_previously_visited_buffer");
- BIND(/* m-> */ "meta->", "/input jump_next_visited_buffer");
-
- /* bind meta-j + {01..99} to switch to buffers # > 10 */
- for (i = 1; i < 100; i++)
- {
- sprintf (key_str, "meta-j%02d", i);
- sprintf (command, "/buffer %d", i);
- BIND(key_str, command);
- }
- break;
- case GUI_KEY_CONTEXT_SEARCH:
- BIND(/* RC */ "ctrl-M", "/input search_stop");
- BIND(/* RC */ "ctrl-J", "/input search_stop");
- BIND(/* ^R */ "ctrl-R", "/input search_switch_case");
- BIND(/* up */ "meta2-A", "/input search_previous");
- BIND(/* down */ "meta2-B", "/input search_next");
- break;
+ BIND(/* Enter */ "ctrl-M", "/input return");
+ BIND(/* Enter */ "ctrl-J", "/input return");
+ BIND(/* tab */ "ctrl-I", "/input complete_next");
+ BIND(/* s-tab */ "meta2-Z", "/input complete_previous");
+ BIND(/* ^R */ "ctrl-R", "/input search_text");
+ BIND(/* basckpace */ "ctrl-H", "/input delete_previous_char");
+ BIND(/* basckpace */ "ctrl-?", "/input delete_previous_char");
+ BIND(/* ^_ */ "ctrl-_", "/input undo");
+ BIND(/* m-_ */ "meta-_", "/input redo");
+ BIND(/* del */ "meta2-3~", "/input delete_next_char");
+ BIND(/* ^D */ "ctrl-D", "/input delete_next_char");
+ BIND(/* ^W */ "ctrl-W", "/input delete_previous_word");
+ BIND(/* ^X */ "ctrl-X", "/input switch_active_buffer");
+ BIND(/* m-d */ "meta-d", "/input delete_next_word");
+ BIND(/* ^K */ "ctrl-K", "/input delete_end_of_line");
+ BIND(/* m-r */ "meta-r", "/input delete_line");
+ BIND(/* ^T */ "ctrl-T", "/input transpose_chars");
+ BIND(/* ^U */ "ctrl-U", "/input delete_beginning_of_line");
+ BIND(/* ^Y */ "ctrl-Y", "/input clipboard_paste");
+ BIND(/* home */ "meta2-1~", "/input move_beginning_of_line");
+ BIND(/* home */ "meta2-H", "/input move_beginning_of_line");
+ BIND(/* home */ "meta2-7~", "/input move_beginning_of_line");
+ BIND(/* home */ "meta-OH", "/input move_beginning_of_line");
+ BIND(/* ^A */ "ctrl-A", "/input move_beginning_of_line");
+ BIND(/* end */ "meta2-4~", "/input move_end_of_line");
+ BIND(/* end */ "meta2-F", "/input move_end_of_line");
+ BIND(/* end */ "meta2-8~", "/input move_end_of_line");
+ BIND(/* end */ "meta-OF", "/input move_end_of_line");
+ BIND(/* ^E */ "ctrl-E", "/input move_end_of_line");
+ BIND(/* left */ "meta2-D", "/input move_previous_char");
+ BIND(/* ^B */ "ctrl-B", "/input move_previous_char");
+ BIND(/* right */ "meta2-C", "/input move_next_char");
+ BIND(/* ^F */ "ctrl-F", "/input move_next_char");
+ BIND(/* m-b */ "meta-b", "/input move_previous_word");
+ BIND(/* ^left */ "meta-Od", "/input move_previous_word");
+ BIND(/* ^left */ "meta-OD", "/input move_previous_word");
+ BIND(/* m-f */ "meta-f", "/input move_next_word");
+ BIND(/* ^right */ "meta-Oc", "/input move_next_word");
+ BIND(/* ^right */ "meta-OC", "/input move_next_word");
+ BIND(/* up */ "meta2-A", "/input history_previous");
+ BIND(/* down */ "meta2-B", "/input history_next");
+ BIND(/* ^up */ "meta-Oa", "/input history_global_previous");
+ BIND(/* ^up */ "meta-OA", "/input history_global_previous");
+ BIND(/* ^up */ "meta2-1;5A", "/input history_global_previous");
+ BIND(/* ^down */ "meta-Ob", "/input history_global_next");
+ BIND(/* ^down */ "meta-OB", "/input history_global_next");
+ BIND(/* ^down */ "meta2-1;5B", "/input history_global_next");
+ BIND(/* m-a */ "meta-a", "/input jump_smart");
+ BIND(/* m-j,m-l */ "meta-jmeta-l", "/input jump_last_buffer");
+ BIND(/* m-j,m-r */ "meta-jmeta-r", "/server raw");
+ BIND(/* m-j,m-s */ "meta-jmeta-s", "/server jump");
+ BIND(/* m-h */ "meta-h", "/input hotlist_clear");
+ BIND(/* m-k */ "meta-k", "/input grab_key_command");
+ BIND(/* m-u */ "meta-u", "/input scroll_unread");
+ BIND(/* ^S^U */ "ctrl-Sctrl-U", "/input set_unread");
+ BIND(/* ^Cb */ "ctrl-Cb", "/input insert \\x02");
+ BIND(/* ^Cc */ "ctrl-Cc", "/input insert \\x03");
+ BIND(/* ^Ci */ "ctrl-Ci", "/input insert \\x1D");
+ BIND(/* ^Co */ "ctrl-Co", "/input insert \\x0F");
+ BIND(/* ^Cr */ "ctrl-Cr", "/input insert \\x12");
+ BIND(/* ^Cu */ "ctrl-Cu", "/input insert \\x15");
+ BIND(/* m-right */ "meta-meta2-C", "/buffer +1");
+ BIND(/* m-right */ "meta2-1;3C", "/buffer +1");
+ BIND(/* m-down */ "meta-meta2-B", "/buffer +1");
+ BIND(/* m-down */ "meta2-1;3B", "/buffer +1");
+ BIND(/* F6 */ "meta2-17~", "/buffer +1");
+ BIND(/* ^N */ "ctrl-N", "/buffer +1");
+ BIND(/* m-left */ "meta-meta2-D", "/buffer -1");
+ BIND(/* m-left */ "meta2-1;3D", "/buffer -1");
+ BIND(/* m-up */ "meta-meta2-A", "/buffer -1");
+ BIND(/* m-up */ "meta2-1;3A", "/buffer -1");
+ BIND(/* F5 */ "meta2-15~", "/buffer -1");
+ BIND(/* ^P */ "ctrl-P", "/buffer -1");
+ BIND(/* pgup */ "meta2-5~", "/window page_up");
+ BIND(/* pgup */ "meta2-I", "/window page_up");
+ BIND(/* pgdn */ "meta2-6~", "/window page_down");
+ BIND(/* pgdn */ "meta2-G", "/window page_down");
+ BIND(/* m-pgup */ "meta-meta2-5~", "/window scroll_up");
+ BIND(/* m-pgup */ "meta2-5;3~", "/window scroll_up");
+ BIND(/* m-pgdn */ "meta-meta2-6~", "/window scroll_down");
+ BIND(/* m-pgdn */ "meta2-6;3~", "/window scroll_down");
+ BIND(/* m-home */ "meta-meta2-1~", "/window scroll_top");
+ BIND(/* m-home */ "meta-meta2-7~", "/window scroll_top");
+ BIND(/* m-end */ "meta-meta2-4~", "/window scroll_bottom");
+ BIND(/* m-end */ "meta-meta2-8~", "/window scroll_bottom");
+ BIND(/* m-n */ "meta-n", "/window scroll_next_highlight");
+ BIND(/* m-p */ "meta-p", "/window scroll_previous_highlight");
+ BIND(/* F9 */ "meta2-20~", "/bar scroll title * -30%");
+ BIND(/* F10 */ "meta2-21~", "/bar scroll title * +30%");
+ BIND(/* F11 */ "meta2-23~", "/bar scroll nicklist * -100%");
+ BIND(/* F12 */ "meta2-24~", "/bar scroll nicklist * +100%");
+ BIND(/* m-F11 */ "meta-meta2-23~", "/bar scroll nicklist * b");
+ BIND(/* m-F12 */ "meta-meta2-24~", "/bar scroll nicklist * e");
+ BIND(/* ^L */ "ctrl-L", "/window refresh");
+ BIND(/* F7 */ "meta2-18~", "/window -1");
+ BIND(/* F8 */ "meta2-19~", "/window +1");
+ BIND(/* m-w,m-up */ "meta-wmeta-meta2-A", "/window up");
+ BIND(/* m-w,m-up */ "meta-wmeta2-1;3A", "/window up");
+ BIND(/* m-w,m-down */ "meta-wmeta-meta2-B", "/window down");
+ BIND(/* m-w,m-down */ "meta-wmeta2-1;3B", "/window down");
+ BIND(/* m-w,m-right */ "meta-wmeta-meta2-C", "/window right");
+ BIND(/* m-w,m-right */ "meta-wmeta2-1;3C", "/window right");
+ BIND(/* m-w,m-left */ "meta-wmeta-meta2-D", "/window left");
+ BIND(/* m-w,m-left */ "meta-wmeta2-1;3D", "/window left");
+ BIND(/* m-w,m-b */ "meta-wmeta-b", "/window balance");
+ BIND(/* m-w,m-s */ "meta-wmeta-s", "/window swap");
+ BIND(/* m-z */ "meta-z", "/window zoom");
+ BIND(/* m-= */ "meta-=", "/filter toggle");
+ BIND(/* m-0 */ "meta-0", "/buffer *10");
+ BIND(/* m-1 */ "meta-1", "/buffer *1");
+ BIND(/* m-2 */ "meta-2", "/buffer *2");
+ BIND(/* m-3 */ "meta-3", "/buffer *3");
+ BIND(/* m-4 */ "meta-4", "/buffer *4");
+ BIND(/* m-5 */ "meta-5", "/buffer *5");
+ BIND(/* m-6 */ "meta-6", "/buffer *6");
+ BIND(/* m-7 */ "meta-7", "/buffer *7");
+ BIND(/* m-8 */ "meta-8", "/buffer *8");
+ BIND(/* m-9 */ "meta-9", "/buffer *9");
+ BIND(/* m-< */ "meta-<", "/input jump_previously_visited_buffer");
+ BIND(/* m-> */ "meta->", "/input jump_next_visited_buffer");
+ BIND(/* mouse */ "meta2-M", "/mouse grab");
+ BIND(/* m-m */ "meta-m", "/mouse toggle");
+
+ /* bind meta-j + {01..99} to switch to buffers # > 10 */
+ for (i = 1; i < 100; i++)
+ {
+ sprintf (key_str, "meta-j%02d", i);
+ sprintf (command, "/buffer %d", i);
+ BIND(key_str, command);
+ }
+ }
+ else if (context == GUI_KEY_CONTEXT_SEARCH)
+ {
+ BIND(/* Enter */ "ctrl-M", "/input search_stop");
+ BIND(/* Enter */ "ctrl-J", "/input search_stop");
+ BIND(/* ^R */ "ctrl-R", "/input search_switch_case");
+ BIND(/* up */ "meta2-A", "/input search_previous");
+ BIND(/* down */ "meta2-B", "/input search_next");
+ }
+ else if (context == GUI_KEY_CONTEXT_CURSOR)
+ {
+ BIND(/* Enter */ "ctrl-M", "/cursor stop");
+ BIND(/* Enter */ "ctrl-J", "/cursor stop");
+ BIND(/* up */ "meta2-A", "/cursor move up");
+ BIND(/* down */ "meta2-B", "/cursor move down");
+ BIND(/* left */ "meta2-D", "/cursor move left");
+ BIND(/* right */ "meta2-C", "/cursor move right");
+ BIND(/* m-up */ "meta-meta2-A", "/cursor move area_up");
+ BIND(/* m-up */ "meta2-1;3A", "/cursor move area_up");
+ BIND(/* m-down */ "meta-meta2-B", "/cursor move area_down");
+ BIND(/* m-down */ "meta2-1;3B", "/cursor move area_down");
+ BIND(/* m-left */ "meta-meta2-D", "/cursor move area_left");
+ BIND(/* m-left */ "meta2-1;3D", "/cursor move area_left");
+ BIND(/* m-right */ "meta-meta2-C", "/cursor move area_right");
+ BIND(/* m-right */ "meta2-1;3C", "/cursor move area_right");
+ BIND(/* b */ "@item(buffer_nicklist):b", "/ban ${nick}");
+ BIND(/* k */ "@item(buffer_nicklist):k", "/kick ${nick}");
+ BIND(/* K */ "@item(buffer_nicklist):K", "/kickban ${nick}");
+ BIND(/* q */ "@item(buffer_nicklist):q", "/query ${nick};/cursor stop");
+ BIND(/* w */ "@item(buffer_nicklist):w", "/whois ${nick}");
+ }
+ else if (context == GUI_KEY_CONTEXT_MOUSE)
+ {
+ /* mouse events on chat area */
+ BIND("@chat:button1-gesture-left", "/buffer -1");
+ BIND("@chat:button1-gesture-right", "/buffer +1");
+ BIND("@chat:button1-gesture-left-long", "/buffer 1");
+ BIND("@chat:button1-gesture-right-long", "/input jump_last_buffer");
+ BIND("@chat:wheelup", "/window scroll_up");
+ BIND("@chat:wheeldown", "/window scroll_down");
+ /* mouse events on nicklist */
+ BIND("@bar(nicklist):button1-gesture-up", "/bar scroll nicklist * -100%");
+ BIND("@bar(nicklist):button1-gesture-down", "/bar scroll nicklist * +100%");
+ BIND("@bar(nicklist):button1-gesture-up-long", "/bar scroll nicklist * b");
+ BIND("@bar(nicklist):button1-gesture-down-long", "/bar scroll nicklist * e");
+ BIND("@item(buffer_nicklist):button1", "/query ${nick}");
+ BIND("@item(buffer_nicklist):button2", "/whois ${nick}");
+ BIND("@item(buffer_nicklist):button1-gesture-left", "/kick ${nick}");
+ BIND("@item(buffer_nicklist):button1-gesture-left-long", "/kickban ${nick}");
+ BIND("@item(buffer_nicklist):button2-gesture-left", "/ban ${nick}");
+ /* mouse wheel on any bar */
+ BIND("@bar(*):wheelup", "/bar scroll ${_bar_name} * -10%");
+ BIND("@bar(*):wheeldown", "/bar scroll ${_bar_name} * +10%");
+ /* middle click to enable cursor mode at position */
+ BIND("@*:button3", "/cursor go ${_x},${_y}");
}
}
@@ -246,16 +296,22 @@ gui_key_flush ()
insert_ok = 1;
- if (key < 32)
+ if (gui_mouse_grab)
+ {
+ insert_ok = 0;
+ key_str[0] = (char) key;
+ key_str[1] = '\0';
+ }
+ else if (key < 32)
{
insert_ok = 0;
- key_str[0] = '^';
+ key_str[0] = '\x01';
key_str[1] = (char) key + '@';
key_str[2] = '\0';
}
else if (key == 127)
{
- key_str[0] = '^';
+ key_str[0] = '\x01';
key_str[1] = '?';
key_str[2] = '\0';
}
@@ -339,12 +395,6 @@ gui_key_flush ()
}
}
- if (strcmp (key_str, "^") == 0)
- {
- key_str[1] = '^';
- key_str[2] = '\0';
- }
-
hook_signal_send ("key_pressed",
WEECHAT_HOOK_SIGNAL_STRING, key_str);
@@ -354,11 +404,9 @@ gui_key_flush ()
else
input_old = NULL;
- if ((gui_key_pressed (key_str) != 0) && (insert_ok))
+ if ((gui_key_pressed (key_str) != 0) && (insert_ok)
+ && (!gui_cursor_mode))
{
- if (strcmp (key_str, "^^") == 0)
- key_str[1] = '\0';
-
gui_buffer_undo_snap (gui_current_window->buffer);
gui_input_insert_string (gui_current_window->buffer,
key_str, -1);
@@ -405,9 +453,6 @@ gui_key_flush ()
free (input_old);
}
- if (gui_key_grab && (gui_key_grab_count > 0))
- gui_key_grab_end ();
-
gui_key_buffer_reset ();
}
}
diff --git a/src/gui/curses/gui-curses-main.c b/src/gui/curses/gui-curses-main.c
index ce95938a1..b95961fc3 100644
--- a/src/gui/curses/gui-curses-main.c
+++ b/src/gui/curses/gui-curses-main.c
@@ -48,10 +48,12 @@
#include "../gui-buffer.h"
#include "../gui-chat.h"
#include "../gui-color.h"
+#include "../gui-cursor.h"
#include "../gui-filter.h"
#include "../gui-input.h"
#include "../gui-layout.h"
#include "../gui-history.h"
+#include "../gui-mouse.h"
#include "../gui-nicklist.h"
#include "../gui-window.h"
#include "gui-curses.h"
@@ -149,7 +151,7 @@ gui_main_init ()
/*
* create bar windows for root bars (they were read from config,
- * but no window was created (GUI was not initialized)
+ * but no window was created, GUI was not initialized)
*/
for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
{
@@ -166,6 +168,11 @@ gui_main_init ()
gui_bar_window_create_win (ptr_bar_win);
}
}
+
+ if (CONFIG_BOOLEAN(config_look_mouse))
+ gui_mouse_enable ();
+ else
+ gui_mouse_disable ();
}
/*
@@ -277,7 +284,6 @@ gui_main_refreshs ()
}
/* refresh bars if needed */
-
for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
{
if (ptr_bar->bar_refresh_needed)
@@ -285,6 +291,10 @@ gui_main_refreshs ()
gui_bar_draw (ptr_bar);
}
}
+
+ /* move cursor (for cursor mode) */
+ if (gui_cursor_mode)
+ gui_window_move_cursor ();
}
/*
@@ -387,6 +397,9 @@ gui_main_end (int clean_exit)
gui_main_refreshs ();
}
+ /* disable mouse */
+ gui_mouse_disable ();
+
/* remove bar items and bars */
gui_bar_item_end ();
gui_bar_free_all ();
diff --git a/src/gui/curses/gui-curses-mouse.c b/src/gui/curses/gui-curses-mouse.c
new file mode 100644
index 000000000..7ca78c77b
--- /dev/null
+++ b/src/gui/curses/gui-curses-mouse.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2011 Sebastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * gui-curses-mouse.c: mouse functions for Curses GUI
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "../../core/weechat.h"
+#include "../../core/wee-config.h"
+#include "../gui-chat.h"
+#include "../gui-mouse.h"
+
+
+/*
+ * gui_mouse_enable: enable mouse
+ */
+
+void
+gui_mouse_enable ()
+{
+ gui_mouse_enabled = 1;
+ fprintf (stderr, "\033[?1005h\033[?1000h\033[?1002h");
+}
+
+/*
+ * gui_mouse_disable: disable mouse
+ */
+
+void
+gui_mouse_disable ()
+{
+ gui_mouse_enabled = 0;
+ fprintf (stderr, "\033[?1002l\033[?1000l\033[?1005l");
+}
+
+/*
+ * gui_mouse_display_state: display state of mouse
+ */
+
+void
+gui_mouse_display_state ()
+{
+ gui_chat_printf (NULL,
+ (CONFIG_BOOLEAN(config_look_mouse)) ?
+ _("Mouse is enabled") : _("Mouse is disabled"));
+}
+
+/*
+ * gui_mouse_grab_init: init "grab mouse" mode
+ */
+
+void
+gui_mouse_grab_init ()
+{
+ gui_mouse_grab = 1;
+}
+
+/*
+ * gui_mouse_grab_code2key: get key name with a mouse code
+ */
+
+const char *
+gui_mouse_grab_code2key (const char *code)
+{
+ int x, y;
+ double diff_x, diff_y, distance, angle, pi4;
+ static char key[128];
+ char button[2];
+
+ /* mouse code must have at least 3 chars */
+ if (strlen (code) < 3)
+ return NULL;
+
+ key[0] = '\0';
+
+ /* ignore code '#' (button released) if it's received as first event */
+ if ((gui_mouse_event_index == 0) && (code[0] == '#'))
+ return key;
+
+ /* get coordinates and button */
+ x = ((unsigned char)code[1]) - 33;
+ if (x < 0)
+ x = 0;
+ y = ((unsigned char)code[2]) - 33;
+ if (y < 0)
+ y = 0;
+ gui_mouse_event_x[gui_mouse_event_index] = x;
+ gui_mouse_event_y[gui_mouse_event_index] = y;
+ if (gui_mouse_event_index == 0)
+ gui_mouse_event_button = code[0];
+
+ if (gui_mouse_event_index == 0)
+ gui_mouse_event_index = 1;
+
+ if (code[0] == '`')
+ {
+ strcat (key, "wheelup");
+ return key;
+ }
+
+ if (code[0] == 'a')
+ {
+ strcat (key, "wheeldown");
+ return key;
+ }
+
+ if (code[0] != '#')
+ return key;
+
+ /* add button/wheel */
+ switch (gui_mouse_event_button)
+ {
+ case ' ': /* left button pressed */
+ strcat (key, "button1");
+ break;
+ case '"': /* right button pressed */
+ strcat (key, "button2");
+ break;
+ case '!': /* middle button pressed */
+ strcat (key, "button3");
+ break;
+ default: /* extra buttons: button4..button9 */
+ if ((gui_mouse_event_button >= 'b')
+ && (gui_mouse_event_button <= 'g'))
+ {
+ button[0] = gui_mouse_event_button - ('b' - '4');
+ button[1] = '\0';
+ strcat (key, "button");
+ strcat (key, button);
+ }
+ break;
+ }
+
+ /*
+ * Mouse gesture: if (x,y) on release is different from (x,y) on click,
+ * compute distance and angle between 2 points.
+ *
+ * Distance: sqrt((x2-x1)²+(y2-y1)²)
+ * Angle : atan2(x1-x1, y2-y1)
+ *
+ * Angle:
+ *
+ * 3.14 pi
+ * /\
+ * -2.35 || 2.35 3/4 * pi
+ * ||
+ * -1.57 /----++----\ 1.57 1/2 * pi
+ * \----++----/
+ * ||
+ * -0.78 || 0.78 1/4 * pi
+ * \/
+ * 0.00 0
+ *
+ * Possible returned gestures are:
+ *
+ * key name | dist. | angle
+ * ---------------------------+-------+--------------------------
+ * buttonX-gesture-up | 3..19 | -2.35..-3.14 + 2.35..3.14
+ * buttonX-gesture-up-long | >= 20 |
+ * buttonX-gesture-down | 3..19 | -0.78..0.78
+ * buttonX-gesture-down-long | >= 20 |
+ * buttonX-gesture-left | 3..39 | -0.78..-2.35
+ * buttonX-gesture-left-long | >= 40 |
+ * buttonX-gesture-right | 3..39 | 0.78..2.35
+ * buttonX-gesture-right-long | >= 40 |
+ */
+
+ distance = 0;
+ if (key[0]
+ && ((gui_mouse_event_x[0] != gui_mouse_event_x[1])
+ || (gui_mouse_event_y[0] != gui_mouse_event_y[1])))
+ {
+ diff_x = gui_mouse_event_x[1] - gui_mouse_event_x[0];
+ diff_y = gui_mouse_event_y[1] - gui_mouse_event_y[0];
+ distance = sqrt ((diff_x * diff_x) + (diff_y * diff_y));
+ if (distance >= 3)
+ {
+ angle = atan2 ((double)(gui_mouse_event_x[1] - gui_mouse_event_x[0]),
+ (double)(gui_mouse_event_y[1] - gui_mouse_event_y[0]));
+ pi4 = 3.14159265358979 / 4;
+ if ((angle <= pi4 * (-3)) || (angle >= pi4 * 3))
+ {
+ strcat (key, "-gesture-up");
+ if (distance >= 20)
+ strcat (key, "-long");
+ }
+ else if ((angle >= pi4 * (-1)) && (angle <= pi4))
+ {
+ strcat (key, "-gesture-down");
+ if (distance >= 20)
+ strcat (key, "-long");
+ }
+ else if ((angle >= pi4 * (-3)) && (angle <= pi4 * (-1)))
+ {
+ strcat (key, "-gesture-left");
+ if (distance >= 40)
+ strcat (key, "-long");
+ }
+ else if ((angle >= pi4) && (angle <= pi4 * 3))
+ {
+ strcat (key, "-gesture-right");
+ if (distance >= 40)
+ strcat (key, "-long");
+ }
+ }
+ }
+
+ return key;
+}
+
+/*
+ * gui_mouse_grab_end: end "grab mouse" mode
+ */
+
+void
+gui_mouse_grab_end ()
+{
+ gui_mouse_grab = 0;
+}
diff --git a/src/gui/curses/gui-curses-window.c b/src/gui/curses/gui-curses-window.c
index 3e2f0d90f..bac2ecfd0 100644
--- a/src/gui/curses/gui-curses-window.c
+++ b/src/gui/curses/gui-curses-window.c
@@ -46,6 +46,7 @@
#include "../gui-buffer.h"
#include "../gui-chat.h"
#include "../gui-color.h"
+#include "../gui-cursor.h"
#include "../gui-hotlist.h"
#include "../gui-input.h"
#include "../gui-key.h"
@@ -1514,7 +1515,8 @@ gui_window_refresh_windows ()
for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
{
- if (CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_ROOT)
+ if ((CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_ROOT)
+ && !CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
{
gui_bar_window_calculate_pos_size (ptr_bar->bar_window, NULL);
gui_bar_window_create_win (ptr_bar->bar_window);
@@ -2197,6 +2199,20 @@ gui_window_set_title (const char *title)
}
/*
+ * gui_window_move_cursor: move cursor on screen (for cursor mode)
+ */
+
+void
+gui_window_move_cursor ()
+{
+ if (gui_cursor_mode)
+ {
+ move (gui_cursor_y, gui_cursor_x);
+ refresh ();
+ }
+}
+
+/*
* gui_window_term_display_infos: display some infos about terminal and colors
*/
diff --git a/src/gui/gtk/CMakeLists.txt b/src/gui/gtk/CMakeLists.txt
index d40e6b6f6..e6596205d 100644
--- a/src/gui/gtk/CMakeLists.txt
+++ b/src/gui/gtk/CMakeLists.txt
@@ -25,6 +25,7 @@ gui-gtk-chat.c
gui-gtk-color.c
gui-gtk-key.c
gui-gtk-main.c
+gui-gtk-mouse.c
gui-gtk-term.c
gui-gtk-window.c)
diff --git a/src/gui/gtk/Makefile.am b/src/gui/gtk/Makefile.am
index 6f84e647f..01833e78d 100644
--- a/src/gui/gtk/Makefile.am
+++ b/src/gui/gtk/Makefile.am
@@ -37,6 +37,7 @@ weechat_gtk_SOURCES = gui-gtk-bar-window.c \
gui-gtk-color.c \
gui-gtk-key.c \
gui-gtk-main.c \
+ gui-gtk-mouse.c \
gui-gtk-term.c \
gui-gtk-window.c \
gui-gtk.h
diff --git a/src/gui/gtk/gui-gtk-mouse.c b/src/gui/gtk/gui-gtk-mouse.c
new file mode 100644
index 000000000..8d7533d8d
--- /dev/null
+++ b/src/gui/gtk/gui-gtk-mouse.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 Sebastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * gui-gtk-mouse.c: mouse functions for Gtk GUI
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../../core/weechat.h"
+#include "../gui-mouse.h"
+
+
+/*
+ * gui_mouse_enable: enable mouse
+ */
+
+void
+gui_mouse_enable ()
+{
+ /* This function does nothing in Gtk GUI */
+}
+
+/*
+ * gui_mouse_disable: disable mouse
+ */
+
+void
+gui_mouse_disable ()
+{
+ /* This function does nothing in Gtk GUI */
+}
+
+/*
+ * gui_mouse_display_state: display state of mouse
+ */
+
+void
+gui_mouse_display_state ()
+{
+ /* This function does nothing in Gtk GUI */
+}
+
+/*
+ * gui_mouse_grab_init: init "grab mouse" mode
+ */
+
+void
+gui_mouse_grab_init ()
+{
+ /* This function does nothing in Gtk GUI */
+}
+
+/*
+ * gui_mouse_grab_code2key: get key name with a mouse code
+ */
+
+const char *
+gui_mouse_grab_code2key (const char *code)
+{
+ (void) code;
+
+ /* This function does nothing in Gtk GUI */
+
+ return NULL;
+}
+
+/*
+ * gui_mouse_grab_end: end "grab mouse" mode
+ */
+
+void
+gui_mouse_grab_end ()
+{
+ /* This function does nothing in Gtk GUI */
+}
diff --git a/src/gui/gtk/gui-gtk-window.c b/src/gui/gtk/gui-gtk-window.c
index c7bd94041..baa0dd326 100644
--- a/src/gui/gtk/gui-gtk-window.c
+++ b/src/gui/gtk/gui-gtk-window.c
@@ -849,6 +849,16 @@ gui_window_set_title (const char *title)
}
/*
+ * gui_window_move_cursor: move cursor on screen (for cursor mode)
+ */
+
+void
+gui_window_move_cursor ()
+{
+ /* TODO: write this function for Gtk */
+}
+
+/*
* gui_window_term_display_infos: display some infos about terminal and colors
*/
diff --git a/src/gui/gui-bar-item.c b/src/gui/gui-bar-item.c
index 8a20a65bc..5a6af8448 100644
--- a/src/gui/gui-bar-item.c
+++ b/src/gui/gui-bar-item.c
@@ -47,6 +47,7 @@
#include "gui-chat.h"
#include "gui-color.h"
#include "gui-completion.h"
+#include "gui-cursor.h"
#include "gui-filter.h"
#include "gui-hotlist.h"
#include "gui-key.h"
@@ -131,70 +132,6 @@ gui_bar_item_search (const char *item_name)
}
/*
- * gui_bar_item_valid_char_name: return 1 if char is valid for item name
- * (any letter, digit, "-" or "_")
- * return 0 otherwise
- */
-
-int
-gui_bar_item_valid_char_name (char c)
-{
- return (((c >= 'a') && (c <= 'z'))
- || ((c >= 'A') && (c <= 'Z'))
- || ((c >= '0') && (c <= '9'))
- || (c == '-')
- || (c == '_')) ?
- 1 : 0;
-}
-
-/*
- * gui_bar_item_string_get_item_start: return pointer to beginning of item name
- * (string may contain special delimiters
- * at beginning, which are ignored)
- */
-
-const char *
-gui_bar_item_string_get_item_start (const char *string)
-{
- while (string && string[0])
- {
- if (gui_bar_item_valid_char_name (string[0]))
- break;
- string++;
- }
- if (string && string[0])
- return string;
-
- return NULL;
-}
-
-/*
- * gui_bar_item_string_is_item: return 1 if string is item (string may contain
- * special delimiters at beginning and end of
- * string, which are ignored)
- */
-
-int
-gui_bar_item_string_is_item (const char *string, const char *item_name)
-{
- const char *item_start;
- int length;
-
- item_start = gui_bar_item_string_get_item_start (string);
- if (!item_start)
- return 0;
-
- length = strlen (item_name);
- if (strncmp (item_start, item_name, length) == 0)
- {
- if (!gui_bar_item_valid_char_name (item_start[length]))
- return 1;
- }
-
- return 0;
-}
-
-/*
* gui_bar_item_search_with_plugin: search a bar item for a plugin
* if exact_plugin == 1, then search only for
* this plugin, otherwise, if plugin is not
@@ -249,7 +186,6 @@ gui_bar_item_used_in_a_bar (const char *item_name, int partial_name)
{
struct t_gui_bar *ptr_bar;
int i, j, length;
- const char *ptr_start;
length = strlen (item_name);
@@ -259,13 +195,14 @@ gui_bar_item_used_in_a_bar (const char *item_name, int partial_name)
{
for (j = 0; j < ptr_bar->items_subcount[i]; j++)
{
- ptr_start = gui_bar_item_string_get_item_start (ptr_bar->items_array[i][j]);
- if (ptr_start)
+ if (ptr_bar->items_name[i][j])
{
if ((partial_name
- && strncmp (ptr_start, item_name, length) == 0)
+ && strncmp (ptr_bar->items_name[i][j],
+ item_name, length) == 0)
|| (!partial_name
- && strcmp (ptr_start, item_name) == 0))
+ && strcmp (ptr_bar->items_name[i][j],
+ item_name) == 0))
{
return 1;
}
@@ -279,40 +216,39 @@ gui_bar_item_used_in_a_bar (const char *item_name, int partial_name)
}
/*
- * gui_bar_item_get_value: return value of a bar item
- * first look for prefix/suffix in name, then run item
- * callback (if found) and concatene strings
- * for example: if name == "[time]"
- * return: color(delimiter) + "[" +
- * (value of item "time") + color(delimiter) +
- * "]"
+ * gui_bar_item_set_prefix_name_suffix: get prefix, name and suffix for an item
+ * for example, item name "[time]"
+ * will return:
+ * prefix: "["
+ * name : "time"
+ * suffix: "]"
*/
-char *
-gui_bar_item_get_value (const char *name, struct t_gui_bar *bar,
- struct t_gui_window *window)
+void
+gui_bar_item_set_prefix_name_suffix (const char *item_name,
+ char **prefix, char **name, char **suffix)
{
const char *ptr, *start, *end;
- char *prefix, *item_name, *suffix;
- char *item_value, delimiter_color[32], bar_color[32];
- char *result, str_attr[8];
- int valid_char, length;
- struct t_gui_bar_item *ptr_item;
- struct t_weechat_plugin *ptr_plugin;
+ int valid_char;
- if (!name)
- return NULL;
+ *prefix = NULL;
+ *name = NULL;
+ *suffix = NULL;
+
+ if (!item_name)
+ return;
start = NULL;
end = NULL;
- prefix = NULL;
- item_name = NULL;
- suffix = NULL;
- ptr = name;
+ ptr = item_name;
while (ptr[0])
{
- valid_char = gui_bar_item_valid_char_name (ptr[0]);
+ valid_char = (((ptr[0] >= 'a') && (ptr[0] <= 'z'))
+ || ((ptr[0] >= 'A') && (ptr[0] <= 'Z'))
+ || ((ptr[0] >= '0') && (ptr[0] <= '9'))
+ || (ptr[0] == '-')
+ || (ptr[0] == '_')) ? 1 : 0;
if (!start && valid_char)
start = ptr;
else if (start && !end && !valid_char)
@@ -321,56 +257,70 @@ gui_bar_item_get_value (const char *name, struct t_gui_bar *bar,
}
if (start)
{
- if (start > name)
- prefix = string_strndup (name, start - name);
+ if (start > item_name)
+ *prefix = string_strndup (item_name, start - item_name);
}
else
- prefix = strdup (name);
+ *prefix = strdup (item_name);
if (start)
{
- item_name = (end) ?
+ *name = (end) ?
string_strndup (start, end - start + 1) : strdup (start);
}
if (end && end[0] && end[1])
- suffix = strdup (end + 1);
+ *suffix = strdup (end + 1);
+}
+
+/*
+ * gui_bar_item_get_value: return value of a bar item
+ * run callback if a name exists, then concatenate
+ * prefix + return of callback + suffix
+ * for example: if item == "[time]"
+ * return: color(delimiter) + "[" +
+ * (value of item "time") + color(delimiter) +
+ * "]"
+ */
+
+char *
+gui_bar_item_get_value (struct t_gui_bar *bar, struct t_gui_window *window,
+ int item, int subitem)
+{
+ char *item_value, delimiter_color[32], bar_color[32];
+ char *result, str_attr[8];
+ int length;
+ struct t_gui_bar_item *ptr_item;
+ struct t_weechat_plugin *ptr_plugin;
+
+ if (!bar->items_array[item][subitem])
+ return NULL;
item_value = NULL;
- if (item_name)
+ if (bar->items_name[item][subitem])
{
ptr_plugin = NULL;
if (window && window->buffer)
ptr_plugin = window->buffer->plugin;
else if (gui_current_window && gui_current_window->buffer)
ptr_plugin = gui_current_window->buffer->plugin;
- ptr_item = gui_bar_item_search_with_plugin (ptr_plugin, 0, item_name);
+ ptr_item = gui_bar_item_search_with_plugin (ptr_plugin, 0,
+ bar->items_name[item][subitem]);
if (ptr_item && ptr_item->build_callback)
{
item_value = (ptr_item->build_callback) (ptr_item->build_callback_data,
ptr_item, window);
}
- if (!item_value || !item_value[0])
- {
- if (prefix)
- {
- free (prefix);
- prefix = NULL;
- }
- if (suffix)
- {
- free (suffix);
- suffix = NULL;
- }
- }
+ if (!item_value)
+ return NULL;
}
length = 0;
- if (prefix)
- length += 64 + strlen (prefix) + 1; /* color + prefix + color */
+ if (bar->items_prefix[item][subitem])
+ length += 64 + strlen (bar->items_prefix[item][subitem]) + 1; /* color + prefix + color */
if (item_value && item_value[0])
- length += strlen (item_value) + 16 + 1; /* length + "move cursor" id */
- if (suffix)
- length += 32 + strlen (suffix) + 1; /* color + suffix */
-
+ length += strlen (item_value) + 1;
+ if (bar->items_suffix[item][subitem])
+ length += 32 + strlen (bar->items_suffix[item][subitem]) + 1; /* color + suffix */
+
result = NULL;
if (length > 0)
{
@@ -379,7 +329,8 @@ gui_bar_item_get_value (const char *name, struct t_gui_bar *bar,
{
delimiter_color[0] = '\0';
bar_color[0] = '\0';
- if (prefix || suffix)
+ if (bar->items_prefix[item][subitem]
+ || bar->items_suffix[item][subitem])
{
/* color for text in bar */
gui_color_attr_build_string (CONFIG_COLOR(bar->options[GUI_BAR_OPTION_COLOR_FG]),
@@ -429,21 +380,15 @@ gui_bar_item_get_value (const char *name, struct t_gui_bar *bar,
}
snprintf (result, length,
"%s%s%s%s%s%s",
- (prefix) ? delimiter_color : "",
- (prefix) ? prefix : "",
- (prefix) ? bar_color : "",
+ (bar->items_prefix[item][subitem]) ? delimiter_color : "",
+ (bar->items_prefix[item][subitem]) ? bar->items_prefix[item][subitem] : "",
+ (bar->items_prefix[item][subitem]) ? bar_color : "",
(item_value) ? item_value : "",
- (suffix) ? delimiter_color : "",
- (suffix) ? suffix : "");
+ (bar->items_suffix[item][subitem]) ? delimiter_color : "",
+ (bar->items_suffix[item][subitem]) ? bar->items_suffix[item][subitem] : "");
}
}
- if (prefix)
- free (prefix);
- if (item_name)
- free (item_name);
- if (suffix)
- free (suffix);
if (item_value)
free (item_value);
@@ -451,6 +396,30 @@ gui_bar_item_get_value (const char *name, struct t_gui_bar *bar,
}
/*
+ * gui_bar_item_count_lines: count number of lines in item
+ */
+
+int
+gui_bar_item_count_lines (char *string)
+{
+ int count, i;
+
+ if (!string || !string[0])
+ return 0;
+
+ count = 1;
+ i = 0;
+ while (string[i])
+ {
+ if ((string[i] == '\n') && string[i + 1])
+ count++;
+ i++;
+ }
+
+ return count;
+}
+
+/*
* gui_bar_item_new: create a new bar item
*/
@@ -505,22 +474,20 @@ gui_bar_item_update (const char *item_name)
struct t_gui_bar *ptr_bar;
struct t_gui_window *ptr_window;
struct t_gui_bar_window *ptr_bar_window;
- int index_item, index_subitem;
+ int i, j;
for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
{
- for (index_item = 0; index_item < ptr_bar->items_count; index_item++)
+ for (i = 0; i < ptr_bar->items_count; i++)
{
- for (index_subitem = 0;
- index_subitem < ptr_bar->items_subcount[index_item];
- index_subitem++)
+ for (j = 0; j < ptr_bar->items_subcount[i]; j++)
{
- if (gui_bar_item_string_is_item (ptr_bar->items_array[index_item][index_subitem],
- item_name))
+ if (ptr_bar->items_name[i][j]
+ && (strcmp (ptr_bar->items_name[i][j], item_name) == 0))
{
if (ptr_bar->bar_window)
{
- ptr_bar->bar_window->items_refresh_needed[index_item][index_subitem] = 1;
+ ptr_bar->bar_window->items_refresh_needed[i][j] = 1;
}
else
{
@@ -533,7 +500,7 @@ gui_bar_item_update (const char *item_name)
{
if (ptr_bar_window->bar == ptr_bar)
{
- ptr_bar_window->items_refresh_needed[index_item][index_subitem] = 1;
+ ptr_bar_window->items_refresh_needed[i][j] = 1;
}
}
}
@@ -744,11 +711,15 @@ gui_bar_item_default_input_text (void *data, struct t_gui_bar_item *item,
"0x%lx", (long unsigned int)(window->buffer));
/* execute modifier with basic string (without cursor tag) */
- ptr_input = hook_modifier_exec (NULL,
- "input_text_display",
- str_buffer,
- (window->buffer->input_buffer) ?
- window->buffer->input_buffer : "");
+ ptr_input = NULL;
+ if (!gui_cursor_mode)
+ {
+ ptr_input = hook_modifier_exec (NULL,
+ "input_text_display",
+ str_buffer,
+ (window->buffer->input_buffer) ?
+ window->buffer->input_buffer : "");
+ }
if (!ptr_input)
{
ptr_input = (window->buffer->input_buffer) ?
@@ -791,13 +762,16 @@ gui_bar_item_default_input_text (void *data, struct t_gui_bar_item *item,
}
/* execute modifier with cursor in string */
- ptr_input2 = hook_modifier_exec (NULL,
- "input_text_display_with_cursor",
- str_buffer,
- (ptr_input) ? ptr_input : "");
- if (ptr_input)
- free (ptr_input);
- ptr_input = ptr_input2;
+ if (!gui_cursor_mode)
+ {
+ ptr_input2 = hook_modifier_exec (NULL,
+ "input_text_display_with_cursor",
+ str_buffer,
+ (ptr_input) ? ptr_input : "");
+ if (ptr_input)
+ free (ptr_input);
+ ptr_input = ptr_input2;
+ }
/* insert "start input" at beginning of string */
if (ptr_input)
@@ -1448,6 +1422,74 @@ gui_bar_item_default_buffer_nicklist (void *data, struct t_gui_bar_item *item,
}
/*
+ * gui_bar_item_focus_buffer_nicklist: focus on nicklist
+ */
+
+struct t_hashtable *
+gui_bar_item_focus_buffer_nicklist (void *data,
+ struct t_hashtable *info)
+{
+ struct t_gui_nick_group *ptr_group;
+ struct t_gui_nick *ptr_nick;
+ int i, rc, item_line;
+ unsigned long int value;
+ const char *str_window;
+ struct t_gui_window *window;
+ char *error;
+
+ /* make C compiler happy */
+ (void) data;
+
+ str_window = hashtable_get (info, "_window");
+ rc = sscanf (str_window, "%lx", &value);
+ if ((rc == EOF) || (rc == 0))
+ return NULL;
+
+ window = (struct t_gui_window *)value;
+ if (!window)
+ window = gui_current_window;
+
+ error = NULL;
+ item_line = (int) strtol (hashtable_get (info, "_item_line"), &error, 10);
+ if (!error || error[0])
+ return NULL;
+
+ i = 0;
+ ptr_group = NULL;
+ ptr_nick = NULL;
+ gui_nicklist_get_next_item (window->buffer, &ptr_group, &ptr_nick);
+ while (ptr_group || ptr_nick)
+ {
+ if ((ptr_nick && ptr_nick->visible)
+ || (ptr_group && !ptr_nick
+ && window->buffer->nicklist_display_groups
+ && ptr_group->visible))
+ {
+ if (i == item_line)
+ break;
+ i++;
+ }
+ gui_nicklist_get_next_item (window->buffer, &ptr_group, &ptr_nick);
+ }
+
+ if (i != item_line)
+ return NULL;
+
+ if (ptr_nick)
+ {
+ hashtable_set (info, "nick", ptr_nick->name);
+ hashtable_set (info, "prefix", ptr_nick->prefix);
+ }
+ else
+ {
+ hashtable_set (info,
+ "group",
+ gui_nicklist_get_group_start (ptr_group->name));
+ }
+ return info;
+}
+
+/*
* gui_bar_item_timer_cb: timer callback
*/
@@ -1673,6 +1715,8 @@ gui_bar_item_init ()
gui_bar_item_names[GUI_BAR_ITEM_BUFFER_NICKLIST]);
gui_bar_item_hook_signal ("buffer_switch",
gui_bar_item_names[GUI_BAR_ITEM_BUFFER_NICKLIST]);
+ hook_focus (NULL, gui_bar_item_names[GUI_BAR_ITEM_BUFFER_NICKLIST],
+ &gui_bar_item_focus_buffer_nicklist, NULL);
}
/*
diff --git a/src/gui/gui-bar-item.h b/src/gui/gui-bar-item.h
index a6d8bdb06..bcc7b134b 100644
--- a/src/gui/gui-bar-item.h
+++ b/src/gui/gui-bar-item.h
@@ -74,13 +74,15 @@ extern char *gui_bar_items_default_for_bars[][2];
extern int gui_bar_item_valid (struct t_gui_bar_item *bar_item);
extern struct t_gui_bar_item *gui_bar_item_search (const char *name);
-extern int gui_bar_item_string_is_item (const char *string,
- const char *item_name);
extern int gui_bar_item_used_in_a_bar (const char *item_name,
int partial_name);
-extern char *gui_bar_item_get_value (const char *name,
- struct t_gui_bar *bar,
- struct t_gui_window *window);
+extern void gui_bar_item_set_prefix_name_suffix (const char *item_name,
+ char **prefix, char **name,
+ char **suffix);
+extern char *gui_bar_item_get_value (struct t_gui_bar *bar,
+ struct t_gui_window *window,
+ int item, int subitem);
+extern int gui_bar_item_count_lines (char *string);
extern struct t_gui_bar_item *gui_bar_item_new (struct t_weechat_plugin *plugin,
const char *name,
char *(*build_callback)(void *data,
diff --git a/src/gui/gui-bar-window.c b/src/gui/gui-bar-window.c
index 58cca2112..65069f187 100644
--- a/src/gui/gui-bar-window.c
+++ b/src/gui/gui-bar-window.c
@@ -26,14 +26,17 @@
#endif
#include <stdlib.h>
+#include <stddef.h>
#include <limits.h>
#include <string.h>
#include "../core/weechat.h"
#include "../core/wee-config.h"
+#include "../core/wee-hdata.h"
#include "../core/wee-infolist.h"
#include "../core/wee-log.h"
#include "../core/wee-string.h"
+#include "../plugins/plugin.h"
#include "gui-bar-window.h"
#include "gui-bar.h"
#include "gui-bar-item.h"
@@ -102,6 +105,149 @@ gui_bar_window_search_bar (struct t_gui_window *window, struct t_gui_bar *bar)
}
/*
+ * gui_bar_window_search_by_xy: get bar_window pointer displayed at (x,y)
+ * if window is not NULL, search is done in
+ * bar windows of window
+ * if window is NULL, search is done in root
+ * bar windows
+ */
+
+void
+gui_bar_window_search_by_xy (struct t_gui_window *window, int x, int y,
+ struct t_gui_bar_window **bar_window,
+ char **bar_item, int *item_line, int *item_col)
+{
+ struct t_gui_bar *ptr_bar;
+ struct t_gui_bar_window *ptr_bar_window;
+ int filling, num_cols, column, lines, lines_old, i, j, coord_x, coord_y;
+ int item, subitem;
+
+ *bar_window = NULL;
+ *bar_item = NULL;
+ *item_line = -1;
+ *item_col = -1;
+
+ if (window)
+ {
+ for (ptr_bar_window = window->bar_windows; ptr_bar_window;
+ ptr_bar_window = ptr_bar_window->next_bar_window)
+ {
+ if ((x >= ptr_bar_window->x) && (y >= ptr_bar_window->y)
+ && (x <= ptr_bar_window->x + ptr_bar_window->width - 1)
+ && (y <= ptr_bar_window->y + ptr_bar_window->height - 1))
+ {
+ *bar_window = ptr_bar_window;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
+ {
+ if (ptr_bar->bar_window
+ && (x >= ptr_bar->bar_window->x)
+ && (y >= ptr_bar->bar_window->y)
+ && (x <= ptr_bar->bar_window->x + ptr_bar->bar_window->width - 1)
+ && (y <= ptr_bar->bar_window->y + ptr_bar->bar_window->height - 1))
+ {
+ *bar_window = ptr_bar->bar_window;
+ break;
+ }
+ }
+ }
+
+ if (*bar_window)
+ {
+ filling = gui_bar_get_filling ((*bar_window)->bar);
+
+ *item_line = y - (*bar_window)->y + (*bar_window)->scroll_y;
+ *item_col = x - (*bar_window)->x + (*bar_window)->scroll_x;
+
+ if ((filling == GUI_BAR_FILLING_COLUMNS_HORIZONTAL)
+ && ((*bar_window)->screen_col_size > 0))
+ {
+ num_cols = (*bar_window)->width / (*bar_window)->screen_col_size;
+ column = *item_col / (*bar_window)->screen_col_size;
+ *item_line = (*item_line * num_cols) + column;
+ *item_col = *item_col - (column * ((*bar_window)->screen_col_size));
+ }
+
+ if ((filling == GUI_BAR_FILLING_COLUMNS_VERTICAL)
+ && ((*bar_window)->screen_col_size > 0))
+ {
+ column = *item_col / (*bar_window)->screen_col_size;
+ *item_line = (column * ((*bar_window)->height)) + *item_line;
+ *item_col = *item_col % ((*bar_window)->screen_col_size);
+ }
+
+ if (filling == GUI_BAR_FILLING_HORIZONTAL)
+ {
+ i = 0;
+ while (i < (*bar_window)->coords_count)
+ {
+ coord_x = (*bar_window)->coords[i]->x;
+ coord_y = (*bar_window)->coords[i]->y;
+ while ((i < (*bar_window)->coords_count - 1)
+ && (coord_x == (*bar_window)->coords[i + 1]->x)
+ && (coord_y == (*bar_window)->coords[i + 1]->y))
+ {
+ i++;
+ }
+ if (i == (*bar_window)->coords_count - 1)
+ {
+ item = (*bar_window)->coords[i]->item;
+ subitem = (*bar_window)->coords[i]->subitem;
+ if ((item >= 0) && (subitem >= 0))
+ {
+ *bar_item = (*bar_window)->bar->items_name[item][subitem];
+ *item_line = (*bar_window)->coords[i]->line;
+ *item_col = x - (*bar_window)->coords[i]->x;
+ }
+ break;
+ }
+ coord_x = (*bar_window)->coords[i + 1]->x;
+ coord_y = (*bar_window)->coords[i + 1]->y;
+ if ((y < coord_y) || ((y == coord_y) && (x < coord_x)))
+ {
+ item = (*bar_window)->coords[i]->item;
+ subitem = (*bar_window)->coords[i]->subitem;
+ *bar_item = (*bar_window)->bar->items_name[item][subitem];
+ *item_line = (*bar_window)->coords[i]->line;
+ *item_col = x - (*bar_window)->coords[i]->x;
+ break;
+ }
+ i++;
+ }
+ }
+ else
+ {
+ i = 0;
+ j = 0;
+ lines = 0;
+ lines_old = 0;
+ while (i < (*bar_window)->items_count)
+ {
+ lines_old = lines;
+ lines += (*bar_window)->items_num_lines[i][j];
+ if (*item_line < lines)
+ {
+ *bar_item = (*bar_window)->bar->items_name[i][j];
+ break;
+ }
+ j++;
+ if (j >= (*bar_window)->items_subcount[i])
+ {
+ j = 0;
+ i++;
+ }
+ }
+ *item_line -= lines_old;
+ }
+ }
+}
+
+/*
* gui_bar_window_get_size: get total bar size (window bars) for a position
* bar is optional, if not NULL, size is computed
* from bar 1 to bar # - 1
@@ -159,6 +305,9 @@ gui_bar_window_calculate_pos_size (struct t_gui_bar_window *bar_window,
int x1, y1, x2, y2;
int add_bottom, add_top, add_left, add_right;
+ if (CONFIG_BOOLEAN(bar_window->bar->options[GUI_BAR_OPTION_HIDDEN]))
+ return;
+
if (window)
{
x1 = window->win_x;
@@ -247,7 +396,9 @@ gui_bar_window_content_alloc (struct t_gui_bar_window *bar_window)
bar_window->items_count = bar_window->bar->items_count;
bar_window->items_subcount = NULL;
bar_window->items_content = NULL;
+ bar_window->items_num_lines = NULL;
bar_window->items_refresh_needed = NULL;
+ bar_window->screen_col_size = 0;
bar_window->items_subcount = malloc (bar_window->items_count *
sizeof (*bar_window->items_subcount));
if (!bar_window->items_subcount)
@@ -256,6 +407,10 @@ gui_bar_window_content_alloc (struct t_gui_bar_window *bar_window)
sizeof (*bar_window->items_content));
if (!bar_window->items_content)
goto error;
+ bar_window->items_num_lines = malloc ((bar_window->items_count) *
+ sizeof (*bar_window->items_num_lines));
+ if (!bar_window->items_num_lines)
+ goto error;
bar_window->items_refresh_needed = malloc (bar_window->items_count *
sizeof (*bar_window->items_refresh_needed));
if (!bar_window->items_refresh_needed)
@@ -264,6 +419,7 @@ gui_bar_window_content_alloc (struct t_gui_bar_window *bar_window)
for (i = 0; i < bar_window->items_count; i++)
{
bar_window->items_content[i] = NULL;
+ bar_window->items_num_lines[i] = NULL;
bar_window->items_refresh_needed[i] = NULL;
}
@@ -274,6 +430,10 @@ gui_bar_window_content_alloc (struct t_gui_bar_window *bar_window)
sizeof (**bar_window->items_content));
if (!bar_window->items_content[i])
goto error;
+ bar_window->items_num_lines[i] = malloc (bar_window->items_subcount[i] *
+ sizeof (**bar_window->items_num_lines));
+ if (!bar_window->items_num_lines[i])
+ goto error;
bar_window->items_refresh_needed[i] = malloc (bar_window->items_subcount[i] *
sizeof (**bar_window->items_refresh_needed));
if (!bar_window->items_refresh_needed[i])
@@ -282,6 +442,8 @@ gui_bar_window_content_alloc (struct t_gui_bar_window *bar_window)
{
if (bar_window->items_content[i])
bar_window->items_content[i][j] = NULL;
+ if (bar_window->items_num_lines[i])
+ bar_window->items_num_lines[i][j] = 0;
if (bar_window->items_refresh_needed[i])
bar_window->items_refresh_needed[i][j] = 1;
}
@@ -304,6 +466,16 @@ error:
free (bar_window->items_content);
bar_window->items_content = NULL;
}
+ if (bar_window->items_num_lines)
+ {
+ for (i = 0; i < bar_window->items_count; i++)
+ {
+ if (bar_window->items_num_lines[i])
+ free (bar_window->items_num_lines[i]);
+ }
+ free (bar_window->items_num_lines);
+ bar_window->items_num_lines = NULL;
+ }
if (bar_window->items_refresh_needed)
{
for (i = 0; i < bar_window->items_count; i++)
@@ -338,12 +510,15 @@ gui_bar_window_content_free (struct t_gui_bar_window *bar_window)
}
}
free (bar_window->items_content[i]);
+ free (bar_window->items_num_lines[i]);
free (bar_window->items_refresh_needed[i]);
}
free (bar_window->items_subcount);
bar_window->items_subcount = NULL;
free (bar_window->items_content);
bar_window->items_content = NULL;
+ free (bar_window->items_num_lines);
+ bar_window->items_num_lines = NULL;
free (bar_window->items_refresh_needed);
bar_window->items_refresh_needed = NULL;
}
@@ -368,14 +543,17 @@ gui_bar_window_content_build_item (struct t_gui_bar_window *bar_window,
free (bar_window->items_content[index_item][index_subitem]);
bar_window->items_content[index_item][index_subitem] = NULL;
}
+ bar_window->items_num_lines[index_item][index_subitem] = 0;
/* build item, but only if there's a buffer in window */
if ((window && window->buffer)
|| (gui_current_window && gui_current_window->buffer))
{
bar_window->items_content[index_item][index_subitem] =
- gui_bar_item_get_value (bar_window->bar->items_array[index_item][index_subitem],
- bar_window->bar, window);
+ gui_bar_item_get_value (bar_window->bar, window,
+ index_item, index_subitem);
+ bar_window->items_num_lines[index_item][index_subitem] =
+ gui_bar_item_count_lines (bar_window->items_content[index_item][index_subitem]);
bar_window->items_refresh_needed[index_item][index_subitem] = 0;
}
}
@@ -437,28 +615,50 @@ gui_bar_window_content_get_with_filling (struct t_gui_bar_window *bar_window,
struct t_gui_window *window)
{
enum t_gui_bar_filling filling;
- char *ptr_content, *content, reinit_color[32], reinit_color_space[32];
+ char *ptr_content, *content, str_reinit_color[32];
+ char str_reinit_color_space[32], str_reinit_color_space_start_line[32];
+ char str_start_item[32];
char *item_value, *item_value2, ****split_items, **linear_items;
- int index_content, content_length, i, first_sub_item, sub, j, k, index;
- int length_reinit_color_space, length, max_length, max_length_screen;
+ int index_content, content_length, i, j, k, sub, index;
+ int at_least_one_item, first_sub_item;
+ int length_reinit_color_space, length_start_item, length;
+ int max_length, max_length_screen;
int total_items, columns, lines;
if (!bar_window->items_subcount || !bar_window->items_content
- || !bar_window->items_refresh_needed)
+ || !bar_window->items_num_lines || !bar_window->items_refresh_needed)
return NULL;
- snprintf (reinit_color, sizeof (reinit_color),
+ snprintf (str_reinit_color, sizeof (str_reinit_color),
"%c",
GUI_COLOR_RESET_CHAR);
- snprintf (reinit_color_space, sizeof (reinit_color_space),
+ snprintf (str_reinit_color_space, sizeof (str_reinit_color_space),
"%c ",
GUI_COLOR_RESET_CHAR);
- length_reinit_color_space = strlen (reinit_color_space);
+ length_reinit_color_space = strlen (str_reinit_color_space);
+
+ snprintf (str_reinit_color_space_start_line,
+ sizeof (str_reinit_color_space_start_line),
+ "%c %c%c%c",
+ GUI_COLOR_RESET_CHAR,
+ GUI_COLOR_COLOR_CHAR,
+ GUI_COLOR_BAR_CHAR,
+ GUI_COLOR_BAR_START_LINE_ITEM);
+
+ snprintf (str_start_item, sizeof (str_start_item),
+ "%c%c%c",
+ GUI_COLOR_COLOR_CHAR,
+ GUI_COLOR_BAR_CHAR,
+ GUI_COLOR_BAR_START_ITEM);
+ length_start_item = strlen (str_start_item);
- content = NULL;
content_length = 1;
+ content = malloc (content_length);
+ if (content)
+ content[0] = '\0';
filling = gui_bar_get_filling (bar_window->bar);
+ at_least_one_item = 0;
switch (filling)
{
case GUI_BAR_FILLING_HORIZONTAL: /* items separated by space */
@@ -472,10 +672,10 @@ gui_bar_window_content_get_with_filling (struct t_gui_bar_window *bar_window,
i, sub);
if (ptr_content && ptr_content[0])
{
- if (gui_bar_get_filling (bar_window->bar) == GUI_BAR_FILLING_HORIZONTAL)
+ if (filling == GUI_BAR_FILLING_HORIZONTAL)
{
item_value = string_replace (ptr_content, "\n",
- reinit_color_space);
+ str_reinit_color_space_start_line);
if (item_value)
{
item_value2 = string_replace (item_value,
@@ -489,43 +689,55 @@ gui_bar_window_content_get_with_filling (struct t_gui_bar_window *bar_window,
}
else
item_value = NULL;
- if (!content)
+
+ content_length += ((filling == GUI_BAR_FILLING_HORIZONTAL) ? length_start_item : 0) +
+ length_reinit_color_space +
+ strlen ((item_value) ? item_value : ptr_content);
+ content = realloc (content, content_length);
+ if (at_least_one_item && first_sub_item)
{
- content_length += strlen ((item_value) ?
- item_value : ptr_content);
- content = strdup ((item_value) ? item_value : ptr_content);
- first_sub_item = 0;
+ /* first sub item: insert space after last item */
+ if (filling == GUI_BAR_FILLING_HORIZONTAL)
+ strcat (content, str_reinit_color_space);
+ else
+ strcat (content, "\n");
}
else
{
- content_length += length_reinit_color_space +
- strlen ((item_value) ? item_value : ptr_content);
- content = realloc (content, content_length);
- if (first_sub_item)
- {
- /* first sub item: insert space after last item */
- if (gui_bar_get_filling (bar_window->bar) == GUI_BAR_FILLING_HORIZONTAL)
- strcat (content, reinit_color_space);
- else
- strcat (content, "\n");
- }
- else
- {
- strcat (content, reinit_color);
- }
- strcat (content,
- (item_value) ? item_value : ptr_content);
- first_sub_item = 0;
+ strcat (content, str_reinit_color);
}
+ if (filling == GUI_BAR_FILLING_HORIZONTAL)
+ strcat (content, str_start_item);
+ strcat (content,
+ (item_value) ? item_value : ptr_content);
+ first_sub_item = 0;
+
if (item_value)
free (item_value);
+ at_least_one_item = 1;
+ }
+ else
+ {
+ if (filling == GUI_BAR_FILLING_HORIZONTAL)
+ {
+ content_length += length_start_item;
+ content = realloc (content, content_length);
+ if (content)
+ strcat (content, str_start_item);
+ }
}
}
}
+ if (filling == GUI_BAR_FILLING_HORIZONTAL)
+ {
+ content_length += length_start_item;
+ content = realloc (content, content_length);
+ if (content)
+ strcat (content, str_start_item);
+ }
break;
case GUI_BAR_FILLING_COLUMNS_HORIZONTAL: /* items in columns, with horizontal filling */
case GUI_BAR_FILLING_COLUMNS_VERTICAL: /* items in columns, with vertical filling */
- content = NULL;
total_items = 0;
max_length = 1;
max_length_screen = 1;
@@ -580,6 +792,7 @@ gui_bar_window_content_get_with_filling (struct t_gui_bar_window *bar_window,
columns++;
lines = bar_window->height;
}
+ bar_window->screen_col_size = max_length_screen + 1;
/* build array with pointers to split items */
@@ -605,9 +818,10 @@ gui_bar_window_content_get_with_filling (struct t_gui_bar_window *bar_window,
}
/* build content with lines and columns */
- content = malloc (1 + (lines *
- ((columns *
- (max_length + max_length_screen + length_reinit_color_space)) + 1)));
+ content_length = 1 + (lines *
+ ((columns *
+ (max_length + max_length_screen + length_reinit_color_space)) + 1));
+ content = realloc (content, content_length);
if (content)
{
content[0] = '\0';
@@ -641,7 +855,8 @@ gui_bar_window_content_get_with_filling (struct t_gui_bar_window *bar_window,
}
if (j < columns - 1)
{
- strcpy (content + index_content, reinit_color_space);
+ strcpy (content + index_content,
+ str_reinit_color_space);
index_content += length_reinit_color_space;
}
}
@@ -671,25 +886,126 @@ gui_bar_window_content_get_with_filling (struct t_gui_bar_window *bar_window,
break;
}
+ if (content_length == 1)
+ {
+ free (content);
+ content = NULL;
+ }
+
return content;
}
/*
+ * gui_bar_window_coords_add: add coordinates (item index/subindex and x,y)
+ */
+
+void
+gui_bar_window_coords_add (struct t_gui_bar_window *bar_window,
+ int index_item, int index_subitem, int index_line,
+ int x, int y)
+{
+ if (!bar_window->coords)
+ {
+ bar_window->coords_count = 1;
+ bar_window->coords = malloc (sizeof (*(bar_window->coords)));
+ }
+ else
+ {
+ bar_window->coords_count++;
+ bar_window->coords = realloc (bar_window->coords,
+ bar_window->coords_count * sizeof (*(bar_window->coords)));
+ }
+ bar_window->coords[bar_window->coords_count - 1] = malloc (sizeof (*(bar_window->coords[bar_window->coords_count - 1])));
+ bar_window->coords[bar_window->coords_count - 1]->item = index_item;
+ bar_window->coords[bar_window->coords_count - 1]->subitem = index_subitem;
+ bar_window->coords[bar_window->coords_count - 1]->line = index_line;
+ bar_window->coords[bar_window->coords_count - 1]->x = x;
+ bar_window->coords[bar_window->coords_count - 1]->y = y;
+}
+
+/*
+ * gui_bar_window_coords_free: free coords of a bar window
+ */
+
+void
+gui_bar_window_coords_free (struct t_gui_bar_window *bar_window)
+{
+ int i;
+
+ if (bar_window->coords)
+ {
+ for (i = 0; i < bar_window->coords_count; i++)
+ {
+ free (bar_window->coords[i]);
+ }
+ free (bar_window->coords);
+ bar_window->coords = NULL;
+ }
+ bar_window->coords_count = 0;
+}
+
+/*
+ * gui_bar_window_insert: insert bar window in list of bar windows (at good
+ * position, according to priority)
+ */
+
+void
+gui_bar_window_insert (struct t_gui_bar_window *bar_window,
+ struct t_gui_window *window)
+{
+ struct t_gui_bar_window *pos_bar_window;
+
+ if (window->bar_windows)
+ {
+ pos_bar_window = gui_bar_window_find_pos (bar_window->bar, window);
+ if (pos_bar_window)
+ {
+ /* insert before bar window found */
+ bar_window->prev_bar_window = pos_bar_window->prev_bar_window;
+ bar_window->next_bar_window = pos_bar_window;
+ if (pos_bar_window->prev_bar_window)
+ (pos_bar_window->prev_bar_window)->next_bar_window = bar_window;
+ else
+ window->bar_windows = bar_window;
+ pos_bar_window->prev_bar_window = bar_window;
+ }
+ else
+ {
+ /* add to end of list for window */
+ bar_window->prev_bar_window = window->last_bar_window;
+ bar_window->next_bar_window = NULL;
+ (window->last_bar_window)->next_bar_window = bar_window;
+ window->last_bar_window = bar_window;
+ }
+ }
+ else
+ {
+ bar_window->prev_bar_window = NULL;
+ bar_window->next_bar_window = NULL;
+ window->bar_windows = bar_window;
+ window->last_bar_window = bar_window;
+ }
+}
+
+/*
* gui_bar_window_new: create a new "window bar" for a bar, in screen or a window
* if window is not NULL, bar window will be in this window
* return 1 if ok, 0 if error
*/
-int
+void
gui_bar_window_new (struct t_gui_bar *bar, struct t_gui_window *window)
{
- struct t_gui_bar_window *new_bar_window, *pos_bar_window;
+ struct t_gui_bar_window *new_bar_window;
+
+ if (CONFIG_BOOLEAN(bar->options[GUI_BAR_OPTION_HIDDEN]))
+ return;
if (window)
{
if ((CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_WINDOW)
&& (!gui_bar_check_conditions_for_window (bar, window)))
- return 1;
+ return;
}
new_bar_window = malloc (sizeof (*new_bar_window));
@@ -699,36 +1015,7 @@ gui_bar_window_new (struct t_gui_bar *bar, struct t_gui_window *window)
if (window)
{
bar->bar_window = NULL;
- if (window->bar_windows)
- {
- pos_bar_window = gui_bar_window_find_pos (bar, window);
- if (pos_bar_window)
- {
- /* insert before bar window found */
- new_bar_window->prev_bar_window = pos_bar_window->prev_bar_window;
- new_bar_window->next_bar_window = pos_bar_window;
- if (pos_bar_window->prev_bar_window)
- (pos_bar_window->prev_bar_window)->next_bar_window = new_bar_window;
- else
- window->bar_windows = new_bar_window;
- pos_bar_window->prev_bar_window = new_bar_window;
- }
- else
- {
- /* add to end of list for window */
- new_bar_window->prev_bar_window = window->last_bar_window;
- new_bar_window->next_bar_window = NULL;
- (window->last_bar_window)->next_bar_window = new_bar_window;
- window->last_bar_window = new_bar_window;
- }
- }
- else
- {
- new_bar_window->prev_bar_window = NULL;
- new_bar_window->next_bar_window = NULL;
- window->bar_windows = new_bar_window;
- window->last_bar_window = new_bar_window;
- }
+ gui_bar_window_insert (new_bar_window, window);
}
else
{
@@ -750,7 +1037,11 @@ gui_bar_window_new (struct t_gui_bar *bar, struct t_gui_window *window)
new_bar_window->items_count = 0;
new_bar_window->items_subcount = NULL;
new_bar_window->items_content = NULL;
+ new_bar_window->items_num_lines = NULL;
new_bar_window->items_refresh_needed = NULL;
+ new_bar_window->screen_col_size = 0;
+ new_bar_window->coords_count = 0;
+ new_bar_window->coords = NULL;
gui_bar_window_objects_init (new_bar_window);
gui_bar_window_content_alloc (new_bar_window);
@@ -760,12 +1051,7 @@ gui_bar_window_new (struct t_gui_bar *bar, struct t_gui_window *window)
gui_bar_window_create_win (new_bar_window);
gui_window_ask_refresh (1);
}
-
- return 1;
}
-
- /* failed to create bar window */
- return 0;
}
/*
@@ -916,6 +1202,7 @@ gui_bar_window_free (struct t_gui_bar_window *bar_window,
/* free data */
gui_bar_window_content_free (bar_window);
+ gui_bar_window_coords_free (bar_window);
gui_bar_window_objects_free (bar_window);
free (bar_window->gui_objects);
@@ -1060,6 +1347,46 @@ gui_bar_window_scroll (struct t_gui_bar_window *bar_window,
}
/*
+ * gui_bar_window_hdata_bar_window_cb: return hdata for bar window
+ */
+
+struct t_hdata *
+gui_bar_window_hdata_bar_window_cb (void *data, const char *hdata_name)
+{
+ struct t_hdata *hdata;
+
+ /* make C compiler happy */
+ (void) data;
+
+ hdata = hdata_new (NULL, hdata_name, "prev_bar_window", "next_bar_window");
+ if (hdata)
+ {
+ HDATA_VAR(struct t_gui_bar_window, bar, POINTER, "bar");
+ HDATA_VAR(struct t_gui_bar_window, x, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, y, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, width, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, height, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, scroll_x, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, scroll_y, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, cursor_x, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, cursor_y, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, current_size, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, items_count, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, items_subcount, POINTER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, items_content, POINTER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, items_num_lines, POINTER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, items_refresh_needed, POINTER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, screen_col_size, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, coords_count, INTEGER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, coords, POINTER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, gui_objects, POINTER, NULL);
+ HDATA_VAR(struct t_gui_bar_window, prev_bar_window, POINTER, hdata_name);
+ HDATA_VAR(struct t_gui_bar_window, next_bar_window, POINTER, hdata_name);
+ }
+ return hdata;
+}
+
+/*
* gui_bar_window_add_to_infolist: add a bar window in an infolist
* return 1 if ok, 0 if error
*/
@@ -1110,8 +1437,15 @@ gui_bar_window_add_to_infolist (struct t_infolist *infolist,
if (!infolist_new_var_string (ptr_item, option_name,
bar_window->items_content[i][j]))
return 0;
+ snprintf (option_name, sizeof (option_name),
+ "items_num_lines_%05d_%05d", i + 1, j + 1);
+ if (!infolist_new_var_integer (ptr_item, option_name,
+ bar_window->items_num_lines[i][j]))
+ return 0;
}
}
+ if (!infolist_new_var_integer (ptr_item, "screen_col_size", bar_window->screen_col_size))
+ return 0;
if (!infolist_new_var_pointer (ptr_item, "gui_objects", bar_window->gui_objects))
return 0;
@@ -1151,11 +1485,13 @@ gui_bar_window_print_log (struct t_gui_bar_window *bar_window)
{
for (j = 0; j < bar_window->items_subcount[i]; j++)
{
- log_printf (" items_content[%03d][%03d]: '%s' (item: '%s')",
+ log_printf (" items_content[%03d][%03d]: '%s' "
+ "(item: '%s', num_lines: %d)",
i, j,
bar_window->items_content[i][j],
(bar_window->items_count >= i + 1) ?
- bar_window->bar->items_array[i][j] : "?");
+ bar_window->bar->items_array[i][j] : "?",
+ bar_window->items_num_lines[i][j]);
}
}
else
@@ -1163,6 +1499,19 @@ gui_bar_window_print_log (struct t_gui_bar_window *bar_window)
log_printf (" items_content. . . . . . : 0x%lx", bar_window->items_content);
}
}
+ log_printf (" screen_col_size. . . . : %d", bar_window->screen_col_size);
+ log_printf (" coords_count . . . . . : %d", bar_window->coords_count);
+ for (i = 0; i < bar_window->coords_count; i++)
+ {
+ log_printf (" coords[%03d]. . . . . . : item=%d, subitem=%d, "
+ "line=%d, x=%d, y=%d",
+ i,
+ bar_window->coords[i]->item,
+ bar_window->coords[i]->subitem,
+ bar_window->coords[i]->line,
+ bar_window->coords[i]->x,
+ bar_window->coords[i]->y);
+ }
log_printf (" gui_objects. . . . . . : 0x%lx", bar_window->gui_objects);
gui_bar_window_objects_print_log (bar_window);
log_printf (" prev_bar_window. . . . : 0x%lx", bar_window->prev_bar_window);
diff --git a/src/gui/gui-bar-window.h b/src/gui/gui-bar-window.h
index ddaeebbe3..337e9254e 100644
--- a/src/gui/gui-bar-window.h
+++ b/src/gui/gui-bar-window.h
@@ -20,9 +20,19 @@
#ifndef __WEECHAT_GUI_BAR_WINDOW_H
#define __WEECHAT_GUI_BAR_WINDOW_H 1
+struct t_infolist;
struct t_gui_window;
enum t_gui_bar_position;
+struct t_gui_bar_window_coords
+{
+ int item; /* index of item */
+ int subitem; /* index of sub item */
+ int line; /* line */
+ int x; /* X on screen */
+ int y; /* Y on screen */
+};
+
struct t_gui_bar_window
{
struct t_gui_bar *bar; /* pointer to bar */
@@ -34,8 +44,14 @@ struct t_gui_bar_window
int current_size; /* current size (width or height) */
int items_count; /* number of bar items */
int *items_subcount; /* number of sub items */
- char ***items_content; /* content for each item/sub item of bar*/
+ char ***items_content; /* content for each (sub)item of bar */
+ int **items_num_lines; /* number of lines for each (sub)item */
int **items_refresh_needed; /* refresh needed for (sub)item? */
+ int screen_col_size; /* size of columns on screen */
+ /* (for filling with columns) */
+ int coords_count; /* number of coords saved */
+ struct t_gui_bar_window_coords **coords; /* coords for filling horiz. */
+ /* (size is 5 * coords_count) */
void *gui_objects; /* pointer to a GUI specific struct */
struct t_gui_bar_window *prev_bar_window; /* link to previous bar win */
/* (only for non-root bars) */
@@ -46,6 +62,12 @@ struct t_gui_bar_window
/* functions */
extern int gui_bar_window_valid (struct t_gui_bar_window *bar_window);
+extern void gui_bar_window_search_by_xy (struct t_gui_window *window,
+ int x, int y,
+ struct t_gui_bar_window **bar_window,
+ char **bar_item,
+ int *item_line,
+ int *item_col);
extern void gui_bar_window_calculate_pos_size (struct t_gui_bar_window *bar_window,
struct t_gui_window *window);
extern void gui_bar_window_content_build (struct t_gui_bar_window *bar_window,
@@ -61,8 +83,15 @@ extern void gui_bar_window_set_current_size (struct t_gui_bar_window *bar_window
extern int gui_bar_window_get_size (struct t_gui_bar *bar,
struct t_gui_window *window,
enum t_gui_bar_position position);
-extern int gui_bar_window_new (struct t_gui_bar *bar,
- struct t_gui_window *window);
+extern void gui_bar_window_coords_add (struct t_gui_bar_window *bar_window,
+ int index_item, int index_subitem,
+ int index_line,
+ int x, int y);
+extern void gui_bar_window_coords_free (struct t_gui_bar_window *bar_window);
+extern void gui_bar_window_insert (struct t_gui_bar_window *bar_window,
+ struct t_gui_window *window);
+extern void gui_bar_window_new (struct t_gui_bar *bar,
+ struct t_gui_window *window);
extern void gui_bar_window_free (struct t_gui_bar_window *bar_window,
struct t_gui_window *window);
extern int gui_bar_window_remove_unused_bars (struct t_gui_window *window);
@@ -72,6 +101,8 @@ extern void gui_bar_window_scroll (struct t_gui_bar_window *bar_window,
int add_x, int scroll_beginning,
int scroll_end, int add, int percent,
int value);
+extern struct t_hdata *gui_bar_window_hdata_bar_window_cb (void *data,
+ const char *hdata_name);
extern int gui_bar_window_add_to_infolist (struct t_infolist *infolist,
struct t_gui_bar_window *bar_window);
extern void gui_bar_window_print_log (struct t_gui_bar_window *bar_window);
diff --git a/src/gui/gui-bar.c b/src/gui/gui-bar.c
index 381f4fdcb..d7ec19aee 100644
--- a/src/gui/gui-bar.c
+++ b/src/gui/gui-bar.c
@@ -637,24 +637,54 @@ gui_bar_apply_current_size (struct t_gui_bar *bar)
}
/*
- * gui_bar_free_items_array: free array with items for a bar
+ * gui_bar_free_items_arrays: free arrays with items for a bar
*/
void
-gui_bar_free_items_array (struct t_gui_bar *bar)
+gui_bar_free_items_arrays (struct t_gui_bar *bar)
{
- int i;
+ int i, j;
for (i = 0; i < bar->items_count; i++)
{
if (bar->items_array[i])
string_free_split (bar->items_array[i]);
+ for (j = 0; j < bar->items_subcount[i]; j++)
+ {
+ if (bar->items_prefix[i][j])
+ free (bar->items_prefix[i][j]);
+ if (bar->items_name[i][j])
+ free (bar->items_name[i][j]);
+ if (bar->items_suffix[i][j])
+ free (bar->items_suffix[i][j]);
+ }
+ if (bar->items_prefix[i])
+ free (bar->items_prefix[i]);
+ if (bar->items_name[i])
+ free (bar->items_name[i]);
+ if (bar->items_suffix[i])
+ free (bar->items_suffix[i]);
}
if (bar->items_array)
{
free (bar->items_array);
bar->items_array = NULL;
}
+ if (bar->items_prefix)
+ {
+ free (bar->items_prefix);
+ bar->items_prefix = NULL;
+ }
+ if (bar->items_name)
+ {
+ free (bar->items_name);
+ bar->items_name = NULL;
+ }
+ if (bar->items_suffix)
+ {
+ free (bar->items_suffix);
+ bar->items_suffix = NULL;
+ }
if (bar->items_subcount)
{
free (bar->items_subcount);
@@ -670,10 +700,10 @@ gui_bar_free_items_array (struct t_gui_bar *bar)
void
gui_bar_set_items_array (struct t_gui_bar *bar, const char *items)
{
- int i, count;
+ int i, j, count;
char **tmp_array;
- gui_bar_free_items_array (bar);
+ gui_bar_free_items_arrays (bar);
if (items && items[0])
{
@@ -683,10 +713,29 @@ gui_bar_set_items_array (struct t_gui_bar *bar, const char *items)
bar->items_count = count;
bar->items_subcount = malloc (count * sizeof (*bar->items_subcount));
bar->items_array = malloc (count * sizeof (*bar->items_array));
+ bar->items_prefix = malloc (count * sizeof (*bar->items_prefix));
+ bar->items_name = malloc (count * sizeof (*bar->items_name));
+ bar->items_suffix = malloc (count * sizeof (*bar->items_suffix));
for (i = 0; i < count; i++)
{
bar->items_array[i] = string_split (tmp_array[i], "+", 0, 0,
&(bar->items_subcount[i]));
+ if (bar->items_subcount[i] > 0)
+ {
+ bar->items_prefix[i] = malloc (bar->items_subcount[i] *
+ sizeof (*(bar->items_prefix[i])));
+ bar->items_name[i] = malloc (bar->items_subcount[i] *
+ sizeof (*(bar->items_name[i])));
+ bar->items_suffix[i] = malloc (bar->items_subcount[i] *
+ sizeof (*(bar->items_suffix[i])));
+ for (j = 0; j < bar->items_subcount[i]; j++)
+ {
+ gui_bar_item_set_prefix_name_suffix (bar->items_array[i][j],
+ &bar->items_prefix[i][j],
+ &bar->items_name[i][j],
+ &bar->items_suffix[i][j]);
+ }
+ }
}
}
string_free_split (tmp_array);
@@ -722,6 +771,8 @@ gui_bar_config_change_hidden (void *data, struct t_config_option *option)
{
struct t_gui_bar *ptr_bar;
struct t_gui_window *ptr_win;
+ struct t_gui_bar_window *ptr_bar_win;
+ int bar_window_exists;
/* make C compiler happy */
(void) data;
@@ -729,26 +780,43 @@ gui_bar_config_change_hidden (void *data, struct t_config_option *option)
ptr_bar = gui_bar_search_with_option_name (option->name);
if (ptr_bar)
{
- /* free bar windows */
- for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
+ if (CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_ROOT)
{
- gui_bar_free_bar_windows (ptr_bar);
+ if (CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
+ {
+ gui_bar_window_free (ptr_bar->bar_window, NULL);
+ ptr_bar->bar_window = NULL;
+ }
+ else
+ {
+ gui_bar_window_new (ptr_bar, NULL);
+ }
}
-
- for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
+ else
{
- for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
+ for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
{
- if (!CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN])
- && (CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_TYPE]) != GUI_BAR_TYPE_ROOT))
+ bar_window_exists = 0;
+ for (ptr_bar_win = ptr_win->bar_windows; ptr_bar_win;
+ ptr_bar_win = ptr_bar_win->next_bar_window)
+ {
+ if (ptr_bar_win->bar == ptr_bar)
+ {
+ if (CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
+ gui_bar_window_free (ptr_bar_win, ptr_win);
+ else
+ bar_window_exists = 1;
+ }
+ }
+ if (!bar_window_exists
+ && !CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN]))
{
gui_bar_window_new (ptr_bar, ptr_win);
}
}
}
+ gui_window_ask_refresh (1);
}
-
- gui_window_ask_refresh (1);
}
/*
@@ -760,6 +828,7 @@ gui_bar_config_change_priority (void *data, struct t_config_option *option)
{
struct t_gui_bar *ptr_bar;
struct t_gui_window *ptr_win;
+ struct t_gui_bar_window *bar_windows, *ptr_bar_win, *next_bar_win;
/* make C compiler happy */
(void) data;
@@ -785,26 +854,24 @@ gui_bar_config_change_priority (void *data, struct t_config_option *option)
gui_bar_insert (ptr_bar);
- /* free bar windows */
- for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
- {
- gui_bar_free_bar_windows (ptr_bar);
- }
-
for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
{
- for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
+ bar_windows = ptr_win->bar_windows;
+ ptr_win->bar_windows = NULL;
+ ptr_win->last_bar_window = NULL;
+ ptr_bar_win = bar_windows;
+ while (ptr_bar_win)
{
- if (!CONFIG_BOOLEAN(ptr_bar->options[GUI_BAR_OPTION_HIDDEN])
- && (CONFIG_INTEGER(ptr_bar->options[GUI_BAR_OPTION_TYPE]) != GUI_BAR_TYPE_ROOT))
- {
- gui_bar_window_new (ptr_bar, ptr_win);
- }
+ next_bar_win = ptr_bar_win->next_bar_window;
+
+ gui_bar_window_insert (ptr_bar_win, ptr_win);
+
+ ptr_bar_win = next_bar_win;
}
}
+
+ gui_window_ask_refresh (1);
}
-
- gui_window_ask_refresh (1);
}
/*
@@ -1468,6 +1535,9 @@ gui_bar_alloc (const char *name)
new_bar->conditions_array = NULL;
new_bar->items_count = 0;
new_bar->items_array = NULL;
+ new_bar->items_prefix = NULL;
+ new_bar->items_name = NULL;
+ new_bar->items_suffix = NULL;
new_bar->bar_window = NULL;
new_bar->bar_refresh_needed = 0;
new_bar->prev_bar = NULL;
@@ -1533,6 +1603,9 @@ gui_bar_new_with_options (const char *name,
new_bar->items_count = 0;
new_bar->items_subcount = NULL;
new_bar->items_array = NULL;
+ new_bar->items_prefix = NULL;
+ new_bar->items_name = NULL;
+ new_bar->items_suffix = NULL;
gui_bar_set_items_array (new_bar, CONFIG_STRING(items));
new_bar->bar_window = NULL;
new_bar->bar_refresh_needed = 1;
@@ -1983,7 +2056,11 @@ gui_bar_scroll (struct t_gui_bar *bar, struct t_gui_buffer *buffer,
scroll++;
}
else
- return 0;
+ {
+ /* auto-detect if we scroll X/Y, according to filling */
+ if (gui_bar_get_filling (bar) == GUI_BAR_FILLING_HORIZONTAL)
+ add_x = 1;
+ }
if ((scroll[0] == 'b') || (scroll[0] == 'B'))
{
@@ -2032,9 +2109,11 @@ gui_bar_scroll (struct t_gui_bar *bar, struct t_gui_buffer *buffer,
}
if (CONFIG_INTEGER(bar->options[GUI_BAR_OPTION_TYPE]) == GUI_BAR_TYPE_ROOT)
+ {
gui_bar_window_scroll (bar->bar_window, NULL,
add_x, scroll_beginning, scroll_end,
add, percent, number);
+ }
else
{
for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
@@ -2055,7 +2134,8 @@ gui_bar_scroll (struct t_gui_bar *bar, struct t_gui_buffer *buffer,
}
}
- free (str);
+ if (str)
+ free (str);
return 1;
}
@@ -2101,7 +2181,7 @@ gui_bar_free (struct t_gui_bar *bar)
}
if (bar->conditions_array)
string_free_split (bar->conditions_array);
- gui_bar_free_items_array (bar);
+ gui_bar_free_items_arrays (bar);
free (bar);
}
@@ -2129,17 +2209,25 @@ gui_bar_free_bar_windows (struct t_gui_bar *bar)
struct t_gui_window *ptr_win;
struct t_gui_bar_window *ptr_bar_win, *next_bar_win;
- for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
+ if (bar->bar_window)
{
- ptr_bar_win = ptr_win->bar_windows;
- while (ptr_bar_win)
+ gui_bar_window_free (bar->bar_window, NULL);
+ bar->bar_window = NULL;
+ }
+ else
+ {
+ for (ptr_win = gui_windows; ptr_win; ptr_win = ptr_win->next_window)
{
- next_bar_win = ptr_bar_win->next_bar_window;
-
- if (ptr_bar_win->bar == bar)
- gui_bar_window_free (ptr_bar_win, ptr_win);
-
- ptr_bar_win = next_bar_win;
+ ptr_bar_win = ptr_win->bar_windows;
+ while (ptr_bar_win)
+ {
+ next_bar_win = ptr_bar_win->next_bar_window;
+
+ if (ptr_bar_win->bar == bar)
+ gui_bar_window_free (ptr_bar_win, ptr_win);
+
+ ptr_bar_win = next_bar_win;
+ }
}
}
}
@@ -2166,7 +2254,10 @@ gui_bar_hdata_bar_cb (void *data, const char *hdata_name)
HDATA_VAR(struct t_gui_bar, items_count, INTEGER, NULL);
HDATA_VAR(struct t_gui_bar, items_subcount, POINTER, NULL);
HDATA_VAR(struct t_gui_bar, items_array, POINTER, NULL);
- HDATA_VAR(struct t_gui_bar, bar_window, POINTER, NULL);
+ HDATA_VAR(struct t_gui_bar, items_prefix, POINTER, NULL);
+ HDATA_VAR(struct t_gui_bar, items_name, POINTER, NULL);
+ HDATA_VAR(struct t_gui_bar, items_suffix, POINTER, NULL);
+ HDATA_VAR(struct t_gui_bar, bar_window, POINTER, "bar_window");
HDATA_VAR(struct t_gui_bar, bar_refresh_needed, INTEGER, NULL);
HDATA_VAR(struct t_gui_bar, prev_bar, POINTER, hdata_name);
HDATA_VAR(struct t_gui_bar, next_bar, POINTER, hdata_name);
@@ -2247,6 +2338,16 @@ gui_bar_add_to_infolist (struct t_infolist *infolist,
if (!infolist_new_var_string (ptr_item, option_name,
bar->items_array[i][j]))
return 0;
+ snprintf (option_name, sizeof (option_name),
+ "items_prefix_%05d_%05d", i + 1, j + 1);
+ if (!infolist_new_var_string (ptr_item, option_name,
+ bar->items_prefix[i][j]))
+ return 0;
+ snprintf (option_name, sizeof (option_name),
+ "items_suffix_%05d_%05d", i + 1, j + 1);
+ if (!infolist_new_var_string (ptr_item, option_name,
+ bar->items_suffix[i][j]))
+ return 0;
}
}
if (!infolist_new_var_pointer (ptr_item, "bar_window", bar->bar_window))
@@ -2307,8 +2408,13 @@ gui_bar_print_log ()
i, ptr_bar->items_subcount[i]);
for (j = 0; j < ptr_bar->items_subcount[i]; j++)
{
- log_printf (" items_array[%03d][%03d]: '%s'",
- i, j, ptr_bar->items_array[i][j]);
+ log_printf (" items_array[%03d][%03d]: '%s' "
+ "(prefix: '%s', name: '%s', suffix: '%s')",
+ i, j,
+ ptr_bar->items_array[i][j],
+ ptr_bar->items_prefix[i][j],
+ ptr_bar->items_name[i][j],
+ ptr_bar->items_suffix[i][j]);
}
}
log_printf (" bar_window . . . . . . : 0x%lx", ptr_bar->bar_window);
diff --git a/src/gui/gui-bar.h b/src/gui/gui-bar.h
index e53626fa5..cb5e8b8d8 100644
--- a/src/gui/gui-bar.h
+++ b/src/gui/gui-bar.h
@@ -20,6 +20,7 @@
#ifndef __WEECHAT_GUI_BAR_H
#define __WEECHAT_GUI_BAR_H 1
+struct t_infolist;
struct t_weechat_plugin;
struct t_gui_window;
struct t_gui_buffer;
@@ -89,6 +90,9 @@ struct t_gui_bar
int items_count; /* number of bar items */
int *items_subcount; /* number of sub items */
char ***items_array; /* bar items (after split) */
+ char ***items_prefix; /* prefix for each (sub)item */
+ char ***items_name; /* name for each (sub)item */
+ char ***items_suffix; /* suffix for each (sub)item */
struct t_gui_bar_window *bar_window; /* pointer to bar window */
/* (for type root only) */
int bar_refresh_needed; /* refresh for bar is needed? */
diff --git a/src/gui/gui-color.c b/src/gui/gui-color.c
index 66d3b4f33..1dc72ec0f 100644
--- a/src/gui/gui-color.c
+++ b/src/gui/gui-color.c
@@ -515,6 +515,8 @@ gui_color_decode (const char *string, const char *replacement)
case GUI_COLOR_BAR_START_INPUT_CHAR:
case GUI_COLOR_BAR_START_INPUT_HIDDEN_CHAR:
case GUI_COLOR_BAR_MOVE_CURSOR_CHAR:
+ case GUI_COLOR_BAR_START_ITEM:
+ case GUI_COLOR_BAR_START_LINE_ITEM:
ptr_string++;
break;
}
diff --git a/src/gui/gui-color.h b/src/gui/gui-color.h
index d4c6fb633..b0f114cfe 100644
--- a/src/gui/gui-color.h
+++ b/src/gui/gui-color.h
@@ -104,6 +104,8 @@ enum t_gui_color_enum
#define GUI_COLOR_BAR_START_INPUT_CHAR '_'
#define GUI_COLOR_BAR_START_INPUT_HIDDEN_CHAR '-'
#define GUI_COLOR_BAR_MOVE_CURSOR_CHAR '#'
+#define GUI_COLOR_BAR_START_ITEM 'i'
+#define GUI_COLOR_BAR_START_LINE_ITEM 'l'
#define GUI_COLOR_EXTENDED_FLAG 0x0100000
#define GUI_COLOR_EXTENDED_BOLD_FLAG 0x0200000
diff --git a/src/gui/gui-completion.c b/src/gui/gui-completion.c
index 4bdcc9c98..6f6118b62 100644
--- a/src/gui/gui-completion.c
+++ b/src/gui/gui-completion.c
@@ -1027,7 +1027,7 @@ gui_completion_complete (struct t_gui_completion *completion)
other_completion++;
}
if (completion->word_found &&
- (string_strcasecmp (ptr_item->data, completion->word_found) == 0))
+ (strcmp (ptr_item->data, completion->word_found) == 0))
word_found_seen = 1;
if (completion->direction < 0)
diff --git a/src/gui/gui-cursor.c b/src/gui/gui-cursor.c
new file mode 100644
index 000000000..f210826cf
--- /dev/null
+++ b/src/gui/gui-cursor.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2011 Sebastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * gui-cursor.c: functions for free movement of cursor (used by all GUI)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../core/weechat.h"
+#include "gui-cursor.h"
+#include "gui-bar.h"
+#include "gui-bar-window.h"
+#include "gui-buffer.h"
+#include "gui-chat.h"
+#include "gui-color.h"
+#include "gui-input.h"
+#include "gui-window.h"
+
+
+int gui_cursor_mode = 0; /* cursor mode? (free movement) */
+int gui_cursor_debug = 0; /* debug mode (show info in input) */
+int gui_cursor_x = 0; /* position of cursor in cursor mode */
+int gui_cursor_y = 0; /* position of cursor in cursor mode */
+
+
+/*
+ * gui_cursor_mode_toggle: toggle cursor mode
+ */
+
+void
+gui_cursor_mode_toggle ()
+{
+ gui_cursor_mode ^= 1;
+
+ if (gui_cursor_mode)
+ {
+ if (gui_cursor_debug)
+ gui_input_delete_line (gui_current_window->buffer);
+ gui_cursor_x = gui_window_cursor_x;
+ gui_cursor_y = gui_window_cursor_y;
+ gui_cursor_move_xy (0, 0);
+ }
+ else
+ {
+ /* restore input (and move cursor in input) */
+ if (gui_cursor_debug)
+ gui_input_delete_line (gui_current_window->buffer);
+ gui_input_text_changed_modifier_and_signal (gui_current_window->buffer, 0);
+ gui_buffer_ask_chat_refresh (gui_current_window->buffer, 2);
+ }
+}
+
+/*
+ * gui_cursor_debug_toggle: toggle debug for cursor mode
+ */
+
+void
+gui_cursor_debug_toggle ()
+{
+ gui_cursor_debug ^= 1;
+
+ if (gui_cursor_debug)
+ gui_chat_printf (NULL, _("Debug enabled for cursor mode"));
+ else
+ gui_chat_printf (NULL, _("Debug disabled for cursor mode"));
+}
+
+/*
+ * gui_cursor_get_info: get info about what is pointed by cursor at (x,y)
+ */
+
+void
+gui_cursor_get_info (int x, int y, struct t_gui_cursor_info *cursor_info)
+{
+ cursor_info->x = x;
+ cursor_info->y = y;
+
+ /* search window */
+ cursor_info->window = gui_window_search_by_xy (x, y);
+
+ /* chat area in this window? */
+ if (cursor_info->window
+ && (x >= (cursor_info->window)->win_chat_x)
+ && (y >= (cursor_info->window)->win_chat_y)
+ && (x <= (cursor_info->window)->win_chat_x + (cursor_info->window)->win_chat_width - 1)
+ && (y <= (cursor_info->window)->win_chat_y + (cursor_info->window)->win_chat_height - 1))
+ {
+ cursor_info->chat = 1;
+ }
+ else
+ cursor_info->chat = 0;
+
+ /* search bar window, item, and line/col in item */
+ gui_bar_window_search_by_xy (cursor_info->window, x, y,
+ &cursor_info->bar_window,
+ &cursor_info->bar_item,
+ &cursor_info->item_line,
+ &cursor_info->item_col);
+}
+
+/*
+ * gui_cursor_display_debug_info: display debug info about (x,y) in input
+ */
+
+void
+gui_cursor_display_debug_info ()
+{
+ struct t_gui_cursor_info cursor_info;
+ char str_info[1024];
+
+ if (!gui_cursor_debug)
+ return;
+
+ gui_cursor_get_info (gui_cursor_x, gui_cursor_y, &cursor_info);
+
+ snprintf (str_info, sizeof (str_info),
+ "%s(%d,%d) window:0x%lx (buffer: %s), chat: %d, "
+ "bar_window:0x%lx (bar: %s, item: %s, line: %d, col: %d)",
+ gui_color_get_custom ("yellow,red"),
+ cursor_info.x, cursor_info.y,
+ (long unsigned int)cursor_info.window,
+ (cursor_info.window) ? (cursor_info.window)->buffer->name : "-",
+ cursor_info.chat,
+ (long unsigned int)cursor_info.bar_window,
+ (cursor_info.bar_window) ? (cursor_info.bar_window)->bar->name : "-",
+ (cursor_info.bar_item) ? cursor_info.bar_item : "-",
+ cursor_info.item_line,
+ cursor_info.item_col);
+ gui_input_delete_line (gui_current_window->buffer);
+ gui_input_insert_string (gui_current_window->buffer, str_info, -1);
+}
+
+/*
+ * gui_cursor_move_xy: set cursor at position (x,y)
+ */
+
+void
+gui_cursor_move_xy (int x, int y)
+{
+ if (!gui_cursor_mode)
+ gui_cursor_mode_toggle ();
+
+ gui_cursor_x = x;
+ gui_cursor_y = y;
+
+ if (gui_cursor_x < 0)
+ gui_cursor_x = 0;
+ else if (gui_cursor_x > gui_window_get_width () - 1)
+ gui_cursor_x = gui_window_get_width () - 1;
+
+ if (gui_cursor_y < 0)
+ gui_cursor_y = 0;
+ else if (gui_cursor_y > gui_window_get_height () - 1)
+ gui_cursor_y = gui_window_get_height () - 1;
+
+ gui_cursor_display_debug_info ();
+ gui_window_move_cursor ();
+}
+
+/*
+ * gui_cursor_move_add_xy: move cursor by adding values to (x,y)
+ */
+
+void
+gui_cursor_move_add_xy (int add_x, int add_y)
+{
+ if (!gui_cursor_mode)
+ gui_cursor_mode_toggle ();
+
+ gui_cursor_x += add_x;
+ gui_cursor_y += add_y;
+
+ if (gui_cursor_x < 0)
+ gui_cursor_x = gui_window_get_width () - 1;
+ else if (gui_cursor_x > gui_window_get_width () - 1)
+ gui_cursor_x = 0;
+
+ if (gui_cursor_y < 0)
+ gui_cursor_y = gui_window_get_height () - 1;
+ else if (gui_cursor_y > gui_window_get_height () - 1)
+ gui_cursor_y = 0;
+
+ gui_cursor_display_debug_info ();
+ gui_window_move_cursor ();
+}
+
+/*
+ * gui_cursor_move_area_add_xy: move cursor to another area by adding values to
+ * (x,y)
+ */
+
+void
+gui_cursor_move_area_add_xy (int add_x, int add_y)
+{
+ int x, y, width, height, area_found;
+ struct t_gui_cursor_info cursor_info_old, cursor_info_new;
+
+ if (!gui_cursor_mode)
+ gui_cursor_mode_toggle ();
+
+ area_found = 0;
+
+ x = gui_cursor_x;
+ y = gui_cursor_y;
+ width = gui_window_get_width ();
+ height = gui_window_get_height ();
+
+ gui_cursor_get_info (x, y, &cursor_info_old);
+
+ if (add_x != 0)
+ x += add_x;
+ else
+ y += add_y;
+
+ while ((x >= 0) && (x < width) && (y >= 0) && (y < height))
+ {
+ gui_cursor_get_info (x, y, &cursor_info_new);
+ if (((cursor_info_new.window && cursor_info_new.chat)
+ || cursor_info_new.bar_window)
+ && ((cursor_info_old.window != cursor_info_new.window)
+ || (cursor_info_old.bar_window != cursor_info_new.bar_window)))
+ {
+ area_found = 1;
+ break;
+ }
+
+ if (add_x != 0)
+ x += add_x;
+ else
+ y += add_y;
+ }
+
+ if (area_found)
+ {
+ if (cursor_info_new.window && cursor_info_new.chat)
+ {
+ x = (cursor_info_new.window)->win_chat_x;
+ y = (cursor_info_new.window)->win_chat_y;
+ }
+ else if (cursor_info_new.bar_window)
+ {
+ x = (cursor_info_new.bar_window)->x;
+ y = (cursor_info_new.bar_window)->y;
+ }
+ else
+ area_found = 0;
+ }
+
+ if (area_found)
+ {
+ gui_cursor_x = x;
+ gui_cursor_y = y;
+ gui_cursor_display_debug_info ();
+ gui_window_move_cursor ();
+ }
+}
+
+/*
+ * gui_cursor_move_area: move cursor to another area by name
+ */
+
+void
+gui_cursor_move_area (const char *area)
+{
+ int area_found, x, y;
+ struct t_gui_bar_window *ptr_bar_win;
+ struct t_gui_bar *ptr_bar;
+
+ area_found = 0;
+ x = 0;
+ y = 0;
+
+ if (strcmp (area, "chat") == 0)
+ {
+ area_found = 1;
+ x = gui_current_window->win_chat_x;
+ y = gui_current_window->win_chat_y;
+ }
+ else
+ {
+ for (ptr_bar_win = gui_current_window->bar_windows; ptr_bar_win;
+ ptr_bar_win = ptr_bar_win->next_bar_window)
+ {
+ if (strcmp (ptr_bar_win->bar->name, area) == 0)
+ {
+ area_found = 1;
+ x = ptr_bar_win->x;
+ y = ptr_bar_win->y;
+ break;
+ }
+ }
+ if (!area_found)
+ {
+ for (ptr_bar = gui_bars; ptr_bar; ptr_bar = ptr_bar->next_bar)
+ {
+ if (ptr_bar->bar_window && (strcmp (ptr_bar->name, area) == 0))
+ {
+ area_found = 1;
+ x = ptr_bar->bar_window->x;
+ y = ptr_bar->bar_window->y;
+ }
+ }
+ }
+ }
+
+ if (area_found)
+ {
+ if (!gui_cursor_mode)
+ gui_cursor_mode_toggle ();
+ gui_cursor_x = x;
+ gui_cursor_y = y;
+ gui_cursor_display_debug_info ();
+ gui_window_move_cursor ();
+ }
+}
diff --git a/src/gui/gui-cursor.h b/src/gui/gui-cursor.h
new file mode 100644
index 000000000..b27b8f4eb
--- /dev/null
+++ b/src/gui/gui-cursor.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 Sebastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEECHAT_GUI_CURSOR_H
+#define __WEECHAT_GUI_CURSOR_H 1
+
+/* cursor structures */
+
+struct t_gui_cursor_info
+{
+ int x, y; /* (x,y) on screen */
+ struct t_gui_window *window; /* window found */
+ int chat; /* 1 for chat area, otherwise 0 */
+ struct t_gui_bar_window *bar_window; /* bar window found */
+ char *bar_item; /* bar item found */
+ int item_line; /* line in bar item */
+ int item_col; /* column in bar item */
+};
+
+/* cursor variables */
+
+extern int gui_cursor_mode;
+extern int gui_cursor_debug;
+extern int gui_cursor_x;
+extern int gui_cursor_y;
+
+/* cursor functions */
+
+extern void gui_cursor_mode_toggle ();
+extern void gui_cursor_debug_toggle ();
+extern void gui_cursor_get_info (int x, int y,
+ struct t_gui_cursor_info *cursor_info);
+extern void gui_cursor_move_xy (int x, int y);
+extern void gui_cursor_move_add_xy (int add_x, int add_y);
+extern void gui_cursor_move_area_add_xy (int add_x, int add_y);
+extern void gui_cursor_move_area (const char *area);
+
+#endif /* __WEECHAT_GUI_CURSOR_H */
diff --git a/src/gui/gui-input.c b/src/gui/gui-input.c
index 7828e77a9..aa5c5dc5a 100644
--- a/src/gui/gui-input.c
+++ b/src/gui/gui-input.c
@@ -38,6 +38,7 @@
#include "gui-input.h"
#include "gui-buffer.h"
#include "gui-completion.h"
+#include "gui-cursor.h"
#include "gui-history.h"
#include "gui-hotlist.h"
#include "gui-key.h"
@@ -117,26 +118,29 @@ gui_input_text_changed_modifier_and_signal (struct t_gui_buffer *buffer,
{
char str_buffer[128], *new_input;
- if (save_undo)
- gui_buffer_undo_add (buffer);
-
- /* send modifier, and change input if needed */
- snprintf (str_buffer, sizeof (str_buffer),
- "0x%lx", (long unsigned int)buffer);
- new_input = hook_modifier_exec (NULL,
- "input_text_content",
- str_buffer,
- (buffer->input_buffer) ?
- buffer->input_buffer : "");
- if (new_input)
+ if (!gui_cursor_mode)
{
- if (!buffer->input_buffer
- || strcmp (new_input, buffer->input_buffer) != 0)
+ if (save_undo)
+ gui_buffer_undo_add (buffer);
+
+ /* send modifier, and change input if needed */
+ snprintf (str_buffer, sizeof (str_buffer),
+ "0x%lx", (long unsigned int)buffer);
+ new_input = hook_modifier_exec (NULL,
+ "input_text_content",
+ str_buffer,
+ (buffer->input_buffer) ?
+ buffer->input_buffer : "");
+ if (new_input)
{
- /* input has been changed by modifier, use it */
- gui_input_replace_input (buffer, new_input);
+ if (!buffer->input_buffer
+ || strcmp (new_input, buffer->input_buffer) != 0)
+ {
+ /* input has been changed by modifier, use it */
+ gui_input_replace_input (buffer, new_input);
+ }
+ free (new_input);
}
- free (new_input);
}
/* send signal */
@@ -1339,10 +1343,10 @@ gui_input_hotlist_clear (struct t_gui_buffer *buffer)
*/
void
-gui_input_grab_key (struct t_gui_buffer *buffer)
+gui_input_grab_key (struct t_gui_buffer *buffer, const char *delay)
{
if (buffer->input)
- gui_key_grab_init (0);
+ gui_key_grab_init (0, delay);
}
/*
@@ -1351,10 +1355,10 @@ gui_input_grab_key (struct t_gui_buffer *buffer)
*/
void
-gui_input_grab_key_command (struct t_gui_buffer *buffer)
+gui_input_grab_key_command (struct t_gui_buffer *buffer, const char *delay)
{
if (buffer->input)
- gui_key_grab_init (1);
+ gui_key_grab_init (1, delay);
}
/*
diff --git a/src/gui/gui-input.h b/src/gui/gui-input.h
index dbad22b7a..89a919baa 100644
--- a/src/gui/gui-input.h
+++ b/src/gui/gui-input.h
@@ -70,8 +70,10 @@ extern void gui_input_jump_last_buffer (struct t_gui_buffer *buffer);
extern void gui_input_jump_previously_visited_buffer (struct t_gui_buffer *buffer);
extern void gui_input_jump_next_visited_buffer (struct t_gui_buffer *buffer);
extern void gui_input_hotlist_clear (struct t_gui_buffer *buffer);
-extern void gui_input_grab_key (struct t_gui_buffer *buffer);
-extern void gui_input_grab_key_command (struct t_gui_buffer *buffer);
+extern void gui_input_grab_key (struct t_gui_buffer *buffer,
+ const char *delay);
+extern void gui_input_grab_key_command (struct t_gui_buffer *buffer,
+ const char *delay);
extern void gui_input_scroll_unread (struct t_gui_buffer *buffer);
extern void gui_input_set_unread ();
extern void gui_input_set_unread_current (struct t_gui_buffer *buffer);
diff --git a/src/gui/gui-key.c b/src/gui/gui-key.c
index 30d40d65f..7bf4ccb6f 100644
--- a/src/gui/gui-key.c
+++ b/src/gui/gui-key.c
@@ -32,6 +32,7 @@
#include <time.h>
#include "../core/weechat.h"
+#include "../core/wee-hashtable.h"
#include "../core/wee-hdata.h"
#include "../core/wee-hook.h"
#include "../core/wee-infolist.h"
@@ -41,11 +42,15 @@
#include "../core/wee-utf8.h"
#include "../plugins/plugin.h"
#include "gui-key.h"
+#include "gui-bar.h"
+#include "gui-bar-window.h"
#include "gui-buffer.h"
#include "gui-chat.h"
#include "gui-color.h"
#include "gui-completion.h"
+#include "gui-cursor.h"
#include "gui-input.h"
+#include "gui-mouse.h"
#include "gui-window.h"
@@ -57,14 +62,15 @@ int gui_keys_count[GUI_KEY_NUM_CONTEXTS]; /* keys number */
int gui_default_keys_count[GUI_KEY_NUM_CONTEXTS]; /* default keys number */
char *gui_key_context_string[GUI_KEY_NUM_CONTEXTS] =
-{ "default", "search" };
+{ "default", "search", "cursor", "mouse" };
int gui_key_verbose = 0; /* 1 to see some messages */
-char gui_key_combo_buffer[128]; /* buffer used for combos */
+char gui_key_combo_buffer[256]; /* buffer used for combos */
int gui_key_grab = 0; /* 1 if grab mode enabled (alt-k) */
int gui_key_grab_count = 0; /* number of keys pressed in grab mode */
int gui_key_grab_command = 0; /* grab command bound to key? */
+int gui_key_grab_delay = 0; /* delay for grab (default is 500) */
int *gui_key_buffer = NULL; /* input buffer (for paste detection) */
int gui_key_buffer_alloc = 0; /* input buffer allocated size */
@@ -136,6 +142,9 @@ gui_key_search_context (const char *context)
int
gui_key_get_current_context ()
{
+ if (gui_cursor_mode)
+ return GUI_KEY_CONTEXT_CURSOR;
+
if (gui_current_window
&& (gui_current_window->buffer->text_search != GUI_TEXT_SEARCH_DISABLED))
return GUI_KEY_CONTEXT_SEARCH;
@@ -148,24 +157,44 @@ gui_key_get_current_context ()
*/
void
-gui_key_grab_init (int grab_command)
+gui_key_grab_init (int grab_command, const char *delay)
{
+ long milliseconds;
+ char *error;
+
gui_key_grab = 1;
gui_key_grab_count = 0;
gui_key_grab_command = grab_command;
+
+ gui_key_grab_delay = GUI_KEY_GRAB_DELAY_DEFAULT;
+ if (delay != NULL)
+ {
+ error = NULL;
+ milliseconds = strtol (delay, &error, 10);
+ if (error && !error[0] && (milliseconds >= 0))
+ {
+ gui_key_grab_delay = milliseconds;
+ if (gui_key_grab_delay == 0)
+ gui_key_grab_delay = 1;
+ }
+ }
}
/*
- * gui_key_grab_end: insert grabbed key in input buffer
+ * gui_key_grab_end_timer_cb: insert grabbed key in input buffer
*/
-void
-gui_key_grab_end ()
+int
+gui_key_grab_end_timer_cb (void *data, int remaining_calls)
{
char *expanded_key;
struct t_gui_key *ptr_key;
- /* get expanded name (for example: ^U => ctrl-u) */
+ /* make C compiler happy */
+ (void) data;
+ (void) remaining_calls;
+
+ /* get expanded name (for example: \x01+U => ctrl-u) */
expanded_key = gui_key_get_expanded_name (gui_key_combo_buffer);
if (expanded_key)
@@ -195,11 +224,13 @@ gui_key_grab_end ()
gui_key_grab_count = 0;
gui_key_grab_command = 0;
gui_key_combo_buffer[0] = '\0';
+
+ return WEECHAT_RC_OK;
}
/*
* gui_key_get_internal_code: get internal code from user key name
- * for example: return "^R" for "ctrl-R"
+ * for example: return "\x01+R" for "ctrl-R"
*/
char *
@@ -214,17 +245,17 @@ gui_key_get_internal_code (const char *key)
{
if (strncmp (key, "meta2-", 6) == 0)
{
- strcat (result, "^[[");
+ strcat (result, "\x01[[");
key += 6;
}
if (strncmp (key, "meta-", 5) == 0)
{
- strcat (result, "^[");
+ strcat (result, "\x01[");
key += 5;
}
else if (strncmp (key, "ctrl-", 5) == 0)
{
- strcat (result, "^");
+ strcat (result, "\x01");
key += 5;
}
else
@@ -242,7 +273,7 @@ gui_key_get_internal_code (const char *key)
/*
* gui_key_get_expanded_name: get expanded name from internal key code
- * for example: return "ctrl-R" for "^R"
+ * for example: return "ctrl-R" for "\x01+R"
*/
char *
@@ -259,17 +290,17 @@ gui_key_get_expanded_name (const char *key)
result[0] = '\0';
while (key[0])
{
- if (strncmp (key, "^[[", 3) == 0)
+ if (strncmp (key, "\x01[[", 3) == 0)
{
strcat (result, "meta2-");
key += 3;
}
- if (strncmp (key, "^[", 2) == 0)
+ if (strncmp (key, "\x01[", 2) == 0)
{
strcat (result, "meta-");
key += 2;
}
- else if ((key[0] == '^') && (key[1]))
+ else if ((key[0] == '\x01') && (key[1]))
{
strcat (result, "ctrl-");
key++;
@@ -403,8 +434,10 @@ gui_key_new (struct t_gui_buffer *buffer, int context, const char *key,
if (gui_key_verbose)
{
- gui_chat_printf (NULL,
- _("New key binding: %s%s => %s%s"),
+ gui_chat_printf (gui_current_window->buffer,
+ _("New key binding (context \"%s\"): "
+ "%s%s => %s%s"),
+ gui_key_context_string[context],
(expanded_name) ? expanded_name : new_key->key,
GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS),
GUI_COLOR(GUI_COLOR_CHAT),
@@ -443,10 +476,13 @@ gui_key_search (struct t_gui_key *keys, const char *key)
*/
int
-gui_key_cmp (const char *key, const char *search)
+gui_key_cmp (const char *key, const char *search, int context)
{
int diff;
+ if (context == GUI_KEY_CONTEXT_MOUSE)
+ return strcmp (key, search);
+
while (search[0])
{
diff = utf8_charcmp (key, search);
@@ -472,8 +508,14 @@ gui_key_search_part (struct t_gui_buffer *buffer, int context,
for (ptr_key = (buffer) ? buffer->keys : gui_keys[context]; ptr_key;
ptr_key = ptr_key->next_key)
{
- if (ptr_key->key && (gui_key_cmp (ptr_key->key, key) == 0))
- return ptr_key;
+ if (ptr_key->key
+ && (((context != GUI_KEY_CONTEXT_CURSOR)
+ && (context != GUI_KEY_CONTEXT_MOUSE))
+ || (ptr_key->key[0] != '@')))
+ {
+ if (gui_key_cmp (ptr_key->key, key, context) == 0)
+ return ptr_key;
+ }
}
/* key not found */
@@ -552,6 +594,173 @@ gui_key_unbind (struct t_gui_buffer *buffer, int context, const char *key,
}
/*
+ * gui_key_focus_matching: return 1 if area in key is matching focus area on
+ * screen (cursor/mouse)
+ */
+
+int
+gui_key_focus_matching (const char *key,
+ struct t_gui_cursor_info *cursor_info)
+{
+ int match, area_chat;
+ char *area_bar, *area_item, *pos;
+
+ if (key[1] == '*')
+ return 1;
+
+ match = 0;
+
+ pos = strchr (key, ':');
+ if (pos)
+ {
+ area_chat = 0;
+ area_bar = NULL;
+ area_item = NULL;
+ if (strncmp (key + 1, "chat:", 5) == 0)
+ area_chat = 1;
+ else if (strncmp (key + 1, "bar(", 4) == 0)
+ {
+ area_bar = string_strndup (key + 5, pos - key - 6);
+ }
+ else if (strncmp (key + 1, "item(", 5) == 0)
+ {
+ area_item = string_strndup (key + 6, pos - key - 7);
+ }
+ if (area_chat || area_bar || area_item)
+ {
+ if (area_chat && cursor_info->chat)
+ {
+ match = 1;
+ }
+ else if (area_bar && cursor_info->bar_window
+ && ((strcmp (area_bar, "*") == 0)
+ || (strcmp (area_bar, (cursor_info->bar_window)->bar->name) == 0)))
+ {
+ match = 1;
+ }
+ else if (area_item && cursor_info->bar_item
+ && ((strcmp (area_item, "*") == 0)
+ || (strcmp (area_item, cursor_info->bar_item) == 0)))
+ {
+ match = 1;
+ }
+ }
+
+ if (area_bar)
+ free (area_bar);
+ if (area_item)
+ free (area_item);
+ }
+
+ return match;
+}
+
+/*
+ * gui_key_focus_command: run command according to focus
+ * return 1 if a command was executed, otherwise 0
+ */
+
+int
+gui_key_focus_command (const char *key, int context,
+ int focus_specific, int focus_any,
+ struct t_gui_cursor_info *cursor_info)
+{
+ struct t_gui_key *ptr_key;
+ int i, errors;
+ char *pos, *pos_joker, *command, **commands;
+ struct t_hashtable *hashtable;
+
+ for (ptr_key = gui_keys[context]; ptr_key;
+ ptr_key = ptr_key->next_key)
+ {
+ if (ptr_key->key && (ptr_key->key[0] == '@'))
+ {
+ pos = strchr (ptr_key->key, ':');
+ if (pos)
+ {
+ pos_joker = strchr (ptr_key->key, '*');
+ if (!focus_specific && (!pos_joker || (pos_joker > pos)))
+ continue;
+ if (!focus_any && pos_joker && (pos_joker < pos))
+ continue;
+
+ pos++;
+ if (gui_key_cmp (pos, key, context) == 0)
+ {
+ if (gui_key_focus_matching (ptr_key->key, cursor_info))
+ {
+ hashtable = hook_focus_get_data (cursor_info);
+ if (gui_mouse_debug)
+ {
+ gui_chat_printf (NULL, "Hashtable focus: %s",
+ hashtable_get_string (hashtable,
+ "keys_values"));
+ }
+ command = string_replace_with_hashtable (ptr_key->command,
+ hashtable,
+ &errors);
+ if (command)
+ {
+ if (errors == 0)
+ {
+ if ((context == GUI_KEY_CONTEXT_CURSOR)
+ && gui_cursor_debug)
+ {
+ gui_input_delete_line (gui_current_window->buffer);
+ }
+ commands = string_split_command (command,
+ ';');
+ if (commands)
+ {
+ for (i = 0; commands[i]; i++)
+ {
+ input_data (gui_current_window->buffer, commands[i]);
+ }
+ string_free_split_command (commands);
+ }
+ }
+ free (command);
+ }
+ if (hashtable)
+ hashtable_free (hashtable);
+ return 1;
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * gui_key_focus: treat key pressed in cursor or mouse mode,
+ * looking for keys: "{area}key" in context "cursor" or "mouse"
+ * return 1 if a command was executed, otherwise 0
+ */
+
+int
+gui_key_focus (const char *key, int context)
+{
+ struct t_gui_cursor_info cursor_info;
+
+ if (context == GUI_KEY_CONTEXT_MOUSE)
+ {
+ gui_cursor_get_info (gui_mouse_event_x[0], gui_mouse_event_y[0],
+ &cursor_info);
+ }
+ else
+ {
+ gui_cursor_get_info (gui_cursor_x, gui_cursor_y, &cursor_info);
+ }
+
+ if (gui_key_focus_command (key, context, 1, 0, &cursor_info))
+ return 1;
+
+ return gui_key_focus_command (key, context, 0, 1, &cursor_info);
+}
+
+/*
* gui_key_pressed: treat new key pressed
* return: 1 if key should be added to input buffer
* 0 otherwise
@@ -560,22 +769,52 @@ gui_key_unbind (struct t_gui_buffer *buffer, int context, const char *key,
int
gui_key_pressed (const char *key_str)
{
- int first_key, context;
+ int i, first_key, context, length, length_key;
struct t_gui_key *ptr_key;
- char *buffer_before_key;
- char **commands, **ptr_cmd;
+ char **commands;
+ const char *mouse_key;
/* add key to buffer */
first_key = (gui_key_combo_buffer[0] == '\0');
- strcat (gui_key_combo_buffer, key_str);
+ length = strlen (gui_key_combo_buffer);
+ length_key = strlen (key_str);
+ if (length + length_key + 1 <= (int)sizeof (gui_key_combo_buffer))
+ strcat (gui_key_combo_buffer, key_str);
/* if we are in "show mode", increase counter and return */
if (gui_key_grab)
{
+ if (gui_key_grab_count == 0)
+ {
+ hook_timer (NULL, gui_key_grab_delay, 0, 1,
+ &gui_key_grab_end_timer_cb, NULL);
+ }
gui_key_grab_count++;
return 0;
}
+ /* mode "mouse grab" (mouse event pending) */
+ if (gui_mouse_grab)
+ {
+ mouse_key = gui_mouse_grab_code2key (gui_key_combo_buffer);
+ if (mouse_key)
+ {
+ gui_key_combo_buffer[0] = '\0';
+ strcat (gui_key_combo_buffer, mouse_key);
+ gui_mouse_grab_end ();
+ if (gui_key_combo_buffer[0])
+ {
+ (void) gui_key_focus (gui_key_combo_buffer,
+ GUI_KEY_CONTEXT_MOUSE);
+ gui_key_combo_buffer[0] = '\0';
+ gui_mouse_reset_event ();
+ }
+ }
+ return 0;
+ }
+
+ ptr_key = NULL;
+
context = gui_key_get_current_context ();
switch (context)
{
@@ -601,6 +840,11 @@ gui_key_pressed (const char *key_str)
gui_key_combo_buffer);
}
break;
+ case GUI_KEY_CONTEXT_CURSOR:
+ ptr_key = gui_key_search_part (NULL,
+ GUI_KEY_CONTEXT_CURSOR,
+ gui_key_combo_buffer);
+ break;
}
/* if key is found, then execute action */
@@ -609,29 +853,30 @@ gui_key_pressed (const char *key_str)
if (strcmp (ptr_key->key, gui_key_combo_buffer) == 0)
{
/* exact combo found => execute function or command */
- buffer_before_key =
- (gui_current_window->buffer->input_buffer) ?
- strdup (gui_current_window->buffer->input_buffer) : strdup ("");
gui_key_combo_buffer[0] = '\0';
if (ptr_key->command)
{
commands = string_split_command (ptr_key->command, ';');
if (commands)
{
- for (ptr_cmd = commands; *ptr_cmd; ptr_cmd++)
+ for (i = 0; commands[i]; i++)
{
- input_data (gui_current_window->buffer,
- *ptr_cmd);
+ input_data (gui_current_window->buffer, commands[i]);
}
string_free_split_command (commands);
}
}
-
- if (buffer_before_key)
- free (buffer_before_key);
}
return 0;
}
+ else if (context == GUI_KEY_CONTEXT_CURSOR)
+ {
+ if (gui_key_focus (gui_key_combo_buffer, GUI_KEY_CONTEXT_CURSOR))
+ {
+ gui_key_combo_buffer[0] = '\0';
+ return 0;
+ }
+ }
gui_key_combo_buffer[0] = '\0';
@@ -829,6 +1074,8 @@ struct t_hdata *
gui_key_hdata_key_cb (void *data, const char *hdata_name)
{
struct t_hdata *hdata;
+ int i;
+ char str_list[128];
/* make C compiler happy */
(void) data;
@@ -840,10 +1087,29 @@ gui_key_hdata_key_cb (void *data, const char *hdata_name)
HDATA_VAR(struct t_gui_key, command, STRING, NULL);
HDATA_VAR(struct t_gui_key, prev_key, POINTER, hdata_name);
HDATA_VAR(struct t_gui_key, next_key, POINTER, hdata_name);
- HDATA_LIST(gui_keys);
- HDATA_LIST(last_gui_key);
- HDATA_LIST(gui_default_keys);
- HDATA_LIST(last_gui_default_key);
+ for (i = 0; i < GUI_KEY_NUM_CONTEXTS; i++)
+ {
+ snprintf (str_list, sizeof (str_list),
+ "gui_keys%s%s",
+ (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_",
+ (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]);
+ hdata_new_list(hdata, str_list, &gui_keys[i]);
+ snprintf (str_list, sizeof (str_list),
+ "last_gui_key%s%s",
+ (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_",
+ (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]);
+ hdata_new_list(hdata, str_list, &last_gui_key[i]);
+ snprintf (str_list, sizeof (str_list),
+ "gui_default_keys%s%s",
+ (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_",
+ (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]);
+ hdata_new_list(hdata, str_list, &gui_default_keys[i]);
+ snprintf (str_list, sizeof (str_list),
+ "last_gui_default_key%s%s",
+ (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : "_",
+ (i == GUI_KEY_CONTEXT_DEFAULT) ? "" : gui_key_context_string[i]);
+ hdata_new_list(hdata, str_list, &last_gui_default_key[i]);
+ }
}
return hdata;
}
diff --git a/src/gui/gui-key.h b/src/gui/gui-key.h
index 32e3f0482..d05ef7391 100644
--- a/src/gui/gui-key.h
+++ b/src/gui/gui-key.h
@@ -22,10 +22,14 @@
#define GUI_KEY_BUFFER_BLOCK_SIZE 256
+#define GUI_KEY_GRAB_DELAY_DEFAULT 500
+
enum t_gui_key_context
{
GUI_KEY_CONTEXT_DEFAULT = 0,
GUI_KEY_CONTEXT_SEARCH,
+ GUI_KEY_CONTEXT_CURSOR,
+ GUI_KEY_CONTEXT_MOUSE,
/* number of key contexts */
GUI_KEY_NUM_CONTEXTS,
};
@@ -62,8 +66,7 @@ extern time_t gui_key_last_activity_time;
extern void gui_key_init ();
extern int gui_key_search_context (const char *context);
-extern void gui_key_grab_init (int grab_command);
-extern void gui_key_grab_end ();
+extern void gui_key_grab_init (int grab_command, const char *delay);
extern char *gui_key_get_internal_code (const char *key);
extern char *gui_key_get_expanded_name (const char *key);
extern struct t_gui_key *gui_key_new (struct t_gui_buffer *buffer,
diff --git a/src/gui/gui-mouse.c b/src/gui/gui-mouse.c
new file mode 100644
index 000000000..81fc9ffd3
--- /dev/null
+++ b/src/gui/gui-mouse.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 Sebastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * gui-mouse.c: functions for mouse (used by all GUI)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../core/weechat.h"
+#include "gui-chat.h"
+
+
+int gui_mouse_enabled = 0; /* 1 if mouse support is enabled */
+int gui_mouse_debug = 0; /* debug mode for mouse */
+int gui_mouse_grab = 0; /* 1 if grab mouse code enabled */
+int gui_mouse_event_index = 0; /* index for x/y in array (0 or 1) */
+int gui_mouse_event_x[2] = { 0, 0 }; /* position of latest mouse event: */
+ /* (on click, on release) */
+int gui_mouse_event_y[2] = { 0, 0 }; /* position of latest mouse event */
+ /* (on click, on release) */
+char gui_mouse_event_button = '#'; /* button pressed (or wheel) */
+
+
+/*
+ * gui_mouse_debug_toggle: toggle debug for mouse events
+ */
+
+void
+gui_mouse_debug_toggle ()
+{
+ gui_mouse_debug ^= 1;
+
+ if (gui_mouse_debug)
+ gui_chat_printf (NULL, _("Debug enabled for mouse"));
+ else
+ gui_chat_printf (NULL, _("Debug disabled for mouse"));
+}
+
+/*
+ * gui_mouse_reset_event: reset event values
+ */
+
+void
+gui_mouse_reset_event ()
+{
+ gui_mouse_event_index = 0;
+ gui_mouse_event_x[0] = 0;
+ gui_mouse_event_y[0] = 0;
+ gui_mouse_event_x[1] = 0;
+ gui_mouse_event_y[1] = 0;
+ gui_mouse_event_button = '#';
+}
diff --git a/src/gui/gui-mouse.h b/src/gui/gui-mouse.h
new file mode 100644
index 000000000..a579655f8
--- /dev/null
+++ b/src/gui/gui-mouse.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 Sebastien Helleu <flashcode@flashtux.org>
+ *
+ * This file is part of WeeChat, the extensible chat client.
+ *
+ * WeeChat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WeeChat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with WeeChat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WEECHAT_GUI_MOUSE_H
+#define __WEECHAT_GUI_MOUSE_H 1
+
+/* mouse variables */
+
+extern int gui_mouse_enabled;
+extern int gui_mouse_debug;
+extern int gui_mouse_grab;
+extern int gui_mouse_event_index;
+extern int gui_mouse_event_x[2];
+extern int gui_mouse_event_y[2];
+extern char gui_mouse_event_button;
+
+/* mouse functions */
+
+extern void gui_mouse_debug_toggle ();
+extern void gui_mouse_reset_event ();
+
+/* mouse functions (GUI dependent) */
+
+extern void gui_mouse_enable ();
+extern void gui_mouse_disable ();
+extern void gui_mouse_display_state ();
+extern void gui_mouse_grab_init ();
+extern const char *gui_mouse_grab_code2key (const char *code);
+extern void gui_mouse_grab_end ();
+
+#endif /* __WEECHAT_GUI_MOUSE_H */
diff --git a/src/gui/gui-window.c b/src/gui/gui-window.c
index bb22d1297..34102870e 100644
--- a/src/gui/gui-window.c
+++ b/src/gui/gui-window.c
@@ -70,9 +70,36 @@ struct t_gui_layout_window *gui_window_layout_before_zoom = NULL;
/* layout before zooming on a window */
int gui_window_layout_id_current_window = -1;
/* current window id before zoom */
+int gui_window_cursor_x = 0; /* cursor pos on screen */
+int gui_window_cursor_y = 0; /* cursor pos on screen */
/*
+ * gui_window_search_by_xy: get pointer of window displayed at (x,y)
+ * return NULL if no window is found
+ */
+
+struct t_gui_window *
+gui_window_search_by_xy (int x, int y)
+{
+ struct t_gui_window *ptr_window;
+
+ for (ptr_window = gui_windows; ptr_window;
+ ptr_window = ptr_window->next_window)
+ {
+ if ((x >= ptr_window->win_x) && (y >= ptr_window->win_y)
+ && (x <= ptr_window->win_x + ptr_window->win_width - 1)
+ && (y <= ptr_window->win_y + ptr_window->win_height - 1))
+ {
+ return ptr_window;
+ }
+ }
+
+ /* no window at this location */
+ return NULL;
+}
+
+/*
* gui_window_ask_refresh: set "gui_window_refresh_needed" flag
*/
@@ -1293,8 +1320,8 @@ gui_window_hdata_window_cb (void *data, const char *hdata_name)
HDATA_VAR(struct t_gui_window, win_chat_height, INTEGER, NULL);
HDATA_VAR(struct t_gui_window, win_chat_cursor_x, INTEGER, NULL);
HDATA_VAR(struct t_gui_window, win_chat_cursor_y, INTEGER, NULL);
- HDATA_VAR(struct t_gui_window, bar_windows, POINTER, NULL);
- HDATA_VAR(struct t_gui_window, last_bar_window, POINTER, NULL);
+ HDATA_VAR(struct t_gui_window, bar_windows, POINTER, "bar_window");
+ HDATA_VAR(struct t_gui_window, last_bar_window, POINTER, "bar_window");
HDATA_VAR(struct t_gui_window, refresh_needed, INTEGER, NULL);
HDATA_VAR(struct t_gui_window, gui_objects, POINTER, NULL);
HDATA_VAR(struct t_gui_window, buffer, POINTER, "buffer");
diff --git a/src/gui/gui-window.h b/src/gui/gui-window.h
index 92b76a517..9bb76623a 100644
--- a/src/gui/gui-window.h
+++ b/src/gui/gui-window.h
@@ -27,10 +27,12 @@
#define GUI_WINDOW_CHAT_MIN_HEIGHT 2
struct t_infolist;
+struct t_gui_bar_window;
extern int gui_init_ok;
extern int gui_ok;
extern int gui_window_refresh_needed;
+extern int gui_window_cursor_x, gui_window_cursor_y;
/* window structures */
@@ -116,6 +118,8 @@ extern struct t_gui_window *gui_current_window;
extern struct t_gui_window_tree *gui_windows_tree;
/* window functions */
+
+extern struct t_gui_window *gui_window_search_by_xy (int x, int y);
extern void gui_window_ask_refresh (int refresh);
extern int gui_window_tree_init (struct t_gui_window *window);
extern void gui_window_tree_node_to_leaf (struct t_gui_window_tree *node,
@@ -200,6 +204,7 @@ extern int gui_window_balance (struct t_gui_window_tree *tree);
extern void gui_window_swap (struct t_gui_window *window, int direction);
extern void gui_window_refresh_screen (int full_refresh);
extern void gui_window_set_title (const char *title);
+extern void gui_window_move_cursor ();
extern void gui_window_term_display_infos ();
extern void gui_window_objects_print_log (struct t_gui_window *window);
diff --git a/src/plugins/irc/irc-bar-item.c b/src/plugins/irc/irc-bar-item.c
index e6e24e682..89b50392c 100644
--- a/src/plugins/irc/irc-bar-item.c
+++ b/src/plugins/irc/irc-bar-item.c
@@ -493,6 +493,49 @@ irc_bar_item_input_prompt (void *data, struct t_gui_bar_item *item,
}
/*
+ * irc_bar_item_focus_buffer_nicklist: focus on nicklist
+ */
+
+struct t_hashtable *
+irc_bar_item_focus_buffer_nicklist (void *data,
+ struct t_hashtable *info)
+{
+ long unsigned int value;
+ int rc;
+ struct t_gui_buffer *buffer;
+ struct t_irc_nick *ptr_nick;
+ const char *str_buffer, *nick;
+
+ str_buffer = weechat_hashtable_get (info, "_buffer");
+ rc = sscanf (str_buffer, "%lx", &value);
+ if ((rc == EOF) || (rc == 0))
+ return NULL;
+
+ buffer = (struct t_gui_buffer *)value;
+
+ IRC_BUFFER_GET_SERVER_CHANNEL(buffer);
+
+ /* make C compiler happy */
+ (void) data;
+
+ if (ptr_channel)
+ {
+ nick = weechat_hashtable_get (info, "nick");
+ if (nick)
+ {
+ ptr_nick = irc_nick_search (ptr_channel, nick);
+ if (ptr_nick && ptr_nick->host)
+ {
+ weechat_hashtable_set (info, "host", ptr_nick->host);
+ return info;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
* irc_bar_item_init: initialize IRC bar items
*/
@@ -506,4 +549,6 @@ irc_bar_item_init ()
weechat_bar_item_new ("irc_channel", &irc_bar_item_channel, NULL);
weechat_bar_item_new ("lag", &irc_bar_item_lag, NULL);
weechat_bar_item_new ("input_prompt", &irc_bar_item_input_prompt, NULL);
+ weechat_hook_focus ("500|buffer_nicklist",
+ &irc_bar_item_focus_buffer_nicklist, NULL);
}
diff --git a/src/plugins/plugin-api.c b/src/plugins/plugin-api.c
index 7e3861541..b54b2ab2d 100644
--- a/src/plugins/plugin-api.c
+++ b/src/plugins/plugin-api.c
@@ -50,6 +50,7 @@
#include "../gui/gui-chat.h"
#include "../gui/gui-completion.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"
@@ -365,6 +366,11 @@ plugin_api_info_get_internal (void *data, const char *info_name,
snprintf (value, sizeof (value), "%d", gui_filters_enabled);
return value;
}
+ else if (string_strcasecmp (info_name, "cursor_mode") == 0)
+ {
+ snprintf (value, sizeof (value), "%d", gui_cursor_mode);
+ return value;
+ }
/* info not found */
return NULL;
@@ -997,6 +1003,8 @@ plugin_api_init ()
&plugin_api_info_get_internal, NULL);
hook_info (NULL, "filters_enabled", N_("1 if filters are enabled"), NULL,
&plugin_api_info_get_internal, NULL);
+ hook_info (NULL, "cursor_mode", N_("1 if cursor mode is enabled"), NULL,
+ &plugin_api_info_get_internal, NULL);
/* WeeChat core infolist hooks */
hook_infolist (NULL, "bar", N_("list of bars"),
@@ -1064,6 +1072,8 @@ plugin_api_init ()
&gui_bar_hdata_bar_cb, NULL);
hook_hdata (NULL, "bar_item", N_("bar item"),
&gui_bar_item_hdata_bar_item_cb, NULL);
+ hook_hdata (NULL, "bar_window", N_("bar window"),
+ &gui_bar_window_hdata_bar_window_cb, NULL);
hook_hdata (NULL, "buffer", N_("buffer"),
&gui_buffer_hdata_buffer_cb, NULL);
hook_hdata (NULL, "completion", N_("structure with completion"),
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 79bf76039..c785d3c46 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -607,6 +607,7 @@ plugin_load (const char *filename)
new_plugin->hook_info_hashtable = &hook_info_hashtable;
new_plugin->hook_infolist = &hook_infolist;
new_plugin->hook_hdata = &hook_hdata;
+ new_plugin->hook_focus = &hook_focus;
new_plugin->unhook = &unhook;
new_plugin->unhook_all = &unhook_all_plugin;
diff --git a/src/plugins/scripts/lua/weechat-lua-api.c b/src/plugins/scripts/lua/weechat-lua-api.c
index ccdba77ad..fe6ecaccc 100644
--- a/src/plugins/scripts/lua/weechat-lua-api.c
+++ b/src/plugins/scripts/lua/weechat-lua-api.c
@@ -4693,6 +4693,76 @@ weechat_lua_api_hook_infolist (lua_State *L)
}
/*
+ * weechat_lua_api_hook_focus_cb: callback for focus hooked
+ */
+
+struct t_hashtable *
+weechat_lua_api_hook_focus_cb (void *data,
+ struct t_hashtable *info)
+{
+ struct t_script_callback *script_callback;
+ void *lua_argv[2];
+ char empty_arg[1] = { '\0' };
+
+ script_callback = (struct t_script_callback *)data;
+
+ if (script_callback && script_callback->function && script_callback->function[0])
+ {
+ lua_argv[0] = (script_callback->data) ? script_callback->data : empty_arg;
+ lua_argv[1] = info;
+
+ return (struct t_hashtable *)weechat_lua_exec (script_callback->script,
+ WEECHAT_SCRIPT_EXEC_HASHTABLE,
+ script_callback->function,
+ "sh", lua_argv);
+ }
+
+ return NULL;
+}
+
+/*
+ * weechat_lua_api_hook_focus: hook a focus
+ */
+
+static int
+weechat_lua_api_hook_focus (lua_State *L)
+{
+ const char *area, *function, *data;
+ char *result;
+ int n;
+
+ /* make C compiler happy */
+ (void) L;
+
+ if (!lua_current_script || !lua_current_script->name)
+ {
+ WEECHAT_SCRIPT_MSG_NOT_INIT(LUA_CURRENT_SCRIPT_NAME, "hook_focus");
+ LUA_RETURN_EMPTY;
+ }
+
+ n = lua_gettop (lua_current_interpreter);
+
+ if (n < 3)
+ {
+ WEECHAT_SCRIPT_MSG_WRONG_ARGS(LUA_CURRENT_SCRIPT_NAME, "hook_focus");
+ LUA_RETURN_EMPTY;
+ }
+
+ area = lua_tostring (lua_current_interpreter, -3);
+ function = lua_tostring (lua_current_interpreter, -2);
+ data = lua_tostring (lua_current_interpreter, -1);
+
+ result = script_ptr2str (script_api_hook_focus (weechat_lua_plugin,
+ lua_current_script,
+ area,
+ &weechat_lua_api_hook_focus_cb,
+ function,
+ data));
+
+ LUA_RETURN_STRING_FREE(result);
+}
+
+/*
* weechat_lua_api_unhook: unhook something
*/
@@ -8322,6 +8392,7 @@ const struct luaL_reg weechat_lua_api_funcs[] = {
{ "hook_info", &weechat_lua_api_hook_info },
{ "hook_info_hashtable", &weechat_lua_api_hook_info_hashtable },
{ "hook_infolist", &weechat_lua_api_hook_infolist },
+ { "hook_focus", &weechat_lua_api_hook_focus },
{ "unhook", &weechat_lua_api_unhook },
{ "unhook_all", &weechat_lua_api_unhook_all },
{ "buffer_new", &weechat_lua_api_buffer_new },
diff --git a/src/plugins/scripts/perl/weechat-perl-api.c b/src/plugins/scripts/perl/weechat-perl-api.c
index 9fb575b99..45429dbbc 100644
--- a/src/plugins/scripts/perl/weechat-perl-api.c
+++ b/src/plugins/scripts/perl/weechat-perl-api.c
@@ -4267,6 +4267,72 @@ XS (XS_weechat_api_hook_infolist)
}
/*
+ * weechat_perl_api_hook_focus_cb: callback for focus hooked
+ */
+
+struct t_hashtable *
+weechat_perl_api_hook_focus_cb (void *data,
+ struct t_hashtable *info)
+{
+ struct t_script_callback *script_callback;
+ void *perl_argv[2];
+ char empty_arg[1] = { '\0' };
+
+ script_callback = (struct t_script_callback *)data;
+
+ if (script_callback && script_callback->function && script_callback->function[0])
+ {
+ perl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg;
+ perl_argv[1] = info;
+
+ return (struct t_hashtable *)weechat_perl_exec (script_callback->script,
+ WEECHAT_SCRIPT_EXEC_HASHTABLE,
+ script_callback->function,
+ "sh", perl_argv);
+ }
+
+ return NULL;
+}
+
+/*
+ * weechat::hook_focus: hook a focus
+ */
+
+XS (XS_weechat_api_hook_focus)
+{
+ char *result, *area, *function, *data;
+ dXSARGS;
+
+ /* make C compiler happy */
+ (void) cv;
+
+ if (!perl_current_script || !perl_current_script->name)
+ {
+ WEECHAT_SCRIPT_MSG_NOT_INIT(PERL_CURRENT_SCRIPT_NAME, "hook_focus");
+ PERL_RETURN_EMPTY;
+ }
+
+ if (items < 3)
+ {
+ WEECHAT_SCRIPT_MSG_WRONG_ARGS(PERL_CURRENT_SCRIPT_NAME, "hook_focus");
+ PERL_RETURN_EMPTY;
+ }
+
+ area = SvPV (ST (0), PL_na);
+ function = SvPV (ST (1), PL_na);
+ data = SvPV (ST (2), PL_na);
+
+ result = script_ptr2str (script_api_hook_focus (weechat_perl_plugin,
+ perl_current_script,
+ area,
+ &weechat_perl_api_hook_focus_cb,
+ function,
+ data));
+
+ PERL_RETURN_STRING_FREE(result);
+}
+
+/*
* weechat::unhook: unhook something
*/
@@ -7213,6 +7279,7 @@ weechat_perl_api_init (pTHX)
newXS ("weechat::hook_info", XS_weechat_api_hook_info, "weechat");
newXS ("weechat::hook_info_hashtable", XS_weechat_api_hook_info_hashtable, "weechat");
newXS ("weechat::hook_infolist", XS_weechat_api_hook_infolist, "weechat");
+ newXS ("weechat::hook_focus", XS_weechat_api_hook_focus, "weechat");
newXS ("weechat::unhook", XS_weechat_api_unhook, "weechat");
newXS ("weechat::unhook_all", XS_weechat_api_unhook_all, "weechat");
newXS ("weechat::buffer_new", XS_weechat_api_buffer_new, "weechat");
diff --git a/src/plugins/scripts/python/weechat-python-api.c b/src/plugins/scripts/python/weechat-python-api.c
index 05df01e70..162974f8c 100644
--- a/src/plugins/scripts/python/weechat-python-api.c
+++ b/src/plugins/scripts/python/weechat-python-api.c
@@ -3656,15 +3656,15 @@ weechat_python_api_hook_print (PyObject *self, PyObject *args)
PYTHON_RETURN_EMPTY;
}
- result = script_ptr2str(script_api_hook_print (weechat_python_plugin,
- python_current_script,
- script_str2ptr (buffer),
- tags,
- message,
- strip_colors,
- &weechat_python_api_hook_print_cb,
- function,
- data));
+ result = script_ptr2str (script_api_hook_print (weechat_python_plugin,
+ python_current_script,
+ script_str2ptr (buffer),
+ tags,
+ message,
+ strip_colors,
+ &weechat_python_api_hook_print_cb,
+ function,
+ data));
PYTHON_RETURN_STRING_FREE(result);
}
@@ -4012,12 +4012,12 @@ weechat_python_api_hook_config (PyObject *self, PyObject *args)
PYTHON_RETURN_EMPTY;
}
- result = script_ptr2str(script_api_hook_config (weechat_python_plugin,
- python_current_script,
- option,
- &weechat_python_api_hook_config_cb,
- function,
- data));
+ result = script_ptr2str (script_api_hook_config (weechat_python_plugin,
+ python_current_script,
+ option,
+ &weechat_python_api_hook_config_cb,
+ function,
+ data));
PYTHON_RETURN_STRING_FREE(result);
}
@@ -4099,13 +4099,13 @@ weechat_python_api_hook_completion (PyObject *self, PyObject *args)
PYTHON_RETURN_EMPTY;
}
- result = script_ptr2str(script_api_hook_completion (weechat_python_plugin,
- python_current_script,
- completion,
- description,
- &weechat_python_api_hook_completion_cb,
- function,
- data));
+ result = script_ptr2str (script_api_hook_completion (weechat_python_plugin,
+ python_current_script,
+ completion,
+ description,
+ &weechat_python_api_hook_completion_cb,
+ function,
+ data));
PYTHON_RETURN_STRING_FREE(result);
}
@@ -4208,12 +4208,12 @@ weechat_python_api_hook_modifier (PyObject *self, PyObject *args)
PYTHON_RETURN_EMPTY;
}
- result = script_ptr2str(script_api_hook_modifier (weechat_python_plugin,
- python_current_script,
- modifier,
- &weechat_python_api_hook_modifier_cb,
- function,
- data));
+ result = script_ptr2str (script_api_hook_modifier (weechat_python_plugin,
+ python_current_script,
+ modifier,
+ &weechat_python_api_hook_modifier_cb,
+ function,
+ data));
PYTHON_RETURN_STRING_FREE(result);
}
@@ -4313,14 +4313,14 @@ weechat_python_api_hook_info (PyObject *self, PyObject *args)
PYTHON_RETURN_EMPTY;
}
- result = script_ptr2str(script_api_hook_info (weechat_python_plugin,
- python_current_script,
- info_name,
- description,
- args_description,
- &weechat_python_api_hook_info_cb,
- function,
- data));
+ result = script_ptr2str (script_api_hook_info (weechat_python_plugin,
+ python_current_script,
+ info_name,
+ description,
+ args_description,
+ &weechat_python_api_hook_info_cb,
+ function,
+ data));
PYTHON_RETURN_STRING_FREE(result);
}
@@ -4397,15 +4397,15 @@ weechat_python_api_hook_info_hashtable (PyObject *self, PyObject *args)
PYTHON_RETURN_EMPTY;
}
- result = script_ptr2str(script_api_hook_info_hashtable (weechat_python_plugin,
- python_current_script,
- info_name,
- description,
- args_description,
- output_description,
- &weechat_python_api_hook_info_hashtable_cb,
- function,
- data));
+ result = script_ptr2str (script_api_hook_info_hashtable (weechat_python_plugin,
+ python_current_script,
+ info_name,
+ description,
+ args_description,
+ output_description,
+ &weechat_python_api_hook_info_hashtable_cb,
+ function,
+ data));
PYTHON_RETURN_STRING_FREE(result);
}
@@ -4481,15 +4481,82 @@ weechat_python_api_hook_infolist (PyObject *self, PyObject *args)
PYTHON_RETURN_EMPTY;
}
- result = script_ptr2str(script_api_hook_infolist (weechat_python_plugin,
- python_current_script,
- infolist_name,
- description,
- pointer_description,
- args_description,
- &weechat_python_api_hook_infolist_cb,
- function,
- data));
+ result = script_ptr2str (script_api_hook_infolist (weechat_python_plugin,
+ python_current_script,
+ infolist_name,
+ description,
+ pointer_description,
+ args_description,
+ &weechat_python_api_hook_infolist_cb,
+ function,
+ data));
+
+ PYTHON_RETURN_STRING_FREE(result);
+}
+
+/*
+ * weechat_python_api_hook_focus_cb: callback for focus hooked
+ */
+
+struct t_hashtable *
+weechat_python_api_hook_focus_cb (void *data,
+ struct t_hashtable *info)
+{
+ struct t_script_callback *script_callback;
+ void *python_argv[2];
+ char empty_arg[1] = { '\0' };
+
+ script_callback = (struct t_script_callback *)data;
+
+ if (script_callback && script_callback->function && script_callback->function[0])
+ {
+ python_argv[0] = (script_callback->data) ? script_callback->data : empty_arg;
+ python_argv[1] = info;
+
+ return (struct t_hashtable *)weechat_python_exec (script_callback->script,
+ WEECHAT_SCRIPT_EXEC_HASHTABLE,
+ script_callback->function,
+ "sh", python_argv);
+ }
+
+ return NULL;
+}
+
+/*
+ * weechat_python_api_hook_focus: hook a focus
+ */
+
+static PyObject *
+weechat_python_api_hook_focus (PyObject *self, PyObject *args)
+{
+ char *area, *function, *data, *result;
+ PyObject *object;
+
+ /* make C compiler happy */
+ (void) self;
+
+ if (!python_current_script || !python_current_script->name)
+ {
+ WEECHAT_SCRIPT_MSG_NOT_INIT(PYTHON_CURRENT_SCRIPT_NAME, "hook_focus");
+ PYTHON_RETURN_EMPTY;
+ }
+
+ area = NULL;
+ function = NULL;
+ data = NULL;
+
+ if (!PyArg_ParseTuple (args, "sss", &area, &function, &data))
+ {
+ WEECHAT_SCRIPT_MSG_WRONG_ARGS(PYTHON_CURRENT_SCRIPT_NAME, "hook_focus");
+ PYTHON_RETURN_EMPTY;
+ }
+
+ result = script_ptr2str (script_api_hook_focus (weechat_python_plugin,
+ python_current_script,
+ area,
+ &weechat_python_api_hook_focus_cb,
+ function,
+ data));
PYTHON_RETURN_STRING_FREE(result);
}
@@ -7555,6 +7622,7 @@ PyMethodDef weechat_python_funcs[] =
{ "hook_info", &weechat_python_api_hook_info, METH_VARARGS, "" },
{ "hook_info_hashtable", &weechat_python_api_hook_info_hashtable, METH_VARARGS, "" },
{ "hook_infolist", &weechat_python_api_hook_infolist, METH_VARARGS, "" },
+ { "hook_focus", &weechat_python_api_hook_focus, METH_VARARGS, "" },
{ "unhook", &weechat_python_api_unhook, METH_VARARGS, "" },
{ "unhook_all", &weechat_python_api_unhook_all, METH_VARARGS, "" },
{ "buffer_new", &weechat_python_api_buffer_new, METH_VARARGS, "" },
diff --git a/src/plugins/scripts/ruby/weechat-ruby-api.c b/src/plugins/scripts/ruby/weechat-ruby-api.c
index 6e61c0e2e..69394dc73 100644
--- a/src/plugins/scripts/ruby/weechat-ruby-api.c
+++ b/src/plugins/scripts/ruby/weechat-ruby-api.c
@@ -4874,6 +4874,78 @@ weechat_ruby_api_hook_infolist (VALUE class, VALUE infolist_name,
}
/*
+ * weechat_ruby_api_hook_focus_cb: callback for focus hooked
+ */
+
+struct t_hashtable *
+weechat_ruby_api_hook_focus_cb (void *data,
+ struct t_hashtable *info)
+{
+ struct t_script_callback *script_callback;
+ void *ruby_argv[2];
+ char empty_arg[1] = { '\0' };
+
+ script_callback = (struct t_script_callback *)data;
+
+ if (script_callback && script_callback->function && script_callback->function[0])
+ {
+ ruby_argv[0] = (script_callback->data) ? script_callback->data : empty_arg;
+ ruby_argv[1] = info;
+
+ return (struct t_hashtable *)weechat_ruby_exec (script_callback->script,
+ WEECHAT_SCRIPT_EXEC_HASHTABLE,
+ script_callback->function,
+ "sh", ruby_argv);
+ }
+
+ return NULL;
+}
+
+/*
+ * weechat_ruby_api_hook_focus: hook a focus
+ */
+
+static VALUE
+weechat_ruby_api_hook_focus (VALUE class, VALUE area, VALUE function,
+ VALUE data)
+{
+ char *c_area, *c_function, *c_data, *result;
+ VALUE return_value;
+
+ /* make C compiler happy */
+ (void) class;
+
+ if (!ruby_current_script || !ruby_current_script->name)
+ {
+ WEECHAT_SCRIPT_MSG_NOT_INIT(RUBY_CURRENT_SCRIPT_NAME, "hook_focus");
+ RUBY_RETURN_EMPTY;
+ }
+
+ if (NIL_P (area) || NIL_P (function) || NIL_P (data))
+ {
+ WEECHAT_SCRIPT_MSG_WRONG_ARGS(RUBY_CURRENT_SCRIPT_NAME, "hook_focus");
+ RUBY_RETURN_EMPTY;
+ }
+
+ Check_Type (area, T_STRING);
+ Check_Type (function, T_STRING);
+ Check_Type (data, T_STRING);
+
+ c_area = StringValuePtr (area);
+ c_function = StringValuePtr (function);
+ c_data = StringValuePtr (data);
+
+ result = script_ptr2str (script_api_hook_focus (weechat_ruby_plugin,
+ ruby_current_script,
+ c_area,
+ &weechat_ruby_api_hook_focus_cb,
+ c_function,
+ c_data));
+
+ RUBY_RETURN_STRING_FREE(result);
+}
+
+/*
* weechat_ruby_api_unhook: unhook something
*/
@@ -8279,6 +8351,7 @@ weechat_ruby_api_init (VALUE ruby_mWeechat)
rb_define_module_function (ruby_mWeechat, "hook_info", &weechat_ruby_api_hook_info, 5);
rb_define_module_function (ruby_mWeechat, "hook_info_hashtable", &weechat_ruby_api_hook_info_hashtable, 6);
rb_define_module_function (ruby_mWeechat, "hook_infolist", &weechat_ruby_api_hook_infolist, 6);
+ rb_define_module_function (ruby_mWeechat, "hook_focus", &weechat_ruby_api_hook_focus, 3);
rb_define_module_function (ruby_mWeechat, "unhook", &weechat_ruby_api_unhook, 1);
rb_define_module_function (ruby_mWeechat, "unhook_all", &weechat_ruby_api_unhook_all, 0);
rb_define_module_function (ruby_mWeechat, "buffer_new", &weechat_ruby_api_buffer_new, 5);
diff --git a/src/plugins/scripts/script-api.c b/src/plugins/scripts/script-api.c
index b7a6fbf55..9f05f6d2c 100644
--- a/src/plugins/scripts/script-api.c
+++ b/src/plugins/scripts/script-api.c
@@ -1329,6 +1329,43 @@ script_api_hook_infolist (struct t_weechat_plugin *weechat_plugin,
}
/*
+ * script_api_hook_focus: hook a focus
+ * return new hook, NULL if error
+ */
+
+struct t_hook *
+script_api_hook_focus (struct t_weechat_plugin *weechat_plugin,
+ struct t_plugin_script *script,
+ const char *area,
+ struct t_hashtable *(*callback)(void *data,
+ struct t_hashtable *info),
+ const char *function,
+ const char *data)
+{
+ struct t_script_callback *new_script_callback;
+ struct t_hook *new_hook;
+
+ new_script_callback = script_callback_alloc ();
+ if (!new_script_callback)
+ return NULL;
+
+ new_hook = weechat_hook_focus (area, callback, new_script_callback);
+ if (!new_hook)
+ {
+ script_callback_free_data (new_script_callback);
+ free (new_script_callback);
+ return NULL;
+ }
+
+ script_callback_init (new_script_callback, script, function, data);
+ new_script_callback->hook = new_hook;
+
+ script_callback_add (script, new_script_callback);
+
+ return new_hook;
+}
+
+/*
* script_api_unhook: unhook something
*/
diff --git a/src/plugins/scripts/script-api.h b/src/plugins/scripts/script-api.h
index 80ec4e2b9..c1c9dbe5b 100644
--- a/src/plugins/scripts/script-api.h
+++ b/src/plugins/scripts/script-api.h
@@ -276,6 +276,13 @@ extern struct t_hook *script_api_hook_infolist (struct t_weechat_plugin *weechat
const char *arguments),
const char *function,
const char *data);
+extern struct t_hook *script_api_hook_focus (struct t_weechat_plugin *weechat_plugin,
+ struct t_plugin_script *script,
+ const char *area,
+ struct t_hashtable *(*callback)(void *data,
+ struct t_hashtable *info),
+ const char *function,
+ const char *data);
extern void script_api_unhook (struct t_weechat_plugin *weechat_plugin,
struct t_plugin_script *script,
struct t_hook *hook);
diff --git a/src/plugins/scripts/tcl/weechat-tcl-api.c b/src/plugins/scripts/tcl/weechat-tcl-api.c
index 5bc243bab..61570a5d2 100644
--- a/src/plugins/scripts/tcl/weechat-tcl-api.c
+++ b/src/plugins/scripts/tcl/weechat-tcl-api.c
@@ -4792,6 +4792,75 @@ weechat_tcl_api_hook_infolist (ClientData clientData, Tcl_Interp *interp,
}
/*
+ * weechat_tcl_api_hook_focus_cb: callback for focus hooked
+ */
+
+struct t_hashtable *
+weechat_tcl_api_hook_focus_cb (void *data,
+ struct t_hashtable *info)
+{
+ struct t_script_callback *script_callback;
+ void *tcl_argv[2];
+ char empty_arg[1] = { '\0' };
+
+ script_callback = (struct t_script_callback *)data;
+
+ if (script_callback && script_callback->function && script_callback->function[0])
+ {
+ tcl_argv[0] = (script_callback->data) ? script_callback->data : empty_arg;
+ tcl_argv[1] = info;
+
+ return (struct t_hashtable *)weechat_tcl_exec (script_callback->script,
+ WEECHAT_SCRIPT_EXEC_HASHTABLE,
+ script_callback->function,
+ "sh", tcl_argv);
+ }
+
+ return NULL;
+}
+
+/*
+ * weechat_tcl_api_hook_focus: hook a focus
+ */
+
+static int
+weechat_tcl_api_hook_focus (ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ Tcl_Obj *objp;
+ char *result, *area, *function, *data;
+ int i;
+
+ /* make C compiler happy */
+ (void) clientData;
+
+ if (!tcl_current_script || !tcl_current_script->name)
+ {
+ WEECHAT_SCRIPT_MSG_NOT_INIT(TCL_CURRENT_SCRIPT_NAME, "hook_focus");
+ TCL_RETURN_EMPTY;
+ }
+
+ if (objc < 4)
+ {
+ WEECHAT_SCRIPT_MSG_WRONG_ARGS(TCL_CURRENT_SCRIPT_NAME, "hook_focus");
+ TCL_RETURN_EMPTY;
+ }
+
+ area = Tcl_GetStringFromObj (objv[1], &i);
+ function = Tcl_GetStringFromObj (objv[2], &i);
+ data = Tcl_GetStringFromObj (objv[3], &i);
+
+ result = script_ptr2str (script_api_hook_focus (weechat_tcl_plugin,
+ tcl_current_script,
+ area,
+ &weechat_tcl_api_hook_focus_cb,
+ function,
+ data));
+
+ TCL_RETURN_STRING_FREE(result);
+}
+
+/*
* weechat_tcl_api_unhook: unhook something
*/
@@ -8205,6 +8274,8 @@ void weechat_tcl_api_init (Tcl_Interp *interp)
weechat_tcl_api_hook_info_hashtable, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
Tcl_CreateObjCommand (interp, "weechat::hook_infolist",
weechat_tcl_api_hook_infolist, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+ Tcl_CreateObjCommand (interp, "weechat::hook_focus",
+ weechat_tcl_api_hook_focus, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
Tcl_CreateObjCommand (interp, "weechat::unhook",
weechat_tcl_api_unhook, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
Tcl_CreateObjCommand (interp, "weechat::unhook_all",
diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h
index 6a6ec60e0..99eead9ed 100644
--- a/src/plugins/weechat-plugin.h
+++ b/src/plugins/weechat-plugin.h
@@ -46,7 +46,7 @@ struct timeval;
*/
/* API version (used to check that plugin has same API and can be loaded) */
-#define WEECHAT_PLUGIN_API_VERSION "20110613-01"
+#define WEECHAT_PLUGIN_API_VERSION "20110726-01"
/* macros for defining plugin infos */
#define WEECHAT_PLUGIN_NAME(__name) \
@@ -584,6 +584,11 @@ struct t_weechat_plugin
struct t_hdata *(*callback)(void *data,
const char *hdata_name),
void *callback_data);
+ struct t_hook *(*hook_focus) (struct t_weechat_plugin *plugin,
+ const char *area,
+ struct t_hashtable *(*callback)(void *data,
+ struct t_hashtable *info),
+ void *callback_data);
void (*unhook) (struct t_hook *hook);
void (*unhook_all) (struct t_weechat_plugin *plugin);
@@ -1281,6 +1286,9 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin);
__data) \
weechat_plugin->hook_hdata(weechat_plugin, __hdata_name, \
__description, __callback, __data)
+#define weechat_hook_focus(__area, __callback, __data) \
+ weechat_plugin->hook_focus(weechat_plugin, __area, __callback, \
+ __data)
#define weechat_unhook(__hook) \
weechat_plugin->unhook( __hook)
#define weechat_unhook_all() \