File sb_splits.c of Package irssi-sb-splits
/*
* COMPILATION:
* ============
* gcc -fPIC -Wall -shared -g -o ~/.irssi/modules/libsb_splits.so -DHAVE_CONFIG_H `pkg-config --cflags glib-2.0` sb_splits.c
*
* Old Irssis:
* -----------
* export IRSSI=~/src/irssi
* gcc -fPIC -Wall -shared -g -o ~/.irssi/modules/libsb_splits.so -I$IRSSI -I$IRSSI/src -I$IRSSI/src/fe-common/core -I$IRSSI/src/core -I$IRSSI/src/fe-text -DHAVE_CONFIG_H `pkg-config --cflags glib-2.0` sb_splits.c
*
* USAGE:
* ======
* /load sb_splits
* /statusbar window add -after window_empty splits
* /statusbar window_inact add -after window_empty splits
*/
#define MODULE_NAME "fe-text/sb-splits"
#include <irssi/src/common.h>
#include <irssi/src/core/modules.h>
#include <irssi/src/core/signals.h>
#include <irssi/src/fe-text/mainwindows.h>
#include <irssi/src/fe-text/gui-windows.h>
#include <irssi/src/fe-text/statusbar.h>
static GHashTable *deco_notes;
static GSList *list_windows(MAIN_WINDOW_REC *mainwin, gboolean sticky)
{
GSList *tmp, *list;
list = NULL;
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
if (WINDOW_GUI(rec) == NULL)
continue;
if ((sticky && WINDOW_GUI(rec)->sticky &&
WINDOW_MAIN(rec) == mainwin) ||
(!sticky && !WINDOW_GUI(rec)->sticky &&
(WINDOW_MAIN(rec)->active != rec ||
WINDOW_MAIN(rec) == mainwin))) {
list = g_slist_insert_sorted(list, rec, (GCompareFunc)
window_refnum_cmp);
}
}
return list;
}
static inline gboolean item_too_long(SBAR_ITEM_REC *item, const char *buf,
size_t str_len, int deco_len, size_t float_len, size_t was_active_len)
{
return str_len + strlen(buf) + float_len - was_active_len - 1 > item->size - deco_len;
}
static inline char *render_window(GSList **list_item, SBAR_ITEM_REC *item, gboolean get_size_only,
size_t str_len, int deco_len, size_t float_len, size_t was_active_len)
{
WINDOW_REC *window;
char *buf = NULL;
if (*list_item) {
window = (*list_item)->data;
buf = g_strdup_printf("%d ", window->refnum);
*list_item = (*list_item)->next;
if (!get_size_only && item_too_long(item, buf, str_len, deco_len, float_len, was_active_len)) {
g_free(buf);
buf = NULL;
}
}
return buf;
}
#define WAS_ACTIVE_LEN (was_active ? 4 /* strlen("%8%8") */ : 0)
#define FLOAT_LEN (is_sticky ? 0 : 2 /* strlen("<>") */)
static void item_splits(SBAR_ITEM_REC *item, int get_size_only)
{
GSList *tmp, *tmp2, *winlist, *winlist2;
MAIN_WINDOW_REC *mainwin;
WINDOW_REC *active;
GString *str;
gboolean was_active, is_sticky;
int deco;
mainwin = item->bar->parent_window;
active = mainwin->active;
if (mainwin == NULL || active == NULL) {
statusbar_item_default_handler(item, get_size_only, NULL, "", FALSE);
return;
}
is_sticky = mainwin->sticky_windows;
winlist = list_windows(mainwin, is_sticky);
winlist2 = g_slist_reverse(g_slist_copy(winlist));
str = g_string_new(NULL);
for (tmp = winlist; tmp != NULL && ((WINDOW_REC*)tmp->data)->refnum < active->refnum;
tmp = tmp->next);
for (tmp2 = winlist2; tmp2 != NULL && ((WINDOW_REC*)tmp2->data)->refnum >= active->refnum;
tmp2 = tmp2->next);
was_active = tmp != NULL && tmp->data == active;
deco = GPOINTER_TO_INT(g_hash_table_lookup(deco_notes, item));
if (was_active) {
g_string_append_printf(str, "%%8%d%%8 ", active->refnum);
tmp = tmp->next;
}
while (tmp || tmp2) {
char *buf;
if ((buf = render_window(&tmp2, item, get_size_only, str->len, deco, FLOAT_LEN, WAS_ACTIVE_LEN)) != NULL) {
g_string_prepend(str, buf);
g_free(buf);
}
if ((buf = render_window(&tmp, item, get_size_only, str->len, deco, FLOAT_LEN, WAS_ACTIVE_LEN)) != NULL) {
g_string_append(str, buf);
g_free(buf);
}
}
g_slist_free(winlist);
g_slist_free(winlist2);
if (!is_sticky) {
g_string_prepend(str, "<>");
}
if (str->len > 0) {
g_string_truncate(str, str->len - 1);
}
statusbar_item_default_handler(item, get_size_only,
NULL, str->str, FALSE);
if (get_size_only) {
g_hash_table_insert(deco_notes, item,
GINT_TO_POINTER(item->max_size - (str->len - WAS_ACTIVE_LEN)));
}
g_string_free(str, TRUE);
}
static void redraw_splits(void)
{
statusbar_items_redraw("splits");
}
void sb_splits_init(void)
{
deco_notes = g_hash_table_new(g_direct_hash, g_direct_equal);
statusbar_item_register("splits", "{sb $0-}", item_splits);
signal_add("window changed", (SIGNAL_FUNC) redraw_splits);
signal_add_last("window changed automatic", (SIGNAL_FUNC) redraw_splits);
signal_add_last("window created", (SIGNAL_FUNC) redraw_splits);
signal_add("window destroyed", (SIGNAL_FUNC) redraw_splits);
signal_add("window refnum changed", (SIGNAL_FUNC) redraw_splits);
signal_add_last("command window stick", (SIGNAL_FUNC) redraw_splits);
redraw_splits();
module_register("sb_splits", "core");
}
void sb_splits_deinit(void)
{
signal_remove("window changed", (SIGNAL_FUNC) redraw_splits);
signal_remove("window changed automatic", (SIGNAL_FUNC) redraw_splits);
signal_remove("window created", (SIGNAL_FUNC) redraw_splits);
signal_remove("window destroyed", (SIGNAL_FUNC) redraw_splits);
signal_remove("window refnum changed", (SIGNAL_FUNC) redraw_splits);
signal_remove("command window stick", (SIGNAL_FUNC) redraw_splits);
statusbar_item_unregister("splits");
redraw_splits();
g_hash_table_destroy(deco_notes);
}
#ifdef MODULE_ABICHECK
MODULE_ABICHECK(sb_splits)
#else
#ifdef IRSSI_ABI_VERSION
void sb_splits_abicheck(int *version)
{
*version = IRSSI_ABI_VERSION;
}
#endif
#endif