# HG changeset patch # User mikael # Date 1114917259 0 # Node ID b69c0b7a23e33a23fd9fb878b16eb5544207b971 # Parent 5647381a7dfb1315d855549905dd9d279b8bb43c [/trunk] Changeset 163 by mikael * Window resize handling 8-) diff -r 5647381a7dfb -r b69c0b7a23e3 mcabber/src/TODO --- a/mcabber/src/TODO Sun May 01 03:09:40 2005 +0000 +++ b/mcabber/src/TODO Sun May 01 03:14:19 2005 +0000 @@ -2,8 +2,8 @@ BUGS: * Presence notification is always accepted. -* Resize not handled. * I have seen a segfault, but don't know how to reproduce it... + Seems to be due to a disconnection from the server. TODO: @@ -15,6 +15,8 @@ * Key bindings (ex: F5 <-> /group toggle) * Pending message not displayed if buddy outside Contact window, maybe we could show it someway (maybe just a flag?). +* Add a function in hbuf ~previous_persistent(hbuf *top) (to avoid loosing the + top variable). * Commands! :-) - /roster @@ -39,7 +41,6 @@ * External commands for events * Multi-lines * Handle message type "error" -* Handle window resize * Read history * Shortcut to jump to next message received (shift-tab?) * File transfer? :) diff -r 5647381a7dfb -r b69c0b7a23e3 mcabber/src/main.c --- a/mcabber/src/main.c Sun May 01 03:09:40 2005 +0000 +++ b/mcabber/src/main.c Sun May 01 03:14:19 2005 +0000 @@ -81,6 +81,7 @@ unsigned int ping; int ssl; int ret = 0; + unsigned int refresh = 0; credits(); @@ -150,7 +151,7 @@ scr_InitCurses(); ut_WriteLog("Drawing main window...\n"); - scr_DrawMainWindow(); + scr_DrawMainWindow(TRUE); optstring = cfg_read("logging"); if (optstring && (atoi(optstring) > 0)) @@ -194,11 +195,17 @@ ut_WriteLog("Ready to send/receive messages...\n"); jb_reset_keepalive(); - keypad(scr_GetInputWindow(), TRUE); while (ret != 255) { key = scr_Getch(); + + // The refresh is really an ugly hack, but we need to call doupdate() + // from time to time to catch the RESIZE events, because getch keep + // returning ERR until a real key is pressed :-( if (key != ERR) ret = process_key(key); + else if (++refresh % 2) + doupdate(); + jb_main(); if (update_roster) scr_DrawRoster(); diff -r 5647381a7dfb -r b69c0b7a23e3 mcabber/src/screen.c --- a/mcabber/src/screen.c Sun May 01 03:09:40 2005 +0000 +++ b/mcabber/src/screen.c Sun May 01 03:14:19 2005 +0000 @@ -18,6 +18,8 @@ #define window_entry(n) list_entry(n, window_entry_t, list) +inline void check_offset(int); + LIST_HEAD(window_list); typedef struct _window_entry_t { @@ -176,11 +178,20 @@ } -window_entry_t *scr_CreatePanel(const char *title, int x, int y, - int lines, int cols, int dont_show) +window_entry_t *scr_CreateBuddyPanel(const char *title, int dont_show) { + int x; + int y; + int lines; + int cols; window_entry_t *tmp = calloc(1, sizeof(window_entry_t)); + // Dimensions + x = ROSTER_WIDTH; + y = 0; + lines = CHAT_WIN_HEIGHT; + cols = maxX - ROSTER_WIDTH; + tmp->win = newwin(lines, cols, y, x); tmp->panel = new_panel(tmp->win); tmp->name = (char *) calloc(1, 1024); @@ -365,8 +376,7 @@ // If the window entry doesn't exist yet, let's create it. if (win_entry == NULL) { - win_entry = scr_CreatePanel(winId, ROSTER_WIDTH, 0, CHAT_WIN_HEIGHT, - maxX - ROSTER_WIDTH, dont_show); + win_entry = scr_CreateBuddyPanel(winId, dont_show); } hbuf_add_line(&win_entry->hbuf, text, fullprefix, @@ -419,41 +429,130 @@ return; } -void scr_DrawMainWindow(void) +// scr_DrawMainWindow() +// Set fullinit to TRUE to also create panels +// +// I think it could be improved a _lot_ but I'm really not an ncurses +// expert... :-\ Mikael. +// +void scr_DrawMainWindow(unsigned int fullinit) { int l; - /* Draw main panels */ + /* Create windows */ rosterWnd = newwin(CHAT_WIN_HEIGHT, ROSTER_WIDTH, 0, 0); - rosterPanel = new_panel(rosterWnd); + chatWnd = newwin(CHAT_WIN_HEIGHT, maxX - ROSTER_WIDTH, 0, ROSTER_WIDTH); + logWnd_border = newwin(LOG_WIN_HEIGHT, maxX, CHAT_WIN_HEIGHT, 0); + logWnd = derwin(logWnd_border, LOG_WIN_HEIGHT-2, maxX-2, 1, 1); + inputWnd = newwin(1, maxX, maxY-1, 0); + + /* Draw/init windows */ + + // - Clear roster and draw vertical line scr_clear_box(rosterWnd, 0, 0, CHAT_WIN_HEIGHT, ROSTER_WIDTH, COLOR_GENERAL); for (l=0 ; l < CHAT_WIN_HEIGHT ; l++) mvwaddch(rosterWnd, l, ROSTER_WIDTH-1, ACS_VLINE); - chatWnd = newwin(CHAT_WIN_HEIGHT, maxX - ROSTER_WIDTH, 0, ROSTER_WIDTH); - chatPanel = new_panel(chatWnd); + // - Clear chat window scr_clear_box(chatWnd, 0, 0, CHAT_WIN_HEIGHT, maxX - ROSTER_WIDTH, COLOR_GENERAL); - scrollok(chatWnd, TRUE); mvwprintw(chatWnd, 0, 0, "This is the status window"); - logWnd_border = newwin(LOG_WIN_HEIGHT, maxX, CHAT_WIN_HEIGHT, 0); - logPanel_border = new_panel(logWnd_border); + // - Draw/clear the log window scr_draw_box(logWnd_border, 0, 0, LOG_WIN_HEIGHT, maxX, COLOR_GENERAL, 0, 0); - logWnd = derwin(logWnd_border, LOG_WIN_HEIGHT-2, maxX-2, 1, 1); - logPanel = new_panel(logWnd); wbkgd(logWnd, COLOR_PAIR(COLOR_GENERAL)); - scrollok(logWnd, TRUE); - inputWnd = newwin(1, maxX, maxY-1, 0); - inputPanel = new_panel(inputWnd); + // Enable keypad (+ special keys) + keypad(inputWnd, TRUE); + if (fullinit) { + // Create panels + rosterPanel = new_panel(rosterWnd); + chatPanel = new_panel(chatWnd); + logPanel_border = new_panel(logWnd_border); + logPanel = new_panel(logWnd); + inputPanel = new_panel(inputWnd); + } + + // We'll need to redraw the roster update_roster = TRUE; return; } +// scr_Resize() +// Function called when the window is resized. +// - Recreate windows +// - Update panels +// - Rewrap lines in each buddy buffer +void scr_Resize() +{ + WINDOW *w_roster, *w_chat, *w_log, *w_log_bord, *w_input; + + struct list_head *pos, *n; + window_entry_t *search_entry; + int x, y, lines, cols; + + // First, update the global variables + getmaxyx(stdscr, maxY, maxX); + // Make sure the cursor stays inside the window + check_offset(0); + + // Backup pointers + w_roster = rosterWnd; + w_chat = chatWnd; + w_log = logWnd; + w_log_bord = logWnd_border; + w_input = inputWnd; + + // Recreate windows + scr_DrawMainWindow(FALSE); + + // Replace windows for panels + replace_panel(rosterPanel, rosterWnd); + replace_panel(chatPanel, chatWnd); + replace_panel(logPanel, logWnd); + replace_panel(logPanel_border, logWnd_border); + replace_panel(inputPanel, inputWnd); + + // Destroy old windows + delwin(w_roster); + delwin(w_chat); + delwin(w_log); + delwin(w_log_bord); + delwin(w_input); + + // Resize all buddy windows + x = ROSTER_WIDTH; + y = 0; + lines = CHAT_WIN_HEIGHT; + cols = maxX - ROSTER_WIDTH; + + list_for_each_safe(pos, n, &window_list) { + search_entry = window_entry(pos); + if (search_entry->win) { + WINDOW *w_buddy = search_entry->win; + // Create new window + search_entry->win = newwin(lines, cols, y, x); + scr_clear_box(search_entry->win, 0, 0, lines, cols, COLOR_GENERAL); + // If a panel exists, replace the old window with the new + if (search_entry->panel) { + replace_panel(search_entry->panel, search_entry->win); + } + // Redo line wrapping + hbuf_rebuild(&search_entry->hbuf, + maxX - scr_WindowWidth(rosterWnd) - 14); + // Delete old buddy window + delwin(w_buddy); + } + } + + // Refresh current buddy window + if (chatmode) + scr_ShowBuddyWindow(); +} + // scr_DrawRoster() // Actually, display the buddylist on the screen. void scr_DrawRoster(void) @@ -1104,6 +1203,10 @@ top_panel(chatPanel); top_panel(inputPanel); break; + case 12: // Ctrl-l + case KEY_RESIZE: + scr_Resize(); + break; default: scr_LogPrint("Unkown key=%d", key); } diff -r 5647381a7dfb -r b69c0b7a23e3 mcabber/src/screen.h --- a/mcabber/src/screen.h Sun May 01 03:09:40 2005 +0000 +++ b/mcabber/src/screen.h Sun May 01 03:14:19 2005 +0000 @@ -19,7 +19,7 @@ extern int update_roster; void scr_InitCurses(void); -void scr_DrawMainWindow(void); +void scr_DrawMainWindow(unsigned int fullinit); void scr_DrawRoster(void); void scr_TerminateCurses(void); void scr_WriteIncomingMessage(const char *jidfrom, const char *text);