diff options
Diffstat (limited to 'src/fe-text')
-rw-r--r-- | src/fe-text/Makefile.am | 5 | ||||
-rw-r--r-- | src/fe-text/gui-entry.c | 367 | ||||
-rw-r--r-- | src/fe-text/gui-entry.h | 49 | ||||
-rw-r--r-- | src/fe-text/gui-expandos.c | 2 | ||||
-rw-r--r-- | src/fe-text/gui-printtext.c | 14 | ||||
-rw-r--r-- | src/fe-text/gui-readline.c | 112 | ||||
-rw-r--r-- | src/fe-text/gui-windows.c | 98 | ||||
-rw-r--r-- | src/fe-text/gui-windows.h | 2 | ||||
-rw-r--r-- | src/fe-text/irssi.c | 4 | ||||
-rw-r--r-- | src/fe-text/mainwindows.c | 117 | ||||
-rw-r--r-- | src/fe-text/mainwindows.h | 19 | ||||
-rw-r--r-- | src/fe-text/screen.c | 74 | ||||
-rw-r--r-- | src/fe-text/statusbar-config.c | 263 | ||||
-rw-r--r-- | src/fe-text/statusbar-config.h | 12 | ||||
-rw-r--r-- | src/fe-text/statusbar-items.c | 683 | ||||
-rw-r--r-- | src/fe-text/statusbar-items.h | 7 | ||||
-rw-r--r-- | src/fe-text/statusbar.c | 819 | ||||
-rw-r--r-- | src/fe-text/statusbar.h | 98 |
18 files changed, 1629 insertions, 1116 deletions
diff --git a/src/fe-text/Makefile.am b/src/fe-text/Makefile.am index ed261a3e..00e0f856 100644 --- a/src/fe-text/Makefile.am +++ b/src/fe-text/Makefile.am @@ -35,6 +35,7 @@ irssi_SOURCES = \ mainwindows-layout.c \ screen.c \ statusbar.c \ + statusbar-config.c \ statusbar-items.c \ textbuffer.c \ textbuffer-commands.c \ @@ -49,8 +50,10 @@ noinst_HEADERS = \ gui-readline.h \ gui-windows.h \ mainwindows.h \ - statusbar.h \ screen.h \ + statusbar.h \ + statusbar-config.h \ + statusbar-items.h \ textbuffer.h \ textbuffer-view.h \ textbuffer-reformat.h \ diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 0cdfa719..84a7cd7a 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -21,43 +21,65 @@ #include "module.h" #include "formats.h" +#include "gui-entry.h" #include "gui-printtext.h" #include "screen.h" -static GString *entry; -static int promptlen, permanent_prompt, pos, scrstart, scrpos; -static int prompt_hidden; -static char *prompt; +GUI_ENTRY_REC *active_entry; -static void entry_screenpos(void) +GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width) { - if (pos-scrstart < screen_width-2-promptlen && pos-scrstart > 0) { - scrpos = pos-scrstart; - return; - } + GUI_ENTRY_REC *rec; + + rec = g_new0(GUI_ENTRY_REC, 1); + rec->xpos = xpos; + rec->ypos = ypos; + rec->width = width; + rec->text = g_string_new(NULL); + return rec; +} + +void gui_entry_destroy(GUI_ENTRY_REC *entry) +{ + g_return_if_fail(entry != NULL); + + g_free_not_null(entry->prompt); + g_string_free(entry->text, TRUE); + g_free(entry); +} - if (pos < screen_width-1-promptlen) { - scrstart = 0; - scrpos = pos; +/* Fixes the cursor position in screen */ +static void gui_entry_fix_cursor(GUI_ENTRY_REC *entry) +{ + if (entry->pos - entry->scrstart < entry->width-2 - entry->promptlen && + entry->pos - entry->scrstart > 0) { + entry->scrpos = entry->pos - entry->scrstart; + } else if (entry->pos < entry->width-1 - entry->promptlen) { + entry->scrstart = 0; + entry->scrpos = entry->pos; } else { - scrpos = (screen_width-promptlen)*2/3; - scrstart = pos-scrpos; + entry->scrpos = (entry->width - entry->promptlen)*2/3; + entry->scrstart = entry->pos - entry->scrpos; } } -static void entry_update(void) +static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos) { char *p; - int n, len; + int xpos, end_xpos; - len = entry->len-scrstart > screen_width-1-promptlen ? - screen_width-1-promptlen : entry->len-scrstart; + xpos = entry->xpos + entry->promptlen + pos; + end_xpos = entry->xpos + entry->width; + if (xpos > end_xpos) + return; screen_set_color(screen_root, 0); - screen_move(screen_root, promptlen, screen_height-1); + screen_move(screen_root, xpos, entry->ypos); - for (p = entry->str+scrstart, n = 0; n < len; n++, p++) { - if (prompt_hidden) + p = entry->scrstart + pos >= entry->text->len ? "" : + entry->text->str + entry->scrstart + pos; + for (; *p != '\0' && xpos < end_xpos; p++, xpos++) { + if (entry->hidden) screen_addch(screen_root, ' '); else if ((unsigned char) *p >= 32) screen_addch(screen_root, (unsigned char) *p); @@ -67,234 +89,299 @@ static void entry_update(void) screen_set_color(screen_root, 0); } } - screen_clrtoeol(screen_root); - screen_move_cursor(scrpos+promptlen, screen_height-1); + /* clear the rest of the input line */ + if (entry->xpos + entry->width == screen_width) + screen_clrtoeol(screen_root); + else { + while (xpos < end_xpos) { + screen_addch(screen_root, ' '); + xpos++; + } + } + + screen_move_cursor(entry->xpos + entry->scrpos + entry->promptlen, + entry->ypos); screen_refresh(NULL); } -void gui_entry_set_prompt(const char *str) +static void gui_entry_draw(GUI_ENTRY_REC *entry) { - if (str != NULL) { - if (permanent_prompt) return; + gui_entry_draw_from(entry, 0); +} - g_free_not_null(prompt); - prompt = g_strdup(str); - promptlen = format_get_length(prompt); +void gui_entry_move(GUI_ENTRY_REC *entry, int xpos, int ypos, int width) +{ + int old_width; + + g_return_if_fail(entry != NULL); + + if (entry->xpos != xpos || entry->ypos != ypos) { + /* position in screen changed - needs a full redraw */ + entry->xpos = xpos; + entry->ypos = ypos; + entry->width = width; + gui_entry_redraw(entry); + return; } - if (prompt != NULL) - gui_printtext(0, screen_height-1, prompt); + if (entry->width == width) + return; /* no changes */ - entry_screenpos(); - entry_update(); + if (width > entry->width) { + /* input line grew - need to draw text at the end */ + old_width = width; + entry->width = width; + gui_entry_draw_from(entry, old_width); + } else { + /* input line shrinked - make sure the cursor + is inside the input line */ + if (entry->pos - entry->scrstart > + entry->width-2 - entry->promptlen) { + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); + } + } } -void gui_entry_set_perm_prompt(const char *str) +void gui_entry_set_active(GUI_ENTRY_REC *entry) { - g_return_if_fail(str != NULL); + active_entry = entry; - g_free_not_null(prompt); - prompt = g_strdup(str); - promptlen = format_get_length(prompt); - - permanent_prompt = TRUE; - gui_entry_set_prompt(NULL); + screen_move_cursor(entry->xpos + entry->scrpos + entry->promptlen, + entry->ypos); + screen_refresh(NULL); } -void gui_entry_set_hidden(int hidden) +void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const char *str) { - prompt_hidden = hidden; + int oldlen; + + g_return_if_fail(entry != NULL); + + oldlen = entry->promptlen; + if (str != NULL) { + g_free_not_null(entry->prompt); + entry->prompt = g_strdup(str); + entry->promptlen = format_get_length(str); + } + + if (entry->prompt != NULL) + gui_printtext(entry->xpos, entry->ypos, entry->prompt); + + if (entry->promptlen != oldlen) { + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); + } } -void gui_entry_remove_perm_prompt(void) +void gui_entry_set_hidden(GUI_ENTRY_REC *entry, int hidden) { - permanent_prompt = FALSE; + g_return_if_fail(entry != NULL); + + entry->hidden = hidden; } -void gui_entry_set_text(const char *str) +void gui_entry_set_text(GUI_ENTRY_REC *entry, const char *str) { + g_return_if_fail(entry != NULL); g_return_if_fail(str != NULL); - g_string_assign(entry, str); - pos = entry->len; + g_string_assign(entry->text, str); + entry->pos = entry->text->len; - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -char *gui_entry_get_text(void) +char *gui_entry_get_text(GUI_ENTRY_REC *entry) { - return entry->str; + g_return_val_if_fail(entry != NULL, NULL); + + return entry->text->str; } -void gui_entry_insert_text(const char *str) +void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str) { + g_return_if_fail(entry != NULL); g_return_if_fail(str != NULL); - g_string_insert(entry, pos, str); - pos += strlen(str); + g_string_insert(entry->text, entry->pos, str); + entry->pos += strlen(str); - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_insert_char(char chr) +void gui_entry_insert_char(GUI_ENTRY_REC *entry, char chr) { - if (chr == 0) return; /* never insert NUL characters */ + g_return_if_fail(entry != NULL); + + if (chr == 0) + return; /* never insert NUL characters */ - g_string_insert_c(entry, pos, chr); - pos++; + g_string_insert_c(entry->text, entry->pos, chr); + entry->pos++; - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_erase(int size) +void gui_entry_erase(GUI_ENTRY_REC *entry, int size) { - if (pos < size) return; + g_return_if_fail(entry != NULL); + + if (entry->pos < size) + return; #ifdef WANT_BIG5 - if (is_big5(entry->str[pos-2], entry->str[pos-1])) + if (is_big5(entry->text->str[entry->pos-2], + entry->text->str[entry->pos-1])) size++; #endif - pos -= size; - g_string_erase(entry, pos, size); + entry->pos -= size; + g_string_erase(entry->text, entry->pos, size); - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_erase_word(void) +void gui_entry_erase_word(GUI_ENTRY_REC *entry) { int to; - - if (pos == 0) return; - to = pos - 1; + g_return_if_fail(entry != NULL); + if (entry->pos == 0) + return; + + to = entry->pos - 1; - while (entry->str[to] == ' ' && to > 0) + while (entry->text->str[to] == ' ' && to > 0) to--; - while (entry->str[to] != ' ' && to > 0) + while (entry->text->str[to] != ' ' && to > 0) to--; - if (entry->str[to] == ' ' && to > 0) + if (entry->text->str[to] == ' ' && to > 0) to++; - g_string_erase(entry, to, pos - to); - pos = to; + g_string_erase(entry->text, to, entry->pos - to); + entry->pos = to; - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_erase_next_word(void) +void gui_entry_erase_next_word(GUI_ENTRY_REC *entry) { - int to = pos; - - if (pos == entry->len) return; + int to; + + g_return_if_fail(entry != NULL); + if (entry->pos == entry->text->len) + return; - while (entry->str[to] == ' ' && to < entry->len) + to = entry->pos; + while (entry->text->str[to] == ' ' && to < entry->text->len) to++; - while (entry->str[to] != ' ' && to < entry->len) + while (entry->text->str[to] != ' ' && to < entry->text->len) to++; - g_string_erase(entry, pos, to - pos); + g_string_erase(entry->text, entry->pos, to - entry->pos); - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -int gui_entry_get_pos(void) +int gui_entry_get_pos(GUI_ENTRY_REC *entry) { - return pos; + g_return_val_if_fail(entry != NULL, 0); + + return entry->pos; } -void gui_entry_set_pos(int p) +void gui_entry_set_pos(GUI_ENTRY_REC *entry, int pos) { - if (p >= 0 && p <= entry->len) - pos = p; + g_return_if_fail(entry != NULL); + + if (pos >= 0 && pos <= entry->text->len) + entry->pos = pos; - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_move_pos(int p) +void gui_entry_move_pos(GUI_ENTRY_REC *entry, int pos) { + g_return_if_fail(entry != NULL); + #ifdef WANT_BIG5 - if (p > 0 && is_big5 (entry->str[pos], entry->str[pos+1])) - p++; - else if (p < 0 && is_big5 (entry->str[pos-1], entry->str[pos])) - p--; + if (pos > 0 && is_big5(entry->text->str[entry->pos], + entry->text->str[entry->pos+1])) + pos++; + else if (pos < 0 && is_big5(entry->text->str[entry->pos-1], + entry->text->str[entry->pos])) + pos--; #endif - if (pos+p >= 0 && pos+p <= entry->len) - pos += p; + if (entry->pos+pos >= 0 && entry->pos+pos <= entry->text->len) + entry->pos += pos; - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -static void gui_entry_move_words_left(int count) +static void gui_entry_move_words_left(GUI_ENTRY_REC *entry, int count) { - if (pos == 0) return; + int pos; + pos = entry->pos; while (count > 0 && pos > 0) { - while (pos > 0 && entry->str[pos-1] == ' ') + while (pos > 0 && entry->text->str[pos-1] == ' ') pos--; - while (pos > 0 && entry->str[pos-1] != ' ') + while (pos > 0 && entry->text->str[pos-1] != ' ') pos--; count--; } + + entry->pos = pos; } -static void gui_entry_move_words_right(int count) +static void gui_entry_move_words_right(GUI_ENTRY_REC *entry, int count) { - if (pos == entry->len) return; + int pos; - while (count > 0 && pos < entry->len) { - while (pos < entry->len && entry->str[pos] != ' ') + pos = entry->pos; + while (count > 0 && pos < entry->text->len) { + while (pos < entry->text->len && entry->text->str[pos] != ' ') pos++; - while (pos < entry->len && entry->str[pos] == ' ') + while (pos < entry->text->len && entry->text->str[pos] == ' ') pos++; count--; } + + entry->pos = pos; } -void gui_entry_move_words(int count) +void gui_entry_move_words(GUI_ENTRY_REC *entry, int count) { + g_return_if_fail(entry != NULL); + if (count < 0) - gui_entry_move_words_left(-count); + gui_entry_move_words_left(entry, -count); else if (count > 0) - gui_entry_move_words_right(count); + gui_entry_move_words_right(entry, count); - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_redraw(void) +void gui_entry_redraw(GUI_ENTRY_REC *entry) { - gui_entry_set_prompt(NULL); + g_return_if_fail(entry != NULL); - entry_screenpos(); - entry_update(); -} - -void gui_entry_init(void) -{ - entry = g_string_new(NULL); - - pos = scrpos = 0; - prompt = NULL; promptlen = 0; - permanent_prompt = FALSE; - prompt_hidden = FALSE; -} - -void gui_entry_deinit(void) -{ - if (prompt != NULL) g_free(prompt); - g_string_free(entry, TRUE); + gui_entry_set_prompt(entry, NULL); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h index ff8f3ef5..2a35bc4c 100644 --- a/src/fe-text/gui-entry.h +++ b/src/fe-text/gui-entry.h @@ -1,31 +1,42 @@ #ifndef __GUI_ENTRY_H #define __GUI_ENTRY_H -void gui_entry_set_prompt(const char *str); +typedef struct { + GString *text; + int xpos, ypos, width; /* entry position in screen */ + int pos, scrstart, scrpos; /* cursor position */ + int hidden; /* print the chars as spaces in input line (useful for passwords) */ -/* permanent prompt can't be overwritten with gui_entry_set_prompt() */ -void gui_entry_set_perm_prompt(const char *str); -void gui_entry_remove_perm_prompt(void); -void gui_entry_set_hidden(int hidden); + int promptlen; + char *prompt; +} GUI_ENTRY_REC; -void gui_entry_set_text(const char *str); -char *gui_entry_get_text(void); +extern GUI_ENTRY_REC *active_entry; -void gui_entry_insert_text(const char *str); -void gui_entry_insert_char(char chr); +GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width); +void gui_entry_destroy(GUI_ENTRY_REC *entry); +void gui_entry_move(GUI_ENTRY_REC *entry, int xpos, int ypos, int width); -void gui_entry_erase(int size); -void gui_entry_erase_word(void); -void gui_entry_erase_next_word(void); +void gui_entry_set_active(GUI_ENTRY_REC *entry); -int gui_entry_get_pos(void); -void gui_entry_set_pos(int pos); -void gui_entry_move_pos(int pos); -void gui_entry_move_words(int count); +void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const char *str); +void gui_entry_set_hidden(GUI_ENTRY_REC *entry, int hidden); -void gui_entry_redraw(void); +void gui_entry_set_text(GUI_ENTRY_REC *entry, const char *str); +char *gui_entry_get_text(GUI_ENTRY_REC *entry); -void gui_entry_init(void); -void gui_entry_deinit(void); +void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str); +void gui_entry_insert_char(GUI_ENTRY_REC *entry, char chr); + +void gui_entry_erase(GUI_ENTRY_REC *entry, int size); +void gui_entry_erase_word(GUI_ENTRY_REC *entry); +void gui_entry_erase_next_word(GUI_ENTRY_REC *entry); + +int gui_entry_get_pos(GUI_ENTRY_REC *entry); +void gui_entry_set_pos(GUI_ENTRY_REC *entry, int pos); +void gui_entry_move_pos(GUI_ENTRY_REC *entry, int pos); +void gui_entry_move_words(GUI_ENTRY_REC *entry, int count); + +void gui_entry_redraw(GUI_ENTRY_REC *entry); #endif diff --git a/src/fe-text/gui-expandos.c b/src/fe-text/gui-expandos.c index c95ac621..b07bf129 100644 --- a/src/fe-text/gui-expandos.c +++ b/src/fe-text/gui-expandos.c @@ -37,7 +37,7 @@ static char *expando_idletime(SERVER_REC *server, void *item, int *free_ret) /* current contents of the input line */ static char *expando_inputline(SERVER_REC *server, void *item, int *free_ret) { - return gui_entry_get_text(); + return gui_entry_get_text(active_entry); } /* value of cutbuffer */ diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c index 5d94d877..3a70ef23 100644 --- a/src/fe-text/gui-printtext.c +++ b/src/fe-text/gui-printtext.c @@ -97,11 +97,8 @@ static void get_colors(int flags, int *fg, int *bg) current_theme->default_real_color; } - if (flags & GUI_PRINT_FLAG_REVERSE) { - int tmp; - - tmp = *fg; *fg = *bg; *bg = tmp; - } + if (flags & GUI_PRINT_FLAG_REVERSE) + *fg |= ATTR_REVERSE; if (*fg == 8) *fg |= ATTR_COLOR8; if (flags & GUI_PRINT_FLAG_BOLD) { @@ -180,8 +177,13 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor, g_return_if_fail(next_xpos != -1); screen_move(screen_root, next_xpos, next_ypos); + if (flags & GUI_PRINT_FLAG_CLRTOEOL) { + screen_set_bg(screen_root, fg | (bg << 4)); + screen_clrtoeol(screen_root); + screen_set_bg(screen_root, 0); + } screen_set_color(screen_root, fg | (bg << 4)); - screen_addstr(screen_root, str); + screen_addstr(screen_root, str); next_xpos += strlen(str); return; } diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index c44be58f..4d71e195 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -63,8 +63,7 @@ static void handle_key_redirect(int key) if (func != NULL) func(key, data, active_win->active_server, active_win->active); - gui_entry_remove_perm_prompt(); - window_update_prompt(); + gui_entry_set_prompt(active_entry, ""); } static void handle_entry_redirect(const char *line) @@ -72,7 +71,7 @@ static void handle_entry_redirect(const char *line) ENTRY_REDIRECT_ENTRY_FUNC func; void *data; - gui_entry_set_hidden(FALSE); + gui_entry_set_hidden(active_entry, FALSE); func = (ENTRY_REDIRECT_ENTRY_FUNC) redir->func; data = redir->data; @@ -83,8 +82,7 @@ static void handle_entry_redirect(const char *line) active_win->active); } - gui_entry_remove_perm_prompt(); - window_update_prompt(); + gui_entry_set_prompt(active_entry, ""); } static int get_scroll_count(void) @@ -141,7 +139,7 @@ void handle_key(int key) if (!key_pressed(keyboard, str)) { /* key wasn't used for anything, print it */ - gui_entry_insert_char((char) key); + gui_entry_insert_char(active_entry, (char) key); } } @@ -150,7 +148,7 @@ static void key_send_line(void) int add_history; char *str; - str = gui_entry_get_text(); + str = gui_entry_get_text(active_entry); if (*str == '\0') return; translate_output(str); @@ -167,10 +165,10 @@ static void key_send_line(void) } if (add_history) { - command_history_add(active_win, gui_entry_get_text(), + command_history_add(active_win, gui_entry_get_text(active_entry), FALSE); } - gui_entry_set_text(""); + gui_entry_set_text(active_entry, ""); command_history_clear_pos(active_win); } @@ -182,83 +180,83 @@ static void key_backward_history(void) { const char *text; - text = command_history_prev(active_win, gui_entry_get_text()); - gui_entry_set_text(text); + text = command_history_prev(active_win, gui_entry_get_text(active_entry)); + gui_entry_set_text(active_entry, text); } static void key_forward_history(void) { const char *text; - text = command_history_next(active_win, gui_entry_get_text()); - gui_entry_set_text(text); + text = command_history_next(active_win, gui_entry_get_text(active_entry)); + gui_entry_set_text(active_entry, text); } static void key_beginning_of_line(void) { - gui_entry_set_pos(0); + gui_entry_set_pos(active_entry, 0); } static void key_end_of_line(void) { - gui_entry_set_pos(strlen(gui_entry_get_text())); + gui_entry_set_pos(active_entry, strlen(gui_entry_get_text(active_entry))); } static void key_backward_character(void) { - gui_entry_move_pos(-1); + gui_entry_move_pos(active_entry, -1); } static void key_forward_character(void) { - gui_entry_move_pos(1); + gui_entry_move_pos(active_entry, 1); } static void key_backward_word(void) { - gui_entry_move_words(-1); + gui_entry_move_words(active_entry, -1); } static void key_forward_word(void) { - gui_entry_move_words(1); + gui_entry_move_words(active_entry, 1); } static void key_erase_line(void) { g_free_not_null(cutbuffer); - cutbuffer = g_strdup(gui_entry_get_text()); + cutbuffer = g_strdup(gui_entry_get_text(active_entry)); - gui_entry_set_text(""); + gui_entry_set_text(active_entry, ""); } static void key_erase_to_beg_of_line(void) { int pos; - pos = gui_entry_get_pos(); + pos = gui_entry_get_pos(active_entry); g_free_not_null(cutbuffer); - cutbuffer = g_strndup(gui_entry_get_text(), pos); + cutbuffer = g_strndup(gui_entry_get_text(active_entry), pos); - gui_entry_erase(pos); + gui_entry_erase(active_entry, pos); } static void key_erase_to_end_of_line(void) { int pos; - pos = gui_entry_get_pos(); + pos = gui_entry_get_pos(active_entry); g_free_not_null(cutbuffer); - cutbuffer = g_strdup(gui_entry_get_text()+pos); + cutbuffer = g_strdup(gui_entry_get_text(active_entry)+pos); - gui_entry_set_pos(strlen(gui_entry_get_text())); - gui_entry_erase(strlen(gui_entry_get_text()) - pos); + gui_entry_set_pos(active_entry, strlen(gui_entry_get_text(active_entry))); + gui_entry_erase(active_entry, strlen(gui_entry_get_text(active_entry)) - pos); } static void key_yank_from_cutbuffer(void) { if (cutbuffer != NULL) - gui_entry_insert_text(cutbuffer); + gui_entry_insert_text(active_entry, cutbuffer); } static void key_transpose_characters(void) @@ -266,46 +264,46 @@ static void key_transpose_characters(void) char *line, c; int pos; - pos = gui_entry_get_pos(); - line = gui_entry_get_text(); + pos = gui_entry_get_pos(active_entry); + line = gui_entry_get_text(active_entry); if (pos == 0 || strlen(line) < 2) return; if (line[pos] != '\0') - gui_entry_move_pos(1); - c = line[gui_entry_get_pos()-1]; - gui_entry_erase(1); - gui_entry_move_pos(-1); - gui_entry_insert_char(c); - gui_entry_set_pos(pos); + gui_entry_move_pos(active_entry, 1); + c = line[gui_entry_get_pos(active_entry)-1]; + gui_entry_erase(active_entry, 1); + gui_entry_move_pos(active_entry, -1); + gui_entry_insert_char(active_entry, c); + gui_entry_set_pos(active_entry, pos); } static void key_delete_character(void) { - if (gui_entry_get_pos() < (int)strlen(gui_entry_get_text())) { - gui_entry_move_pos(1); - gui_entry_erase(1); + if (gui_entry_get_pos(active_entry) < (int)strlen(gui_entry_get_text(active_entry))) { + gui_entry_move_pos(active_entry, 1); + gui_entry_erase(active_entry, 1); } } static void key_backspace(void) { - gui_entry_erase(1); + gui_entry_erase(active_entry, 1); } static void key_delete_previous_word(void) { - gui_entry_erase_word(); + gui_entry_erase_word(active_entry); } static void key_delete_next_word(void) { - gui_entry_erase_next_word(); + gui_entry_erase_next_word(active_entry); } static void key_delete_to_previous_space(void) { - gui_entry_erase_word(); + gui_entry_erase_word(active_entry); } void readline(void) @@ -356,12 +354,12 @@ static void key_word_completion(void) char *line; int pos; - pos = gui_entry_get_pos(); + pos = gui_entry_get_pos(active_entry); - line = word_complete(active_win, gui_entry_get_text(), &pos); + line = word_complete(active_win, gui_entry_get_text(active_entry), &pos); if (line != NULL) { - gui_entry_set_text(line); - gui_entry_set_pos(pos); + gui_entry_set_text(active_entry, line); + gui_entry_set_pos(active_entry, pos); g_free(line); } } @@ -371,12 +369,12 @@ static void key_check_replaces(void) char *line; int pos; - pos = gui_entry_get_pos(); + pos = gui_entry_get_pos(active_entry); - line = auto_word_complete(gui_entry_get_text(), &pos); + line = auto_word_complete(gui_entry_get_text(active_entry), &pos); if (line != NULL) { - gui_entry_set_text(line); - gui_entry_set_pos(pos); + gui_entry_set_text(active_entry, line); + gui_entry_set_pos(active_entry, pos); g_free(line); } } @@ -464,14 +462,14 @@ static void key_insert_text(const char *data) str = parse_special_string(data, active_win->active_server, active_win->active, "", NULL, 0); - gui_entry_insert_text(str); + gui_entry_insert_text(active_entry, str); g_free(str); } static void sig_window_auto_changed(void) { - command_history_next(active_win, gui_entry_get_text()); - gui_entry_set_text(""); + command_history_next(active_win, gui_entry_get_text(active_entry)); + gui_entry_set_text(active_entry, ""); } static void sig_gui_entry_redirect(SIGNAL_FUNC func, const char *entry, @@ -483,8 +481,8 @@ static void sig_gui_entry_redirect(SIGNAL_FUNC func, const char *entry, redir->data = data; if (redir->flags & ENTRY_REDIRECT_FLAG_HIDDEN) - gui_entry_set_hidden(TRUE); - gui_entry_set_perm_prompt(entry); + gui_entry_set_hidden(active_entry, TRUE); + gui_entry_set_prompt(active_entry, entry); } void gui_readline_init(void) diff --git a/src/fe-text/gui-windows.c b/src/fe-text/gui-windows.c index 48c1feb7..0f4a6702 100644 --- a/src/fe-text/gui-windows.c +++ b/src/fe-text/gui-windows.c @@ -31,15 +31,13 @@ static int window_create_override; -static char *prompt, *prompt_window; - static GUI_WINDOW_REC *gui_window_init(WINDOW_REC *window, MAIN_WINDOW_REC *parent) { GUI_WINDOW_REC *gui; window->width = parent->width; - window->height = parent->height; + window->height = MAIN_WINDOW_TEXT_HEIGHT(parent); gui = g_new0(GUI_WINDOW_REC, 1); gui->parent = parent; @@ -161,54 +159,6 @@ void gui_window_set_unsticky(WINDOW_REC *window) } } -void window_update_prompt(void) -{ - const char *special; - char *prompt, *text; - int var_used; - - special = settings_get_str(active_win->active != NULL ? - "prompt" : "prompt_window"); - if (*special == '\0') { - gui_entry_set_prompt(""); - return; - } - - prompt = parse_special_string(special, active_win->active_server, - active_win->active, "", &var_used, - PARSE_FLAG_ISSET_ANY | - PARSE_FLAG_ESCAPE_VARS); - if (!var_used && strchr(special, '$') != NULL) { - /* none of the $vars had non-empty values, use empty prompt */ - *prompt = '\0'; - } - - /* set prompt */ - text = show_lowascii(prompt); - gui_entry_set_prompt(text); - g_free(text); - - g_free(prompt); -} - -static void window_update_prompt_server(SERVER_REC *server) -{ - if (server == active_win->active_server) - window_update_prompt(); -} - -static void window_update_prompt_window(WINDOW_REC *window) -{ - if (window == active_win) - window_update_prompt(); -} - -static void window_update_prompt_window_item(WI_ITEM_REC *item) -{ - if (item == active_win->active) - window_update_prompt(); -} - void gui_window_reparent(WINDOW_REC *window, MAIN_WINDOW_REC *parent) { MAIN_WINDOW_REC *oldparent; @@ -224,9 +174,12 @@ void gui_window_reparent(WINDOW_REC *window, MAIN_WINDOW_REC *parent) if (parent->sticky_windows) gui_window_set_sticky(window); - if (parent->height != oldparent->height || - parent->width != oldparent->width) - gui_window_resize(window, parent->width, parent->height); + if (MAIN_WINDOW_TEXT_HEIGHT(parent) != + MAIN_WINDOW_TEXT_HEIGHT(oldparent) || + parent->width != oldparent->width) { + gui_window_resize(window, parent->width, + MAIN_WINDOW_TEXT_HEIGHT(parent)); + } } static MAIN_WINDOW_REC *mainwindow_find_unsticky(void) @@ -282,36 +235,12 @@ static void signal_window_changed(WINDOW_REC *window) textbuffer_view_set_window(WINDOW_GUI(window)->view, parent->screen_win); - - window_update_prompt(); -} - -static void sig_check_window_update(WINDOW_REC *window) -{ - if (window == active_win) - window_update_prompt(); } static void read_settings(void) { GSList *tmp; - SIGNAL_FUNC funcs[] = { - (SIGNAL_FUNC) window_update_prompt, - (SIGNAL_FUNC) window_update_prompt_server, - (SIGNAL_FUNC) window_update_prompt_window, - (SIGNAL_FUNC) window_update_prompt_window_item - }; - - if (prompt != NULL) { - special_vars_remove_signals(prompt, 4, funcs); - special_vars_remove_signals(prompt_window, 4, funcs); - g_free(prompt); - g_free(prompt_window); - } - prompt = g_strdup(settings_get_str("prompt")); - prompt_window = g_strdup(settings_get_str("prompt_window")); - for (tmp = windows; tmp != NULL; tmp = tmp->next) { WINDOW_REC *rec = tmp->data; GUI_WINDOW_REC *gui = WINDOW_GUI(rec); @@ -324,11 +253,6 @@ static void read_settings(void) gui->use_scroll ? gui->scroll : settings_get_bool("scroll")); } - - special_vars_add_signals(prompt, 4, funcs); - special_vars_add_signals(prompt_window, 4, funcs); - - if (active_win != NULL) window_update_prompt(); } void gui_windows_init(void) @@ -336,11 +260,8 @@ void gui_windows_init(void) settings_add_bool("lookandfeel", "autostick_split_windows", TRUE); settings_add_int("lookandfeel", "indent", 10); settings_add_bool("lookandfeel", "indent_always", FALSE); - settings_add_str("lookandfeel", "prompt", "[$[.15]T] "); - settings_add_str("lookandfeel", "prompt_window", "[$winname] "); settings_add_bool("lookandfeel", "scroll", TRUE); - prompt = NULL; prompt_window = NULL; window_create_override = -1; read_settings(); @@ -348,15 +269,11 @@ void gui_windows_init(void) signal_add("window created", (SIGNAL_FUNC) gui_window_created); signal_add("window destroyed", (SIGNAL_FUNC) gui_window_destroyed); signal_add_first("window changed", (SIGNAL_FUNC) signal_window_changed); - signal_add("window item remove", (SIGNAL_FUNC) sig_check_window_update); signal_add("setup changed", (SIGNAL_FUNC) read_settings); } void gui_windows_deinit(void) { - g_free_not_null(prompt); - g_free_not_null(prompt_window); - while (windows != NULL) window_destroy(windows->data); @@ -364,6 +281,5 @@ void gui_windows_deinit(void) signal_remove("window created", (SIGNAL_FUNC) gui_window_created); signal_remove("window destroyed", (SIGNAL_FUNC) gui_window_destroyed); signal_remove("window changed", (SIGNAL_FUNC) signal_window_changed); - signal_remove("window item remove", (SIGNAL_FUNC) sig_check_window_update); signal_remove("setup changed", (SIGNAL_FUNC) read_settings); } diff --git a/src/fe-text/gui-windows.h b/src/fe-text/gui-windows.h index 220b4661..b67f6de7 100644 --- a/src/fe-text/gui-windows.h +++ b/src/fe-text/gui-windows.h @@ -39,6 +39,4 @@ void gui_window_scroll_line(WINDOW_REC *window, LINE_REC *line); void gui_window_set_sticky(WINDOW_REC *window); void gui_window_set_unsticky(WINDOW_REC *window); -void window_update_prompt(void); - #endif diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index 22f2b8d7..900fcf8c 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -98,8 +98,6 @@ void irssi_redraw(void) mainwindows_redraw(); /* statusbar */ statusbar_redraw(NULL); - /* entry line */ - gui_entry_redraw(); } static void textui_init(void) @@ -123,7 +121,6 @@ static void textui_finish_init(void) textbuffer_view_init(); textbuffer_commands_init(); textbuffer_reformat_init(); - gui_entry_init(); gui_expandos_init(); gui_printtext_init(); gui_readline_init(); @@ -173,7 +170,6 @@ static void textui_deinit(void) mainwindow_activity_deinit(); mainwindows_deinit(); gui_expandos_deinit(); - gui_entry_deinit(); textbuffer_reformat_deinit(); textbuffer_commands_deinit(); textbuffer_view_deinit(); diff --git a/src/fe-text/mainwindows.c b/src/fe-text/mainwindows.c index 6c8a02c8..3944ac5f 100644 --- a/src/fe-text/mainwindows.c +++ b/src/fe-text/mainwindows.c @@ -28,7 +28,6 @@ #include "printtext.h" #include "screen.h" -#include "statusbar.h" #include "gui-windows.h" #define NEW_WINDOW_SIZE (WINDOW_MIN_SIZE + 1) @@ -36,12 +35,21 @@ GSList *mainwindows; MAIN_WINDOW_REC *active_mainwin; -static int reserved_up, reserved_down; +static int reserved_top, reserved_bottom; static int old_screen_width, old_screen_height; #define mainwindow_create_screen(window) \ - screen_window_create(0, (window)->first_line, \ - (window)->width, (window)->height) + screen_window_create(0, \ + (window)->first_line + (window)->statusbar_lines_top, \ + (window)->width, \ + (window)->height + (window)->statusbar_lines_bottom) + +#define mainwindow_set_screen_size(window) \ + screen_window_move((window)->screen_win, 0, \ + (window)->first_line + (window)->statusbar_lines_top, \ + (window)->width, \ + (window)->height - (window)->statusbar_lines_bottom); + static MAIN_WINDOW_REC *find_window_with_room(void) { @@ -67,13 +75,12 @@ static void mainwindow_resize(MAIN_WINDOW_REC *window, int xdiff, int ydiff) { GSList *tmp; - if (xdiff == 0 && ydiff == 0) + if (quitting || (xdiff == 0 && ydiff == 0)) return; window->width += xdiff; window->height = window->last_line-window->first_line+1; - screen_window_move(window->screen_win, 0, window->first_line, - window->width, window->height); + mainwindow_set_screen_size(window); for (tmp = windows; tmp != NULL; tmp = tmp->next) { WINDOW_REC *rec = tmp->data; @@ -161,14 +168,12 @@ MAIN_WINDOW_REC *mainwindow_create(void) rec = g_new0(MAIN_WINDOW_REC, 1); rec->width = screen_width; - rec->statusbar_lines = 1; if (mainwindows == NULL) { active_mainwin = rec; - rec->first_line = reserved_up; - rec->last_line = screen_height-1 - - reserved_down-rec->statusbar_lines; + rec->first_line = reserved_top; + rec->last_line = screen_height-1 - reserved_bottom; rec->height = rec->last_line-rec->first_line+1; } else { parent = WINDOW_MAIN(active_win); @@ -177,11 +182,12 @@ MAIN_WINDOW_REC *mainwindow_create(void) if (parent == NULL) return NULL; /* not enough space */ - space = (parent->height-parent->statusbar_lines)/2; + space = parent->height / 2; rec->first_line = parent->first_line; - rec->last_line = rec->first_line + space-rec->statusbar_lines; + rec->last_line = rec->first_line + space; rec->height = rec->last_line-rec->first_line+1; - parent->first_line = rec->last_line+1+rec->statusbar_lines; + + parent->first_line = rec->last_line+1; parent->height = parent->last_line-parent->first_line+1; mainwindow_resize(parent, 0, -space-1); @@ -248,7 +254,7 @@ static void mainwindows_add_space(int first_line, int last_line) rec = mainwindows_find_upper(first_line); if (rec != NULL) { - rec->last_line = last_line-rec->statusbar_lines; + rec->last_line = last_line; mainwindow_resize(rec, 0, size); } } @@ -278,10 +284,9 @@ void mainwindow_destroy(MAIN_WINDOW_REC *window) if (!quitting && mainwindows != NULL) { gui_windows_remove_parent(window); - mainwindows_add_space(window->first_line, window->last_line+window->statusbar_lines); + mainwindows_add_space(window->first_line, window->last_line); mainwindows_redraw(); - statusbar_redraw(NULL); } g_free(window); @@ -468,35 +473,68 @@ void mainwindows_resize(int width, int height) irssi_redraw(); } -int mainwindows_reserve_lines(int count, int up) +int mainwindows_reserve_lines(int top, int bottom) { MAIN_WINDOW_REC *window; int ret; - if (up) { - g_return_val_if_fail(count > 0 || reserved_up > count, -1); + ret = -1; + if (top != 0) { + g_return_val_if_fail(top > 0 || reserved_top > top, -1); - ret = reserved_up; - reserved_up += count; + ret = reserved_top; + reserved_top += top; window = mainwindows_find_lower(-1); - if (window != NULL) window->first_line += count; - } else { - g_return_val_if_fail(count > 0 || reserved_down > count, -1); + if (window != NULL) { + window->first_line += top; + mainwindow_resize(window, 0, -top); + } + } + + if (bottom != 0) { + g_return_val_if_fail(bottom > 0 || reserved_bottom > bottom, -1); - ret = reserved_down; - reserved_down += count; + ret = reserved_bottom; + reserved_bottom += bottom; window = mainwindows_find_upper(screen_height); - if (window != NULL) window->last_line -= count; + if (window != NULL) { + window->last_line -= bottom; + mainwindow_resize(window, 0, -bottom); + } } - if (window != NULL) - mainwindow_resize(window, 0, -count); - return ret; } +int mainwindow_set_statusbar_lines(MAIN_WINDOW_REC *window, + int top, int bottom) +{ + int ret; + + ret = -1; + if (top != 0) { + ret = window->statusbar_lines_top; + window->statusbar_lines_top += top; + window->statusbar_lines += top; + } + + if (bottom != 0) { + ret = window->statusbar_lines_bottom; + window->statusbar_lines_bottom += bottom; + window->statusbar_lines += bottom; + } + + if (top+bottom != 0) { + mainwindow_set_screen_size(window); + gui_window_resize(window->active, window->width, + MAIN_WINDOW_TEXT_HEIGHT(window)); + } + + return ret; +} + static void mainwindows_resize_two(MAIN_WINDOW_REC *grow_win, MAIN_WINDOW_REC *shrink_win, int count) { @@ -504,8 +542,6 @@ static void mainwindows_resize_two(MAIN_WINDOW_REC *grow_win, mainwindow_resize(shrink_win, 0, -count); gui_window_redraw(grow_win->active); gui_window_redraw(shrink_win->active); - statusbar_redraw(grow_win->statusbar); - statusbar_redraw(shrink_win->statusbar); } static int mainwindow_grow(MAIN_WINDOW_REC *window, int count) @@ -620,33 +656,31 @@ static void cmd_window_balance(void) windows = g_slist_length(mainwindows); if (windows == 1) return; - avail_size = screen_height - reserved_up-reserved_down; + avail_size = screen_height - reserved_top-reserved_bottom; unit_size = avail_size/windows; bigger_units = avail_size%windows; sorted = mainwindows_get_sorted(FALSE); - last_line = reserved_up; + last_line = reserved_top; for (tmp = sorted; tmp != NULL; tmp = tmp->next) { MAIN_WINDOW_REC *rec = tmp->data; old_size = rec->height; rec->first_line = last_line; - rec->last_line = rec->first_line + unit_size-1 - - rec->statusbar_lines; + rec->last_line = rec->first_line + unit_size-1; rec->height = rec->last_line-rec->first_line+1; if (bigger_units > 0) { rec->last_line++; bigger_units--; } - last_line = rec->last_line+1 + rec->statusbar_lines; + last_line = rec->last_line+1; mainwindow_resize(rec, 0, rec->height-old_size); } g_slist_free(sorted); mainwindows_redraw(); - statusbar_redraw(NULL); } /* SYNTAX: WINDOW HIDE [<number>|<name>] */ @@ -954,10 +988,7 @@ void mainwindows_init(void) mainwindows = NULL; active_mainwin = NULL; - reserved_up = reserved_down = 0; - - /* for entry line */ - mainwindows_reserve_lines(1, FALSE); + reserved_top = reserved_bottom = 0; command_bind("window grow", NULL, (SIGNAL_FUNC) cmd_window_grow); command_bind("window shrink", NULL, (SIGNAL_FUNC) cmd_window_shrink); diff --git a/src/fe-text/mainwindows.h b/src/fe-text/mainwindows.h index 754cd011..514677b5 100644 --- a/src/fe-text/mainwindows.h +++ b/src/fe-text/mainwindows.h @@ -6,18 +6,22 @@ #define WINDOW_MIN_SIZE 2 +#define MAIN_WINDOW_TEXT_HEIGHT(window) \ + ((window)->height-(window)->statusbar_lines) + typedef struct { WINDOW_REC *active; SCREEN_WINDOW *screen_win; int sticky_windows; /* number of sticky windows */ - int first_line, last_line; /* first/last line used by this window (0..x), not including statusbar */ - int width, height; /* width/height of the window, not including statusbar */ + int first_line, last_line; /* first/last line used by this window (0..x) (includes statusbars) */ + int width, height; /* width/height of the window (includes statusbars) */ - int statusbar_lines; /* number of lines the statusbar takes below the window */ - void *statusbar; - void *statusbar_window_item; + GSList *statusbars; + int statusbar_lines_top; + int statusbar_lines_bottom; + int statusbar_lines; /* top+bottom */ } MAIN_WINDOW_REC; extern GSList *mainwindows; @@ -38,7 +42,10 @@ void mainwindows_resize(int width, int height); void mainwindow_change_active(MAIN_WINDOW_REC *mainwin, WINDOW_REC *skip_window); -int mainwindows_reserve_lines(int count, int up); +int mainwindows_reserve_lines(int top, int bottom); +int mainwindow_set_statusbar_lines(MAIN_WINDOW_REC *window, + int top, int bottom); + GSList *mainwindows_get_sorted(int reverse); #endif diff --git a/src/fe-text/screen.c b/src/fe-text/screen.c index 288f8e02..f04fd905 100644 --- a/src/fe-text/screen.c +++ b/src/fe-text/screen.c @@ -52,7 +52,9 @@ #define MIN_SCREEN_WIDTH 20 struct _SCREEN_WINDOW { - WINDOW *win; + int x, y; + int width, height; + WINDOW *win; }; SCREEN_WINDOW *screen_root; @@ -255,13 +257,15 @@ void screen_clear(void) SCREEN_WINDOW *screen_window_create(int x, int y, int width, int height) { - SCREEN_WINDOW *scrwin; + SCREEN_WINDOW *window; - scrwin = g_new0(SCREEN_WINDOW, 1); - scrwin->win = newwin(height, width, y, x); - idlok(scrwin->win, 1); + window = g_new0(SCREEN_WINDOW, 1); + window->x = x; window->y = y; + window->width = width; window->height = height; + window->win = newwin(height, width, y, x); + idlok(window->win, 1); - return scrwin; + return window; } void screen_window_destroy(SCREEN_WINDOW *window) @@ -279,13 +283,20 @@ void screen_window_move(SCREEN_WINDOW *window, int x, int y, int width, int height) { #ifdef HAVE_CURSES_WRESIZE - wresize(window->win, height, width); - mvwin(window->win, y, x); + if (window->width != width || window->height != height) + wresize(window->win, height, width); + if (window->x != x || window->y != y) + mvwin(window->win, y, x); #else - delwin(window->win); - window->win = newwin(height, width, y, x); - idlok(window->win, 1); + if (window->width != width || window->height != height || + window->x != x || window->y != y) { + delwin(window->win); + window->win = newwin(height, width, y, x); + idlok(window->win, 1); + } #endif + window->x = x; window->y = y; + window->width = width; window->height = height; } void screen_window_scroll(SCREEN_WINDOW *window, int count) @@ -295,44 +306,35 @@ void screen_window_scroll(SCREEN_WINDOW *window, int count) scrollok(window->win, FALSE); } -void screen_set_color(SCREEN_WINDOW *window, int col) +static int get_attr(int color) { int attr; if (!use_colors) - attr = (col & 0x70) ? A_REVERSE : 0; - else if (col & ATTR_COLOR8) + attr = (color & 0x70) ? A_REVERSE : 0; + else if (color & ATTR_COLOR8) attr = (A_DIM | COLOR_PAIR(63)); - else if ((col & 0x77) == 0) + else if ((color & 0x77) == 0) attr = A_NORMAL; else - attr = (COLOR_PAIR((col&7) + (col&0x70)/2)); - - if (col & 0x08) attr |= A_BOLD; - if (col & 0x80) attr |= A_BLINK; + attr = (COLOR_PAIR((color&7) + (color&0x70)/2)); - if (col & ATTR_UNDERLINE) attr |= A_UNDERLINE; - if (col & ATTR_REVERSE) attr |= A_REVERSE; + if (color & 0x08) attr |= A_BOLD; + if (color & 0x80) attr |= A_BLINK; - wattrset(window->win, attr); + if (color & ATTR_UNDERLINE) attr |= A_UNDERLINE; + if (color & ATTR_REVERSE) attr |= A_REVERSE; + return attr; } -void screen_set_bg(SCREEN_WINDOW *window, int col) +void screen_set_color(SCREEN_WINDOW *window, int color) { - int attr; - - if (!use_colors) - attr = (col & 0x70) ? A_REVERSE : 0; - else { - attr = (col == 8) ? - (A_DIM | COLOR_PAIR(63)) : - (COLOR_PAIR((col&7) + (col&0x70)/2)); - } - - if (col & 0x08) attr |= A_BOLD; - if (col & 0x80) attr |= A_BLINK; + wattrset(window->win, get_attr(color)); +} - wbkgdset(window->win, ' ' | attr); +void screen_set_bg(SCREEN_WINDOW *window, int color) +{ + wbkgdset(window->win, ' ' | get_attr(color)); } void screen_move(SCREEN_WINDOW *window, int x, int y) diff --git a/src/fe-text/statusbar-config.c b/src/fe-text/statusbar-config.c new file mode 100644 index 00000000..cc14b886 --- /dev/null +++ b/src/fe-text/statusbar-config.c @@ -0,0 +1,263 @@ +/* + statusbar-config.c : irssi + + Copyright (C) 2001 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "signals.h" +#include "settings.h" +#include "lib-config/iconfig.h" + +#include "statusbar.h" + +static void read_statusbar_config_from_node(CONFIG_NODE *node); + +static STATUSBAR_CONFIG_REC * +statusbar_config_create(STATUSBAR_GROUP_REC *group, const char *name) +{ + STATUSBAR_CONFIG_REC *bar; + + g_return_val_if_fail(group != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + bar = g_new0(STATUSBAR_CONFIG_REC, 1); + group->config_bars = g_slist_append(group->config_bars, bar); + + bar->name = g_strdup(name); + return bar; +} + +static SBAR_ITEM_CONFIG_REC * +statusbar_item_config_create(STATUSBAR_CONFIG_REC *bar, const char *name, + int priority, int right_alignment) +{ + SBAR_ITEM_CONFIG_REC *rec; + + g_return_val_if_fail(bar != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + rec = g_new0(SBAR_ITEM_CONFIG_REC, 1); + bar->items = g_slist_append(bar->items, rec); + + rec->name = g_strdup(name); + rec->priority = priority; + rec->right_alignment = right_alignment; + + return rec; +} + +static void statusbar_config_item_destroy(STATUSBAR_CONFIG_REC *barconfig, + SBAR_ITEM_CONFIG_REC *itemconfig) +{ + barconfig->items = g_slist_remove(barconfig->items, itemconfig); + + g_free(itemconfig->name); + g_free(itemconfig); +} + +void statusbar_config_destroy(STATUSBAR_GROUP_REC *group, + STATUSBAR_CONFIG_REC *config) +{ + group->config_bars = g_slist_remove(group->config_bars, config); + + while (config->items != NULL) + statusbar_config_item_destroy(config, config->items->data); + + g_free(config->name); + g_free(config); +} + +static STATUSBAR_CONFIG_REC * +statusbar_config_find(STATUSBAR_GROUP_REC *group, const char *name) +{ + GSList *tmp; + + for (tmp = group->config_bars; tmp != NULL; tmp = tmp->next) { + STATUSBAR_CONFIG_REC *config = tmp->data; + + if (strcmp(config->name, name) == 0) + return config; + } + + return NULL; +} + +static void statusbar_reset_defaults(void) +{ + CONFIG_REC *config; + CONFIG_NODE *node; + + while (statusbar_groups != NULL) + statusbar_group_destroy(statusbar_groups->data); + active_statusbar_group = NULL; + + /* read the default statusbar settings from internal config */ + config = config_open(NULL, -1); + config_parse_data(config, default_config, "internal"); + node = config_node_traverse(config, "statusbar", FALSE); + if (node != NULL) + read_statusbar_config_from_node(node); + config_close(config); +} + +static void statusbar_read_items(CONFIG_NODE *items) +{ + GSList *tmp; + + tmp = config_node_first(items->value); + for (; tmp != NULL; tmp = config_node_next(tmp)) { + CONFIG_NODE *node = tmp->data; + + statusbar_item_register(node->key, node->value, NULL); + } +} + +static void statusbar_read_item(STATUSBAR_CONFIG_REC *bar, CONFIG_NODE *node) +{ + int priority, right_alignment; + + priority = config_node_get_int(node, "priority", 0); + right_alignment = strcmp(config_node_get_str(node, "alignment", ""), "right") == 0; + statusbar_item_config_create(bar, node->key, + priority, right_alignment); +} + +static void statusbar_read(STATUSBAR_GROUP_REC *group, CONFIG_NODE *node) +{ + STATUSBAR_CONFIG_REC *bar; + GSList *tmp; + int type, placement, position, visible; + const char *visible_str; + + bar = statusbar_config_find(group, node->key); + + type = STATUSBAR_TYPE_ROOT; + placement = STATUSBAR_BOTTOM; + position = 0; + visible = STATUSBAR_VISIBLE_ALWAYS; + + visible_str = config_node_get_str(node, "visible", ""); + if (strcmp(visible_str, "active") == 0) + visible = STATUSBAR_VISIBLE_ACTIVE; + else if (strcmp(visible_str, "inactive") == 0) + visible = STATUSBAR_VISIBLE_INACTIVE; + else if (strcmp(visible_str, "never") == 0) { + /* we don't want this statusbar - + destroy it if it already exists */ + if (bar != NULL) + statusbar_config_destroy(group, bar); + return; + } + + if (strcmp(config_node_get_str(node, "type", ""), "window") == 0) + type = STATUSBAR_TYPE_WINDOW; + if (strcmp(config_node_get_str(node, "placement", ""), "top") == 0) + placement = STATUSBAR_TOP; + position = config_node_get_int(node, "position", 0); + + if (bar == NULL) + bar = statusbar_config_create(group, node->key); + + bar->type = type; + bar->placement = placement; + bar->position = position; + bar->visible = visible; + + node = config_node_section(node, "items", -1); + if (node != NULL) { + /* we're overriding the items - destroy the old */ + while (bar->items != NULL) + statusbar_config_item_destroy(bar, bar->items->data); + + tmp = config_node_first(node->value); + for (; tmp != NULL; tmp = config_node_next(tmp)) + statusbar_read_item(bar, tmp->data); + } +} + +static void statusbar_read_group(CONFIG_NODE *node) +{ + STATUSBAR_GROUP_REC *group; + GSList *tmp; + + group = statusbar_group_find(node->key); + if (group == NULL) { + group = statusbar_group_create(node->key); + if (active_statusbar_group == NULL) + active_statusbar_group = group; + } + + tmp = config_node_first(node->value); + for (; tmp != NULL; tmp = config_node_next(tmp)) + statusbar_read(group, tmp->data); +} + +static void create_root_statusbars(void) +{ + STATUSBAR_REC *bar; + GSList *tmp; + + tmp = active_statusbar_group->config_bars; + for (; tmp != NULL; tmp = tmp->next) { + STATUSBAR_CONFIG_REC *rec = tmp->data; + + if (rec->type == STATUSBAR_TYPE_ROOT) { + bar = statusbar_create(active_statusbar_group, rec, NULL); + statusbar_redraw(bar); + } + } +} + +static void read_statusbar_config_from_node(CONFIG_NODE *node) +{ + CONFIG_NODE *items; + GSList *tmp; + + items = config_node_section(node, "items", -1); + if (items != NULL) + statusbar_read_items(items); + + tmp = config_node_first(node->value); + for (; tmp != NULL; tmp = config_node_next(tmp)) { + if (tmp->data != items) + statusbar_read_group(tmp->data); + } +} + +static void read_statusbar_config(void) +{ + CONFIG_NODE *node; + + statusbar_reset_defaults(); + + node = iconfig_node_traverse("statusbar", FALSE); + if (node != NULL) + read_statusbar_config_from_node(node); + + create_root_statusbars(); +} + +void statusbar_config_init(void) +{ + read_statusbar_config(); + signal_add("setup reread", (SIGNAL_FUNC) read_statusbar_config); +} + +void statusbar_config_deinit(void) +{ +} diff --git a/src/fe-text/statusbar-config.h b/src/fe-text/statusbar-config.h new file mode 100644 index 00000000..a2a0b049 --- /dev/null +++ b/src/fe-text/statusbar-config.h @@ -0,0 +1,12 @@ +#ifndef __STATUSBAR_CONFIG_H +#define __STATUSBAR_CONFIG_H + +#include "statusbar.h" + +void statusbar_config_destroy(STATUSBAR_GROUP_REC *group, + STATUSBAR_CONFIG_REC *config); + +void statusbar_config_init(void); +void statusbar_config_deinit(void); + +#endif diff --git a/src/fe-text/statusbar-items.c b/src/fe-text/statusbar-items.c index 9af6278b..ee33dafa 100644 --- a/src/fe-text/statusbar-items.c +++ b/src/fe-text/statusbar-items.c @@ -20,183 +20,103 @@ #include "module.h" #include "signals.h" -#include "misc.h" #include "settings.h" -#include "special-vars.h" - -#include "window-items.h" -#include "formats.h" #include "statusbar.h" -#include "gui-printtext.h" +#include "gui-entry.h" /* how often to redraw lagging time (seconds) */ #define LAG_REFRESH_TIME 10 -/* how often to check for new mail (seconds) */ -#define MAIL_REFRESH_TIME 60 - /* If we haven't been able to check lag for this long, "(??)" is added after the lag */ #define MAX_LAG_UNKNOWN_TIME 30 -static STATUSBAR_REC *mainbar; -static MAIN_WINDOW_REC *mainbar_window; -static int use_colors; - -/* clock */ -static SBAR_ITEM_REC *clock_item; -static int clock_timetag; -static time_t clock_last; - -/* nick */ -static SBAR_ITEM_REC *nick_item; - -/* channel */ -static SBAR_ITEM_REC *window_item; - /* activity */ -static SBAR_ITEM_REC *activity_item; +static GSList *activity_items; static GList *activity_list; -/* more */ -static SBAR_ITEM_REC *more_item; - -/* lag */ -static SBAR_ITEM_REC *lag_item; -static int lag_timetag, lag_min_show; -static time_t lag_last_draw; +static GHashTable *input_entries; -/* mbox counter */ -static SBAR_ITEM_REC *mail_item; -static int mail_timetag, mail_last_count; -static time_t mail_last_mtime = -1; -static off_t mail_last_size = -1; - -/* topic */ -static SBAR_ITEM_REC *topic_item; -static STATUSBAR_REC *topic_bar; - -static void item_default(SBAR_ITEM_REC *item, int get_size_only, - const char *str, const char *data) +static void item_window_active(SBAR_ITEM_REC *item, int get_size_only) { - SERVER_REC *server; - WI_ITEM_REC *wiitem; - char *tmpstr, *tmpstr2; - int len; - - if (active_win == NULL) { - server = NULL; - wiitem = NULL; - } else { - server = active_win->active_server; - wiitem = active_win->active; - } - - /* expand $variables */ - tmpstr = parse_special_string(str, server, wiitem, data, NULL, - PARSE_FLAG_ESCAPE_VARS | - PARSE_FLAG_ESCAPE_THEME); - - /* expand templates */ - str = tmpstr; - tmpstr2 = theme_format_expand_data(current_theme, &str, - 'n', '0' + item->bar->color, - NULL, NULL, - EXPAND_FLAG_ROOT | - EXPAND_FLAG_IGNORE_REPLACES | - EXPAND_FLAG_IGNORE_EMPTY); - g_free(tmpstr); - - /* remove color codes */ - tmpstr = strip_codes(tmpstr2); - g_free(tmpstr2); + WINDOW_REC *window; - if (get_size_only) { - item->min_size = item->max_size = format_get_length(tmpstr); - } else { - if (item->size < item->min_size) { - /* they're forcing us smaller than minimum size.. */ - len = format_real_length(tmpstr, item->size); - tmpstr[len] = '\0'; - } + window = active_win; + if (item->bar->parent_window != NULL) + window = item->bar->parent_window->active; - tmpstr2 = g_strconcat(item->bar->color_string, tmpstr, NULL); - gui_printtext(item->xpos, item->bar->ypos, tmpstr2); - g_free(tmpstr2); + if (window != NULL && window->active != NULL) { + statusbar_item_default_handler(item, get_size_only, + NULL, "", TRUE); + } else if (get_size_only) { + item->min_size = item->max_size = 0; } - g_free(tmpstr); -} - -/* redraw clock */ -static void statusbar_clock(SBAR_ITEM_REC *item, int get_size_only) -{ - item_default(item, get_size_only, "{sb $Z}", ""); } -/* check if we need to redraw clock.. */ -static int statusbar_clock_timeout(void) +static void item_window_empty(SBAR_ITEM_REC *item, int get_size_only) { - struct tm *tm; - time_t t; - int min; - - tm = localtime(&clock_last); - min = tm->tm_min; + WINDOW_REC *window; - t = time(NULL); - tm = localtime(&t); + window = active_win; + if (item->bar->parent_window != NULL) + window = item->bar->parent_window->active; - if (tm->tm_min != min) { - /* minute changed, redraw! */ - clock_last = t; - statusbar_item_redraw(clock_item); + if (window != NULL && window->active == NULL) { + statusbar_item_default_handler(item, get_size_only, + NULL, "", TRUE); + } else if (get_size_only) { + item->min_size = item->max_size = 0; } - return 1; -} - -/* redraw nick */ -static void statusbar_nick(SBAR_ITEM_REC *item, int get_size_only) -{ - item_default(item, get_size_only, - "{sb $cumode$N{sbmode $usermode}{sbaway $A}}", ""); } -static void sig_statusbar_nick_redraw(void) +static void item_lag(SBAR_ITEM_REC *item, int get_size_only) { - statusbar_item_redraw(nick_item); -} + SERVER_REC *server; + GString *str; + int lag_unknown, lag_min_show; + time_t now; -/* redraw window */ -static void statusbar_window(SBAR_ITEM_REC *item, int get_size_only) -{ - if (active_win->active != NULL) { - item_default(item, get_size_only, - "{sb $winref:$T{sbmode $M}}", ""); - } else { - item_default(item, get_size_only, - "{sb $winref{sbservertag $tag}}", ""); + server = active_win == NULL ? NULL : active_win->active_server; + if (server == NULL || server->lag_last_check == 0) { + /* No lag information */ + if (get_size_only) + item->min_size = item->max_size = 0; + return; } -} -static void sig_statusbar_window_redraw(void) -{ - statusbar_item_redraw(window_item); -} + now = time(NULL); + str = g_string_new(NULL); -static void sig_statusbar_window_redraw_window(WINDOW_REC *window) -{ - if (is_window_visible(window)) - statusbar_item_redraw(window_item); -} + /* FIXME: ugly ugly.. */ + if (server->lag_sent == 0 || now-server->lag_sent < 5) { + lag_unknown = now-server->lag_last_check > + MAX_LAG_UNKNOWN_TIME+settings_get_int("lag_check_time"); + lag_min_show = settings_get_int("lag_min_show"); -static void sig_statusbar_window_redraw_window_item(WI_ITEM_REC *item) -{ - WINDOW_REC *window; + if (lag_min_show < 0 || (server->lag < lag_min_show && !lag_unknown)) { + /* small lag, don't display */ + } else { + g_string_sprintfa(str, "%d.%02d", server->lag/1000, + (server->lag % 1000)/10); + if (lag_unknown) + g_string_append(str, " (?""?)"); + } + } else { + /* big lag, still waiting .. */ + g_string_sprintfa(str, "%ld (?""?)", + (long) (now-server->lag_sent)); + } - window = window_item_window(item); - if (window->active == item && is_window_visible(window)) - statusbar_item_redraw(window_item); + if (str->len != 0) { + statusbar_item_default_handler(item, get_size_only, + NULL, str->str, TRUE); + } else { + if (get_size_only) + item->min_size = item->max_size = 0; + } + + g_string_free(str, TRUE); } static char *get_activity_list(int normal, int hilight) @@ -245,31 +165,21 @@ static char *get_activity_list(int normal, int hilight) /* redraw activity, FIXME: if we didn't get enough size, this gets buggy. At least "Det:" isn't printed properly. also we should rearrange the act list so that the highest priority items comes first. */ -static void statusbar_activity(SBAR_ITEM_REC *item, int get_size_only) +static void item_act(SBAR_ITEM_REC *item, int get_size_only) { - char *actlist, *detlist, *data; + char *actlist; - if (use_colors) { - actlist = get_activity_list(TRUE, TRUE); - detlist = NULL; - } else { - actlist = get_activity_list(TRUE, FALSE); - detlist = get_activity_list(FALSE, TRUE); - } - - if (actlist == NULL && detlist == NULL) { + actlist = get_activity_list(TRUE, TRUE); + if (actlist == NULL) { if (get_size_only) item->min_size = item->max_size = 0; return; } - data = g_strconcat("{sbact ", actlist != NULL ? actlist : "", - " ", detlist != NULL ? detlist : "", "}", NULL); - item_default(item, get_size_only, data, ""); - g_free(data); + statusbar_item_default_handler(item, get_size_only, + NULL, actlist, FALSE); g_free_not_null(actlist); - g_free_not_null(detlist); } static void sig_statusbar_activity_hilight(WINDOW_REC *window, gpointer oldlevel) @@ -285,7 +195,7 @@ static void sig_statusbar_activity_hilight(WINDOW_REC *window, gpointer oldlevel activity_list = g_list_remove(activity_list, window); if (window->data_level != 0) activity_list = g_list_prepend(activity_list, window); - statusbar_item_redraw(activity_item); + statusbar_items_redraw(activity_items); return; } @@ -294,12 +204,12 @@ static void sig_statusbar_activity_hilight(WINDOW_REC *window, gpointer oldlevel if (window->data_level == 0) { /* remove from activity list */ activity_list = g_list_remove(activity_list, window); - statusbar_item_redraw(activity_item); + statusbar_items_redraw(activity_items); } else if (window->data_level != GPOINTER_TO_INT(oldlevel) || window->hilight_color != 0) { /* different level as last time (or maybe different hilight color?), just redraw it. */ - statusbar_item_redraw(activity_item); + statusbar_items_redraw(activity_items); } return; } @@ -321,7 +231,7 @@ static void sig_statusbar_activity_hilight(WINDOW_REC *window, gpointer oldlevel if (tmp == NULL) activity_list = g_list_append(activity_list, window); - statusbar_item_redraw(activity_item); + statusbar_items_redraw(activity_items); } static void sig_statusbar_activity_window_destroyed(WINDOW_REC *window) @@ -330,444 +240,97 @@ static void sig_statusbar_activity_window_destroyed(WINDOW_REC *window) if (g_list_find(activity_list, window) != NULL) activity_list = g_list_remove(activity_list, window); - statusbar_item_redraw(activity_item); + statusbar_items_redraw(activity_items); } static void sig_statusbar_activity_updated(void) { - statusbar_item_redraw(activity_item); + statusbar_items_redraw(activity_items); } -/* redraw -- more -- */ -static void statusbar_more(SBAR_ITEM_REC *item, int get_size_only) +static void item_more(SBAR_ITEM_REC *item, int get_size_only) { - item_default(item, get_size_only, "{sbmore}", ""); } -static void sig_statusbar_more_check_remove(WINDOW_REC *window) +static void item_input(SBAR_ITEM_REC *item, int get_size_only) { - g_return_if_fail(window != NULL); + GUI_ENTRY_REC *rec; - if (!is_window_visible(window)) - return; - - if (more_item != NULL && WINDOW_GUI(window)->view->bottom) { - statusbar_item_remove(more_item); - more_item = NULL; - } -} - -static void sig_statusbar_more_check(WINDOW_REC *window) -{ - if (window == NULL || !is_window_visible(window)) - return; - - if (!WINDOW_GUI(window)->view->bottom) { - if (more_item == NULL) { - more_item = statusbar_item_create(mainbar, SBAR_PRIORITY_LOW, FALSE, statusbar_more); - statusbar_redraw(mainbar); - } - } else if (more_item != NULL) { - statusbar_item_remove(more_item); - more_item = NULL; - } -} - -static void statusbar_lag(SBAR_ITEM_REC *item, int get_size_only) -{ - SERVER_REC *server; - GString *str; - int lag_unknown; - time_t now; - - server = active_win == NULL ? NULL : active_win->active_server; - if (server == NULL || server->lag_last_check == 0) { - /* No lag information */ - if (get_size_only) - item->min_size = item->max_size = 0; - return; + if (get_size_only) { + item->min_size = 2+screen_width/10; + item->max_size = screen_width; + return; } - now = time(NULL); - str = g_string_new(NULL); - - /* FIXME: ugly ugly.. */ - if (server->lag_sent == 0 || now-server->lag_sent < 5) { - lag_unknown = now-server->lag_last_check > - MAX_LAG_UNKNOWN_TIME+settings_get_int("lag_check_time"); - - if (lag_min_show < 0 || (server->lag < lag_min_show && !lag_unknown)) { - /* small lag, don't display */ - } else { - g_string_sprintfa(str, "%d.%02d", server->lag/1000, - (server->lag % 1000)/10); - if (lag_unknown) - g_string_append(str, " (?""?)"); - } + rec = g_hash_table_lookup(input_entries, item); + if (rec == NULL) { + rec = gui_entry_create(item->xpos, item->bar->real_ypos, + item->size); + if (active_entry == NULL) + gui_entry_set_active(rec); + g_hash_table_insert(input_entries, item, rec); } else { - /* big lag, still waiting .. */ - g_string_sprintfa(str, "%ld (?""?)", - (long) (now-server->lag_sent)); - } - - item_default(item, get_size_only, "{sblag $0-}", str->str); - - g_string_free(str, TRUE); -} - -static void sig_statusbar_lag_redraw(void) -{ - statusbar_item_redraw(lag_item); -} - -static int statusbar_lag_timeout(void) -{ - /* refresh statusbar every 10 seconds */ - if (time(NULL)-lag_last_draw < LAG_REFRESH_TIME) - return 1; - - statusbar_item_redraw(lag_item); - return 1; -} - -/* FIXME: this isn't very good.. it handles only mbox mailboxes. - this whole mail feature should really be in it's own module with lots - of other mail formats supported and people who don't want to use it - wouldn't need to.. */ -static int get_mail_count(void) -{ - struct stat statbuf; - FILE *f; - char str[512], *fname; - int count; - - fname = g_getenv("MAIL"); - if (fname == NULL) return 0; - - if (stat(fname, &statbuf) != 0) { - mail_last_mtime = -1; - mail_last_size = -1; - mail_last_count = 0; - return 0; - } - - if (statbuf.st_mtime == mail_last_mtime && - statbuf.st_size == mail_last_size) - return mail_last_count; - mail_last_mtime = statbuf.st_mtime; - mail_last_size = statbuf.st_size; - - f = fopen(fname, "r"); - if (f == NULL) { - mail_last_count = 0; - return 0; - } - - count = 0; - while (fgets(str, sizeof(str), f) != NULL) { - if (strncmp(str, "From ", 5) == 0) - count++; - if (strncmp(str, "Subject: ", 9) == 0 && - strstr(str, "FOLDER INTERNAL DATA")) { - /* don't count these. */ - count--; - } - } - - fclose(f); - - if (mail_last_count != count) - signal_emit("mail counter", 0); - - mail_last_count = count; - return count; -} - -static void statusbar_mail(SBAR_ITEM_REC *item, int get_size_only) -{ - char countstr[MAX_INT_STRLEN]; - int mail_count; - - mail_count = settings_get_bool("mail_counter") ? get_mail_count() : 0; - - if (mail_count <= 0) { - if (get_size_only) - item->min_size = item->max_size = 0; - return; - } - - ltoa(countstr, mail_count); - item_default(item, get_size_only, "{sbmail $0-}", countstr); -} - -static int statusbar_mail_timeout(void) -{ - statusbar_item_redraw(mail_item); - return 1; -} - -static void statusbar_topic(SBAR_ITEM_REC *item, int get_size_only) -{ - item_default(item, get_size_only, "$topic", ""); -} - -static void sig_statusbar_topic_redraw(void) -{ - if (topic_item != NULL) statusbar_item_redraw(topic_item); -} - -static void sig_sidebars_redraw(void) -{ - GSList *tmp; - - for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { - MAIN_WINDOW_REC *rec = tmp->data; - - if (rec->statusbar_window_item != NULL) - statusbar_item_redraw(rec->statusbar_window_item); + gui_entry_move(rec, item->xpos, item->bar->real_ypos, + item->size); + gui_entry_redraw(rec); /* FIXME: this is only necessary with ^L.. */ } } -static void topicbar_create(void) +static void sig_statusbar_item_created(SBAR_ITEM_REC *item) { - if (topic_bar != NULL) - return; - - topic_bar = statusbar_create(STATUSBAR_POS_UP, 0); - topic_item = statusbar_item_create(topic_bar, SBAR_PRIORITY_NORMAL, FALSE, statusbar_topic); - topic_item->max_size = TRUE; - statusbar_redraw(topic_bar); - - signal_add("window changed", (SIGNAL_FUNC) sig_statusbar_topic_redraw); - signal_add("window item changed", (SIGNAL_FUNC) sig_statusbar_topic_redraw); - signal_add("channel topic changed", (SIGNAL_FUNC) sig_statusbar_topic_redraw); - signal_add("query address changed", (SIGNAL_FUNC) sig_statusbar_topic_redraw); + if (item->func == item_act) + activity_items = g_slist_prepend(activity_items, item); } -static void topicbar_destroy(void) +static void sig_statusbar_item_destroyed(SBAR_ITEM_REC *item) { - if (topic_bar == NULL) - return; + if (item->func == item_act) + activity_items = g_slist_remove(activity_items, item); + else { + GUI_ENTRY_REC *rec; - statusbar_destroy(topic_bar); - topic_item = NULL; - topic_bar = NULL; - - signal_remove("window changed", (SIGNAL_FUNC) sig_statusbar_topic_redraw); - signal_remove("window item changed", (SIGNAL_FUNC) sig_statusbar_topic_redraw); - signal_remove("channel topic changed", (SIGNAL_FUNC) sig_statusbar_topic_redraw); - signal_remove("query address changed", (SIGNAL_FUNC) sig_statusbar_topic_redraw); -} - -static void mainbar_remove_items(void) -{ - statusbar_item_remove(clock_item); - statusbar_item_remove(nick_item); - statusbar_item_remove(window_item); - statusbar_item_remove(mail_item); - statusbar_item_remove(lag_item); - statusbar_item_remove(activity_item); -} - -static void mainbar_add_items(MAIN_WINDOW_REC *window) -{ - mainbar = window->statusbar; - mainbar_window = window; - - clock_item = statusbar_item_create(mainbar, SBAR_PRIORITY_HIGH, FALSE, statusbar_clock); - nick_item = statusbar_item_create(mainbar, SBAR_PRIORITY_NORMAL, FALSE, statusbar_nick); - window_item = statusbar_item_create(mainbar, SBAR_PRIORITY_NORMAL, FALSE, statusbar_window); - mail_item = statusbar_item_create(mainbar, SBAR_PRIORITY_LOW, FALSE, statusbar_mail); - lag_item = statusbar_item_create(mainbar, SBAR_PRIORITY_LOW, FALSE, statusbar_lag); - activity_item = statusbar_item_create(mainbar, SBAR_PRIORITY_HIGH, FALSE, statusbar_activity); -} - -static void sidebar_add_items(MAIN_WINDOW_REC *window) -{ - window->statusbar_window_item = - statusbar_item_create(window->statusbar, SBAR_PRIORITY_NORMAL, FALSE, statusbar_window); -} - -static void sidebar_remove_items(MAIN_WINDOW_REC *window) -{ - if (window->statusbar_window_item != NULL) { - statusbar_item_remove(window->statusbar_window_item); - window->statusbar_window_item = NULL; + rec = g_hash_table_lookup(input_entries, item); + if (rec != NULL) gui_entry_destroy(rec); } } -static void sig_mainwindow_created(MAIN_WINDOW_REC *window) -{ - window->statusbar = - statusbar_create(STATUSBAR_POS_MIDDLE, - window->first_line+window->height); - ((STATUSBAR_REC *) window->statusbar)->window = window; - sidebar_add_items(window); -} - -static void sig_mainwindow_destroyed(MAIN_WINDOW_REC *window) -{ - if (window == mainbar_window) { - statusbar_destroy(mainbar); - window->statusbar = NULL; - - mainbar = NULL; - mainbar_window = NULL; - } - - if (window->statusbar != NULL) - statusbar_destroy(window->statusbar); -} - -static void sig_main_statusbar_changed(WINDOW_REC *window) -{ - MAIN_WINDOW_REC *parent; - - if (window == NULL) - return; - - parent = WINDOW_GUI(window)->parent; - if (mainbar == parent->statusbar) - return; - - if (mainbar != NULL) { - mainbar_remove_items(); - sidebar_add_items(mainbar_window); - } - sidebar_remove_items(parent); - mainbar_add_items(parent); -} - -static void read_settings(void) -{ - use_colors = settings_get_bool("colors") && screen_has_colors(); - if (settings_get_bool("topicbar")) - topicbar_create(); - else - topicbar_destroy(); - - lag_min_show = settings_get_int("lag_min_show")*10; - statusbar_redraw(NULL); -} - void statusbar_items_init(void) { - GSList *tmp; - settings_add_int("misc", "lag_min_show", 100); - settings_add_bool("lookandfeel", "topicbar", TRUE); settings_add_bool("lookandfeel", "actlist_moves", FALSE); - settings_add_bool("misc", "mail_counter", TRUE); - - /* clock */ - clock_timetag = g_timeout_add(1000, (GSourceFunc) statusbar_clock_timeout, NULL); - - /* nick */ - signal_add("server connected", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_add("channel wholist", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_add("window changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_add("window item changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_add("nick mode changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_add("user mode changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_add("server nick changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_add("window server changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_add("away mode changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - - /* channel */ - signal_add("window changed", (SIGNAL_FUNC) sig_statusbar_window_redraw); - signal_add("window item changed", (SIGNAL_FUNC) sig_statusbar_window_redraw_window); - signal_add("channel mode changed", (SIGNAL_FUNC) sig_statusbar_window_redraw_window_item); - signal_add("window server changed", (SIGNAL_FUNC) sig_statusbar_window_redraw_window); - signal_add("window refnum changed", (SIGNAL_FUNC) sig_statusbar_window_redraw_window); - - /* activity */ + + statusbar_item_register("window", NULL, item_window_active); + statusbar_item_register("window_empty", NULL, item_window_empty); + statusbar_item_register("prompt", NULL, item_window_active); + statusbar_item_register("prompt_empty", NULL, item_window_empty); + statusbar_item_register("lag", NULL, item_lag); + statusbar_item_register("act", NULL, item_act); + statusbar_item_register("more", NULL, item_more); + statusbar_item_register("input", NULL, item_input); + + input_entries = g_hash_table_new((GHashFunc) g_direct_hash, + (GCompareFunc) g_direct_equal); + activity_list = NULL; signal_add("window activity", (SIGNAL_FUNC) sig_statusbar_activity_hilight); signal_add("window destroyed", (SIGNAL_FUNC) sig_statusbar_activity_window_destroyed); signal_add("window refnum changed", (SIGNAL_FUNC) sig_statusbar_activity_updated); - /* more */ - more_item = NULL; - signal_add("gui page scrolled", (SIGNAL_FUNC) sig_statusbar_more_check_remove); - signal_add("window changed", (SIGNAL_FUNC) sig_statusbar_more_check); - signal_add_last("gui print text finished", (SIGNAL_FUNC) sig_statusbar_more_check); - - /* lag */ - lag_timetag = g_timeout_add(1000*LAG_REFRESH_TIME, (GSourceFunc) statusbar_lag_timeout, NULL); - signal_add("server lag", (SIGNAL_FUNC) sig_statusbar_lag_redraw); - signal_add("window server changed", (SIGNAL_FUNC) sig_statusbar_lag_redraw); - - /* mail */ - mail_timetag = g_timeout_add(1000*MAIL_REFRESH_TIME, (GSourceFunc) statusbar_mail_timeout, NULL); - - /* topic */ - topic_item = NULL; topic_bar = NULL; - signal_add("setup changed", (SIGNAL_FUNC) read_settings); - - read_settings(); - statusbar_redraw(NULL); - - /* middle bars */ - signal_add("mainwindow created", (SIGNAL_FUNC) sig_mainwindow_created); - signal_add("mainwindow destroyed", (SIGNAL_FUNC) sig_mainwindow_destroyed); - signal_add("window changed", (SIGNAL_FUNC) sig_main_statusbar_changed); - signal_add("window refnum changed", (SIGNAL_FUNC) sig_sidebars_redraw); - - /* add statusbars to existing windows */ - for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) - sig_mainwindow_created(tmp->data); - sig_main_statusbar_changed(active_win); + signal_add("statusbar item created", (SIGNAL_FUNC) sig_statusbar_item_created); + signal_add("statusbar item destroyed", (SIGNAL_FUNC) sig_statusbar_item_destroyed); } void statusbar_items_deinit(void) { - /* clock */ - g_source_remove(clock_timetag); - - /* nick */ - signal_remove("server connected", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_remove("channel wholist", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_remove("window changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_remove("window item changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_remove("nick mode changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_remove("user mode changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_remove("server nick changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_remove("window server changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - signal_remove("away mode changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); - - /* channel */ - signal_remove("window changed", (SIGNAL_FUNC) sig_statusbar_window_redraw); - signal_remove("window item changed", (SIGNAL_FUNC) sig_statusbar_window_redraw_window); - signal_remove("channel mode changed", (SIGNAL_FUNC) sig_statusbar_window_redraw_window_item); - signal_remove("window server changed", (SIGNAL_FUNC) sig_statusbar_window_redraw_window); - signal_remove("window refnum changed", (SIGNAL_FUNC) sig_statusbar_window_redraw_window); - - /* activity */ + g_hash_table_destroy(input_entries); + signal_remove("window activity", (SIGNAL_FUNC) sig_statusbar_activity_hilight); signal_remove("window destroyed", (SIGNAL_FUNC) sig_statusbar_activity_window_destroyed); signal_remove("window refnum changed", (SIGNAL_FUNC) sig_statusbar_activity_updated); - g_list_free(activity_list); - - /* more */ - signal_remove("gui page scrolled", (SIGNAL_FUNC) sig_statusbar_more_check_remove); - signal_remove("window changed", (SIGNAL_FUNC) sig_statusbar_more_check); - signal_remove("gui print text finished", (SIGNAL_FUNC) sig_statusbar_more_check); - /* lag */ - g_source_remove(lag_timetag); - signal_remove("server lag", (SIGNAL_FUNC) sig_statusbar_lag_redraw); - signal_remove("window server changed", (SIGNAL_FUNC) sig_statusbar_lag_redraw); - - /* mail */ - g_source_remove(mail_timetag); - - /* topic */ - topicbar_destroy(); - signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + g_list_free(activity_list); + activity_list = NULL; - /* middle bars */ - signal_remove("mainwindow created", (SIGNAL_FUNC) sig_mainwindow_created); - signal_remove("mainwindow destroyed", (SIGNAL_FUNC) sig_mainwindow_destroyed); - signal_remove("window changed", (SIGNAL_FUNC) sig_main_statusbar_changed); - signal_remove("window refnum changed", (SIGNAL_FUNC) sig_sidebars_redraw); + signal_remove("statusbar item created", (SIGNAL_FUNC) sig_statusbar_item_created); + signal_remove("statusbar item destroyed", (SIGNAL_FUNC) sig_statusbar_item_destroyed); } diff --git a/src/fe-text/statusbar-items.h b/src/fe-text/statusbar-items.h new file mode 100644 index 00000000..29e0b783 --- /dev/null +++ b/src/fe-text/statusbar-items.h @@ -0,0 +1,7 @@ +#ifndef __STATUSBAR_ITEMS_H +#define __STATUSBAR_ITEMS_H + +void statusbar_items_init(void); +void statusbar_items_deinit(void); + +#endif diff --git a/src/fe-text/statusbar.c b/src/fe-text/statusbar.c index b8de3ff6..8f12e3e4 100644 --- a/src/fe-text/statusbar.c +++ b/src/fe-text/statusbar.c @@ -20,32 +20,123 @@ #include "module.h" #include "signals.h" +#include "expandos.h" +#include "special-vars.h" #include "themes.h" #include "statusbar.h" +#include "statusbar-config.h" +#include "statusbar-items.h" #include "gui-windows.h" +#include "gui-printtext.h" -static int backs[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; /* FIXME: should be in some more generic place.. */ +GSList *statusbar_groups; +STATUSBAR_GROUP_REC *active_statusbar_group; -void statusbar_items_init(void); -void statusbar_items_deinit(void); +/* + sbar_item_defs: char *name => char *value + sbar_item_funcs: char *name => STATUSBAR_FUNC func + sbar_signal_items: int signal_id => GSList *(SBAR_ITEM_REC *items) + sbar_item_signals: SBAR_ITEM_REC *item => GSList *(int *signal_ids) + +*/ +static GHashTable *sbar_item_defs, *sbar_item_funcs; +static GHashTable *sbar_signal_items, *sbar_item_signals; + +void statusbar_item_register(const char *name, const char *value, + STATUSBAR_FUNC func) +{ + gpointer hkey, hvalue; + + if (value != NULL) { + if (g_hash_table_lookup_extended(sbar_item_defs, + name, &hkey, &hvalue)) { + g_hash_table_remove(sbar_item_defs, name); + g_free(hkey); + g_free(hvalue); + } + g_hash_table_insert(sbar_item_defs, + g_strdup(name), g_strdup(value)); + } + + if (func != NULL) { + if (g_hash_table_lookup(sbar_item_funcs, name) == NULL) { + g_hash_table_insert(sbar_item_funcs, + g_strdup(name), func); + } + } +} + +void statusbar_item_unregister(const char *name) +{ + gpointer key, value; + + if (g_hash_table_lookup_extended(sbar_item_defs, + name, &key, &value)) { + g_hash_table_remove(sbar_item_defs, key); + g_free(key); + g_free(value); + } + + if (g_hash_table_lookup_extended(sbar_item_funcs, + name, &key, &value)) { + g_hash_table_remove(sbar_item_funcs, key); + g_free(key); + } +} + +STATUSBAR_GROUP_REC *statusbar_group_create(const char *name) +{ + STATUSBAR_GROUP_REC *rec; + + rec = g_new0(STATUSBAR_GROUP_REC, 1); + rec->name = g_strdup(name); + + statusbar_groups = g_slist_append(statusbar_groups, rec); + return rec; +} + +void statusbar_group_destroy(STATUSBAR_GROUP_REC *rec) +{ + statusbar_groups = g_slist_remove(statusbar_groups, rec); + + while (rec->bars != NULL) + statusbar_destroy(rec->bars->data); + while (rec->config_bars != NULL) + statusbar_config_destroy(rec, rec->config_bars->data); -static GSList *statusbars; -static int sbar_uppest, sbar_lowest, sbars_up, sbars_down; + g_free(rec->name); + g_free(rec); +} -static void statusbar_item_destroy(SBAR_ITEM_REC *rec) +STATUSBAR_GROUP_REC *statusbar_group_find(const char *name) { - rec->bar->items = g_slist_remove(rec->bar->items, rec); - g_free(rec); + GSList *tmp; + + for (tmp = statusbar_groups; tmp != NULL; tmp = tmp->next) { + STATUSBAR_GROUP_REC *rec = tmp->data; + + if (strcmp(rec->name, name) == 0) + return rec; + } + + return NULL; } static int sbar_item_cmp(SBAR_ITEM_REC *item1, SBAR_ITEM_REC *item2) { - return item1->priority == item2->priority ? 0 : - item1->priority < item2->priority ? -1 : 1; + return item1->config->priority == item2->config->priority ? 0 : + item1->config->priority < item2->config->priority ? -1 : 1; +} + +static int sbar_cmp_position(STATUSBAR_REC *bar1, STATUSBAR_REC *bar2) +{ + return bar1->config->position < bar2->config->position ? -1 : 1; } +/* Shink all items in statusbar to their minimum requested size. + The items list should be sorted by priority, highest first. */ static int statusbar_shrink_to_min(GSList *items, int size, int max_width) { GSList *tmp; @@ -71,6 +162,9 @@ static int statusbar_shrink_to_min(GSList *items, int size, int max_width) return size; } +/* shink the items in statusbar, even if their size gets smaller than + their minimum requested size. The items list should be sorted by + priority, highest first. */ static void statusbar_shrink_forced(GSList *items, int size, int max_width) { GSList *tmp; @@ -80,7 +174,7 @@ static void statusbar_shrink_forced(GSList *items, int size, int max_width) if (size-rec->size > max_width) { /* remove the whole item */ - size -= rec->size+1; /* +1 == the marginal */ + size -= rec->size; rec->size = 0; } else { /* shrink the item */ @@ -90,14 +184,14 @@ static void statusbar_shrink_forced(GSList *items, int size, int max_width) } } -static void statusbar_get_sizes(STATUSBAR_REC *bar, int max_width) +static void statusbar_resize_items(STATUSBAR_REC *bar, int max_width) { GSList *tmp, *prior_sorted; int width; /* first give items their max. size */ prior_sorted = NULL; - width = -1; /* -1 because of the marginals */ + width = 0; for (tmp = bar->items; tmp != NULL; tmp = tmp->next) { SBAR_ITEM_REC *rec = tmp->data; @@ -105,8 +199,7 @@ static void statusbar_get_sizes(STATUSBAR_REC *bar, int max_width) rec->size = rec->max_size; if (rec->size > 0) { - /* +1 == marginal between items */ - width += rec->max_size+1; + width += rec->max_size; prior_sorted = g_slist_insert_sorted(prior_sorted, rec, (GCompareFunc) @@ -131,36 +224,36 @@ static void statusbar_get_sizes(STATUSBAR_REC *bar, int max_width) g_slist_free(prior_sorted); } -static void statusbar_redraw_line(STATUSBAR_REC *bar) +static void statusbar_redraw_items(STATUSBAR_REC *bar) { WINDOW_REC *old_active_win; GSList *tmp; int xpos, rxpos; old_active_win = active_win; - if (bar->window != NULL) - active_win = bar->window->active; + if (bar->parent_window != NULL) + active_win = bar->parent_window->active; - statusbar_get_sizes(bar, screen_width-2); + statusbar_resize_items(bar, screen_width); - xpos = 1; + xpos = 0; for (tmp = bar->items; tmp != NULL; tmp = tmp->next) { SBAR_ITEM_REC *rec = tmp->data; - if (!rec->right_justify && rec->size > 0) { + if (!rec->config->right_alignment && rec->size > 0) { rec->xpos = xpos; - xpos += rec->size+1; + xpos += rec->size; rec->func(rec, FALSE); } } - rxpos = screen_width-1; + rxpos = screen_width; for (tmp = bar->items; tmp != NULL; tmp = tmp->next) { SBAR_ITEM_REC *rec = tmp->data; - if (rec->right_justify && rec->size > 0) { - rxpos -= rec->size+1; - rec->xpos = rxpos+1; + if (rec->config->right_alignment && rec->size > 0) { + rxpos -= rec->size; + rec->xpos = rxpos; rec->func(rec, FALSE); } } @@ -168,14 +261,7 @@ static void statusbar_redraw_line(STATUSBAR_REC *bar) active_win = old_active_win; } -static void statusbar_redraw_all(void) -{ - screen_refresh_freeze(); - g_slist_foreach(statusbars, (GFunc) statusbar_redraw, NULL); - screen_refresh_thaw(); -} - -STATUSBAR_REC *statusbar_find(int pos, int line) +/*STATUSBAR_REC *statusbar_find(int pos, int line) { GSList *tmp; @@ -187,22 +273,27 @@ STATUSBAR_REC *statusbar_find(int pos, int line) } return NULL; -} +}*/ void statusbar_redraw(STATUSBAR_REC *bar) { + char *str; + if (bar == NULL) { - statusbar_redraw_all(); + if (active_statusbar_group != NULL) { + screen_refresh_freeze(); + g_slist_foreach(active_statusbar_group->bars, + (GFunc) statusbar_redraw, NULL); + screen_refresh_thaw(); + } return; } - screen_set_bg(screen_root, backs[bar->color] << 4); - screen_move(screen_root, 0, bar->ypos); - screen_clrtoeol(screen_root); - screen_set_bg(screen_root, 0); - - statusbar_redraw_line(bar); + str = g_strconcat(bar->color, "%>", NULL); + gui_printtext(0, bar->real_ypos, str); + g_free(str); + statusbar_redraw_items(bar); screen_refresh(NULL); } @@ -213,13 +304,17 @@ void statusbar_item_redraw(SBAR_ITEM_REC *item) g_return_if_fail(item != NULL); old_active_win = active_win; - if (item->bar->window != NULL) - active_win = item->bar->window->active; + if (item->bar->parent_window != NULL) + active_win = item->bar->parent_window->active; item->func(item, TRUE); - if (item->max_size != item->size) + if (item->max_size != item->size) { + /* item wants a new size - we'll need to redraw + the statusbar to see if this is allowed */ + /*FIXME:fprintf(stderr, "%s resizes & redraws whole statusbar", item->config->name);*/ statusbar_redraw(item->bar); - else { + } else { + /*FIXME:fprintf(stderr, "%s redrawing", item->config->name);*/ item->func(item, FALSE); screen_refresh(NULL); } @@ -227,154 +322,630 @@ void statusbar_item_redraw(SBAR_ITEM_REC *item) active_win = old_active_win; } -static int get_last_bg(const char *str) +static void statusbar_recalc_ypos(STATUSBAR_REC *bar) { - int last = -1; + GSList *tmp, *bar_group; + int ypos; - while (*str != '\0') { - if (*str == '%' && str[1] != '\0') { - str++; - if (*str >= '0' && *str <= '7') - last = *str-'0'; + /* get list of statusbars with same type and placement, + sorted by position */ + bar_group = NULL; + tmp = bar->config->type == STATUSBAR_TYPE_ROOT ? bar->group->bars : + bar->parent_window->statusbars; + + for (; tmp != NULL; tmp = tmp->next) { + STATUSBAR_REC *rec = tmp->data; + + if (rec->config->type == bar->config->type && + rec->config->placement == bar->config->placement) { + bar_group = g_slist_insert_sorted(bar_group, rec, + (GCompareFunc) + sbar_cmp_position); } - str++; } - return last; + if (bar_group == NULL) { + /* we just destroyed the last statusbar in this + type/placement group */ + return; + } + + /* get the Y-position for the first statusbar */ + if (bar->config->type == STATUSBAR_TYPE_ROOT) { + ypos = bar->config->placement == STATUSBAR_TOP ? 0 : + screen_height - g_slist_length(bar_group); + } else { + ypos = bar->config->placement == STATUSBAR_TOP ? + bar->parent_window->first_line : + bar->parent_window->last_line - + (g_slist_length(bar_group)-1); + } + + /* set the Y-positions */ + while (bar_group != NULL) { + bar = bar_group->data; + + if (bar->real_ypos != ypos) { + bar->real_ypos = ypos; + statusbar_redraw(bar); + } + + ypos++; + bar_group = g_slist_remove(bar_group, bar_group->data); + } } -/* ypos is used only when pos == STATUSBAR_POS_MIDDLE */ -STATUSBAR_REC *statusbar_create(int pos, int ypos) +STATUSBAR_REC *statusbar_create(STATUSBAR_GROUP_REC *group, + STATUSBAR_CONFIG_REC *config, + MAIN_WINDOW_REC *parent_window) { - STATUSBAR_REC *rec; - char *str; + STATUSBAR_REC *bar; + THEME_REC *theme; + GSList *tmp; + char *name, *value; + + g_return_val_if_fail(group != NULL, NULL); + g_return_val_if_fail(config != NULL, NULL); + g_return_val_if_fail(config->type != STATUSBAR_TYPE_WINDOW || + parent_window != NULL, NULL); + + bar = g_new0(STATUSBAR_REC, 1); + group->bars = g_slist_append(group->bars, bar); + + bar->group = group; + + bar->config = config; + bar->parent_window = parent_window; + + if (config->type == STATUSBAR_TYPE_ROOT) { + /* top/bottom of the screen */ + mainwindows_reserve_lines(config->placement == STATUSBAR_TOP, + config->placement == STATUSBAR_BOTTOM); + theme = current_theme; + } else { + /* top/bottom of the window */ + parent_window->statusbars = + g_slist_append(parent_window->statusbars, bar); + mainwindow_set_statusbar_lines(parent_window, + config->placement == STATUSBAR_TOP, + config->placement == STATUSBAR_BOTTOM); + theme = parent_window != NULL && parent_window->active != NULL && + parent_window->active->theme != NULL ? + parent_window->active->theme : current_theme; + } - rec = g_new0(STATUSBAR_REC, 1); - statusbars = g_slist_append(statusbars, rec); + /* get background color from sb_background abstract */ + name = g_strdup_printf("{sb_%s_bg}", config->name); + value = theme_format_expand(theme, name); + g_free(name); - rec->pos = pos; - rec->line = pos == STATUSBAR_POS_MIDDLE ? ypos : - mainwindows_reserve_lines(1, pos == STATUSBAR_POS_UP); - rec->ypos = pos == STATUSBAR_POS_MIDDLE ? ypos : - pos == STATUSBAR_POS_UP ? rec->line : - screen_height-1-rec->line; + if (*value == '\0') { + /* try with the statusbar group name */ + g_free(value); - /* get background color from sb_background abstract */ - str = theme_format_expand(current_theme, "{sb_background}"); - if (str == NULL) str = g_strdup("%n%8"); - rec->color_string = g_strconcat("%n", str, NULL); - g_free(str); + name = g_strdup_printf("{sb_%s_bg}", group->name); + value = theme_format_expand(theme, name); + g_free(name); + } - rec->color = get_last_bg(rec->color_string); - if (rec->color < 0) rec->color = current_theme->default_real_color; + if (*value == '\0') { + g_free(value); + value = g_strdup("%8"); + } + bar->color = g_strconcat("%n", value, NULL); + g_free(value); + + statusbar_recalc_ypos(bar); + signal_emit("statusbar created", 1, bar); - if (pos == STATUSBAR_POS_UP) { - if (sbars_up == 0) sbar_uppest = rec->line; - sbars_up++; - rec->line -= sbar_uppest; - } else if (pos == STATUSBAR_POS_DOWN) { - if (sbars_down == 0) sbar_lowest = rec->line; - sbars_down++; - rec->line -= sbar_lowest; + /* create the items to statusbar */ + for (tmp = config->items; tmp != NULL; tmp = tmp->next) { + SBAR_ITEM_CONFIG_REC *rec = tmp->data; + + statusbar_item_create(bar, rec); } + return bar; +} - screen_set_bg(screen_root, backs[rec->color] << 4); - screen_move(screen_root, 0, rec->ypos); - screen_clrtoeol(screen_root); - screen_set_bg(screen_root, 0); +void statusbar_destroy(STATUSBAR_REC *bar) +{ + int top; - return rec; + g_return_if_fail(bar != NULL); + + bar->group->bars = g_slist_remove(bar->group->bars, bar); + if (bar->parent_window != NULL) { + bar->parent_window->statusbars = + g_slist_remove(bar->parent_window->statusbars, bar); + } + + signal_emit("statusbar destroyed", 1, bar); + + while (bar->items != NULL) + statusbar_item_destroy(bar->items->data); + + g_free(bar->color); + + if (bar->config->type != STATUSBAR_TYPE_WINDOW || + bar->parent_window != NULL) + statusbar_recalc_ypos(bar); + + top = bar->config->placement == STATUSBAR_TOP; + if (bar->config->type == STATUSBAR_TYPE_ROOT) { + /* top/bottom of the screen */ + mainwindows_reserve_lines(top ? -1 : 0, !top ? -1 : 0); + } else if (bar->parent_window != NULL) { + /* top/bottom of the window */ + mainwindow_set_statusbar_lines(bar->parent_window, + top ? -1 : 0, !top ? -1 : 0); + } + + g_free(bar); } -static void statusbars_pack(int pos, int line) +STATUSBAR_REC *statusbar_find(STATUSBAR_GROUP_REC *group, const char *name, + MAIN_WINDOW_REC *window) { GSList *tmp; - for (tmp = statusbars; tmp != NULL; tmp = tmp->next) { + for (tmp = group->bars; tmp != NULL; tmp = tmp->next) { STATUSBAR_REC *rec = tmp->data; - if (rec->pos == pos && rec->line > line) { - rec->line--; - rec->ypos += (pos == STATUSBAR_POS_UP ? -1 : 1); + if (rec->parent_window == window && + strcmp(rec->config->name, name) == 0) + return rec; + } + + return NULL; +} + +static char *update_statusbar_bg(const char *str, const char *color) +{ + GString *out; + char *ret; + + out = g_string_new(color); + while (*str != '\0') { + if (*str == '%' && str[1] == 'n') { + g_string_append(out, color); + str += 2; + continue; } + + g_string_append_c(out, *str); + str++; } + + ret = out->str; + g_string_free(out, FALSE); + return ret; } -void statusbar_destroy(STATUSBAR_REC *bar) +const char *statusbar_item_get_value(SBAR_ITEM_REC *item) { - g_return_if_fail(bar != NULL); + const char *value; - if (bar->pos != STATUSBAR_POS_MIDDLE) - mainwindows_reserve_lines(-1, bar->pos == STATUSBAR_POS_UP); + value = item->config->value; + if (value == NULL) { + value = g_hash_table_lookup(sbar_item_defs, + item->config->name); + } - if (bar->pos == STATUSBAR_POS_UP) sbars_up--; - if (bar->pos == STATUSBAR_POS_DOWN) sbars_down--; - statusbars = g_slist_remove(statusbars, bar); + return value; +} - while (bar->items != NULL) - statusbar_item_destroy(bar->items->data); +void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only, + const char *str, const char *data, + int escape_vars) +{ + SERVER_REC *server; + WI_ITEM_REC *wiitem; + char *tmpstr, *tmpstr2; + int len; + + if (str == NULL) + str = statusbar_item_get_value(item); + if (str == NULL || *str == '\0') { + item->min_size = item->max_size = 0; + return; + } - if (bar->pos != STATUSBAR_POS_MIDDLE) - statusbars_pack(bar->pos, bar->pos); - g_free(bar->color_string); - g_free(bar); + if (active_win == NULL) { + server = NULL; + wiitem = NULL; + } else { + server = active_win->active_server; + wiitem = active_win->active; + } + + /* expand $variables */ + tmpstr = parse_special_string(str, server, wiitem, data, NULL, + (escape_vars ? PARSE_FLAG_ESCAPE_VARS : 0 ) | + PARSE_FLAG_ESCAPE_THEME); + + /* expand templates */ + str = tmpstr; + tmpstr2 = theme_format_expand_data(current_theme, &str, + 'n', 'n', + NULL, NULL, + EXPAND_FLAG_ROOT | + EXPAND_FLAG_IGNORE_REPLACES | + EXPAND_FLAG_IGNORE_EMPTY); + g_free(tmpstr); + + /* remove color codes (not %formats) */ + tmpstr = strip_codes(tmpstr2); + g_free(tmpstr2); + + if (get_size_only) { + item->min_size = item->max_size = format_get_length(tmpstr); + } else { + if (item->size < item->min_size) { + /* they're forcing us smaller than minimum size.. */ + len = format_real_length(tmpstr, item->size); + tmpstr[len] = '\0'; + } + + tmpstr2 = update_statusbar_bg(tmpstr, item->bar->color); + gui_printtext(item->xpos, item->bar->real_ypos, tmpstr2); + g_free(tmpstr2); + } + g_free(tmpstr); +} - if (!quitting) statusbar_redraw_all(); +static void statusbar_item_default_func(SBAR_ITEM_REC *item, int get_size_only) +{ + statusbar_item_default_handler(item, get_size_only, NULL, "", TRUE); +} + +static void statusbar_update_item(void) +{ + GSList *items; + + items = g_hash_table_lookup(sbar_signal_items, + GINT_TO_POINTER(signal_get_emitted_id())); + while (items != NULL) { + SBAR_ITEM_REC *item = items->data; + + statusbar_item_redraw(item); + items = items->next; + } +} + +static void statusbar_update_server(SERVER_REC *server) +{ + SERVER_REC *item_server; + GSList *items; + + items = g_hash_table_lookup(sbar_signal_items, + GINT_TO_POINTER(signal_get_emitted_id())); + while (items != NULL) { + SBAR_ITEM_REC *item = items->data; + + item_server = item->bar->parent_window != NULL ? + item->bar->parent_window->active->active_server : + active_win->active_server; + + if (item_server == server) + statusbar_item_redraw(item); + + items = items->next; + } +} + +static void statusbar_update_window(WINDOW_REC *window) +{ + WINDOW_REC *item_window; + GSList *items; + + items = g_hash_table_lookup(sbar_signal_items, + GINT_TO_POINTER(signal_get_emitted_id())); + while (items != NULL) { + SBAR_ITEM_REC *item = items->data; + + item_window = item->bar->parent_window != NULL ? + item->bar->parent_window->active : active_win; + + if (item_window == window) + statusbar_item_redraw(item); + + items = items->next; + } +} + +static void statusbar_update_window_item(WI_ITEM_REC *wiitem) +{ + WI_ITEM_REC *item_wi; + GSList *items; + + items = g_hash_table_lookup(sbar_signal_items, + GINT_TO_POINTER(signal_get_emitted_id())); + while (items != NULL) { + SBAR_ITEM_REC *item = items->data; + + item_wi = item->bar->parent_window != NULL ? + item->bar->parent_window->active->active : + active_win->active; + + if (item_wi == wiitem) + statusbar_item_redraw(item); + + items = items->next; + } +} + +static void statusbar_item_default_signals(SBAR_ITEM_REC *item) +{ + SIGNAL_FUNC func; + GSList *list; + const char *value; + void *signal_id; + int *signals, *pos; + + value = statusbar_item_get_value(item); + if (value == NULL) + return; + + signals = special_vars_get_signals(value); + if (signals == NULL) + return; + + for (pos = signals; *pos != -1; pos += 2) { + /* update signal -> item mappings */ + signal_id = GINT_TO_POINTER(*pos); + list = g_hash_table_lookup(sbar_signal_items, signal_id); + if (list == NULL) { + switch (pos[1]) { + case EXPANDO_ARG_NONE: + func = (SIGNAL_FUNC) statusbar_update_item; + break; + case EXPANDO_ARG_SERVER: + func = (SIGNAL_FUNC) statusbar_update_server; + break; + case EXPANDO_ARG_WINDOW: + func = (SIGNAL_FUNC) statusbar_update_window; + break; + case EXPANDO_ARG_WINDOW_ITEM: + func = (SIGNAL_FUNC) statusbar_update_window_item; + break; + default: + func = NULL; + break; + } + if (func != NULL) + signal_add_to_id(MODULE_NAME, 1, *pos, func); + } + + if (g_slist_find(list, item) == NULL) + list = g_slist_append(list, item); + g_hash_table_insert(sbar_signal_items, signal_id, list); + + /* update item -> signal mappings */ + list = g_hash_table_lookup(sbar_item_signals, item); + if (g_slist_find(list, signal_id) == NULL) + list = g_slist_append(list, signal_id); + g_hash_table_insert(sbar_item_signals, item, list); + } + g_free(signals); } SBAR_ITEM_REC *statusbar_item_create(STATUSBAR_REC *bar, - int priority, int right_justify, - STATUSBAR_FUNC func) + SBAR_ITEM_CONFIG_REC *config) { SBAR_ITEM_REC *rec; g_return_val_if_fail(bar != NULL, NULL); - g_return_val_if_fail(func != NULL, NULL); + g_return_val_if_fail(config != NULL, NULL); rec = g_new0(SBAR_ITEM_REC, 1); - rec->bar = bar; bar->items = g_slist_append(bar->items, rec); - rec->priority = priority; - rec->right_justify = right_justify; - rec->func = func; + rec->bar = bar; + rec->config = config; + + rec->func = g_hash_table_lookup(sbar_item_funcs, config->name); + if (rec->func == NULL) + rec->func = statusbar_item_default_func; + statusbar_item_default_signals(rec); + signal_emit("statusbar item created", 1, rec); return rec; } -void statusbar_item_remove(SBAR_ITEM_REC *item) +static void statusbar_signal_remove(int signal_id) +{ + signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_item); + signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_server); + signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_window); + signal_remove_id(signal_id, (SIGNAL_FUNC) statusbar_update_window_item); +} + +static void statusbar_item_remove_signal(SBAR_ITEM_REC *item, int signal_id) { + GSList *list; + + /* update signal -> item hash */ + list = g_hash_table_lookup(sbar_signal_items, + GINT_TO_POINTER(signal_id)); + list = g_slist_remove(list, item); + if (list != NULL) { + g_hash_table_insert(sbar_signal_items, + GINT_TO_POINTER(signal_id), list); + } else { + g_hash_table_remove(sbar_signal_items, + GINT_TO_POINTER(signal_id)); + statusbar_signal_remove(signal_id); + } +} + +void statusbar_item_destroy(SBAR_ITEM_REC *item) +{ + GSList *list; + g_return_if_fail(item != NULL); - statusbar_item_destroy(item); - if (!quitting) statusbar_redraw_all(); + item->bar->items = g_slist_remove(item->bar->items, item); + signal_emit("statusbar item destroyed", 1, item); + + list = g_hash_table_lookup(sbar_item_signals, item); + g_hash_table_remove(sbar_item_signals, item); + + while (list != NULL) { + statusbar_item_remove_signal(item, GPOINTER_TO_INT(list->data)); + list = g_slist_remove(list, list->data); + } + + g_free(item); +} + +static void mainwindow_recalc_ypos(MAIN_WINDOW_REC *window, int placement) +{ + GSList *tmp; + + for (tmp = window->statusbars; tmp != NULL; tmp = tmp->next) { + STATUSBAR_REC *bar = tmp->data; + + if (bar->config->placement == placement) { + statusbar_recalc_ypos(bar); + break; + } + } } static void sig_mainwindow_resized(MAIN_WINDOW_REC *window) { - STATUSBAR_REC *rec; + mainwindow_recalc_ypos(window, STATUSBAR_TOP); + mainwindow_recalc_ypos(window, STATUSBAR_BOTTOM); +} + +#define STATUSBAR_IS_VISIBLE(bar, window) \ + ((bar)->visible == STATUSBAR_VISIBLE_ALWAYS || \ + (active_mainwin == (window) && \ + (bar)->visible == STATUSBAR_VISIBLE_ACTIVE) || \ + (active_mainwin != (window) && \ + (bar)->visible == STATUSBAR_VISIBLE_INACTIVE)) + +static void statusbars_remove_unvisible(MAIN_WINDOW_REC *window) +{ + GSList *tmp, *next; + + for (tmp = window->statusbars; tmp != NULL; tmp = next) { + STATUSBAR_REC *bar = tmp->data; + + next = tmp->next; + if (!STATUSBAR_IS_VISIBLE(bar->config, window)) + statusbar_destroy(bar); + } +} + +static void statusbars_add_visible(MAIN_WINDOW_REC *window) +{ + STATUSBAR_GROUP_REC *group; + STATUSBAR_REC *bar; + GSList *tmp; + + group = active_statusbar_group; + for (tmp = group->config_bars; tmp != NULL; tmp = tmp->next) { + STATUSBAR_CONFIG_REC *config = tmp->data; + + if (config->type == STATUSBAR_TYPE_WINDOW && + STATUSBAR_IS_VISIBLE(config, window) && + statusbar_find(group, config->name, window) == NULL) { + bar = statusbar_create(group, config, window); + statusbar_redraw(bar); + } + } +} + +static void sig_mainwindow_destroyed(MAIN_WINDOW_REC *window) +{ + while (window->statusbars != NULL) { + STATUSBAR_REC *bar = window->statusbars->data; + + bar->parent_window->statusbars = + g_slist_remove(bar->parent_window->statusbars, bar); + bar->parent_window = NULL; + statusbar_destroy(bar); + } +} + +static void sig_window_changed(void) +{ + GSList *tmp; - rec = window->statusbar; - rec->ypos = window->first_line+window->height; + for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + statusbars_remove_unvisible(rec); + statusbars_add_visible(rec); + } +} + +static void statusbar_item_def_destroy(void *key, void *value) +{ + g_free(key); + g_free(value); +} + +static void statusbar_signal_item_destroy(void *key, GSList *value) +{ + while (value != NULL) { + statusbar_signal_remove(GPOINTER_TO_INT(value->data)); + value->data = g_slist_remove(value, value->data); + } +} + +static void statusbar_item_signal_destroy(void *key, GSList *value) +{ + g_slist_free(value); } void statusbar_init(void) { - statusbars = NULL; - sbars_up = sbars_down = 0; + statusbar_groups = NULL; + active_statusbar_group = NULL; + sbar_item_defs = g_hash_table_new((GHashFunc) g_str_hash, + (GCompareFunc) g_str_equal); + sbar_item_funcs = g_hash_table_new((GHashFunc) g_str_hash, + (GCompareFunc) g_str_equal); + sbar_signal_items = g_hash_table_new((GHashFunc) g_direct_hash, + (GCompareFunc) g_direct_equal); + sbar_item_signals = g_hash_table_new((GHashFunc) g_direct_hash, + (GCompareFunc) g_direct_equal); statusbar_items_init(); + statusbar_config_init(); + signal_add("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized); signal_add("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized); + signal_add("window changed", (SIGNAL_FUNC) sig_window_changed); + signal_add("mainwindow destroyed", (SIGNAL_FUNC) sig_mainwindow_destroyed); } void statusbar_deinit(void) { - statusbar_items_deinit(); + while (statusbar_groups != NULL) + statusbar_group_destroy(statusbar_groups->data); + + g_hash_table_foreach(sbar_item_defs, + (GHFunc) statusbar_item_def_destroy, NULL); + g_hash_table_destroy(sbar_item_defs); - while (statusbars != NULL) - statusbar_destroy(statusbars->data); + g_hash_table_foreach(sbar_item_funcs, (GHFunc) g_free, NULL); + g_hash_table_destroy(sbar_item_funcs); + + g_hash_table_foreach(sbar_signal_items, + (GHFunc) statusbar_signal_item_destroy, NULL); + g_hash_table_destroy(sbar_signal_items); + g_hash_table_foreach(sbar_item_signals, + (GHFunc) statusbar_item_signal_destroy, NULL); + g_hash_table_destroy(sbar_item_signals); signal_remove("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized); signal_remove("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized); + signal_remove("window changed", (SIGNAL_FUNC) sig_window_changed); + signal_remove("mainwindow destroyed", (SIGNAL_FUNC) sig_mainwindow_destroyed); + + statusbar_items_deinit(); + statusbar_config_deinit(); } diff --git a/src/fe-text/statusbar.h b/src/fe-text/statusbar.h index 32d35b82..4a1865db 100644 --- a/src/fe-text/statusbar.h +++ b/src/fe-text/statusbar.h @@ -3,59 +3,105 @@ #include "mainwindows.h" -#define SBAR_PRIORITY_HIGH 100 -#define SBAR_PRIORITY_NORMAL 0 -#define SBAR_PRIORITY_LOW -100 - -enum { - STATUSBAR_POS_UP, - STATUSBAR_POS_MIDDLE, - STATUSBAR_POS_DOWN -}; +#define STATUSBAR_PRIORITY_HIGH 100 +#define STATUSBAR_PRIORITY_NORMAL 0 +#define STATUSBAR_PRIORITY_LOW -100 typedef struct SBAR_ITEM_REC SBAR_ITEM_REC; typedef void (*STATUSBAR_FUNC) (SBAR_ITEM_REC *item, int get_size_only); +/* type */ +#define STATUSBAR_TYPE_ROOT 1 +#define STATUSBAR_TYPE_WINDOW 2 + +/* placement */ +#define STATUSBAR_TOP 1 +#define STATUSBAR_BOTTOM 2 + +/* visible */ +#define STATUSBAR_VISIBLE_ALWAYS 1 +#define STATUSBAR_VISIBLE_ACTIVE 2 +#define STATUSBAR_VISIBLE_INACTIVE 3 + typedef struct { - MAIN_WINDOW_REC *window; + char *name; + GSList *config_bars; + GSList *bars; +} STATUSBAR_GROUP_REC; - int pos; - int line; +typedef struct { + char *name; - char *color_string; - int color; + int type; /* root/window */ + int placement; /* top/bottom */ + int position; /* the higher the number, the lower it is in screen */ + int visible; /* active/inactive/always */ - int ypos; /* real position in screen at the moment */ GSList *items; +} STATUSBAR_CONFIG_REC; + +typedef struct { + STATUSBAR_GROUP_REC *group; + STATUSBAR_CONFIG_REC *config; + + MAIN_WINDOW_REC *parent_window; /* if config->type == STATUSBAR_TYPE_WINDOW */ + GSList *items; + + char *color; /* background color */ + int real_ypos; /* real Y-position in screen at the moment */ } STATUSBAR_REC; +typedef struct { + char *name; + char *value; /* if non-NULL, overrides the default */ + + int priority; + unsigned int right_alignment:1; +} SBAR_ITEM_CONFIG_REC; + struct SBAR_ITEM_REC { STATUSBAR_REC *bar; - STATUSBAR_FUNC func; + SBAR_ITEM_CONFIG_REC *config; + STATUSBAR_FUNC func; /* what item wants */ - int priority; int min_size, max_size; - unsigned int right_justify:1; /* what item gets */ - int xpos, size; + int xpos, size; }; -/* ypos is used only when pos == STATUSBAR_POS_MIDDLE */ -STATUSBAR_REC *statusbar_create(int pos, int ypos); -void statusbar_destroy(STATUSBAR_REC *bar); +extern GSList *statusbar_groups; +extern STATUSBAR_GROUP_REC *active_statusbar_group; -STATUSBAR_REC *statusbar_find(int pos, int line); +void statusbar_item_register(const char *name, const char *value, + STATUSBAR_FUNC func); +void statusbar_item_unregister(const char *name); + +STATUSBAR_GROUP_REC *statusbar_group_create(const char *name); +void statusbar_group_destroy(STATUSBAR_GROUP_REC *rec); +STATUSBAR_GROUP_REC *statusbar_group_find(const char *name); + +STATUSBAR_REC *statusbar_create(STATUSBAR_GROUP_REC *group, + STATUSBAR_CONFIG_REC *config, + MAIN_WINDOW_REC *parent_window); +void statusbar_destroy(STATUSBAR_REC *bar); +STATUSBAR_REC *statusbar_find(STATUSBAR_GROUP_REC *group, const char *name, + MAIN_WINDOW_REC *window); SBAR_ITEM_REC *statusbar_item_create(STATUSBAR_REC *bar, - int priority, int right_justify, - STATUSBAR_FUNC func); -void statusbar_item_remove(SBAR_ITEM_REC *item); + SBAR_ITEM_CONFIG_REC *config); +void statusbar_item_destroy(SBAR_ITEM_REC *item); + +void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only, + const char *str, const char *data, + int escape_vars); /* redraw statusbar, NULL = all */ void statusbar_redraw(STATUSBAR_REC *bar); void statusbar_item_redraw(SBAR_ITEM_REC *item); +#define statusbar_items_redraw(list) \ + g_slist_foreach(list, (GFunc) statusbar_item_redraw, NULL); void statusbar_init(void); void statusbar_deinit(void); |