irssi/src/fe-text/statusbar-items.c
Timo Sirainen bd6fe052bc Added time, size and level setting types. Breaks some settings - I'll add
automatic converter to these settings later. Meanwhile you CVS users can
fix your config files yourself :)

Time settings allow using "days", "hours", "minutes", "seconds" and
"milliseconds" or several of their abbreviations. For example "5d 4h
5msecs".

Size settings allow using "gbytes", "mbytes", "kbytes" and "bytes" or their
abbrevations. For example "5MB".

Level settings are currently handled pretty much the way they were before.


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@3080 dbcabf3a-b0e7-0310-adc4-f8d773084564
2002-12-28 17:54:13 +00:00

449 lines
13 KiB
C

/*
statusbar-items.c : irssi
Copyright (C) 1999-2001 Timo Sirainen
This program 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 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "module.h"
#include "signals.h"
#include "settings.h"
#include "servers.h"
#include "themes.h"
#include "statusbar.h"
#include "gui-entry.h"
#include "gui-windows.h"
/* how often to redraw lagging time (seconds) */
#define LAG_REFRESH_TIME 10
static GList *activity_list;
static GSList *more_visible; /* list of MAIN_WINDOW_RECs which have --more-- */
static GHashTable *input_entries;
static int last_lag, last_lag_unknown, lag_timeout_tag;
static void item_window_active(SBAR_ITEM_REC *item, int get_size_only)
{
WINDOW_REC *window;
window = active_win;
if (item->bar->parent_window != NULL)
window = item->bar->parent_window->active;
if (window != NULL && window->active != NULL) {
statusbar_item_default_handler(item, get_size_only,
NULL, "", TRUE);
} else if (get_size_only) {
item->min_size = item->max_size = 0;
}
}
static void item_window_empty(SBAR_ITEM_REC *item, int get_size_only)
{
WINDOW_REC *window;
window = active_win;
if (item->bar->parent_window != NULL)
window = item->bar->parent_window->active;
if (window != NULL && window->active == NULL) {
statusbar_item_default_handler(item, get_size_only,
NULL, "", TRUE);
} else if (get_size_only) {
item->min_size = item->max_size = 0;
}
}
static char *get_activity_list(MAIN_WINDOW_REC *window, int normal, int hilight)
{
THEME_REC *theme;
GString *str;
GList *tmp;
char *ret, *name, *format, *value;
int is_det;
str = g_string_new(NULL);
theme = window != NULL && window->active != NULL &&
window->active->theme != NULL ?
window->active->theme : current_theme;
for (tmp = activity_list; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *window = tmp->data;
is_det = window->data_level >= DATA_LEVEL_HILIGHT;
if ((!is_det && !normal) || (is_det && !hilight))
continue;
/* comma separator */
if (str->len > 0) {
value = theme_format_expand(theme, "{sb_act_sep ,}");
g_string_append(str, value);
g_free(value);
}
switch (window->data_level) {
case DATA_LEVEL_NONE:
case DATA_LEVEL_TEXT:
name = "{sb_act_text %d}";
break;
case DATA_LEVEL_MSG:
name = "{sb_act_msg %d}";
break;
default:
if (window->hilight_color == NULL)
name = "{sb_act_hilight %d}";
else
name = NULL;
break;
}
if (name != NULL)
format = g_strdup_printf(name, window->refnum);
else
format = g_strdup_printf("{sb_act_hilight_color %s %d}",
window->hilight_color,
window->refnum);
value = theme_format_expand(theme, format);
g_string_append(str, value);
g_free(value);
g_free(format);
}
ret = str->len == 0 ? NULL : str->str;
g_string_free(str, ret == NULL);
return ret;
}
/* redraw activity, FIXME: if we didn't get enough size, this gets buggy.
At least "Det:" isn't printed properly. also we should rearrange the
act list so that the highest priority items comes first. */
static void item_act(SBAR_ITEM_REC *item, int get_size_only)
{
char *actlist;
actlist = get_activity_list(item->bar->parent_window, TRUE, TRUE);
if (actlist == NULL) {
if (get_size_only)
item->min_size = item->max_size = 0;
return;
}
statusbar_item_default_handler(item, get_size_only,
NULL, actlist, FALSE);
g_free_not_null(actlist);
}
static void sig_statusbar_activity_hilight(WINDOW_REC *window, gpointer oldlevel)
{
GList *tmp;
int inspos;
g_return_if_fail(window != NULL);
if (settings_get_bool("actlist_moves")) {
/* Move the window to the first in the activity list */
if (g_list_find(activity_list, window) != NULL)
activity_list = g_list_remove(activity_list, window);
if (window->data_level != 0)
activity_list = g_list_prepend(activity_list, window);
statusbar_items_redraw("act");
return;
}
if (g_list_find(activity_list, window) != NULL) {
/* already in activity list */
if (window->data_level == 0) {
/* remove from activity list */
activity_list = g_list_remove(activity_list, window);
statusbar_items_redraw("act");
} else if (window->data_level != GPOINTER_TO_INT(oldlevel) ||
window->hilight_color != 0) {
/* different level as last time (or maybe different
hilight color?), just redraw it. */
statusbar_items_redraw("act");
}
return;
}
if (window->data_level == 0)
return;
/* add window to activity list .. */
inspos = 0;
for (tmp = activity_list; tmp != NULL; tmp = tmp->next, inspos++) {
WINDOW_REC *rec = tmp->data;
if (window->refnum < rec->refnum) {
activity_list =
g_list_insert(activity_list, window, inspos);
break;
}
}
if (tmp == NULL)
activity_list = g_list_append(activity_list, window);
statusbar_items_redraw("act");
}
static void sig_statusbar_activity_window_destroyed(WINDOW_REC *window)
{
g_return_if_fail(window != NULL);
if (g_list_find(activity_list, window) != NULL)
activity_list = g_list_remove(activity_list, window);
statusbar_items_redraw("act");
}
static void sig_statusbar_activity_updated(void)
{
statusbar_items_redraw("act");
}
static void item_more(SBAR_ITEM_REC *item, int get_size_only)
{
MAIN_WINDOW_REC *mainwin;
int visible;
if (active_win == NULL) {
mainwin = NULL;
visible = FALSE;
} else {
mainwin = WINDOW_MAIN(active_win);
visible = WINDOW_GUI(active_win)->view->more_text;
}
if (!visible) {
if (mainwin != NULL)
more_visible = g_slist_remove(more_visible, mainwin);
if (get_size_only)
item->min_size = item->max_size = 0;
return;
}
more_visible = g_slist_prepend(more_visible, mainwin);
statusbar_item_default_handler(item, get_size_only, NULL, "", FALSE);
}
static void sig_statusbar_more_updated(void)
{
int visible;
visible = g_slist_find(more_visible, WINDOW_MAIN(active_win)) != NULL;
if (WINDOW_GUI(active_win)->view->more_text != visible)
statusbar_items_redraw("more");
}
/* Returns the lag in milliseconds. If we haven't been able to ask the lag
for a while, unknown is set to TRUE. */
static int get_lag(SERVER_REC *server, int *unknown)
{
long lag;
*unknown = FALSE;
if (server == NULL || server->lag_last_check == 0) {
/* lag has not been asked even once yet */
return 0;
}
if (server->lag_sent.tv_sec == 0) {
/* no lag queries going on currently */
return server->lag;
}
/* we're not sure about our current lag.. */
*unknown = TRUE;
lag = (long) (time(NULL)-server->lag_sent.tv_sec);
if (server->lag/1000 > lag) {
/* we've been waiting the lag reply less time than
what last known lag was -> use the last known lag */
return server->lag;
}
/* return how long we have been waiting for lag reply */
return lag*1000;
}
static void item_lag(SBAR_ITEM_REC *item, int get_size_only)
{
SERVER_REC *server;
char str[MAX_INT_STRLEN+10];
int lag, lag_unknown;
server = active_win == NULL ? NULL : active_win->active_server;
lag = get_lag(server, &lag_unknown);
if (lag <= 0 || lag < settings_get_time("lag_min_show")) {
/* don't print the lag item */
if (get_size_only)
item->min_size = item->max_size = 0;
return;
}
lag /= 10;
last_lag = lag;
last_lag_unknown = lag_unknown;
if (lag_unknown) {
g_snprintf(str, sizeof(str), "%d (?""?)", lag/100);
} else {
g_snprintf(str, sizeof(str),
lag%100 == 0 ? "%d" : "%d.%02d", lag/100, lag%100);
}
statusbar_item_default_handler(item, get_size_only,
NULL, str, TRUE);
}
static void lag_check_update(void)
{
SERVER_REC *server;
int lag, lag_unknown;
server = active_win == NULL ? NULL : active_win->active_server;
lag = get_lag(server, &lag_unknown)/10;
if (lag < settings_get_time("lag_min_show"))
lag = 0;
else
lag /= 10;
if (lag != last_lag || (lag > 0 && lag_unknown != last_lag_unknown))
statusbar_items_redraw("lag");
}
static void sig_server_lag_updated(SERVER_REC *server)
{
if (active_win != NULL && active_win->active_server == server)
lag_check_update();
}
static int sig_lag_timeout(void)
{
lag_check_update();
return 1;
}
static void item_input(SBAR_ITEM_REC *item, int get_size_only)
{
GUI_ENTRY_REC *rec;
rec = g_hash_table_lookup(input_entries, item->bar->config->name);
if (rec == NULL) {
rec = gui_entry_create(item->xpos, item->bar->real_ypos,
item->size, term_type == TERM_TYPE_UTF8);
gui_entry_set_active(rec);
g_hash_table_insert(input_entries,
g_strdup(item->bar->config->name), rec);
}
if (get_size_only) {
item->min_size = 2+term_width/10;
item->max_size = term_width;
return;
}
gui_entry_move(rec, item->xpos, item->bar->real_ypos,
item->size);
gui_entry_redraw(rec); /* FIXME: this is only necessary with ^L.. */
}
static void read_settings(void)
{
if (active_entry != NULL)
gui_entry_set_utf8(active_entry, term_type == TERM_TYPE_UTF8);
}
void statusbar_items_init(void)
{
settings_add_time("misc", "lag_min_show", "100msec");
settings_add_bool("lookandfeel", "actlist_moves", FALSE);
statusbar_item_register("window", NULL, item_window_active);
statusbar_item_register("window_empty", NULL, item_window_empty);
statusbar_item_register("prompt", NULL, item_window_active);
statusbar_item_register("prompt_empty", NULL, item_window_empty);
statusbar_item_register("topic", NULL, item_window_active);
statusbar_item_register("topic_empty", NULL, item_window_empty);
statusbar_item_register("lag", NULL, item_lag);
statusbar_item_register("act", NULL, item_act);
statusbar_item_register("more", NULL, item_more);
statusbar_item_register("input", NULL, item_input);
/* activity */
activity_list = NULL;
signal_add("window activity", (SIGNAL_FUNC) sig_statusbar_activity_hilight);
signal_add("window destroyed", (SIGNAL_FUNC) sig_statusbar_activity_window_destroyed);
signal_add("window refnum changed", (SIGNAL_FUNC) sig_statusbar_activity_updated);
/* more */
more_visible = NULL;
signal_add("gui page scrolled", (SIGNAL_FUNC) sig_statusbar_more_updated);
signal_add("window changed", (SIGNAL_FUNC) sig_statusbar_more_updated);
signal_add_last("gui print text finished", (SIGNAL_FUNC) sig_statusbar_more_updated);
signal_add_last("command clear", (SIGNAL_FUNC) sig_statusbar_more_updated);
signal_add_last("command scrollback", (SIGNAL_FUNC) sig_statusbar_more_updated);
/* lag */
last_lag = 0; last_lag_unknown = FALSE;
signal_add("server lag", (SIGNAL_FUNC) sig_server_lag_updated);
signal_add("window changed", (SIGNAL_FUNC) lag_check_update);
signal_add("window server changed", (SIGNAL_FUNC) lag_check_update);
lag_timeout_tag = g_timeout_add(5000, (GSourceFunc) sig_lag_timeout, NULL);
/* input */
input_entries = g_hash_table_new((GHashFunc) g_str_hash,
(GCompareFunc) g_str_equal);
read_settings();
signal_add_last("setup changed", (SIGNAL_FUNC) read_settings);
}
void statusbar_items_deinit(void)
{
/* activity */
signal_remove("window activity", (SIGNAL_FUNC) sig_statusbar_activity_hilight);
signal_remove("window destroyed", (SIGNAL_FUNC) sig_statusbar_activity_window_destroyed);
signal_remove("window refnum changed", (SIGNAL_FUNC) sig_statusbar_activity_updated);
g_list_free(activity_list);
activity_list = NULL;
/* more */
g_slist_free(more_visible);
signal_remove("gui page scrolled", (SIGNAL_FUNC) sig_statusbar_more_updated);
signal_remove("window changed", (SIGNAL_FUNC) sig_statusbar_more_updated);
signal_remove("gui print text finished", (SIGNAL_FUNC) sig_statusbar_more_updated);
signal_remove("command clear", (SIGNAL_FUNC) sig_statusbar_more_updated);
signal_remove("command scrollback", (SIGNAL_FUNC) sig_statusbar_more_updated);
/* lag */
signal_remove("server lag", (SIGNAL_FUNC) sig_server_lag_updated);
signal_remove("window changed", (SIGNAL_FUNC) lag_check_update);
signal_remove("window server changed", (SIGNAL_FUNC) lag_check_update);
g_source_remove(lag_timeout_tag);
/* input */
g_hash_table_foreach(input_entries, (GHFunc) g_free, NULL);
g_hash_table_destroy(input_entries);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
}