4 Copyright (C) 1999-2001 Timo Sirainen
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "special-vars.h"
28 #include "statusbar.h"
29 #include "statusbar-config.h"
30 #include "gui-windows.h"
31 #include "gui-printtext.h"
33 void statusbar_items_init(void);
34 void statusbar_items_deinit(void);
36 GSList *statusbar_groups;
37 STATUSBAR_GROUP_REC *active_statusbar_group;
40 sbar_item_defs: char *name => char *value
41 sbar_item_funcs: char *name => STATUSBAR_FUNC func
42 sbar_signal_items: int signal_id => GSList *(SBAR_ITEM_REC *items)
43 sbar_item_signals: SBAR_ITEM_REC *item => GSList *(int *signal_ids)
44 named_sbar_items: const char *name => GSList *(SBAR_ITEM_REC *items)
46 static GHashTable *sbar_item_defs, *sbar_item_funcs;
47 static GHashTable *sbar_signal_items, *sbar_item_signals;
48 static GHashTable *named_sbar_items;
49 static int statusbar_need_recreate_items;
51 void statusbar_item_register(const char *name, const char *value,
54 gpointer hkey, hvalue;
56 statusbar_need_recreate_items = TRUE;
58 if (g_hash_table_lookup_extended(sbar_item_defs,
59 name, &hkey, &hvalue)) {
60 g_hash_table_remove(sbar_item_defs, name);
64 g_hash_table_insert(sbar_item_defs,
65 g_strdup(name), g_strdup(value));
69 if (g_hash_table_lookup(sbar_item_funcs, name) == NULL) {
70 g_hash_table_insert(sbar_item_funcs,
71 g_strdup(name), (void *) func);
76 void statusbar_item_unregister(const char *name)
80 statusbar_need_recreate_items = TRUE;
81 if (g_hash_table_lookup_extended(sbar_item_defs,
82 name, &key, &value)) {
83 g_hash_table_remove(sbar_item_defs, key);
88 if (g_hash_table_lookup_extended(sbar_item_funcs,
89 name, &key, &value)) {
90 g_hash_table_remove(sbar_item_funcs, key);
95 STATUSBAR_GROUP_REC *statusbar_group_create(const char *name)
97 STATUSBAR_GROUP_REC *rec;
99 rec = g_new0(STATUSBAR_GROUP_REC, 1);
100 rec->name = g_strdup(name);
102 statusbar_groups = g_slist_append(statusbar_groups, rec);
106 void statusbar_group_destroy(STATUSBAR_GROUP_REC *rec)
108 statusbar_groups = g_slist_remove(statusbar_groups, rec);
110 while (rec->bars != NULL)
111 statusbar_destroy(rec->bars->data);
112 while (rec->config_bars != NULL)
113 statusbar_config_destroy(rec, rec->config_bars->data);
119 STATUSBAR_GROUP_REC *statusbar_group_find(const char *name)
123 for (tmp = statusbar_groups; tmp != NULL; tmp = tmp->next) {
124 STATUSBAR_GROUP_REC *rec = tmp->data;
126 if (strcmp(rec->name, name) == 0)
133 static int sbar_item_cmp(SBAR_ITEM_REC *item1, SBAR_ITEM_REC *item2)
135 return item1->config->priority == item2->config->priority ? 0 :
136 item1->config->priority < item2->config->priority ? -1 : 1;
139 static int sbar_cmp_position(STATUSBAR_REC *bar1, STATUSBAR_REC *bar2)
141 return bar1->config->position < bar2->config->position ? -1 : 1;
144 /* Shink all items in statusbar to their minimum requested size.
145 The items list should be sorted by priority, highest first. */
146 static int statusbar_shrink_to_min(GSList *items, int size, int max_width)
150 for (tmp = items; tmp != NULL; tmp = tmp->next) {
151 SBAR_ITEM_REC *rec = tmp->data;
153 size -= (rec->max_size-rec->min_size);
154 rec->size = rec->min_size;
156 if (size <= max_width) {
157 rec->size += max_width-size;
161 if (rec->size == 0) {
162 /* min_size was 0, item removed.
163 remove the marginal too */
171 /* shink the items in statusbar, even if their size gets smaller than
172 their minimum requested size. The items list should be sorted by
173 priority, highest first. */
174 static void statusbar_shrink_forced(GSList *items, int size, int max_width)
178 for (tmp = items; tmp != NULL; tmp = tmp->next) {
179 SBAR_ITEM_REC *rec = tmp->data;
181 if (size-rec->size > max_width) {
182 /* remove the whole item */
186 /* shrink the item */
187 rec->size -= size-max_width;
193 static void statusbar_resize_items(STATUSBAR_REC *bar, int max_width)
195 GSList *tmp, *prior_sorted;
198 /* first give items their max. size */
201 for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
202 SBAR_ITEM_REC *rec = tmp->data;
204 rec->func(rec, TRUE);
205 rec->size = rec->max_size;
208 width += rec->max_size;
210 prior_sorted = g_slist_insert_sorted(prior_sorted, rec,
216 if (width > max_width) {
217 /* too big, start shrinking from items with lowest priority
218 and shrink until everything fits or until we've shrinked
220 width = statusbar_shrink_to_min(prior_sorted, width,
222 if (width > max_width) {
223 /* still need to shrink, remove the items with lowest
224 priority until everything fits to screen */
225 statusbar_shrink_forced(prior_sorted, width,
230 g_slist_free(prior_sorted);
233 #define SBAR_ITEM_REDRAW_NEEDED(_bar, _item, _xpos) \
234 (((_bar)->dirty_xpos != -1 && \
235 (_xpos) >= (_bar)->dirty_xpos) || \
236 (_item)->xpos != (_xpos) || (_item)->current_size != (_item)->size)
238 static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
240 WINDOW_REC *old_active_win;
241 GSList *tmp, *right_items;
244 old_active_win = active_win;
245 if (bar->parent_window != NULL)
246 active_win = bar->parent_window->active;
248 statusbar_resize_items(bar, term_width);
250 /* left-aligned items */
252 for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
253 SBAR_ITEM_REC *rec = tmp->data;
255 if (!rec->config->right_alignment &&
256 (rec->size > 0 || rec->current_size > 0)) {
257 if (SBAR_ITEM_REDRAW_NEEDED(bar, rec, xpos)) {
258 /* redraw the item */
260 if (bar->dirty_xpos == -1 ||
261 xpos < bar->dirty_xpos) {
264 bar->dirty_xpos = xpos;
273 /* right-aligned items - first copy them to a new list backwards,
274 easier to draw them in right order */
276 for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
277 SBAR_ITEM_REC *rec = tmp->data;
279 if (rec->config->right_alignment) {
281 right_items = g_slist_prepend(right_items, rec);
282 else if (rec->current_size > 0) {
283 /* item was hidden - set the dirty position
284 to begin from the item's old xpos */
287 bar->dirty_xpos = rec->xpos;
293 for (tmp = right_items; tmp != NULL; tmp = tmp->next) {
294 SBAR_ITEM_REC *rec = tmp->data;
297 if (SBAR_ITEM_REDRAW_NEEDED(bar, rec, rxpos)) {
299 if (bar->dirty_xpos == -1 ||
300 rxpos < bar->dirty_xpos) {
303 bar->dirty_xpos = rxpos;
308 g_slist_free(right_items);
310 active_win = old_active_win;
313 void statusbar_redraw(STATUSBAR_REC *bar, int force)
315 if (statusbar_need_recreate_items)
316 return; /* don't bother yet */
324 statusbar_calc_item_positions(bar);
325 } else if (active_statusbar_group != NULL) {
326 g_slist_foreach(active_statusbar_group->bars,
327 (GFunc) statusbar_redraw,
328 GINT_TO_POINTER(force));
332 void statusbar_item_redraw(SBAR_ITEM_REC *item)
334 WINDOW_REC *old_active_win;
336 g_return_if_fail(item != NULL);
338 old_active_win = active_win;
339 if (item->bar->parent_window != NULL)
340 active_win = item->bar->parent_window->active;
342 item->func(item, TRUE);
345 item->bar->dirty = TRUE;
348 if (item->max_size != item->size) {
349 /* item wants a new size - we'll need to redraw
350 the statusbar to see if this is allowed */
351 statusbar_redraw(item->bar, FALSE);
354 active_win = old_active_win;
357 void statusbar_items_redraw(const char *name)
359 g_slist_foreach(g_hash_table_lookup(named_sbar_items, name),
360 (GFunc) statusbar_item_redraw, NULL);
363 static void statusbars_recalc_ypos(STATUSBAR_REC *bar)
365 GSList *tmp, *bar_group;
368 /* get list of statusbars with same type and placement,
369 sorted by position */
371 tmp = bar->config->type == STATUSBAR_TYPE_ROOT ? bar->group->bars :
372 bar->parent_window->statusbars;
374 for (; tmp != NULL; tmp = tmp->next) {
375 STATUSBAR_REC *rec = tmp->data;
377 if (rec->config->type == bar->config->type &&
378 rec->config->placement == bar->config->placement) {
379 bar_group = g_slist_insert_sorted(bar_group, rec,
385 if (bar_group == NULL) {
386 /* we just destroyed the last statusbar in this
387 type/placement group */
391 /* get the Y-position for the first statusbar */
392 if (bar->config->type == STATUSBAR_TYPE_ROOT) {
393 ypos = bar->config->placement == STATUSBAR_TOP ? 0 :
394 term_height - g_slist_length(bar_group);
396 ypos = bar->config->placement == STATUSBAR_TOP ?
397 bar->parent_window->first_line :
398 bar->parent_window->last_line -
399 (g_slist_length(bar_group)-1);
402 /* set the Y-positions */
403 while (bar_group != NULL) {
404 bar = bar_group->data;
406 if (bar->real_ypos != ypos) {
407 bar->real_ypos = ypos;
408 statusbar_redraw(bar, TRUE);
412 bar_group = g_slist_remove(bar_group, bar_group->data);
416 static void sig_terminal_resized(void)
420 for (tmp = active_statusbar_group->bars; tmp != NULL; tmp = tmp->next) {
421 STATUSBAR_REC *bar = tmp->data;
423 if (bar->config->type == STATUSBAR_TYPE_ROOT &&
424 bar->config->placement == STATUSBAR_BOTTOM) {
425 statusbars_recalc_ypos(bar);
431 static void mainwindow_recalc_ypos(MAIN_WINDOW_REC *window, int placement)
435 for (tmp = window->statusbars; tmp != NULL; tmp = tmp->next) {
436 STATUSBAR_REC *bar = tmp->data;
438 if (bar->config->placement == placement) {
439 statusbars_recalc_ypos(bar);
445 static void sig_mainwindow_resized(MAIN_WINDOW_REC *window)
447 mainwindow_recalc_ypos(window, STATUSBAR_TOP);
448 mainwindow_recalc_ypos(window, STATUSBAR_BOTTOM);
451 STATUSBAR_REC *statusbar_create(STATUSBAR_GROUP_REC *group,
452 STATUSBAR_CONFIG_REC *config,
453 MAIN_WINDOW_REC *parent_window)
460 g_return_val_if_fail(group != NULL, NULL);
461 g_return_val_if_fail(config != NULL, NULL);
462 g_return_val_if_fail(config->type != STATUSBAR_TYPE_WINDOW ||
463 parent_window != NULL, NULL);
465 bar = g_new0(STATUSBAR_REC, 1);
466 group->bars = g_slist_append(group->bars, bar);
470 bar->config = config;
471 bar->parent_window = parent_window;
477 signal_remove("terminal resized", (SIGNAL_FUNC) sig_terminal_resized);
478 signal_remove("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized);
479 signal_remove("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized);
481 if (config->type == STATUSBAR_TYPE_ROOT) {
482 /* top/bottom of the screen */
483 mainwindows_reserve_lines(config->placement == STATUSBAR_TOP,
484 config->placement == STATUSBAR_BOTTOM);
485 theme = current_theme;
487 /* top/bottom of the window */
488 parent_window->statusbars =
489 g_slist_append(parent_window->statusbars, bar);
490 mainwindow_set_statusbar_lines(parent_window,
491 config->placement == STATUSBAR_TOP,
492 config->placement == STATUSBAR_BOTTOM);
493 theme = parent_window != NULL && parent_window->active != NULL &&
494 parent_window->active->theme != NULL ?
495 parent_window->active->theme : current_theme;
498 signal_add("terminal resized", (SIGNAL_FUNC) sig_terminal_resized);
499 signal_add("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized);
500 signal_add("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized);
502 /* get background color from sb_background abstract */
503 name = g_strdup_printf("{sb_%s_bg}", config->name);
504 value = theme_format_expand(theme, name);
507 if (*value == '\0') {
508 /* try with the statusbar group name */
511 name = g_strdup_printf("{sb_%s_bg}", group->name);
512 value = theme_format_expand(theme, name);
515 if (*value == '\0') {
516 /* fallback to default statusbar background
517 (also provides backwards compatibility..) */
519 value = theme_format_expand(theme, "{sb_background}");
523 if (*value == '\0') {
525 value = g_strdup("%8");
527 bar->color = g_strconcat("%n", value, NULL);
530 statusbars_recalc_ypos(bar);
531 signal_emit("statusbar created", 1, bar);
533 /* create the items to statusbar */
534 for (tmp = config->items; tmp != NULL; tmp = tmp->next) {
535 SBAR_ITEM_CONFIG_REC *rec = tmp->data;
537 statusbar_item_create(bar, rec);
542 void statusbar_destroy(STATUSBAR_REC *bar)
546 g_return_if_fail(bar != NULL);
548 bar->group->bars = g_slist_remove(bar->group->bars, bar);
549 if (bar->parent_window != NULL) {
550 bar->parent_window->statusbars =
551 g_slist_remove(bar->parent_window->statusbars, bar);
554 signal_emit("statusbar destroyed", 1, bar);
556 while (bar->items != NULL)
557 statusbar_item_destroy(bar->items->data);
561 if (bar->config->type != STATUSBAR_TYPE_WINDOW ||
562 bar->parent_window != NULL)
563 statusbars_recalc_ypos(bar);
565 top = bar->config->placement == STATUSBAR_TOP;
566 if (bar->config->type == STATUSBAR_TYPE_ROOT) {
567 /* top/bottom of the screen */
568 mainwindows_reserve_lines(top ? -1 : 0, !top ? -1 : 0);
569 } else if (bar->parent_window != NULL) {
570 /* top/bottom of the window */
571 mainwindow_set_statusbar_lines(bar->parent_window,
572 top ? -1 : 0, !top ? -1 : 0);
578 void statusbar_recreate_items(STATUSBAR_REC *bar)
583 while (bar->items != NULL)
584 statusbar_item_destroy(bar->items->data);
587 for (tmp = bar->config->items; tmp != NULL; tmp = tmp->next) {
588 SBAR_ITEM_CONFIG_REC *rec = tmp->data;
590 statusbar_item_create(bar, rec);
593 statusbar_redraw(bar, TRUE);
596 void statusbars_recreate_items(void)
598 if (active_statusbar_group != NULL) {
599 g_slist_foreach(active_statusbar_group->bars,
600 (GFunc) statusbar_recreate_items, NULL);
604 STATUSBAR_REC *statusbar_find(STATUSBAR_GROUP_REC *group, const char *name,
605 MAIN_WINDOW_REC *window)
609 for (tmp = group->bars; tmp != NULL; tmp = tmp->next) {
610 STATUSBAR_REC *rec = tmp->data;
612 if (rec->parent_window == window &&
613 strcmp(rec->config->name, name) == 0)
620 static char *update_statusbar_bg(const char *str, const char *color)
625 out = g_string_new(color);
626 while (*str != '\0') {
627 if (*str == '%' && str[1] == 'n') {
628 g_string_append(out, color);
633 g_string_append_c(out, *str);
638 g_string_free(out, FALSE);
642 const char *statusbar_item_get_value(SBAR_ITEM_REC *item)
646 value = item->config->value;
648 value = g_hash_table_lookup(sbar_item_defs,
655 void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
656 const char *str, const char *data,
661 char *tmpstr, *tmpstr2;
665 str = statusbar_item_get_value(item);
666 if (str == NULL || *str == '\0') {
667 item->min_size = item->max_size = 0;
671 if (active_win == NULL) {
675 server = active_win->active_server;
676 wiitem = active_win->active;
679 /* expand templates */
680 tmpstr = theme_format_expand_data(current_theme, &str,
684 EXPAND_FLAG_IGNORE_REPLACES |
685 EXPAND_FLAG_IGNORE_EMPTY);
686 /* expand $variables */
687 tmpstr2 = parse_special_string(tmpstr, server, wiitem, data, NULL,
688 (escape_vars ? PARSE_FLAG_ESCAPE_VARS : 0 ));
691 /* remove color codes (not %formats) */
692 tmpstr = strip_codes(tmpstr2);
696 item->min_size = item->max_size = format_get_length(tmpstr);
698 if (item->size < item->min_size) {
699 /* they're forcing us smaller than minimum size.. */
700 len = format_real_length(tmpstr, item->size);
704 tmpstr2 = update_statusbar_bg(tmpstr, item->bar->color);
705 gui_printtext(item->xpos, item->bar->real_ypos, tmpstr2);
711 static void statusbar_item_default_func(SBAR_ITEM_REC *item, int get_size_only)
713 statusbar_item_default_handler(item, get_size_only, NULL, "", TRUE);
716 static void statusbar_update_item(void)
720 items = g_hash_table_lookup(sbar_signal_items,
721 GINT_TO_POINTER(signal_get_emitted_id()));
722 while (items != NULL) {
723 SBAR_ITEM_REC *item = items->data;
725 statusbar_item_redraw(item);
730 static void statusbar_update_server(SERVER_REC *server)
732 SERVER_REC *item_server;
735 items = g_hash_table_lookup(sbar_signal_items,
736 GINT_TO_POINTER(signal_get_emitted_id()));
737 while (items != NULL) {
738 SBAR_ITEM_REC *item = items->data;
740 item_server = item->bar->parent_window != NULL ?
741 item->bar->parent_window->active->active_server :
742 active_win->active_server;
744 if (item_server == server)
745 statusbar_item_redraw(item);
751 static void statusbar_update_window(WINDOW_REC *window)
753 WINDOW_REC *item_window;
756 items = g_hash_table_lookup(sbar_signal_items,
757 GINT_TO_POINTER(signal_get_emitted_id()));
758 while (items != NULL) {
759 SBAR_ITEM_REC *item = items->data;
761 item_window = item->bar->parent_window != NULL ?
762 item->bar->parent_window->active : active_win;
764 if (item_window == window)
765 statusbar_item_redraw(item);
771 static void statusbar_update_window_item(WI_ITEM_REC *wiitem)
773 WI_ITEM_REC *item_wi;
776 items = g_hash_table_lookup(sbar_signal_items,
777 GINT_TO_POINTER(signal_get_emitted_id()));
778 while (items != NULL) {
779 SBAR_ITEM_REC *item = items->data;
781 item_wi = item->bar->parent_window != NULL ?
782 item->bar->parent_window->active->active :
785 if (item_wi == wiitem)
786 statusbar_item_redraw(item);
792 static void statusbar_item_default_signals(SBAR_ITEM_REC *item)
800 value = statusbar_item_get_value(item);
804 signals = special_vars_get_signals(value);
808 for (pos = signals; *pos != -1; pos += 2) {
809 /* update signal -> item mappings */
810 signal_id = GINT_TO_POINTER(*pos);
811 list = g_hash_table_lookup(sbar_signal_items, signal_id);
814 case EXPANDO_ARG_NONE:
815 func = (SIGNAL_FUNC) statusbar_update_item;
817 case EXPANDO_ARG_SERVER:
818 func = (SIGNAL_FUNC) statusbar_update_server;
820 case EXPANDO_ARG_WINDOW:
821 func = (SIGNAL_FUNC) statusbar_update_window;
823 case EXPANDO_ARG_WINDOW_ITEM:
824 func = (SIGNAL_FUNC) statusbar_update_window_item;
831 signal_add_to_id(MODULE_NAME, 1, *pos, func);
834 if (g_slist_find(list, item) == NULL)
835 list = g_slist_append(list, item);
836 g_hash_table_insert(sbar_signal_items, signal_id, list);
838 /* update item -> signal mappings */
839 list = g_hash_table_lookup(sbar_item_signals, item);
840 if (g_slist_find(list, signal_id) == NULL)
841 list = g_slist_append(list, signal_id);
842 g_hash_table_insert(sbar_item_signals, item, list);
847 SBAR_ITEM_REC *statusbar_item_create(STATUSBAR_REC *bar,
848 SBAR_ITEM_CONFIG_REC *config)
853 g_return_val_if_fail(bar != NULL, NULL);
854 g_return_val_if_fail(config != NULL, NULL);
856 rec = g_new0(SBAR_ITEM_REC, 1);
857 bar->items = g_slist_append(bar->items, rec);
860 rec->config = config;
862 rec->func = (STATUSBAR_FUNC) g_hash_table_lookup(sbar_item_funcs,
864 if (rec->func == NULL)
865 rec->func = statusbar_item_default_func;
866 statusbar_item_default_signals(rec);
868 items = g_hash_table_lookup(named_sbar_items, config->name);
869 items = g_slist_append(items, rec);
870 g_hash_table_insert(named_sbar_items, config->name, items);
876 signal_emit("statusbar item created", 1, rec);
880 static void statusbar_signal_remove(int signal_id)
882 signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_item);
883 signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_server);
884 signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_window);
885 signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_window_item);
888 static void statusbar_item_remove_signal(SBAR_ITEM_REC *item, int signal_id)
892 /* update signal -> item hash */
893 list = g_hash_table_lookup(sbar_signal_items,
894 GINT_TO_POINTER(signal_id));
895 list = g_slist_remove(list, item);
897 g_hash_table_insert(sbar_signal_items,
898 GINT_TO_POINTER(signal_id), list);
900 g_hash_table_remove(sbar_signal_items,
901 GINT_TO_POINTER(signal_id));
902 statusbar_signal_remove(signal_id);
906 void statusbar_item_destroy(SBAR_ITEM_REC *item)
910 g_return_if_fail(item != NULL);
912 item->bar->items = g_slist_remove(item->bar->items, item);
914 list = g_hash_table_lookup(named_sbar_items, item->config->name);
915 list = g_slist_remove(list, item);
917 g_hash_table_remove(named_sbar_items, item->config->name);
919 g_hash_table_insert(named_sbar_items, item->config->name, list);
921 signal_emit("statusbar item destroyed", 1, item);
923 list = g_hash_table_lookup(sbar_item_signals, item);
924 g_hash_table_remove(sbar_item_signals, item);
926 while (list != NULL) {
927 statusbar_item_remove_signal(item, GPOINTER_TO_INT(list->data));
928 list = g_slist_remove(list, list->data);
934 static void statusbar_redraw_needed_items(STATUSBAR_REC *bar)
936 WINDOW_REC *old_active_win;
940 old_active_win = active_win;
941 if (bar->parent_window != NULL)
942 active_win = bar->parent_window->active;
944 if (bar->dirty_xpos >= 0) {
945 str = g_strconcat(bar->color, "%>", NULL);
946 gui_printtext(bar->dirty_xpos, bar->real_ypos, str);
950 for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
951 SBAR_ITEM_REC *rec = tmp->data;
954 (bar->dirty_xpos != -1 &&
955 rec->xpos >= bar->dirty_xpos)) {
956 rec->current_size = rec->size;
957 rec->func(rec, FALSE);
962 active_win = old_active_win;
965 void statusbar_redraw_dirty(void)
969 if (statusbar_need_recreate_items) {
970 statusbar_need_recreate_items = FALSE;
971 statusbars_recreate_items();
974 for (tmp = active_statusbar_group->bars; tmp != NULL; tmp = tmp->next) {
975 STATUSBAR_REC *rec = tmp->data;
978 statusbar_redraw_needed_items(rec);
980 rec->dirty_xpos = -1;
985 #define STATUSBAR_IS_VISIBLE(bar, window) \
986 ((bar)->visible == STATUSBAR_VISIBLE_ALWAYS || \
987 (active_mainwin == (window) && \
988 (bar)->visible == STATUSBAR_VISIBLE_ACTIVE) || \
989 (active_mainwin != (window) && \
990 (bar)->visible == STATUSBAR_VISIBLE_INACTIVE))
992 static void statusbars_remove_unvisible(MAIN_WINDOW_REC *window)
996 for (tmp = window->statusbars; tmp != NULL; tmp = next) {
997 STATUSBAR_REC *bar = tmp->data;
1000 if (!STATUSBAR_IS_VISIBLE(bar->config, window))
1001 statusbar_destroy(bar);
1005 static void statusbars_add_visible(MAIN_WINDOW_REC *window)
1007 STATUSBAR_GROUP_REC *group;
1011 group = active_statusbar_group;
1012 for (tmp = group->config_bars; tmp != NULL; tmp = tmp->next) {
1013 STATUSBAR_CONFIG_REC *config = tmp->data;
1015 if (config->type == STATUSBAR_TYPE_WINDOW &&
1016 STATUSBAR_IS_VISIBLE(config, window) &&
1017 statusbar_find(group, config->name, window) == NULL) {
1018 bar = statusbar_create(group, config, window);
1019 statusbar_redraw(bar, TRUE);
1024 static void sig_mainwindow_destroyed(MAIN_WINDOW_REC *window)
1026 while (window->statusbars != NULL) {
1027 STATUSBAR_REC *bar = window->statusbars->data;
1029 bar->parent_window->statusbars =
1030 g_slist_remove(bar->parent_window->statusbars, bar);
1031 bar->parent_window = NULL;
1032 statusbar_destroy(bar);
1036 static void sig_window_changed(void)
1040 for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) {
1041 MAIN_WINDOW_REC *rec = tmp->data;
1043 statusbars_remove_unvisible(rec);
1044 statusbars_add_visible(rec);
1048 static void sig_gui_window_created(WINDOW_REC *window)
1050 statusbars_add_visible(WINDOW_MAIN(window));
1053 static void statusbar_item_def_destroy(void *key, void *value)
1059 static void statusbar_signal_item_destroy(void *key, GSList *value)
1061 while (value != NULL) {
1062 statusbar_signal_remove(GPOINTER_TO_INT(value->data));
1063 value->data = g_slist_remove(value, value->data);
1067 static void statusbar_item_signal_destroy(void *key, GSList *value)
1069 g_slist_free(value);
1072 static void sig_setup_reload(void)
1074 /* statusbar-config.c recreates root statusbars,
1075 we need to create window-statusbars */
1076 g_slist_foreach(mainwindows, (GFunc) statusbars_add_visible, NULL);
1079 void statusbar_init(void)
1081 statusbar_need_recreate_items = FALSE;
1082 statusbar_groups = NULL;
1083 active_statusbar_group = NULL;
1084 sbar_item_defs = g_hash_table_new((GHashFunc) g_str_hash,
1085 (GCompareFunc) g_str_equal);
1086 sbar_item_funcs = g_hash_table_new((GHashFunc) g_str_hash,
1087 (GCompareFunc) g_str_equal);
1088 sbar_signal_items = g_hash_table_new((GHashFunc) g_direct_hash,
1089 (GCompareFunc) g_direct_equal);
1090 sbar_item_signals = g_hash_table_new((GHashFunc) g_direct_hash,
1091 (GCompareFunc) g_direct_equal);
1092 named_sbar_items = g_hash_table_new((GHashFunc) g_str_hash,
1093 (GCompareFunc) g_str_equal);
1095 signal_add("terminal resized", (SIGNAL_FUNC) sig_terminal_resized);
1096 signal_add("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized);
1097 signal_add("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized);
1098 signal_add("gui window created", (SIGNAL_FUNC) sig_gui_window_created);
1099 signal_add("window changed", (SIGNAL_FUNC) sig_window_changed);
1100 signal_add("mainwindow destroyed", (SIGNAL_FUNC) sig_mainwindow_destroyed);
1101 signal_add_last("setup reread", (SIGNAL_FUNC) sig_setup_reload);
1103 statusbar_items_init();
1104 statusbar_config_init(); /* signals need to be before this call */
1107 void statusbar_deinit(void)
1109 while (statusbar_groups != NULL)
1110 statusbar_group_destroy(statusbar_groups->data);
1112 g_hash_table_foreach(sbar_item_defs,
1113 (GHFunc) statusbar_item_def_destroy, NULL);
1114 g_hash_table_destroy(sbar_item_defs);
1116 g_hash_table_foreach(sbar_item_funcs, (GHFunc) g_free, NULL);
1117 g_hash_table_destroy(sbar_item_funcs);
1119 g_hash_table_foreach(sbar_signal_items,
1120 (GHFunc) statusbar_signal_item_destroy, NULL);
1121 g_hash_table_destroy(sbar_signal_items);
1122 g_hash_table_foreach(sbar_item_signals,
1123 (GHFunc) statusbar_item_signal_destroy, NULL);
1124 g_hash_table_destroy(sbar_item_signals);
1125 g_hash_table_destroy(named_sbar_items);
1127 signal_remove("terminal resized", (SIGNAL_FUNC) sig_terminal_resized);
1128 signal_remove("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized);
1129 signal_remove("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized);
1130 signal_remove("gui window created", (SIGNAL_FUNC) sig_gui_window_created);
1131 signal_remove("window changed", (SIGNAL_FUNC) sig_window_changed);
1132 signal_remove("mainwindow destroyed", (SIGNAL_FUNC) sig_mainwindow_destroyed);
1133 signal_remove("setup reread", (SIGNAL_FUNC) sig_setup_reload);
1135 statusbar_items_deinit();
1136 statusbar_config_deinit();