From a63d0aff98a761cd4823cba03ece5b16f3e52458 Mon Sep 17 00:00:00 2001 From: James Booth Date: Mon, 28 Jan 2013 01:17:46 +0000 Subject: Renamed UI related files --- Makefile.am | 6 +- src/input_win.c | 569 ------------ src/status_bar.c | 285 ------ src/title_bar.c | 221 ----- src/ui_inputwin.c | 569 ++++++++++++ src/ui_statusbar.c | 285 ++++++ src/ui_titlebar.c | 221 +++++ src/ui_windows.c | 2423 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/windows.c | 2423 ---------------------------------------------------- 9 files changed, 3501 insertions(+), 3501 deletions(-) delete mode 100644 src/input_win.c delete mode 100644 src/status_bar.c delete mode 100644 src/title_bar.c create mode 100644 src/ui_inputwin.c create mode 100644 src/ui_statusbar.c create mode 100644 src/ui_titlebar.c create mode 100644 src/ui_windows.c delete mode 100644 src/windows.c diff --git a/Makefile.am b/Makefile.am index 0a6b95b0..5de143b6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,9 +1,9 @@ bin_PROGRAMS = profanity profanity_SOURCES = src/command.c src/contact.c src/history.c src/xmpp.h \ - src/preferences.c src/autocomplete.c src/status_bar.c \ + src/preferences.c src/autocomplete.c src/ui_statusbar.c \ src/command.h src/contact.h src/history.h src/log.c src/preferences.h \ - src/autocomplete.h src/title_bar.c src/windows.c src/common.c \ - src/contact_list.c src/input_win.c src/log.h src/profanity.c \ + src/autocomplete.h src/ui_titlebar.c src/ui_windows.c src/common.c \ + src/contact_list.c src/ui_inputwin.c src/log.h src/profanity.c \ src/prof_history.c src/ui.h src/common.h src/ contact_list.h src/xmpp_conn.c \ src/main.c src/profanity.h src/prof_history.h src/chat_log.c \ src/chat_log.h src/tinyurl.c src/tinyurl.h src/chat_session.c \ diff --git a/src/input_win.c b/src/input_win.c deleted file mode 100644 index 20971c0f..00000000 --- a/src/input_win.c +++ /dev/null @@ -1,569 +0,0 @@ -/* - * input_win.c - * - * Copyright (C) 2012, 2013 James Booth - * - * This file is part of Profanity. - * - * Profanity 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 3 of the License, or - * (at your option) any later version. - * - * Profanity 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 Profanity. If not, see . - * - */ - -#define _XOPEN_SOURCE_EXTENDED -#include "config.h" - -#include -#include -#include - -#ifdef HAVE_NCURSESW_NCURSES_H -#include -#elif HAVE_NCURSES_H -#include -#endif - -#include "common.h" -#include "command.h" -#include "contact_list.h" -#include "history.h" -#include "log.h" -#include "preferences.h" -#include "profanity.h" -#include "theme.h" -#include "ui.h" - -#define _inp_win_refresh() prefresh(inp_win, 0, pad_start, rows-1, 0, rows-1, cols-1) - -static WINDOW *inp_win; -static int pad_start = 0; -static int rows, cols; - -static int _handle_edit(int result, const wint_t ch, char *input, int *size); -static int _printable(const wint_t ch); -static void _clear_input(void); -static void _go_to_end(int display_size); - -void -create_input_window(void) -{ -#ifdef NCURSES_REENTRANT - set_escdelay(25); -#else - ESCDELAY = 25; -#endif - getmaxyx(stdscr, rows, cols); - inp_win = newpad(1, INP_WIN_MAX); - wbkgd(inp_win, COLOUR_INPUT_TEXT); - keypad(inp_win, TRUE); - wmove(inp_win, 0, 0); - _inp_win_refresh(); -} - -void -inp_win_resize(const char * const input, const int size) -{ - int inp_x; - getmaxyx(stdscr, rows, cols); - inp_x = getcurx(inp_win); - - // if lost cursor off screen, move contents to show it - if (inp_x >= pad_start + cols) { - pad_start = inp_x - (cols / 2); - if (pad_start < 0) { - pad_start = 0; - } - } - - _inp_win_refresh(); -} - -void -inp_non_block(void) -{ - wtimeout(inp_win, 20); -} - -void -inp_block(void) -{ - wtimeout(inp_win, -1); -} - -wint_t -inp_get_char(char *input, int *size) -{ - int inp_x = 0; - int i; - wint_t ch; - int display_size = 0; - - if (*size != 0) { - display_size = g_utf8_strlen(input, *size); - } - - // echo off, and get some more input - noecho(); - int result = wget_wch(inp_win, &ch); - - gboolean in_command = FALSE; - if ((display_size > 0 && input[0] == '/') || - (display_size == 0 && ch == '/')) { - in_command = TRUE; - } - - if (prefs_get_states()) { - if (result == ERR) { - prof_handle_idle(); - } - if (prefs_get_outtype() && (result != ERR) && !in_command - && _printable(ch)) { - prof_handle_activity(); - } - } - - // if it wasn't an arrow key etc - if (!_handle_edit(result, ch, input, size)) { - if (_printable(ch) && result != KEY_CODE_YES) { - inp_x = getcurx(inp_win); - - // handle insert if not at end of input - if (inp_x < display_size) { - char bytes[MB_CUR_MAX]; - size_t utf_len = wcrtomb(bytes, ch, NULL); - - char *next_ch = g_utf8_offset_to_pointer(input, inp_x); - char *offset; - for (offset = &input[*size - 1]; offset >= next_ch; offset--) { - *(offset + utf_len) = *offset; - } - for (i = 0; i < utf_len; i++) { - *(next_ch + i) = bytes[i]; - } - - *size += utf_len; - input[*size] = '\0'; - wprintw(inp_win, next_ch); - wmove(inp_win, 0, inp_x + 1); - - if (inp_x - pad_start > cols-3) { - pad_start++; - _inp_win_refresh(); - } - - // otherwise just append - } else { - char bytes[MB_CUR_MAX+1]; - size_t utf_len = wcrtomb(bytes, ch, NULL); - - // wcrtomb can return (size_t) -1 - if (utf_len < MB_CUR_MAX) { - for (i = 0 ; i < utf_len; i++) { - input[(*size)++] = bytes[i]; - } - input[*size] = '\0'; - - bytes[utf_len] = '\0'; - wprintw(inp_win, bytes); - display_size++; - - // if gone over screen size follow input - int rows, cols; - getmaxyx(stdscr, rows, cols); - if (display_size - pad_start > cols-2) { - pad_start++; - _inp_win_refresh(); - } - } - } - - cmd_reset_autocomplete(); - } - } - - echo(); - - return ch; -} - -void -inp_get_password(char *passwd) -{ - _clear_input(); - _inp_win_refresh(); - noecho(); - mvwgetnstr(inp_win, 0, 1, passwd, 20); - wmove(inp_win, 0, 0); - echo(); - status_bar_clear(); -} - -void -inp_put_back(void) -{ - _inp_win_refresh(); -} - -void -inp_replace_input(char *input, const char * const new_input, int *size) -{ - int display_size; - strcpy(input, new_input); - *size = strlen(input); - display_size = g_utf8_strlen(input, *size); - inp_win_reset(); - input[*size] = '\0'; - wprintw(inp_win, input); - _go_to_end(display_size); -} - -void -inp_win_reset(void) -{ - _clear_input(); - pad_start = 0; - _inp_win_refresh(); -} - -static void -_clear_input(void) -{ - wclear(inp_win); - wmove(inp_win, 0, 0); -} - -/* - * Deal with command editing, return 1 if ch was an edit - * key press: up, down, left, right or backspace - * return 0 if it wasnt - */ -static int -_handle_edit(int result, const wint_t ch, char *input, int *size) -{ - char *prev = NULL; - char *next = NULL; - int inp_x = 0; - int next_ch; - int display_size = 0; - - if (*size != 0) { - display_size = g_utf8_strlen(input, *size); - } - - inp_x = getcurx(inp_win); - - // CTRL-LEFT - if ((result == KEY_CODE_YES) && (ch == 545 || ch == 540 || ch == 539) && (inp_x > 0)) { - input[*size] = '\0'; - gchar *curr_ch = g_utf8_offset_to_pointer(input, inp_x); - curr_ch = g_utf8_find_prev_char(input, curr_ch); - gchar *prev_ch; - gunichar curr_uni; - gunichar prev_uni; - - while (curr_ch != NULL) { - curr_uni = g_utf8_get_char(curr_ch); - - if (g_unichar_isspace(curr_uni)) { - curr_ch = g_utf8_find_prev_char(input, curr_ch); - } else { - prev_ch = g_utf8_find_prev_char(input, curr_ch); - if (prev_ch == NULL) { - curr_ch = NULL; - break; - } else { - prev_uni = g_utf8_get_char(prev_ch); - if (g_unichar_isspace(prev_uni)) { - break; - } else { - curr_ch = prev_ch; - } - } - } - } - - if (curr_ch == NULL) { - inp_x = 0; - wmove(inp_win, 0, inp_x); - } else { - glong offset = g_utf8_pointer_to_offset(input, curr_ch); - inp_x = offset; - wmove(inp_win, 0, inp_x); - } - - // if gone off screen to left, jump left (half a screen worth) - if (inp_x <= pad_start) { - pad_start = pad_start - (cols / 2); - if (pad_start < 0) { - pad_start = 0; - } - - _inp_win_refresh(); - } - return 1; - - // CTRL-RIGHT - } else if ((result == KEY_CODE_YES) && (ch == 560 || ch == 555 || ch == 554) && (inp_x < display_size)) { - input[*size] = '\0'; - gchar *curr_ch = g_utf8_offset_to_pointer(input, inp_x); - gchar *next_ch = g_utf8_find_next_char(curr_ch, NULL); - gunichar curr_uni; - gunichar next_uni; - gboolean moved = FALSE; - - while (g_utf8_pointer_to_offset(input, next_ch) < display_size) { - curr_uni = g_utf8_get_char(curr_ch); - next_uni = g_utf8_get_char(next_ch); - curr_ch = next_ch; - next_ch = g_utf8_find_next_char(next_ch, NULL); - - if (!g_unichar_isspace(curr_uni) && g_unichar_isspace(next_uni) && moved) { - break; - } else { - moved = TRUE; - } - } - - if (next_ch == NULL) { - inp_x = display_size; - wmove(inp_win, 0, inp_x); - } else { - glong offset = g_utf8_pointer_to_offset(input, curr_ch); - if (offset == display_size - 1) { - inp_x = offset + 1; - } else { - inp_x = offset; - } - wmove(inp_win, 0, inp_x); - } - - // if gone off screen to right, jump right (half a screen worth) - if (inp_x > pad_start + cols) { - pad_start = pad_start + (cols / 2); - _inp_win_refresh(); - } - - return 1; - - // other editing keys - } else { - switch(ch) { - - case 27: // ESC - // check for ALT-num - next_ch = wgetch(inp_win); - if (next_ch != ERR) { - switch (next_ch) - { - case '1': - ui_switch_win(0); - break; - case '2': - ui_switch_win(1); - break; - case '3': - ui_switch_win(2); - break; - case '4': - ui_switch_win(3); - break; - case '5': - ui_switch_win(4); - break; - case '6': - ui_switch_win(5); - break; - case '7': - ui_switch_win(6); - break; - case '8': - ui_switch_win(7); - break; - case '9': - ui_switch_win(8); - break; - case '0': - ui_switch_win(9); - break; - default: - break; - } - return 1; - } else { - *size = 0; - inp_win_reset(); - return 1; - } - - case 127: - case KEY_BACKSPACE: - contact_list_reset_search_attempts(); - if (display_size > 0) { - - // if at end, delete last char - if (inp_x >= display_size) { - gchar *start = g_utf8_substring(input, 0, inp_x-1); - for (*size = 0; *size < strlen(start); (*size)++) { - input[*size] = start[*size]; - } - input[*size] = '\0'; - - g_free(start); - - _clear_input(); - wprintw(inp_win, input); - wmove(inp_win, 0, inp_x -1); - - // if in middle, delete and shift chars left - } else if (inp_x > 0 && inp_x < display_size) { - gchar *start = g_utf8_substring(input, 0, inp_x - 1); - gchar *end = g_utf8_substring(input, inp_x, *size); - GString *new = g_string_new(start); - g_string_append(new, end); - - for (*size = 0; *size < strlen(new->str); (*size)++) { - input[*size] = new->str[*size]; - } - input[*size] = '\0'; - - g_free(start); - g_free(end); - g_string_free(new, FALSE); - - _clear_input(); - wprintw(inp_win, input); - wmove(inp_win, 0, inp_x -1); - } - - // if gone off screen to left, jump left (half a screen worth) - if (inp_x <= pad_start) { - pad_start = pad_start - (cols / 2); - if (pad_start < 0) { - pad_start = 0; - } - - _inp_win_refresh(); - } - } - return 1; - - case KEY_DC: // DEL - if (inp_x == display_size-1) { - gchar *start = g_utf8_substring(input, 0, inp_x); - for (*size = 0; *size < strlen(start); (*size)++) { - input[*size] = start[*size]; - } - input[*size] = '\0'; - - g_free(start); - - _clear_input(); - wprintw(inp_win, input); - } else if (inp_x < display_size-1) { - gchar *start = g_utf8_substring(input, 0, inp_x); - gchar *end = g_utf8_substring(input, inp_x+1, *size); - GString *new = g_string_new(start); - g_string_append(new, end); - - for (*size = 0; *size < strlen(new->str); (*size)++) { - input[*size] = new->str[*size]; - } - input[*size] = '\0'; - - g_free(start); - g_free(end); - g_string_free(new, FALSE); - - _clear_input(); - wprintw(inp_win, input); - wmove(inp_win, 0, inp_x); - } - return 1; - - case KEY_LEFT: - if (inp_x > 0) { - wmove(inp_win, 0, inp_x-1); - - // current position off screen to left - if (inp_x - 1 < pad_start) { - pad_start--; - _inp_win_refresh(); - } - } - return 1; - - case KEY_RIGHT: - if (inp_x < display_size) { - wmove(inp_win, 0, inp_x+1); - - // current position off screen to right - if ((inp_x + 1 - pad_start) >= cols) { - pad_start++; - _inp_win_refresh(); - } - } - return 1; - - case KEY_UP: - prev = history_previous(input, size); - if (prev) { - inp_replace_input(input, prev, size); - } - return 1; - - case KEY_DOWN: - next = history_next(input, size); - if (next) { - inp_replace_input(input, next, size); - } - return 1; - - case KEY_HOME: - wmove(inp_win, 0, 0); - pad_start = 0; - _inp_win_refresh(); - return 1; - - case KEY_END: - _go_to_end(display_size); - return 1; - - case 9: // tab - cmd_autocomplete(input, size); - return 1; - - default: - return 0; - } - } -} - -static void -_go_to_end(int display_size) -{ - wmove(inp_win, 0, display_size); - if (display_size > cols-2) { - pad_start = display_size - cols + 1; - _inp_win_refresh(); - } -} - -static int -_printable(const wint_t ch) -{ - char bytes[MB_CUR_MAX+1]; - size_t utf_len = wcrtomb(bytes, ch, NULL); - bytes[utf_len] = '\0'; - gunichar unichar = g_utf8_get_char(bytes); - return g_unichar_isprint(unichar) && (ch != KEY_MOUSE); -} diff --git a/src/status_bar.c b/src/status_bar.c deleted file mode 100644 index 34347572..00000000 --- a/src/status_bar.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * status_bar.c - * - * Copyright (C) 2012, 2013 James Booth - * - * This file is part of Profanity. - * - * Profanity 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 3 of the License, or - * (at your option) any later version. - * - * Profanity 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 Profanity. If not, see . - * - */ - -#include "config.h" - -#include -#include - -#ifdef HAVE_NCURSESW_NCURSES_H -#include -#elif HAVE_NCURSES_H -#include -#endif - -#include "theme.h" -#include "ui.h" - -static WINDOW *status_bar; -static char *message = NULL; -static char _active[31] = "[ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]"; -static int is_active[10]; -static int is_new[10]; -static int dirty; -static GDateTime *last_time; - -static void _status_bar_update_time(void); - -void -create_status_bar(void) -{ - int rows, cols, i; - getmaxyx(stdscr, rows, cols); - - is_active[0] = TRUE; - is_new[0] = FALSE; - for (i = 1; i < 10; i++) { - is_active[i] = FALSE; - is_new[i] = FALSE; - } - - status_bar = newwin(1, cols, rows-2, 0); - wbkgd(status_bar, COLOUR_STATUS_TEXT); - wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwprintw(status_bar, 0, cols - 31, _active); - wattroff(status_bar, COLOUR_STATUS_BRACKET); - - last_time = g_date_time_new_now_local(); - - dirty = TRUE; -} - -void -status_bar_refresh(void) -{ - GDateTime *now_time = g_date_time_new_now_local(); - GTimeSpan elapsed = g_date_time_difference(now_time, last_time); - - if (elapsed >= 60000000) { - dirty = TRUE; - last_time = g_date_time_new_now_local(); - } - - if (dirty) { - _status_bar_update_time(); - wrefresh(status_bar); - inp_put_back(); - dirty = FALSE; - } - - g_date_time_unref(now_time); -} - -void -status_bar_resize(void) -{ - int rows, cols, i; - getmaxyx(stdscr, rows, cols); - - mvwin(status_bar, rows-2, 0); - wresize(status_bar, 1, cols); - wbkgd(status_bar, COLOUR_STATUS_TEXT); - wclear(status_bar); - wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwprintw(status_bar, 0, cols - 31, _active); - wattroff(status_bar, COLOUR_STATUS_BRACKET); - - for(i = 0; i < 10; i++) { - if (is_new[i]) - status_bar_new(i); - else if (is_active[i]) - status_bar_active(i); - } - - if (message != NULL) - mvwprintw(status_bar, 0, 10, message); - - last_time = g_date_time_new_now_local(); - dirty = TRUE; -} - -void -status_bar_inactive(const int win) -{ - is_active[win] = FALSE; - is_new[win] = FALSE; - - int active_pos = 1 + (win * 3); - - int cols = getmaxx(stdscr); - - mvwaddch(status_bar, 0, cols - 31 + active_pos, ' '); - - dirty = TRUE; -} - -void -status_bar_active(const int win) -{ - is_active[win] = TRUE; - is_new[win] = FALSE; - - int active_pos = 1 + (win * 3); - - int cols = getmaxx(stdscr); - - wattron(status_bar, COLOUR_STATUS_ACTIVE); - if (win+1 < 10) - mvwprintw(status_bar, 0, cols - 31 + active_pos, "%d", win+1); - else - mvwprintw(status_bar, 0, cols - 31 + active_pos, "0"); - wattroff(status_bar, COLOUR_STATUS_ACTIVE); - - dirty = TRUE; -} - -void -status_bar_new(const int win) -{ - is_active[win] = TRUE; - is_new[win] = TRUE; - - int active_pos = 1 + (win * 3); - - int cols = getmaxx(stdscr); - - wattron(status_bar, COLOUR_STATUS_NEW); - wattron(status_bar, A_BLINK); - if (win+1 < 10) - mvwprintw(status_bar, 0, cols - 31 + active_pos, "%d", win+1); - else - mvwprintw(status_bar, 0, cols - 31 + active_pos, "0"); - wattroff(status_bar, COLOUR_STATUS_NEW); - wattroff(status_bar, A_BLINK); - - dirty = TRUE; -} - -void -status_bar_get_password(void) -{ - status_bar_print_message("Enter password:"); - dirty = TRUE; -} - -void -status_bar_print_message(const char * const msg) -{ - if (message != NULL) { - free(message); - message = NULL; - } - - wclear(status_bar); - - message = (char *) malloc((strlen(msg) + 1) * sizeof(char)); - strcpy(message, msg); - mvwprintw(status_bar, 0, 10, message); - - int cols = getmaxx(stdscr); - - wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwprintw(status_bar, 0, cols - 31, _active); - wattroff(status_bar, COLOUR_STATUS_BRACKET); - - int i; - for(i = 0; i < 10; i++) { - if (is_new[i]) - status_bar_new(i); - else if (is_active[i]) - status_bar_active(i); - } - - dirty = TRUE; -} - -void -status_bar_clear(void) -{ - if (message != NULL) { - free(message); - message = NULL; - } - - int i; - is_active[0] = TRUE; - is_new[0] = FALSE; - for (i = 1; i < 10; i++) { - is_active[i] = FALSE; - is_new[i] = FALSE; - } - - wclear(status_bar); - - int cols = getmaxx(stdscr); - - wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwprintw(status_bar, 0, cols - 31, _active); - wattroff(status_bar, COLOUR_STATUS_BRACKET); - - dirty = TRUE; -} - -void -status_bar_clear_message(void) -{ - if (message != NULL) { - free(message); - message = NULL; - } - - wclear(status_bar); - - int cols = getmaxx(stdscr); - - wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwprintw(status_bar, 0, cols - 31, _active); - wattroff(status_bar, COLOUR_STATUS_BRACKET); - - int i; - for(i = 0; i < 10; i++) { - if (is_new[i]) - status_bar_new(i); - else if (is_active[i]) - status_bar_active(i); - } - - dirty = TRUE; -} - -static void -_status_bar_update_time(void) -{ - gchar *date_fmt = g_date_time_format(last_time, "%H:%M"); - - wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwaddch(status_bar, 0, 1, '['); - wattroff(status_bar, COLOUR_STATUS_BRACKET); - mvwprintw(status_bar, 0, 2, date_fmt); - wattron(status_bar, COLOUR_STATUS_BRACKET); - mvwaddch(status_bar, 0, 7, ']'); - wattroff(status_bar, COLOUR_STATUS_BRACKET); - - free(date_fmt); - - dirty = TRUE; -} diff --git a/src/title_bar.c b/src/title_bar.c deleted file mode 100644 index 29f02c55..00000000 --- a/src/title_bar.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * title_bar.c - * - * Copyright (C) 2012, 2013 James Booth - * - * This file is part of Profanity. - * - * Profanity 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 3 of the License, or - * (at your option) any later version. - * - * Profanity 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 Profanity. If not, see . - * - */ - -#include -#include - -#include "common.h" -#include "theme.h" -#include "ui.h" - -static WINDOW *title_bar; -static char *current_title = NULL; -static char *recipient = NULL; -static GTimer *typing_elapsed; -static int dirty; -static jabber_presence_t current_status; - -static void _title_bar_draw_title(void); -static void _title_bar_draw_status(void); - -void -create_title_bar(void) -{ - int cols = getmaxx(stdscr); - - title_bar = newwin(1, cols, 0, 0); - wbkgd(title_bar, COLOUR_TITLE_TEXT); - title_bar_title(); - title_bar_set_status(PRESENCE_OFFLINE); - dirty = TRUE; -} - -void -title_bar_title(void) -{ - wclear(title_bar); - recipient = NULL; - typing_elapsed = NULL; - title_bar_show("Profanity. Type /help for help information."); - _title_bar_draw_status(); - dirty = TRUE; -} - -void -title_bar_resize(void) -{ - int cols = getmaxx(stdscr); - - wresize(title_bar, 1, cols); - wbkgd(title_bar, COLOUR_TITLE_TEXT); - wclear(title_bar); - _title_bar_draw_title(); - _title_bar_draw_status(); - dirty = TRUE; -} - -void -title_bar_refresh(void) -{ - if (recipient != NULL) { - - if (typing_elapsed != NULL) { - gdouble seconds = g_timer_elapsed(typing_elapsed, NULL); - - if (seconds >= 10) { - - if (current_title != NULL) { - free(current_title); - } - - current_title = (char *) malloc((strlen(recipient) + 1) * sizeof(char)); - strcpy(current_title, recipient); - - title_bar_draw(); - - g_timer_destroy(typing_elapsed); - typing_elapsed = NULL; - - dirty = TRUE; - } - } - } - - if (dirty) { - wrefresh(title_bar); - inp_put_back(); - dirty = FALSE; - } -} - -void -title_bar_show(const char * const title) -{ - if (current_title != NULL) - free(current_title); - - current_title = (char *) malloc((strlen(title) + 1) * sizeof(char)); - strcpy(current_title, title); - _title_bar_draw_title(); -} - -void -title_bar_set_status(jabber_presence_t status) -{ - current_status = status; - _title_bar_draw_status(); -} - -void -title_bar_set_recipient(char *from) -{ - if (typing_elapsed != NULL) { - g_timer_destroy(typing_elapsed); - typing_elapsed = NULL; - } - recipient = from; - - if (current_title != NULL) { - free(current_title); - } - - current_title = (char *) malloc((strlen(from) + 1) * sizeof(char)); - strcpy(current_title, from); - - dirty = TRUE; -} - -void -title_bar_set_typing(gboolean is_typing) -{ - if (is_typing) { - if (typing_elapsed != NULL) { - g_timer_start(typing_elapsed); - } else { - typing_elapsed = g_timer_new(); - } - } - - if (current_title != NULL) { - free(current_title); - } - - if (is_typing) { - current_title = (char *) malloc((strlen(recipient) + 13) * sizeof(char)); - sprintf(current_title, "%s (typing...)", recipient); - } else { - current_title = (char *) malloc((strlen(recipient) + 1) * sizeof(char)); - strcpy(current_title, recipient); - } - - dirty = TRUE; -} - -void -title_bar_draw(void) -{ - wclear(title_bar); - _title_bar_draw_status(); - _title_bar_draw_title(); -} - -static void -_title_bar_draw_status(void) -{ - int cols = getmaxx(stdscr); - - wattron(title_bar, COLOUR_TITLE_BRACKET); - mvwaddch(title_bar, 0, cols - 14, '['); - wattroff(title_bar, COLOUR_TITLE_BRACKET); - - if (current_status == PRESENCE_ONLINE) { - mvwprintw(title_bar, 0, cols - 13, " ...online "); - } else if (current_status == PRESENCE_AWAY) { - mvwprintw(title_bar, 0, cols - 13, " .....away "); - } else if (current_status == PRESENCE_DND) { - mvwprintw(title_bar, 0, cols - 13, " ......dnd "); - } else if (current_status == PRESENCE_CHAT) { - mvwprintw(title_bar, 0, cols - 13, " .....chat "); - } else if (current_status == PRESENCE_XA) { - mvwprintw(title_bar, 0, cols - 13, " .......xa "); - } else { - mvwprintw(title_bar, 0, cols - 13, " ..offline "); - } - - wattron(title_bar, COLOUR_TITLE_BRACKET); - mvwaddch(title_bar, 0, cols - 2, ']'); - wattroff(title_bar, COLOUR_TITLE_BRACKET); - - dirty = TRUE; -} - -static void -_title_bar_draw_title(void) -{ - wmove(title_bar, 0, 0); - int i; - for (i = 0; i < 45; i++) - waddch(title_bar, ' '); - mvwprintw(title_bar, 0, 0, " %s", current_title); - - dirty = TRUE; -} diff --git a/src/ui_inputwin.c b/src/ui_inputwin.c new file mode 100644 index 00000000..f4e70d95 --- /dev/null +++ b/src/ui_inputwin.c @@ -0,0 +1,569 @@ +/* + * ui_inputwin.c + * + * Copyright (C) 2012, 2013 James Booth + * + * This file is part of Profanity. + * + * Profanity 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 3 of the License, or + * (at your option) any later version. + * + * Profanity 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 Profanity. If not, see . + * + */ + +#define _XOPEN_SOURCE_EXTENDED +#include "config.h" + +#include +#include +#include + +#ifdef HAVE_NCURSESW_NCURSES_H +#include +#elif HAVE_NCURSES_H +#include +#endif + +#include "common.h" +#include "command.h" +#include "contact_list.h" +#include "history.h" +#include "log.h" +#include "preferences.h" +#include "profanity.h" +#include "theme.h" +#include "ui.h" + +#define _inp_win_refresh() prefresh(inp_win, 0, pad_start, rows-1, 0, rows-1, cols-1) + +static WINDOW *inp_win; +static int pad_start = 0; +static int rows, cols; + +static int _handle_edit(int result, const wint_t ch, char *input, int *size); +static int _printable(const wint_t ch); +static void _clear_input(void); +static void _go_to_end(int display_size); + +void +create_input_window(void) +{ +#ifdef NCURSES_REENTRANT + set_escdelay(25); +#else + ESCDELAY = 25; +#endif + getmaxyx(stdscr, rows, cols); + inp_win = newpad(1, INP_WIN_MAX); + wbkgd(inp_win, COLOUR_INPUT_TEXT); + keypad(inp_win, TRUE); + wmove(inp_win, 0, 0); + _inp_win_refresh(); +} + +void +inp_win_resize(const char * const input, const int size) +{ + int inp_x; + getmaxyx(stdscr, rows, cols); + inp_x = getcurx(inp_win); + + // if lost cursor off screen, move contents to show it + if (inp_x >= pad_start + cols) { + pad_start = inp_x - (cols / 2); + if (pad_start < 0) { + pad_start = 0; + } + } + + _inp_win_refresh(); +} + +void +inp_non_block(void) +{ + wtimeout(inp_win, 20); +} + +void +inp_block(void) +{ + wtimeout(inp_win, -1); +} + +wint_t +inp_get_char(char *input, int *size) +{ + int inp_x = 0; + int i; + wint_t ch; + int display_size = 0; + + if (*size != 0) { + display_size = g_utf8_strlen(input, *size); + } + + // echo off, and get some more input + noecho(); + int result = wget_wch(inp_win, &ch); + + gboolean in_command = FALSE; + if ((display_size > 0 && input[0] == '/') || + (display_size == 0 && ch == '/')) { + in_command = TRUE; + } + + if (prefs_get_states()) { + if (result == ERR) { + prof_handle_idle(); + } + if (prefs_get_outtype() && (result != ERR) && !in_command + && _printable(ch)) { + prof_handle_activity(); + } + } + + // if it wasn't an arrow key etc + if (!_handle_edit(result, ch, input, size)) { + if (_printable(ch) && result != KEY_CODE_YES) { + inp_x = getcurx(inp_win); + + // handle insert if not at end of input + if (inp_x < display_size) { + char bytes[MB_CUR_MAX]; + size_t utf_len = wcrtomb(bytes, ch, NULL); + + char *next_ch = g_utf8_offset_to_pointer(input, inp_x); + char *offset; + for (offset = &input[*size - 1]; offset >= next_ch; offset--) { + *(offset + utf_len) = *offset; + } + for (i = 0; i < utf_len; i++) { + *(next_ch + i) = bytes[i]; + } + + *size += utf_len; + input[*size] = '\0'; + wprintw(inp_win, next_ch); + wmove(inp_win, 0, inp_x + 1); + + if (inp_x - pad_start > cols-3) { + pad_start++; + _inp_win_refresh(); + } + + // otherwise just append + } else { + char bytes[MB_CUR_MAX+1]; + size_t utf_len = wcrtomb(bytes, ch, NULL); + + // wcrtomb can return (size_t) -1 + if (utf_len < MB_CUR_MAX) { + for (i = 0 ; i < utf_len; i++) { + input[(*size)++] = bytes[i]; + } + input[*size] = '\0'; + + bytes[utf_len] = '\0'; + wprintw(inp_win, bytes); + display_size++; + + // if gone over screen size follow input + int rows, cols; + getmaxyx(stdscr, rows, cols); + if (display_size - pad_start > cols-2) { + pad_start++; + _inp_win_refresh(); + } + } + } + + cmd_reset_autocomplete(); + } + } + + echo(); + + return ch; +} + +void +inp_get_password(char *passwd) +{ + _clear_input(); + _inp_win_refresh(); + noecho(); + mvwgetnstr(inp_win, 0, 1, passwd, 20); + wmove(inp_win, 0, 0); + echo(); + status_bar_clear(); +} + +void +inp_put_back(void) +{ + _inp_win_refresh(); +} + +void +inp_replace_input(char *input, const char * const new_input, int *size) +{ + int display_size; + strcpy(input, new_input); + *size = strlen(input); + display_size = g_utf8_strlen(input, *size); + inp_win_reset(); + input[*size] = '\0'; + wprintw(inp_win, input); + _go_to_end(display_size); +} + +void +inp_win_reset(void) +{ + _clear_input(); + pad_start = 0; + _inp_win_refresh(); +} + +static void +_clear_input(void) +{ + wclear(inp_win); + wmove(inp_win, 0, 0); +} + +/* + * Deal with command editing, return 1 if ch was an edit + * key press: up, down, left, right or backspace + * return 0 if it wasnt + */ +static int +_handle_edit(int result, const wint_t ch, char *input, int *size) +{ + char *prev = NULL; + char *next = NULL; + int inp_x = 0; + int next_ch; + int display_size = 0; + + if (*size != 0) { + display_size = g_utf8_strlen(input, *size); + } + + inp_x = getcurx(inp_win); + + // CTRL-LEFT + if ((result == KEY_CODE_YES) && (ch == 545 || ch == 540 || ch == 539) && (inp_x > 0)) { + input[*size] = '\0'; + gchar *curr_ch = g_utf8_offset_to_pointer(input, inp_x); + curr_ch = g_utf8_find_prev_char(input, curr_ch); + gchar *prev_ch; + gunichar curr_uni; + gunichar prev_uni; + + while (curr_ch != NULL) { + curr_uni = g_utf8_get_char(curr_ch); + + if (g_unichar_isspace(curr_uni)) { + curr_ch = g_utf8_find_prev_char(input, curr_ch); + } else { + prev_ch = g_utf8_find_prev_char(input, curr_ch); + if (prev_ch == NULL) { + curr_ch = NULL; + break; + } else { + prev_uni = g_utf8_get_char(prev_ch); + if (g_unichar_isspace(prev_uni)) { + break; + } else { + curr_ch = prev_ch; + } + } + } + } + + if (curr_ch == NULL) { + inp_x = 0; + wmove(inp_win, 0, inp_x); + } else { + glong offset = g_utf8_pointer_to_offset(input, curr_ch); + inp_x = offset; + wmove(inp_win, 0, inp_x); + } + + // if gone off screen to left, jump left (half a screen worth) + if (inp_x <= pad_start) { + pad_start = pad_start - (cols / 2); + if (pad_start < 0) { + pad_start = 0; + } + + _inp_win_refresh(); + } + return 1; + + // CTRL-RIGHT + } else if ((result == KEY_CODE_YES) && (ch == 560 || ch == 555 || ch == 554) && (inp_x < display_size)) { + input[*size] = '\0'; + gchar *curr_ch = g_utf8_offset_to_pointer(input, inp_x); + gchar *next_ch = g_utf8_find_next_char(curr_ch, NULL); + gunichar curr_uni; + gunichar next_uni; + gboolean moved = FALSE; + + while (g_utf8_pointer_to_offset(input, next_ch) < display_size) { + curr_uni = g_utf8_get_char(curr_ch); + next_uni = g_utf8_get_char(next_ch); + curr_ch = next_ch; + next_ch = g_utf8_find_next_char(next_ch, NULL); + + if (!g_unichar_isspace(curr_uni) && g_unichar_isspace(next_uni) && moved) { + break; + } else { + moved = TRUE; + } + } + + if (next_ch == NULL) { + inp_x = display_size; + wmove(inp_win, 0, inp_x); + } else { + glong offset = g_utf8_pointer_to_offset(input, curr_ch); + if (offset == display_size - 1) { + inp_x = offset + 1; + } else { + inp_x = offset; + } + wmove(inp_win, 0, inp_x); + } + + // if gone off screen to right, jump right (half a screen worth) + if (inp_x > pad_start + cols) { + pad_start = pad_start + (cols / 2); + _inp_win_refresh(); + } + + return 1; + + // other editing keys + } else { + switch(ch) { + + case 27: // ESC + // check for ALT-num + next_ch = wgetch(inp_win); + if (next_ch != ERR) { + switch (next_ch) + { + case '1': + ui_switch_win(0); + break; + case '2': + ui_switch_win(1); + break; + case '3': + ui_switch_win(2); + break; + case '4': + ui_switch_win(3); + break; + case '5': + ui_switch_win(4); + break; + case '6': + ui_switch_win(5); + break; + case '7': + ui_switch_win(6); + break; + case '8': + ui_switch_win(7); + break; + case '9': + ui_switch_win(8); + break; + case '0': + ui_switch_win(9); + break; + default: + break; + } + return 1; + } else { + *size = 0; + inp_win_reset(); + return 1; + } + + case 127: + case KEY_BACKSPACE: + contact_list_reset_search_attempts(); + if (display_size > 0) { + + // if at end, delete last char + if (inp_x >= display_size) { + gchar *start = g_utf8_substring(input, 0, inp_x-1); + for (*size = 0; *size < strlen(start); (*size)++) { + input[*size] = start[*size]; + } + input[*size] = '\0'; + + g_free(start); + + _clear_input(); + wprintw(inp_win, input); + wmove(inp_win, 0, inp_x -1); + + // if in middle, delete and shift chars left + } else if (inp_x > 0 && inp_x < display_size) { + gchar *start = g_utf8_substring(input, 0, inp_x - 1); + gchar *end = g_utf8_substring(input, inp_x, *size); + GString *new = g_string_new(start); + g_string_append(new, end); + + for (*size = 0; *size < strlen(new->str); (*size)++) { + input[*size] = new->str[*size]; + } + input[*size] = '\0'; + + g_free(start); + g_free(end); + g_string_free(new, FALSE); + + _clear_input(); + wprintw(inp_win, input); + wmove(inp_win, 0, inp_x -1); + } + + // if gone off screen to left, jump left (half a screen worth) + if (inp_x <= pad_start) { + pad_start = pad_start - (cols / 2); + if (pad_start < 0) { + pad_start = 0; + } + + _inp_win_refresh(); + } + } + return 1; + + case KEY_DC: // DEL + if (inp_x == display_size-1) { + gchar *start = g_utf8_substring(input, 0, inp_x); + for (*size = 0; *size < strlen(start); (*size)++) { + input[*size] = start[*size]; + } + input[*size] = '\0'; + + g_free(start); + + _clear_input(); + wprintw(inp_win, input); + } else if (inp_x < display_size-1) { + gchar *start = g_utf8_substring(input, 0, inp_x); + gchar *end = g_utf8_substring(input, inp_x+1, *size); + GString *new = g_string_new(start); + g_string_append(new, end); + + for (*size = 0; *size < strlen(new->str); (*size)++) { + input[*size] = new->str[*size]; + } + input[*size] = '\0'; + + g_free(start); + g_free(end); + g_string_free(new, FALSE); + + _clear_input(); + wprintw(inp_win, input); + wmove(inp_win, 0, inp_x); + } + return 1; + + case KEY_LEFT: + if (inp_x > 0) { + wmove(inp_win, 0, inp_x-1); + + // current position off screen to left + if (inp_x - 1 < pad_start) { + pad_start--; + _inp_win_refresh(); + } + } + return 1; + + case KEY_RIGHT: + if (inp_x < display_size) { + wmove(inp_win, 0, inp_x+1); + + // current position off screen to right + if ((inp_x + 1 - pad_start) >= cols) { + pad_start++; + _inp_win_refresh(); + } + } + return 1; + + case KEY_UP: + prev = history_previous(input, size); + if (prev) { + inp_replace_input(input, prev, size); + } + return 1; + + case KEY_DOWN: + next = history_next(input, size); + if (next) { + inp_replace_input(input, next, size); + } + return 1; + + case KEY_HOME: + wmove(inp_win, 0, 0); + pad_start = 0; + _inp_win_refresh(); + return 1; + + case KEY_END: + _go_to_end(display_size); + return 1; + + case 9: // tab + cmd_autocomplete(input, size); + return 1; + + default: + return 0; + } + } +} + +static void +_go_to_end(int display_size) +{ + wmove(inp_win, 0, display_size); + if (display_size > cols-2) { + pad_start = display_size - cols + 1; + _inp_win_refresh(); + } +} + +static int +_printable(const wint_t ch) +{ + char bytes[MB_CUR_MAX+1]; + size_t utf_len = wcrtomb(bytes, ch, NULL); + bytes[utf_len] = '\0'; + gunichar unichar = g_utf8_get_char(bytes); + return g_unichar_isprint(unichar) && (ch != KEY_MOUSE); +} diff --git a/src/ui_statusbar.c b/src/ui_statusbar.c new file mode 100644 index 00000000..9cc85108 --- /dev/null +++ b/src/ui_statusbar.c @@ -0,0 +1,285 @@ +/* + * ui_statusbar.c + * + * Copyright (C) 2012, 2013 James Booth + * + * This file is part of Profanity. + * + * Profanity 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 3 of the License, or + * (at your option) any later version. + * + * Profanity 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 Profanity. If not, see . + * + */ + +#include "config.h" + +#include +#include + +#ifdef HAVE_NCURSESW_NCURSES_H +#include +#elif HAVE_NCURSES_H +#include +#endif + +#include "theme.h" +#include "ui.h" + +static WINDOW *status_bar; +static char *message = NULL; +static char _active[31] = "[ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]"; +static int is_active[10]; +static int is_new[10]; +static int dirty; +static GDateTime *last_time; + +static void _status_bar_update_time(void); + +void +create_status_bar(void) +{ + int rows, cols, i; + getmaxyx(stdscr, rows, cols); + + is_active[0] = TRUE; + is_new[0] = FALSE; + for (i = 1; i < 10; i++) { + is_active[i] = FALSE; + is_new[i] = FALSE; + } + + status_bar = newwin(1, cols, rows-2, 0); + wbkgd(status_bar, COLOUR_STATUS_TEXT); + wattron(status_bar, COLOUR_STATUS_BRACKET); + mvwprintw(status_bar, 0, cols - 31, _active); + wattroff(status_bar, COLOUR_STATUS_BRACKET); + + last_time = g_date_time_new_now_local(); + + dirty = TRUE; +} + +void +status_bar_refresh(void) +{ + GDateTime *now_time = g_date_time_new_now_local(); + GTimeSpan elapsed = g_date_time_difference(now_time, last_time); + + if (elapsed >= 60000000) { + dirty = TRUE; + last_time = g_date_time_new_now_local(); + } + + if (dirty) { + _status_bar_update_time(); + wrefresh(status_bar); + inp_put_back(); + dirty = FALSE; + } + + g_date_time_unref(now_time); +} + +void +status_bar_resize(void) +{ + int rows, cols, i; + getmaxyx(stdscr, rows, cols); + + mvwin(status_bar, rows-2, 0); + wresize(status_bar, 1, cols); + wbkgd(status_bar, COLOUR_STATUS_TEXT); + wclear(status_bar); + wattron(status_bar, COLOUR_STATUS_BRACKET); + mvwprintw(status_bar, 0, cols - 31, _active); + wattroff(status_bar, COLOUR_STATUS_BRACKET); + + for(i = 0; i < 10; i++) { + if (is_new[i]) + status_bar_new(i); + else if (is_active[i]) + status_bar_active(i); + } + + if (message != NULL) + mvwprintw(status_bar, 0, 10, message); + + last_time = g_date_time_new_now_local(); + dirty = TRUE; +} + +void +status_bar_inactive(const int win) +{ + is_active[win] = FALSE; + is_new[win] = FALSE; + + int active_pos = 1 + (win * 3); + + int cols = getmaxx(stdscr); + + mvwaddch(status_bar, 0, cols - 31 + active_pos, ' '); + + dirty = TRUE; +} + +void +status_bar_active(const int win) +{ + is_active[win] = TRUE; + is_new[win] = FALSE; + + int active_pos = 1 + (win * 3); + + int cols = getmaxx(stdscr); + + wattron(status_bar, COLOUR_STATUS_ACTIVE); + if (win+1 < 10) + mvwprintw(status_bar, 0, cols - 31 + active_pos, "%d", win+1); + else + mvwprintw(status_bar, 0, cols - 31 + active_pos, "0"); + wattroff(status_bar, COLOUR_STATUS_ACTIVE); + + dirty = TRUE; +} + +void +status_bar_new(const int win) +{ + is_active[win] = TRUE; + is_new[win] = TRUE; + + int active_pos = 1 + (win * 3); + + int cols = getmaxx(stdscr); + + wattron(status_bar, COLOUR_STATUS_NEW); + wattron(status_bar, A_BLINK); + if (win+1 < 10) + mvwprintw(status_bar, 0, cols - 31 + active_pos, "%d", win+1); + else + mvwprintw(status_bar, 0, cols - 31 + active_pos, "0"); + wattroff(status_bar, COLOUR_STATUS_NEW); + wattroff(status_bar, A_BLINK); + + dirty = TRUE; +} + +void +status_bar_get_password(void) +{ + status_bar_print_message("Enter password:"); + dirty = TRUE; +} + +void +status_bar_print_message(const char * const msg) +{ + if (message != NULL) { + free(message); + message = NULL; + } + + wclear(status_bar); + + message = (char *) malloc((strlen(msg) + 1) * sizeof(char)); + strcpy(message, msg); + mvwprintw(status_bar, 0, 10, message); + + int cols = getmaxx(stdscr); + + wattron(status_bar, COLOUR_STATUS_BRACKET); + mvwprintw(status_bar, 0, cols - 31, _active); + wattroff(status_bar, COLOUR_STATUS_BRACKET); + + int i; + for(i = 0; i < 10; i++) { + if (is_new[i]) + status_bar_new(i); + else if (is_active[i]) + status_bar_active(i); + } + + dirty = TRUE; +} + +void +status_bar_clear(void) +{ + if (message != NULL) { + free(message); + message = NULL; + } + + int i; + is_active[0] = TRUE; + is_new[0] = FALSE; + for (i = 1; i < 10; i++) { + is_active[i] = FALSE; + is_new[i] = FALSE; + } + + wclear(status_bar); + + int cols = getmaxx(stdscr); + + wattron(status_bar, COLOUR_STATUS_BRACKET); + mvwprintw(status_bar, 0, cols - 31, _active); + wattroff(status_bar, COLOUR_STATUS_BRACKET); + + dirty = TRUE; +} + +void +status_bar_clear_message(void) +{ + if (message != NULL) { + free(message); + message = NULL; + } + + wclear(status_bar); + + int cols = getmaxx(stdscr); + + wattron(status_bar, COLOUR_STATUS_BRACKET); + mvwprintw(status_bar, 0, cols - 31, _active); + wattroff(status_bar, COLOUR_STATUS_BRACKET); + + int i; + for(i = 0; i < 10; i++) { + if (is_new[i]) + status_bar_new(i); + else if (is_active[i]) + status_bar_active(i); + } + + dirty = TRUE; +} + +static void +_status_bar_update_time(void) +{ + gchar *date_fmt = g_date_time_format(last_time, "%H:%M"); + + wattron(status_bar, COLOUR_STATUS_BRACKET); + mvwaddch(status_bar, 0, 1, '['); + wattroff(status_bar, COLOUR_STATUS_BRACKET); + mvwprintw(status_bar, 0, 2, date_fmt); + wattron(status_bar, COLOUR_STATUS_BRACKET); + mvwaddch(status_bar, 0, 7, ']'); + wattroff(status_bar, COLOUR_STATUS_BRACKET); + + free(date_fmt); + + dirty = TRUE; +} diff --git a/src/ui_titlebar.c b/src/ui_titlebar.c new file mode 100644 index 00000000..17886a24 --- /dev/null +++ b/src/ui_titlebar.c @@ -0,0 +1,221 @@ +/* + * ui_titlebar.c + * + * Copyright (C) 2012, 2013 James Booth + * + * This file is part of Profanity. + * + * Profanity 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 3 of the License, or + * (at your option) any later version. + * + * Profanity 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 Profanity. If not, see . + * + */ + +#include +#include + +#include "common.h" +#include "theme.h" +#include "ui.h" + +static WINDOW *title_bar; +static char *current_title = NULL; +static char *recipient = NULL; +static GTimer *typing_elapsed; +static int dirty; +static jabber_presence_t current_status; + +static void _title_bar_draw_title(void); +static void _title_bar_draw_status(void); + +void +create_title_bar(void) +{ + int cols = getmaxx(stdscr); + + title_bar = newwin(1, cols, 0, 0); + wbkgd(title_bar, COLOUR_TITLE_TEXT); + title_bar_title(); + title_bar_set_status(PRESENCE_OFFLINE); + dirty = TRUE; +} + +void +title_bar_title(void) +{ + wclear(title_bar); + recipient = NULL; + typing_elapsed = NULL; + title_bar_show("Profanity. Type /help for help information."); + _title_bar_draw_status(); + dirty = TRUE; +} + +void +title_bar_resize(void) +{ + int cols = getmaxx(stdscr); + + wresize(title_bar, 1, cols); + wbkgd(title_bar, COLOUR_TITLE_TEXT); + wclear(title_bar); + _title_bar_draw_title(); + _title_bar_draw_status(); + dirty = TRUE; +} + +void +title_bar_refresh(void) +{ + if (recipient != NULL) { + + if (typing_elapsed != NULL) { + gdouble seconds = g_timer_elapsed(typing_elapsed, NULL); + + if (seconds >= 10) { + + if (current_title != NULL) { + free(current_title); + } + + current_title = (char *) malloc((strlen(recipient) + 1) * sizeof(char)); + strcpy(current_title, recipient); + + title_bar_draw(); + + g_timer_destroy(typing_elapsed); + typing_elapsed = NULL; + + dirty = TRUE; + } + } + } + + if (dirty) { + wrefresh(title_bar); + inp_put_back(); + dirty = FALSE; + } +} + +void +title_bar_show(const char * const title) +{ + if (current_title != NULL) + free(current_title); + + current_title = (char *) malloc((strlen(title) + 1) * sizeof(char)); + strcpy(current_title, title); + _title_bar_draw_title(); +} + +void +title_bar_set_status(jabber_presence_t status) +{ + current_status = status; + _title_bar_draw_status(); +} + +void +title_bar_set_recipient(char *from) +{ + if (typing_elapsed != NULL) { + g_timer_destroy(typing_elapsed); + typing_elapsed = NULL; + } + recipient = from; + + if (current_title != NULL) { + free(current_title); + } + + current_title = (char *) malloc((strlen(from) + 1) * sizeof(char)); + strcpy(current_title, from); + + dirty = TRUE; +} + +void +title_bar_set_typing(gboolean is_typing) +{ + if (is_typing) { + if (typing_elapsed != NULL) { + g_timer_start(typing_elapsed); + } else { + typing_elapsed = g_timer_new(); + } + } + + if (current_title != NULL) { + free(current_title); + } + + if (is_typing) { + current_title = (char *) malloc((strlen(recipient) + 13) * sizeof(char)); + sprintf(current_title, "%s (typing...)", recipient); + } else { + current_title = (char *) malloc((strlen(recipient) + 1) * sizeof(char)); + strcpy(current_title, recipient); + } + + dirty = TRUE; +} + +void +title_bar_draw(void) +{ + wclear(title_bar); + _title_bar_draw_status(); + _title_bar_draw_title(); +} + +static void +_title_bar_draw_status(void) +{ + int cols = getmaxx(stdscr); + + wattron(title_bar, COLOUR_TITLE_BRACKET); + mvwaddch(title_bar, 0, cols - 14, '['); + wattroff(title_bar, COLOUR_TITLE_BRACKET); + + if (current_status == PRESENCE_ONLINE) { + mvwprintw(title_bar, 0, cols - 13, " ...online "); + } else if (current_status == PRESENCE_AWAY) { + mvwprintw(title_bar, 0, cols - 13, " .....away "); + } else if (current_status == PRESENCE_DND) { + mvwprintw(title_bar, 0, cols - 13, " ......dnd "); + } else if (current_status == PRESENCE_CHAT) { + mvwprintw(title_bar, 0, cols - 13, " .....chat "); + } else if (current_status == PRESENCE_XA) { + mvwprintw(title_bar, 0, cols - 13, " .......xa "); + } else { + mvwprintw(title_bar, 0, cols - 13, " ..offline "); + } + + wattron(title_bar, COLOUR_TITLE_BRACKET); + mvwaddch(title_bar, 0, cols - 2, ']'); + wattroff(title_bar, COLOUR_TITLE_BRACKET); + + dirty = TRUE; +} + +static void +_title_bar_draw_title(void) +{ + wmove(title_bar, 0, 0); + int i; + for (i = 0; i < 45; i++) + waddch(title_bar, ' '); + mvwprintw(title_bar, 0, 0, " %s", current_title); + + dirty = TRUE; +} diff --git a/src/ui_windows.c b/src/ui_windows.c new file mode 100644 index 00000000..ae47c85b --- /dev/null +++ b/src/ui_windows.c @@ -0,0 +1,2423 @@ +/* + * ui_windows.c + * + * Copyright (C) 2012, 2013 James Booth + * + * This file is part of Profanity. + * + * Profanity 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 3 of the License, or + * (at your option) any later version. + * + * Profanity 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 Profanity. If not, see . + * + */ + +#include "config.h" + +#include +#include + +#ifdef HAVE_LIBXSS +#include +#endif + +#include + +#ifdef HAVE_LIBNOTIFY +#include +#endif +#ifdef PLATFORM_CYGWIN +#include +#endif + +#ifdef HAVE_NCURSESW_NCURSES_H +#include +#elif HAVE_NCURSES_H +#include +#endif + +#include "chat_log.h" +#include "chat_session.h" +#include "command.h" +#include "common.h" +#include "contact.h" +#include "contact_list.h" +#include "jid.h" +#include "log.h" +#include "preferences.h" +#include "release.h" +#include "muc.h" +#include "theme.h" +#include "ui.h" +#include "window.h" + +#define CONS_WIN_TITLE "_cons" +#define NUM_WINS 10 + +// holds console at index 0 and chat wins 1 through to 9 +static ProfWin* windows[NUM_WINS]; + +// the window currently being displayed +static int current_index = 0; +static ProfWin *current; +static ProfWin *console; + +// current window state +static int dirty; + +// max columns for main windows, never resize below +static int max_cols = 0; + +static char *win_title; + +#ifdef HAVE_LIBXSS +static Display *display; +#endif + +static GTimer *ui_idle_time; + +static void _set_current(int index); +static void _create_windows(void); +static void _cons_splash_logo(void); +static void _cons_show_basic_help(void); +static void _win_show_contact(ProfWin *window, PContact contact); +static int _find_prof_win_index(const char * const contact); +static int _new_prof_win(const char * const contact, win_type_t type); +static void _current_window_refresh(void); +static void _win_show_time(WINDOW *win, char showchar); +static void _win_show_user(WINDOW *win, const char * const user, const int colour); +static void _win_show_message(WINDOW *win, const char * const message); +static void _win_show_error_msg(WINDOW *win, const char * const message); +static void _show_status_string(WINDOW *win, const char * const from, + const char * const show, const char * const status, + GDateTime *last_activity, const char * const pre, + const char * const default_show); +static void _cons_show_typing(const char * const short_from); +static void _cons_show_incoming_message(const char * const short_from, + const int win_index); +static void _win_handle_switch(const wint_t * const ch); +static void _win_handle_page(const wint_t * const ch); +static void _win_resize_all(void); +static gint _win_get_unread(void); +static void _win_show_history(WINDOW *win, int win_index, + const char * const contact); +static void _win_show_info(WINDOW *win, PContact pcontact); +static gboolean _new_release(char *found_version); +static void _ui_draw_win_title(void); +static void _presence_colour_on(WINDOW *win, const char * const presence); +static void _presence_colour_off(WINDOW *win, const char * const presence); + +static void _notify(const char * const message, int timeout, + const char * const category); +static void _notify_remind(gint unread); +static void _notify_message(const char * const short_from); +static void _notify_typing(const char * const from); + +void +ui_init(void) +{ + log_info("Initialising UI"); + initscr(); + raw(); + keypad(stdscr, TRUE); + if (prefs_get_mouse()) { + mousemask(ALL_MOUSE_EVENTS, NULL); + mouseinterval(5); + } + ui_load_colours(); + refresh(); + create_title_bar(); + create_status_bar(); + status_bar_active(0); + create_input_window(); + _create_windows(); +#ifdef HAVE_LIBXSS + display = XOpenDisplay(0); +#endif + ui_idle_time = g_timer_new(); + dirty = TRUE; +} + +void +ui_refresh(void) +{ + _ui_draw_win_title(); + + title_bar_refresh(); + status_bar_refresh(); + + if (dirty) { + _current_window_refresh(); + dirty = FALSE; + } + + inp_put_back(); +} + +static void +_ui_draw_win_title(void) +{ + char new_win_title[100]; + + GString *version_str = g_string_new(""); + + if (prefs_get_titlebarversion()) { + g_string_append(version_str, " "); + g_string_append(version_str, PACKAGE_VERSION); + if (strcmp(PACKAGE_STATUS, "development") == 0) { + g_string_append(version_str, "dev"); + } + } + + jabber_conn_status_t status = jabber_get_connection_status(); + + if (status == JABBER_CONNECTED) { + const char * const jid = jabber_get_jid(); + gint unread = _win_get_unread(); + + if (unread != 0) { + snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s (%d) - %s%c", '\033', "Profanity", version_str->str, unread, jid, '\007'); + } else { + snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s - %s%c", '\033', "Profanity", version_str->str, jid, '\007'); + } + } else { + snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s%c", '\033', "Profanity", version_str->str, '\007'); + } + + g_string_free(version_str, TRUE); + + if (g_strcmp0(win_title, new_win_title) != 0) { + // print to x-window title bar + printf("%s", new_win_title); + if (win_title != NULL) { + free(win_title); + } + win_title = strdup(new_win_title); + } +} + +unsigned long +ui_get_idle_time(void) +{ +// if compiled with libxss, get the x sessions idle time +#ifdef HAVE_LIBXSS + XScreenSaverInfo *info = XScreenSaverAllocInfo(); + if (info != NULL && display != NULL) { + XScreenSaverQueryInfo(display, DefaultRootWindow(display), info); + unsigned long result = info->idle; + XFree(info); + return result; + } +// if no libxss or xss idle time failed, use profanity idle time +#endif + gdouble seconds_elapsed = g_timer_elapsed(ui_idle_time, NULL); + unsigned long ms_elapsed = seconds_elapsed * 1000.0; + return ms_elapsed; +} + +void +ui_reset_idle_time(void) +{ + g_timer_start(ui_idle_time); +} + +void +ui_close(void) +{ +#ifdef HAVE_LIBNOTIFY + if (notify_is_initted()) { + notify_uninit(); + } +#endif + endwin(); +} + +void +ui_resize(const int ch, const char * const input, const int size) +{ + log_info("Resizing UI"); + title_bar_resize(); + status_bar_resize(); + _win_resize_all(); + inp_win_resize(input, size); + dirty = TRUE; +} + +void +ui_load_colours(void) +{ + if (has_colors()) { + use_default_colors(); + start_color(); + theme_init_colours(); + } +} + +gboolean +ui_windows_full(void) +{ + int i; + for (i = 1; i < NUM_WINS; i++) { + if (windows[i] == NULL) { + return FALSE; + } + } + + return TRUE; +} + +void +ui_show_typing(const char * const from) +{ + int win_index = _find_prof_win_index(from); + + if (prefs_get_intype()) { + // no chat window for user + if (win_index == NUM_WINS) { + _cons_show_typing(from); + + // have chat window but not currently in it + } else if (win_index != current_index) { + _cons_show_typing(from); + dirty = TRUE; + + // in chat window with user + } else { + title_bar_set_typing(TRUE); + title_bar_draw(); + + status_bar_active(win_index); + dirty = TRUE; + } + } + + if (prefs_get_notify_typing()) + _notify_typing(from); +} + +void +ui_idle(void) +{ + int i; + + // loop through regular chat windows and update states + for (i = 1; i < NUM_WINS; i++) { + if ((windows[i] != NULL) && (windows[i]->type == WIN_CHAT)) { + char *recipient = windows[i]->from; + chat_session_no_activity(recipient); + + if (chat_session_is_gone(recipient) && + !chat_session_get_sent(recipient)) { + jabber_send_gone(recipient); + } else if (chat_session_is_inactive(recipient) && + !chat_session_get_sent(recipient)) { + jabber_send_inactive(recipient); + } else if (prefs_get_outtype() && + chat_session_is_paused(recipient) && + !chat_session_get_sent(recipient)) { + jabber_send_paused(recipient); + } + } + } +} + +void +ui_show_incoming_msg(const char * const from, const char * const message, + GTimeVal *tv_stamp, gboolean priv) +{ + char *display_from; + win_type_t win_type; + if (priv) { + win_type = WIN_PRIVATE; + display_from = get_nick_from_full_jid(from); + } else { + win_type = WIN_CHAT; + display_from = strdup(from); + } + + int win_index = _find_prof_win_index(from); + if (win_index == NUM_WINS) + win_index = _new_prof_win(from, win_type); + + // no spare windows left + if (win_index == 0) { + if (tv_stamp == NULL) { + _win_show_time(console->win, '-'); + } else { + GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); + gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); + wattron(console->win, COLOUR_TIME); + wprintw(console->win, "%s - ", date_fmt); + wattroff(console->win, COLOUR_TIME); + g_date_time_unref(time); + g_free(date_fmt); + } + + if (strncmp(message, "/me ", 4) == 0) { + wattron(console->win, COLOUR_THEM); + wprintw(console->win, "*%s ", from); + wprintw(console->win, message + 4); + wprintw(console->win, "\n"); + wattroff(console->win, COLOUR_THEM); + } else { + _win_show_user(console->win, from, 1); + _win_show_message(console->win, message); + } + + cons_bad_show("Windows all used, close a window to respond."); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } + + // window found or created + } else { + WINDOW *win = windows[win_index]->win; + + // currently viewing chat window with sender + if (win_index == current_index) { + if (tv_stamp == NULL) { + _win_show_time(win, '-'); + } else { + GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); + gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); + wattron(win, COLOUR_TIME); + wprintw(win, "%s - ", date_fmt); + wattroff(win, COLOUR_TIME); + g_date_time_unref(time); + g_free(date_fmt); + } + + if (strncmp(message, "/me ", 4) == 0) { + wattron(win, COLOUR_THEM); + wprintw(win, "*%s ", display_from); + wprintw(win, message + 4); + wprintw(win, "\n"); + wattroff(win, COLOUR_THEM); + } else { + _win_show_user(win, display_from, 1); + _win_show_message(win, message); + } + title_bar_set_typing(FALSE); + title_bar_draw(); + status_bar_active(win_index); + dirty = TRUE; + + // not currently viewing chat window with sender + } else { + status_bar_new(win_index); + _cons_show_incoming_message(from, win_index); + if (prefs_get_flash()) + flash(); + + windows[win_index]->unread++; + if (prefs_get_chlog() && prefs_get_history()) { + _win_show_history(win, win_index, from); + } + + if (tv_stamp == NULL) { + _win_show_time(win, '-'); + } else { + GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); + gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); + wattron(win, COLOUR_TIME); + wprintw(win, "%s - ", date_fmt); + wattroff(win, COLOUR_TIME); + g_date_time_unref(time); + g_free(date_fmt); + } + + if (strncmp(message, "/me ", 4) == 0) { + wattron(win, COLOUR_THEM); + wprintw(win, "*%s ", display_from); + wprintw(win, message + 4); + wprintw(win, "\n"); + wattroff(win, COLOUR_THEM); + } else { + _win_show_user(win, display_from, 1); + _win_show_message(win, message); + } + } + } + + if (prefs_get_beep()) + beep(); + if (prefs_get_notify_message()) + _notify_message(display_from); + + g_free(display_from); +} + +void +ui_contact_online(const char * const from, const char * const show, + const char * const status, GDateTime *last_activity) +{ + _show_status_string(console->win, from, show, status, last_activity, "++", + "online"); + + int win_index = _find_prof_win_index(from); + if (win_index != NUM_WINS) { + WINDOW *win = windows[win_index]->win; + _show_status_string(win, from, show, status, last_activity, "++", + "online"); + } + + if (win_index == current_index) + dirty = TRUE; +} + +void +ui_contact_offline(const char * const from, const char * const show, + const char * const status) +{ + _show_status_string(console->win, from, show, status, NULL, "--", "offline"); + + int win_index = _find_prof_win_index(from); + if (win_index != NUM_WINS) { + WINDOW *win = windows[win_index]->win; + _show_status_string(win, from, show, status, NULL, "--", "offline"); + } + + if (win_index == current_index) + dirty = TRUE; +} + +void +ui_disconnected(void) +{ + int i; + // show message in all active chats + for (i = 1; i < NUM_WINS; i++) { + if (windows[i] != NULL) { + WINDOW *win = windows[i]->win; + _win_show_time(win, '-'); + wattron(win, COLOUR_ERROR); + wprintw(win, "%s\n", "Lost connection."); + wattroff(win, COLOUR_ERROR); + + // if current win, set dirty + if (i == current_index) { + dirty = TRUE; + } + } + } +} + +void +ui_handle_special_keys(const wint_t * const ch) +{ + _win_handle_switch(ch); + _win_handle_page(ch); +} + +void +ui_switch_win(const int i) +{ + win_current_page_off(); + if (windows[i] != NULL) { + current_index = i; + current = windows[current_index]; + win_current_page_off(); + + current->unread = 0; + + if (i == 0) { + title_bar_title(); + status_bar_active(0); + } else { + title_bar_set_recipient(current->from); + title_bar_draw();; + status_bar_active(i); + } + } + + dirty = TRUE; +} + +void +win_current_close(void) +{ + window_free(current); + windows[current_index] = NULL; + + // set it as inactive in the status bar + status_bar_inactive(current_index); + + // go back to console window + _set_current(0); + status_bar_active(0); + title_bar_title(); + + dirty = TRUE; +} + +int +win_current_is_console(void) +{ + return (current->type == WIN_CONSOLE); +} + +int +win_current_is_chat(void) +{ + return (current->type == WIN_CHAT); +} + +int +win_current_is_groupchat(void) +{ + return (current->type == WIN_MUC); +} + +int +win_current_is_private(void) +{ + return (current->type == WIN_PRIVATE); +} + +char * +win_current_get_recipient(void) +{ + return strdup(current->from); +} + +void +win_current_show(const char * const msg, ...) +{ + va_list arg; + va_start(arg, msg); + GString *fmt_msg = g_string_new(NULL); + g_string_vprintf(fmt_msg, msg, arg); + _win_show_time(current->win, '-'); + wprintw(current->win, "%s\n", fmt_msg->str); + g_string_free(fmt_msg, TRUE); + va_end(arg); + + dirty = TRUE; +} + +void +win_current_bad_show(const char * const msg) +{ + WINDOW *win = current->win; + _win_show_time(win, '-'); + wattron(win, COLOUR_ERROR); + wprintw(win, "%s\n", msg); + wattroff(win, COLOUR_ERROR); + + dirty = TRUE; +} + +void +win_current_page_off(void) +{ + int rows = getmaxy(stdscr); + ProfWin *window = windows[current_index]; + + window->paged = 0; + + int y = getcury(window->win); + + int size = rows - 3; + + window->y_pos = y - (size - 1); + if (window->y_pos < 0) + window->y_pos = 0; + + dirty = TRUE; +} + +void +win_show_error_msg(const char * const from, const char *err_msg) +{ + int win_index; + WINDOW *win; + + if (from == NULL || err_msg == NULL) + return; + + win_index = _find_prof_win_index(from); + // chat window exists + if (win_index < NUM_WINS) { + win = windows[win_index]->win; + _win_show_time(win, '-'); + _win_show_error_msg(win, err_msg); + if (win_index == current_index) { + dirty = TRUE; + } + } +} + +void +win_show_system_msg(const char * const from, const char *message) +{ + int win_index; + WINDOW *win; + char from_cpy[strlen(from) + 1]; + char *bare_jid; + + if (from == NULL || message == NULL) + return; + + strcpy(from_cpy, from); + bare_jid = strtok(from_cpy, "/"); + + win_index = _find_prof_win_index(bare_jid); + if (win_index == NUM_WINS) { + win_index = _new_prof_win(bare_jid, WIN_CHAT); + status_bar_active(win_index); + dirty = TRUE; + } + win = windows[win_index]->win; + + _win_show_time(win, '-'); + wprintw(win, "*%s %s\n", bare_jid, message); + + // this is the current window + if (win_index == current_index) { + dirty = TRUE; + } +} + +void +win_show_gone(const char * const from) +{ + int win_index; + WINDOW *win; + + if (from == NULL) + return; + + win_index = _find_prof_win_index(from); + // chat window exists + if (win_index < NUM_WINS) { + win = windows[win_index]->win; + _win_show_time(win, '-'); + wattron(win, COLOUR_GONE); + wprintw(win, "*%s ", from); + wprintw(win, "has left the conversation."); + wprintw(win, "\n"); + wattroff(win, COLOUR_GONE); + if (win_index == current_index) { + dirty = TRUE; + } + } +} + +void +win_new_chat_win(const char * const to) +{ + // if the contact is offline, show a message + PContact contact = contact_list_get_contact(to); + int win_index = _find_prof_win_index(to); + WINDOW *win = NULL; + + // create new window + if (win_index == NUM_WINS) { + Jid *jid = jid_create(to); + + if (muc_room_is_active(jid)) { + win_index = _new_prof_win(to, WIN_PRIVATE); + } else { + win_index = _new_prof_win(to, WIN_CHAT); + } + + jid_destroy(jid); + + win = windows[win_index]->win; + + if (prefs_get_chlog() && prefs_get_history()) { + _win_show_history(win, win_index, to); + } + + if (contact != NULL) { + if (strcmp(p_contact_presence(contact), "offline") == 0) { + const char const *show = p_contact_presence(contact); + const char const *status = p_contact_status(contact); + _show_status_string(win, to, show, status, NULL, "--", "offline"); + } + } + + // use existing window + } else { + win = windows[win_index]->win; + } + + ui_switch_win(win_index); +} + +void +win_show_outgoing_msg(const char * const from, const char * const to, + const char * const message) +{ + // if the contact is offline, show a message + PContact contact = contact_list_get_contact(to); + int win_index = _find_prof_win_index(to); + WINDOW *win = NULL; + + // create new window + if (win_index == NUM_WINS) { + Jid *jid = jid_create(to); + + if (muc_room_is_active(jid)) { + win_index = _new_prof_win(to, WIN_PRIVATE); + } else { + win_index = _new_prof_win(to, WIN_CHAT); + } + + jid_destroy(jid); + + win = windows[win_index]->win; + + if (prefs_get_chlog() && prefs_get_history()) { + _win_show_history(win, win_index, to); + } + + if (contact != NULL) { + if (strcmp(p_contact_presence(contact), "offline") == 0) { + const char const *show = p_contact_presence(contact); + const char const *status = p_contact_status(contact); + _show_status_string(win, to, show, status, NULL, "--", "offline"); + } + } + + // use existing window + } else { + win = windows[win_index]->win; + } + + _win_show_time(win, '-'); + if (strncmp(message, "/me ", 4) == 0) { + wattron(win, COLOUR_ME); + wprintw(win, "*%s ", from); + wprintw(win, message + 4); + wprintw(win, "\n"); + wattroff(win, COLOUR_ME); + } else { + _win_show_user(win, from, 0); + _win_show_message(win, message); + } + ui_switch_win(win_index); +} + +void +win_join_chat(Jid *jid) +{ + int win_index = _find_prof_win_index(jid->barejid); + + // create new window + if (win_index == NUM_WINS) { + win_index = _new_prof_win(jid->barejid, WIN_MUC); + } + + ui_switch_win(win_index); +} + +void +win_show_room_roster(const char * const room, GList *roster, const char * const presence) +{ + int win_index = _find_prof_win_index(room); + WINDOW *win = windows[win_index]->win; + + _win_show_time(win, '!'); + if ((roster == NULL) || (g_list_length(roster) == 0)) { + wattron(win, COLOUR_ROOMINFO); + if (presence == NULL) { + wprintw(win, "Room is empty.\n"); + } else { + wprintw(win, "No participants are %s.\n", presence); + } + wattroff(win, COLOUR_ROOMINFO); + } else { + wattron(win, COLOUR_ROOMINFO); + if (presence == NULL) { + wprintw(win, "Participants: "); + } else { + wprintw(win, "Participants (%s): ", presence); + } + wattroff(win, COLOUR_ROOMINFO); + wattron(win, COLOUR_ONLINE); + + while (roster != NULL) { + PContact member = roster->data; + const char const *name = p_contact_jid(member); + const char const *show = p_contact_presence(member); + + _presence_colour_on(win, show); + wprintw(win, "%s", name); + _presence_colour_off(win, show); + + if (roster->next != NULL) { + wprintw(win, ", "); + } + + roster = g_list_next(roster); + } + + wprintw(win, "\n"); + wattroff(win, COLOUR_ONLINE); + } + + if (win_index == current_index) + dirty = TRUE; +} + +void +win_show_room_member_offline(const char * const room, const char * const nick) +{ + int win_index = _find_prof_win_index(room); + WINDOW *win = windows[win_index]->win; + + _win_show_time(win, '!'); + wattron(win, COLOUR_OFFLINE); + wprintw(win, "<- %s has left the room.\n", nick); + wattroff(win, COLOUR_OFFLINE); + + if (win_index == current_index) + dirty = TRUE; +} + +void +win_show_room_member_online(const char * const room, const char * const nick, + const char * const show, const char * const status) +{ + int win_index = _find_prof_win_index(room); + WINDOW *win = windows[win_index]->win; + + _win_show_time(win, '!'); + wattron(win, COLOUR_ONLINE); + wprintw(win, "-> %s has joined the room.\n", nick); + wattroff(win, COLOUR_ONLINE); + + if (win_index == current_index) + dirty = TRUE; +} + +void +win_show_room_member_presence(const char * const room, const char * const nick, + const char * const show, const char * const status) +{ + int win_index = _find_prof_win_index(room); + if (win_index != NUM_WINS) { + WINDOW *win = windows[win_index]->win; + _show_status_string(win, nick, show, status, NULL, "++", "online"); + } + + if (win_index == current_index) + dirty = TRUE; +} + +void +win_show_room_member_nick_change(const char * const room, + const char * const old_nick, const char * const nick) +{ + int win_index = _find_prof_win_index(room); + WINDOW *win = windows[win_index]->win; + + _win_show_time(win, '!'); + wattron(win, COLOUR_THEM); + wprintw(win, "** %s is now known as %s\n", old_nick, nick); + wattroff(win, COLOUR_THEM); + + if (win_index == current_index) + dirty = TRUE; +} + +void +win_show_room_nick_change(const char * const room, const char * const nick) +{ + int win_index = _find_prof_win_index(room); + WINDOW *win = windows[win_index]->win; + + _win_show_time(win, '!'); + wattron(win, COLOUR_ME); + wprintw(win, "** You are now known as %s\n", nick); + wattroff(win, COLOUR_ME); + + if (win_index == current_index) + dirty = TRUE; +} + +void +win_show_room_history(const char * const room_jid, const char * const nick, + GTimeVal tv_stamp, const char * const message) +{ + int win_index = _find_prof_win_index(room_jid); + WINDOW *win = windows[win_index]->win; + + GDateTime *time = g_date_time_new_from_timeval_utc(&tv_stamp); + gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); + wprintw(win, "%s - ", date_fmt); + g_date_time_unref(time); + g_free(date_fmt); + + if (strncmp(message, "/me ", 4) == 0) { + wprintw(win, "*%s ", nick); + wprintw(win, message + 4); + wprintw(win, "\n"); + } else { + wprintw(win, "%s: ", nick); + _win_show_message(win, message); + } + + if (win_index == current_index) + dirty = TRUE; +} + +void +win_show_room_message(const char * const room_jid, const char * const nick, + const char * const message) +{ + int win_index = _find_prof_win_index(room_jid); + WINDOW *win = windows[win_index]->win; + + _win_show_time(win, '-'); + if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { + if (strncmp(message, "/me ", 4) == 0) { + wattron(win, COLOUR_THEM); + wprintw(win, "*%s ", nick); + wprintw(win, message + 4); + wprintw(win, "\n"); + wattroff(win, COLOUR_THEM); + } else { + _win_show_user(win, nick, 1); + _win_show_message(win, message); + } + + } else { + if (strncmp(message, "/me ", 4) == 0) { + wattron(win, COLOUR_ME); + wprintw(win, "*%s ", nick); + wprintw(win, message + 4); + wprintw(win, "\n"); + wattroff(win, COLOUR_ME); + } else { + _win_show_user(win, nick, 0); + _win_show_message(win, message); + } + } + + // currently in groupchat window + if (win_index == current_index) { + status_bar_active(win_index); + dirty = TRUE; + + // not currenlty on groupchat window + } else { + status_bar_new(win_index); + _cons_show_incoming_message(nick, win_index); + if (current_index == 0) { + dirty = TRUE; + } + + if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { + if (prefs_get_flash()) { + flash(); + } + } + + windows[win_index]->unread++; + } + + if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { + if (prefs_get_beep()) { + beep(); + } + if (prefs_get_notify_message()) { + _notify_message(nick); + } + } +} + +void +win_show_room_subject(const char * const room_jid, const char * const subject) +{ + int win_index = _find_prof_win_index(room_jid); + WINDOW *win = windows[win_index]->win; + + _win_show_time(win, '!'); + wattron(win, COLOUR_ROOMINFO); + wprintw(win, "Room subject: "); + wattroff(win, COLOUR_ROOMINFO); + wprintw(win, "%s\n", subject); + + // currently in groupchat window + if (win_index == current_index) { + status_bar_active(win_index); + dirty = TRUE; + + // not currenlty on groupchat window + } else { + status_bar_new(win_index); + } +} + +void +win_show_room_broadcast(const char * const room_jid, const char * const message) +{ + int win_index = _find_prof_win_index(room_jid); + WINDOW *win = windows[win_index]->win; + + _win_show_time(win, '!'); + wattron(win, COLOUR_ROOMINFO); + wprintw(win, "Room message: "); + wattroff(win, COLOUR_ROOMINFO); + wprintw(win, "%s\n", message); + + // currently in groupchat window + if (win_index == current_index) { + status_bar_active(win_index); + dirty = TRUE; + + // not currenlty on groupchat window + } else { + status_bar_new(win_index); + } +} + +void +cons_show_wins(void) +{ + int i = 0; + int count = 0; + + cons_show(""); + cons_show("Active windows:"); + _win_show_time(console->win, '-'); + wprintw(console->win, "1: Console\n"); + + for (i = 1; i < NUM_WINS; i++) { + if (windows[i] != NULL) { + count++; + } + } + + if (count != 0) { + for (i = 1; i < NUM_WINS; i++) { + if (windows[i] != NULL) { + ProfWin *window = windows[i]; + _win_show_time(console->win, '-'); + + switch (window->type) + { + case WIN_CHAT: + wprintw(console->win, "%d: chat %s", i + 1, window->from); + PContact contact = contact_list_get_contact(window->from); + + if (contact != NULL) { + if (p_contact_name(contact) != NULL) { + wprintw(console->win, " (%s)", p_contact_name(contact)); + } + wprintw(console->win, " - %s", p_contact_presence(contact)); + } + + if (window->unread > 0) { + wprintw(console->win, ", %d unread", window->unread); + } + + break; + + case WIN_PRIVATE: + wprintw(console->win, "%d: private %s", i + 1, window->from); + + if (window->unread > 0) { + wprintw(console->win, ", %d unread", window->unread); + } + + break; + + case WIN_MUC: + wprintw(console->win, "%d: room %s", i + 1, window->from); + + if (window->unread > 0) { + wprintw(console->win, ", %d unread", window->unread); + } + + break; + + default: + break; + } + + wprintw(console->win, "\n"); + } + } + } + + cons_show(""); +} + +void +cons_show_info(PContact pcontact) +{ + _win_show_info(console->win, pcontact); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +void +cons_show_status(const char * const contact) +{ + PContact pcontact = contact_list_get_contact(contact); + + if (pcontact != NULL) { + _win_show_contact(console, pcontact); + } else { + cons_show("No such contact \"%s\" in roster.", contact); + } +} + +void +win_show_status(void) +{ + char *recipient = win_current_get_recipient(); + PContact pcontact = contact_list_get_contact(recipient); + + if (pcontact != NULL) { + _win_show_contact(current, pcontact); + } else { + win_current_show("Error getting contact info."); + } +} + +void +win_private_show_status(void) +{ + Jid *jid = jid_create(win_current_get_recipient()); + + PContact pcontact = muc_get_participant(jid->barejid, jid->resourcepart); + + if (pcontact != NULL) { + _win_show_contact(current, pcontact); + } else { + win_current_show("Error getting contact info."); + } + + jid_destroy(jid); +} + +void +win_room_show_status(const char * const contact) +{ + PContact pcontact = muc_get_participant(win_current_get_recipient(), contact); + + if (pcontact != NULL) { + _win_show_contact(current, pcontact); + } else { + win_current_show("No such participant \"%s\" in room.", contact); + } +} + +void +cons_show_account(ProfAccount *account) +{ + cons_show("%s account details:", account->name); + if (account->enabled) { + cons_show("enabled : TRUE"); + } else { + cons_show("enabled : FALSE"); + } + cons_show("jid : %s", account->jid); + if (account->resource != NULL) { + cons_show("resource : %s", account->resource); + } + if (account->server != NULL) { + cons_show("server : %s", account->server); + } + cons_show(""); +} + +void +cons_show_ui_prefs(void) +{ + cons_show("UI preferences:"); + cons_show(""); + + gchar *theme = prefs_get_theme(); + if (theme == NULL) { + cons_show("Theme (/theme) : default"); + } else { + cons_show("Theme (/theme) : %s", theme); + } + + if (prefs_get_beep()) + cons_show("Terminal beep (/beep) : ON"); + else + cons_show("Terminal beep (/beep) : OFF"); + + if (prefs_get_flash()) + cons_show("Terminal flash (/flash) : ON"); + else + cons_show("Terminal flash (/flash) : OFF"); + + if (prefs_get_intype()) + cons_show("Show typing (/intype) : ON"); + else + cons_show("Show typing (/intype) : OFF"); + + if (prefs_get_splash()) + cons_show("Splash screen (/splash) : ON"); + else + cons_show("Splash screen (/splash) : OFF"); + + if (prefs_get_history()) + cons_show("Chat history (/history) : ON"); + else + cons_show("Chat history (/history) : OFF"); + + if (prefs_get_vercheck()) + cons_show("Version checking (/vercheck) : ON"); + else + cons_show("Version checking (/vercheck) : OFF"); + + if (prefs_get_mouse()) + cons_show("Mouse handling (/mouse) : ON"); + else + cons_show("Mouse handling (/mouse) : OFF"); + + if (prefs_get_statuses()) + cons_show("Status (/statuses) : ON"); + else + cons_show("Status (/statuses) : OFF"); +} + +void +cons_show_desktop_prefs(void) +{ + cons_show("Desktop notification preferences:"); + cons_show(""); + + if (prefs_get_notify_message()) + cons_show("Messages (/notify message) : ON"); + else + cons_show("Messages (/notify message) : OFF"); + + if (prefs_get_notify_typing()) + cons_show("Composing (/notify typing) : ON"); + else + cons_show("Composing (/notify typing) : OFF"); + + gint remind_period = prefs_get_notify_remind(); + if (remind_period == 0) { + cons_show("Reminder period (/notify remind) : OFF"); + } else if (remind_period == 1) { + cons_show("Reminder period (/notify remind) : 1 second"); + } else { + cons_show("Reminder period (/notify remind) : %d seconds", remind_period); + } +} + +void +cons_show_chat_prefs(void) +{ + cons_show("Chat preferences:"); + cons_show(""); + + if (prefs_get_states()) + cons_show("Send chat states (/states) : ON"); + else + cons_show("Send chat states (/states) : OFF"); + + if (prefs_get_outtype()) + cons_show("Send composing (/outtype) : ON"); + else + cons_show("Send composing (/outtype) : OFF"); + + gint gone_time = prefs_get_gone(); + if (gone_time == 0) { + cons_show("Leave conversation (/gone) : OFF"); + } else if (gone_time == 1) { + cons_show("Leave conversation (/gone) : 1 minute"); + } else { + cons_show("Leave conversation (/gone) : %d minutes", gone_time); + } +} + +void +cons_show_log_prefs(void) +{ + cons_show("Logging preferences:"); + cons_show(""); + + cons_show("Max log size (/log maxsize) : %d bytes", prefs_get_max_log_size()); + + if (prefs_get_chlog()) + cons_show("Chat logging (/chlog) : ON"); + else + cons_show("Chat logging (/chlog) : OFF"); +} + +void +cons_show_presence_prefs(void) +{ + cons_show("Presence preferences:"); + cons_show(""); + + cons_show("Priority (/priority) : %d", prefs_get_priority()); + + if (strcmp(prefs_get_autoaway_mode(), "off") == 0) { + cons_show("Autoaway (/autoaway mode) : OFF"); + } else { + cons_show("Autoaway (/autoaway mode) : %s", prefs_get_autoaway_mode()); + } + + cons_show("Autoaway minutes (/autoaway time) : %d minutes", prefs_get_autoaway_time()); + + if ((prefs_get_autoaway_message() == NULL) || + (strcmp(prefs_get_autoaway_message(), "") == 0)) { + cons_show("Autoaway message (/autoaway message) : OFF"); + } else { + cons_show("Autoaway message (/autoaway message) : \"%s\"", prefs_get_autoaway_message()); + } + + if (prefs_get_autoaway_check()) { + cons_show("Autoaway check (/autoaway check) : ON"); + } else { + cons_show("Autoaway check (/autoaway check) : OFF"); + } +} + +void +cons_show_connection_prefs(void) +{ + cons_show("Connection preferences:"); + cons_show(""); + + gint reconnect_interval = prefs_get_reconnect(); + if (reconnect_interval == 0) { + cons_show("Reconnect interval (/reconnect) : OFF"); + } else if (reconnect_interval == 1) { + cons_show("Reconnect interval (/reconnect) : 1 second"); + } else { + cons_show("Reconnect interval (/reconnect) : %d seconds", reconnect_interval); + } + + gint autoping_interval = prefs_get_autoping(); + if (autoping_interval == 0) { + cons_show("Autoping interval (/autoping) : OFF"); + } else if (autoping_interval == 1) { + cons_show("Autoping interval (/autoping) : 1 second"); + } else { + cons_show("Autoping interval (/autoping) : %d seconds", autoping_interval); + } +} + +void +cons_show_themes(GSList *themes) +{ + cons_show(""); + + if (themes == NULL) { + cons_show("No available themes."); + } else { + cons_show("Available themes:"); + while (themes != NULL) { + cons_show(themes->data); + themes = g_slist_next(themes); + } + } +} + +void +cons_prefs(void) +{ + cons_show(""); + cons_show_ui_prefs(); + cons_show(""); + cons_show_desktop_prefs(); + cons_show(""); + cons_show_chat_prefs(); + cons_show(""); + cons_show_log_prefs(); + cons_show(""); + cons_show_presence_prefs(); + cons_show(""); + cons_show_connection_prefs(); + cons_show(""); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +static void +_cons_show_basic_help(void) +{ + cons_show(""); + + GSList *basic_helpers = cmd_get_basic_help(); + while (basic_helpers != NULL) { + struct cmd_help_t *help = (struct cmd_help_t *)basic_helpers->data; + cons_show("%-30s: %s", help->usage, help->short_help); + basic_helpers = g_slist_next(basic_helpers); + } + + cons_show(""); +} + +void +cons_help(void) +{ + cons_show(""); + cons_show("Choose a help option:"); + cons_show(""); + cons_show("/help list - List all commands."); + cons_show("/help basic - Summary of basic usage commands."); + cons_show("/help presence - Summary of online status change commands."); + cons_show("/help settings - Summary of commands for changing Profanity settings."); + cons_show("/help navigation - How to navigate around Profanity."); + cons_show("/help [command] - Detailed help on a specific command."); + cons_show(""); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +void +cons_basic_help(void) +{ + cons_show(""); + cons_show("Basic Commands:"); + _cons_show_basic_help(); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +void +cons_settings_help(void) +{ + cons_show(""); + cons_show("Settings:"); + cons_show(""); + + GSList *settings_helpers = cmd_get_settings_help(); + while (settings_helpers != NULL) { + struct cmd_help_t *help = (struct cmd_help_t *)settings_helpers->data; + cons_show("%-27s: %s", help->usage, help->short_help); + settings_helpers = g_slist_next(settings_helpers); + } + + cons_show(""); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +void +cons_presence_help(void) +{ + cons_show(""); + cons_show("Presence changes:"); + cons_show(""); + + GSList *presence_helpers = cmd_get_presence_help(); + while (presence_helpers != NULL) { + struct cmd_help_t *help = (struct cmd_help_t *)presence_helpers->data; + cons_show("%-25s: %s", help->usage, help->short_help); + presence_helpers = g_slist_next(presence_helpers); + } + + cons_show(""); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +void +cons_navigation_help(void) +{ + cons_show(""); + cons_show("Navigation:"); + cons_show(""); + cons_show("Alt-1 : This console window."); + cons_show("Alt-2..Alt-0 : Chat windows."); + cons_show("F1 : This console window."); + cons_show("F2..F10 : Chat windows."); + cons_show("UP, DOWN : Navigate input history."); + cons_show("LEFT, RIGHT, HOME, END : Edit current input."); + cons_show("ESC : Clear current input."); + cons_show("TAB : Autocomplete command/recipient/login."); + cons_show("PAGE UP, PAGE DOWN : Page the main window."); + cons_show("Mouse wheel : Scroll the main window."); + cons_show(""); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +void +cons_show_contacts(GSList *list) +{ + GSList *curr = list; + + while(curr) { + PContact contact = curr->data; + if (strcmp(p_contact_subscription(contact), "none") != 0) { + _win_show_contact(console, contact); + } + curr = g_slist_next(curr); + } +} + +void +cons_bad_show(const char * const msg, ...) +{ + va_list arg; + va_start(arg, msg); + GString *fmt_msg = g_string_new(NULL); + g_string_vprintf(fmt_msg, msg, arg); + _win_show_time(console->win, '-'); + wattron(console->win, COLOUR_ERROR); + wprintw(console->win, "%s\n", fmt_msg->str); + wattroff(console->win, COLOUR_ERROR); + g_string_free(fmt_msg, TRUE); + va_end(arg); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +void +cons_show_time(void) +{ + _win_show_time(console->win, '-'); +} + +void +cons_show(const char * const msg, ...) +{ + va_list arg; + va_start(arg, msg); + GString *fmt_msg = g_string_new(NULL); + g_string_vprintf(fmt_msg, msg, arg); + _win_show_time(console->win, '-'); + wprintw(console->win, "%s\n", fmt_msg->str); + g_string_free(fmt_msg, TRUE); + va_end(arg); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +void +cons_show_word(const char * const word) +{ + wprintw(console->win, "%s", word); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +void +cons_bad_command(const char * const cmd) +{ + _win_show_time(console->win, '-'); + wprintw(console->win, "Unknown command: %s\n", cmd); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +void +cons_about(void) +{ + int rows, cols; + getmaxyx(stdscr, rows, cols); + + if (prefs_get_splash()) { + _cons_splash_logo(); + } else { + _win_show_time(console->win, '-'); + + if (strcmp(PACKAGE_STATUS, "development") == 0) { + wprintw(console->win, "Welcome to Profanity, version %sdev\n", PACKAGE_VERSION); + } else { + wprintw(console->win, "Welcome to Profanity, version %s\n", PACKAGE_VERSION); + } + } + + _win_show_time(console->win, '-'); + wprintw(console->win, "Copyright (C) 2012, 2013 James Booth <%s>.\n", PACKAGE_BUGREPORT); + _win_show_time(console->win, '-'); + wprintw(console->win, "License GPLv3+: GNU GPL version 3 or later \n"); + _win_show_time(console->win, '-'); + wprintw(console->win, "\n"); + _win_show_time(console->win, '-'); + wprintw(console->win, "This is free software; you are free to change and redistribute it.\n"); + _win_show_time(console->win, '-'); + wprintw(console->win, "There is NO WARRANTY, to the extent permitted by law.\n"); + _win_show_time(console->win, '-'); + wprintw(console->win, "\n"); + _win_show_time(console->win, '-'); + wprintw(console->win, "Type '/help' to show complete help.\n"); + _win_show_time(console->win, '-'); + wprintw(console->win, "\n"); + + if (prefs_get_vercheck()) { + cons_check_version(FALSE); + } + + prefresh(console->win, 0, 0, 1, 0, rows-3, cols-1); + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } +} + +void +cons_check_version(gboolean not_available_msg) +{ + char *latest_release = release_get_latest(); + + if (latest_release != NULL) { + gboolean relase_valid = g_regex_match_simple("^\\d+\\.\\d+\\.\\d+$", latest_release, 0, 0); + + if (relase_valid) { + if (_new_release(latest_release)) { + _win_show_time(console->win, '-'); + wprintw(console->win, "A new version of Profanity is available: %s", latest_release); + _win_show_time(console->win, '-'); + wprintw(console->win, "Check for details.\n"); + free(latest_release); + _win_show_time(console->win, '-'); + wprintw(console->win, "\n"); + } else { + if (not_available_msg) { + cons_show("No new version available."); + cons_show(""); + } + } + + if (current_index == 0) { + dirty = TRUE; + } else { + status_bar_new(0); + } + } + } +} + +void +notify_remind(void) +{ + gint unread = _win_get_unread(); + if (unread > 0) { + _notify_remind(unread); + } +} + +static void +_notify(const char * const message, int timeout, + const char * const category) +{ +#ifdef HAVE_LIBNOTIFY + gboolean notify_initted = notify_is_initted(); + + if (!notify_initted) { + notify_initted = notify_init("Profanity"); + } + + if (notify_initted) { + NotifyNotification *notification; + notification = notify_notification_new("Profanity", message, NULL); + notify_notification_set_timeout(notification, timeout); + notify_notification_set_category(notification, category); + notify_notification_set_urgency(notification, NOTIFY_URGENCY_NORMAL); + + GError *error = NULL; + gboolean notify_success = notify_notification_show(notification, &error); + + if (!notify_success) { + log_error("Error sending desktop notification:"); + log_error(" -> Message : %s", message); + log_error(" -> Error : %s", error->message); + } + } else { + log_error("Libnotify initialisation error."); + } +#endif +#ifdef PLATFORM_CYGWIN + NOTIFYICONDATA nid; + nid.cbSize = sizeof(NOTIFYICONDATA); + //nid.hWnd = hWnd; + nid.uID = 100; + nid.uVersion = NOTIFYICON_VERSION; + //nid.uCallbackMessage = WM_MYMESSAGE; + nid.hIcon = LoadIcon(NULL, IDI_APPLICATION); + strcpy(nid.szTip, "Tray Icon"); + nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; + Shell_NotifyIcon(NIM_ADD, &nid); + + // For a Ballon Tip + nid.uFlags = NIF_INFO; + strcpy(nid.szInfoTitle, "Profanity"); // Title + strcpy(nid.szInfo, message); // Copy Tip + nid.uTimeout = timeout; // 3 Seconds + nid.dwInfoFlags = NIIF_INFO; + + Shell_NotifyIcon(NIM_MODIFY, &nid); +#endif +} + +static void +_notify_remind(gint unread) +{ + char message[20]; + if (unread == 1) { + sprintf(message, "1 unread message"); + } else { + snprintf(message, sizeof(message), "%d unread messages", unread); + } + + _notify(message, 5000, "Incoming message"); +} + +static void +_notify_message(const char * const short_from) +{ + char message[strlen(short_from) + 1 + 10]; + sprintf(message, "%s: message.", short_from); + + _notify(message, 10000, "Incoming message"); +} + +static void +_notify_typing(const char * const from) +{ + char message[strlen(from) + 1 + 11]; + sprintf(message, "%s: typing...", from); + + _notify(message, 10000, "Incoming message"); +} + +static void +_create_windows(void) +{ + int cols = getmaxx(stdscr); + max_cols = cols; + windows[0] = window_create(CONS_WIN_TITLE, cols, WIN_CONSOLE); + console = windows[0]; + current = console; + cons_about(); +} + +static gboolean +_new_release(char *found_version) +{ + int curr_maj, curr_min, curr_patch, found_maj, found_min, found_patch; + + int parse_curr = sscanf(PACKAGE_VERSION, "%d.%d.%d", &curr_maj, &curr_min, + &curr_patch); + int parse_found = sscanf(found_version, "%d.%d.%d", &found_maj, &found_min, + &found_patch); + + if (parse_found == 3 && parse_curr == 3) { + if (found_maj > curr_maj) { + return TRUE; + } else if (found_maj == curr_maj && found_min > curr_min) { + return TRUE; + } else if (found_maj == curr_maj && found_min == curr_min + && found_patch > curr_patch) { + return TRUE; + } else { + return FALSE; + } + } else { + return FALSE; + } +} + +static void +_cons_splash_logo(void) +{ + _win_show_time(console->win, '-'); + wprintw(console->win, "Welcome to\n"); + + _win_show_time(console->win, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, " ___ _ \n"); + wattroff(console->win, COLOUR_SPLASH); + + _win_show_time(console->win, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, " / __) (_)_ \n"); + wattroff(console->win, COLOUR_SPLASH); + + _win_show_time(console->win, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, " ____ ____ ___ | |__ ____ ____ _| |_ _ _ \n"); + wattroff(console->win, COLOUR_SPLASH); + + _win_show_time(console->win, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, "| _ \\ / ___) _ \\| __) _ | _ \\| | _) | | |\n"); + wattroff(console->win, COLOUR_SPLASH); + + _win_show_time(console->win, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, "| | | | | | |_| | | ( ( | | | | | | |_| |_| |\n"); + wattroff(console->win, COLOUR_SPLASH); + + _win_show_time(console->win, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, "| ||_/|_| \\___/|_| \\_||_|_| |_|_|\\___)__ |\n"); + wattroff(console->win, COLOUR_SPLASH); + + _win_show_time(console->win, '-'); + wattron(console->win, COLOUR_SPLASH); + wprintw(console->win, "|_| (____/ \n"); + wattroff(console->win, COLOUR_SPLASH); + + _win_show_time(console->win, '-'); + wprintw(console->win, "\n"); + _win_show_time(console->win, '-'); + if (strcmp(PACKAGE_STATUS, "development") == 0) { + wprintw(console->win, "Version %sdev\n", PACKAGE_VERSION); + } else { + wprintw(console->win, "Version %s\n", PACKAGE_VERSION); + } +} + +static int +_find_prof_win_index(const char * const contact) +{ + int i; + for (i = 1; i < NUM_WINS; i++) { + if ((windows[i] != NULL) && (strcmp(windows[i]->from, contact) == 0)) { + break; + } + } + + return i; +} + +static int +_new_prof_win(const char * const contact, win_type_t type) +{ + int i; + for (i = 1; i < NUM_WINS; i++) { + if (windows[i] == NULL) { + break; + } + } + + if (i != NUM_WINS) { + int cols = getmaxx(stdscr); + windows[i] = window_create(contact, cols, type); + return i; + } else { + return 0; + } +} + +static void +_win_show_time(WINDOW *win, char showchar) +{ + GDateTime *time = g_date_time_new_now_local(); + gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); + wattron(win, COLOUR_TIME); + wprintw(win, "%s %c ", date_fmt, showchar); + wattroff(win, COLOUR_TIME); + g_date_time_unref(time); + g_free(date_fmt); +} + +static void +_win_show_user(WINDOW *win, const char * const user, const int colour) +{ + if (colour) + wattron(win, COLOUR_THEM); + else + wattron(win, COLOUR_ME); + wprintw(win, "%s: ", user); + if (colour) + wattroff(win, COLOUR_THEM); + else + wattroff(win, COLOUR_ME); +} + +static void +_win_show_message(WINDOW *win, const char * const message) +{ + wprintw(win, "%s\n", message); +} + +static void +_win_show_error_msg(WINDOW *win, const char * const message) +{ + wattron(win, COLOUR_ERROR); + wprintw(win, "%s\n", message); + wattroff(win, COLOUR_ERROR); +} + +static void +_current_window_refresh(void) +{ + int rows, cols; + getmaxyx(stdscr, rows, cols); + + prefresh(current->win, current->y_pos, 0, 1, 0, rows-3, cols-1); +} + +void +_win_resize_all(void) +{ + int rows, cols; + getmaxyx(stdscr, rows, cols); + + // only make the pads bigger, to avoid data loss on cropping + if (cols > max_cols) { + max_cols = cols; + + int i; + for (i = 0; i < NUM_WINS; i++) { + if (windows[i] != NULL) { + wresize(windows[i]->win, PAD_SIZE, cols); + } + } + } + + prefresh(current->win, current->y_pos, 0, 1, 0, rows-3, cols-1); +} + +static void +_presence_colour_on(WINDOW *win, const char * const presence) +{ + if (g_strcmp0(presence, "online") == 0) { + wattron(win, COLOUR_ONLINE); + } else if (g_strcmp0(presence, "away") == 0) { + wattron(win, COLOUR_AWAY); + } else if (g_strcmp0(presence, "chat") == 0) { + wattron(win, COLOUR_CHAT); + } else if (g_strcmp0(presence, "dnd") == 0) { + wattron(win, COLOUR_DND); + } else if (g_strcmp0(presence, "xa") == 0) { + wattron(win, COLOUR_XA); + } else { + wattron(win, COLOUR_OFFLINE); + } +} + +static void +_presence_colour_off(WINDOW *win, const char * const presence) +{ + if (g_strcmp0(presence, "online") == 0) { + wattroff(win, COLOUR_ONLINE); + } else if (g_strcmp0(presence, "away") == 0) { + wattroff(win, COLOUR_AWAY); + } else if (g_strcmp0(presence, "chat") == 0) { + wattroff(win, COLOUR_CHAT); + } else if (g_strcmp0(presence, "dnd") == 0) { + wattroff(win, COLOUR_DND); + } else if (g_strcmp0(presence, "xa") == 0) { + wattroff(win, COLOUR_XA); + } else { + wattroff(win, COLOUR_OFFLINE); + } +} + +static void +_show_status_string(WINDOW *win, const char * const from, + const char * const show, const char * const status, + GDateTime *last_activity, const char * const pre, + const char * const default_show) +{ + if (!prefs_get_statuses()) + return; + + _win_show_time(win, '-'); + + if (show != NULL) { + if (strcmp(show, "away") == 0) { + wattron(win, COLOUR_AWAY); + } else if (strcmp(show, "chat") == 0) { + wattron(win, COLOUR_CHAT); + } else if (strcmp(show, "dnd") == 0) { + wattron(win, COLOUR_DND); + } else if (strcmp(show, "xa") == 0) { + wattron(win, COLOUR_XA); + } else if (strcmp(show, "online") == 0) { + wattron(win, COLOUR_ONLINE); + } else { + wattron(win, COLOUR_OFFLINE); + } + } else if (strcmp(default_show, "online") == 0) { + wattron(win, COLOUR_ONLINE); + } else { + wattron(win, COLOUR_OFFLINE); + } + + wprintw(win, "%s %s", pre, from); + + if (show != NULL) + wprintw(win, " is %s", show); + else + wprintw(win, " is %s", default_show); + + if (last_activity != NULL) { + GDateTime *now = g_date_time_new_now_local(); + GTimeSpan span = g_date_time_difference(now, last_activity); + + wprintw(win, ", idle "); + + int hours = span / G_TIME_SPAN_HOUR; + span = span - hours * G_TIME_SPAN_HOUR; + if (hours > 0) { + wprintw(win, "%dh", hours); + } + + int minutes = span / G_TIME_SPAN_MINUTE; + span = span - minutes * G_TIME_SPAN_MINUTE; + wprintw(win, "%dm", minutes); + + int seconds = span / G_TIME_SPAN_SECOND; + wprintw(win, "%ds", seconds); + } + + if (status != NULL) + wprintw(win, ", \"%s\"", status); + + wprintw(win, "\n"); + + if (show != NULL) { + if (strcmp(show, "away") == 0) { + wattroff(win, COLOUR_AWAY); + } else if (strcmp(show, "chat") == 0) { + wattroff(win, COLOUR_CHAT); + } else if (strcmp(show, "dnd") == 0) { + wattroff(win, COLOUR_DND); + } else if (strcmp(show, "xa") == 0) { + wattroff(win, COLOUR_XA); + } else if (strcmp(show, "online") == 0) { + wattroff(win, COLOUR_ONLINE); + } else { + wattroff(win, COLOUR_OFFLINE); + } + } else if (strcmp(default_show, "online") == 0) { + wattroff(win, COLOUR_ONLINE); + } else { + wattroff(win, COLOUR_OFFLINE); + } +} + +static void +_cons_show_typing(const char * const short_from) +{ + _win_show_time(console->win, '-'); + wattron(console->win, COLOUR_TYPING); + wprintw(console->win, "!! %s is typing a message...\n", short_from); + wattroff(console->win, COLOUR_TYPING); +} + +static void +_cons_show_incoming_message(const char * const short_from, const int win_index) +{ + _win_show_time(console->win, '-'); + wattron(console->win, COLOUR_INCOMING); + wprintw(console->win, "<< incoming from %s (%d)\n", short_from, win_index + 1); + wattroff(console->win, COLOUR_INCOMING); +} + +static void +_win_show_contact(ProfWin *window, PContact contact) +{ + const char *jid = p_contact_jid(contact); + const char *name = p_contact_name(contact); + const char *presence = p_contact_presence(contact); + const char *status = p_contact_status(contact); + GDateTime *last_activity = p_contact_last_activity(contact); + + _win_show_time(window->win, '-'); + _presence_colour_on(window->win, presence); + wprintw(window->win, "%s", jid); + + if (name != NULL) { + wprintw(window->win, " (%s)", name); + } + + wprintw(window->win, " is %s", presence); + + if (last_activity != NULL) { + GDateTime *now = g_date_time_new_now_local(); + GTimeSpan span = g_date_time_difference(now, last_activity); + + wprintw(window->win, ", idle "); + + int hours = span / G_TIME_SPAN_HOUR; + span = span - hours * G_TIME_SPAN_HOUR; + if (hours > 0) { + wprintw(window->win, "%dh", hours); + } + + int minutes = span / G_TIME_SPAN_MINUTE; + span = span - minutes * G_TIME_SPAN_MINUTE; + wprintw(window->win, "%dm", minutes); + + int seconds = span / G_TIME_SPAN_SECOND; + wprintw(window->win, "%ds", seconds); + } + + if (status != NULL) { + wprintw(window->win, ", \"%s\"", p_contact_status(contact)); + } + + wprintw(window->win, "\n"); + _presence_colour_off(window->win, presence); +} + +static void +_win_handle_switch(const wint_t * const ch) +{ + if (*ch == KEY_F(1)) { + ui_switch_win(0); + } else if (*ch == KEY_F(2)) { + ui_switch_win(1); + } else if (*ch == KEY_F(3)) { + ui_switch_win(2); + } else if (*ch == KEY_F(4)) { + ui_switch_win(3); + } else if (*ch == KEY_F(5)) { + ui_switch_win(4); + } else if (*ch == KEY_F(6)) { + ui_switch_win(5); + } else if (*ch == KEY_F(7)) { + ui_switch_win(6); + } else if (*ch == KEY_F(8)) { + ui_switch_win(7); + } else if (*ch == KEY_F(9)) { + ui_switch_win(8); + } else if (*ch == KEY_F(10)) { + ui_switch_win(9); + } +} + +static void +_win_handle_page(const wint_t * const ch) +{ + int rows = getmaxy(stdscr); + int y = getcury(current->win); + + int page_space = rows - 4; + int *page_start = &(current->y_pos); + + if (prefs_get_mouse()) { + MEVENT mouse_event; + + if (*ch == KEY_MOUSE) { + if (getmouse(&mouse_event) == OK) { + +#ifdef PLATFORM_CYGWIN + if (mouse_event.bstate & BUTTON5_PRESSED) { // mouse wheel down +#else + if (mouse_event.bstate & BUTTON2_PRESSED) { // mouse wheel down +#endif + *page_start += 4; + + // only got half a screen, show full screen + if ((y - (*page_start)) < page_space) + *page_start = y - page_space; + + // went past end, show full screen + else if (*page_start >= y) + *page_start = y - page_space; + + current->paged = 1; + dirty = TRUE; + } else if (mouse_event.bstate & BUTTON4_PRESSED) { // mouse wheel up + *page_start -= 4; + + // went past beginning, show first page + if (*page_start < 0) + *page_start = 0; + + current->paged = 1; + dirty = TRUE; + } + } + } + } + + // page up + if (*ch == KEY_PPAGE) { + *page_start -= page_space; + + // went past beginning, show first page + if (*page_start < 0) + *page_start = 0; + + current->paged = 1; + dirty = TRUE; + + // page down + } else if (*ch == KEY_NPAGE) { + *page_start += page_space; + + // only got half a screen, show full screen + if ((y - (*page_start)) < page_space) + *page_start = y - page_space; + + // went past end, show full screen + else if (*page_start >= y) + *page_start = y - page_space; + + current->paged = 1; + dirty = TRUE; + } +} + +static gint +_win_get_unread(void) +{ + int i; + gint result = 0; + for (i = 0; i < NUM_WINS; i++) { + if (windows[i] != NULL) { + result += windows[i]->unread; + } + } + return result; +} + +static void +_win_show_history(WINDOW *win, int win_index, const char * const contact) +{ + if (!windows[win_index]->history_shown) { + GSList *history = NULL; + history = chat_log_get_previous(jabber_get_jid(), contact, history); + while (history != NULL) { + wprintw(win, "%s\n", history->data); + history = g_slist_next(history); + } + windows[win_index]->history_shown = 1; + + g_slist_free_full(history, free); + } +} + +static void +_win_show_info(WINDOW *win, PContact pcontact) +{ + const char *jid = p_contact_jid(pcontact); + const char *name = p_contact_name(pcontact); + const char *presence = p_contact_presence(pcontact); + const char *status = p_contact_status(pcontact); + const char *sub = p_contact_subscription(pcontact); + const char *caps_str = p_contact_caps_str(pcontact); + GDateTime *last_activity = p_contact_last_activity(pcontact); + + _win_show_time(win, '-'); + wprintw(win, "\n"); + _win_show_time(win, '-'); + _presence_colour_on(win, presence); + wprintw(win, "%s:\n", jid); + _presence_colour_off(win, presence); + + if (name != NULL) { + _win_show_time(win, '-'); + wprintw(win, "Name : %s\n", name); + } + + if (sub != NULL) { + _win_show_time(win, '-'); + wprintw(win, "Subscription : %s\n", sub); + } + + _win_show_time(win, '-'); + wprintw(win, "Presence : "); + _presence_colour_on(win, presence); + wprintw(win, "%s\n", presence); + _presence_colour_off(win, presence); + + if (status != NULL) { + _win_show_time(win, '-'); + wprintw(win, "Message : %s\n", status); + } + + if (last_activity != NULL) { + GDateTime *now = g_date_time_new_now_local(); + GTimeSpan span = g_date_time_difference(now, last_activity); + + _win_show_time(win, '-'); + wprintw(win, "Last activity : "); + + int hours = span / G_TIME_SPAN_HOUR; + span = span - hours * G_TIME_SPAN_HOUR; + if (hours > 0) { + wprintw(win, "%dh", hours); + } + + int minutes = span / G_TIME_SPAN_MINUTE; + span = span - minutes * G_TIME_SPAN_MINUTE; + wprintw(win, "%dm", minutes); + + int seconds = span / G_TIME_SPAN_SECOND; + wprintw(win, "%ds", seconds); + + wprintw(win, "\n"); + + g_date_time_unref(now); + } + + if (caps_str != NULL) { + Capabilities *caps = caps_get(caps_str); + if ((caps != NULL) && (caps->client != NULL)) { + _win_show_time(win, '-'); + wprintw(win, "Client : %s\n", caps->client); + } + } + +} + +void +_set_current(int index) +{ + current_index = index; + current = windows[current_index]; +} + diff --git a/src/windows.c b/src/windows.c deleted file mode 100644 index 290bf6a1..00000000 --- a/src/windows.c +++ /dev/null @@ -1,2423 +0,0 @@ -/* - * windows.c - * - * Copyright (C) 2012, 2013 James Booth - * - * This file is part of Profanity. - * - * Profanity 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 3 of the License, or - * (at your option) any later version. - * - * Profanity 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 Profanity. If not, see . - * - */ - -#include "config.h" - -#include -#include - -#ifdef HAVE_LIBXSS -#include -#endif - -#include - -#ifdef HAVE_LIBNOTIFY -#include -#endif -#ifdef PLATFORM_CYGWIN -#include -#endif - -#ifdef HAVE_NCURSESW_NCURSES_H -#include -#elif HAVE_NCURSES_H -#include -#endif - -#include "chat_log.h" -#include "chat_session.h" -#include "command.h" -#include "common.h" -#include "contact.h" -#include "contact_list.h" -#include "jid.h" -#include "log.h" -#include "preferences.h" -#include "release.h" -#include "muc.h" -#include "theme.h" -#include "ui.h" -#include "window.h" - -#define CONS_WIN_TITLE "_cons" -#define NUM_WINS 10 - -// holds console at index 0 and chat wins 1 through to 9 -static ProfWin* windows[NUM_WINS]; - -// the window currently being displayed -static int current_index = 0; -static ProfWin *current; -static ProfWin *console; - -// current window state -static int dirty; - -// max columns for main windows, never resize below -static int max_cols = 0; - -static char *win_title; - -#ifdef HAVE_LIBXSS -static Display *display; -#endif - -static GTimer *ui_idle_time; - -static void _set_current(int index); -static void _create_windows(void); -static void _cons_splash_logo(void); -static void _cons_show_basic_help(void); -static void _win_show_contact(ProfWin *window, PContact contact); -static int _find_prof_win_index(const char * const contact); -static int _new_prof_win(const char * const contact, win_type_t type); -static void _current_window_refresh(void); -static void _win_show_time(WINDOW *win, char showchar); -static void _win_show_user(WINDOW *win, const char * const user, const int colour); -static void _win_show_message(WINDOW *win, const char * const message); -static void _win_show_error_msg(WINDOW *win, const char * const message); -static void _show_status_string(WINDOW *win, const char * const from, - const char * const show, const char * const status, - GDateTime *last_activity, const char * const pre, - const char * const default_show); -static void _cons_show_typing(const char * const short_from); -static void _cons_show_incoming_message(const char * const short_from, - const int win_index); -static void _win_handle_switch(const wint_t * const ch); -static void _win_handle_page(const wint_t * const ch); -static void _win_resize_all(void); -static gint _win_get_unread(void); -static void _win_show_history(WINDOW *win, int win_index, - const char * const contact); -static void _win_show_info(WINDOW *win, PContact pcontact); -static gboolean _new_release(char *found_version); -static void _ui_draw_win_title(void); -static void _presence_colour_on(WINDOW *win, const char * const presence); -static void _presence_colour_off(WINDOW *win, const char * const presence); - -static void _notify(const char * const message, int timeout, - const char * const category); -static void _notify_remind(gint unread); -static void _notify_message(const char * const short_from); -static void _notify_typing(const char * const from); - -void -ui_init(void) -{ - log_info("Initialising UI"); - initscr(); - raw(); - keypad(stdscr, TRUE); - if (prefs_get_mouse()) { - mousemask(ALL_MOUSE_EVENTS, NULL); - mouseinterval(5); - } - ui_load_colours(); - refresh(); - create_title_bar(); - create_status_bar(); - status_bar_active(0); - create_input_window(); - _create_windows(); -#ifdef HAVE_LIBXSS - display = XOpenDisplay(0); -#endif - ui_idle_time = g_timer_new(); - dirty = TRUE; -} - -void -ui_refresh(void) -{ - _ui_draw_win_title(); - - title_bar_refresh(); - status_bar_refresh(); - - if (dirty) { - _current_window_refresh(); - dirty = FALSE; - } - - inp_put_back(); -} - -static void -_ui_draw_win_title(void) -{ - char new_win_title[100]; - - GString *version_str = g_string_new(""); - - if (prefs_get_titlebarversion()) { - g_string_append(version_str, " "); - g_string_append(version_str, PACKAGE_VERSION); - if (strcmp(PACKAGE_STATUS, "development") == 0) { - g_string_append(version_str, "dev"); - } - } - - jabber_conn_status_t status = jabber_get_connection_status(); - - if (status == JABBER_CONNECTED) { - const char * const jid = jabber_get_jid(); - gint unread = _win_get_unread(); - - if (unread != 0) { - snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s (%d) - %s%c", '\033', "Profanity", version_str->str, unread, jid, '\007'); - } else { - snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s - %s%c", '\033', "Profanity", version_str->str, jid, '\007'); - } - } else { - snprintf(new_win_title, sizeof(new_win_title), "%c]0;%s%s%c", '\033', "Profanity", version_str->str, '\007'); - } - - g_string_free(version_str, TRUE); - - if (g_strcmp0(win_title, new_win_title) != 0) { - // print to x-window title bar - printf("%s", new_win_title); - if (win_title != NULL) { - free(win_title); - } - win_title = strdup(new_win_title); - } -} - -unsigned long -ui_get_idle_time(void) -{ -// if compiled with libxss, get the x sessions idle time -#ifdef HAVE_LIBXSS - XScreenSaverInfo *info = XScreenSaverAllocInfo(); - if (info != NULL && display != NULL) { - XScreenSaverQueryInfo(display, DefaultRootWindow(display), info); - unsigned long result = info->idle; - XFree(info); - return result; - } -// if no libxss or xss idle time failed, use profanity idle time -#endif - gdouble seconds_elapsed = g_timer_elapsed(ui_idle_time, NULL); - unsigned long ms_elapsed = seconds_elapsed * 1000.0; - return ms_elapsed; -} - -void -ui_reset_idle_time(void) -{ - g_timer_start(ui_idle_time); -} - -void -ui_close(void) -{ -#ifdef HAVE_LIBNOTIFY - if (notify_is_initted()) { - notify_uninit(); - } -#endif - endwin(); -} - -void -ui_resize(const int ch, const char * const input, const int size) -{ - log_info("Resizing UI"); - title_bar_resize(); - status_bar_resize(); - _win_resize_all(); - inp_win_resize(input, size); - dirty = TRUE; -} - -void -ui_load_colours(void) -{ - if (has_colors()) { - use_default_colors(); - start_color(); - theme_init_colours(); - } -} - -gboolean -ui_windows_full(void) -{ - int i; - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] == NULL) { - return FALSE; - } - } - - return TRUE; -} - -void -ui_show_typing(const char * const from) -{ - int win_index = _find_prof_win_index(from); - - if (prefs_get_intype()) { - // no chat window for user - if (win_index == NUM_WINS) { - _cons_show_typing(from); - - // have chat window but not currently in it - } else if (win_index != current_index) { - _cons_show_typing(from); - dirty = TRUE; - - // in chat window with user - } else { - title_bar_set_typing(TRUE); - title_bar_draw(); - - status_bar_active(win_index); - dirty = TRUE; - } - } - - if (prefs_get_notify_typing()) - _notify_typing(from); -} - -void -ui_idle(void) -{ - int i; - - // loop through regular chat windows and update states - for (i = 1; i < NUM_WINS; i++) { - if ((windows[i] != NULL) && (windows[i]->type == WIN_CHAT)) { - char *recipient = windows[i]->from; - chat_session_no_activity(recipient); - - if (chat_session_is_gone(recipient) && - !chat_session_get_sent(recipient)) { - jabber_send_gone(recipient); - } else if (chat_session_is_inactive(recipient) && - !chat_session_get_sent(recipient)) { - jabber_send_inactive(recipient); - } else if (prefs_get_outtype() && - chat_session_is_paused(recipient) && - !chat_session_get_sent(recipient)) { - jabber_send_paused(recipient); - } - } - } -} - -void -ui_show_incoming_msg(const char * const from, const char * const message, - GTimeVal *tv_stamp, gboolean priv) -{ - char *display_from; - win_type_t win_type; - if (priv) { - win_type = WIN_PRIVATE; - display_from = get_nick_from_full_jid(from); - } else { - win_type = WIN_CHAT; - display_from = strdup(from); - } - - int win_index = _find_prof_win_index(from); - if (win_index == NUM_WINS) - win_index = _new_prof_win(from, win_type); - - // no spare windows left - if (win_index == 0) { - if (tv_stamp == NULL) { - _win_show_time(console->win, '-'); - } else { - GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); - gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wattron(console->win, COLOUR_TIME); - wprintw(console->win, "%s - ", date_fmt); - wattroff(console->win, COLOUR_TIME); - g_date_time_unref(time); - g_free(date_fmt); - } - - if (strncmp(message, "/me ", 4) == 0) { - wattron(console->win, COLOUR_THEM); - wprintw(console->win, "*%s ", from); - wprintw(console->win, message + 4); - wprintw(console->win, "\n"); - wattroff(console->win, COLOUR_THEM); - } else { - _win_show_user(console->win, from, 1); - _win_show_message(console->win, message); - } - - cons_bad_show("Windows all used, close a window to respond."); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } - - // window found or created - } else { - WINDOW *win = windows[win_index]->win; - - // currently viewing chat window with sender - if (win_index == current_index) { - if (tv_stamp == NULL) { - _win_show_time(win, '-'); - } else { - GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); - gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wattron(win, COLOUR_TIME); - wprintw(win, "%s - ", date_fmt); - wattroff(win, COLOUR_TIME); - g_date_time_unref(time); - g_free(date_fmt); - } - - if (strncmp(message, "/me ", 4) == 0) { - wattron(win, COLOUR_THEM); - wprintw(win, "*%s ", display_from); - wprintw(win, message + 4); - wprintw(win, "\n"); - wattroff(win, COLOUR_THEM); - } else { - _win_show_user(win, display_from, 1); - _win_show_message(win, message); - } - title_bar_set_typing(FALSE); - title_bar_draw(); - status_bar_active(win_index); - dirty = TRUE; - - // not currently viewing chat window with sender - } else { - status_bar_new(win_index); - _cons_show_incoming_message(from, win_index); - if (prefs_get_flash()) - flash(); - - windows[win_index]->unread++; - if (prefs_get_chlog() && prefs_get_history()) { - _win_show_history(win, win_index, from); - } - - if (tv_stamp == NULL) { - _win_show_time(win, '-'); - } else { - GDateTime *time = g_date_time_new_from_timeval_utc(tv_stamp); - gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wattron(win, COLOUR_TIME); - wprintw(win, "%s - ", date_fmt); - wattroff(win, COLOUR_TIME); - g_date_time_unref(time); - g_free(date_fmt); - } - - if (strncmp(message, "/me ", 4) == 0) { - wattron(win, COLOUR_THEM); - wprintw(win, "*%s ", display_from); - wprintw(win, message + 4); - wprintw(win, "\n"); - wattroff(win, COLOUR_THEM); - } else { - _win_show_user(win, display_from, 1); - _win_show_message(win, message); - } - } - } - - if (prefs_get_beep()) - beep(); - if (prefs_get_notify_message()) - _notify_message(display_from); - - g_free(display_from); -} - -void -ui_contact_online(const char * const from, const char * const show, - const char * const status, GDateTime *last_activity) -{ - _show_status_string(console->win, from, show, status, last_activity, "++", - "online"); - - int win_index = _find_prof_win_index(from); - if (win_index != NUM_WINS) { - WINDOW *win = windows[win_index]->win; - _show_status_string(win, from, show, status, last_activity, "++", - "online"); - } - - if (win_index == current_index) - dirty = TRUE; -} - -void -ui_contact_offline(const char * const from, const char * const show, - const char * const status) -{ - _show_status_string(console->win, from, show, status, NULL, "--", "offline"); - - int win_index = _find_prof_win_index(from); - if (win_index != NUM_WINS) { - WINDOW *win = windows[win_index]->win; - _show_status_string(win, from, show, status, NULL, "--", "offline"); - } - - if (win_index == current_index) - dirty = TRUE; -} - -void -ui_disconnected(void) -{ - int i; - // show message in all active chats - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - WINDOW *win = windows[i]->win; - _win_show_time(win, '-'); - wattron(win, COLOUR_ERROR); - wprintw(win, "%s\n", "Lost connection."); - wattroff(win, COLOUR_ERROR); - - // if current win, set dirty - if (i == current_index) { - dirty = TRUE; - } - } - } -} - -void -ui_handle_special_keys(const wint_t * const ch) -{ - _win_handle_switch(ch); - _win_handle_page(ch); -} - -void -ui_switch_win(const int i) -{ - win_current_page_off(); - if (windows[i] != NULL) { - current_index = i; - current = windows[current_index]; - win_current_page_off(); - - current->unread = 0; - - if (i == 0) { - title_bar_title(); - status_bar_active(0); - } else { - title_bar_set_recipient(current->from); - title_bar_draw();; - status_bar_active(i); - } - } - - dirty = TRUE; -} - -void -win_current_close(void) -{ - window_free(current); - windows[current_index] = NULL; - - // set it as inactive in the status bar - status_bar_inactive(current_index); - - // go back to console window - _set_current(0); - status_bar_active(0); - title_bar_title(); - - dirty = TRUE; -} - -int -win_current_is_console(void) -{ - return (current->type == WIN_CONSOLE); -} - -int -win_current_is_chat(void) -{ - return (current->type == WIN_CHAT); -} - -int -win_current_is_groupchat(void) -{ - return (current->type == WIN_MUC); -} - -int -win_current_is_private(void) -{ - return (current->type == WIN_PRIVATE); -} - -char * -win_current_get_recipient(void) -{ - return strdup(current->from); -} - -void -win_current_show(const char * const msg, ...) -{ - va_list arg; - va_start(arg, msg); - GString *fmt_msg = g_string_new(NULL); - g_string_vprintf(fmt_msg, msg, arg); - _win_show_time(current->win, '-'); - wprintw(current->win, "%s\n", fmt_msg->str); - g_string_free(fmt_msg, TRUE); - va_end(arg); - - dirty = TRUE; -} - -void -win_current_bad_show(const char * const msg) -{ - WINDOW *win = current->win; - _win_show_time(win, '-'); - wattron(win, COLOUR_ERROR); - wprintw(win, "%s\n", msg); - wattroff(win, COLOUR_ERROR); - - dirty = TRUE; -} - -void -win_current_page_off(void) -{ - int rows = getmaxy(stdscr); - ProfWin *window = windows[current_index]; - - window->paged = 0; - - int y = getcury(window->win); - - int size = rows - 3; - - window->y_pos = y - (size - 1); - if (window->y_pos < 0) - window->y_pos = 0; - - dirty = TRUE; -} - -void -win_show_error_msg(const char * const from, const char *err_msg) -{ - int win_index; - WINDOW *win; - - if (from == NULL || err_msg == NULL) - return; - - win_index = _find_prof_win_index(from); - // chat window exists - if (win_index < NUM_WINS) { - win = windows[win_index]->win; - _win_show_time(win, '-'); - _win_show_error_msg(win, err_msg); - if (win_index == current_index) { - dirty = TRUE; - } - } -} - -void -win_show_system_msg(const char * const from, const char *message) -{ - int win_index; - WINDOW *win; - char from_cpy[strlen(from) + 1]; - char *bare_jid; - - if (from == NULL || message == NULL) - return; - - strcpy(from_cpy, from); - bare_jid = strtok(from_cpy, "/"); - - win_index = _find_prof_win_index(bare_jid); - if (win_index == NUM_WINS) { - win_index = _new_prof_win(bare_jid, WIN_CHAT); - status_bar_active(win_index); - dirty = TRUE; - } - win = windows[win_index]->win; - - _win_show_time(win, '-'); - wprintw(win, "*%s %s\n", bare_jid, message); - - // this is the current window - if (win_index == current_index) { - dirty = TRUE; - } -} - -void -win_show_gone(const char * const from) -{ - int win_index; - WINDOW *win; - - if (from == NULL) - return; - - win_index = _find_prof_win_index(from); - // chat window exists - if (win_index < NUM_WINS) { - win = windows[win_index]->win; - _win_show_time(win, '-'); - wattron(win, COLOUR_GONE); - wprintw(win, "*%s ", from); - wprintw(win, "has left the conversation."); - wprintw(win, "\n"); - wattroff(win, COLOUR_GONE); - if (win_index == current_index) { - dirty = TRUE; - } - } -} - -void -win_new_chat_win(const char * const to) -{ - // if the contact is offline, show a message - PContact contact = contact_list_get_contact(to); - int win_index = _find_prof_win_index(to); - WINDOW *win = NULL; - - // create new window - if (win_index == NUM_WINS) { - Jid *jid = jid_create(to); - - if (muc_room_is_active(jid)) { - win_index = _new_prof_win(to, WIN_PRIVATE); - } else { - win_index = _new_prof_win(to, WIN_CHAT); - } - - jid_destroy(jid); - - win = windows[win_index]->win; - - if (prefs_get_chlog() && prefs_get_history()) { - _win_show_history(win, win_index, to); - } - - if (contact != NULL) { - if (strcmp(p_contact_presence(contact), "offline") == 0) { - const char const *show = p_contact_presence(contact); - const char const *status = p_contact_status(contact); - _show_status_string(win, to, show, status, NULL, "--", "offline"); - } - } - - // use existing window - } else { - win = windows[win_index]->win; - } - - ui_switch_win(win_index); -} - -void -win_show_outgoing_msg(const char * const from, const char * const to, - const char * const message) -{ - // if the contact is offline, show a message - PContact contact = contact_list_get_contact(to); - int win_index = _find_prof_win_index(to); - WINDOW *win = NULL; - - // create new window - if (win_index == NUM_WINS) { - Jid *jid = jid_create(to); - - if (muc_room_is_active(jid)) { - win_index = _new_prof_win(to, WIN_PRIVATE); - } else { - win_index = _new_prof_win(to, WIN_CHAT); - } - - jid_destroy(jid); - - win = windows[win_index]->win; - - if (prefs_get_chlog() && prefs_get_history()) { - _win_show_history(win, win_index, to); - } - - if (contact != NULL) { - if (strcmp(p_contact_presence(contact), "offline") == 0) { - const char const *show = p_contact_presence(contact); - const char const *status = p_contact_status(contact); - _show_status_string(win, to, show, status, NULL, "--", "offline"); - } - } - - // use existing window - } else { - win = windows[win_index]->win; - } - - _win_show_time(win, '-'); - if (strncmp(message, "/me ", 4) == 0) { - wattron(win, COLOUR_ME); - wprintw(win, "*%s ", from); - wprintw(win, message + 4); - wprintw(win, "\n"); - wattroff(win, COLOUR_ME); - } else { - _win_show_user(win, from, 0); - _win_show_message(win, message); - } - ui_switch_win(win_index); -} - -void -win_join_chat(Jid *jid) -{ - int win_index = _find_prof_win_index(jid->barejid); - - // create new window - if (win_index == NUM_WINS) { - win_index = _new_prof_win(jid->barejid, WIN_MUC); - } - - ui_switch_win(win_index); -} - -void -win_show_room_roster(const char * const room, GList *roster, const char * const presence) -{ - int win_index = _find_prof_win_index(room); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - if ((roster == NULL) || (g_list_length(roster) == 0)) { - wattron(win, COLOUR_ROOMINFO); - if (presence == NULL) { - wprintw(win, "Room is empty.\n"); - } else { - wprintw(win, "No participants are %s.\n", presence); - } - wattroff(win, COLOUR_ROOMINFO); - } else { - wattron(win, COLOUR_ROOMINFO); - if (presence == NULL) { - wprintw(win, "Participants: "); - } else { - wprintw(win, "Participants (%s): ", presence); - } - wattroff(win, COLOUR_ROOMINFO); - wattron(win, COLOUR_ONLINE); - - while (roster != NULL) { - PContact member = roster->data; - const char const *name = p_contact_jid(member); - const char const *show = p_contact_presence(member); - - _presence_colour_on(win, show); - wprintw(win, "%s", name); - _presence_colour_off(win, show); - - if (roster->next != NULL) { - wprintw(win, ", "); - } - - roster = g_list_next(roster); - } - - wprintw(win, "\n"); - wattroff(win, COLOUR_ONLINE); - } - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_room_member_offline(const char * const room, const char * const nick) -{ - int win_index = _find_prof_win_index(room); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_OFFLINE); - wprintw(win, "<- %s has left the room.\n", nick); - wattroff(win, COLOUR_OFFLINE); - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_room_member_online(const char * const room, const char * const nick, - const char * const show, const char * const status) -{ - int win_index = _find_prof_win_index(room); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_ONLINE); - wprintw(win, "-> %s has joined the room.\n", nick); - wattroff(win, COLOUR_ONLINE); - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_room_member_presence(const char * const room, const char * const nick, - const char * const show, const char * const status) -{ - int win_index = _find_prof_win_index(room); - if (win_index != NUM_WINS) { - WINDOW *win = windows[win_index]->win; - _show_status_string(win, nick, show, status, NULL, "++", "online"); - } - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_room_member_nick_change(const char * const room, - const char * const old_nick, const char * const nick) -{ - int win_index = _find_prof_win_index(room); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_THEM); - wprintw(win, "** %s is now known as %s\n", old_nick, nick); - wattroff(win, COLOUR_THEM); - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_room_nick_change(const char * const room, const char * const nick) -{ - int win_index = _find_prof_win_index(room); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_ME); - wprintw(win, "** You are now known as %s\n", nick); - wattroff(win, COLOUR_ME); - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_room_history(const char * const room_jid, const char * const nick, - GTimeVal tv_stamp, const char * const message) -{ - int win_index = _find_prof_win_index(room_jid); - WINDOW *win = windows[win_index]->win; - - GDateTime *time = g_date_time_new_from_timeval_utc(&tv_stamp); - gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wprintw(win, "%s - ", date_fmt); - g_date_time_unref(time); - g_free(date_fmt); - - if (strncmp(message, "/me ", 4) == 0) { - wprintw(win, "*%s ", nick); - wprintw(win, message + 4); - wprintw(win, "\n"); - } else { - wprintw(win, "%s: ", nick); - _win_show_message(win, message); - } - - if (win_index == current_index) - dirty = TRUE; -} - -void -win_show_room_message(const char * const room_jid, const char * const nick, - const char * const message) -{ - int win_index = _find_prof_win_index(room_jid); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '-'); - if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { - if (strncmp(message, "/me ", 4) == 0) { - wattron(win, COLOUR_THEM); - wprintw(win, "*%s ", nick); - wprintw(win, message + 4); - wprintw(win, "\n"); - wattroff(win, COLOUR_THEM); - } else { - _win_show_user(win, nick, 1); - _win_show_message(win, message); - } - - } else { - if (strncmp(message, "/me ", 4) == 0) { - wattron(win, COLOUR_ME); - wprintw(win, "*%s ", nick); - wprintw(win, message + 4); - wprintw(win, "\n"); - wattroff(win, COLOUR_ME); - } else { - _win_show_user(win, nick, 0); - _win_show_message(win, message); - } - } - - // currently in groupchat window - if (win_index == current_index) { - status_bar_active(win_index); - dirty = TRUE; - - // not currenlty on groupchat window - } else { - status_bar_new(win_index); - _cons_show_incoming_message(nick, win_index); - if (current_index == 0) { - dirty = TRUE; - } - - if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { - if (prefs_get_flash()) { - flash(); - } - } - - windows[win_index]->unread++; - } - - if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { - if (prefs_get_beep()) { - beep(); - } - if (prefs_get_notify_message()) { - _notify_message(nick); - } - } -} - -void -win_show_room_subject(const char * const room_jid, const char * const subject) -{ - int win_index = _find_prof_win_index(room_jid); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_ROOMINFO); - wprintw(win, "Room subject: "); - wattroff(win, COLOUR_ROOMINFO); - wprintw(win, "%s\n", subject); - - // currently in groupchat window - if (win_index == current_index) { - status_bar_active(win_index); - dirty = TRUE; - - // not currenlty on groupchat window - } else { - status_bar_new(win_index); - } -} - -void -win_show_room_broadcast(const char * const room_jid, const char * const message) -{ - int win_index = _find_prof_win_index(room_jid); - WINDOW *win = windows[win_index]->win; - - _win_show_time(win, '!'); - wattron(win, COLOUR_ROOMINFO); - wprintw(win, "Room message: "); - wattroff(win, COLOUR_ROOMINFO); - wprintw(win, "%s\n", message); - - // currently in groupchat window - if (win_index == current_index) { - status_bar_active(win_index); - dirty = TRUE; - - // not currenlty on groupchat window - } else { - status_bar_new(win_index); - } -} - -void -cons_show_wins(void) -{ - int i = 0; - int count = 0; - - cons_show(""); - cons_show("Active windows:"); - _win_show_time(console->win, '-'); - wprintw(console->win, "1: Console\n"); - - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - count++; - } - } - - if (count != 0) { - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - ProfWin *window = windows[i]; - _win_show_time(console->win, '-'); - - switch (window->type) - { - case WIN_CHAT: - wprintw(console->win, "%d: chat %s", i + 1, window->from); - PContact contact = contact_list_get_contact(window->from); - - if (contact != NULL) { - if (p_contact_name(contact) != NULL) { - wprintw(console->win, " (%s)", p_contact_name(contact)); - } - wprintw(console->win, " - %s", p_contact_presence(contact)); - } - - if (window->unread > 0) { - wprintw(console->win, ", %d unread", window->unread); - } - - break; - - case WIN_PRIVATE: - wprintw(console->win, "%d: private %s", i + 1, window->from); - - if (window->unread > 0) { - wprintw(console->win, ", %d unread", window->unread); - } - - break; - - case WIN_MUC: - wprintw(console->win, "%d: room %s", i + 1, window->from); - - if (window->unread > 0) { - wprintw(console->win, ", %d unread", window->unread); - } - - break; - - default: - break; - } - - wprintw(console->win, "\n"); - } - } - } - - cons_show(""); -} - -void -cons_show_info(PContact pcontact) -{ - _win_show_info(console->win, pcontact); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_show_status(const char * const contact) -{ - PContact pcontact = contact_list_get_contact(contact); - - if (pcontact != NULL) { - _win_show_contact(console, pcontact); - } else { - cons_show("No such contact \"%s\" in roster.", contact); - } -} - -void -win_show_status(void) -{ - char *recipient = win_current_get_recipient(); - PContact pcontact = contact_list_get_contact(recipient); - - if (pcontact != NULL) { - _win_show_contact(current, pcontact); - } else { - win_current_show("Error getting contact info."); - } -} - -void -win_private_show_status(void) -{ - Jid *jid = jid_create(win_current_get_recipient()); - - PContact pcontact = muc_get_participant(jid->barejid, jid->resourcepart); - - if (pcontact != NULL) { - _win_show_contact(current, pcontact); - } else { - win_current_show("Error getting contact info."); - } - - jid_destroy(jid); -} - -void -win_room_show_status(const char * const contact) -{ - PContact pcontact = muc_get_participant(win_current_get_recipient(), contact); - - if (pcontact != NULL) { - _win_show_contact(current, pcontact); - } else { - win_current_show("No such participant \"%s\" in room.", contact); - } -} - -void -cons_show_account(ProfAccount *account) -{ - cons_show("%s account details:", account->name); - if (account->enabled) { - cons_show("enabled : TRUE"); - } else { - cons_show("enabled : FALSE"); - } - cons_show("jid : %s", account->jid); - if (account->resource != NULL) { - cons_show("resource : %s", account->resource); - } - if (account->server != NULL) { - cons_show("server : %s", account->server); - } - cons_show(""); -} - -void -cons_show_ui_prefs(void) -{ - cons_show("UI preferences:"); - cons_show(""); - - gchar *theme = prefs_get_theme(); - if (theme == NULL) { - cons_show("Theme (/theme) : default"); - } else { - cons_show("Theme (/theme) : %s", theme); - } - - if (prefs_get_beep()) - cons_show("Terminal beep (/beep) : ON"); - else - cons_show("Terminal beep (/beep) : OFF"); - - if (prefs_get_flash()) - cons_show("Terminal flash (/flash) : ON"); - else - cons_show("Terminal flash (/flash) : OFF"); - - if (prefs_get_intype()) - cons_show("Show typing (/intype) : ON"); - else - cons_show("Show typing (/intype) : OFF"); - - if (prefs_get_splash()) - cons_show("Splash screen (/splash) : ON"); - else - cons_show("Splash screen (/splash) : OFF"); - - if (prefs_get_history()) - cons_show("Chat history (/history) : ON"); - else - cons_show("Chat history (/history) : OFF"); - - if (prefs_get_vercheck()) - cons_show("Version checking (/vercheck) : ON"); - else - cons_show("Version checking (/vercheck) : OFF"); - - if (prefs_get_mouse()) - cons_show("Mouse handling (/mouse) : ON"); - else - cons_show("Mouse handling (/mouse) : OFF"); - - if (prefs_get_statuses()) - cons_show("Status (/statuses) : ON"); - else - cons_show("Status (/statuses) : OFF"); -} - -void -cons_show_desktop_prefs(void) -{ - cons_show("Desktop notification preferences:"); - cons_show(""); - - if (prefs_get_notify_message()) - cons_show("Messages (/notify message) : ON"); - else - cons_show("Messages (/notify message) : OFF"); - - if (prefs_get_notify_typing()) - cons_show("Composing (/notify typing) : ON"); - else - cons_show("Composing (/notify typing) : OFF"); - - gint remind_period = prefs_get_notify_remind(); - if (remind_period == 0) { - cons_show("Reminder period (/notify remind) : OFF"); - } else if (remind_period == 1) { - cons_show("Reminder period (/notify remind) : 1 second"); - } else { - cons_show("Reminder period (/notify remind) : %d seconds", remind_period); - } -} - -void -cons_show_chat_prefs(void) -{ - cons_show("Chat preferences:"); - cons_show(""); - - if (prefs_get_states()) - cons_show("Send chat states (/states) : ON"); - else - cons_show("Send chat states (/states) : OFF"); - - if (prefs_get_outtype()) - cons_show("Send composing (/outtype) : ON"); - else - cons_show("Send composing (/outtype) : OFF"); - - gint gone_time = prefs_get_gone(); - if (gone_time == 0) { - cons_show("Leave conversation (/gone) : OFF"); - } else if (gone_time == 1) { - cons_show("Leave conversation (/gone) : 1 minute"); - } else { - cons_show("Leave conversation (/gone) : %d minutes", gone_time); - } -} - -void -cons_show_log_prefs(void) -{ - cons_show("Logging preferences:"); - cons_show(""); - - cons_show("Max log size (/log maxsize) : %d bytes", prefs_get_max_log_size()); - - if (prefs_get_chlog()) - cons_show("Chat logging (/chlog) : ON"); - else - cons_show("Chat logging (/chlog) : OFF"); -} - -void -cons_show_presence_prefs(void) -{ - cons_show("Presence preferences:"); - cons_show(""); - - cons_show("Priority (/priority) : %d", prefs_get_priority()); - - if (strcmp(prefs_get_autoaway_mode(), "off") == 0) { - cons_show("Autoaway (/autoaway mode) : OFF"); - } else { - cons_show("Autoaway (/autoaway mode) : %s", prefs_get_autoaway_mode()); - } - - cons_show("Autoaway minutes (/autoaway time) : %d minutes", prefs_get_autoaway_time()); - - if ((prefs_get_autoaway_message() == NULL) || - (strcmp(prefs_get_autoaway_message(), "") == 0)) { - cons_show("Autoaway message (/autoaway message) : OFF"); - } else { - cons_show("Autoaway message (/autoaway message) : \"%s\"", prefs_get_autoaway_message()); - } - - if (prefs_get_autoaway_check()) { - cons_show("Autoaway check (/autoaway check) : ON"); - } else { - cons_show("Autoaway check (/autoaway check) : OFF"); - } -} - -void -cons_show_connection_prefs(void) -{ - cons_show("Connection preferences:"); - cons_show(""); - - gint reconnect_interval = prefs_get_reconnect(); - if (reconnect_interval == 0) { - cons_show("Reconnect interval (/reconnect) : OFF"); - } else if (reconnect_interval == 1) { - cons_show("Reconnect interval (/reconnect) : 1 second"); - } else { - cons_show("Reconnect interval (/reconnect) : %d seconds", reconnect_interval); - } - - gint autoping_interval = prefs_get_autoping(); - if (autoping_interval == 0) { - cons_show("Autoping interval (/autoping) : OFF"); - } else if (autoping_interval == 1) { - cons_show("Autoping interval (/autoping) : 1 second"); - } else { - cons_show("Autoping interval (/autoping) : %d seconds", autoping_interval); - } -} - -void -cons_show_themes(GSList *themes) -{ - cons_show(""); - - if (themes == NULL) { - cons_show("No available themes."); - } else { - cons_show("Available themes:"); - while (themes != NULL) { - cons_show(themes->data); - themes = g_slist_next(themes); - } - } -} - -void -cons_prefs(void) -{ - cons_show(""); - cons_show_ui_prefs(); - cons_show(""); - cons_show_desktop_prefs(); - cons_show(""); - cons_show_chat_prefs(); - cons_show(""); - cons_show_log_prefs(); - cons_show(""); - cons_show_presence_prefs(); - cons_show(""); - cons_show_connection_prefs(); - cons_show(""); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -static void -_cons_show_basic_help(void) -{ - cons_show(""); - - GSList *basic_helpers = cmd_get_basic_help(); - while (basic_helpers != NULL) { - struct cmd_help_t *help = (struct cmd_help_t *)basic_helpers->data; - cons_show("%-30s: %s", help->usage, help->short_help); - basic_helpers = g_slist_next(basic_helpers); - } - - cons_show(""); -} - -void -cons_help(void) -{ - cons_show(""); - cons_show("Choose a help option:"); - cons_show(""); - cons_show("/help list - List all commands."); - cons_show("/help basic - Summary of basic usage commands."); - cons_show("/help presence - Summary of online status change commands."); - cons_show("/help settings - Summary of commands for changing Profanity settings."); - cons_show("/help navigation - How to navigate around Profanity."); - cons_show("/help [command] - Detailed help on a specific command."); - cons_show(""); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_basic_help(void) -{ - cons_show(""); - cons_show("Basic Commands:"); - _cons_show_basic_help(); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_settings_help(void) -{ - cons_show(""); - cons_show("Settings:"); - cons_show(""); - - GSList *settings_helpers = cmd_get_settings_help(); - while (settings_helpers != NULL) { - struct cmd_help_t *help = (struct cmd_help_t *)settings_helpers->data; - cons_show("%-27s: %s", help->usage, help->short_help); - settings_helpers = g_slist_next(settings_helpers); - } - - cons_show(""); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_presence_help(void) -{ - cons_show(""); - cons_show("Presence changes:"); - cons_show(""); - - GSList *presence_helpers = cmd_get_presence_help(); - while (presence_helpers != NULL) { - struct cmd_help_t *help = (struct cmd_help_t *)presence_helpers->data; - cons_show("%-25s: %s", help->usage, help->short_help); - presence_helpers = g_slist_next(presence_helpers); - } - - cons_show(""); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_navigation_help(void) -{ - cons_show(""); - cons_show("Navigation:"); - cons_show(""); - cons_show("Alt-1 : This console window."); - cons_show("Alt-2..Alt-0 : Chat windows."); - cons_show("F1 : This console window."); - cons_show("F2..F10 : Chat windows."); - cons_show("UP, DOWN : Navigate input history."); - cons_show("LEFT, RIGHT, HOME, END : Edit current input."); - cons_show("ESC : Clear current input."); - cons_show("TAB : Autocomplete command/recipient/login."); - cons_show("PAGE UP, PAGE DOWN : Page the main window."); - cons_show("Mouse wheel : Scroll the main window."); - cons_show(""); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_show_contacts(GSList *list) -{ - GSList *curr = list; - - while(curr) { - PContact contact = curr->data; - if (strcmp(p_contact_subscription(contact), "none") != 0) { - _win_show_contact(console, contact); - } - curr = g_slist_next(curr); - } -} - -void -cons_bad_show(const char * const msg, ...) -{ - va_list arg; - va_start(arg, msg); - GString *fmt_msg = g_string_new(NULL); - g_string_vprintf(fmt_msg, msg, arg); - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_ERROR); - wprintw(console->win, "%s\n", fmt_msg->str); - wattroff(console->win, COLOUR_ERROR); - g_string_free(fmt_msg, TRUE); - va_end(arg); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_show_time(void) -{ - _win_show_time(console->win, '-'); -} - -void -cons_show(const char * const msg, ...) -{ - va_list arg; - va_start(arg, msg); - GString *fmt_msg = g_string_new(NULL); - g_string_vprintf(fmt_msg, msg, arg); - _win_show_time(console->win, '-'); - wprintw(console->win, "%s\n", fmt_msg->str); - g_string_free(fmt_msg, TRUE); - va_end(arg); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_show_word(const char * const word) -{ - wprintw(console->win, "%s", word); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_bad_command(const char * const cmd) -{ - _win_show_time(console->win, '-'); - wprintw(console->win, "Unknown command: %s\n", cmd); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_about(void) -{ - int rows, cols; - getmaxyx(stdscr, rows, cols); - - if (prefs_get_splash()) { - _cons_splash_logo(); - } else { - _win_show_time(console->win, '-'); - - if (strcmp(PACKAGE_STATUS, "development") == 0) { - wprintw(console->win, "Welcome to Profanity, version %sdev\n", PACKAGE_VERSION); - } else { - wprintw(console->win, "Welcome to Profanity, version %s\n", PACKAGE_VERSION); - } - } - - _win_show_time(console->win, '-'); - wprintw(console->win, "Copyright (C) 2012, 2013 James Booth <%s>.\n", PACKAGE_BUGREPORT); - _win_show_time(console->win, '-'); - wprintw(console->win, "License GPLv3+: GNU GPL version 3 or later \n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "\n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "This is free software; you are free to change and redistribute it.\n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "There is NO WARRANTY, to the extent permitted by law.\n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "\n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "Type '/help' to show complete help.\n"); - _win_show_time(console->win, '-'); - wprintw(console->win, "\n"); - - if (prefs_get_vercheck()) { - cons_check_version(FALSE); - } - - prefresh(console->win, 0, 0, 1, 0, rows-3, cols-1); - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } -} - -void -cons_check_version(gboolean not_available_msg) -{ - char *latest_release = release_get_latest(); - - if (latest_release != NULL) { - gboolean relase_valid = g_regex_match_simple("^\\d+\\.\\d+\\.\\d+$", latest_release, 0, 0); - - if (relase_valid) { - if (_new_release(latest_release)) { - _win_show_time(console->win, '-'); - wprintw(console->win, "A new version of Profanity is available: %s", latest_release); - _win_show_time(console->win, '-'); - wprintw(console->win, "Check for details.\n"); - free(latest_release); - _win_show_time(console->win, '-'); - wprintw(console->win, "\n"); - } else { - if (not_available_msg) { - cons_show("No new version available."); - cons_show(""); - } - } - - if (current_index == 0) { - dirty = TRUE; - } else { - status_bar_new(0); - } - } - } -} - -void -notify_remind(void) -{ - gint unread = _win_get_unread(); - if (unread > 0) { - _notify_remind(unread); - } -} - -static void -_notify(const char * const message, int timeout, - const char * const category) -{ -#ifdef HAVE_LIBNOTIFY - gboolean notify_initted = notify_is_initted(); - - if (!notify_initted) { - notify_initted = notify_init("Profanity"); - } - - if (notify_initted) { - NotifyNotification *notification; - notification = notify_notification_new("Profanity", message, NULL); - notify_notification_set_timeout(notification, timeout); - notify_notification_set_category(notification, category); - notify_notification_set_urgency(notification, NOTIFY_URGENCY_NORMAL); - - GError *error = NULL; - gboolean notify_success = notify_notification_show(notification, &error); - - if (!notify_success) { - log_error("Error sending desktop notification:"); - log_error(" -> Message : %s", message); - log_error(" -> Error : %s", error->message); - } - } else { - log_error("Libnotify initialisation error."); - } -#endif -#ifdef PLATFORM_CYGWIN - NOTIFYICONDATA nid; - nid.cbSize = sizeof(NOTIFYICONDATA); - //nid.hWnd = hWnd; - nid.uID = 100; - nid.uVersion = NOTIFYICON_VERSION; - //nid.uCallbackMessage = WM_MYMESSAGE; - nid.hIcon = LoadIcon(NULL, IDI_APPLICATION); - strcpy(nid.szTip, "Tray Icon"); - nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; - Shell_NotifyIcon(NIM_ADD, &nid); - - // For a Ballon Tip - nid.uFlags = NIF_INFO; - strcpy(nid.szInfoTitle, "Profanity"); // Title - strcpy(nid.szInfo, message); // Copy Tip - nid.uTimeout = timeout; // 3 Seconds - nid.dwInfoFlags = NIIF_INFO; - - Shell_NotifyIcon(NIM_MODIFY, &nid); -#endif -} - -static void -_notify_remind(gint unread) -{ - char message[20]; - if (unread == 1) { - sprintf(message, "1 unread message"); - } else { - snprintf(message, sizeof(message), "%d unread messages", unread); - } - - _notify(message, 5000, "Incoming message"); -} - -static void -_notify_message(const char * const short_from) -{ - char message[strlen(short_from) + 1 + 10]; - sprintf(message, "%s: message.", short_from); - - _notify(message, 10000, "Incoming message"); -} - -static void -_notify_typing(const char * const from) -{ - char message[strlen(from) + 1 + 11]; - sprintf(message, "%s: typing...", from); - - _notify(message, 10000, "Incoming message"); -} - -static void -_create_windows(void) -{ - int cols = getmaxx(stdscr); - max_cols = cols; - windows[0] = window_create(CONS_WIN_TITLE, cols, WIN_CONSOLE); - console = windows[0]; - current = console; - cons_about(); -} - -static gboolean -_new_release(char *found_version) -{ - int curr_maj, curr_min, curr_patch, found_maj, found_min, found_patch; - - int parse_curr = sscanf(PACKAGE_VERSION, "%d.%d.%d", &curr_maj, &curr_min, - &curr_patch); - int parse_found = sscanf(found_version, "%d.%d.%d", &found_maj, &found_min, - &found_patch); - - if (parse_found == 3 && parse_curr == 3) { - if (found_maj > curr_maj) { - return TRUE; - } else if (found_maj == curr_maj && found_min > curr_min) { - return TRUE; - } else if (found_maj == curr_maj && found_min == curr_min - && found_patch > curr_patch) { - return TRUE; - } else { - return FALSE; - } - } else { - return FALSE; - } -} - -static void -_cons_splash_logo(void) -{ - _win_show_time(console->win, '-'); - wprintw(console->win, "Welcome to\n"); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, " ___ _ \n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, " / __) (_)_ \n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, " ____ ____ ___ | |__ ____ ____ _| |_ _ _ \n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, "| _ \\ / ___) _ \\| __) _ | _ \\| | _) | | |\n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, "| | | | | | |_| | | ( ( | | | | | | |_| |_| |\n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, "| ||_/|_| \\___/|_| \\_||_|_| |_|_|\\___)__ |\n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_SPLASH); - wprintw(console->win, "|_| (____/ \n"); - wattroff(console->win, COLOUR_SPLASH); - - _win_show_time(console->win, '-'); - wprintw(console->win, "\n"); - _win_show_time(console->win, '-'); - if (strcmp(PACKAGE_STATUS, "development") == 0) { - wprintw(console->win, "Version %sdev\n", PACKAGE_VERSION); - } else { - wprintw(console->win, "Version %s\n", PACKAGE_VERSION); - } -} - -static int -_find_prof_win_index(const char * const contact) -{ - int i; - for (i = 1; i < NUM_WINS; i++) { - if ((windows[i] != NULL) && (strcmp(windows[i]->from, contact) == 0)) { - break; - } - } - - return i; -} - -static int -_new_prof_win(const char * const contact, win_type_t type) -{ - int i; - for (i = 1; i < NUM_WINS; i++) { - if (windows[i] == NULL) { - break; - } - } - - if (i != NUM_WINS) { - int cols = getmaxx(stdscr); - windows[i] = window_create(contact, cols, type); - return i; - } else { - return 0; - } -} - -static void -_win_show_time(WINDOW *win, char showchar) -{ - GDateTime *time = g_date_time_new_now_local(); - gchar *date_fmt = g_date_time_format(time, "%H:%M:%S"); - wattron(win, COLOUR_TIME); - wprintw(win, "%s %c ", date_fmt, showchar); - wattroff(win, COLOUR_TIME); - g_date_time_unref(time); - g_free(date_fmt); -} - -static void -_win_show_user(WINDOW *win, const char * const user, const int colour) -{ - if (colour) - wattron(win, COLOUR_THEM); - else - wattron(win, COLOUR_ME); - wprintw(win, "%s: ", user); - if (colour) - wattroff(win, COLOUR_THEM); - else - wattroff(win, COLOUR_ME); -} - -static void -_win_show_message(WINDOW *win, const char * const message) -{ - wprintw(win, "%s\n", message); -} - -static void -_win_show_error_msg(WINDOW *win, const char * const message) -{ - wattron(win, COLOUR_ERROR); - wprintw(win, "%s\n", message); - wattroff(win, COLOUR_ERROR); -} - -static void -_current_window_refresh(void) -{ - int rows, cols; - getmaxyx(stdscr, rows, cols); - - prefresh(current->win, current->y_pos, 0, 1, 0, rows-3, cols-1); -} - -void -_win_resize_all(void) -{ - int rows, cols; - getmaxyx(stdscr, rows, cols); - - // only make the pads bigger, to avoid data loss on cropping - if (cols > max_cols) { - max_cols = cols; - - int i; - for (i = 0; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - wresize(windows[i]->win, PAD_SIZE, cols); - } - } - } - - prefresh(current->win, current->y_pos, 0, 1, 0, rows-3, cols-1); -} - -static void -_presence_colour_on(WINDOW *win, const char * const presence) -{ - if (g_strcmp0(presence, "online") == 0) { - wattron(win, COLOUR_ONLINE); - } else if (g_strcmp0(presence, "away") == 0) { - wattron(win, COLOUR_AWAY); - } else if (g_strcmp0(presence, "chat") == 0) { - wattron(win, COLOUR_CHAT); - } else if (g_strcmp0(presence, "dnd") == 0) { - wattron(win, COLOUR_DND); - } else if (g_strcmp0(presence, "xa") == 0) { - wattron(win, COLOUR_XA); - } else { - wattron(win, COLOUR_OFFLINE); - } -} - -static void -_presence_colour_off(WINDOW *win, const char * const presence) -{ - if (g_strcmp0(presence, "online") == 0) { - wattroff(win, COLOUR_ONLINE); - } else if (g_strcmp0(presence, "away") == 0) { - wattroff(win, COLOUR_AWAY); - } else if (g_strcmp0(presence, "chat") == 0) { - wattroff(win, COLOUR_CHAT); - } else if (g_strcmp0(presence, "dnd") == 0) { - wattroff(win, COLOUR_DND); - } else if (g_strcmp0(presence, "xa") == 0) { - wattroff(win, COLOUR_XA); - } else { - wattroff(win, COLOUR_OFFLINE); - } -} - -static void -_show_status_string(WINDOW *win, const char * const from, - const char * const show, const char * const status, - GDateTime *last_activity, const char * const pre, - const char * const default_show) -{ - if (!prefs_get_statuses()) - return; - - _win_show_time(win, '-'); - - if (show != NULL) { - if (strcmp(show, "away") == 0) { - wattron(win, COLOUR_AWAY); - } else if (strcmp(show, "chat") == 0) { - wattron(win, COLOUR_CHAT); - } else if (strcmp(show, "dnd") == 0) { - wattron(win, COLOUR_DND); - } else if (strcmp(show, "xa") == 0) { - wattron(win, COLOUR_XA); - } else if (strcmp(show, "online") == 0) { - wattron(win, COLOUR_ONLINE); - } else { - wattron(win, COLOUR_OFFLINE); - } - } else if (strcmp(default_show, "online") == 0) { - wattron(win, COLOUR_ONLINE); - } else { - wattron(win, COLOUR_OFFLINE); - } - - wprintw(win, "%s %s", pre, from); - - if (show != NULL) - wprintw(win, " is %s", show); - else - wprintw(win, " is %s", default_show); - - if (last_activity != NULL) { - GDateTime *now = g_date_time_new_now_local(); - GTimeSpan span = g_date_time_difference(now, last_activity); - - wprintw(win, ", idle "); - - int hours = span / G_TIME_SPAN_HOUR; - span = span - hours * G_TIME_SPAN_HOUR; - if (hours > 0) { - wprintw(win, "%dh", hours); - } - - int minutes = span / G_TIME_SPAN_MINUTE; - span = span - minutes * G_TIME_SPAN_MINUTE; - wprintw(win, "%dm", minutes); - - int seconds = span / G_TIME_SPAN_SECOND; - wprintw(win, "%ds", seconds); - } - - if (status != NULL) - wprintw(win, ", \"%s\"", status); - - wprintw(win, "\n"); - - if (show != NULL) { - if (strcmp(show, "away") == 0) { - wattroff(win, COLOUR_AWAY); - } else if (strcmp(show, "chat") == 0) { - wattroff(win, COLOUR_CHAT); - } else if (strcmp(show, "dnd") == 0) { - wattroff(win, COLOUR_DND); - } else if (strcmp(show, "xa") == 0) { - wattroff(win, COLOUR_XA); - } else if (strcmp(show, "online") == 0) { - wattroff(win, COLOUR_ONLINE); - } else { - wattroff(win, COLOUR_OFFLINE); - } - } else if (strcmp(default_show, "online") == 0) { - wattroff(win, COLOUR_ONLINE); - } else { - wattroff(win, COLOUR_OFFLINE); - } -} - -static void -_cons_show_typing(const char * const short_from) -{ - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_TYPING); - wprintw(console->win, "!! %s is typing a message...\n", short_from); - wattroff(console->win, COLOUR_TYPING); -} - -static void -_cons_show_incoming_message(const char * const short_from, const int win_index) -{ - _win_show_time(console->win, '-'); - wattron(console->win, COLOUR_INCOMING); - wprintw(console->win, "<< incoming from %s (%d)\n", short_from, win_index + 1); - wattroff(console->win, COLOUR_INCOMING); -} - -static void -_win_show_contact(ProfWin *window, PContact contact) -{ - const char *jid = p_contact_jid(contact); - const char *name = p_contact_name(contact); - const char *presence = p_contact_presence(contact); - const char *status = p_contact_status(contact); - GDateTime *last_activity = p_contact_last_activity(contact); - - _win_show_time(window->win, '-'); - _presence_colour_on(window->win, presence); - wprintw(window->win, "%s", jid); - - if (name != NULL) { - wprintw(window->win, " (%s)", name); - } - - wprintw(window->win, " is %s", presence); - - if (last_activity != NULL) { - GDateTime *now = g_date_time_new_now_local(); - GTimeSpan span = g_date_time_difference(now, last_activity); - - wprintw(window->win, ", idle "); - - int hours = span / G_TIME_SPAN_HOUR; - span = span - hours * G_TIME_SPAN_HOUR; - if (hours > 0) { - wprintw(window->win, "%dh", hours); - } - - int minutes = span / G_TIME_SPAN_MINUTE; - span = span - minutes * G_TIME_SPAN_MINUTE; - wprintw(window->win, "%dm", minutes); - - int seconds = span / G_TIME_SPAN_SECOND; - wprintw(window->win, "%ds", seconds); - } - - if (status != NULL) { - wprintw(window->win, ", \"%s\"", p_contact_status(contact)); - } - - wprintw(window->win, "\n"); - _presence_colour_off(window->win, presence); -} - -static void -_win_handle_switch(const wint_t * const ch) -{ - if (*ch == KEY_F(1)) { - ui_switch_win(0); - } else if (*ch == KEY_F(2)) { - ui_switch_win(1); - } else if (*ch == KEY_F(3)) { - ui_switch_win(2); - } else if (*ch == KEY_F(4)) { - ui_switch_win(3); - } else if (*ch == KEY_F(5)) { - ui_switch_win(4); - } else if (*ch == KEY_F(6)) { - ui_switch_win(5); - } else if (*ch == KEY_F(7)) { - ui_switch_win(6); - } else if (*ch == KEY_F(8)) { - ui_switch_win(7); - } else if (*ch == KEY_F(9)) { - ui_switch_win(8); - } else if (*ch == KEY_F(10)) { - ui_switch_win(9); - } -} - -static void -_win_handle_page(const wint_t * const ch) -{ - int rows = getmaxy(stdscr); - int y = getcury(current->win); - - int page_space = rows - 4; - int *page_start = &(current->y_pos); - - if (prefs_get_mouse()) { - MEVENT mouse_event; - - if (*ch == KEY_MOUSE) { - if (getmouse(&mouse_event) == OK) { - -#ifdef PLATFORM_CYGWIN - if (mouse_event.bstate & BUTTON5_PRESSED) { // mouse wheel down -#else - if (mouse_event.bstate & BUTTON2_PRESSED) { // mouse wheel down -#endif - *page_start += 4; - - // only got half a screen, show full screen - if ((y - (*page_start)) < page_space) - *page_start = y - page_space; - - // went past end, show full screen - else if (*page_start >= y) - *page_start = y - page_space; - - current->paged = 1; - dirty = TRUE; - } else if (mouse_event.bstate & BUTTON4_PRESSED) { // mouse wheel up - *page_start -= 4; - - // went past beginning, show first page - if (*page_start < 0) - *page_start = 0; - - current->paged = 1; - dirty = TRUE; - } - } - } - } - - // page up - if (*ch == KEY_PPAGE) { - *page_start -= page_space; - - // went past beginning, show first page - if (*page_start < 0) - *page_start = 0; - - current->paged = 1; - dirty = TRUE; - - // page down - } else if (*ch == KEY_NPAGE) { - *page_start += page_space; - - // only got half a screen, show full screen - if ((y - (*page_start)) < page_space) - *page_start = y - page_space; - - // went past end, show full screen - else if (*page_start >= y) - *page_start = y - page_space; - - current->paged = 1; - dirty = TRUE; - } -} - -static gint -_win_get_unread(void) -{ - int i; - gint result = 0; - for (i = 0; i < NUM_WINS; i++) { - if (windows[i] != NULL) { - result += windows[i]->unread; - } - } - return result; -} - -static void -_win_show_history(WINDOW *win, int win_index, const char * const contact) -{ - if (!windows[win_index]->history_shown) { - GSList *history = NULL; - history = chat_log_get_previous(jabber_get_jid(), contact, history); - while (history != NULL) { - wprintw(win, "%s\n", history->data); - history = g_slist_next(history); - } - windows[win_index]->history_shown = 1; - - g_slist_free_full(history, free); - } -} - -static void -_win_show_info(WINDOW *win, PContact pcontact) -{ - const char *jid = p_contact_jid(pcontact); - const char *name = p_contact_name(pcontact); - const char *presence = p_contact_presence(pcontact); - const char *status = p_contact_status(pcontact); - const char *sub = p_contact_subscription(pcontact); - const char *caps_str = p_contact_caps_str(pcontact); - GDateTime *last_activity = p_contact_last_activity(pcontact); - - _win_show_time(win, '-'); - wprintw(win, "\n"); - _win_show_time(win, '-'); - _presence_colour_on(win, presence); - wprintw(win, "%s:\n", jid); - _presence_colour_off(win, presence); - - if (name != NULL) { - _win_show_time(win, '-'); - wprintw(win, "Name : %s\n", name); - } - - if (sub != NULL) { - _win_show_time(win, '-'); - wprintw(win, "Subscription : %s\n", sub); - } - - _win_show_time(win, '-'); - wprintw(win, "Presence : "); - _presence_colour_on(win, presence); - wprintw(win, "%s\n", presence); - _presence_colour_off(win, presence); - - if (status != NULL) { - _win_show_time(win, '-'); - wprintw(win, "Message : %s\n", status); - } - - if (last_activity != NULL) { - GDateTime *now = g_date_time_new_now_local(); - GTimeSpan span = g_date_time_difference(now, last_activity); - - _win_show_time(win, '-'); - wprintw(win, "Last activity : "); - - int hours = span / G_TIME_SPAN_HOUR; - span = span - hours * G_TIME_SPAN_HOUR; - if (hours > 0) { - wprintw(win, "%dh", hours); - } - - int minutes = span / G_TIME_SPAN_MINUTE; - span = span - minutes * G_TIME_SPAN_MINUTE; - wprintw(win, "%dm", minutes); - - int seconds = span / G_TIME_SPAN_SECOND; - wprintw(win, "%ds", seconds); - - wprintw(win, "\n"); - - g_date_time_unref(now); - } - - if (caps_str != NULL) { - Capabilities *caps = caps_get(caps_str); - if ((caps != NULL) && (caps->client != NULL)) { - _win_show_time(win, '-'); - wprintw(win, "Client : %s\n", caps->client); - } - } - -} - -void -_set_current(int index) -{ - current_index = index; - current = windows[current_index]; -} - -- cgit 1.4.1-2-gfad0