summaryrefslogtreecommitdiff
path: root/src/fe-text
diff options
context:
space:
mode:
Diffstat (limited to 'src/fe-text')
-rw-r--r--src/fe-text/Makefile.am5
-rw-r--r--src/fe-text/gui-entry.c367
-rw-r--r--src/fe-text/gui-entry.h49
-rw-r--r--src/fe-text/gui-expandos.c2
-rw-r--r--src/fe-text/gui-printtext.c14
-rw-r--r--src/fe-text/gui-readline.c112
-rw-r--r--src/fe-text/gui-windows.c98
-rw-r--r--src/fe-text/gui-windows.h2
-rw-r--r--src/fe-text/irssi.c4
-rw-r--r--src/fe-text/mainwindows.c117
-rw-r--r--src/fe-text/mainwindows.h19
-rw-r--r--src/fe-text/screen.c74
-rw-r--r--src/fe-text/statusbar-config.c263
-rw-r--r--src/fe-text/statusbar-config.h12
-rw-r--r--src/fe-text/statusbar-items.c683
-rw-r--r--src/fe-text/statusbar-items.h7
-rw-r--r--src/fe-text/statusbar.c819
-rw-r--r--src/fe-text/statusbar.h98
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);