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 along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 void statusbar_item_set_size(struct SBAR_ITEM_REC *item, int min_size, int max_size)
97 item->min_size = min_size;
98 item->max_size = max_size;
101 STATUSBAR_GROUP_REC *statusbar_group_create(const char *name)
103 STATUSBAR_GROUP_REC *rec;
105 rec = g_new0(STATUSBAR_GROUP_REC, 1);
106 rec->name = g_strdup(name);
108 statusbar_groups = g_slist_append(statusbar_groups, rec);
112 void statusbar_group_destroy(STATUSBAR_GROUP_REC *rec)
114 statusbar_groups = g_slist_remove(statusbar_groups, rec);
116 while (rec->bars != NULL)
117 statusbar_destroy(rec->bars->data);
118 while (rec->config_bars != NULL)
119 statusbar_config_destroy(rec, rec->config_bars->data);
125 STATUSBAR_GROUP_REC *statusbar_group_find(const char *name)
129 for (tmp = statusbar_groups; tmp != NULL; tmp = tmp->next) {
130 STATUSBAR_GROUP_REC *rec = tmp->data;
132 if (strcmp(rec->name, name) == 0)
139 static int sbar_item_cmp(SBAR_ITEM_REC *item1, SBAR_ITEM_REC *item2)
141 return item1->config->priority == item2->config->priority ? 0 :
142 item1->config->priority < item2->config->priority ? -1 : 1;
145 static int sbar_cmp_position(STATUSBAR_REC *bar1, STATUSBAR_REC *bar2)
147 return bar1->config->position < bar2->config->position ? -1 : 1;
150 /* Shink all items in statusbar to their minimum requested size.
151 The items list should be sorted by priority, highest first. */
152 static int statusbar_shrink_to_min(GSList *items, int size, int max_width)
156 for (tmp = items; tmp != NULL; tmp = tmp->next) {
157 SBAR_ITEM_REC *rec = tmp->data;
159 size -= (rec->max_size-rec->min_size);
160 rec->size = rec->min_size;
162 if (size <= max_width) {
163 rec->size += max_width-size;
167 if (rec->size == 0) {
168 /* min_size was 0, item removed.
169 remove the marginal too */
177 /* shink the items in statusbar, even if their size gets smaller than
178 their minimum requested size. The items list should be sorted by
179 priority, highest first. */
180 static void statusbar_shrink_forced(GSList *items, int size, int max_width)
184 for (tmp = items; tmp != NULL; tmp = tmp->next) {
185 SBAR_ITEM_REC *rec = tmp->data;
187 if (size-rec->size > max_width) {
188 /* remove the whole item */
192 /* shrink the item */
193 rec->size -= size-max_width;
199 static void statusbar_resize_items(STATUSBAR_REC *bar, int max_width)
201 GSList *tmp, *prior_sorted;
204 /* first give items their max. size */
207 for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
208 SBAR_ITEM_REC *rec = tmp->data;
210 rec->func(rec, TRUE);
211 rec->size = rec->max_size;
214 width += rec->max_size;
216 prior_sorted = g_slist_insert_sorted(prior_sorted, rec,
222 if (width > max_width) {
223 /* too big, start shrinking from items with lowest priority
224 and shrink until everything fits or until we've shrinked
226 width = statusbar_shrink_to_min(prior_sorted, width,
228 if (width > max_width) {
229 /* still need to shrink, remove the items with lowest
230 priority until everything fits to screen */
231 statusbar_shrink_forced(prior_sorted, width,
236 g_slist_free(prior_sorted);
239 #define SBAR_ITEM_REDRAW_NEEDED(_bar, _item, _xpos) \
240 (((_bar)->dirty_xpos != -1 && (_xpos) >= (_bar)->dirty_xpos) || \
241 (_item)->xpos != (_xpos) || (_item)->current_size != (_item)->size)
243 static void statusbar_calc_item_positions(STATUSBAR_REC *bar)
245 WINDOW_REC *old_active_win;
246 GSList *tmp, *right_items;
249 old_active_win = active_win;
250 if (bar->parent_window != NULL)
251 active_win = bar->parent_window->active;
253 statusbar_resize_items(bar, term_width);
255 /* left-aligned items */
257 for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
258 SBAR_ITEM_REC *rec = tmp->data;
260 if (!rec->config->right_alignment &&
261 (rec->size > 0 || rec->current_size > 0)) {
262 if (SBAR_ITEM_REDRAW_NEEDED(bar, rec, xpos)) {
263 /* redraw the item */
265 if (bar->dirty_xpos == -1 ||
266 xpos < bar->dirty_xpos) {
269 bar->dirty_xpos = xpos;
278 /* right-aligned items - first copy them to a new list backwards,
279 easier to draw them in right order */
281 for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
282 SBAR_ITEM_REC *rec = tmp->data;
284 if (rec->config->right_alignment) {
286 right_items = g_slist_prepend(right_items, rec);
287 else if (rec->current_size > 0 &&
288 (bar->dirty_xpos == -1 ||
289 rec->xpos < bar->dirty_xpos)) {
290 /* item was hidden - set the dirty position
291 to begin from the item's old xpos */
294 bar->dirty_xpos = rec->xpos;
300 for (tmp = right_items; tmp != NULL; tmp = tmp->next) {
301 SBAR_ITEM_REC *rec = tmp->data;
304 if (SBAR_ITEM_REDRAW_NEEDED(bar, rec, rxpos)) {
306 if (bar->dirty_xpos == -1 ||
307 rxpos < bar->dirty_xpos) {
310 bar->dirty_xpos = rxpos;
315 g_slist_free(right_items);
317 active_win = old_active_win;
320 void statusbar_redraw(STATUSBAR_REC *bar, int force)
322 if (statusbar_need_recreate_items)
323 return; /* don't bother yet */
331 statusbar_calc_item_positions(bar);
332 } else if (active_statusbar_group != NULL) {
333 g_slist_foreach(active_statusbar_group->bars,
334 (GFunc) statusbar_redraw,
335 GINT_TO_POINTER(force));
339 void statusbar_item_redraw(SBAR_ITEM_REC *item)
341 WINDOW_REC *old_active_win;
343 g_return_if_fail(item != NULL);
345 old_active_win = active_win;
346 if (item->bar->parent_window != NULL)
347 active_win = item->bar->parent_window->active;
349 item->func(item, TRUE);
352 item->bar->dirty = TRUE;
355 if (item->max_size != item->size) {
356 /* item wants a new size - we'll need to redraw
357 the statusbar to see if this is allowed */
358 statusbar_redraw(item->bar, FALSE);
361 active_win = old_active_win;
364 void statusbar_items_redraw(const char *name)
366 g_slist_foreach(g_hash_table_lookup(named_sbar_items, name),
367 (GFunc) statusbar_item_redraw, NULL);
370 static void statusbars_recalc_ypos(STATUSBAR_REC *bar)
372 GSList *tmp, *bar_group;
375 /* get list of statusbars with same type and placement,
376 sorted by position */
378 tmp = bar->config->type == STATUSBAR_TYPE_ROOT ? bar->group->bars :
379 bar->parent_window->statusbars;
381 for (; tmp != NULL; tmp = tmp->next) {
382 STATUSBAR_REC *rec = tmp->data;
384 if (rec->config->type == bar->config->type &&
385 rec->config->placement == bar->config->placement) {
386 bar_group = g_slist_insert_sorted(bar_group, rec,
392 if (bar_group == NULL) {
393 /* we just destroyed the last statusbar in this
394 type/placement group */
398 /* get the Y-position for the first statusbar */
399 if (bar->config->type == STATUSBAR_TYPE_ROOT) {
400 ypos = bar->config->placement == STATUSBAR_TOP ? 0 :
401 term_height - g_slist_length(bar_group);
403 ypos = bar->config->placement == STATUSBAR_TOP ?
404 bar->parent_window->first_line :
405 bar->parent_window->last_line -
406 (g_slist_length(bar_group)-1);
409 /* set the Y-positions */
410 while (bar_group != NULL) {
411 bar = bar_group->data;
413 if (bar->real_ypos != ypos) {
414 bar->real_ypos = ypos;
415 statusbar_redraw(bar, TRUE);
419 bar_group = g_slist_remove(bar_group, bar_group->data);
423 static void sig_terminal_resized(void)
427 for (tmp = active_statusbar_group->bars; tmp != NULL; tmp = tmp->next) {
428 STATUSBAR_REC *bar = tmp->data;
430 if (bar->config->type == STATUSBAR_TYPE_ROOT &&
431 bar->config->placement == STATUSBAR_BOTTOM) {
432 statusbars_recalc_ypos(bar);
438 static void mainwindow_recalc_ypos(MAIN_WINDOW_REC *window, int placement)
442 for (tmp = window->statusbars; tmp != NULL; tmp = tmp->next) {
443 STATUSBAR_REC *bar = tmp->data;
445 if (bar->config->placement == placement) {
446 statusbars_recalc_ypos(bar);
452 static void sig_mainwindow_resized(MAIN_WINDOW_REC *window)
454 mainwindow_recalc_ypos(window, STATUSBAR_TOP);
455 mainwindow_recalc_ypos(window, STATUSBAR_BOTTOM);
458 STATUSBAR_REC *statusbar_create(STATUSBAR_GROUP_REC *group,
459 STATUSBAR_CONFIG_REC *config,
460 MAIN_WINDOW_REC *parent_window)
467 g_return_val_if_fail(group != NULL, NULL);
468 g_return_val_if_fail(config != NULL, NULL);
469 g_return_val_if_fail(config->type != STATUSBAR_TYPE_WINDOW ||
470 parent_window != NULL, NULL);
472 bar = g_new0(STATUSBAR_REC, 1);
473 group->bars = g_slist_append(group->bars, bar);
477 bar->config = config;
478 bar->parent_window = parent_window;
484 signal_remove("terminal resized", (SIGNAL_FUNC) sig_terminal_resized);
485 signal_remove("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized);
486 signal_remove("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized);
488 if (config->type == STATUSBAR_TYPE_ROOT) {
489 /* top/bottom of the screen */
490 mainwindows_reserve_lines(config->placement == STATUSBAR_TOP,
491 config->placement == STATUSBAR_BOTTOM);
492 theme = current_theme;
494 /* top/bottom of the window */
495 parent_window->statusbars =
496 g_slist_append(parent_window->statusbars, bar);
497 mainwindow_set_statusbar_lines(parent_window,
498 config->placement == STATUSBAR_TOP,
499 config->placement == STATUSBAR_BOTTOM);
500 theme = parent_window != NULL && parent_window->active != NULL &&
501 parent_window->active->theme != NULL ?
502 parent_window->active->theme : current_theme;
505 signal_add("terminal resized", (SIGNAL_FUNC) sig_terminal_resized);
506 signal_add("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized);
507 signal_add("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized);
509 /* get background color from sb_background abstract */
510 name = g_strdup_printf("{sb_%s_bg}", config->name);
511 value = theme_format_expand(theme, name);
514 if (*value == '\0') {
515 /* try with the statusbar group name */
518 name = g_strdup_printf("{sb_%s_bg}", group->name);
519 value = theme_format_expand(theme, name);
522 if (*value == '\0') {
523 /* fallback to default statusbar background
524 (also provides backwards compatibility..) */
526 value = theme_format_expand(theme, "{sb_background}");
530 if (*value == '\0') {
532 value = g_strdup("%8");
534 bar->color = g_strconcat("%n", value, NULL);
537 statusbars_recalc_ypos(bar);
538 signal_emit("statusbar created", 1, bar);
540 /* create the items to statusbar */
541 for (tmp = config->items; tmp != NULL; tmp = tmp->next) {
542 SBAR_ITEM_CONFIG_REC *rec = tmp->data;
544 statusbar_item_create(bar, rec);
549 void statusbar_destroy(STATUSBAR_REC *bar)
553 g_return_if_fail(bar != NULL);
555 bar->group->bars = g_slist_remove(bar->group->bars, bar);
556 if (bar->parent_window != NULL) {
557 bar->parent_window->statusbars =
558 g_slist_remove(bar->parent_window->statusbars, bar);
561 signal_emit("statusbar destroyed", 1, bar);
563 while (bar->items != NULL)
564 statusbar_item_destroy(bar->items->data);
568 if (bar->config->type != STATUSBAR_TYPE_WINDOW ||
569 bar->parent_window != NULL)
570 statusbars_recalc_ypos(bar);
572 top = bar->config->placement == STATUSBAR_TOP;
573 if (bar->config->type == STATUSBAR_TYPE_ROOT) {
574 /* top/bottom of the screen */
575 mainwindows_reserve_lines(top ? -1 : 0, !top ? -1 : 0);
576 } else if (bar->parent_window != NULL) {
577 /* top/bottom of the window */
578 mainwindow_set_statusbar_lines(bar->parent_window,
579 top ? -1 : 0, !top ? -1 : 0);
585 void statusbar_recreate_items(STATUSBAR_REC *bar)
590 while (bar->items != NULL)
591 statusbar_item_destroy(bar->items->data);
594 for (tmp = bar->config->items; tmp != NULL; tmp = tmp->next) {
595 SBAR_ITEM_CONFIG_REC *rec = tmp->data;
597 statusbar_item_create(bar, rec);
600 statusbar_redraw(bar, TRUE);
603 void statusbars_recreate_items(void)
605 if (active_statusbar_group != NULL) {
606 g_slist_foreach(active_statusbar_group->bars,
607 (GFunc) statusbar_recreate_items, NULL);
611 STATUSBAR_REC *statusbar_find(STATUSBAR_GROUP_REC *group, const char *name,
612 MAIN_WINDOW_REC *window)
616 for (tmp = group->bars; tmp != NULL; tmp = tmp->next) {
617 STATUSBAR_REC *rec = tmp->data;
619 if (rec->parent_window == window &&
620 strcmp(rec->config->name, name) == 0)
627 static const char *statusbar_item_get_value(SBAR_ITEM_REC *item)
631 value = item->config->value;
633 value = g_hash_table_lookup(sbar_item_defs,
640 static GString *finalize_string(const char *str, const char *color)
644 out = g_string_new(color);
646 while (*str != '\0') {
647 if ((unsigned char) *str < 32 ||
648 (term_type == TERM_TYPE_8BIT &&
649 (unsigned char) (*str & 0x7f) < 32)) {
651 g_string_append_printf(out, "%%8%c%%8",
652 'A'-1 + (*str & 0x7f));
653 } else if (*str == '%' && str[1] == 'n') {
654 g_string_append(out, color);
657 g_string_append_c(out, *str);
666 void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
667 const char *str, const char *data,
672 char *tmpstr, *tmpstr2;
676 str = statusbar_item_get_value(item);
677 if (str == NULL || *str == '\0') {
678 item->min_size = item->max_size = 0;
682 if (active_win == NULL) {
686 server = active_win->active_server != NULL ?
687 active_win->active_server : active_win->connect_server;
688 wiitem = active_win->active;
691 /* expand templates */
692 tmpstr = theme_format_expand_data(current_theme, &str,
696 EXPAND_FLAG_IGNORE_REPLACES |
697 EXPAND_FLAG_IGNORE_EMPTY);
698 /* expand $variables */
699 tmpstr2 = parse_special_string(tmpstr, server, wiitem, data, NULL,
700 (escape_vars ? PARSE_FLAG_ESCAPE_VARS : 0 ));
703 /* remove color codes (not %formats) */
704 tmpstr = strip_codes(tmpstr2);
708 item->min_size = item->max_size = format_get_length(tmpstr);
712 if (item->size < item->min_size) {
713 /* they're forcing us smaller than minimum size.. */
714 len = format_real_length(tmpstr, item->size);
717 out = finalize_string(tmpstr, item->bar->color);
718 /* make sure the str is big enough to fill the
719 requested size, so it won't corrupt screen */
720 len = format_get_length(tmpstr);
721 if (len < item->size) {
724 len = item->size-len;
725 for (i = 0; i < len; i++)
726 g_string_append_c(out, ' ');
729 gui_printtext(item->xpos, item->bar->real_ypos, out->str);
730 g_string_free(out, TRUE);
735 static void statusbar_item_default_func(SBAR_ITEM_REC *item, int get_size_only)
737 statusbar_item_default_handler(item, get_size_only, NULL, "", TRUE);
740 static void statusbar_update_item(void)
744 items = g_hash_table_lookup(sbar_signal_items,
745 GINT_TO_POINTER(signal_get_emitted_id()));
746 while (items != NULL) {
747 SBAR_ITEM_REC *item = items->data;
749 statusbar_item_redraw(item);
754 static void statusbar_update_server(SERVER_REC *server)
756 SERVER_REC *item_server;
759 items = g_hash_table_lookup(sbar_signal_items,
760 GINT_TO_POINTER(signal_get_emitted_id()));
761 while (items != NULL) {
762 SBAR_ITEM_REC *item = items->data;
764 item_server = item->bar->parent_window != NULL ?
765 item->bar->parent_window->active->active_server :
766 active_win->active_server;
768 if (item_server == server)
769 statusbar_item_redraw(item);
775 static void statusbar_update_window(WINDOW_REC *window)
777 WINDOW_REC *item_window;
780 items = g_hash_table_lookup(sbar_signal_items,
781 GINT_TO_POINTER(signal_get_emitted_id()));
782 while (items != NULL) {
783 SBAR_ITEM_REC *item = items->data;
785 item_window = item->bar->parent_window != NULL ?
786 item->bar->parent_window->active : active_win;
788 if (item_window == window)
789 statusbar_item_redraw(item);
795 static void statusbar_update_window_item(WI_ITEM_REC *wiitem)
797 WI_ITEM_REC *item_wi;
800 items = g_hash_table_lookup(sbar_signal_items,
801 GINT_TO_POINTER(signal_get_emitted_id()));
802 while (items != NULL) {
803 SBAR_ITEM_REC *item = items->data;
805 item_wi = item->bar->parent_window != NULL ?
806 item->bar->parent_window->active->active :
809 if (item_wi == wiitem)
810 statusbar_item_redraw(item);
816 static void statusbar_item_default_signals(SBAR_ITEM_REC *item)
824 value = statusbar_item_get_value(item);
828 signals = special_vars_get_signals(value);
832 for (pos = signals; *pos != -1; pos += 2) {
833 /* update signal -> item mappings */
834 signal_id = GINT_TO_POINTER(*pos);
835 list = g_hash_table_lookup(sbar_signal_items, signal_id);
838 case EXPANDO_ARG_NONE:
839 func = (SIGNAL_FUNC) statusbar_update_item;
841 case EXPANDO_ARG_SERVER:
842 func = (SIGNAL_FUNC) statusbar_update_server;
844 case EXPANDO_ARG_WINDOW:
845 func = (SIGNAL_FUNC) statusbar_update_window;
847 case EXPANDO_ARG_WINDOW_ITEM:
848 func = (SIGNAL_FUNC) statusbar_update_window_item;
855 signal_add_full_id(MODULE_NAME,
856 SIGNAL_PRIORITY_DEFAULT,
861 if (g_slist_find(list, item) == NULL)
862 list = g_slist_append(list, item);
863 g_hash_table_insert(sbar_signal_items, signal_id, list);
865 /* update item -> signal mappings */
866 list = g_hash_table_lookup(sbar_item_signals, item);
867 if (g_slist_find(list, signal_id) == NULL)
868 list = g_slist_append(list, signal_id);
869 g_hash_table_insert(sbar_item_signals, item, list);
874 SBAR_ITEM_REC *statusbar_item_create(STATUSBAR_REC *bar,
875 SBAR_ITEM_CONFIG_REC *config)
880 g_return_val_if_fail(bar != NULL, NULL);
881 g_return_val_if_fail(config != NULL, NULL);
883 rec = g_new0(SBAR_ITEM_REC, 1);
884 bar->items = g_slist_append(bar->items, rec);
887 rec->config = config;
889 rec->func = (STATUSBAR_FUNC) g_hash_table_lookup(sbar_item_funcs,
891 if (rec->func == NULL)
892 rec->func = statusbar_item_default_func;
893 statusbar_item_default_signals(rec);
895 items = g_hash_table_lookup(named_sbar_items, config->name);
896 items = g_slist_append(items, rec);
897 g_hash_table_insert(named_sbar_items, config->name, items);
903 signal_emit("statusbar item created", 1, rec);
907 static void statusbar_signal_remove(int signal_id)
909 signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_item, NULL);
910 signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_server, NULL);
911 signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_window, NULL);
912 signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_window_item, NULL);
915 static void statusbar_item_remove_signal(SBAR_ITEM_REC *item, int signal_id)
919 /* update signal -> item hash */
920 list = g_hash_table_lookup(sbar_signal_items,
921 GINT_TO_POINTER(signal_id));
922 list = g_slist_remove(list, item);
924 g_hash_table_insert(sbar_signal_items,
925 GINT_TO_POINTER(signal_id), list);
927 g_hash_table_remove(sbar_signal_items,
928 GINT_TO_POINTER(signal_id));
929 statusbar_signal_remove(signal_id);
933 void statusbar_item_destroy(SBAR_ITEM_REC *item)
937 g_return_if_fail(item != NULL);
939 item->bar->items = g_slist_remove(item->bar->items, item);
941 list = g_hash_table_lookup(named_sbar_items, item->config->name);
942 list = g_slist_remove(list, item);
944 g_hash_table_remove(named_sbar_items, item->config->name);
946 g_hash_table_insert(named_sbar_items, item->config->name, list);
948 signal_emit("statusbar item destroyed", 1, item);
950 list = g_hash_table_lookup(sbar_item_signals, item);
951 g_hash_table_remove(sbar_item_signals, item);
953 while (list != NULL) {
954 statusbar_item_remove_signal(item, GPOINTER_TO_INT(list->data));
955 list = g_slist_remove(list, list->data);
961 static void statusbar_redraw_needed_items(STATUSBAR_REC *bar)
963 WINDOW_REC *old_active_win;
967 old_active_win = active_win;
968 if (bar->parent_window != NULL)
969 active_win = bar->parent_window->active;
971 if (bar->dirty_xpos >= 0) {
972 str = g_strconcat(bar->color, "%>", NULL);
973 gui_printtext(bar->dirty_xpos, bar->real_ypos, str);
977 for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
978 SBAR_ITEM_REC *rec = tmp->data;
981 (bar->dirty_xpos != -1 &&
982 rec->xpos >= bar->dirty_xpos)) {
983 rec->current_size = rec->size;
984 rec->func(rec, FALSE);
989 active_win = old_active_win;
992 void statusbar_redraw_dirty(void)
996 if (statusbar_need_recreate_items) {
997 statusbar_need_recreate_items = FALSE;
998 statusbars_recreate_items();
1001 for (tmp = active_statusbar_group->bars; tmp != NULL; tmp = tmp->next) {
1002 STATUSBAR_REC *rec = tmp->data;
1005 statusbar_redraw_needed_items(rec);
1007 rec->dirty_xpos = -1;
1012 #define STATUSBAR_IS_VISIBLE(bar, window) \
1013 ((bar)->visible == STATUSBAR_VISIBLE_ALWAYS || \
1014 (active_mainwin == (window) && \
1015 (bar)->visible == STATUSBAR_VISIBLE_ACTIVE) || \
1016 (active_mainwin != (window) && \
1017 (bar)->visible == STATUSBAR_VISIBLE_INACTIVE))
1019 static void statusbars_remove_unvisible(MAIN_WINDOW_REC *window)
1023 for (tmp = window->statusbars; tmp != NULL; tmp = next) {
1024 STATUSBAR_REC *bar = tmp->data;
1027 if (!STATUSBAR_IS_VISIBLE(bar->config, window))
1028 statusbar_destroy(bar);
1032 static void statusbars_add_visible(MAIN_WINDOW_REC *window)
1034 STATUSBAR_GROUP_REC *group;
1038 group = active_statusbar_group;
1039 for (tmp = group->config_bars; tmp != NULL; tmp = tmp->next) {
1040 STATUSBAR_CONFIG_REC *config = tmp->data;
1042 if (config->type == STATUSBAR_TYPE_WINDOW &&
1043 STATUSBAR_IS_VISIBLE(config, window) &&
1044 statusbar_find(group, config->name, window) == NULL) {
1045 bar = statusbar_create(group, config, window);
1046 statusbar_redraw(bar, TRUE);
1051 static void sig_mainwindow_destroyed(MAIN_WINDOW_REC *window)
1053 while (window->statusbars != NULL) {
1054 STATUSBAR_REC *bar = window->statusbars->data;
1056 bar->parent_window->statusbars =
1057 g_slist_remove(bar->parent_window->statusbars, bar);
1058 bar->parent_window = NULL;
1059 statusbar_destroy(bar);
1063 static void sig_window_changed(void)
1067 for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) {
1068 MAIN_WINDOW_REC *rec = tmp->data;
1070 statusbars_remove_unvisible(rec);
1071 statusbars_add_visible(rec);
1075 static void sig_gui_window_created(WINDOW_REC *window)
1077 statusbars_add_visible(WINDOW_MAIN(window));
1080 static void statusbar_item_def_destroy(void *key, void *value)
1086 static void statusbar_signal_item_destroy(void *key, GSList *value)
1088 while (value != NULL) {
1089 statusbar_signal_remove(GPOINTER_TO_INT(value->data));
1090 value->data = g_slist_remove(value, value->data);
1094 static void statusbar_item_signal_destroy(void *key, GSList *value)
1096 g_slist_free(value);
1099 void statusbars_create_window_bars(void)
1101 g_slist_foreach(mainwindows, (GFunc) statusbars_add_visible, NULL);
1104 void statusbar_init(void)
1106 statusbar_need_recreate_items = FALSE;
1107 statusbar_groups = NULL;
1108 active_statusbar_group = NULL;
1109 sbar_item_defs = g_hash_table_new((GHashFunc) g_str_hash,
1110 (GCompareFunc) g_str_equal);
1111 sbar_item_funcs = g_hash_table_new((GHashFunc) g_str_hash,
1112 (GCompareFunc) g_str_equal);
1113 sbar_signal_items = g_hash_table_new((GHashFunc) g_direct_hash,
1114 (GCompareFunc) g_direct_equal);
1115 sbar_item_signals = g_hash_table_new((GHashFunc) g_direct_hash,
1116 (GCompareFunc) g_direct_equal);
1117 named_sbar_items = g_hash_table_new((GHashFunc) g_str_hash,
1118 (GCompareFunc) g_str_equal);
1120 signal_add("terminal resized", (SIGNAL_FUNC) sig_terminal_resized);
1121 signal_add("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized);
1122 signal_add("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized);
1123 signal_add("gui window created", (SIGNAL_FUNC) sig_gui_window_created);
1124 signal_add("window changed", (SIGNAL_FUNC) sig_window_changed);
1125 signal_add("mainwindow destroyed", (SIGNAL_FUNC) sig_mainwindow_destroyed);
1127 statusbar_items_init();
1128 statusbar_config_init(); /* signals need to be before this call */
1131 void statusbar_deinit(void)
1133 while (statusbar_groups != NULL)
1134 statusbar_group_destroy(statusbar_groups->data);
1136 g_hash_table_foreach(sbar_item_defs,
1137 (GHFunc) statusbar_item_def_destroy, NULL);
1138 g_hash_table_destroy(sbar_item_defs);
1140 g_hash_table_foreach(sbar_item_funcs, (GHFunc) g_free, NULL);
1141 g_hash_table_destroy(sbar_item_funcs);
1143 g_hash_table_foreach(sbar_signal_items,
1144 (GHFunc) statusbar_signal_item_destroy, NULL);
1145 g_hash_table_destroy(sbar_signal_items);
1146 g_hash_table_foreach(sbar_item_signals,
1147 (GHFunc) statusbar_item_signal_destroy, NULL);
1148 g_hash_table_destroy(sbar_item_signals);
1149 g_hash_table_destroy(named_sbar_items);
1151 signal_remove("terminal resized", (SIGNAL_FUNC) sig_terminal_resized);
1152 signal_remove("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized);
1153 signal_remove("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized);
1154 signal_remove("gui window created", (SIGNAL_FUNC) sig_gui_window_created);
1155 signal_remove("window changed", (SIGNAL_FUNC) sig_window_changed);
1156 signal_remove("mainwindow destroyed", (SIGNAL_FUNC) sig_mainwindow_destroyed);
1158 statusbar_items_deinit();
1159 statusbar_config_deinit();