summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/command.c30
-rw-r--r--src/gui/gui-buffer.c201
-rw-r--r--src/gui/gui.h1
3 files changed, 227 insertions, 5 deletions
diff --git a/src/common/command.c b/src/common/command.c
index 3347be88b..66c7f1f22 100644
--- a/src/common/command.c
+++ b/src/common/command.c
@@ -65,12 +65,27 @@ t_weechat_command weechat_commands[] =
" move: move buffer in the list (may be relative, for example -1)\n"
" close: close buffer (optional arg is part message, for a channel)\n"
" list: list open buffers (no parameter implies this list)\n"
- " notify: set notify level for buffer (0=never, 1=highlight, 2=1+msg, 3=2+join/part)\n"
- " (when executed on server buffer, this sets default notify level for whole server)\n"
+ " notify: set notify level for buffer (0=never, 1=highlight, 2=1+msg, "
+ "3=2+join/part)\n"
+ " (when executed on server buffer, this sets default notify "
+ "level for whole server)\n"
+ " scroll: scroll in history (may be relative, and may end by a letter: "
+ "s=sec, m=min, h=hour, d=day, M=month, y=year); if there is "
+ "only letter, then scroll to beginning of this item\n\n"
+ " number: jump to buffer by number\n"
"server,\n"
- "channel: jump to buffer by server and/or channel name\n"
- " number: jump to buffer by number"),
- "move|close|list|notify|%S|%C %S|%C", 0, MAX_ARGS, 0, NULL, weechat_cmd_buffer },
+ "channel: jump to buffer by server and/or channel name\n\n"
+ "Examples:\n"
+ " move buffer: /buffer move 5\n"
+ " close buffer: /buffer close this is part msg\n"
+ " set notify: /buffer notify 2\n"
+ " scroll 1 day up: /buffer scroll 1d == /buffer scroll -1d == /buffer scroll -24h\n"
+ "scroll to beginning\n"
+ " of this day: /buffer scroll d\n"
+ " scroll 15 min down: /buffer scroll +15m\n"
+ " scroll 20 msgs up: /buffer scroll -20\n"
+ " jump to #weechat: /buffer #weechat"),
+ "move|close|list|notify|scroll|%S|%C %S|%C", 0, MAX_ARGS, 0, NULL, weechat_cmd_buffer },
{ "builtin", N_("launch WeeChat/IRC builtin command (do not look at plugins handlers or aliases)"),
N_("command"),
N_("command: command to execute (a '/' is automatically added if not found at beginning of command)\n"),
@@ -1380,6 +1395,11 @@ weechat_cmd_buffer (t_irc_server *server, t_irc_channel *channel,
}
}
}
+ else if (ascii_strcasecmp (argv[0], "scroll") == 0)
+ {
+ if (argc >= 2)
+ gui_buffer_scroll (window, argv[1]);
+ }
else
{
/* jump to buffer by number or server/channel name */
diff --git a/src/gui/gui-buffer.c b/src/gui/gui-buffer.c
index 267478c45..3de88052a 100644
--- a/src/gui/gui-buffer.c
+++ b/src/gui/gui-buffer.c
@@ -1190,6 +1190,207 @@ gui_buffer_search_stop (t_gui_window *window)
}
/*
+ * gui_buffer_scroll: scroll buffer by # messages or time
+ */
+
+void
+gui_buffer_scroll (t_gui_window *window, char *scroll)
+{
+ int direction, stop, count_msg;
+ char time_letter, saved_char;
+ time_t old_date, diff_date;
+ char *error;
+ long number;
+ t_gui_line *ptr_line;
+ struct tm *date_tmp, line_date, old_line_date;
+
+ if (window->buffer->lines)
+ {
+ direction = -1;
+ number = 0;
+ time_letter = ' ';
+
+ // search direction
+ if (scroll[0] == '-')
+ {
+ direction = -1;
+ scroll++;
+ }
+ else if (scroll[0] == '+')
+ {
+ direction = +1;
+ scroll++;
+ }
+
+ // search number and letter
+ char *pos = scroll;
+ while (pos && pos[0] && isdigit (pos[0]))
+ {
+ pos++;
+ }
+ if (pos)
+ {
+ if (pos == scroll)
+ {
+ if (pos[0])
+ time_letter = scroll[0];
+ }
+ else
+ {
+ if (pos[0])
+ time_letter = pos[0];
+ saved_char = pos[0];
+ pos[0] = '\0';
+ error = NULL;
+ number = strtol (scroll, &error, 10);
+ if (!error || (error[0] != '\0'))
+ number = 0;
+ pos[0] = saved_char;
+ }
+ }
+
+ /* at least number or letter has to he given */
+ if ((number == 0) && (time_letter == ' '))
+ return;
+
+ // do the scroll!
+ stop = 0;
+ count_msg = 0;
+ if (direction < 0)
+ ptr_line = (window->start_line) ?
+ window->start_line : window->buffer->last_line;
+ else
+ ptr_line = (window->start_line) ?
+ window->start_line : window->buffer->lines;
+
+ old_date = ptr_line->date;
+ date_tmp = localtime (&old_date);
+ memcpy (&old_line_date, date_tmp, sizeof (struct tm));
+
+ while (ptr_line)
+ {
+ ptr_line = (direction < 0) ? ptr_line->prev_line : ptr_line->next_line;
+
+ if (ptr_line)
+ {
+ if (time_letter == ' ')
+ {
+ count_msg++;
+ if (count_msg >= number)
+ stop = 1;
+ }
+ else
+ {
+ date_tmp = localtime (&(ptr_line->date));
+ memcpy (&line_date, date_tmp, sizeof (struct tm));
+ if (old_date > ptr_line->date)
+ diff_date = old_date - ptr_line->date;
+ else
+ diff_date = ptr_line->date - old_date;
+ switch (time_letter)
+ {
+ case 's': /* seconds */
+ if (number == 0)
+ {
+ /* stop if line has different second */
+ if ((line_date.tm_sec != old_line_date.tm_sec)
+ || (line_date.tm_min != old_line_date.tm_min)
+ || (line_date.tm_hour != old_line_date.tm_hour)
+ || (line_date.tm_mday != old_line_date.tm_mday)
+ || (line_date.tm_mon != old_line_date.tm_mon)
+ || (line_date.tm_year != old_line_date.tm_year))
+ if (line_date.tm_sec != old_line_date.tm_sec)
+ stop = 1;
+ }
+ else if (diff_date >= number)
+ stop = 1;
+ break;
+ case 'm': /* minutes */
+ if (number == 0)
+ {
+ /* stop if line has different minute */
+ if ((line_date.tm_min != old_line_date.tm_min)
+ || (line_date.tm_hour != old_line_date.tm_hour)
+ || (line_date.tm_mday != old_line_date.tm_mday)
+ || (line_date.tm_mon != old_line_date.tm_mon)
+ || (line_date.tm_year != old_line_date.tm_year))
+ stop = 1;
+ }
+ else if (diff_date >= number * 60)
+ stop = 1;
+ break;
+ case 'h': /* hours */
+ if (number == 0)
+ {
+ /* stop if line has different hour */
+ if ((line_date.tm_hour != old_line_date.tm_hour)
+ || (line_date.tm_mday != old_line_date.tm_mday)
+ || (line_date.tm_mon != old_line_date.tm_mon)
+ || (line_date.tm_year != old_line_date.tm_year))
+ stop = 1;
+ }
+ else if (diff_date >= number * 60 * 60)
+ stop = 1;
+ break;
+ case 'd': /* days */
+ if (number == 0)
+ {
+ /* stop if line has different day */
+ if ((line_date.tm_mday != old_line_date.tm_mday)
+ || (line_date.tm_mon != old_line_date.tm_mon)
+ || (line_date.tm_year != old_line_date.tm_year))
+ stop = 1;
+ }
+ else if (diff_date >= number * 60 * 60 * 24)
+ stop = 1;
+ break;
+ case 'M': /* months */
+ if (number == 0)
+ {
+ /* stop if line has different month */
+ if ((line_date.tm_mon != old_line_date.tm_mon)
+ || (line_date.tm_year != old_line_date.tm_year))
+ stop = 1;
+ }
+ /* we consider month is 30 days, who will find I'm too
+ lazy to code exact date diff ? ;) */
+ else if (diff_date >= number * 60 * 60 * 24 * 30)
+ stop = 1;
+ break;
+ case 'y': /* years */
+ if (number == 0)
+ {
+ /* stop if line has different year */
+ if (line_date.tm_year != old_line_date.tm_year)
+ stop = 1;
+ }
+ /* we consider year is 365 days, who will find I'm too
+ lazy to code exact date diff ? ;) */
+ else if (diff_date >= number * 60 * 60 * 24 * 365)
+ stop = 1;
+ break;
+ }
+ }
+ if (stop)
+ {
+ window->start_line = ptr_line;
+ window->start_line_pos = 0;
+ window->first_line_displayed =
+ (window->start_line == window->buffer->lines);
+ gui_chat_draw (window->buffer, 1);
+ gui_status_draw (window->buffer, 0);
+ return;
+ }
+ }
+ }
+ if (direction < 0)
+ gui_window_scroll_top (window);
+ else
+ gui_window_scroll_bottom (window);
+ }
+}
+
+/*
* gui_buffer_print_log: print buffer infos in log (usually for crash dump)
*/
diff --git a/src/gui/gui.h b/src/gui/gui.h
index 3a022bffd..8afb5d79c 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -105,6 +105,7 @@ extern void gui_buffer_search_start (t_gui_window *);
extern void gui_buffer_search_restart (t_gui_window *);
extern void gui_buffer_search_stop (t_gui_window *);
extern int gui_buffer_search_text (t_gui_window *);
+extern void gui_buffer_scroll (t_gui_window *, char *);
extern void gui_buffer_print_log (t_gui_buffer *);
/* panel */