diff options
Diffstat (limited to 'src/fe-text')
-rw-r--r-- | src/fe-text/Makefile.am | 11 | ||||
-rw-r--r-- | src/fe-text/gui-entry.c | 30 | ||||
-rw-r--r-- | src/fe-text/gui-entry.h | 4 | ||||
-rw-r--r-- | src/fe-text/gui-mainwindows.c | 66 | ||||
-rw-r--r-- | src/fe-text/gui-mainwindows.h | 21 | ||||
-rw-r--r-- | src/fe-text/gui-printtext.c | 12 | ||||
-rw-r--r-- | src/fe-text/gui-readline.c | 516 | ||||
-rw-r--r-- | src/fe-text/gui-statusbar-items.h | 7 | ||||
-rw-r--r-- | src/fe-text/gui-statusbar.h | 21 | ||||
-rw-r--r-- | src/fe-text/gui-textwidget.c | 15 | ||||
-rw-r--r-- | src/fe-text/gui-windows.c | 312 | ||||
-rw-r--r-- | src/fe-text/gui-windows.h | 120 | ||||
-rw-r--r-- | src/fe-text/irssi.c | 149 | ||||
-rw-r--r-- | src/fe-text/mainwindows.c | 606 | ||||
-rw-r--r-- | src/fe-text/mainwindows.h | 29 | ||||
-rw-r--r-- | src/fe-text/module-formats.c | 3 | ||||
-rw-r--r-- | src/fe-text/module-formats.h | 9 | ||||
-rw-r--r-- | src/fe-text/screen.c | 246 | ||||
-rw-r--r-- | src/fe-text/statusbar-items.c (renamed from src/fe-text/gui-statusbar-items.c) | 454 | ||||
-rw-r--r-- | src/fe-text/statusbar.c | 266 | ||||
-rw-r--r-- | src/fe-text/statusbar.h | 45 |
21 files changed, 1984 insertions, 958 deletions
diff --git a/src/fe-text/Makefile.am b/src/fe-text/Makefile.am index c651cf0e..0120a4d9 100644 --- a/src/fe-text/Makefile.am +++ b/src/fe-text/Makefile.am @@ -20,12 +20,12 @@ irssi_text_LDADD = \ irssi_text_SOURCES = \ gui-entry.c \ - gui-mainwindows.c \ + mainwindows.c \ gui-printtext.c \ gui-readline.c \ gui-special-vars.c \ - gui-statusbar.c \ - gui-statusbar-items.c \ + statusbar.c \ + statusbar-items.c \ gui-textwidget.c \ gui-windows.c \ irssi.c \ @@ -34,12 +34,11 @@ irssi_text_SOURCES = \ noinst_HEADERS = \ gui-entry.h \ - gui-mainwindows.h \ + mainwindows.h \ gui-printtext.h \ gui-readline.h \ gui-special-vars.h \ - gui-statusbar.h \ - gui-statusbar-items.h \ + statusbar.h \ gui-textwidget.h \ gui-windows.h \ module-formats.h \ diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index d4505195..5f96d30f 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -23,7 +23,7 @@ #include "screen.h" static GString *entry; -static int promptlen, pos, scrstart, scrpos; +static int promptlen, permanent_prompt, pos, scrstart, scrpos; static char *prompt; static void entry_screenpos(void) @@ -71,14 +71,11 @@ static void entry_update(void) void gui_entry_set_prompt(const char *str) { if (str != NULL) { - if (prompt != NULL) g_free(prompt); - prompt = g_strdup(str); + if (permanent_prompt) return; + g_free_not_null(prompt); + prompt = g_strdup(str); promptlen = strlen(prompt); - if (promptlen > 20) { - promptlen = 20; - prompt[20] = '\0'; - } } set_color(0); @@ -88,6 +85,23 @@ void gui_entry_set_prompt(const char *str) entry_update(); } +void gui_entry_set_perm_prompt(const char *str) +{ + g_return_if_fail(str != NULL); + + g_free_not_null(prompt); + prompt = g_strdup(str); + promptlen = strlen(prompt); + + permanent_prompt = TRUE; + gui_entry_set_prompt(NULL); +} + +void gui_entry_remove_perm_prompt(void) +{ + permanent_prompt = FALSE; +} + void gui_entry_set_text(const char *str) { g_return_if_fail(str != NULL); @@ -166,8 +180,10 @@ void gui_entry_redraw(void) void gui_entry_init(void) { entry = g_string_new(NULL); + pos = scrpos = 0; prompt = NULL; promptlen = 0; + permanent_prompt = FALSE; } void gui_entry_deinit(void) diff --git a/src/fe-text/gui-entry.h b/src/fe-text/gui-entry.h index 443d2509..4fbf5c16 100644 --- a/src/fe-text/gui-entry.h +++ b/src/fe-text/gui-entry.h @@ -3,6 +3,10 @@ void gui_entry_set_prompt(const char *str); +/* 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_text(const char *str); char *gui_entry_get_text(void); diff --git a/src/fe-text/gui-mainwindows.c b/src/fe-text/gui-mainwindows.c deleted file mode 100644 index d5d66c1d..00000000 --- a/src/fe-text/gui-mainwindows.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - gui-mainwindows.c : irssi - - Copyright (C) 1999 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 "windows.h" -#include "gui-mainwindows.h" - -GList *mainwindows; - -MAIN_WINDOW_REC *gui_mainwindow_create(void) -{ - MAIN_WINDOW_REC *window; - - window = g_new0(MAIN_WINDOW_REC, 1); - mainwindows = g_list_append(mainwindows, window); - - return window; -} - -void gui_mainwindow_destroy(MAIN_WINDOW_REC *window) -{ - g_return_if_fail(window != NULL); - if (window->destroying) return; - - mainwindows = g_list_remove(mainwindows, window); - - window->destroying = TRUE; - while (window->children != NULL) - window_destroy(window->children->data); - window->destroying = FALSE; - - g_free(window); - - if (mainwindows == NULL) - signal_emit("gui exit", 0); -} - -void gui_mainwindows_init(void) -{ - mainwindows = NULL; -} - -void gui_mainwindows_deinit(void) -{ - while (mainwindows != NULL) - gui_mainwindow_destroy(mainwindows->data); -} diff --git a/src/fe-text/gui-mainwindows.h b/src/fe-text/gui-mainwindows.h deleted file mode 100644 index b91f35a9..00000000 --- a/src/fe-text/gui-mainwindows.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __GUI_MAINWINDOWS_H -#define __GUI_MAINWINDOWS_H - -#include "windows.h" - -typedef struct { - WINDOW_REC *active; - GList *children; - - int destroying; -} MAIN_WINDOW_REC; - -extern GList *mainwindows; - -void gui_mainwindows_init(void); -void gui_mainwindows_deinit(void); - -MAIN_WINDOW_REC *gui_mainwindow_create(void); -void gui_mainwindow_destroy(MAIN_WINDOW_REC *window); - -#endif diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c index 1ef4aa32..59e00d52 100644 --- a/src/fe-text/gui-printtext.c +++ b/src/fe-text/gui-printtext.c @@ -28,7 +28,6 @@ #include "themes.h" #include "screen.h" -#include "gui-mainwindows.h" #include "gui-windows.h" #define TEXT_CHUNK_USABLE_SIZE (LINE_TEXT_CHUNK_SIZE-2-sizeof(char*)) @@ -46,6 +45,9 @@ static LINE_REC *create_line(GUI_WINDOW_REC *gui, gint level) gui->cur_line->level = (gint32) GPOINTER_TO_INT(level); gui->cur_line->time = time(NULL); + /* temporarily mark the end of line. */ + memcpy(gui->cur_text->buffer+gui->cur_text->pos, "\0\x80", 2); + gui->last_color = -1; gui->last_flags = 0; @@ -67,6 +69,8 @@ static TEXT_CHUNK_REC *create_text_chunk(GUI_WINDOW_REC *gui) g_return_val_if_fail(gui != NULL, NULL); rec = g_new(TEXT_CHUNK_REC, 1); + rec->overflow[0] = 0; + rec->overflow[1] = (char) LINE_CMD_OVERFLOW; rec->pos = 0; rec->lines = 0; @@ -268,7 +272,7 @@ static void gui_printtext(WINDOW_REC *window, gpointer fgcolor, gpointer bgcolor if (visible) { /* draw the line to screen. */ - lines = gui_window_line_draw(gui, line, first_text_line+gui->ypos, gui->last_subline, -1); + lines = gui_window_line_draw(gui, line, gui->parent->first_line+gui->ypos, gui->last_subline, -1); } else { @@ -289,7 +293,7 @@ static void cmd_clear(gchar *data) if (is_window_visible(active_win)) { - for (n = first_text_line; n < last_text_line; n++) + for (n = gui->parent->first_line; n <= gui->parent->last_line; n++) { move(n, 0); clrtoeol(); @@ -300,7 +304,7 @@ static void cmd_clear(gchar *data) gui->ypos = -1; gui->bottom_startline = gui->startline = g_list_last(gui->lines); gui->bottom_subline = gui->subline = gui->last_subline+1; - gui->empty_linecount = last_text_line-first_text_line; + gui->empty_linecount = gui->parent->last_line-gui->parent->first_line+1; gui->bottom = TRUE; } diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 39608119..0171dc8d 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -31,25 +31,71 @@ #include "screen.h" #include "gui-entry.h" -#include "gui-mainwindows.h" #include "gui-windows.h" #include <signal.h> -static gint readtag, sigint_count = 0; +typedef void (*ENTRY_REDIRECT_KEY_FUNC) (int key, void *data, SERVER_REC *server, WI_ITEM_REC *item); +typedef void (*ENTRY_REDIRECT_ENTRY_FUNC) (const char *line, void *data, SERVER_REC *server, WI_ITEM_REC *item); + +typedef struct { + SIGNAL_FUNC func; + int key; + void *data; +} ENTRY_REDIRECT_REC; + +static ENTRY_REDIRECT_REC *redir; + +static int readtag, sigint_count = 0; static time_t idle_time; +static void handle_key_redirect(int key) +{ + ENTRY_REDIRECT_KEY_FUNC func; + void *data; + + func = (ENTRY_REDIRECT_KEY_FUNC) redir->func; + data = redir->data; + g_free_and_null(redir); + + if (func != NULL) + func(key, data, active_win->active_server, active_win->active); + + gui_entry_remove_perm_prompt(); + window_update_prompt(active_win); +} + +static void handle_entry_redirect(const char *line) +{ + ENTRY_REDIRECT_ENTRY_FUNC func; + void *data; + + func = (ENTRY_REDIRECT_ENTRY_FUNC) redir->func; + data = redir->data; + g_free_and_null(redir); + + if (func != NULL) + func(line, data, active_win->active_server, active_win->active); + + gui_entry_remove_perm_prompt(); + window_update_prompt(active_win); +} + static void window_prev_page(void) { - gui_window_scroll(active_win, -(last_text_line-first_text_line)/2); + GUI_WINDOW_REC *gui = WINDOW_GUI(active_win); + + gui_window_scroll(active_win, -(gui->parent->last_line-gui->parent->first_line)/2); } static void window_next_page(void) { - gui_window_scroll(active_win, (last_text_line-first_text_line)/2); + GUI_WINDOW_REC *gui = WINDOW_GUI(active_win); + + gui_window_scroll(active_win, (gui->parent->last_line-gui->parent->first_line)/2); } -static char *get_key_name(int key) +static const char *get_key_name(int key) { static char str[MAX_INT_STRLEN]; @@ -76,157 +122,163 @@ static char *get_key_name(int key) } } -void handle_key(gint key) +void handle_key(int key) { - const char *text; - char *str; - int c; - - /* Quit if we get 5 CTRL-C's in a row. */ - if (key != 3) - sigint_count = 0; - else if (++sigint_count >= 5) - raise(SIGTERM); - - idle_time = time(NULL); - switch (key) - { - case 27: - c = getch(); - if (c == toupper(c) && c != tolower(c)) - str = g_strdup_printf("ALT-SHIFT-%c", c); - else { - if (c < 256) - str = g_strdup_printf("ALT-%c", toupper(c)); - else - str = g_strdup_printf("ALT-%s", get_key_name(c)); - } - key_pressed(str, NULL); - g_free(str); - break; + const char *text; + char *str; + int c; + + /* Quit if we get 5 CTRL-C's in a row. */ + if (key != 3) + sigint_count = 0; + else if (++sigint_count >= 5) + raise(SIGTERM); + + idle_time = time(NULL); + + if (redir != NULL && redir->key) { + handle_key_redirect(key); + return; + } + + switch (key) + { + case 27: + c = getch(); + if (c == toupper(c) && c != tolower(c)) + str = g_strdup_printf("ALT-SHIFT-%c", c); + else { + if (c < 256) + str = g_strdup_printf("ALT-%c", toupper(c)); + else + str = g_strdup_printf("ALT-%s", get_key_name(c)); + } + key_pressed(str, NULL); + g_free(str); + break; case KEY_HOME: - /* home */ - gui_entry_set_pos(0); - gui_entry_move_pos(0); - break; - case KEY_END: - /* end */ - gui_entry_set_pos(strlen(gui_entry_get_text())); - gui_entry_move_pos(0); - break; - case KEY_PPAGE: - /* page up */ - window_prev_page(); - break; - case KEY_NPAGE: - /* page down */ - window_next_page(); - break; - - case KEY_UP: - /* up */ - text = command_history_prev(active_win, gui_entry_get_text()); - gui_entry_set_text(text); - break; - case KEY_DOWN: - /* down */ - text = command_history_next(active_win, gui_entry_get_text()); - gui_entry_set_text(text); - break; - case KEY_RIGHT: - /* right */ - gui_entry_move_pos(1); - break; - case KEY_LEFT: - /* left */ - gui_entry_move_pos(-1); - break; + /* home */ + gui_entry_set_pos(0); + gui_entry_move_pos(0); + break; + case KEY_END: + /* end */ + gui_entry_set_pos(strlen(gui_entry_get_text())); + gui_entry_move_pos(0); + break; + case KEY_PPAGE: + /* page up */ + window_prev_page(); + break; + case KEY_NPAGE: + /* page down */ + window_next_page(); + break; + + case KEY_UP: + /* up */ + text = command_history_prev(active_win, gui_entry_get_text()); + gui_entry_set_text(text); + break; + case KEY_DOWN: + /* down */ + text = command_history_next(active_win, gui_entry_get_text()); + gui_entry_set_text(text); + break; + case KEY_RIGHT: + /* right */ + gui_entry_move_pos(1); + break; + case KEY_LEFT: + /* left */ + gui_entry_move_pos(-1); + break; case 21: - /* Ctrl-U, clear line */ - gui_entry_set_text(""); - break; + /* Ctrl-U, clear line */ + gui_entry_set_text(""); + break; case 9: - key_pressed("Tab", NULL); - break; + key_pressed("Tab", NULL); + break; case 8: case 127: - case KEY_BACKSPACE: - gui_entry_erase(1); - break; - - case KEY_DC: - if (gui_entry_get_pos() < strlen(gui_entry_get_text())) - { - gui_entry_move_pos(1); - gui_entry_erase(1); - } - break; + case KEY_BACKSPACE: + gui_entry_erase(1); + break; + + case KEY_DC: + if (gui_entry_get_pos() < strlen(gui_entry_get_text())) { + gui_entry_move_pos(1); + gui_entry_erase(1); + } + break; case 0: - /* Ctrl-space - ignore */ - break; - case 1: - /* C-A, home */ - gui_entry_set_pos(0); - gui_entry_move_pos(0); - break; - case 5: - /* C-E, end */ - gui_entry_set_pos(strlen(gui_entry_get_text())); - gui_entry_move_pos(0); - break; - - case '\n': + /* Ctrl-space - ignore */ + break; + case 1: + /* C-A, home */ + gui_entry_set_pos(0); + gui_entry_move_pos(0); + break; + case 5: + /* C-E, end */ + gui_entry_set_pos(strlen(gui_entry_get_text())); + gui_entry_move_pos(0); + break; + + case '\n': case 13: - key_pressed("Return", NULL); + key_pressed("Return", NULL); - str = gui_entry_get_text(); - if (*str == '\0') break; + str = gui_entry_get_text(); + if (*str == '\0') break; - translate_output(str); - signal_emit("send command", 3, str, active_win->active_server, active_win->active); + translate_output(str); - command_history_add(active_win, gui_entry_get_text(), FALSE); - gui_entry_set_text(""); - command_history_clear_pos(active_win); - break; + if (redir == NULL) + signal_emit("send command", 3, str, active_win->active_server, active_win->active); + else + handle_entry_redirect(str); - default: - if (key > 0 && key < 32) - { - str = g_strdup_printf("CTRL-%c", key == 31 ? '-' : key+'A'-1); - key_pressed(str, NULL); - g_free(str); + command_history_add(active_win, gui_entry_get_text(), FALSE); + gui_entry_set_text(""); + command_history_clear_pos(active_win); break; - } - - if (key < 256) - { - gchar str[2]; - str[0] = toupper(key); str[1] = '\0'; - key_pressed(str, NULL); - gui_entry_insert_char((gchar) key); - } - break; - } + default: + if (key > 0 && key < 32) { + str = g_strdup_printf("CTRL-%c", key == 31 ? '-' : key+'A'-1); + key_pressed(str, NULL); + g_free(str); + break; + } + + if (key < 256) { + char str[2]; + + str[0] = toupper(key); str[1] = '\0'; + key_pressed(str, NULL); + gui_entry_insert_char((char) key); + } + break; + } } void readline(void) { - gint key; + int key; - for (;;) - { - key = getch(); - if (key == ERR) break; + for (;;) { + key = getch(); + if (key == ERR) break; - handle_key(key); - } + handle_key(key); + } } time_t get_idle_time(void) @@ -236,147 +288,169 @@ time_t get_idle_time(void) static void sig_prev_page(void) { - window_prev_page(); + window_prev_page(); } static void sig_next_page(void) { - window_next_page(); + window_next_page(); } -static void sig_change_window(gchar *data) +static void sig_change_window(const char *data) { - signal_emit("command window goto", 3, data, active_win->active_server, active_win->active); + signal_emit("command window goto", 3, data, active_win->active_server, active_win->active); } static void sig_completion(void) { - gchar *line; - gint pos; - - pos = gui_entry_get_pos(); - - line = completion_line(active_win, gui_entry_get_text(), &pos); - if (line != NULL) - { - gui_entry_set_text(line); - gui_entry_set_pos(pos); - g_free(line); - } + char *line; + int pos; + + pos = gui_entry_get_pos(); + + line = completion_line(active_win, gui_entry_get_text(), &pos); + if (line != NULL) { + gui_entry_set_text(line); + gui_entry_set_pos(pos); + g_free(line); + } } static void sig_replace(void) { - gchar *line; - gint pos; - - pos = gui_entry_get_pos(); - - line = auto_completion(gui_entry_get_text(), &pos); - if (line != NULL) - { - gui_entry_set_text(line); - gui_entry_set_pos(pos); - g_free(line); - } + char *line; + int pos; + + pos = gui_entry_get_pos(); + + line = auto_completion(gui_entry_get_text(), &pos); + if (line != NULL) { + gui_entry_set_text(line); + gui_entry_set_pos(pos); + g_free(line); + } } static void sig_prev_window(void) { - signal_emit("command window prev", 3, "", active_win->active_server, active_win->active); + signal_emit("command window prev", 3, "", active_win->active_server, active_win->active); } static void sig_next_window(void) { - signal_emit("command window next", 3, "", active_win->active_server, active_win->active); + signal_emit("command window next", 3, "", active_win->active_server, active_win->active); +} + +static void sig_up_window(void) +{ + signal_emit("command window up", 3, "", active_win->active_server, active_win->active); +} + +static void sig_down_window(void) +{ + signal_emit("command window down", 3, "", active_win->active_server, active_win->active); } static void sig_window_goto_active(void) { - signal_emit("command window goto", 3, "active", active_win->active_server, active_win->active); + signal_emit("command window goto", 3, "active", active_win->active_server, active_win->active); } -static void sig_prev_channel(void) +static void sig_prev_window_item(void) { - signal_emit("command channel prev", 3, "", active_win->active_server, active_win->active); + signal_emit("command window item prev", 3, "", active_win->active_server, active_win->active); } -static void sig_next_channel(void) +static void sig_next_window_item(void) { - signal_emit("command channel next", 3, "", active_win->active_server, active_win->active); + signal_emit("command window item next", 3, "", active_win->active_server, active_win->active); } -static void sig_addchar(gchar *data) +static void sig_addchar(const char *data) { - gui_entry_insert_char(*data); + gui_entry_insert_char(*data); } -static void signal_window_auto_changed(WINDOW_REC *window) +static void sig_window_auto_changed(WINDOW_REC *window) { command_history_next(active_win, gui_entry_get_text()); gui_entry_set_text(""); } +static void sig_gui_entry_redirect(SIGNAL_FUNC func, const char *entry, gpointer key, void *data) +{ + redir = g_new0(ENTRY_REDIRECT_REC, 1); + redir->func = func; + redir->key = key != NULL; + redir->data = data; + + gui_entry_set_perm_prompt(entry); +} + void gui_readline_init(void) { - static gchar changekeys[] = "1234567890QWERTYUIO"; - gchar *key, *data; - gint n; - - idle_time = time(NULL); - readtag = g_input_add(0, G_INPUT_READ, (GInputFunction) readline, NULL); - - key_bind("completion", NULL, "Nick completion", "Tab", (SIGNAL_FUNC) sig_completion); - key_bind("check replaces", NULL, "Check word replaces", " ", (SIGNAL_FUNC) sig_replace); - key_bind("check replaces", NULL, NULL, "Return", (SIGNAL_FUNC) sig_replace); - key_bind("window prev", NULL, "Previous window", "CTRL-P", (SIGNAL_FUNC) sig_prev_window); - key_bind("window prev", NULL, NULL, "ALT-Left", (SIGNAL_FUNC) sig_prev_window); - key_bind("window next", NULL, "Next window", "CTRL-N", (SIGNAL_FUNC) sig_next_window); - key_bind("window next", NULL, NULL, "ALT-Right", (SIGNAL_FUNC) sig_next_window); - key_bind("window active", NULL, "Go to next window with the highest activity", "ALT-A", (SIGNAL_FUNC) sig_window_goto_active); - key_bind("channel next", NULL, "Next channel", "CTRL-X", (SIGNAL_FUNC) sig_next_channel); - key_bind("channel prev", NULL, "Next channel", NULL, (SIGNAL_FUNC) sig_prev_channel); - - key_bind("redraw", NULL, "Redraw window", "CTRL-L", (SIGNAL_FUNC) irssi_redraw); - key_bind("prev page", NULL, "Previous page", "ALT-P", (SIGNAL_FUNC) sig_prev_page); - key_bind("next page", NULL, "Next page", "ALT-N", (SIGNAL_FUNC) sig_next_page); - - key_bind("special char", "\x02", "Insert special character", "CTRL-B", (SIGNAL_FUNC) sig_addchar); - key_bind("special char", "\x1f", NULL, "CTRL--", (SIGNAL_FUNC) sig_addchar); - key_bind("special char", "\x03", NULL, "CTRL-C", (SIGNAL_FUNC) sig_addchar); - key_bind("special char", "\x16", NULL, "CTRL-V", (SIGNAL_FUNC) sig_addchar); - key_bind("special char", "\x07", NULL, "CTRL-G", (SIGNAL_FUNC) sig_addchar); - key_bind("special char", "\x0f", NULL, "CTRL-O", (SIGNAL_FUNC) sig_addchar); - - for (n = 0; changekeys[n] != '\0'; n++) - { - key = g_strdup_printf("ALT-%c", changekeys[n]); - data = g_strdup_printf("%d", n+1); - key_bind("change window", data, "Change window", key, (SIGNAL_FUNC) sig_change_window); - g_free(data); g_free(key); - } - - signal_add("window changed automatic", (SIGNAL_FUNC) signal_window_auto_changed); + static char changekeys[] = "1234567890QWERTYUIO"; + char *key, data[MAX_INT_STRLEN]; + int n; + + redir = NULL; + idle_time = time(NULL); + readtag = g_input_add(0, G_INPUT_READ, (GInputFunction) readline, NULL); + + key_bind("completion", NULL, "Nick completion", "Tab", (SIGNAL_FUNC) sig_completion); + key_bind("check replaces", NULL, "Check word replaces", " ", (SIGNAL_FUNC) sig_replace); + key_bind("check replaces", NULL, NULL, "Return", (SIGNAL_FUNC) sig_replace); + key_bind("window prev", NULL, "Previous window", "CTRL-P", (SIGNAL_FUNC) sig_prev_window); + key_bind("window prev", NULL, NULL, "ALT-Left", (SIGNAL_FUNC) sig_prev_window); + key_bind("window next", NULL, "Next window", "CTRL-N", (SIGNAL_FUNC) sig_next_window); + key_bind("window next", NULL, NULL, "ALT-Right", (SIGNAL_FUNC) sig_next_window); + key_bind("window up", NULL, "Upper window", "ALT-Up", (SIGNAL_FUNC) sig_up_window); + key_bind("window down", NULL, "Lower window", "ALT-Down", (SIGNAL_FUNC) sig_down_window); + key_bind("window active", NULL, "Go to next window with the highest activity", "ALT-A", (SIGNAL_FUNC) sig_window_goto_active); + key_bind("window item next", NULL, "Next channel", "CTRL-X", (SIGNAL_FUNC) sig_next_window_item); + key_bind("window item prev", NULL, "Next channel", NULL, (SIGNAL_FUNC) sig_prev_window_item); + + key_bind("redraw", NULL, "Redraw window", "CTRL-L", (SIGNAL_FUNC) irssi_redraw); + key_bind("prev page", NULL, "Previous page", "ALT-P", (SIGNAL_FUNC) sig_prev_page); + key_bind("next page", NULL, "Next page", "ALT-N", (SIGNAL_FUNC) sig_next_page); + + key_bind("special char", "\x02", "Insert special character", "CTRL-B", (SIGNAL_FUNC) sig_addchar); + key_bind("special char", "\x1f", NULL, "CTRL--", (SIGNAL_FUNC) sig_addchar); + key_bind("special char", "\x03", NULL, "CTRL-C", (SIGNAL_FUNC) sig_addchar); + key_bind("special char", "\x16", NULL, "CTRL-V", (SIGNAL_FUNC) sig_addchar); + key_bind("special char", "\x07", NULL, "CTRL-G", (SIGNAL_FUNC) sig_addchar); + key_bind("special char", "\x0f", NULL, "CTRL-O", (SIGNAL_FUNC) sig_addchar); + + for (n = 0; changekeys[n] != '\0'; n++) { + key = g_strdup_printf("ALT-%c", changekeys[n]); + ltoa(data, n+1); + key_bind("change window", data, "Change window", key, (SIGNAL_FUNC) sig_change_window); + g_free(key); + } + + signal_add("window changed automatic", (SIGNAL_FUNC) sig_window_auto_changed); + signal_add("gui entry redirect", (SIGNAL_FUNC) sig_gui_entry_redirect); } void gui_readline_deinit(void) { - g_source_remove(readtag); + g_source_remove(readtag); - key_unbind("completion", (SIGNAL_FUNC) sig_completion); - key_unbind("check replaces", (SIGNAL_FUNC) sig_replace); - key_unbind("window prev", (SIGNAL_FUNC) sig_prev_window); - key_unbind("window next", (SIGNAL_FUNC) sig_next_window); - key_unbind("window active", (SIGNAL_FUNC) sig_window_goto_active); - key_unbind("channel next", (SIGNAL_FUNC) sig_next_channel); - key_unbind("channel prev", (SIGNAL_FUNC) sig_prev_channel); + key_unbind("completion", (SIGNAL_FUNC) sig_completion); + key_unbind("check replaces", (SIGNAL_FUNC) sig_replace); + key_unbind("window prev", (SIGNAL_FUNC) sig_prev_window); + key_unbind("window next", (SIGNAL_FUNC) sig_next_window); + key_unbind("window active", (SIGNAL_FUNC) sig_window_goto_active); + key_unbind("window item next", (SIGNAL_FUNC) sig_next_window_item); + key_unbind("window item prev", (SIGNAL_FUNC) sig_prev_window_item); - key_unbind("redraw", (SIGNAL_FUNC) irssi_redraw); - key_unbind("prev page", (SIGNAL_FUNC) sig_prev_page); - key_unbind("next page", (SIGNAL_FUNC) sig_next_page); + key_unbind("redraw", (SIGNAL_FUNC) irssi_redraw); + key_unbind("prev page", (SIGNAL_FUNC) sig_prev_page); + key_unbind("next page", (SIGNAL_FUNC) sig_next_page); - key_unbind("special char", (SIGNAL_FUNC) sig_addchar); - key_unbind("change window", (SIGNAL_FUNC) sig_change_window); + key_unbind("special char", (SIGNAL_FUNC) sig_addchar); + key_unbind("change window", (SIGNAL_FUNC) sig_change_window); - signal_remove("window changed automatic", (SIGNAL_FUNC) signal_window_auto_changed); + signal_remove("window changed automatic", (SIGNAL_FUNC) sig_window_auto_changed); + signal_remove("gui entry redirect", (SIGNAL_FUNC) sig_gui_entry_redirect); } diff --git a/src/fe-text/gui-statusbar-items.h b/src/fe-text/gui-statusbar-items.h deleted file mode 100644 index f71415f0..00000000 --- a/src/fe-text/gui-statusbar-items.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __GUI_STATUSBAR_ITEMS_H -#define __GUI_STATUSBAR_ITEMS_H - -void gui_statusbar_items_init(void); -void gui_statusbar_items_deinit(void); - -#endif diff --git a/src/fe-text/gui-statusbar.h b/src/fe-text/gui-statusbar.h deleted file mode 100644 index bdaba584..00000000 --- a/src/fe-text/gui-statusbar.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __GUI_STATUSBAR_H -#define __GUI_STATUSBAR_H - -typedef void (*STATUSBAR_FUNC) (gint xpos, gint ypos, gint size); - -/* create new statusbar, return position */ -gint gui_statusbar_create(gboolean up); -void gui_statusbar_delete(gboolean up, gint ypos); - -/* allocate area in statusbar, returns tag or -1 if failed */ -gint gui_statusbar_allocate(gint size, gboolean right_justify, gboolean up, gint ypos, STATUSBAR_FUNC func); -void gui_statusbar_resize(gint tag, gint size); -void gui_statusbar_remove(gint tag); - -/* redraw item, -1 = all */ -void gui_statusbar_redraw(gint tag); - -void gui_statusbar_init(void); -void gui_statusbar_deinit(void); - -#endif diff --git a/src/fe-text/gui-textwidget.c b/src/fe-text/gui-textwidget.c index c4d6d2f4..a380322b 100644 --- a/src/fe-text/gui-textwidget.c +++ b/src/fe-text/gui-textwidget.c @@ -29,7 +29,6 @@ #include "windows.h" #include "screen.h" -#include "gui-mainwindows.h" #include "gui-windows.h" static gchar *gui_window_line2text(LINE_REC *line) @@ -178,7 +177,7 @@ static void cmd_lastlog(const char *data) countstr = text; text = ""; } - count = atol(countstr); + count = atoi(countstr); if (count == 0) count = -1; level = lastlog_parse_args(args, &flags); @@ -188,7 +187,7 @@ static void cmd_lastlog(const char *data) printformat(NULL, NULL, MSGLEVEL_LASTLOG, IRCTXT_LASTLOG_START); list = gui_window_find_text(active_win, text, startline, flags & LASTLOG_FLAG_REGEXP, flags & LASTLOG_FLAG_WORD); - tmp = lastlog_find_startline(list, count, atol(start), level); + tmp = lastlog_find_startline(list, count, atoi(start), level); for (; tmp != NULL && (count < 0 || count > 0); tmp = tmp->next, count--) { LINE_REC *rec = tmp->data; @@ -197,13 +196,13 @@ static void cmd_lastlog(const char *data) continue; text = gui_window_line2text(rec); - if (settings_get_bool("toggle_show_timestamps")) - printtext(NULL, NULL, MSGLEVEL_LASTLOG, text); + if (settings_get_bool("timestamps")) + printtext(NULL, NULL, MSGLEVEL_LASTLOG, "%s", text); else { tm = localtime(&rec->time); str = g_strdup_printf("[%02d:%02d] %s", tm->tm_hour, tm->tm_min, text); - printtext(NULL, NULL, MSGLEVEL_LASTLOG, str); + printtext(NULL, NULL, MSGLEVEL_LASTLOG, "%s", str); g_free(str); } g_free(text); @@ -249,7 +248,7 @@ static void scrollback_goto_pos(WINDOW_REC *window, GList *pos) gui->bottom = TRUE; gui->startline = gui->bottom_startline; gui->subline = gui->bottom_subline; - gui->ypos = last_text_line-first_text_line-1; + gui->ypos = gui->parent->last_line-gui->parent->first_line-1; } if (is_window_visible(window)) @@ -362,7 +361,7 @@ static void cmd_scrollback_end(gchar *data) gui->bottom = TRUE; gui->startline = gui->bottom_startline; gui->subline = gui->bottom_subline; - gui->ypos = last_text_line-first_text_line-1; + gui->ypos = gui->parent->last_line-gui->parent->first_line-1; if (is_window_visible(active_win)) gui_window_redraw(active_win); diff --git a/src/fe-text/gui-windows.c b/src/fe-text/gui-windows.c index bdcfa916..df1ba8ec 100644 --- a/src/fe-text/gui-windows.c +++ b/src/fe-text/gui-windows.c @@ -30,14 +30,13 @@ #include "screen.h" #include "gui-entry.h" -#include "gui-mainwindows.h" #include "gui-windows.h" #include <regex.h> #define DEFAULT_INDENT_POS 10 -int first_text_line = 0, last_text_line = 0; +static int window_create_override; static GUI_WINDOW_REC *gui_window_init(WINDOW_REC *window, MAIN_WINDOW_REC *parent) { @@ -49,7 +48,7 @@ static GUI_WINDOW_REC *gui_window_init(WINDOW_REC *window, MAIN_WINDOW_REC *pare gui->bottom = TRUE; gui->line_chunk = g_mem_chunk_new("line chunk", sizeof(LINE_REC), sizeof(LINE_REC)*100, G_ALLOC_AND_FREE); - gui->empty_linecount = last_text_line-first_text_line-1; + gui->empty_linecount = parent->last_line-parent->first_line; return gui; } @@ -65,19 +64,31 @@ static void gui_window_deinit(GUI_WINDOW_REC *gui) g_free(gui); } +static void sig_window_create_override(gpointer tab) +{ + window_create_override = GPOINTER_TO_INT(tab); +} + static void gui_window_created(WINDOW_REC *window) { - MAIN_WINDOW_REC *parent; + MAIN_WINDOW_REC *parent; - g_return_if_fail(window != NULL); + g_return_if_fail(window != NULL); - parent = (active_win == NULL || WINDOW_GUI(active_win) == NULL) ? - gui_mainwindow_create() : WINDOW_GUI(active_win)->parent; - if (parent->children == NULL) parent->active = window; - parent->children = g_list_append(parent->children, window); + parent = window_create_override != 0 && + active_win != NULL && WINDOW_GUI(active_win) != NULL ? + WINDOW_GUI(active_win)->parent : mainwindow_create(); + if (parent == NULL) { + /* not enough space for new window, but we really can't + abort creation of the window anymore, so create hidden + window instead. */ + parent = WINDOW_GUI(active_win)->parent; + } + window_create_override = -1; - window->gui_data = gui_window_init(window, parent); - signal_emit("gui window created", 1, window); + if (parent->active == NULL) parent->active = window; + window->gui_data = gui_window_init(window, parent); + signal_emit("gui window created", 1, window); } static void gui_window_destroyed(WINDOW_REC *window) @@ -89,39 +100,35 @@ static void gui_window_destroyed(WINDOW_REC *window) gui = WINDOW_GUI(window); parent = gui->parent; - parent->children = g_list_remove(parent->children, window); signal_emit("gui window destroyed", 1, window); gui_window_deinit(gui); window->gui_data = NULL; - if (parent->children == NULL) - gui_mainwindow_destroy(parent); - - if (windows != NULL && active_win == window && !quitting) - window_set_active(windows->data); + if (mainwindows->next != NULL && parent->active == window) + mainwindow_destroy(parent); } void gui_window_clear(WINDOW_REC *window) { - MAIN_WINDOW_REC *parent; + MAIN_WINDOW_REC *parent; - g_return_if_fail(window != NULL); + g_return_if_fail(window != NULL); - parent = WINDOW_GUI(window)->parent; - gui_window_deinit(WINDOW_GUI(window)); - window->gui_data = gui_window_init(window, parent); + parent = WINDOW_GUI(window)->parent; + gui_window_deinit(WINDOW_GUI(window)); + window->gui_data = gui_window_init(window, parent); - window->lines = 0; + window->lines = 0; - if (is_window_visible(window)) - gui_window_redraw(window); + if (is_window_visible(window)) + gui_window_redraw(window); } -gint gui_window_update_bottom(GUI_WINDOW_REC *gui, gint lines) +int gui_window_update_bottom(GUI_WINDOW_REC *gui, int lines) { - gint linecount, last_linecount; + int linecount, last_linecount; if (gui->bottom_startline == NULL) return -1; @@ -173,7 +180,7 @@ void gui_window_newline(GUI_WINDOW_REC *gui, gboolean visible) g_return_if_fail(gui != NULL); gui->xpos = 0; - last_line = gui->ypos >= last_text_line-first_text_line-1; + last_line = gui->ypos >= gui->parent->last_line-gui->parent->first_line; if (gui->empty_linecount > 0) { @@ -211,8 +218,8 @@ void gui_window_newline(GUI_WINDOW_REC *gui, gboolean visible) if (visible) { - scroll_up(first_text_line, last_text_line-1); - move(last_text_line-1, 0); clrtoeol(); + scroll_up(gui->parent->first_line, gui->parent->last_line); + move(gui->parent->last_line, 0); clrtoeol(); } } } @@ -240,6 +247,8 @@ gint gui_window_get_linecount(GUI_WINDOW_REC *gui, LINE_REC *line) ptr++; switch ((guchar) *ptr) { + case LINE_CMD_OVERFLOW: + g_error("buffer overflow!"); case LINE_CMD_EOL: return lines; case LINE_CMD_CONTINUE: @@ -306,6 +315,8 @@ gint gui_window_line_draw(GUI_WINDOW_REC *gui, LINE_REC *line, gint ypos, gint s } else switch ((guchar) *ptr) { + case LINE_CMD_OVERFLOW: + g_error("buffer overflow!"); case LINE_CMD_EOL: return lines; case LINE_CMD_CONTINUE: @@ -365,7 +376,7 @@ gint gui_window_line_draw(GUI_WINDOW_REC *gui, LINE_REC *line, gint ypos, gint s else { gui_window_newline(gui, TRUE); - ypos = first_text_line+gui->ypos; + ypos = gui->parent->first_line+gui->ypos; } lines++; } @@ -409,7 +420,7 @@ void gui_window_redraw(WINDOW_REC *window) gui = WINDOW_GUI(window); - for (ypos = first_text_line; ypos < last_text_line; ypos++) + for (ypos = gui->parent->first_line; ypos <= gui->parent->last_line; ypos++) { set_color(0); move(ypos, 0); @@ -417,12 +428,12 @@ void gui_window_redraw(WINDOW_REC *window) } skip = gui->subline; - ypos = first_text_line; + ypos = gui->parent->first_line; for (line = gui->startline; line != NULL; line = line->next) { LINE_REC *rec = line->data; - max = last_text_line - ypos-1; + max = gui->parent->last_line - ypos; if (max < 0) break; lines = gui_window_line_draw(gui, rec, ypos, skip, max); @@ -460,7 +471,7 @@ static void gui_window_scroll_up(GUI_WINDOW_REC *gui, gint lines) gui->ypos -= -count; } - gui->bottom = (gui->ypos >= -1 && gui->ypos <= last_text_line-first_text_line-1); + gui->bottom = (gui->ypos >= -1 && gui->ypos <= gui->parent->last_line-gui->parent->first_line); } static void gui_window_scroll_down(GUI_WINDOW_REC *gui, gint lines) @@ -507,28 +518,28 @@ static void gui_window_scroll_down(GUI_WINDOW_REC *gui, gint lines) gui->startline = gui->startline->next; } - gui->bottom = (gui->ypos >= -1 && gui->ypos <= last_text_line-first_text_line-1); + gui->bottom = (gui->ypos >= -1 && gui->ypos <= gui->parent->last_line-gui->parent->first_line); } -void gui_window_scroll(WINDOW_REC *window, gint lines) +void gui_window_scroll(WINDOW_REC *window, int lines) { - GUI_WINDOW_REC *gui; + GUI_WINDOW_REC *gui; - g_return_if_fail(window != NULL); + g_return_if_fail(window != NULL); - gui = WINDOW_GUI(window); + gui = WINDOW_GUI(window); - if (lines < 0) - gui_window_scroll_up(gui, -lines); - else - gui_window_scroll_down(gui, lines); + if (lines < 0) + gui_window_scroll_up(gui, -lines); + else + gui_window_scroll_down(gui, lines); - if (is_window_visible(window)) - gui_window_redraw(window); - signal_emit("gui page scrolled", 1, window); + if (is_window_visible(window)) + gui_window_redraw(window); + signal_emit("gui page scrolled", 1, window); } -static void window_update_prompt(WINDOW_REC *window) +void window_update_prompt(WINDOW_REC *window) { WI_ITEM_REC *item; char *text, *str; @@ -551,11 +562,34 @@ static void window_update_prompt(WINDOW_REC *window) if (*str != '\0') g_free(str); } +void gui_window_reparent(WINDOW_REC *window, MAIN_WINDOW_REC *parent) +{ + MAIN_WINDOW_REC *oldparent; + int ychange; + + oldparent = WINDOW_GUI(window)->parent; + ychange = (parent->last_line - parent->first_line) - + (oldparent->last_line - oldparent->first_line); + + WINDOW_GUI(window)->parent = parent; + if (ychange != 0) gui_window_resize(window, ychange, FALSE); +} + static void signal_window_changed(WINDOW_REC *window) { g_return_if_fail(window != NULL); - WINDOW_GUI(window)->parent->active = window; + if (is_window_visible(window)) { + /* already visible, great! */ + active_mainwin = WINDOW_GUI(window)->parent; + } else { + /* move it to active main window */ + if (active_mainwin == NULL) + active_mainwin = WINDOW_GUI(window)->parent; + else + gui_window_reparent(window, active_mainwin); + active_mainwin->active = window; + } screen_refresh_freeze(); window_update_prompt(window); @@ -565,15 +599,6 @@ static void signal_window_changed(WINDOW_REC *window) static void signal_window_item_update(WINDOW_REC *window) { - CHANNEL_REC *channel; - - channel = irc_item_channel(window->active); - if (channel != NULL) { - /* redraw channel widgets */ - signal_emit("channel topic changed", 1, channel); - signal_emit("channel mode changed", 1, channel); - } - window_update_prompt(window); } @@ -625,6 +650,8 @@ GList *gui_window_find_text(WINDOW_REC *window, gchar *text, GList *startline, i } else if ((guchar) *ptr == LINE_CMD_EOL) break; + else if ((guchar) *ptr == LINE_CMD_OVERFLOW) + g_error("buffer overflow!"); } } str[n] = '\0'; @@ -645,138 +672,89 @@ GList *gui_window_find_text(WINDOW_REC *window, gchar *text, GList *startline, i static void gui_window_horiz_resize(WINDOW_REC *window) { - GUI_WINDOW_REC *gui; - gint linecount; + GUI_WINDOW_REC *gui; + int linecount; - gui = WINDOW_GUI(window); - if (gui->lines == NULL) return; + gui = WINDOW_GUI(window); + if (gui->lines == NULL) return; - linecount = gui_window_get_linecount(gui, g_list_last(gui->lines)->data); - gui->last_subline = linecount-1; + linecount = gui_window_get_linecount(gui, g_list_last(gui->lines)->data); + gui->last_subline = linecount-1; - /* fake a /CLEAR and scroll window up one page */ - gui->ypos = -1; - gui->bottom = TRUE; - gui->empty_linecount = last_text_line-first_text_line-1; + /* fake a /CLEAR and scroll window up one page */ + gui->ypos = -1; + gui->bottom = TRUE; + gui->empty_linecount = gui->parent->last_line-gui->parent->first_line; - gui->bottom_startline = gui->startline = g_list_last(gui->lines); - gui->bottom_subline = gui->subline = gui->last_subline+1; - gui_window_scroll(window, -gui->empty_linecount-1); + gui->bottom_startline = gui->startline = g_list_last(gui->lines); + gui->bottom_subline = gui->subline = gui->last_subline+1; + gui_window_scroll(window, -gui->empty_linecount-1); - gui->bottom_startline = gui->startline; - gui->bottom_subline = gui->subline; + gui->bottom_startline = gui->startline; + gui->bottom_subline = gui->subline; - /* remove the empty lines from the end */ - if (gui->bottom && gui->startline == gui->lines) - gui->empty_linecount = (last_text_line-first_text_line-1); - else - gui->empty_linecount = 0; + /* remove the empty lines from the end */ + if (gui->bottom && gui->startline == gui->lines) + gui->empty_linecount = (gui->parent->last_line-gui->parent->first_line); + else + gui->empty_linecount = 0; } -void gui_windows_resize(gint ychange, gboolean xchange) +void gui_window_resize(WINDOW_REC *window, int ychange, int xchange) { - GUI_WINDOW_REC *gui; - WINDOW_REC *window; - GSList *tmp; - - screen_refresh_freeze(); - for (tmp = windows; tmp != NULL; tmp = tmp->next) - { - window = tmp->data; + GUI_WINDOW_REC *gui; gui = WINDOW_GUI(window); - if (xchange) - { - /* window width changed, we'll need to recalculate a few things.. */ - gui_window_horiz_resize(window); - continue; + if (xchange) { + /* window width changed, we'll need to recalculate a few things.. */ + gui_window_horiz_resize(window); + return; } - if (ychange < 0 && gui->empty_linecount > 0) - { - /* empty space at the bottom of the screen - just eat it. */ - gui->empty_linecount += ychange; - if (gui->empty_linecount < 0) - gui->empty_linecount = 0; - } - else if (gui->bottom && gui->startline == gui->lines && ychange > 0) - { - /* less than screenful of text, add empty space */ - gui->empty_linecount += ychange; - } - else - { - gui_window_update_bottom(WINDOW_GUI(window), -ychange); - gui_window_scroll(window, -ychange); + if (ychange < 0 && gui->empty_linecount > 0) { + /* empty space at the bottom of the screen - just eat it. */ + gui->empty_linecount += ychange; + if (gui->empty_linecount >= 0) + ychange = 0; + else { + ychange -= gui->empty_linecount; + gui->empty_linecount = 0; + } } - } - - irssi_redraw(); - screen_refresh_thaw(); -} - -static void cmd_window_move(gchar *data) -{ - GSList *w1, *w2; - WINDOW_REC *window; - g_return_if_fail(data != NULL); - - window = active_win; - w1 = g_slist_find(windows, window); - if (g_strcasecmp(data, "LEFT") == 0 || g_strncasecmp(data, "PREV", 4) == 0) - { - w2 = g_slist_nth(windows, g_slist_index(windows, window)-1); - if (w2 == NULL) - { - window = w1->data; - windows = g_slist_remove(windows, window); - windows = g_slist_append(windows, window); - w2 = g_slist_last(windows); - } - } - else if (g_strcasecmp(data, "RIGHT") == 0 || g_strcasecmp(data, "NEXT") == 0) - { - w2 = w1->next; - if (w2 == NULL) - { - window = w1->data; - windows = g_slist_remove(windows, window); - windows = g_slist_prepend(windows, window); + if (gui->bottom && gui->startline == gui->lines && ychange > 0) { + /* less than screenful of text, add empty space */ + gui->empty_linecount += ychange; + } else { + gui_window_update_bottom(WINDOW_GUI(window), -ychange); + gui_window_scroll(window, -ychange); } - } - else - return; - - if (w2 != NULL) - { - window = w1->data; - w1->data = w2->data; - w2->data = window; - } - - window_set_active(window); } 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("window changed", (SIGNAL_FUNC) signal_window_changed); - signal_add("window item changed", (SIGNAL_FUNC) signal_window_item_update); - signal_add("window name changed", (SIGNAL_FUNC) signal_window_item_update); - signal_add("window item remove", (SIGNAL_FUNC) signal_window_item_update); - command_bind("window move", NULL, (SIGNAL_FUNC) cmd_window_move); + window_create_override = -1; + + signal_add("gui window create override", (SIGNAL_FUNC) sig_window_create_override); + 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 changed", (SIGNAL_FUNC) signal_window_item_update); + signal_add("window name changed", (SIGNAL_FUNC) signal_window_item_update); + signal_add("window item remove", (SIGNAL_FUNC) signal_window_item_update); } 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 changed", (SIGNAL_FUNC) signal_window_item_update); - signal_remove("window name changed", (SIGNAL_FUNC) signal_window_item_update); - signal_remove("window item remove", (SIGNAL_FUNC) signal_window_item_update); - command_unbind("window move", (SIGNAL_FUNC) cmd_window_move); + while (windows != NULL) + window_destroy(windows->data); + + signal_remove("gui window create override", (SIGNAL_FUNC) sig_window_create_override); + 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 changed", (SIGNAL_FUNC) signal_window_item_update); + signal_remove("window name changed", (SIGNAL_FUNC) signal_window_item_update); + signal_remove("window item remove", (SIGNAL_FUNC) signal_window_item_update); } diff --git a/src/fe-text/gui-windows.h b/src/fe-text/gui-windows.h index 14a3a982..28dde1e9 100644 --- a/src/fe-text/gui-windows.h +++ b/src/fe-text/gui-windows.h @@ -2,7 +2,7 @@ #define __GUI_WINDOWS_H #include "server.h" -#include "gui-mainwindows.h" +#include "mainwindows.h" #define WINDOW_GUI(a) ((GUI_WINDOW_REC *) ((a)->gui_data)) @@ -12,63 +12,57 @@ #define LINE_TEXT_CHUNK_SIZE 2048 /* 7 first bits of LINE_REC's info byte. */ -enum -{ - LINE_CMD_EOL=0x80, /* line ends here. */ - LINE_CMD_CONTINUE, /* line continues in next block */ - LINE_CMD_COLOR8, /* change to dark grey, normally 8 = bold black */ - LINE_CMD_UNDERLINE, /* enable/disable underlining */ - LINE_CMD_BEEP, /* beep */ - LINE_CMD_INDENT /* if line is split, indent it at this position */ +enum { + LINE_CMD_EOL=0x80, /* line ends here. */ + LINE_CMD_CONTINUE, /* line continues in next block */ + LINE_CMD_OVERFLOW, /* buffer overflow! */ + LINE_CMD_COLOR8, /* change to dark grey, normally 8 = bold black */ + LINE_CMD_UNDERLINE, /* enable/disable underlining */ + LINE_CMD_BEEP, /* beep */ + LINE_CMD_INDENT /* if line is split, indent it at this position */ }; -typedef struct -{ - gchar *text; /* text in the line. \0 means that the next char will be a - color or command. <= 127 = color or if 8.bit is set, the - first 7 bits are the command. See LINE_CMD_xxxx. */ - - gint32 level; - time_t time; -} -LINE_REC; - -typedef struct -{ - gchar buffer[LINE_TEXT_CHUNK_SIZE]; - gint pos; - gint lines; -} -TEXT_CHUNK_REC; - -typedef struct -{ - MAIN_WINDOW_REC *parent; - - GMemChunk *line_chunk; - GSList *text_chunks; - GList *lines; - - LINE_REC *cur_line; - TEXT_CHUNK_REC *cur_text; - - gint xpos, ypos; /* cursor position in screen */ - GList *startline; /* line at the top of the screen */ - gint subline; /* number of "real lines" to skip from `startline' */ - - GList *bottom_startline; /* marks the bottom of the text buffer */ - gint bottom_subline; - gint empty_linecount; /* how many empty lines are in screen. - a screenful when started or used /CLEAR */ - gboolean bottom; /* window is at the bottom of the text buffer */ - - /* for gui-printtext.c */ - gint last_subline; - gint last_color, last_flags; -} -GUI_WINDOW_REC; - -extern gint first_text_line, last_text_line; +typedef struct { + /* text in the line. \0 means that the next char will be a + color or command. <= 127 = color or if 8.bit is set, the + first 7 bits are the command. See LINE_CMD_xxxx. */ + char *text; + + int level; + time_t time; +} LINE_REC; + +typedef struct { + char buffer[LINE_TEXT_CHUNK_SIZE]; + char overflow[2]; + int pos; + int lines; +} TEXT_CHUNK_REC; + +typedef struct { + MAIN_WINDOW_REC *parent; + + GMemChunk *line_chunk; + GSList *text_chunks; + GList *lines; + + LINE_REC *cur_line; + TEXT_CHUNK_REC *cur_text; + + int xpos, ypos; /* cursor position in screen */ + GList *startline; /* line at the top of the screen */ + int subline; /* number of "real lines" to skip from `startline' */ + + GList *bottom_startline; /* marks the bottom of the text buffer */ + int bottom_subline; + int empty_linecount; /* how many empty lines are in screen. + a screenful when started or used /CLEAR */ + int bottom; /* window is at the bottom of the text buffer */ + + /* for gui-printtext.c */ + int last_subline; + int last_color, last_flags; +} GUI_WINDOW_REC; void gui_windows_init(void); void gui_windows_deinit(void); @@ -76,18 +70,20 @@ void gui_windows_deinit(void); WINDOW_REC *gui_window_create(MAIN_WINDOW_REC *parent); void gui_window_set_server(WINDOW_REC *window, SERVER_REC *server); -GList *gui_window_find_text(WINDOW_REC *window, gchar *text, GList *startline, int regexp, int fullword); +GList *gui_window_find_text(WINDOW_REC *window, char *text, GList *startline, int regexp, int fullword); /* get number of real lines that line record takes */ -gint gui_window_get_linecount(GUI_WINDOW_REC *gui, LINE_REC *line); -gint gui_window_line_draw(GUI_WINDOW_REC *gui, LINE_REC *line, gint ypos, gint skip, gint max); +int gui_window_get_linecount(GUI_WINDOW_REC *gui, LINE_REC *line); +int gui_window_line_draw(GUI_WINDOW_REC *gui, LINE_REC *line, int ypos, int skip, int max); void gui_window_clear(WINDOW_REC *window); void gui_window_redraw(WINDOW_REC *window); -void gui_windows_resize(gint ychange, gboolean xchange); +void gui_window_resize(WINDOW_REC *window, int ychange, int xchange); +void gui_window_reparent(WINDOW_REC *window, MAIN_WINDOW_REC *parent); +void window_update_prompt(WINDOW_REC *window); void gui_window_newline(GUI_WINDOW_REC *gui, gboolean visible); -gint gui_window_update_bottom(GUI_WINDOW_REC *gui, gint lines); -void gui_window_scroll(WINDOW_REC *window, gint lines); +int gui_window_update_bottom(GUI_WINDOW_REC *gui, int lines); +void gui_window_scroll(WINDOW_REC *window, int lines); #endif diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index d427a208..2c95b87d 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -29,12 +29,11 @@ #include "screen.h" #include "gui-entry.h" -#include "gui-mainwindows.h" +#include "mainwindows.h" #include "gui-printtext.h" #include "gui-readline.h" #include "gui-special-vars.h" -#include "gui-statusbar.h" -#include "gui-statusbar-items.h" +#include "statusbar.h" #include "gui-textwidget.h" #include "gui-windows.h" @@ -59,109 +58,103 @@ static void sig_exit(void) /* redraw irssi's screen.. */ void irssi_redraw(void) { - clear(); - - /* current window */ - gui_window_redraw(active_win); - /* statusbar */ - gui_statusbar_redraw(-1); - /* entry line */ - gui_entry_redraw(); + clear(); + + /* windows */ + mainwindows_redraw(); + /* statusbar */ + statusbar_redraw(NULL); + /* entry line */ + gui_entry_redraw(); } static void textui_init(void) { - static struct poptOption options[] = { - POPT_AUTOHELP - { NULL, '\0', 0, NULL } - }; - - args_register(options); - - irssi_gui = IRSSI_GUI_TEXT; - core_init(); - irc_init(); - fe_common_core_init(); - fe_common_irc_init(); - signal_add("gui exit", (SIGNAL_FUNC) sig_exit); + static struct poptOption options[] = { + POPT_AUTOHELP + { NULL, '\0', 0, NULL } + }; + + args_register(options); + + irssi_gui = IRSSI_GUI_TEXT; + core_init(); + irc_init(); + fe_common_core_init(); + fe_common_irc_init(); + signal_add("gui exit", (SIGNAL_FUNC) sig_exit); } static void textui_finish_init(void) { - quitting = FALSE; - - screen_refresh_freeze(); - gui_entry_init(); - gui_mainwindows_init(); - gui_printtext_init(); - gui_readline_init(); - gui_special_vars_init(); - gui_textwidget_init(); - gui_windows_init(); - - fe_common_core_finish_init(); - fe_common_irc_finish_init(); - - gui_statusbar_init(); - gui_statusbar_items_init(); - - signal_emit("irssi init finished", 0); + quitting = FALSE; + + screen_refresh_freeze(); + gui_entry_init(); + mainwindows_init(); + gui_printtext_init(); + gui_readline_init(); + gui_special_vars_init(); + gui_textwidget_init(); + gui_windows_init(); + statusbar_init(); + + fe_common_core_finish_init(); + fe_common_irc_finish_init(); + + signal_emit("irssi init finished", 0); #ifdef HAVE_PERL - irssi_perl_init(); + irssi_perl_init(); #endif - screen_refresh_thaw(); + screen_refresh_thaw(); } static void textui_deinit(void) { - quitting = TRUE; - signal(SIGINT, SIG_DFL); + quitting = TRUE; + signal(SIGINT, SIG_DFL); - signal_remove("gui exit", (SIGNAL_FUNC) sig_exit); + signal_remove("gui exit", (SIGNAL_FUNC) sig_exit); #ifdef HAVE_PERL - irssi_perl_deinit(); + irssi_perl_deinit(); #endif - gui_textwidget_deinit(); - gui_special_vars_deinit(); - gui_statusbar_items_deinit(); - gui_statusbar_deinit(); - gui_printtext_deinit(); - gui_readline_deinit(); - gui_mainwindows_deinit(); - gui_windows_deinit(); - gui_entry_deinit(); - deinit_screen(); - - fe_common_irc_deinit(); - fe_common_core_deinit(); - irc_deinit(); - core_deinit(); + gui_textwidget_deinit(); + gui_special_vars_deinit(); + statusbar_deinit(); + gui_printtext_deinit(); + gui_readline_deinit(); + mainwindows_deinit(); + gui_windows_deinit(); + gui_entry_deinit(); + deinit_screen(); + + fe_common_irc_deinit(); + fe_common_core_deinit(); + irc_deinit(); + core_deinit(); } int main(int argc, char **argv) { #ifdef HAVE_SOCKS - SOCKSinit(argv[0]); + SOCKSinit(argv[0]); #endif - textui_init(); - args_execute(argc, argv); + textui_init(); + args_execute(argc, argv); - if (!init_screen()) - { - printf("Can't initialize screen handling, quitting.\n"); - return 1; - } + if (!init_screen()) + g_error(_("Can't initialize screen handling, quitting.\n")); - textui_finish_init(); - main_loop = g_main_new(TRUE); - g_main_run(main_loop); - g_main_destroy(main_loop); - textui_deinit(); + textui_finish_init(); + main_loop = g_main_new(TRUE); + g_main_run(main_loop); + g_main_destroy(main_loop); + textui_deinit(); #ifdef MEM_DEBUG - ig_mem_profile(); + ig_mem_profile(); #endif - return 0; + return 0; } diff --git a/src/fe-text/mainwindows.c b/src/fe-text/mainwindows.c new file mode 100644 index 00000000..35bf4ecd --- /dev/null +++ b/src/fe-text/mainwindows.c @@ -0,0 +1,606 @@ +/* + gui-mainwindows.c : irssi + + Copyright (C) 1999 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 "module-formats.h" +#include "signals.h" +#include "commands.h" +#include "levels.h" +#include "misc.h" + +#include "screen.h" +#include "statusbar.h" +#include "gui-windows.h" + +#define WINDOW_MIN_SIZE 2 +#define NEW_WINDOW_SIZE (WINDOW_MIN_SIZE + 1) + +#define window_size(window) \ + ((window)->last_line - (window)->first_line+1) + +GSList *mainwindows; +MAIN_WINDOW_REC *active_mainwin; + +static int reserved_up, reserved_down; + +static MAIN_WINDOW_REC *find_window_with_room(void) +{ + MAIN_WINDOW_REC *biggest_rec; + GSList *tmp; + int space, biggest; + + biggest = 0; biggest_rec = NULL; + for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + space = window_size(rec); + if (space >= WINDOW_MIN_SIZE+NEW_WINDOW_SIZE && space > biggest) { + biggest = space; + biggest_rec = rec; + } + } + + return biggest_rec; +} + +static void mainwindow_resize(MAIN_WINDOW_REC *window, int ychange, int xchange) +{ + GSList *tmp; + + if (ychange == 0 && !xchange) return; + + for (tmp = windows; tmp != NULL; tmp = tmp->next) { + WINDOW_REC *rec = tmp->data; + + if (rec->gui_data != NULL && WINDOW_GUI(rec)->parent == window) + gui_window_resize(rec, ychange, xchange); + } + + signal_emit("mainwindow resized", 1, window); +} + +MAIN_WINDOW_REC *mainwindow_create(void) +{ + MAIN_WINDOW_REC *rec, *parent; + int space; + + rec = g_new0(MAIN_WINDOW_REC, 1); + rec->statusbar_lines = 1; + + if (mainwindows == NULL) { + active_mainwin = rec; + + rec->first_line = reserved_up; + rec->last_line = LINES-1-reserved_down-rec->statusbar_lines; + } else { + parent = WINDOW_GUI(active_win)->parent; + if (window_size(parent) < WINDOW_MIN_SIZE+NEW_WINDOW_SIZE) + parent = find_window_with_room(); + if (parent == NULL) + return NULL; /* not enough space */ + + space = (window_size(parent)-parent->statusbar_lines)/2; + rec->first_line = parent->first_line; + rec->last_line = rec->first_line + space-rec->statusbar_lines; + parent->first_line = rec->last_line+1+rec->statusbar_lines; + + mainwindow_resize(parent, -space-1, FALSE); + } + + mainwindows = g_slist_append(mainwindows, rec); + signal_emit("mainwindow created", 1, rec); + return rec; +} + +static MAIN_WINDOW_REC *mainwindows_find_lower(int line) +{ + MAIN_WINDOW_REC *best; + GSList *tmp; + + best = NULL; + for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + if (rec->first_line > line && + (best == NULL || rec->first_line < best->first_line)) + best = rec; + } + + return best; +} + +static MAIN_WINDOW_REC *mainwindows_find_upper(int line) +{ + MAIN_WINDOW_REC *best; + GSList *tmp; + + best = NULL; + for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + if (rec->last_line < line && + (best == NULL || rec->last_line > best->last_line)) + best = rec; + } + + return best; +} + +static void mainwindows_add_space(int first_line, int last_line) +{ + MAIN_WINDOW_REC *rec; + int size; + + if (last_line < first_line) + return; + + size = last_line-first_line+1; + + rec = mainwindows_find_lower(last_line); + if (rec != NULL) { + rec->first_line = first_line; + mainwindow_resize(rec, size, FALSE); + return; + } + + rec = mainwindows_find_upper(first_line); + if (rec != NULL) { + rec->last_line = last_line-rec->statusbar_lines; + mainwindow_resize(rec, size, FALSE); + } +} + +static void gui_windows_remove_parent(MAIN_WINDOW_REC *window) +{ + MAIN_WINDOW_REC *new_parent; + GSList *tmp; + + new_parent = mainwindows->data; + for (tmp = windows; tmp != NULL; tmp = tmp->next) { + WINDOW_REC *rec = tmp->data; + + if (rec->gui_data != NULL && WINDOW_GUI(rec)->parent == window) + gui_window_reparent(rec, new_parent); + } +} + +void mainwindow_destroy(MAIN_WINDOW_REC *window) +{ + g_return_if_fail(window != NULL); + + mainwindows = g_slist_remove(mainwindows, window); + signal_emit("mainwindow destroyed", 1, window); + + if (!quitting && mainwindows != NULL) { + gui_windows_remove_parent(window); + mainwindows_add_space(window->first_line, window->last_line+window->statusbar_lines); + + mainwindows_redraw(); + statusbar_redraw(NULL); + } + g_free(window); + + if (active_mainwin == window) active_mainwin = NULL; +} + +void mainwindows_redraw(void) +{ + GSList *tmp; + + screen_refresh_freeze(); + for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + gui_window_redraw(rec->active); + } + screen_refresh_thaw(); +} + +static int mainwindows_compare(MAIN_WINDOW_REC *w1, MAIN_WINDOW_REC *w2) +{ + return w1->first_line < w2->first_line ? -1 : 1; +} + +static int mainwindows_compare_reverse(MAIN_WINDOW_REC *w1, MAIN_WINDOW_REC *w2) +{ + return w1->first_line < w2->first_line ? 1 : -1; +} + +static GSList *mainwindows_get_sorted(int reverse) +{ + GSList *tmp, *list; + + list = NULL; + for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { + list = g_slist_insert_sorted(list, tmp->data, (GCompareFunc) + (reverse ? mainwindows_compare_reverse : mainwindows_compare)); + } + + return list; +} + +static void mainwindows_resize_too_small(int ychange, int xchange) +{ + GSList *sorted, *tmp; + int space, moved; + + /* terminal is too small - just take the space whereever possible */ + sorted = mainwindows_get_sorted(FALSE); + moved = 0; + for (tmp = sorted; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + space = window_size(rec); + if (ychange == 0 || space <= 0) { + if (moved > 0) { + rec->first_line -= moved; + rec->last_line -= moved; + signal_emit("mainwindow moved", 1, rec); + } + continue; + } + + if (space > -ychange) space = -ychange; + ychange += space; + rec->first_line -= moved; + moved += space; + rec->last_line -= space; + mainwindow_resize(rec, -space, xchange); + } + g_slist_free(sorted); +} + +static void mainwindows_resize_smaller(int ychange, int xchange) +{ + GSList *sorted, *tmp; + int space; + + space = 0; + for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + space += window_size(rec)-WINDOW_MIN_SIZE; + } + + if (space < -ychange) { + /* not enough space, use different algorithm */ + mainwindows_resize_too_small(ychange, xchange); + return; + } + + /* resize windows that have space */ + sorted = mainwindows_get_sorted(TRUE); + for (tmp = sorted; tmp != NULL && ychange < 0; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + space = window_size(rec)-WINDOW_MIN_SIZE; + if (space <= 0) { + rec->first_line += ychange; + rec->last_line += ychange; + signal_emit("mainwindow moved", 1, rec); + continue; + } + + if (space <= 0) space = 1; + if (space > -ychange) space = -ychange; + rec->last_line += ychange; + ychange += space; + rec->first_line += ychange; + + mainwindow_resize(rec, -space, xchange); + } + g_slist_free(sorted); +} + +static void mainwindows_resize_bigger(int ychange, int xchange) +{ + GSList *sorted, *tmp; + int moved, space; + + sorted = mainwindows_get_sorted(FALSE); + moved = 0; + for (tmp = sorted; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + space = window_size(rec)-WINDOW_MIN_SIZE; + if (ychange == 0 || (space >= 0 && tmp->next != NULL)) { + if (moved > 0) { + rec->first_line += moved; + rec->last_line += moved; + signal_emit("mainwindow moved", 1, rec); + } + continue; + } + + if (space < 0 && tmp->next != NULL) { + /* space below minimum */ + space = -space; + if (space > ychange) space = ychange; + } else { + /* lowest window - give all the extra space for it */ + space = ychange; + } + ychange -= space; + rec->first_line += moved; + moved += space; + rec->last_line += moved; + + mainwindow_resize(rec, space, xchange); + } + g_slist_free(sorted); +} + +void mainwindows_resize(int ychange, int xchange) +{ + screen_refresh_freeze(); + if (ychange < 0) + mainwindows_resize_smaller(ychange, xchange); + else if (ychange > 0) + mainwindows_resize_bigger(ychange, xchange); + + irssi_redraw(); + screen_refresh_thaw(); +} + +int mainwindows_reserve_lines(int count, int up) +{ + MAIN_WINDOW_REC *window; + int ret; + + if (up) { + g_return_val_if_fail(count > 0 || reserved_up > count, -1); + + ret = reserved_up; + reserved_up += count; + + window = mainwindows_find_lower(-1); + if (window != NULL) window->first_line += count; + } else { + g_return_val_if_fail(count > 0 || reserved_down > count, -1); + + ret = reserved_down; + reserved_down += count; + + window = mainwindows_find_upper(LINES); + if (window != NULL) window->last_line -= count; + } + + if (window != NULL) + mainwindow_resize(window, -count, FALSE); + + return ret; +} + +static void mainwindows_resize_two(MAIN_WINDOW_REC *grow_win, MAIN_WINDOW_REC *shrink_win, int count) +{ + mainwindow_resize(grow_win, count, FALSE); + mainwindow_resize(shrink_win, -count, FALSE); + gui_window_redraw(grow_win->active); + gui_window_redraw(shrink_win->active); + statusbar_redraw(grow_win->statusbar); + statusbar_redraw(shrink_win->statusbar); +} + +static void cmd_window_grow(const char *data) +{ + MAIN_WINDOW_REC *window, *shrink_win; + int count; + + count = *data == '\0' ? 1 : atoi(data); + window = WINDOW_GUI(active_win)->parent; + + /* shrink lower window */ + shrink_win = mainwindows_find_lower(window->last_line); + if (shrink_win != NULL && window_size(shrink_win)-count >= WINDOW_MIN_SIZE) { + window->last_line += count; + shrink_win->first_line += count; + } else { + /* shrink upper window */ + shrink_win = mainwindows_find_upper(window->first_line); + if (shrink_win != NULL && window_size(shrink_win)-count >= WINDOW_MIN_SIZE) { + window->first_line -= count; + shrink_win->last_line -= count; + } else { + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_WINDOW_TOO_SMALL); + return; + } + } + + mainwindows_resize_two(window, shrink_win, count); +} + +static void cmd_window_shrink(const char *data) +{ + MAIN_WINDOW_REC *window, *grow_win; + int count; + + count = *data == '\0' ? 1 : atoi(data); + + window = WINDOW_GUI(active_win)->parent; + if (window_size(window)-count < WINDOW_MIN_SIZE) { + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_WINDOW_TOO_SMALL); + return; + } + + grow_win = mainwindows_find_lower(window->last_line); + if (grow_win != NULL) { + window->last_line -= count; + grow_win->first_line -= count; + } else { + grow_win = mainwindows_find_upper(window->first_line); + if (grow_win == NULL) return; + + window->first_line += count; + grow_win->last_line += count; + } + + mainwindows_resize_two(grow_win, window, count); +} + +static void cmd_window_size(const char *data) +{ + char sizestr[MAX_INT_STRLEN]; + int size; + + if (!is_numeric(data, 0)) return; + size = atoi(data); + + size -= window_size(WINDOW_GUI(active_win)->parent); + if (size == 0) return; + + ltoa(sizestr, size < 0 ? -size : size); + if (size < 0) + cmd_window_shrink(sizestr); + else + cmd_window_grow(sizestr); +} + +static void cmd_window_balance(void) +{ + GSList *sorted, *tmp; + int avail_size, unit_size, bigger_units; + int windows, last_line, old_size; + + windows = g_slist_length(mainwindows); + if (windows == 1) return; + + avail_size = LINES-reserved_up-reserved_down; + unit_size = avail_size/windows; + bigger_units = avail_size%windows; + + sorted = mainwindows_get_sorted(FALSE); + last_line = 0; + for (tmp = sorted; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + old_size = window_size(rec); + rec->first_line = last_line+1; + rec->last_line = rec->first_line-1 + unit_size - + rec->statusbar_lines; + + if (bigger_units > 0) { + rec->last_line++; + bigger_units--; + } + last_line = rec->last_line + rec->statusbar_lines; + + mainwindow_resize(rec, window_size(rec)-old_size, FALSE); + } + g_slist_free(sorted); + + mainwindows_redraw(); + statusbar_redraw(NULL); +} + +static void cmd_window_hide(const char *data) +{ + WINDOW_REC *window; + + if (mainwindows->next == NULL) { + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CANT_HIDE_LAST); + return; + } + + if (*data == '\0') + window = active_win; + else if (is_numeric(data, 0)) + window = window_find_refnum(atoi(data)); + else + window = window_find_item(active_win, data); + + if (window == NULL) return; + if (!is_window_visible(window)) return; + + mainwindow_destroy(WINDOW_GUI(window)->parent); + + if (active_mainwin == NULL) { + active_mainwin = WINDOW_GUI(active_win)->parent; + window_set_active(active_mainwin->active); + } +} + +static void cmd_window_show(const char *data) +{ + WINDOW_REC *window; + + if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); + + window = is_numeric(data, 0) ? + window_find_refnum(atoi(data)) : + window_find_item(active_win, data); + + if (window == NULL) return; + if (is_window_visible(window)) return; + + WINDOW_GUI(window)->parent = mainwindow_create(); + WINDOW_GUI(window)->parent->active = window; + + active_mainwin = NULL; + window_set_active(window); +} + +static void cmd_window_up(void) +{ + MAIN_WINDOW_REC *rec; + + rec = mainwindows_find_upper(active_mainwin->first_line); + if (rec != NULL) + window_set_active(rec->active); +} + +static void cmd_window_down(void) +{ + MAIN_WINDOW_REC *rec; + + rec = mainwindows_find_lower(active_mainwin->last_line); + if (rec != NULL) + window_set_active(rec->active); +} + +void mainwindows_init(void) +{ + mainwindows = NULL; + active_mainwin = NULL; + reserved_up = reserved_down = 0; + + /* for entry line */ + mainwindows_reserve_lines(1, FALSE); + + command_bind("window grow", NULL, (SIGNAL_FUNC) cmd_window_grow); + command_bind("window shrink", NULL, (SIGNAL_FUNC) cmd_window_shrink); + command_bind("window size", NULL, (SIGNAL_FUNC) cmd_window_size); + command_bind("window balance", NULL, (SIGNAL_FUNC) cmd_window_balance); + command_bind("window hide", NULL, (SIGNAL_FUNC) cmd_window_hide); + command_bind("window show", NULL, (SIGNAL_FUNC) cmd_window_show); + command_bind("window up", NULL, (SIGNAL_FUNC) cmd_window_up); + command_bind("window down", NULL, (SIGNAL_FUNC) cmd_window_down); +} + +void mainwindows_deinit(void) +{ + command_unbind("window grow", (SIGNAL_FUNC) cmd_window_grow); + command_unbind("window shrink", (SIGNAL_FUNC) cmd_window_shrink); + command_unbind("window size", (SIGNAL_FUNC) cmd_window_size); + command_unbind("window balance", (SIGNAL_FUNC) cmd_window_balance); + command_unbind("window hide", (SIGNAL_FUNC) cmd_window_hide); + command_unbind("window show", (SIGNAL_FUNC) cmd_window_show); + command_unbind("window up", (SIGNAL_FUNC) cmd_window_up); + command_unbind("window down", (SIGNAL_FUNC) cmd_window_down); +} diff --git a/src/fe-text/mainwindows.h b/src/fe-text/mainwindows.h new file mode 100644 index 00000000..467add2d --- /dev/null +++ b/src/fe-text/mainwindows.h @@ -0,0 +1,29 @@ +#ifndef __MAINWINDOWS_H +#define __MAINWINDOWS_H + +#include "windows.h" + +typedef struct { + WINDOW_REC *active; + + int first_line, last_line; + int statusbar_lines; + void *statusbar; + void *statusbar_channel_item; +} MAIN_WINDOW_REC; + +extern GSList *mainwindows; +extern MAIN_WINDOW_REC *active_mainwin; + +void mainwindows_init(void); +void mainwindows_deinit(void); + +MAIN_WINDOW_REC *mainwindow_create(void); +void mainwindow_destroy(MAIN_WINDOW_REC *window); + +void mainwindows_redraw(void); +void mainwindows_resize(int ychange, int xchange); + +int mainwindows_reserve_lines(int count, int up); + +#endif diff --git a/src/fe-text/module-formats.c b/src/fe-text/module-formats.c index a7576de9..9b38fecb 100644 --- a/src/fe-text/module-formats.c +++ b/src/fe-text/module-formats.c @@ -27,4 +27,7 @@ FORMAT_REC gui_text_formats[] = { "lastlog_start", "%_Lastlog:", 0 }, { "lastlog_end", "%_End of Lastlog", 0 }, + + { "window_too_small", "Not enough room to resize this window", 0 }, + { "cant_hide_last", "You can't hide the last window", 0 } }; diff --git a/src/fe-text/module-formats.h b/src/fe-text/module-formats.h index d8f7a3b8..32f219e2 100644 --- a/src/fe-text/module-formats.h +++ b/src/fe-text/module-formats.h @@ -1,10 +1,13 @@ #include "printtext.h" enum { - IRCTXT_MODULE_NAME, + IRCTXT_MODULE_NAME, - IRCTXT_LASTLOG_START, - IRCTXT_LASTLOG_END + IRCTXT_LASTLOG_START, + IRCTXT_LASTLOG_END, + + IRCTXT_WINDOW_TOO_SMALL, + IRCTXT_CANT_HIDE_LAST }; extern FORMAT_REC gui_text_formats[]; diff --git a/src/fe-text/screen.c b/src/fe-text/screen.c index 19c79f5a..5f197028 100644 --- a/src/fe-text/screen.c +++ b/src/fe-text/screen.c @@ -1,8 +1,7 @@ /* - screen.c : All virtual screen management, real screen management is in - con_???.c files. + screen.c : irssi - Copyright (C) 1999 Timo Sirainen + Copyright (C) 1999-2000 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 @@ -25,7 +24,7 @@ #include "screen.h" #include "gui-readline.h" -#include "gui-windows.h" +#include "mainwindows.h" #ifdef HAVE_SYS_IOCTL_H #include <sys/ioctl.h> @@ -38,52 +37,50 @@ #define MIN_SCREEN_WIDTH 20 -static gint scrx, scry; -gboolean use_colors; -static gint freeze_refresh; +static int scrx, scry; +static int use_colors; +static int freeze_refresh; #ifdef SIGWINCH static void sig_winch(int p) { #ifdef TIOCGWINSZ - struct winsize ws; - gint ychange, xchange; + struct winsize ws; + int ychange, xchange; - /* Get new window size */ - if (ioctl(0, TIOCGWINSZ, &ws) < 0) - return; + /* Get new window size */ + if (ioctl(0, TIOCGWINSZ, &ws) < 0) + return; - if (ws.ws_row == LINES && ws.ws_col == COLS) - { - /* Same size, abort. */ - return; - } + if (ws.ws_row == LINES && ws.ws_col == COLS) { + /* Same size, abort. */ + return; + } - if (ws.ws_col < MIN_SCREEN_WIDTH) - ws.ws_col = MIN_SCREEN_WIDTH; + if (ws.ws_col < MIN_SCREEN_WIDTH) + ws.ws_col = MIN_SCREEN_WIDTH; - /* Resize curses terminal */ - ychange = ws.ws_row-LINES; - xchange = ws.ws_col-COLS; + /* Resize curses terminal */ + ychange = ws.ws_row-LINES; + xchange = ws.ws_col-COLS; #ifdef HAVE_CURSES_RESIZETERM - resizeterm(ws.ws_row, ws.ws_col); + resizeterm(ws.ws_row, ws.ws_col); #else - deinit_screen(); - init_screen(); + deinit_screen(); + init_screen(); #endif - last_text_line += ychange; - gui_windows_resize(ychange, xchange != 0); + mainwindows_resize(ychange, xchange != 0); #endif } #endif -/* SIGINT != ^C .. any better way to make this work? */ +/* FIXME: SIGINT != ^C .. any better way to make this work? */ void sigint_handler(int p) { - ungetch(3); - readline(); + ungetch(3); + readline(); } static void read_settings(void) @@ -93,162 +90,141 @@ static void read_settings(void) } /* Initialize screen, detect screen length */ -gint init_screen(void) +int init_screen(void) { - gchar ansi_tab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; - gint num; + char ansi_tab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + int num; - if (!initscr()) return 0; + if (!initscr()) return 0; - if (COLS < MIN_SCREEN_WIDTH) - COLS = MIN_SCREEN_WIDTH; + if (COLS < MIN_SCREEN_WIDTH) + COLS = MIN_SCREEN_WIDTH; - signal(SIGINT, sigint_handler); - cbreak(); noecho(); idlok(stdscr, 1); + signal(SIGINT, sigint_handler); + cbreak(); noecho(); idlok(stdscr, 1); #ifdef HAVE_CURSES_IDCOK - idcok(stdscr, 1); + idcok(stdscr, 1); #endif - intrflush(stdscr, FALSE); halfdelay(1); keypad(stdscr, 1); + intrflush(stdscr, FALSE); halfdelay(1); keypad(stdscr, 1); - settings_add_bool("lookandfeel", "colors", TRUE); + settings_add_bool("lookandfeel", "colors", TRUE); - use_colors = settings_get_bool("colors") && has_colors(); - if (has_colors()) start_color(); + use_colors = settings_get_bool("colors") && has_colors(); + if (has_colors()) start_color(); #ifdef HAVE_NCURSES_USE_DEFAULT_COLORS - /* this lets us to use the "default" background color for colors <= 7 so - background pixmaps etc. show up right */ - use_default_colors(); + /* this lets us to use the "default" background color for colors <= 7 so + background pixmaps etc. show up right */ + use_default_colors(); - for (num = 1; num < COLOR_PAIRS; num++) - init_pair(num, ansi_tab[num & 7], num <= 7 ? -1 : ansi_tab[num >> 3]); + for (num = 1; num < COLOR_PAIRS; num++) + init_pair(num, ansi_tab[num & 7], num <= 7 ? -1 : ansi_tab[num >> 3]); - init_pair(63, 0, -1); /* hm.. not THAT good idea, but probably more people - want dark grey than white on white.. */ + init_pair(63, 0, -1); /* hm.. not THAT good idea, but probably more + people want dark grey than white on white.. */ #else - for (num = 1; num < COLOR_PAIRS; num++) - init_pair(num, ansi_tab[num & 7], ansi_tab[num >> 3]); - init_pair(63, 0, 0); + for (num = 1; num < COLOR_PAIRS; num++) + init_pair(num, ansi_tab[num & 7], ansi_tab[num >> 3]); + init_pair(63, 0, 0); #endif - scrx = scry = 0; - if (last_text_line == 0) - { - first_text_line = 0; - last_text_line = LINES-1; - } + scrx = scry = 0; #ifdef SIGWINCH - signal(SIGWINCH, sig_winch); + signal(SIGWINCH, sig_winch); #endif - freeze_refresh = 0; - clear(); + freeze_refresh = 0; + clear(); - signal_add("setup changed", (SIGNAL_FUNC) read_settings); - return 1; + signal_add("setup changed", (SIGNAL_FUNC) read_settings); + return 1; } /* Deinitialize screen */ void deinit_screen(void) { - signal_remove("setup changed", (SIGNAL_FUNC) read_settings); - endwin(); + signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + endwin(); } -void set_color(gint col) +void set_color(int col) { - gint attr; - - if (!use_colors) - { - if ((col & 0x70) != 0) - attr = A_REVERSE; - else - attr = 0; - } - else - { - if (col & ATTR_COLOR8) - attr = A_DIM | COLOR_PAIR(63); - else - attr = COLOR_PAIR((col&7) + (col&0x70)/2); - } - - if (col & 0x08) attr |= A_BOLD; - if (col & 0x80) attr |= A_BLINK; - - if (col & ATTR_UNDERLINE) attr |= A_UNDERLINE; - if (col & ATTR_REVERSE) attr |= A_REVERSE; - - attrset(attr); + int attr; + + if (!use_colors) + attr = (col & 0x70) ? A_REVERSE : 0; + else { + attr = (col & ATTR_COLOR8) ? + (A_DIM | COLOR_PAIR(63)) : + (COLOR_PAIR((col&7) + (col&0x70)/2)); + } + + if (col & 0x08) attr |= A_BOLD; + if (col & 0x80) attr |= A_BLINK; + + if (col & ATTR_UNDERLINE) attr |= A_UNDERLINE; + if (col & ATTR_REVERSE) attr |= A_REVERSE; + + attrset(attr); } -void set_bg(gint col) +void set_bg(int col) { - gint attr; - - if (!use_colors) - { - if ((col & 0x70) != 0) - attr = A_REVERSE; - else - attr = 0; - } - else - { - if (col == 8) - attr = A_DIM | COLOR_PAIR(63); - else - attr = COLOR_PAIR((col&7) + (col&0x70)/2); - } - - if (col & 0x08) attr |= A_BOLD; - if (col & 0x80) attr |= A_BLINK; - - bkgdset(' ' | attr); + 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; + + bkgdset(' ' | attr); } /* Scroll area up */ -void scroll_up(gint y1, gint y2) +void scroll_up(int y1, int y2) { - scrollok(stdscr, TRUE); - setscrreg(y1, y2); scrl(1); - scrollok(stdscr, FALSE); + scrollok(stdscr, TRUE); + setscrreg(y1, y2); scrl(1); + scrollok(stdscr, FALSE); } /* Scroll area down */ -void scroll_down(gint y1, gint y2) +void scroll_down(int y1, int y2) { - scrollok(stdscr, TRUE); - setscrreg(y1, y2); scrl(-1); - scrollok(stdscr, FALSE); + scrollok(stdscr, TRUE); + setscrreg(y1, y2); scrl(-1); + scrollok(stdscr, FALSE); } -void move_cursor(gint y, gint x) +void move_cursor(int y, int x) { - scry = y; - scrx = x; + scry = y; + scrx = x; } void screen_refresh_freeze(void) { - freeze_refresh++; + freeze_refresh++; } void screen_refresh_thaw(void) { - if (freeze_refresh > 0) - { - freeze_refresh--; - if (freeze_refresh == 0) screen_refresh(); - } + if (freeze_refresh > 0) { + freeze_refresh--; + if (freeze_refresh == 0) screen_refresh(); + } } void screen_refresh(void) { - if (freeze_refresh == 0) - { - move(scry, scrx); - refresh(); - } + if (freeze_refresh == 0) { + move(scry, scrx); + refresh(); + } } diff --git a/src/fe-text/gui-statusbar-items.c b/src/fe-text/statusbar-items.c index 1cb3740e..8b55f263 100644 --- a/src/fe-text/gui-statusbar-items.c +++ b/src/fe-text/statusbar-items.c @@ -31,10 +31,11 @@ #include "nicklist.h" #include "windows.h" +#include "window-items.h" #include "screen.h" -#include "gui-statusbar.h" -#include "gui-mainwindows.h" +#include "printtext.h" +#include "statusbar.h" #include "gui-windows.h" /* how often to redraw lagging time */ @@ -43,72 +44,78 @@ the lag */ #define MAX_LAG_UNKNOWN_TIME 30 +static STATUSBAR_REC *mainbar; +static MAIN_WINDOW_REC *mainbar_window; +static int use_colors; + /* clock */ -static int clock_tag, clock_timetag; +static SBAR_ITEM_REC *clock_item; +static int clock_timetag; static time_t clock_last; /* nick */ -static int nick_tag; +static SBAR_ITEM_REC *nick_item; /* channel */ -static int channel_tag; +static SBAR_ITEM_REC *channel_item; /* activity */ -static int activity_tag; +static SBAR_ITEM_REC *activity_item; static GList *activity_list; /* more */ -static int more_tag; +static SBAR_ITEM_REC *more_item; /* lag */ -static int lag_tag, lag_timetag, lag_min_show; +static SBAR_ITEM_REC *lag_item; +static int lag_timetag, lag_min_show; static time_t lag_last_draw; /* topic */ -static int topic_tag; +static SBAR_ITEM_REC *topic_item; +static STATUSBAR_REC *topic_bar; /* redraw clock */ -static void statusbar_clock(int xpos, int ypos, int size) +static void statusbar_clock(SBAR_ITEM_REC *item, int ypos) { - struct tm *tm; - gchar str[5]; + struct tm *tm; + char str[6]; - clock_last = time(NULL); - tm = localtime(&clock_last); + clock_last = time(NULL); + tm = localtime(&clock_last); - sprintf(str, "%02d:%02d", tm->tm_hour, tm->tm_min); + g_snprintf(str, sizeof(str), "%02d:%02d", tm->tm_hour, tm->tm_min); - move(ypos, xpos); - set_color((1 << 4)+3); addch('['); - set_color((1 << 4)+15); addstr(str); - set_color((1 << 4)+3); addch(']'); + move(ypos, item->xpos); + set_color((1 << 4)+3); addch('['); + set_color((1 << 4)+15); addstr(str); + set_color((1 << 4)+3); addch(']'); - screen_refresh(); + screen_refresh(); } /* check if we need to redraw clock.. */ static int statusbar_clock_timeout(void) { - struct tm *tm; - time_t t; - int min; + struct tm *tm; + time_t t; + int min; - tm = localtime(&clock_last); - min = tm->tm_min; + tm = localtime(&clock_last); + min = tm->tm_min; - t = time(NULL); - tm = localtime(&t); + t = time(NULL); + tm = localtime(&t); - if (tm->tm_min != min) - { - /* minute changed, redraw! */ - gui_statusbar_redraw(clock_tag); - } - return 1; + if (tm->tm_min != min) { + /* minute changed, redraw! */ + statusbar_item_redraw(clock_item); + } + return 1; } /* redraw nick */ -static void statusbar_nick(int xpos, int ypos, int size) +static void statusbar_nick(SBAR_ITEM_REC *item, int ypos) { CHANNEL_REC *channel; IRC_SERVER_REC *server; @@ -140,15 +147,15 @@ static void statusbar_nick(int xpos, int ypos, int size) (server != NULL && server->usermode_away ? 7 : 0) + (nickrec != NULL && (nickrec->op || nickrec->voice) ? 1 : 0); /* @ + */ - if (size != size_needed) + if (item->size != size_needed) { /* we need more (or less..) space! */ - gui_statusbar_resize(nick_tag, size_needed); + statusbar_item_resize(item, size_needed); return; } /* size ok, draw the nick */ - move(ypos, xpos); + move(ypos, item->xpos); set_color((1 << 4)+3); addch('['); if (nickrec != NULL && (nickrec->op || nickrec->voice)) @@ -175,41 +182,57 @@ static void statusbar_nick(int xpos, int ypos, int size) static void sig_statusbar_nick_redraw(void) { - gui_statusbar_redraw(nick_tag); + statusbar_item_redraw(nick_item); +} + +static WINDOW_REC *mainwindow_find_sbar(SBAR_ITEM_REC *item) +{ + GSList *tmp; + + for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + if (rec->statusbar_channel_item == item) + return rec->active; + } + + return active_win; } /* redraw channel */ -static void statusbar_channel(int xpos, int ypos, int size) +static void statusbar_channel(SBAR_ITEM_REC *item, int ypos) { - WI_ITEM_REC *item; + WINDOW_REC *window; + WI_ITEM_REC *witem; CHANNEL_REC *channel; SERVER_REC *server; - gchar channame[21], window[MAX_INT_STRLEN], *mode; + gchar channame[21], winnum[MAX_INT_STRLEN], *mode; int size_needed; int mode_size; - server = active_win == NULL ? NULL : active_win->active_server; + window = item->bar->pos != STATUSBAR_POS_MIDDLE ? active_win : + mainwindow_find_sbar(item); + server = window == NULL ? NULL : window->active_server; - ltoa(window, active_win == NULL ? 0 : - g_slist_index(windows, active_win)+1); + ltoa(winnum, window == NULL ? 0 : window->refnum); - item = active_win != NULL && irc_item_check(active_win->active) ? - active_win->active : NULL; - if (item == NULL) + witem = window != NULL && irc_item_check(window->active) ? + window->active : NULL; + if (witem == NULL) { /* display server tag */ channame[0] = '\0'; mode = NULL; mode_size = 0; - size_needed = 3 + strlen(window) + (server == NULL ? 0 : strlen(server->tag)); + size_needed = 3 + strlen(winnum) + (server == NULL ? 0 : strlen(server->tag)); } else { /* display channel + mode */ - strncpy(channame, item->name, 20); channame[20] = '\0'; + strncpy(channame, witem->name, 20); channame[20] = '\0'; - channel = irc_item_channel(item); + channel = irc_item_channel(witem); if (channel == NULL) { mode_size = 0; mode = NULL; @@ -219,22 +242,22 @@ static void statusbar_channel(int xpos, int ypos, int size) if (mode_size > 0) mode_size += 3; /* (+) */ } - size_needed = 3 + strlen(window) + strlen(channame) + mode_size; + size_needed = 3 + strlen(winnum) + strlen(channame) + mode_size; } - if (size != size_needed) + if (item->size != size_needed) { /* we need more (or less..) space! */ - gui_statusbar_resize(channel_tag, size_needed); + statusbar_item_resize(item, size_needed); if (mode != NULL) g_free(mode); return; } - move(ypos, xpos); + move(ypos, item->xpos); set_color((1 << 4)+3); addch('['); /* window number */ - set_color((1 << 4)+7); addstr(window); + set_color((1 << 4)+7); addstr(winnum); set_color((1 << 4)+3); addch(':'); if (channame[0] == '\0' && server != NULL) @@ -262,14 +285,29 @@ static void statusbar_channel(int xpos, int ypos, int size) static void sig_statusbar_channel_redraw(void) { - gui_statusbar_redraw(channel_tag); + statusbar_item_redraw(channel_item); +} + +static void sig_statusbar_channel_redraw_window(WINDOW_REC *window) +{ + if (is_window_visible(window)) + statusbar_item_redraw(channel_item); +} + +static void sig_statusbar_channel_redraw_window_item(WI_ITEM_REC *item) +{ + WINDOW_REC *window; + + window = window_item_window(item); + if (window->active == item && is_window_visible(window)) + statusbar_item_redraw(channel_item); } static void draw_activity(gchar *title, gboolean act, gboolean det) { WINDOW_REC *window; GList *tmp; - gchar str[(sizeof(int) * CHAR_BIT + 2) / 3 + 1]; + gchar str[MAX_INT_STRLEN]; gboolean first, is_det; set_color((1 << 4)+7); addstr(title); @@ -291,7 +329,7 @@ static void draw_activity(gchar *title, gboolean act, gboolean det) addch(','); } - sprintf(str, "%d", g_slist_index(windows, window)+1); + ltoa(str, window->refnum); switch (window->new_data) { case NEWDATA_TEXT: @@ -309,7 +347,7 @@ static void draw_activity(gchar *title, gboolean act, gboolean det) } /* redraw activity */ -static void statusbar_activity(int xpos, int ypos, int size) +static void statusbar_activity(SBAR_ITEM_REC *item, int ypos) { WINDOW_REC *window; GList *tmp; @@ -322,7 +360,7 @@ static void statusbar_activity(int xpos, int ypos, int size) { window = tmp->data; - size_needed += 1+g_snprintf(str, sizeof(str), "%d", g_slist_index(windows, window)+1); + size_needed += 1+ltoa(str, window->refnum); if (!use_colors && window->new_data == NEWDATA_MSG_FORYOU) det = TRUE; @@ -334,17 +372,17 @@ static void statusbar_activity(int xpos, int ypos, int size) if (det) size_needed += 6; /* [Det: ], -1 */ if (act && det) size_needed--; - if (size != size_needed) + if (item->size != size_needed) { /* we need more (or less..) space! */ - gui_statusbar_resize(activity_tag, size_needed); + statusbar_item_resize(item, size_needed); return; } - if (size == 0) + if (item->size == 0) return; - move(ypos, xpos); + move(ypos, item->xpos); set_color((1 << 4)+3); addch('['); if (act) draw_activity("Act: ", TRUE, !det); if (act && det) addch(' '); @@ -356,19 +394,19 @@ static void statusbar_activity(int xpos, int ypos, int size) static void sig_statusbar_activity_hilight(WINDOW_REC *window, gpointer oldlevel) { - int pos, inspos; GList *tmp; + int inspos; g_return_if_fail(window != NULL); - if (settings_get_bool("toggle_actlist_moves")) + if (settings_get_bool("actlist_moves")) { /* Move the window to the first in the activity list */ if (g_list_find(activity_list, window) != NULL) activity_list = g_list_remove(activity_list, window); if (window->new_data != 0) activity_list = g_list_prepend(activity_list, window); - gui_statusbar_redraw(activity_tag); + statusbar_item_redraw(activity_item); return; } @@ -379,12 +417,12 @@ static void sig_statusbar_activity_hilight(WINDOW_REC *window, gpointer oldlevel { /* remove from activity list */ activity_list = g_list_remove(activity_list, window); - gui_statusbar_redraw(activity_tag); + statusbar_item_redraw(activity_item); } else if (window->new_data != GPOINTER_TO_INT(oldlevel)) { /* different level as last time, just redraw it. */ - gui_statusbar_redraw(activity_tag); + statusbar_item_redraw(activity_item); } return; } @@ -393,12 +431,12 @@ static void sig_statusbar_activity_hilight(WINDOW_REC *window, gpointer oldlevel return; /* add window to activity list .. */ - pos = g_slist_index(windows, window); - inspos = 0; for (tmp = activity_list; tmp != NULL; tmp = tmp->next, inspos++) { - if (pos < g_slist_index(windows, tmp->data)) + WINDOW_REC *rec = tmp->data; + + if (window->refnum < rec->refnum) { activity_list = g_list_insert(activity_list, window, inspos); break; @@ -407,7 +445,7 @@ static void sig_statusbar_activity_hilight(WINDOW_REC *window, gpointer oldlevel if (tmp == NULL) activity_list = g_list_append(activity_list, window); - gui_statusbar_redraw(activity_tag); + statusbar_item_redraw(activity_item); } static void sig_statusbar_activity_window_destroyed(WINDOW_REC *window) @@ -417,54 +455,50 @@ 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); - gui_statusbar_redraw(activity_tag); + statusbar_item_redraw(activity_item); } } /* redraw -- more -- */ -static void statusbar_more(int xpos, int ypos, int size) +static void statusbar_more(SBAR_ITEM_REC *item, int ypos) { - if (size != 10) return; + if (item->size != 10) return; - move(ypos, xpos); + move(ypos, item->xpos); set_color((1 << 4)+15); addstr("-- more --"); screen_refresh(); } static void sig_statusbar_more_check_remove(WINDOW_REC *window) { - g_return_if_fail(window != NULL); + g_return_if_fail(window != NULL); - if (!is_window_visible(window)) - return; + if (!is_window_visible(window)) + return; - if (more_tag != -1 && WINDOW_GUI(window)->bottom) - { - gui_statusbar_remove(more_tag); - more_tag = -1; - } + if (more_item != NULL && WINDOW_GUI(window)->bottom) { + statusbar_item_remove(more_item); + more_item = NULL; + } } static void sig_statusbar_more_check(WINDOW_REC *window) { - g_return_if_fail(window != NULL); + g_return_if_fail(window != NULL); - if (WINDOW_GUI(window)->parent->active != window) - return; + if (!is_window_visible(window)) + return; - if (!WINDOW_GUI(window)->bottom) - { - if (more_tag == -1) - more_tag = gui_statusbar_allocate(10, FALSE, FALSE, 0, statusbar_more); - } - else if (more_tag != -1) - { - gui_statusbar_remove(more_tag); - more_tag = -1; - } + if (!WINDOW_GUI(window)->bottom) { + if (more_item == NULL) + more_item = statusbar_item_create(mainbar, 10, FALSE, statusbar_more); + } else if (more_item != NULL) { + statusbar_item_remove(more_item); + more_item = NULL; + } } -static void statusbar_lag(int xpos, int ypos, int size) +static void statusbar_lag(SBAR_ITEM_REC *item, int ypos) { IRC_SERVER_REC *server; GString *str; @@ -494,18 +528,18 @@ static void statusbar_lag(int xpos, int ypos, int size) size_needed = str->len+7; } - if (size != size_needed) + if (item->size != size_needed) { /* we need more (or less..) space! */ - gui_statusbar_resize(lag_tag, size_needed); + statusbar_item_resize(item, size_needed); g_string_free(str, TRUE); return; } - if (size != 0) + if (item->size != 0) { lag_last_draw = now; - move(ypos, xpos); + move(ypos, item->xpos); set_color((1 << 4)+3); addch('['); set_color((1 << 4)+7); addstr("Lag: "); @@ -519,7 +553,7 @@ static void statusbar_lag(int xpos, int ypos, int size) static void sig_statusbar_lag_redraw(void) { - gui_statusbar_redraw(lag_tag); + statusbar_item_redraw(lag_item); } static int statusbar_lag_timeout(void) @@ -528,23 +562,23 @@ static int statusbar_lag_timeout(void) if (time(NULL)-lag_last_draw < LAG_REFRESH_TIME) return 1; - gui_statusbar_redraw(lag_tag); + statusbar_item_redraw(lag_item); return 1; } -static void statusbar_topic(int xpos, int ypos, int size) +static void statusbar_topic(SBAR_ITEM_REC *item, int ypos) { CHANNEL_REC *channel; QUERY_REC *query; char *str, *topic; - if (size != COLS-2) { + if (item->size != COLS-2) { /* get all space for topic */ - gui_statusbar_resize(topic_tag, COLS-2); + statusbar_item_resize(item, COLS-2); return; } - move(ypos, xpos); + move(ypos, item->xpos); set_bg((1<<4)+7); clrtoeol(); set_bg(0); if (active_win == NULL) @@ -557,51 +591,156 @@ static void statusbar_topic(int xpos, int ypos, int size) if (query != NULL && query->address != NULL) topic = query->address; if (topic == NULL) return; - str = g_strdup_printf("%.*s", size, topic); + topic = strip_codes(topic); + str = g_strdup_printf("%.*s", item->size, topic); set_color((1<<4)+15); addstr(str); g_free(str); + g_free(topic); screen_refresh(); } static void sig_statusbar_topic_redraw(void) { - gui_statusbar_redraw(topic_tag); + if (topic_item != NULL) statusbar_item_redraw(topic_item); } -static void read_settings(void) +static void sig_sidebars_redraw(void) { - int ypos; - - if (topic_tag == -1 && settings_get_bool("toggle_show_topicbar")) { - ypos = gui_statusbar_create(TRUE); - topic_tag = gui_statusbar_allocate(0, FALSE, TRUE, ypos, statusbar_topic); - 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); - } else if (topic_tag != -1 && !settings_get_bool("toggle_show_topicbar")) { - gui_statusbar_delete(TRUE, 0); - topic_tag = -1; - 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); + GSList *tmp; + + for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) { + MAIN_WINDOW_REC *rec = tmp->data; + + if (rec->statusbar_channel_item != NULL) + statusbar_item_redraw(rec->statusbar_channel_item); } +} + +static void topicbar_create(void) +{ + if (topic_bar != NULL) + return; + + topic_bar = statusbar_create(STATUSBAR_POS_UP, 0); + topic_item = statusbar_item_create(topic_bar, 0, FALSE, statusbar_topic); + 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); +} + +static void topicbar_destroy(void) +{ + if (topic_bar == NULL) + return; + + 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(channel_item); + statusbar_item_remove(activity_item); + statusbar_item_remove(lag_item); +} + +static void mainbar_add_items(MAIN_WINDOW_REC *window) +{ + mainbar = window->statusbar; + mainbar_window = window; + + clock_item = statusbar_item_create(mainbar, 7, FALSE, statusbar_clock); + nick_item = statusbar_item_create(mainbar, 2, FALSE, statusbar_nick); + channel_item = statusbar_item_create(mainbar, 2, FALSE, statusbar_channel); + activity_item = statusbar_item_create(mainbar, 0, FALSE, statusbar_activity); + lag_item = statusbar_item_create(mainbar, 0, FALSE, statusbar_lag); +} + +static void sidebar_add_items(MAIN_WINDOW_REC *window) +{ + window->statusbar_channel_item = + statusbar_item_create(window->statusbar, 3, FALSE, statusbar_channel); +} + +static void sidebar_remove_items(MAIN_WINDOW_REC *window) +{ + if (window->statusbar_channel_item != NULL) { + statusbar_item_remove(window->statusbar_channel_item); + window->statusbar_channel_item = NULL; + } +} + +static void sig_mainwindow_created(MAIN_WINDOW_REC *window) +{ + window->statusbar = statusbar_create(STATUSBAR_POS_MIDDLE, window->last_line+1); + sidebar_add_items(window); +} + +static void sig_mainwindow_destroyed(MAIN_WINDOW_REC *window) +{ + if (window == mainbar_window) { + 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"); + if (settings_get_bool("topicbar")) + topicbar_create(); + else if (!settings_get_bool("topicbar")) + topicbar_destroy(); lag_min_show = settings_get_int("lag_min_show")*10; } -void gui_statusbar_items_init(void) +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); /* clock */ - clock_tag = gui_statusbar_allocate(7, FALSE, FALSE, 0, statusbar_clock); clock_timetag = g_timeout_add(1000, (GSourceFunc) statusbar_clock_timeout, NULL); /* nick */ - nick_tag = gui_statusbar_allocate(2, FALSE, FALSE, 0, statusbar_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); @@ -613,45 +752,53 @@ void gui_statusbar_items_init(void) signal_add("away mode changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); /* channel */ - channel_tag = gui_statusbar_allocate(2, FALSE, FALSE, 0, statusbar_channel); signal_add("window changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw); - signal_add("window item changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw); - signal_add("channel mode changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw); - signal_add("window server changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw); + signal_add("window item changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw_window); + signal_add("channel mode changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw_window_item); + signal_add("window server changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw_window); + signal_add("window refnum changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw_window); /* activity */ activity_list = NULL; - activity_tag = gui_statusbar_allocate(0, FALSE, FALSE, 0, statusbar_activity); signal_add("window activity", (SIGNAL_FUNC) sig_statusbar_activity_hilight); signal_add("window destroyed", (SIGNAL_FUNC) sig_statusbar_activity_window_destroyed); /* more */ - more_tag = -1; + more_item = NULL; signal_add("gui page scrolled", (SIGNAL_FUNC) sig_statusbar_more_check_remove); signal_add("window item changed", (SIGNAL_FUNC) sig_statusbar_more_check); signal_add("gui print text", (SIGNAL_FUNC) sig_statusbar_more_check); /* lag */ - lag_tag = gui_statusbar_allocate(0, FALSE, FALSE, 0, statusbar_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); - /* topic bar */ - topic_tag = -1; + /* 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); } -void gui_statusbar_items_deinit(void) +void statusbar_items_deinit(void) { /* clock */ - gui_statusbar_remove(clock_tag); + g_source_remove(clock_timetag); /* nick */ - gui_statusbar_remove(nick_tag); - g_source_remove(clock_timetag); 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); @@ -663,31 +810,34 @@ void gui_statusbar_items_deinit(void) signal_remove("away mode changed", (SIGNAL_FUNC) sig_statusbar_nick_redraw); /* channel */ - gui_statusbar_remove(channel_tag); signal_remove("window changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw); - signal_remove("window item changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw); - signal_remove("channel mode changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw); - signal_remove("window server changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw); + signal_remove("window item changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw_window); + signal_remove("channel mode changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw_window_item); + signal_remove("window server changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw_window); + signal_remove("window refnum changed", (SIGNAL_FUNC) sig_statusbar_channel_redraw_window); /* activity */ - gui_statusbar_remove(activity_tag); signal_remove("window activity", (SIGNAL_FUNC) sig_statusbar_activity_hilight); signal_remove("window destroyed", (SIGNAL_FUNC) sig_statusbar_activity_window_destroyed); g_list_free(activity_list); /* more */ - if (more_tag != -1) gui_statusbar_remove(more_tag); signal_remove("gui page scrolled", (SIGNAL_FUNC) sig_statusbar_more_check_remove); signal_remove("window item changed", (SIGNAL_FUNC) sig_statusbar_more_check); signal_remove("gui print text", (SIGNAL_FUNC) sig_statusbar_more_check); /* lag */ - gui_statusbar_remove(lag_tag); 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); /* topic */ - if (topic_tag != -1) gui_statusbar_delete(TRUE, 0); + topicbar_destroy(); signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + + /* 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); } diff --git a/src/fe-text/statusbar.c b/src/fe-text/statusbar.c new file mode 100644 index 00000000..24e89107 --- /dev/null +++ b/src/fe-text/statusbar.c @@ -0,0 +1,266 @@ +/* + gui-statusbar.c : irssi + + Copyright (C) 1999 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 "server.h" + +#include "windows.h" + +#include "screen.h" +#include "statusbar.h" +#include "gui-windows.h" + +void statusbar_items_init(void); +void statusbar_items_deinit(void); + +static GSList *statusbars; +static int sbar_uppest, sbar_lowest, sbars_up, sbars_down; + +static void statusbar_item_destroy(SBAR_ITEM_REC *rec) +{ + rec->bar->items = g_slist_remove(rec->bar->items, rec); + g_free(rec); +} + +static void statusbar_redraw_line(STATUSBAR_REC *bar) +{ + static int recurses = 0, resized = FALSE; + STATUSBAR_FUNC func; + GSList *tmp; + int xpos, rxpos, old_resized; + + old_resized = resized; + resized = FALSE; + recurses++; + + xpos = 1; + for (tmp = bar->items; tmp != NULL; tmp = tmp->next) { + SBAR_ITEM_REC *rec = tmp->data; + + if (!rec->right_justify && xpos+rec->size < COLS) { + rec->xpos = xpos; + + func = rec->func; + func(rec, bar->ypos); + + if (resized) break; + if (rec->size > 0) xpos += rec->size+1; + } + } + + rxpos = COLS-1; + for (tmp = bar->items; tmp != NULL; tmp = tmp->next) { + SBAR_ITEM_REC *rec = tmp->data; + + if (rec->right_justify && rxpos-rec->size > xpos) { + rec->xpos = rxpos-rec->size; + + func = rec->func; + func(rec, bar->ypos); + + if (resized) break; + if (rec->size > 0) rxpos -= rec->size+1; + } + } + + resized = old_resized; + if (--recurses > 0) resized = TRUE; +} + +static void statusbar_redraw_all(void) +{ + GSList *tmp; + + screen_refresh_freeze(); + + for (tmp = statusbars; tmp != NULL; tmp = tmp->next) + statusbar_redraw(tmp->data); + + screen_refresh_thaw(); +} + +STATUSBAR_REC *statusbar_find(int pos, int line) +{ + GSList *tmp; + + for (tmp = statusbars; tmp != NULL; tmp = tmp->next) { + STATUSBAR_REC *rec = tmp->data; + + if (rec->pos == pos && rec->line == line) + return rec; + } + + return NULL; +} + +void statusbar_redraw(STATUSBAR_REC *bar) +{ + if (bar == NULL) { + statusbar_redraw_all(); + return; + } + + set_bg((1<<4)+15); + move(bar->ypos, 0); clrtoeol(); + set_bg(0); + + statusbar_redraw_line(bar); +} + +void statusbar_item_redraw(SBAR_ITEM_REC *item) +{ + STATUSBAR_FUNC func; + + g_return_if_fail(item != NULL); + + func = item->func; + func(item, item->bar->ypos); +} + +/* ypos is used only when pos == STATUSBAR_POS_MIDDLE */ +STATUSBAR_REC *statusbar_create(int pos, int ypos) +{ + STATUSBAR_REC *rec; + + rec = g_new0(STATUSBAR_REC, 1); + statusbars = g_slist_append(statusbars, rec); + + 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 : LINES-1-rec->line; + + 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; + } + + set_bg((1<<4)+15); + move(rec->ypos, 0); clrtoeol(); + set_bg(0); + + return rec; +} + +static void statusbars_pack(int pos, int line) +{ + GSList *tmp; + + for (tmp = statusbars; 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; + } + } +} + +void statusbar_destroy(STATUSBAR_REC *bar) +{ + g_return_if_fail(bar != NULL); + + if (bar->pos != STATUSBAR_POS_MIDDLE) + mainwindows_reserve_lines(-1, bar->pos == STATUSBAR_POS_UP); + + if (bar->pos == STATUSBAR_POS_UP) sbars_up--; + if (bar->pos == STATUSBAR_POS_DOWN) sbars_down--; + statusbars = g_slist_remove(statusbars, bar); + + while (bar->items != NULL) + statusbar_item_destroy(bar->items->data); + + if (bar->pos != STATUSBAR_POS_MIDDLE) + statusbars_pack(bar->pos, bar->pos); + g_free(bar); + + if (!quitting) statusbar_redraw_all(); +} + +SBAR_ITEM_REC *statusbar_item_create(STATUSBAR_REC *bar, int size, int right_justify, STATUSBAR_FUNC func) +{ + SBAR_ITEM_REC *rec; + + g_return_val_if_fail(bar != NULL, NULL); + g_return_val_if_fail(func != NULL, NULL); + + rec = g_new0(SBAR_ITEM_REC, 1); + rec->bar = bar; + bar->items = g_slist_append(bar->items, rec); + + rec->xpos = -1; + rec->size = size; + rec->right_justify = right_justify; + rec->func = func; + + return rec; +} + +void statusbar_item_resize(SBAR_ITEM_REC *item, int size) +{ + g_return_if_fail(item != NULL); + + item->size = size; + statusbar_redraw_all(); +} + +void statusbar_item_remove(SBAR_ITEM_REC *item) +{ + g_return_if_fail(item != NULL); + + statusbar_item_destroy(item); + if (!quitting) statusbar_redraw_all(); +} + +static void sig_mainwindow_resized(MAIN_WINDOW_REC *window) +{ + STATUSBAR_REC *rec; + + rec = window->statusbar; + rec->ypos = window->last_line+1; +} + +void statusbar_init(void) +{ + statusbars = NULL; + sbars_up = sbars_down = 0; + + statusbar_items_init(); + signal_add("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized); + signal_add("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized); +} + +void statusbar_deinit(void) +{ + statusbar_items_deinit(); + + while (statusbars != NULL) + statusbar_destroy(statusbars->data); + + signal_remove("mainwindow resized", (SIGNAL_FUNC) sig_mainwindow_resized); + signal_remove("mainwindow moved", (SIGNAL_FUNC) sig_mainwindow_resized); +} diff --git a/src/fe-text/statusbar.h b/src/fe-text/statusbar.h new file mode 100644 index 00000000..3ca133ef --- /dev/null +++ b/src/fe-text/statusbar.h @@ -0,0 +1,45 @@ +#ifndef __STATUSBAR_H +#define __STATUSBAR_H + +enum { + STATUSBAR_POS_UP, + STATUSBAR_POS_MIDDLE, + STATUSBAR_POS_DOWN +}; + +typedef struct { + int pos; + int line; + + int ypos; /* real position in screen at the moment */ + GSList *items; +} STATUSBAR_REC; + +typedef struct { + STATUSBAR_REC *bar; + + int xpos, size; + int right_justify; + void *func; +} SBAR_ITEM_REC; + +typedef void (*STATUSBAR_FUNC) (SBAR_ITEM_REC *item, int ypos); + +/* ypos is used only when pos == STATUSBAR_POS_MIDDLE */ +STATUSBAR_REC *statusbar_create(int pos, int ypos); +void statusbar_destroy(STATUSBAR_REC *bar); + +STATUSBAR_REC *statusbar_find(int pos, int line); + +SBAR_ITEM_REC *statusbar_item_create(STATUSBAR_REC *bar, int size, gboolean right_justify, STATUSBAR_FUNC func); +void statusbar_item_resize(SBAR_ITEM_REC *item, int size); +void statusbar_item_remove(SBAR_ITEM_REC *item); + +/* redraw statusbar, NULL = all */ +void statusbar_redraw(STATUSBAR_REC *bar); +void statusbar_item_redraw(SBAR_ITEM_REC *item); + +void statusbar_init(void); +void statusbar_deinit(void); + +#endif |