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
openSUSE Build Service is sponsored by