1
0
mirror of https://github.com/irssi/irssi.git synced 2024-10-27 05:20:20 -04:00

Merge pull request #585 from ailin-nemui/win_seq

g_sequence backing for window list
This commit is contained in:
ailin-nemui 2017-01-03 12:45:50 +01:00 committed by GitHub
commit 01163710e7
3 changed files with 189 additions and 66 deletions

View File

@ -246,7 +246,7 @@ for try in 1 2; do
echo "*** trying without -lgmodule"
glib_modules=
fi
AM_PATH_GLIB_2_0(2.16.0,,, $glib_modules)
AM_PATH_GLIB_2_0(2.28.0,,, $glib_modules)
if test "$GLIB_LIBS"; then
if test $glib_modules = gmodule; then
AC_DEFINE(HAVE_GMODULE)

View File

@ -35,30 +35,83 @@
GSList *windows; /* first in the list is the active window,
next is the last active, etc. */
GSequence *windows_seq;
WINDOW_REC *active_win;
static int daytag;
static int daycheck; /* 0 = don't check, 1 = time is 00:00, check,
2 = time is 00:00, already checked */
static int window_refnum_lookup(WINDOW_REC *window, void *refnum_p)
{
int refnum = GPOINTER_TO_INT(refnum_p);
return window->refnum == refnum ? 0 : window->refnum < refnum ? -1 : 1;
}
static GSequenceIter *windows_seq_begin(void)
{
return g_sequence_get_begin_iter(windows_seq);
}
static GSequenceIter *windows_seq_end(void)
{
return g_sequence_get_end_iter(windows_seq);
}
static GSequenceIter *windows_seq_insert(WINDOW_REC *rec)
{
return g_sequence_insert_sorted(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL);
}
static GSequenceIter *windows_seq_refnum_lookup(int refnum)
{
return g_sequence_lookup(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL);
}
static void windows_seq_changed(GSequenceIter *iter)
{
g_sequence_sort_changed(iter, (GCompareDataFunc)window_refnum_cmp, NULL);
}
static GSequenceIter *windows_seq_window_lookup(WINDOW_REC *rec)
{
return g_sequence_lookup(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL);
}
/* search to the numerically right iterator of refnum */
static GSequenceIter *windows_seq_refnum_search_right(int refnum)
{
return g_sequence_search(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL);
}
/* we want to find the numerically left iterator of refnum, so we
search the right of the previous refnum. but we need to figure out
the case where the iterator is already at the beginning, i.e
iter->refnum >= refnum */
static GSequenceIter *windows_seq_refnum_search_left(int refnum)
{
GSequenceIter *iter = windows_seq_refnum_search_right(refnum - 1);
return iter == windows_seq_begin() ? NULL : g_sequence_iter_prev(iter);
}
static int window_get_new_refnum(void)
{
WINDOW_REC *win;
GSList *tmp;
GSequenceIter *iter, *end;
int refnum;
refnum = 1;
tmp = windows;
while (tmp != NULL) {
win = tmp->data;
iter = windows_seq_begin();
end = windows_seq_end();
if (refnum != win->refnum) {
tmp = tmp->next;
continue;
}
while (iter != end) {
win = g_sequence_get(iter);
if (refnum != win->refnum)
return refnum;
refnum++;
tmp = windows;
iter = g_sequence_iter_next(iter);
}
return refnum;
@ -73,6 +126,7 @@ WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic)
rec->level = settings_get_level("window_default_level");
windows = g_slist_prepend(windows, rec);
windows_seq_insert(rec);
signal_emit("window created", 2, rec, GINT_TO_POINTER(automatic));
if (item != NULL) window_item_add(rec, item, automatic);
@ -84,6 +138,19 @@ WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic)
return rec;
}
static void window_set_refnum0(WINDOW_REC *window, int refnum)
{
int old_refnum;
g_return_if_fail(window != NULL);
g_return_if_fail(refnum >= 1);
if (window->refnum == refnum) return;
old_refnum = window->refnum;
window->refnum = refnum;
signal_emit("window refnum changed", 2, window, GINT_TO_POINTER(old_refnum));
}
/* removed_refnum was removed from the windows list, pack the windows so
there won't be any holes. If there is any holes after removed_refnum,
leave the windows behind it alone. */
@ -91,23 +158,37 @@ static void windows_pack(int removed_refnum)
{
WINDOW_REC *window;
int refnum;
GSequenceIter *iter, *end;
for (refnum = removed_refnum+1;; refnum++) {
window = window_find_refnum(refnum);
if (window == NULL || window->sticky_refnum)
refnum = removed_refnum + 1;
end = windows_seq_end();
iter = windows_seq_refnum_lookup(refnum);
if (iter == NULL) return;
while (iter != end) {
window = g_sequence_get(iter);
if (window == NULL || window->sticky_refnum || window->refnum != refnum)
break;
window_set_refnum(window, refnum-1);
window_set_refnum0(window, refnum - 1);
windows_seq_changed(iter);
refnum++;
iter = g_sequence_iter_next(iter);
}
}
void window_destroy(WINDOW_REC *window)
{
GSequenceIter *iter;
g_return_if_fail(window != NULL);
if (window->destroying) return;
window->destroying = TRUE;
windows = g_slist_remove(windows, window);
iter = windows_seq_window_lookup(window);
if (iter != NULL) g_sequence_remove(iter);
if (active_win == window) {
active_win = NULL; /* it's corrupted */
@ -189,26 +270,32 @@ void window_change_server(WINDOW_REC *window, void *server)
void window_set_refnum(WINDOW_REC *window, int refnum)
{
GSList *tmp;
GSequenceIter *other_iter, *window_iter;
int old_refnum;
g_return_if_fail(window != NULL);
g_return_if_fail(refnum >= 1);
if (window->refnum == refnum) return;
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
other_iter = windows_seq_refnum_lookup(refnum);
window_iter = windows_seq_refnum_lookup(window->refnum);
if (rec->refnum == refnum) {
rec->refnum = window->refnum;
signal_emit("window refnum changed", 2, rec, GINT_TO_POINTER(refnum));
break;
}
if (other_iter != NULL) {
WINDOW_REC *rec = g_sequence_get(other_iter);
rec->refnum = window->refnum;
signal_emit("window refnum changed", 2, rec, GINT_TO_POINTER(refnum));
}
old_refnum = window->refnum;
window->refnum = refnum;
signal_emit("window refnum changed", 2, window, GINT_TO_POINTER(old_refnum));
if (window_iter != NULL && other_iter != NULL) {
g_sequence_swap(other_iter, window_iter);
} else {
windows_seq_changed(window_iter);
}
}
void window_set_name(WINDOW_REC *window, const char *name)
@ -346,13 +433,13 @@ WINDOW_REC *window_find_closest(void *server, const char *name, int level)
WINDOW_REC *window_find_refnum(int refnum)
{
GSList *tmp;
GSequenceIter *iter;
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
iter = windows_seq_refnum_lookup(refnum);
if (iter != NULL) {
WINDOW_REC *rec = g_sequence_get(iter);
if (rec->refnum == refnum)
return rec;
return rec;
}
return NULL;
@ -400,71 +487,86 @@ WINDOW_REC *window_find_item(SERVER_REC *server, const char *name)
int window_refnum_prev(int refnum, int wrap)
{
GSList *tmp;
int prev, max;
WINDOW_REC *rec;
GSequenceIter *iter, *end;
max = prev = -1;
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
iter = windows_seq_refnum_search_left(refnum);
end = windows_seq_end();
if (rec->refnum < refnum && (prev == -1 || rec->refnum > prev))
prev = rec->refnum;
if (wrap && (max == -1 || rec->refnum > max))
max = rec->refnum;
if (iter != NULL) {
rec = g_sequence_get(iter);
return rec->refnum;
}
return prev != -1 ? prev : max;
if (wrap) {
iter = g_sequence_iter_prev(end);
if (iter != end) {
rec = g_sequence_get(iter);
return rec->refnum;
}
}
return -1;
}
int window_refnum_next(int refnum, int wrap)
{
GSList *tmp;
int min, next;
WINDOW_REC *rec;
GSequenceIter *iter, *end;
min = next = -1;
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
iter = windows_seq_refnum_search_right(refnum);
end = windows_seq_end();
if (rec->refnum > refnum && (next == -1 || rec->refnum < next))
next = rec->refnum;
if (wrap && (min == -1 || rec->refnum < min))
min = rec->refnum;
if (iter != end) {
rec = g_sequence_get(iter);
return rec->refnum;
}
return next != -1 ? next : min;
if (wrap) {
iter = windows_seq_begin();
if (iter != end) {
rec = g_sequence_get(iter);
return rec->refnum;
}
}
return -1;
}
int windows_refnum_last(void)
{
GSList *tmp;
int max;
WINDOW_REC *rec;
GSequenceIter *end, *iter;
max = -1;
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
if (rec->refnum > max)
max = rec->refnum;
end = windows_seq_end();
iter = g_sequence_iter_prev(end);
if (iter != end) {
rec = g_sequence_get(iter);
return rec->refnum;
}
return max;
return -1;
}
int window_refnum_cmp(WINDOW_REC *w1, WINDOW_REC *w2)
{
return w1->refnum < w2->refnum ? -1 : 1;
return w1 == w2 ? 0 : w1->refnum < w2->refnum ? -1 : 1;
}
GSList *windows_get_sorted(void)
{
GSList *tmp, *sorted;
GSequenceIter *iter, *begin;
GSList *sorted;
sorted = NULL;
for (tmp = windows; tmp != NULL; tmp = tmp->next) {
WINDOW_REC *rec = tmp->data;
iter = windows_seq_end();
begin = windows_seq_begin();
sorted = g_slist_insert_sorted(sorted, rec, (GCompareFunc)
window_refnum_cmp);
while (iter != begin) {
iter = g_sequence_iter_prev(iter);
WINDOW_REC *rec = g_sequence_get(iter);
sorted = g_slist_prepend(sorted, rec);
}
return sorted;
@ -709,6 +811,7 @@ static void read_settings(void)
void windows_init(void)
{
active_win = NULL;
windows_seq = g_sequence_new(NULL);
daycheck = 0; daytag = -1;
settings_add_bool("lookandfeel", "window_auto_change", FALSE);
settings_add_bool("lookandfeel", "windows_auto_renumber", TRUE);
@ -733,4 +836,6 @@ void windows_deinit(void)
signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
signal_remove("server connect failed", (SIGNAL_FUNC) sig_server_disconnected);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
g_sequence_free(windows_seq);
windows_seq = NULL;
}

View File

@ -143,16 +143,34 @@ static char *get_activity_list(MAIN_WINDOW_REC *window, int normal, int hilight)
static void item_act(SBAR_ITEM_REC *item, int get_size_only)
{
char *actlist;
int max_size;
actlist = get_activity_list(item->bar->parent_window, TRUE, TRUE);
if (actlist == NULL) {
if (get_size_only)
if (get_size_only) {
if (activity_list == NULL)
item->min_size = item->max_size = 0;
/* Skip activity calculation on regular trigger, only
set dirty */
return;
}
statusbar_item_default_handler(item, get_size_only,
actlist = get_activity_list(item->bar->parent_window, TRUE, TRUE);
if (actlist == NULL) {
return;
}
max_size = item->max_size;
statusbar_item_default_handler(item, TRUE,
NULL, actlist, FALSE);
statusbar_item_default_handler(item, FALSE,
NULL, actlist, FALSE);
if (max_size != item->max_size) {
/* Due to above hack of skipping the calculation, we
need to manually trigger the redraw process now or
we won't see the item */
item->bar->dirty = item->dirty = TRUE;
statusbar_redraw(item->bar, TRUE);
statusbar_redraw_dirty();
}
g_free_not_null(actlist);
}