diff --git a/.gitignore b/.gitignore
index be11f141..ba909849 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
# *.[oa]
# *~
profanity
+profanity.sh
*.o
*.log
*.swp
@@ -25,7 +26,7 @@ configure.scan
stamp-h1
*~
*dirstamp
-valgrind.out
+valgrind*.out*
core
bugs/
TODO
@@ -64,3 +65,7 @@ profanity.workspace
m4/
test.sh
clean-test.sh
+callgrind.out.*
+gen_docs.sh
+main_fragment.html
+toc_fragment.html
diff --git a/.travis.yml b/.travis.yml
index c87d68b7..e546d8b3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
language: c
install:
- sudo apt-get update
- - sudo apt-get -y install libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr2-dev
+ - sudo apt-get -y install libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr2-dev uuid-dev
- git clone git://github.com/strophe/libstrophe.git
- cd libstrophe
- mkdir m4
@@ -11,15 +11,15 @@ install:
- sudo make install
- cd ..
- rm -rf libstrophe
- - wget https://open.cryptomilk.org/attachments/download/42/cmocka-0.4.1.tar.xz
- - tar -xvf cmocka-0.4.1.tar.xz
- - cd cmocka-0.4.1
+ - wget https://cmocka.org/files/1.0/cmocka-1.0.0.tar.xz
+ - tar -xvf cmocka-1.0.0.tar.xz
+ - cd cmocka-1.0.0
- mkdir build
- cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
- make
- sudo make install
- cd ../..
- - rm -rf cmocka-0.4.1
+ - rm -rf cmocka-1.0.0
- ./bootstrap.sh
script: ./configure && make && make check
diff --git a/CHANGELOG b/CHANGELOG
index 815f6e55..519660db 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,16 +1,26 @@
+0.4.7
+=====
+
+- GNU Readline
+- Message Carbons (xep-0280)
+- Message Delivery Receipts (xep-0184)
+- MUC Mediated Invitation support
+
0.4.6
=====
-- 16 colour support
+- 16 colour support (/theme colours)
- UI preferences included in themes
-- Word wrapping (/wrap)
-- Show hide time (/time)
-- Show or hide and customise roster panel (/roster)
+- /wrap - Word wrapping
+- /time - Show/hide time in main window, and configure precision
+- /roster - Show/hide and customise roster panel
+- /roster and /occupants panel size settings (% of screen width)
+- /account default - Set default account for /connect
- /account remove
-- Added default account for /connect
-- Additional readline style shortcuts
-- Improved chat session handling
-- Override resource during chat and resource display settings (/resource)
-- Disable terminal title by default, additonal title on exit
-- Dynamic input blocking timeout to use less CPU
-- eval_password property on accounts for retrieving password from keyring/keychain
+- /presence - Show/hide contact presence in titlebar
+- /resource - Override resource during chat, resource display settings
+- Improved chat session handling
+- Lower CPU usage with dynamic input blocking timeout
+- Keychain/keyring integration using account eval_password property
+- Disable term window title by default
+- Fixed remote code execution bug on OSX when desktop notifications configured to show message text
diff --git a/LICENSE.txt b/LICENSE.txt
index 609ce80c..e1990985 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,5 +1,5 @@
Profanity
-Copyright (C) 2012 - 2014 James Booth
+Copyright (C) 2012 - 2015 James Booth
Profanity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/Makefile.am b/Makefile.am
index d9fa9729..372b60f3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,7 +13,9 @@ core_sources = \
src/xmpp/roster.c src/xmpp/roster.h \
src/xmpp/bookmark.c src/xmpp/bookmark.h \
src/xmpp/form.c src/xmpp/form.h \
- src/server_events.c src/server_events.h \
+ src/event/server_events.c src/event/server_events.h \
+ src/event/client_events.c src/event/client_events.h \
+ src/event/ui_events.c src/event/ui_events.h \
src/ui/ui.h src/ui/window.c src/ui/window.h src/ui/core.c \
src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \
src/ui/titlebar.h src/ui/statusbar.h src/ui/inputwin.h \
@@ -27,7 +29,6 @@ core_sources = \
src/tools/parser.h \
src/tools/p_sha1.h src/tools/p_sha1.c \
src/tools/autocomplete.c src/tools/autocomplete.h \
- src/tools/history.c src/tools/history.h \
src/tools/tinyurl.c src/tools/tinyurl.h \
src/config/accounts.c src/config/accounts.h \
src/config/account.c src/config/account.h \
@@ -44,13 +45,13 @@ tests_sources = \
src/roster_list.c src/roster_list.h \
src/xmpp/xmpp.h src/xmpp/form.c \
src/ui/ui.h \
+ src/otr/otr.h \
src/command/command.h src/command/command.c \
src/command/commands.h src/command/commands.c \
src/tools/parser.c \
src/tools/parser.h \
src/tools/p_sha1.h src/tools/p_sha1.c \
src/tools/autocomplete.c src/tools/autocomplete.h \
- src/tools/history.c src/tools/history.h \
src/tools/tinyurl.c src/tools/tinyurl.h \
src/config/accounts.h \
src/config/account.c src/config/account.h \
@@ -61,9 +62,10 @@ tests_sources = \
src/ui/buffer.c \
src/ui/titlebar.c src/ui/statusbar.c src/ui/inputwin.c \
src/ui/titlebar.h src/ui/statusbar.h src/ui/inputwin.h \
- src/server_events.c src/server_events.h \
+ src/event/server_events.c src/event/server_events.h \
+ src/event/client_events.c src/event/client_events.h \
+ src/event/ui_events.c src/event/ui_events.h \
tests/xmpp/stub_xmpp.c \
- tests/otr/stub_otr.c \
tests/ui/stub_ui.c \
tests/log/stub_log.c \
tests/config/stub_accounts.c \
@@ -78,12 +80,10 @@ tests_sources = \
tests/test_cmd_roster.c tests/test_cmd_roster.h \
tests/test_cmd_statuses.c tests/test_cmd_statuses.h \
tests/test_cmd_sub.c tests/test_cmd_sub.h \
- tests/test_cmd_win.c tests/test_cmd_win.h \
tests/test_cmd_disconnect.c tests/test_cmd_disconnect.h \
tests/test_common.c tests/test_common.h \
tests/test_contact.c tests/test_contact.h \
tests/test_form.c tests/test_form.h \
- tests/test_history.c tests/test_history.h \
tests/test_jid.c tests/test_jid.h \
tests/test_muc.c tests/test_muc.h \
tests/test_parser.c tests/test_parser.h \
@@ -104,6 +104,9 @@ otr3_sources = \
otr4_sources = \
src/otr/otrlib.h src/otr/otrlibv4.c src/otr/otr.h src/otr/otr.c
+otr_test_sources = \
+ tests/otr/stub_otr.c
+
themes_sources = themes/*
script_sources = bootstrap.sh configure-debug install-all.sh
@@ -111,6 +114,7 @@ script_sources = bootstrap.sh configure-debug install-all.sh
man_sources = docs/profanity.1
if BUILD_OTR
+tests_sources += $(otr_test_sources)
if BUILD_OTR3
core_sources += $(otr3_sources)
endif
diff --git a/configure.ac b/configure.ac
index 7369f112..1e2c6173 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
-AC_INIT([profanity], [0.4.6], [boothj5web@gmail.com])
+AC_INIT([profanity], [0.4.7], [boothj5web@gmail.com])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([src/config.h])
@@ -34,6 +34,8 @@ AC_DEFINE_UNQUOTED([PACKAGE_STATUS], ["$PACKAGE_STATUS"], [Status of this build]
AS_IF([test "x$PLATFORM" = xcygwin],
[AC_DEFINE([PLATFORM_CYGWIN], [1], [Cygwin])])
+AS_IF([test "x$PLATFORM" = xosx],
+ [AC_DEFINE([PLATFORM_OSX], [1], [OSx])])
### Options
AC_ARG_ENABLE([notifications],
@@ -134,10 +136,23 @@ PKG_CHECK_MODULES([glib], [glib-2.0 >= 2.26], [],
PKG_CHECK_MODULES([curl], [libcurl], [],
[AC_MSG_ERROR([libcurl is required for profanity])])
+AS_IF([test "x$PLATFORM" != xosx],
+ [AC_CHECK_LIB([readline], [main], [],
+ [AC_MSG_ERROR([libreadline is required for profanity])])],
+ [AC_CHECK_FILE([/usr/local/opt/readline/lib],
+ [LIBS="-lreadline $LIBS"
+ AM_CPPFLAGS="-I/usr/local/opt/readline/include $AM_CPPFLAGS"
+ AM_LDFLAGS="-L/usr/local/opt/readline/lib $AM_LDFLAGS"
+ AC_SUBST(AM_LDFLAGS)],
+ [AC_MSG_ERROR([libreadline is required for profanity])])])
+
+AC_CHECK_LIB([uuid], [uuid_generate], [],
+ [AC_MSG_ERROR([libuuid is required for profanity])])
+
AS_IF([test "x$PLATFORM" = xosx], [LIBS="-lcurl $LIBS"])
### Check for desktop notification support
-### Linux requires libnotify
+### Linux/FreeBSD require libnotify
### Windows uses native OS calls
### OSX requires terminal-notifier
@@ -150,7 +165,7 @@ AS_IF([test "x$PLATFORM" = xosx],
[AC_MSG_ERROR([terminal-notifier not found, required for desktop notifications.])],
[AC_MSG_NOTICE([Desktop notifications not supported.])])],
[AC_DEFINE([HAVE_OSXNOTIFY], [1], [terminal notifier])])])],
- [test "x$PLATFORM" = xnix],
+ [test "x$PLATFORM" = xnix -o "x$PLATFORM" = xfreebsd],
[AS_IF([test "x$enable_notifications" != xno],
[PKG_CHECK_MODULES([libnotify], [libnotify],
[AC_DEFINE([HAVE_LIBNOTIFY], [1], [libnotify module])],
diff --git a/docs/profanity.1 b/docs/profanity.1
index a65281fb..63cd0677 100644
--- a/docs/profanity.1
+++ b/docs/profanity.1
@@ -1,9 +1,9 @@
-.TH Profanity 1 "March 2014" "Profanity XMPP client"
+.TH Profanity 1 "February 2015" "Profanity XMPP client"
.SH NAME
Profanity \- a simple console based XMPP chat client.
.SH SYNOPSIS
.B profanity
-[\-vhd] [\-l level]
+[\-vhd] [\-l level] [\-a account]
.SH DESCRIPTION
.B Profanity
is a simple lightweight console based XMPP chat client. Its emphasis is
@@ -15,19 +15,21 @@ at:
.SH OPTIONS
.TP
.BI "\-v, \-\-version"
-Show version information.
+Show version and build information.
.TP
.BI "\-h, \-\-help"
Show help on command line arguments.
.TP
-.BI "\-a, \-\-account"
-Auto connect to an account on startup.
+.BI "\-a, \-\-account "ACCOUNT
+Auto connect to an account on startup,
+.I ACCOUNT
+must be an existing account.
.TP
.BI "\-d, \-\-disable\-tls"
Disable TLS for servers that either don't support it, or claim to but do not
complete the handshake.
.TP
-.BI "\-l, \-\-log="LEVEL
+.BI "\-l, \-\-log "LEVEL
Set the logging level,
.I LEVEL
may be set to DEBUG, INFO (the default), WARN or ERROR.
@@ -45,10 +47,10 @@ is stored in
, details on configuring Profanity can be found at .
.PP
.SH BUGS
-Bugs can either be reported by sending a mail directly to:
+Bugs can either be reported by raising an issue at the Github issue tracker:
.br
.PP
-
+
.br
.PP
or to the mailing list at:
@@ -57,12 +59,14 @@ or to the mailing list at:
.br
.PP
-or with a Github account by logging issues on the issue tracker at:
+or by sending a mail directly to:
+.br
+.PP
+
.br
.PP
-
.SH LICENSE
-Copyright (C) 2012 \- 2014 James Booth .
+Copyright (C) 2012 \- 2015 James Booth .
License GPLv3+: GNU GPL version 3 or later
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
diff --git a/install-all.sh b/install-all.sh
index cc32d8fd..4ffc5999 100755
--- a/install-all.sh
+++ b/install-all.sh
@@ -24,7 +24,7 @@ debian_prepare()
echo
echo Profanity installer... installing dependencies
echo
- sudo apt-get -y install git automake autoconf libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr5-dev libtool
+ sudo apt-get -y install git automake autoconf libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr5-dev libreadline-dev libtool uuid-dev
}
@@ -36,7 +36,7 @@ fedora_prepare()
ARCH=`arch`
- sudo yum -y install gcc git autoconf automake openssl-devel.$ARCH expat-devel.$ARCH ncurses-devel.$ARCH glib2-devel.$ARCH libnotify-devel.$ARCH libcurl-devel.$ARCH libXScrnSaver-devel.$ARCH libotr3-devel.$ARCH libtool
+ sudo yum -y install gcc git autoconf automake openssl-devel.$ARCH expat-devel.$ARCH ncurses-devel.$ARCH glib2-devel.$ARCH libnotify-devel.$ARCH libcurl-devel.$ARCH libXScrnSaver-devel.$ARCH libotr3-devel.$ARCH readline-devel.$ARCH libtool uuid-devel.$ARCH
}
opensuse_prepare()
@@ -44,7 +44,7 @@ opensuse_prepare()
echo
echo Profanity installer...installing dependencies
echo
- sudo zypper -n in gcc git automake make autoconf libopenssl-devel expat libexpat-devel ncurses-devel glib2-devel libnotify-devel libcurl-devel libXScrnSaver-devel libotr-devel libtool
+ sudo zypper -n in gcc git automake make autoconf libopenssl-devel expat libexpat-devel ncurses-devel glib2-devel libnotify-devel libcurl-devel libXScrnSaver-devel libotr-devel readline-devel libtool libuuid-devel
}
cygwin_prepare()
@@ -60,9 +60,9 @@ cygwin_prepare()
mv apt-cyg /usr/local/bin/
if [ -n "$CYG_MIRROR" ]; then
- apt-cyg -m $CYG_MIRROR install git make gcc-core m4 automake autoconf pkg-config openssl-devel libexpat-devel zlib-devel libncursesw-devel libglib2.0-devel libcurl-devel libidn-devel libssh2-devel libkrb5-devel openldap-devel libgcrypt-devel libtool
+ apt-cyg -m $CYG_MIRROR install git make gcc-core m4 automake autoconf pkg-config openssl-devel libexpat-devel zlib-devel libncursesw-devel libglib2.0-devel libcurl-devel libidn-devel libssh2-devel libkrb5-devel openldap-devel libgcrypt-devel libreadline-devel libtool libuuid-devel
else
- apt-cyg install git make gcc-core m4 automake autoconf pkg-config openssl-devel libexpat-devel zlib-devel libncursesw-devel libglib2.0-devel libcurl-devel libidn-devel libssh2-devel libkrb5-devel openldap-devel libgcrypt-devel libtool
+ apt-cyg install git make gcc-core m4 automake autoconf pkg-config openssl-devel libexpat-devel zlib-devel libncursesw-devel libglib2.0-devel libcurl-devel libidn-devel libssh2-devel libkrb5-devel openldap-devel libgcrypt-devel libreadline-devel libtool libuuid-devel
fi
}
diff --git a/src/chat_session.c b/src/chat_session.c
index fbe06f76..2758d603 100644
--- a/src/chat_session.c
+++ b/src/chat_session.c
@@ -1,7 +1,7 @@
/*
* chat_session.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -64,7 +64,7 @@ _chat_session_new(const char * const barejid, const char * const resource,
static void
_chat_session_free(ChatSession *session)
{
- if (session != NULL) {
+ if (session) {
free(session->barejid);
free(session->resource);
free(session);
@@ -81,7 +81,7 @@ chat_sessions_init(void)
void
chat_sessions_clear(void)
{
- if (sessions != NULL)
+ if (sessions)
g_hash_table_remove_all(sessions);
}
@@ -141,7 +141,7 @@ chat_session_recipient_active(const char * const barejid, const char * const res
// session exists with resource, update chat_states
if (g_strcmp0(session->resource, resource) == 0) {
session->send_states = send_states;
- // session exists with differet resource and no override, replace
+ // session exists with different resource and no override, replace
} else if (!session->resource_override) {
_chat_session_new(barejid, resource, FALSE, send_states);
}
diff --git a/src/chat_session.h b/src/chat_session.h
index 585a523b..f51a8341 100644
--- a/src/chat_session.h
+++ b/src/chat_session.h
@@ -1,7 +1,7 @@
/*
* chat_session.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/chat_state.c b/src/chat_state.c
index 99a83f43..8ddb6f1e 100644
--- a/src/chat_state.c
+++ b/src/chat_state.c
@@ -1,7 +1,7 @@
/*
* chat_state.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/chat_state.h b/src/chat_state.h
index ba394a56..7f0d8832 100644
--- a/src/chat_state.h
+++ b/src/chat_state.h
@@ -1,7 +1,7 @@
/*
* chat_state.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/command/command.c b/src/command/command.c
index 1441ef46..1871ea6c 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -1,7 +1,7 @@
/*
* command.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -36,6 +36,7 @@
#include
#include
#include
+#include
#include
#include
@@ -70,8 +71,6 @@
typedef char*(*autocompleter)(char*, int*);
static gboolean _cmd_execute(const char * const command, const char * const inp);
-static gboolean _cmd_execute_default(const char * inp);
-static gboolean _cmd_execute_alias(const char * const inp, gboolean *ran);
static char * _cmd_complete_parameters(const char * const input);
@@ -101,6 +100,8 @@ static char * _role_autocomplete(const char * const input);
static char * _resource_autocomplete(const char * const input);
static char * _titlebar_autocomplete(const char * const input);
static char * _inpblock_autocomplete(const char * const input);
+static char * _time_autocomplete(const char * const input);
+static char * _receipts_autocomplete(const char * const input);
GHashTable *commands = NULL;
@@ -111,18 +112,19 @@ static struct cmd_t command_defs[] =
{
{ "/help",
cmd_help, parse_args, 0, 1, NULL,
- { "/help [area|command]", "Get help on using Profanity.",
+ { "/help [area|command]", "Help on using Profanity.",
{ "/help [area|command]",
- "-------------------------",
- "Use with no arguments to get a help summary.",
- "Supply an area to see help for commands related to specific features.",
- "Supply a command (without the leading slash) to see help for that command.",
+ "--------------------",
+ "Help on using Profanity.",
"",
- "Example : /help commands",
- "Example : /help presence",
- "Example : /help who",
+ "area : Summary help for commands in a certain area of functionality.",
+ "command : Full help for a specific command, for example '/help connect'.",
"",
- "For more detailed help, see the user guide at http://www.profanity.im/userguide.html.",
+ "Use with no arguments to see a list of areas.",
+ "",
+ "Example: /help commands",
+ "Example: /help presence",
+ "Example: /help who",
NULL } } },
{ "/about",
@@ -135,15 +137,17 @@ static struct cmd_t command_defs[] =
{ "/connect",
cmd_connect, parse_args, 0, 5, NULL,
- { "/connect [account] [server value] [port value]", "Login to a chat service.",
+ { "/connect [account] [server value] [port value]", "Account login.",
{ "/connect [account] [server value] [port value]",
"----------------------------------------------",
- "Connect to an XMPP service using the specified account.",
- "Use the server property to specify a server if required.",
- "Change the default port (5222, or 5223 for SSL) with the port property.",
- "An account is automatically created if one does not exist.",
- "If no account is specified, then the default account is used."
- "See the /account command for more details.",
+ "Login to a chat service.",
+ "",
+ "account : The local account you wish to connect with, or a JID if connecting for the first time.",
+ "server value : Supply a server if it is different to the domain part of your JID.",
+ "port value : The port to use if different to the default (5222, or 5223 for SSL).",
+ "",
+ "If no account is specified, the default is used if one is configured.",
+ "A local account is created with the JID as it's name if it doesn't already exist.",
"",
"Example: /connect",
"Example: /connect myuser@gmail.com",
@@ -162,48 +166,57 @@ static struct cmd_t command_defs[] =
{ "/msg",
cmd_msg, parse_args_with_freetext, 1, 2, NULL,
- { "/msg contact|nick [message]", "Start chat with user.",
+ { "/msg contact|nick [message]", "Start chat with a user.",
{ "/msg contact|nick [message]",
"---------------------------",
- "Open a chat window for the contact and send the message if one is supplied.",
- "When in a chat room, supply a nickname to start private chat with a room member.",
+ "Send a one to one chat message, or a private message to a chat room occupant.",
+ "",
+ "contact : The contact's JID, or nickname if one has been set in your roster.",
+ "nick : A chat room occupant, to whom you wish to send a private message.",
+ "message : The message to send",
+ "",
+ "If the message is omitted, a new chat window will be opened without sending a message.",
"Use quotes if the nickname includes spaces.",
"",
- "Example : /msg myfriend@server.com Hey, here's a message!",
- "Example : /msg otherfriend@server.com",
- "Example : /msg Bob Here is a private message",
- "Example : /msg \"My Friend\" Hi, how are you?",
+ "Example: /msg myfriend@server.com Hey, here's a message!",
+ "Example: /msg otherfriend@server.com",
+ "Example: /msg Bob Here is a private message",
+ "Example: /msg \"My Friend\" Hi, how are you?",
NULL } } },
{ "/roster",
cmd_roster, parse_args_with_freetext, 0, 3, NULL,
- { "/roster [online|show|hide|by|size|add|remove|nick|clearnick] [offline|resource] [percent] [group|presence|none] [jid] [nickname]", "Manage your roster.",
- { "/roster [online|show|hide|by|size|add|remove|nick|clearnick] [offline|resource] [percent] [group|presence|none] [jid] [nickname]",
- "-------------------------------------------------------------------------------------------------------------------------",
- "View, add to, and remove from your roster.",
- "Passing no arguments lists all contacts in your roster.",
- "online - Show all online contacts in your roster.",
- "show - Show the roster panel in the console window.",
- "hide - Hide the roster panel.",
- "show offline - Show offline contacts in the roster panel.",
- "hide offline - Hide offline contacts in the roster panel.",
- "show resource - Show contact's connected resources in the roster panel.",
- "hide resource - Hide contact's connected resources in the roster panel.",
- "by group - Group contacts in the roster panel by roster group.",
- "by presence - Group contacts in the roster panel by presence.",
- "by none - No grouping in the roster panel.",
- "size - Percentage of the screen taken up by the roster (1-99).",
- "add - Add a new item, jid is required, nickname is optional.",
- "remove - Removes a contact, jid is required.",
- "nick - Changes a contacts nickname, both jid and nickname are required,",
- "clearnick - Removes the current nickname, jid is required.",
+ { "/roster [command] [args..]", "Manage your roster.",
+ { "/roster [command] [args..]",
+ "--------------------------",
+ "Manage your roster, and roster display settings.",
"",
- "Example : /roster (show your roster)",
- "Example : /roster add someone@contacts.org (add the contact)",
- "Example : /roster add someone@contacts.org Buddy (add the contact with nickname 'Buddy')",
- "Example : /roster remove someone@contacts.org (remove the contact)",
- "Example : /roster nick myfriend@chat.org My Friend",
- "Example : /roster clearnick kai@server.com (clears nickname)",
+ "command - online|show|hide|by|size|add|remove|nick|clearnick",
+ "",
+ "online : Show all online contacts in your roster.",
+ "show : Show the roster panel.",
+ "show offline : Show offline contacts in the roster panel.",
+ "show resource : Show contact's connected resources in the roster panel.",
+ "hide : Hide the roster panel.",
+ "hide offline : Hide offline contacts in the roster panel.",
+ "hide resource : Hide contact's connected resources in the roster panel.",
+ "by group : Group contacts in the roster panel by roster group.",
+ "by presence : Group contacts in the roster panel by presence.",
+ "by none : No grouping in the roster panel.",
+ "size : Percentage of the screen taken up by the roster (1-99).",
+ "add jid [nick] : Add a new item to the roster.",
+ "remove jid : Removes an item from the roster.",
+ "nick jid nick : Change a contacts nickname.",
+ "clearnick jid : Removes the current nickname.",
+ "",
+ "Passing no arguments lists all contacts in your roster.",
+ "",
+ "Example: /roster (show your roster)",
+ "Example: /roster add someone@contacts.org (add the contact)",
+ "Example: /roster add someone@contacts.org Buddy (add the contact with nickname 'Buddy')",
+ "Example: /roster remove someone@contacts.org (remove the contact)",
+ "Example: /roster nick myfriend@chat.org My Friend",
+ "Example: /roster clearnick kai@server.com (clears nickname)",
NULL } } },
{ "/group",
@@ -212,31 +225,35 @@ static struct cmd_t command_defs[] =
{ "/group [show|add|remove] [group] [contact]",
"------------------------------------------",
"View, add to, and remove from roster groups.",
- "Passing no argument will list all roster groups.",
- "The 'show' command takes 'group' as an argument, and lists all roster items in that group.",
- "The 'add' command takes 'group' and 'contact' arguments, and adds the contact to the group.",
- "The 'remove' command takes 'group' and 'contact' arguments and removes the contact from the group,",
"",
- "Example : /group",
- "Example : /group show friends",
- "Example : /group add friends newfriend@server.org",
- "Example : /group add family Brother (using contacts nickname)",
- "Example : /group remove colleagues boss@work.com",
+ "show group : List all roster items a group.",
+ "add group contact : Added a contact to a group.",
+ "remove group contact : Remove a contact from a group.",
+ "",
+ "Passing no argument will list all roster groups.",
+ "",
+ "Example: /group",
+ "Example: /group show friends",
+ "Example: /group add friends newfriend@server.org",
+ "Example: /group add family Brother (using contacts nickname)",
+ "Example: /group remove colleagues boss@work.com",
NULL } } },
{ "/info",
cmd_info, parse_args, 0, 1, NULL,
- { "/info [contact|nick]", "Show basic information about a contact, room, or room member.",
+ { "/info [contact|nick]", "Show information about a contact, room, or room member.",
{ "/info [contact|nick]",
"--------------------",
- "Show basic information about a contact, room, or room member.",
- "If in the console, a contact must be specified.",
- "If in a chat window the parameter is not required, the current recipient will be used.",
- "If in a chat room, providing no arguments will display information about the room.",
- "If in a chat room, supplying a nick will show information about the occupant.",
+ "Show information about a contact, room, or room member.",
"",
- "Example : /info mybuddy@chat.server.org",
- "Example : /info kai",
+ "contact : The contact you wish to view information about.",
+ "nick : When in a chat room, the occupant you wish to view information about.",
+ "",
+ "Passing no argument in a chat window will use the current recipient.",
+ "Passing no argument in a chat room will display information about the room.",
+ "",
+ "Example: /info mybuddy@chat.server.org",
+ "Example: /info kai",
NULL } } },
{ "/caps",
@@ -244,14 +261,16 @@ static struct cmd_t command_defs[] =
{ "/caps [fulljid|nick]", "Find out a contacts client software capabilities.",
{ "/caps [fulljid|nick]",
"--------------------",
- "Find out a contact, or room members client software capabilities.",
- "If in the console window or a regular chat window, a full JID is required.",
- "If in a chat room, the nickname is required.",
- "If in private chat, no parameter is required.",
+ "Find out a contacts, or room members client software capabilities.",
"",
- "Example : /caps mybuddy@chat.server.org/laptop (contact's laptop resource)",
- "Example : /caps mybuddy@chat.server.org/phone (contact's phone resource)",
- "Example : /caps bruce (room member)",
+ "fulljid : If in the console or a chat window, the full JID for which you wish to see capabilities.",
+ "nick : If in a chat room, nickname for which you wish to see capabilities.",
+ "",
+ "If in private chat initiated from a chat room, no parameter is required.",
+ "",
+ "Example: /caps mybuddy@chat.server.org/laptop (contact's laptop resource)",
+ "Example: /caps mybuddy@chat.server.org/phone (contact's phone resource)",
+ "Example: /caps bruce (room member)",
NULL } } },
{ "/software",
@@ -259,15 +278,17 @@ static struct cmd_t command_defs[] =
{ "/software [fulljid|nick]", "Find out software version information about a contacts resource.",
{ "/software [fulljid|nick]",
"------------------------",
- "Find out a contact, or room members software version information, if such requests are supported.",
- "If in the console window or a regular chat window, a full JID is required.",
- "If in a chat room, the nickname is required.",
- "If in private chat, no parameter is required.",
+ "Find out a contact, or room members software version information.",
+ "",
+ "fulljid : If in the console or a chat window, the full JID for which you wish to see software information.",
+ "nick : If in a chat room, nickname for which you wish to see software information.",
+ "",
+ "If in private chat initiated from a chat room, no parameter is required.",
"If the contact's software does not support software version requests, nothing will be displayed.",
"",
- "Example : /software mybuddy@chat.server.org/laptop (contact's laptop resource)",
- "Example : /software mybuddy@chat.server.org/phone (contact's phone resource)",
- "Example : /software bruce (room member)",
+ "Example: /software mybuddy@chat.server.org/laptop (contact's laptop resource)",
+ "Example: /software mybuddy@chat.server.org/phone (contact's phone resource)",
+ "Example: /software bruce (room member)",
NULL } } },
{ "/status",
@@ -276,39 +297,49 @@ static struct cmd_t command_defs[] =
{ "/status [contact|nick]",
"----------------------",
"Find out a contact, or room members presence information.",
+ "",
+ "contact : The contact who's presence you which to see.",
+ "nick : If in a chat room, the occupant who's presence you wish to see.",
+ "",
"If in a chat window the parameter is not required, the current recipient will be used.",
"",
- "Example : /status buddy@server.com",
- "Example : /status jon",
+ "Example: /status buddy@server.com",
+ "Example: /status jon",
NULL } } },
{ "/resource",
cmd_resource, parse_args, 1, 2, &cons_resource_setting,
- { "/resource set|off|title|message [resource]", "Set the contact's resource.",
+ { "/resource set|off|title|message [resource]", "Set the contact's resource, display settings.",
{ "/resource set|off|title|message [resource]",
"------------------------------------------",
- "Set the resource to use when chatting to a contact and manage resource display settings.",
- "set resource - Set the resource.",
- "off - Let the server choose which resource to route messages to.",
- "title on|off - Show or hide the current resource in the titlebar.",
- "message on|off - Show or hide the resource from which a message was recieved.",
+ "Override chat session resource, and manage resource display settings.",
+ "",
+ "set resource : Set the resource to which messages will be sent.",
+ "off : Let the server choose which resource to route messages to.",
+ "title on|off : Show or hide the current resource in the titlebar.",
+ "message on|off : Show or hide the resource when showing an incoming message.",
NULL } } },
{ "/join",
- cmd_join, parse_args, 1, 5, NULL,
- { "/join room[@server] [nick value] [password value]", "Join a chat room.",
- { "/join room[@server] [nick value] [password value]",
- "-------------------------------------------------",
+ cmd_join, parse_args, 0, 5, NULL,
+ { "/join [room] [nick value] [password value]", "Join a chat room.",
+ { "/join [room] [nick value] [password value]",
+ "-----------------------------------------",
"Join a chat room at the conference server.",
- "If nick is specified you will join with this nickname.",
- "Otherwise the account preference 'muc.nick' will be used which by default is the localpart of your JID (before the @).",
- "If no server is supplied, the account preference 'muc.service' is used, which is 'conference.' by default.",
+ "",
+ "room : Bare room JID (the chat server is determined by the 'muc.service' account property) or full room jid."
+ "nick value : Nickname to use in the room",
+ "password value : Password if the room requires it.",
+ "",
+ "If no room is supplied, a generated name will be used with the format private-chat-[UUID].",
+ "If no nickname is specified the account preference 'muc.nick' will be used which by default is the localpart of your JID.",
"If the room doesn't exist, and the server allows it, a new one will be created.",
"",
- "Example : /join jdev@conference.jabber.org",
- "Example : /join jdev@conference.jabber.org nick mynick",
- "Example : /join private@conference.jabber.org nick mynick password mypassword",
- "Example : /join jdev (as user@jabber.org will join jdev@conference.jabber.org)",
+ "Example: /join",
+ "Example: /join jdev@conference.jabber.org",
+ "Example: /join jdev@conference.jabber.org nick mynick",
+ "Example: /join private@conference.jabber.org nick mynick password mypassword",
+ "Example: /join jdev (as user@jabber.org will join jdev@conference.jabber.org)",
NULL } } },
{ "/leave",
@@ -324,8 +355,10 @@ static struct cmd_t command_defs[] =
{ "/invite contact [message]", "Invite contact to chat room.",
{ "/invite contact [message]",
"-------------------------",
- "Send a direct invite to the specified contact to the current chat room.",
- "If a message is supplied it will be sent as the reason for the invite.",
+ "Send a direct invite to the current chat room.",
+ "",
+ "contact : The contact you wish to invite",
+ "message : An optional message to send with the invite.",
NULL } } },
{ "/invites",
@@ -333,9 +366,7 @@ static struct cmd_t command_defs[] =
{ "/invites", "Show outstanding chat room invites.",
{ "/invites",
"--------",
- "Show all rooms that you have been invited to, and have not yet been accepted or declind.",
- "Use \"/join \" to accept a room invitation.",
- "Use \"/decline \" to decline a room invitation.",
+ "Show all rooms that you have been invited to, and not accepted or declined.",
NULL } } },
{ "/decline",
@@ -343,7 +374,9 @@ static struct cmd_t command_defs[] =
{ "/decline room", "Decline a chat room invite.",
{ "/decline room",
"-------------",
- "Decline invitation to a chat room, the room will no longer be in the list of outstanding invites.",
+ "Decline a chat room invitation.",
+ "",
+ "room : The room for the invite you wish to decline.",
NULL } } },
{ "/room",
@@ -351,9 +384,11 @@ static struct cmd_t command_defs[] =
{ "/room accept|destroy|config", "Room configuration.",
{ "/room accept|destroy|config",
"---------------------------",
- "accept - Accept default room configuration.",
- "destroy - Reject default room configuration.",
- "config - Edit room configuration.",
+ "Chat room configuration.",
+ "",
+ "accept : Accept default room configuration.",
+ "destroy : Reject default room configuration.",
+ "config : Edit room configuration.",
NULL } } },
{ "/kick",
@@ -361,8 +396,10 @@ static struct cmd_t command_defs[] =
{ "/kick nick [reason]", "Kick occupants from chat rooms.",
{ "/kick nick [reason]",
"-------------------",
- "nick - Nickname of the occupant to kick from the room.",
- "reason - Optional reason for kicking the occupant.",
+ "Kick occupants from chat rooms.",
+ "",
+ "nick : Nickname of the occupant to kick from the room.",
+ "reason : Optional reason for kicking the occupant.",
NULL } } },
{ "/ban",
@@ -370,8 +407,10 @@ static struct cmd_t command_defs[] =
{ "/ban jid [reason]", "Ban users from chat rooms.",
{ "/ban jid [reason]",
"-----------------",
- "jid - Bare JID of the user to ban from the room.",
- "reason - Optional reason for banning the user.",
+ "Ban users from chat rooms.",
+ "",
+ "jid : Bare JID of the user to ban from the room.",
+ "reason : Optional reason for banning the user.",
NULL } } },
{ "/subject",
@@ -379,8 +418,10 @@ static struct cmd_t command_defs[] =
{ "/subject set|clear [subject]", "Set or clear room subject.",
{ "/subject set|clear [subject]",
"----------------------------",
- "set subject - Set the room subject.",
- "clear - Clear the room subject.",
+ "Set or clear room subject.",
+ "",
+ "set subject : Set the room subject.",
+ "clear : Clear the room subject.",
NULL } } },
{ "/affiliation",
@@ -388,8 +429,11 @@ static struct cmd_t command_defs[] =
{ "/affiliation set|list [affiliation] [jid] [reason]", "Manage room affiliations.",
{ "/affiliation set|list [affiliation] [jid] [reason]",
"--------------------------------------------------",
- "set affiliation jid [reason]- Set the affiliation of user with jid, with an optional reason.",
- "list [affiliation] - List all users with the specified affiliation, or all if none specified.",
+ "Manage room affiliations.",
+ "",
+ "set affiliation jid [reason]: Set the affiliation of user with jid, with an optional reason.",
+ "list [affiliation] : List all users with the specified affiliation, or all if none specified.",
+ "",
"The affiliation may be one of owner, admin, member, outcast or none.",
NULL } } },
@@ -398,20 +442,28 @@ static struct cmd_t command_defs[] =
{ "/role set|list [role] [nick] [reason]", "Manage room roles.",
{ "/role set|list [role] [nick] [reason]",
"-------------------------------------",
- "set role nick [reason] - Set the role of occupant with nick, with an optional reason.",
- "list [role] - List all occupants with the specified role, or all if none specified.",
+ "Manage room roles.",
+ "",
+ "set role nick [reason] : Set the role of occupant with nick, with an optional reason.",
+ "list [role] : List all occupants with the specified role, or all if none specified.",
+ "",
"The role may be one of moderator, participant, visitor or none.",
NULL } } },
{ "/occupants",
- cmd_occupants, parse_args, 1, 2, cons_occupants_setting,
- { "/occupants show|hide|default|size [show|hide] [percent]", "Show or hide room occupants.",
- { "/occupants show|hide|default|size [show|hide] [percent]",
- "-------------------------------------------------------",
- "show - Show the occupants panel in chat rooms.",
- "hide - Hide the occupants panel in chat rooms.",
- "default - Whether occupants are shown by default in new rooms, 'show' or 'hide'",
- "size - Percentage of the screen taken by the occupants list in rooms (1-99).",
+ cmd_occupants, parse_args, 1, 3, cons_occupants_setting,
+ { "/occupants show|hide|default|size [jid|show|hide|percent] [jid]", "Show or hide room occupants.",
+ { "/occupants show|hide|default|size [jid|show|hide|percent] [jid]",
+ "---------------------------------------------------------------",
+ "Show or hide room occupants, and occupants panel display settings.",
+ "",
+ "show : Show the occupants panel in current room.",
+ "hide : Hide the occupants panel in current room.",
+ "show jid : Show jid in the occupants panel in current room.",
+ "hide jid : Hide jid in the occupants panel in current room.",
+ "default show|hide : Whether occupants are shown by default in new rooms.",
+ "default show|hide jid : Whether occupants jids are shown by default in new rooms.",
+ "size percent : Percentage of the screen taken by the occupants list in rooms (1-99).",
NULL } } },
{ "/form",
@@ -419,10 +471,12 @@ static struct cmd_t command_defs[] =
{ "/form show|submit|cancel|help [tag]", "Form handling.",
{ "/form show|submit|cancel|help [tag]",
"-----------------------------------",
- "show - Show the current form.",
- "submit - Submit the current form.",
- "cancel - Cancel changes to the current form.",
- "help [tag] - Display help for form, or a specific field.",
+ "Form configuration.",
+ "",
+ "show : Show the current form.",
+ "submit : Submit the current form.",
+ "cancel : Cancel changes to the current form.",
+ "help [tag] : Display help for form, or a specific field.",
NULL } } },
{ "/rooms",
@@ -431,45 +485,51 @@ static struct cmd_t command_defs[] =
{ "/rooms [conference-service]",
"---------------------------",
"List the chat rooms available at the specified conference service",
- "If no argument is supplied, the account preference 'muc.service' is used, which is 'conference.' by default.",
"",
- "Example : /rooms conference.jabber.org",
- "Example : /rooms (if logged in as me@server.org, is equivalent to /rooms conference.server.org)",
+ "conference-service : The conference service to query.",
+ "",
+ "If no argument is supplied, the account preference 'muc.service' is used, 'conference.' by default.",
+ "",
+ "Example: /rooms conference.jabber.org",
+ "Example: /rooms (if logged in as me@server.org, is equivalent to /rooms conference.server.org)",
NULL } } },
{ "/bookmark",
cmd_bookmark, parse_args, 0, 8, NULL,
- { "/bookmark [list|add|update|remove|join] [room@server] [nick value] [password value] [autojoin on|off]", "Manage bookmarks.",
- { "/bookmark [list|add|update|remove|join] [room@server] [nick value] [password value] [autojoin on|off]",
- "---------------------------------------------------------------------------------------------------",
- "Manage bookmarks.",
- "list: List all bookmarks.",
- "add: Add a bookmark for room@server with the following optional properties:",
- " nick: Nickname used in the chat room",
- " password: Password for private rooms, note this may be stored in plaintext on your server",
- " autojoin: Whether to join the room automatically on login \"on\" or \"off\".",
- "update: Update any of the above properties associated with the bookmark.",
- "remove: Remove the bookmark for room@server.",
- "join: Join room@server using the properties associated with the bookmark.",
- "When in a chat room, the /bookmark command with no arguments will bookmark the current room with the current settings, and set autojoin to \"on\".",
+ { "/bookmark [command] [args..]", "Manage bookmarks.",
+ { "/bookmark [command] [args..]",
+ "----------------------------",
+ "Manage bookmarks and join bookmarked rooms.",
+ "",
+ "command : list|add|update|remove|join",
+ "",
+ "list : List all bookmarks.",
+ "add room@server [prop value..] : Add a bookmark for room@server with the following optional properties:",
+ " nick value : Nickname used in the chat room",
+ " password value : Password if required, may be stored in plaintext on your server",
+ " autojoin on|off : Whether to join the room automatically on login.",
+ "update room@server [prop value..] : Update any of the above properties associated with the bookmark.",
+ "remove room@server : Remove the bookmark for room@server.",
+ "join room@server : Join room using the properties associated with the bookmark.",
+ "",
+ "In a chat room, /bookmark with no arguments will bookmark the current room, setting autojoin to \"on\".",
NULL } } },
{ "/disco",
cmd_disco, parse_args, 1, 2, NULL,
- { "/disco command entity", "Service discovery.",
- { "/disco command entity",
+ { "/disco info|items entity", "Service discovery.",
+ { "/disco info|items entity",
"---------------------",
"Find out information about an entities supported services.",
- "Command may be one of:",
- "info: List protocols and features supported by an entity.",
- "items: List items associated with an entity.",
"",
- "The entity must be a Jabber ID.",
+ "info : List protocols and features supported by an entity.",
+ "items : List items associated with an entity.",
+ "entity : Jabber ID.",
"",
- "Example : /disco info myserver.org",
- "Example : /disco items myserver.org",
- "Example : /disco items conference.jabber.org",
- "Example : /disco info myfriend@server.com/laptop",
+ "Example: /disco info myserver.org",
+ "Example: /disco items myserver.org",
+ "Example: /disco items conference.jabber.org",
+ "Example: /disco info myfriend@server.com/laptop",
NULL } } },
{ "/nick",
@@ -478,47 +538,52 @@ static struct cmd_t command_defs[] =
{ "/nick nickname",
"--------------",
"Change the name by which other members of a chat room see you.",
- "This command is only valid when called within a chat room window.",
"",
- "Example : /nick kai hansen",
- "Example : /nick bob",
+ "nickname : The new nickname.",
+ "",
+ "Example: /nick kai hansen",
+ "Example: /nick bob",
NULL } } },
{ "/win",
cmd_win, parse_args, 1, 1, NULL,
{ "/win num", "View a window.",
{ "/win num",
- "------------------",
+ "--------",
"Show the contents of a specific window in the main window area.",
+ "",
+ "num - Window number to display.",
NULL } } },
{ "/wins",
cmd_wins, parse_args, 0, 3, NULL,
- { "/wins [tidy|prune|swap] [source] [target]", "List or tidy active windows.",
- { "/wins [tidy|prune|swap] [source] [target]",
- "-----------------------------------------",
- "Passing no argument will list all currently active windows and information about their usage.",
- "tidy : Shuffle windows so there are no gaps.",
+ { "/wins [tidy|prune|swap] [source target]", "List or tidy active windows.",
+ { "/wins [tidy|prune|swap] [source target]",
+ "---------------------------------------",
+ "Show a list of windows, or tidy or swap.",
+ "",
+ "tidy : Move windows so there are no gaps.",
"prune : Close all windows with no unread messages, and then tidy as above.",
"swap source target : Swap windows, target may be an empty position.",
+ "",
+ "Passing no argument will list all currently active windows and information about their usage.",
NULL } } },
{ "/sub",
cmd_sub, parse_args, 1, 2, NULL,
- { "/sub command [jid]", "Manage subscriptions.",
- { "/sub command [jid]",
- "------------------",
- "command : One of the following,",
- "request : Send a subscription request to the user to be informed of their",
- " : presence.",
- "allow : Approve a contact's subscription reqeust to see your presence.",
- "deny : Remove subscription for a contact, or deny a request",
- "show : Show subscriprion status for a contact.",
- "sent : Show all sent subscription requests pending a response.",
- "received : Show all received subscription requests awaiting your response.",
+ { "/sub request|allow|deny|show|sent|received [jid]", "Manage subscriptions.",
+ { "/sub request|allow|deny|show|sent|received [jid]",
+ "------------------------------------------------",
+ "Manage subscriptions to contact presence.",
"",
- "The optional 'jid' parameter only applys to 'request', 'allow', 'deny' and 'show'",
- "If it is omitted the contact of the current window is used.",
+ "request [jid] : Send a subscription request to the user.",
+ "allow [jid] : Approve a contact's subscription request.",
+ "deny [jid] : Remove subscription for a contact, or deny a request",
+ "show [jid] : Show subscription status for a contact.",
+ "sent : Show all sent subscription requests pending a response.",
+ "received : Show all received subscription requests awaiting your response.",
+ "",
+ "If jid is omitted, the contact of the current window is used.",
"",
"Example: /sub request myfriend@jabber.org",
"Example: /sub allow myfriend@jabber.org",
@@ -531,9 +596,11 @@ static struct cmd_t command_defs[] =
{ "/tiny url", "Send url as tinyurl in current chat.",
{ "/tiny url",
"---------",
- "Send the url as a tiny url.",
+ "Send url as tinyurl in current chat.",
"",
- "Example : /tiny http://www.profanity.im",
+ "url : The url to make tiny.",
+ "",
+ "Example: /tiny http://www.profanity.im",
NULL } } },
{ "/who",
@@ -541,31 +608,30 @@ static struct cmd_t command_defs[] =
{ "/who [status|role|affiliation] [group]", "Show contacts/room occupants with chosen status, role or affiliation",
{ "/who [status|role|affiliation] [group]",
"--------------------------------------",
- "Normal usage:",
- "Status may be one of - online, offline, away, dnd, xa, chat, available, unavailable, or any where:",
- "online : Contacts that are online, chat, away, xa, dnd",
- "available : Contacts that are available for chat - online, chat.",
- "unavailable : Contacts that are not available for chat - offline, away, xa, dnd.",
- "any : Contacts with any status (same as calling with no argument).",
+ "Show contacts/room occupants with chosen status, role or affiliation",
"",
- "The group argument filters the list by that group.",
- "",
- "In a chat room, a role or affiliation may also be supplied instead of status.",
- "Roles: moderator, participant, visitor",
- "Affiliations: owner, admin, member",
+ "status : online|offline|away|dnd|xa|chat|available|unavailable|any",
+ " online : Contacts that are online, chat, away, xa, dnd",
+ " available : Contacts that are available for chat - online, chat.",
+ " unavailable : Contacts that are not available for chat - offline, away, xa, dnd.",
+ " any : Contacts with any status (same as calling with no argument).",
+ "role : moderator|participant|visitor",
+ "affiliation : owner|admin|member",
+ "group : Filter the results by the specified group.",
NULL } } },
{ "/close",
cmd_close, parse_args, 0, 1, NULL,
- { "/close [win|read|all]", "Close windows.",
- { "/close [win|read|all]",
+ { "/close [num|read|all]", "Close windows.",
+ { "/close [num|read|all]",
"---------------------",
+ "Close the current window, or a number of windows.",
+ "",
+ "num : Close the specified window.",
+ "all : Close all windows.",
+ "read : Close all windows that have no new messages.",
+ "",
"Passing no argument will close the current window.",
- "2,3,4,5,6,7,8,9 or 0 : Close the specified window.",
- "all : Close all currently open windows.",
- "read : Close all windows that have no new messages.",
- "The console window cannot be closed.",
- "If in a chat room, you will leave the room.",
NULL } } },
{ "/clear",
@@ -588,8 +654,8 @@ static struct cmd_t command_defs[] =
cmd_privileges, parse_args, 1, 1, &cons_privileges_setting,
{ "/privileges on|off", "Show occupant privileges in chat rooms.",
{ "/privileges on|off",
- "---------------------------",
- "If enabled the room roster will be broken down my role, and role information will be showin in the room.",
+ "------------------",
+ "If enabled the room occupants panel will be grouped by role, and role information will be shown in the room.",
NULL } } },
{ "/beep",
@@ -607,7 +673,7 @@ static struct cmd_t command_defs[] =
{ "/presence on|off", "Show the contacts presence in the titlebar.",
{ "/presence on|off",
"----------------",
- "Switch display of the contacts presence on or off.",
+ "Switch display of the contacts presence in the titlebar on or off.",
NULL } } },
{ "/wrap",
@@ -615,71 +681,61 @@ static struct cmd_t command_defs[] =
{ "/wrap on|off", "Word wrapping.",
{ "/wrap on|off",
"------------",
- "Enable or disable word wrapping.",
+ "Enable or disable word wrapping in the main window.",
NULL } } },
{ "/time",
- cmd_time, parse_args, 1, 1, &cons_time_setting,
- { "/time ", "Time display.",
- { "/time ",
- "---------------------",
- "Configure the time format for the main window.",
+ cmd_time, parse_args, 1, 3, &cons_time_setting,
+ { "/time main|statusbar set|off [format]", "Time display.",
+ { "/time main|statusbar set|off [format]",
+ "---------------------------------",
+ "Configure time display preferences.",
+ "",
+ "main set : Change strftime format to in main window.",
+ "main off : Do not show time in main window.",
+ "statusbar set : Change strftime format to in statusbar.",
+ "statusbar off : Do not show time in status bar.",
NULL } } },
{ "/inpblock",
cmd_inpblock, parse_args, 2, 2, &cons_inpblock_setting,
- { "/inpblock timeout|dynamic [millis|on|off]", "Input blocking delay (dynamic or static).",
+ { "/inpblock timeout|dynamic [millis|on|off]", "Configure input blocking.",
{ "/inpblock timeout|dynamic [millis|on|off]",
"-----------------------------------------",
"How long to wait for input before checking for new messages or checking for state changes such as 'idle'.",
- "timeout : Time to wait in milliseconds before reading input from the terminal buffer, defaults to 500.",
- " : Valid values are 1-1000.",
- "dynamic : Start with a 0 timeout and increase the value dynamically up to the specified 'timeout'.",
- " : on|off",
- "A higher timeout will result in less CPU usage, but a noticable delay for response to input.",
- "A lower timeout will result in higher CPU usage, but faster response to input.",
- "Using the dynamic setting, higher CPU usage will occur during activity, but over time the CPU usage will decrease whilst there is no activity.",
+ "",
+ "timeout millis : Time to wait (1-1000) in milliseconds before reading input from the terminal buffer, default: 1000.",
+ "dynamic on|off : Start with 0 millis and dynamically increase up to timeout when no activity, default: on.",
NULL } } },
{ "/notify",
cmd_notify, parse_args, 2, 3, &cons_notify_setting,
- { "/notify [type value]|[type setting value]", "Control various desktop noficiations.",
+ { "/notify [type value]|[type setting value]", "Control various desktop notifications.",
{ "/notify [type value]|[type setting value]",
"-----------------------------------------",
- "Settings for various desktop notifications where type is one of:",
- "message : Notificaitons for regular messages.",
- " : on|off",
- "message current : Whether messages in the current window trigger notifications.",
- " : on|off",
- "message text : Show message text in message notifications.",
- " : on|off",
- "room : Notificaitons for chat room messages.",
- " : on|off|mention",
- "room current : Whether chat room messages in the current window trigger notifications.",
- " : on|off",
- "room text : Show message test in chat room message notifications.",
- " : on|off",
- "remind : Notification reminders of unread messages.",
- " : where value is the reminder period in seconds,",
- " : use 0 to disable.",
- "typing : Notifications when contacts are typing.",
- " : on|off",
- "typing current : Whether typing notifications are triggerd for the current window.",
- " : on|off",
- "invite : Notifications for chat room invites.",
- " : on|off",
- "sub : Notifications for subscription requests.",
- " : on|off",
+ "Settings for various kinds of desktop notifications.",
"",
- "Example : /notify message on (enable message notifications)",
- "Example : /notify message text on (show message text in notifications)",
- "Example : /notify room mention (enable chat room notifications only on mention)",
- "Example : /notify room current off (disable room message notifications when window visible)",
- "Example : /notify room text off (do not show message text in chat room notifications)",
- "Example : /notify remind 10 (remind every 10 seconds)",
- "Example : /notify remind 0 (switch off reminders)",
- "Example : /notify typing on (enable typing notifications)",
- "Example : /notify invite on (enable chat room invite notifications)",
+ "message on|off : Notifications for regular messages.",
+ "message current on|off : Whether messages in the current window trigger notifications.",
+ "message text on|off : Show message text in message notifications.",
+ "room on|off|mention : Notifications for chat room messages.",
+ "room current on|off : Whether chat room messages in the current window trigger notifications.",
+ "room text on|off : Show message text in chat room message notifications.",
+ "remind seconds : Notification reminder period for unread messages, use 0 to disable.",
+ "typing on|off : Notifications when contacts are typing.",
+ "typing current of|off : Whether typing notifications are triggered for the current window.",
+ "invite on|off : Notifications for chat room invites.",
+ "sub on|off : Notifications for subscription requests.",
+ "",
+ "Example: /notify message on (enable message notifications)",
+ "Example: /notify message text on (show message text in notifications)",
+ "Example: /notify room mention (enable chat room notifications only on mention)",
+ "Example: /notify room current off (disable room message notifications when window visible)",
+ "Example: /notify room text off (do not show message text in chat room notifications)",
+ "Example: /notify remind 10 (remind every 10 seconds)",
+ "Example: /notify remind 0 (switch off reminders)",
+ "Example: /notify typing on (enable typing notifications)",
+ "Example: /notify invite on (enable chat room invite notifications)",
NULL } } },
{ "/flash",
@@ -687,8 +743,7 @@ static struct cmd_t command_defs[] =
{ "/flash on|off", "Terminal flash on new messages.",
{ "/flash on|off",
"-------------",
- "Make the terminal flash when incoming messages are received.",
- "The flash will only occur if you are not in the chat window associated with the user sending the message.",
+ "Make the terminal flash when incoming messages are received in another window.",
"If the terminal doesn't support flashing, it may attempt to beep.",
NULL } } },
@@ -717,7 +772,7 @@ static struct cmd_t command_defs[] =
"The setting can be overridden by the -a (--account) command line option.",
"",
"Example: /autoconnect set jc@stuntteam.org (autoconnect with the specified account).",
- "Example: /autoconnect off (disable autoconnect).",
+ "Example: /autoconnect off (disable autoconnect).",
NULL } } },
{ "/vercheck",
@@ -725,18 +780,18 @@ static struct cmd_t command_defs[] =
{ "/vercheck [on|off]", "Check for a new release.",
{ "/vercheck [on|off]",
"------------------",
- "Without a parameter will check for a new release.",
- "Switching on or off will enable/disable a version check when Profanity starts, and each time the /about command is run.",
+ "Enable/disable a version check when Profanity starts, and each time the /about command is run.",
NULL } } },
{ "/titlebar",
cmd_titlebar, parse_args, 2, 2, &cons_titlebar_setting,
{ "/titlebar show|goodbye on|off", "Manage the terminal window title.",
{ "/titlebar show|goodbye on|off",
- "---------------------",
+ "-----------------------------",
"Show or hide a title and exit message in the terminal window title.",
- "show - Show current logged in user, and unread messages in the title.",
- "goodbye - Show a message in the title when exiting profanity.",
+ "",
+ "show : Show current logged in user, and unread messages in the title.",
+ "goodbye : Show a message in the title when exiting profanity.",
NULL } } },
{ "/mouse",
@@ -744,12 +799,7 @@ static struct cmd_t command_defs[] =
{ "/mouse on|off", "Use profanity mouse handling.",
{ "/mouse on|off",
"-------------",
- "If set to 'on', profanity will handle mouse actions, which enables scrolling the main window with the mouse wheel.",
- "To select text, use the shift key while selcting an area.",
- "If set to 'off', profanity leaves mouse handling to the terminal implementation.",
- "This feature is experimental, certain mouse click events may occasionally freeze",
- "Profanity until a key is pressed or another mouse event is received",
- "The default is 'off'.",
+ "This feature is experimental, default is 'off'.",
NULL } } },
{ "/alias",
@@ -758,12 +808,17 @@ static struct cmd_t command_defs[] =
{ "/alias add|remove|list [name value]",
"-----------------------------------",
"Add, remove or show command aliases.",
- "The alias will be available as a command, the leading '/' will be added if not supplied.",
- "Example : /alias add friends /who online friends",
- "Example : /alias add /q /quit",
- "Example : /alias a /away \"I'm in a meeting.\"",
- "Example : /alias remove q",
- "Example : /alias list",
+ "",
+ "add name value : Add a new command alias.",
+ "remove name : Remove a command alias.",
+ "list : List all aliases.",
+ "",
+ "Example: /alias add friends /who online friends",
+ "Example: /alias add /q /quit",
+ "Example: /alias a /away \"I'm in a meeting.\"",
+ "Example: /alias remove q",
+ "Example: /alias list",
+ "",
"The above aliases will be available as /friends and /a",
NULL } } },
@@ -792,29 +847,30 @@ static struct cmd_t command_defs[] =
{ "/states on|off", "Send chat states during a chat session.",
{ "/states on|off",
"--------------",
- "Sending of chat state notifications during chat sessions.",
- "Such as whether you have become inactive, or have closed the chat window.",
+ "Send chat state notifications during chat sessions.",
NULL } } },
{ "/otr",
cmd_otr, parse_args, 1, 3, NULL,
- { "/otr gen|myfp|theirfp|start|end|trust|untrust|log|warn|libver|policy|secret|question|answer", "Off The Record encryption commands.",
- { "/otr gen|myfp|theirfp|start|end|trust|untrust|log|warn|libver|policy|secret|question|answer",
- "-------------------------------------------------------------------------------------------",
- "gen - Generate your private key.",
- "myfp - Show your fingerprint.",
- "theirfp - Show contacts fingerprint.",
- "start [contact] - Start an OTR session with the contact, or the current recipient if in a chat window and no argument supplied.",
- "end - End the current OTR session,",
- "trust - Indicate that you have verified the contact's fingerprint.",
- "untrust - Indicate the the contact's fingerprint is not verified,",
- "log - How to log OTR messages, options are 'on', 'off' and 'redact', with redaction being the default.",
- "warn - Show when unencrypted messaging is being used in the title bar, options are 'on' and 'off' with 'on' being the default.",
- "libver - Show which version of the libotr library is being used.",
- "policy - manual, opportunistic or always.",
- "secret [secret]- Verify a contacts identity using a shared secret.",
- "question [question] [answer] - Verify a contacts identity using a question and expected anwser, if the question has spaces, surround with double quotes.",
- "answer [answer] - Respond to a question answer verification request with your answer.",
+ { "/otr command [args..]", "Off The Record encryption commands.",
+ { "/otr command [args..]",
+ "---------------------",
+ "Off The Record encryption commands.",
+ "",
+ "gen : Generate your private key.",
+ "myfp : Show your fingerprint.",
+ "theirfp : Show contacts fingerprint.",
+ "start [contact] : Start an OTR session with contact, or current recipient if omitted.",
+ "end : End the current OTR session,",
+ "trust : Indicate that you have verified the contact's fingerprint.",
+ "untrust : Indicate the the contact's fingerprint is not verified,",
+ "log on|off|redact : OTR message logging, default: redact.",
+ "warn on|off : Show in the titlebar when unencrypted messaging is being used.",
+ "libver : Show which version of the libotr library is being used.",
+ "policy manual|opportunistic|always : Set the global OTR policy.",
+ "secret [secret] : Verify a contacts identity using a shared secret.",
+ "question [question] [answer] : Verify a contacts identity using a question and expected answer.",
+ "answer [answer] : Respond to a question answer verification request with your answer.",
NULL } } },
{ "/outtype",
@@ -822,8 +878,7 @@ static struct cmd_t command_defs[] =
{ "/outtype on|off", "Send typing notification to recipient.",
{ "/outtype on|off",
"---------------",
- "Send an indication that you are typing to the chat recipient.",
- "Chat states (/states) will be enabled if this setting is set.",
+ "Send typing notifications, chat states (/states) will be enabled if this setting is set.",
NULL } } },
{ "/gone",
@@ -831,8 +886,7 @@ static struct cmd_t command_defs[] =
{ "/gone minutes", "Send 'gone' state to recipient after a period.",
{ "/gone minutes",
"-------------",
- "Send a 'gone' state to the recipient after the specified number of minutes."
- "This indicates to the recipient's client that you have left the conversation.",
+ "Send a 'gone' state to the recipient after the specified number of minutes.",
"A value of 0 will disable sending this chat state.",
"Chat states (/states) will be enabled if this setting is set.",
NULL } } },
@@ -848,16 +902,37 @@ static struct cmd_t command_defs[] =
{ "/log",
cmd_log, parse_args, 1, 2, &cons_log_setting,
- { "/log [property] [value]", "Manage system logging settings.",
- { "/log [property] [value]",
- "-----------------------",
- "where : Show the current log file location.",
- "Property may be one of:",
- "rotate : Rotate log, accepts 'on' or 'off', defaults to 'on'.",
- "maxsize : With rotate enabled, specifies the max log size, defaults to 1048580 (1MB).",
- "shared : Share logs between all instances, accepts 'on' or 'off', defaults to 'on'.",
+ { "/log where|rotate|maxsize|shared [value]", "Manage system logging settings.",
+ { "/log where|rotate|maxsize|shared [value]",
+ "----------------------------------------",
+ "Manage profanity logging settings.",
+ "",
+ "where : Show the current log file location.",
+ "rotate on|off : Rotate log, default on.",
+ "maxsize bytes : With rotate enabled, specifies the max log size, defaults to 1048580 (1MB).",
+ "shared on|off : Share logs between all instances, default: on.",
NULL } } },
+ { "/carbons",
+ cmd_carbons, parse_args, 1, 1, &cons_carbons_setting,
+ { "/carbons on|off", "Message carbons.",
+ { "/carbons on|off",
+ "---------------",
+ "Enable or disable message carbons.",
+ "The message carbons feature ensures that both sides of all conversations are shared with all the user's clients that implement this protocol.",
+ NULL } } },
+
+ { "/receipts",
+ cmd_receipts, parse_args, 2, 2, &cons_receipts_setting,
+ { "/receipts send|request on|off", "Message delivery receipts.",
+ { "/receipts send|request on|off",
+ "-----------------------------",
+ "Enable or disable message delivery receipts. The interface will indicate when a message has been received.",
+ "",
+ "send on|off : Enable or disable sending of delivery receipts.",
+ "request on|off : Enable or disable sending of delivery receipt requests.",
+ NULL } } },
+
{ "/reconnect",
cmd_reconnect, parse_args, 1, 1, &cons_reconnect_setting,
{ "/reconnect seconds", "Set reconnect interval.",
@@ -879,26 +954,25 @@ static struct cmd_t command_defs[] =
{ "/ping",
cmd_ping, parse_args, 0, 1, NULL,
{ "/ping [target]", "Send ping IQ request.",
- { "/ping [rarget]",
+ { "/ping [target]",
"--------------",
- "Sends an IQ ping stanza to the specificed target.",
- "If no target is supplied, your chat server will be used.",
+ "Sends an IQ ping stanza to the specified target.",
+ "If no target is supplied, your chat server will be pinged.",
NULL } } },
{ "/autoaway",
cmd_autoaway, parse_args_with_freetext, 2, 2, &cons_autoaway_setting,
- { "/autoaway setting value", "Set auto idle/away properties.",
- { "/autoaway setting value",
- "-----------------------",
- "'setting' may be one of 'mode', 'time', 'message' or 'check', with the following values:",
+ { "/autoaway mode|time|message|check value", "Set auto idle/away properties.",
+ { "/autoaway mode|time|message|check value",
+ "---------------------------------------",
+ "Manage autoway properties.",
"",
- "mode : idle - Sends idle time, whilst your status remains online.",
- " away - Sends an away presence.",
- " off - Disabled (default).",
- "time : Number of minutes before the presence change is sent, the default is 15.",
- "message : Optional message to send with the presence change.",
- " : off - Disable message (default).",
- "check : on|off, when enabled, checks for activity and sends online presence, default is 'on'.",
+ "mode idle : Sends idle time, status remains online.",
+ "mode away : Sends an away presence.",
+ "mode off : Disabled (default).",
+ "time minutes : Number of minutes before the presence change is sent, default: 15.",
+ "message text|off : Optional message to send with the presence change, default: off (disabled).",
+ "check on|off : When enabled, checks for activity and sends online presence, default: on.",
"",
"Example: /autoaway mode idle",
"Example: /autoaway time 30",
@@ -911,9 +985,11 @@ static struct cmd_t command_defs[] =
{ "/priority value", "Set priority for the current account.",
{ "/priority value",
"---------------",
- "Set priority for the current account, presence will be sent when calling this command.",
- "See the /account command for more specific priority settings per presence status.",
- "value : Number between -128 and 127. Default value is 0.",
+ "Set priority for the current account.",
+ "",
+ "value : Number between -128 and 127, default: 0.",
+ "",
+ "See the /account command for specific priority settings per presence status.",
NULL } } },
{ "/account",
@@ -922,6 +998,7 @@ static struct cmd_t command_defs[] =
{ "/account [command] [account] [property] [value]",
"-----------------------------------------------",
"Commands for creating and managing accounts.",
+ "",
"list : List all accounts.",
"show account : Show information about an account.",
"enable account : Enable the account, it will be used for autocomplete.",
@@ -933,43 +1010,38 @@ static struct cmd_t command_defs[] =
"set account property value : Set 'property' of 'account' to 'value'.",
"clear account property value : Clear 'property' of 'account'.",
"",
- "When connected, the /account command can be called with no arguments, to show current account settings.",
+ "Account properties.",
"",
- "The set command may use one of the following for 'property'.",
- "jid : The Jabber ID of the account, the account name will be used if this property is not set.",
- "server : The chat server, if different to the domainpart of the JID.",
- "port : The port used for connecting if not the default (5222, or 5223 for SSL).",
- "status : The presence status to use on login, use 'last' to use whatever your last status was.",
- "online|chat|away",
- "|xa|dnd : Priority for the specified presence.",
- "resource : The resource to be used.",
- "password : Password for the account, note this is currently stored in plaintext if set.",
- "eval_password : Shell command evaluated to retrieve password for the account. Can be used to retrieve password from keyring.",
- "muc : The default MUC chat service to use.",
- "nick : The default nickname to use when joining chat rooms.",
- "otr : Override global OTR policy for this account: manual, opportunistic or always.",
+ "jid : The Jabber ID of the account, account name will be used if not set.",
+ "server : The chat server, if different to the domainpart of the JID.",
+ "port : The port used for connecting if not the default (5222, or 5223 for SSL).",
+ "status : The presence status to use on login, use 'last' to use your last status before logging out.",
+ "online|chat|away|xa|dnd : Priority for the specified presence.",
+ "resource : The resource to be used.",
+ "password : Password for the account, note this is currently stored in plaintext if set.",
+ "eval_password : Shell command evaluated to retrieve password for the account. Can be used to retrieve password from keyring.",
+ "muc : The default MUC chat service to use.",
+ "nick : The default nickname to use when joining chat rooms.",
+ "otr : Override global OTR policy for this account: manual, opportunistic or always.",
"",
- "The clear command works for password, port and server",
- "",
- "Example : /account add work",
- " : /account set work jid me@chatty",
- " : /account set work server talk.chat.com",
- " : /account set work port 5111",
- " : /account set work resource desktop",
- " : /account set work muc chatservice.mycompany.com",
- " : /account set work nick dennis",
- " : /account set work status dnd",
- " : /account set work dnd -1",
- " : /account set work online 10",
- " : /account rename work gtalk",
+ "Example: /account add me",
+ "Example: /account set me jid me@chatty",
+ "Example: /account set me server talk.chat.com",
+ "Example: /account set me port 5111",
+ "Example: /account set me muc chatservice.mycompany.com",
+ "Example: /account set me nick dennis",
+ "Example: /account set me status dnd",
+ "Example: /account set me dnd -1",
+ "Example: /account rename me gtalk",
NULL } } },
{ "/prefs",
cmd_prefs, parse_args, 0, 1, NULL,
- { "/prefs [area]", "Show configuration.",
- { "/prefs [area]",
- "-------------",
- "Area is one of:",
+ { "/prefs [ui|desktop|chat|log|conn|presence]", "Show configuration.",
+ { "/prefs [ui|desktop|chat|log|conn|presence]",
+ "------------------------------------------",
+ "Show preferences for different areas of functionality.",
+ "",
"ui : User interface preferences.",
"desktop : Desktop notification preferences.",
"chat : Chat state preferences.",
@@ -977,22 +1049,22 @@ static struct cmd_t command_defs[] =
"conn : Connection handling preferences.",
"presence : Chat presence preferences.",
"",
- "No argument shows all categories.",
+ "No argument shows all preferences.",
NULL } } },
{ "/theme",
cmd_theme, parse_args, 1, 2, &cons_theme_setting,
- { "/theme list|set|colours [theme-name]", "Change colour theme.",
- { "/theme list|set|colours [theme-name]",
- "------------------------------------",
- "Change the colour settings used.",
+ { "/theme list|load|colours [theme-name]", "Change colour theme.",
+ { "/theme list|load|colours [theme-name]",
+ "-------------------------------------",
+ "Load a theme, includes colours and UI options.",
"",
- "list : List all available themes.",
- "set theme-name : Load the named theme.\"default\" will reset to the default colours.",
- "colours : Show the colour values as rendered by the terminal.",
+ "list : List all available themes.",
+ "load theme-name : Load the named theme. 'default' will reset to the default theme.",
+ "colours : Show the colour values as rendered by the terminal.",
"",
- "Example : /theme list",
- "Example : /theme set mycooltheme",
+ "Example: /theme list",
+ "Example: /theme load mycooltheme",
NULL } } },
@@ -1001,12 +1073,23 @@ static struct cmd_t command_defs[] =
{ "/statuses console|chat|muc setting", "Set preferences for presence change messages.",
{ "/statuses console|chat|muc setting",
"----------------------------------",
- "Configure how presence changes are displayed in various windows.",
- "Settings:",
- " all - Show all presence changes.",
- " online - Show only online/offline changes.",
- " none - Don't show any presence changes.",
+ "Configure which presence changes are displayed in various windows.",
+ "",
+ "console : Configure what is displayed in the console window.",
+ "chat : Configure what is displayed in chat windows.",
+ "muc : Configure what is displayed in chat room windows.",
+ "",
+ "Available options are:",
+ "",
+ "all : Show all presence changes.",
+ "online : Show only online/offline changes.",
+ "none : Don't show any presence changes.",
+ "",
"The default is 'all' for all windows.",
+ "",
+ "Example: /statuses console none",
+ "Example: /statuses chat online",
+ "Example: /statuses muc all",
NULL } } },
{ "/xmlconsole",
@@ -1019,57 +1102,52 @@ static struct cmd_t command_defs[] =
{ "/away",
cmd_away, parse_args_with_freetext, 0, 1, NULL,
- { "/away [msg]", "Set status to away.",
- { "/away [msg]",
- "-----------",
+ { "/away [message]", "Set status to away.",
+ { "/away [message]",
+ "---------------",
"Set your status to 'away' with the optional message.",
- "Your current status can be found in the top right of the screen.",
"",
- "Example : /away Gone for lunch",
+ "Example: /away Gone for lunch",
NULL } } },
{ "/chat",
cmd_chat, parse_args_with_freetext, 0, 1, NULL,
- { "/chat [msg]", "Set status to chat (available for chat).",
- { "/chat [msg]",
- "-----------",
+ { "/chat [message]", "Set status to chat (available for chat).",
+ { "/chat [message]",
+ "---------------",
"Set your status to 'chat', meaning 'available for chat', with the optional message.",
- "Your current status can be found in the top right of the screen.",
"",
- "Example : /chat Please talk to me!",
+ "Example: /chat Please talk to me!",
NULL } } },
{ "/dnd",
cmd_dnd, parse_args_with_freetext, 0, 1, NULL,
- { "/dnd [msg]", "Set status to dnd (do not disturb).",
- { "/dnd [msg]",
- "----------",
+ { "/dnd [message]", "Set status to dnd (do not disturb).",
+ { "/dnd [message]",
+ "--------------",
"Set your status to 'dnd', meaning 'do not disturb', with the optional message.",
- "Your current status can be found in the top right of the screen.",
"",
- "Example : /dnd I'm in the zone",
+ "Example: /dnd I'm in the zone",
NULL } } },
{ "/online",
cmd_online, parse_args_with_freetext, 0, 1, NULL,
- { "/online [msg]", "Set status to online.",
- { "/online [msg]",
- "-------------",
+ { "/online [message]", "Set status to online.",
+ { "/online [message]",
+ "-----------------",
"Set your status to 'online' with the optional message.",
- "Your current status can be found in the top right of the screen.",
"",
- "Example : /online Up the Irons!",
+ "Example: /online Up the Irons!",
NULL } } },
{ "/xa",
cmd_xa, parse_args_with_freetext, 0, 1, NULL,
- { "/xa [msg]", "Set status to xa (extended away).",
- { "/xa [msg]",
- "---------",
+ { "/xa [message]", "Set status to xa (extended away).",
+ { "/xa [message]",
+ "-------------",
"Set your status to 'xa', meaning 'extended away', with the optional message.",
- "Your current status can be found in the top right of the screen.",
"",
- "Example : /xa This meeting is going to be a long one",
+ "Example: /xa This meeting is going to be a long one",
NULL } } },
};
@@ -1121,8 +1199,12 @@ static Autocomplete form_ac;
static Autocomplete form_field_multi_ac;
static Autocomplete occupants_ac;
static Autocomplete occupants_default_ac;
+static Autocomplete occupants_show_ac;
+static Autocomplete time_ac;
+static Autocomplete time_statusbar_ac;
static Autocomplete resource_ac;
static Autocomplete inpblock_ac;
+static Autocomplete receipts_ac;
/*
* Initialise command autocompleter and history
@@ -1140,7 +1222,7 @@ cmd_init(void)
autocomplete_add(help_ac, "basic");
autocomplete_add(help_ac, "chatting");
autocomplete_add(help_ac, "groupchat");
- autocomplete_add(help_ac, "presence");
+ autocomplete_add(help_ac, "presences");
autocomplete_add(help_ac, "contacts");
autocomplete_add(help_ac, "service");
autocomplete_add(help_ac, "settings");
@@ -1163,7 +1245,7 @@ cmd_init(void)
// load aliases
GList *aliases = prefs_get_aliases();
GList *curr = aliases;
- while (curr != NULL) {
+ while (curr) {
ProfAlias *alias = curr->data;
GString *ac_alias = g_string_new("/");
g_string_append(ac_alias, alias->name);
@@ -1243,8 +1325,8 @@ cmd_init(void)
autocomplete_add(autoconnect_ac, "off");
theme_ac = autocomplete_new();
+ autocomplete_add(theme_ac, "load");
autocomplete_add(theme_ac, "list");
- autocomplete_add(theme_ac, "set");
autocomplete_add(theme_ac, "colours");
disco_ac = autocomplete_new();
@@ -1460,6 +1542,20 @@ cmd_init(void)
autocomplete_add(occupants_default_ac, "show");
autocomplete_add(occupants_default_ac, "hide");
+ occupants_show_ac = autocomplete_new();
+ autocomplete_add(occupants_show_ac, "jid");
+
+ time_ac = autocomplete_new();
+ autocomplete_add(time_ac, "minutes");
+ autocomplete_add(time_ac, "seconds");
+ autocomplete_add(time_ac, "off");
+ autocomplete_add(time_ac, "statusbar");
+
+ time_statusbar_ac = autocomplete_new();
+ autocomplete_add(time_statusbar_ac, "minutes");
+ autocomplete_add(time_statusbar_ac, "seconds");
+ autocomplete_add(time_statusbar_ac, "off");
+
resource_ac = autocomplete_new();
autocomplete_add(resource_ac, "set");
autocomplete_add(resource_ac, "off");
@@ -1469,6 +1565,10 @@ cmd_init(void)
inpblock_ac = autocomplete_new();
autocomplete_add(inpblock_ac, "timeout");
autocomplete_add(inpblock_ac, "dynamic");
+
+ receipts_ac = autocomplete_new();
+ autocomplete_add(receipts_ac, "send");
+ autocomplete_add(receipts_ac, "request");
}
void
@@ -1522,8 +1622,12 @@ cmd_uninit(void)
autocomplete_free(form_field_multi_ac);
autocomplete_free(occupants_ac);
autocomplete_free(occupants_default_ac);
+ autocomplete_free(occupants_show_ac);
+ autocomplete_free(time_ac);
+ autocomplete_free(time_statusbar_ac);
autocomplete_free(resource_ac);
autocomplete_free(inpblock_ac);
+ autocomplete_free(receipts_ac);
}
gboolean
@@ -1539,7 +1643,7 @@ cmd_exists(char *cmd)
void
cmd_autocomplete_add(char *value)
{
- if (commands_ac != NULL) {
+ if (commands_ac) {
autocomplete_add(commands_ac, value);
}
}
@@ -1547,41 +1651,45 @@ cmd_autocomplete_add(char *value)
void
cmd_autocomplete_add_form_fields(DataForm *form)
{
- if (form) {
- GSList *fields = autocomplete_create_list(form->tag_ac);
- GSList *curr_field = fields;
- while (curr_field) {
- GString *field_str = g_string_new("/");
- g_string_append(field_str, curr_field->data);
- cmd_autocomplete_add(field_str->str);
- g_string_free(field_str, TRUE);
- curr_field = g_slist_next(curr_field);
- }
- g_slist_free_full(fields, free);
+ if (form == NULL) {
+ return;
}
+
+ GSList *fields = autocomplete_create_list(form->tag_ac);
+ GSList *curr_field = fields;
+ while (curr_field) {
+ GString *field_str = g_string_new("/");
+ g_string_append(field_str, curr_field->data);
+ cmd_autocomplete_add(field_str->str);
+ g_string_free(field_str, TRUE);
+ curr_field = g_slist_next(curr_field);
+ }
+ g_slist_free_full(fields, free);
}
void
cmd_autocomplete_remove_form_fields(DataForm *form)
{
- if (form) {
- GSList *fields = autocomplete_create_list(form->tag_ac);
- GSList *curr_field = fields;
- while (curr_field) {
- GString *field_str = g_string_new("/");
- g_string_append(field_str, curr_field->data);
- cmd_autocomplete_remove(field_str->str);
- g_string_free(field_str, TRUE);
- curr_field = g_slist_next(curr_field);
- }
- g_slist_free_full(fields, free);
+ if (form == NULL) {
+ return;
}
+
+ GSList *fields = autocomplete_create_list(form->tag_ac);
+ GSList *curr_field = fields;
+ while (curr_field) {
+ GString *field_str = g_string_new("/");
+ g_string_append(field_str, curr_field->data);
+ cmd_autocomplete_remove(field_str->str);
+ g_string_free(field_str, TRUE);
+ curr_field = g_slist_next(curr_field);
+ }
+ g_slist_free_full(fields, free);
}
void
cmd_autocomplete_remove(char *value)
{
- if (commands_ac != NULL) {
+ if (commands_ac) {
autocomplete_remove(commands_ac, value);
}
}
@@ -1589,7 +1697,7 @@ cmd_autocomplete_remove(char *value)
void
cmd_alias_add(char *value)
{
- if (aliases_ac != NULL) {
+ if (aliases_ac) {
autocomplete_add(aliases_ac, value);
}
}
@@ -1597,7 +1705,7 @@ cmd_alias_add(char *value)
void
cmd_alias_remove(char *value)
{
- if (aliases_ac != NULL) {
+ if (aliases_ac) {
autocomplete_remove(aliases_ac, value);
}
}
@@ -1610,7 +1718,7 @@ cmd_autocomplete(const char * const input)
if ((strncmp(input, "/", 1) == 0) && (!str_contains(input, strlen(input), ' '))) {
char *found = NULL;
found = autocomplete_complete(commands_ac, input, TRUE);
- if (found != NULL) {
+ if (found) {
return found;
}
@@ -1650,8 +1758,8 @@ cmd_reset_autocomplete()
autocomplete_reset(autoaway_mode_ac);
autocomplete_reset(autoconnect_ac);
autocomplete_reset(theme_ac);
- if (theme_load_ac != NULL) {
- autocomplete_reset(theme_load_ac);
+ if (theme_load_ac) {
+ autocomplete_free(theme_load_ac);
theme_load_ac = NULL;
}
autocomplete_reset(account_ac);
@@ -1686,8 +1794,12 @@ cmd_reset_autocomplete()
autocomplete_reset(form_field_multi_ac);
autocomplete_reset(occupants_ac);
autocomplete_reset(occupants_default_ac);
+ autocomplete_reset(occupants_show_ac);
+ autocomplete_reset(time_ac);
+ autocomplete_reset(time_statusbar_ac);
autocomplete_reset(resource_ac);
autocomplete_reset(inpblock_ac);
+ autocomplete_reset(receipts_ac);
if (ui_current_win_type() == WIN_CHAT) {
ProfChatWin *chatwin = wins_get_current_chat();
@@ -1724,11 +1836,6 @@ cmd_process_input(char *inp)
gboolean result = FALSE;
g_strstrip(inp);
- // add line to history if something typed
- if (strlen(inp) > 0) {
- ui_inp_history_append(inp);
- }
-
// just carry on if no input
if (strlen(inp) == 0) {
result = TRUE;
@@ -1742,7 +1849,7 @@ cmd_process_input(char *inp)
// call a default handler if input didn't start with '/'
} else {
- result = _cmd_execute_default(inp);
+ result = cmd_execute_default(inp);
}
return result;
@@ -1782,7 +1889,7 @@ _cmd_execute(const char * const command, const char * const inp)
Command *cmd = g_hash_table_lookup(commands, command);
gboolean result = FALSE;
- if (cmd != NULL) {
+ if (cmd) {
gchar **args = cmd->parser(inp, cmd->min_args, cmd->max_args, &result);
if (result == FALSE) {
ui_invalid_command_usage(cmd->help.usage, cmd->setting_func);
@@ -1794,145 +1901,15 @@ _cmd_execute(const char * const command, const char * const inp)
}
} else {
gboolean ran_alias = FALSE;
- gboolean alias_result = _cmd_execute_alias(inp, &ran_alias);
+ gboolean alias_result = cmd_execute_alias(inp, &ran_alias);
if (!ran_alias) {
- return _cmd_execute_default(inp);
+ return cmd_execute_default(inp);
} else {
return alias_result;
}
}
}
-static gboolean
-_cmd_execute_alias(const char * const inp, gboolean *ran)
-{
- if (inp[0] != '/') {
- ran = FALSE;
- return TRUE;
- } else {
- char *alias = strdup(inp+1);
- char *value = prefs_get_alias(alias);
- free(alias);
- if (value != NULL) {
- *ran = TRUE;
- return cmd_process_input(value);
- } else {
- *ran = FALSE;
- return TRUE;
- }
- }
-}
-
-static gboolean
-_cmd_execute_default(const char * inp)
-{
- jabber_conn_status_t status = jabber_get_connection_status();
-
- // handle escaped commands - treat as normal message
- if (g_str_has_prefix(inp, "//")) {
- inp++;
-
- // handle unknown commands
- } else if ((inp[0] == '/') && (!g_str_has_prefix(inp, "/me "))) {
- cons_show("Unknown command: %s", inp);
- cons_alert();
- return TRUE;
- }
-
- win_type_t win_type = ui_current_win_type();
- switch (win_type)
- {
- case WIN_MUC:
- if (status != JABBER_CONNECTED) {
- ui_current_print_line("You are not currently connected.");
- } else {
- ProfMucWin *mucwin = wins_get_current_muc();
- message_send_groupchat(mucwin->roomjid, inp);
- }
- break;
-
- case WIN_CHAT:
- if (status != JABBER_CONNECTED) {
- ui_current_print_line("You are not currently connected.");
- } else {
- ProfWin *current = wins_get_current();
- ProfChatWin *chatwin = (ProfChatWin*)current;
- assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
-#ifdef HAVE_LIBOTR
- prof_otrpolicy_t policy = otr_get_policy(chatwin->barejid);
- if (policy == PROF_OTRPOLICY_ALWAYS && !otr_is_secure(chatwin->barejid)) {
- cons_show_error("Failed to send message. Please check OTR policy");
- return TRUE;
- }
- if (otr_is_secure(chatwin->barejid)) {
- char *encrypted = otr_encrypt_message(chatwin->barejid, inp);
- if (encrypted != NULL) {
- message_send_chat(chatwin->barejid, encrypted);
- otr_free_message(encrypted);
- if (prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
- char *pref_otr_log = prefs_get_string(PREF_OTR_LOG);
- if (strcmp(pref_otr_log, "on") == 0) {
- chat_log_chat(jidp->barejid, chatwin->barejid, inp, PROF_OUT_LOG, NULL);
- } else if (strcmp(pref_otr_log, "redact") == 0) {
- chat_log_chat(jidp->barejid, chatwin->barejid, "[redacted]", PROF_OUT_LOG, NULL);
- }
- prefs_free_string(pref_otr_log);
- jid_destroy(jidp);
- }
-
- ui_outgoing_chat_msg("me", chatwin->barejid, inp);
- } else {
- cons_show_error("Failed to send message.");
- }
- } else {
- message_send_chat(chatwin->barejid, inp);
- if (prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
- chat_log_chat(jidp->barejid, chatwin->barejid, inp, PROF_OUT_LOG, NULL);
- jid_destroy(jidp);
- }
-
- ui_outgoing_chat_msg("me", chatwin->barejid, inp);
- }
-#else
- message_send_chat(chatwin->barejid, inp);
- if (prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
- chat_log_chat(jidp->barejid, chatwin->barejid, inp, PROF_OUT_LOG, NULL);
- jid_destroy(jidp);
- }
-
- ui_outgoing_chat_msg("me", chatwin->barejid, inp);
-#endif
- }
- break;
-
- case WIN_PRIVATE:
- if (status != JABBER_CONNECTED) {
- ui_current_print_line("You are not currently connected.");
- } else {
- ProfPrivateWin *privatewin = wins_get_current_private();
- message_send_private(privatewin->fulljid, inp);
- ui_outgoing_private_msg("me", privatewin->fulljid, inp);
- }
- break;
-
- case WIN_CONSOLE:
- case WIN_XML:
- cons_show("Unknown command: %s", inp);
- break;
-
- default:
- break;
- }
-
- return TRUE;
-}
-
static char *
_cmd_complete_parameters(const char * const input)
{
@@ -1942,7 +1919,7 @@ _cmd_complete_parameters(const char * const input)
// autocomplete boolean settings
gchar *boolean_choices[] = { "/beep", "/intype", "/states", "/outtype",
"/flash", "/splash", "/chlog", "/grlog", "/mouse", "/history",
- "/vercheck", "/privileges", "/presence", "/wrap" };
+ "/vercheck", "/privileges", "/presence", "/wrap", "/carbons" };
for (i = 0; i < ARRAY_SIZE(boolean_choices); i++) {
result = autocomplete_param_with_func(input, boolean_choices[i], prefs_autocomplete_boolean_choice);
@@ -1958,23 +1935,31 @@ _cmd_complete_parameters(const char * const input)
if (nick_ac) {
gchar *nick_choices[] = { "/msg", "/info", "/caps", "/status", "/software" } ;
+ // Remove quote character before and after names when doing autocomplete
+ char *unquoted = strip_arg_quotes(input);
for (i = 0; i < ARRAY_SIZE(nick_choices); i++) {
- result = autocomplete_param_with_ac(input, nick_choices[i], nick_ac, TRUE);
+ result = autocomplete_param_with_ac(unquoted, nick_choices[i], nick_ac, TRUE);
if (result) {
+ free(unquoted);
return result;
}
}
+ free(unquoted);
}
// otherwise autocomplete using roster
} else {
gchar *contact_choices[] = { "/msg", "/info", "/status" };
+ // Remove quote character before and after names when doing autocomplete
+ char *unquoted = strip_arg_quotes(input);
for (i = 0; i < ARRAY_SIZE(contact_choices); i++) {
- result = autocomplete_param_with_func(input, contact_choices[i], roster_contact_autocomplete);
+ result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_contact_autocomplete);
if (result) {
+ free(unquoted);
return result;
}
}
+ free(unquoted);
gchar *resource_choices[] = { "/caps", "/software", "/ping" };
for (i = 0; i < ARRAY_SIZE(resource_choices); i++) {
@@ -1998,8 +1983,8 @@ _cmd_complete_parameters(const char * const input)
}
}
- gchar *cmds[] = { "/help", "/prefs", "/disco", "/close", "/wins", "/subject", "/room", };
- Autocomplete completers[] = { help_ac, prefs_ac, disco_ac, close_ac, wins_ac, subject_ac, room_ac, };
+ gchar *cmds[] = { "/help", "/prefs", "/disco", "/close", "/wins", "/subject", "/room" };
+ Autocomplete completers[] = { help_ac, prefs_ac, disco_ac, close_ac, wins_ac, subject_ac, room_ac };
for (i = 0; i < ARRAY_SIZE(cmds); i++) {
result = autocomplete_param_with_ac(input, cmds[i], completers[i], TRUE);
@@ -2034,6 +2019,8 @@ _cmd_complete_parameters(const char * const input)
g_hash_table_insert(ac_funcs, "/resource", _resource_autocomplete);
g_hash_table_insert(ac_funcs, "/titlebar", _titlebar_autocomplete);
g_hash_table_insert(ac_funcs, "/inpblock", _inpblock_autocomplete);
+ g_hash_table_insert(ac_funcs, "/time", _time_autocomplete);
+ g_hash_table_insert(ac_funcs, "/receipts", _receipts_autocomplete);
int len = strlen(input);
char parsed[len+1];
@@ -2049,7 +2036,7 @@ _cmd_complete_parameters(const char * const input)
parsed[i] = '\0';
char * (*ac_func)(const char * const) = g_hash_table_lookup(ac_funcs, parsed);
- if (ac_func != NULL) {
+ if (ac_func) {
result = ac_func(input);
if (result) {
g_hash_table_destroy(ac_funcs);
@@ -2073,15 +2060,15 @@ _sub_autocomplete(const char * const input)
{
char *result = NULL;
result = autocomplete_param_with_func(input, "/sub allow", presence_sub_request_find);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/sub deny", presence_sub_request_find);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/sub", sub_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2096,7 +2083,7 @@ _who_autocomplete(const char * const input)
if (win_type == WIN_MUC) {
result = autocomplete_param_with_ac(input, "/who", who_room_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
} else {
@@ -2107,13 +2094,13 @@ _who_autocomplete(const char * const input)
for (i = 0; i < ARRAY_SIZE(group_commands); i++) {
result = autocomplete_param_with_func(input, group_commands[i], roster_group_autocomplete);
- if (result != NULL) {
+ if (result) {
return result;
}
}
result = autocomplete_param_with_ac(input, "/who", who_roster_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
}
@@ -2126,31 +2113,31 @@ _roster_autocomplete(const char * const input)
{
char *result = NULL;
result = autocomplete_param_with_func(input, "/roster nick", roster_barejid_autocomplete);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/roster clearnick", roster_barejid_autocomplete);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/roster remove", roster_barejid_autocomplete);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/roster show", roster_option_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/roster hide", roster_option_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/roster by", roster_by_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/roster", roster_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2162,28 +2149,28 @@ _group_autocomplete(const char * const input)
{
char *result = NULL;
result = autocomplete_param_with_func(input, "/group show", roster_group_autocomplete);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_no_with_func(input, "/group add", 4, roster_contact_autocomplete);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_no_with_func(input, "/group remove", 4, roster_contact_autocomplete);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/group add", roster_group_autocomplete);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/group remove", roster_group_autocomplete);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/group", group_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2244,7 +2231,7 @@ _bookmark_autocomplete(const char * const input)
found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE);
}
g_string_free(beginning, TRUE);
- if (found != NULL) {
+ if (found) {
g_strfreev(args);
return found;
}
@@ -2253,15 +2240,15 @@ _bookmark_autocomplete(const char * const input)
g_strfreev(args);
found = autocomplete_param_with_func(input, "/bookmark remove", bookmark_find);
- if (found != NULL) {
+ if (found) {
return found;
}
found = autocomplete_param_with_func(input, "/bookmark join", bookmark_find);
- if (found != NULL) {
+ if (found) {
return found;
}
found = autocomplete_param_with_func(input, "/bookmark update", bookmark_find);
- if (found != NULL) {
+ if (found) {
return found;
}
@@ -2276,42 +2263,42 @@ _notify_autocomplete(const char * const input)
char *result = NULL;
result = autocomplete_param_with_func(input, "/notify room current", prefs_autocomplete_boolean_choice);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/notify message current", prefs_autocomplete_boolean_choice);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/notify typing current", prefs_autocomplete_boolean_choice);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/notify room text", prefs_autocomplete_boolean_choice);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/notify message text", prefs_autocomplete_boolean_choice);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/notify room", notify_room_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/notify message", notify_message_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/notify typing", notify_typing_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2319,13 +2306,13 @@ _notify_autocomplete(const char * const input)
for (i = 0; i < ARRAY_SIZE(boolean_choices); i++) {
result = autocomplete_param_with_func(input, boolean_choices[i],
prefs_autocomplete_boolean_choice);
- if (result != NULL) {
+ if (result) {
return result;
}
}
result = autocomplete_param_with_ac(input, "/notify", notify_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2338,16 +2325,16 @@ _autoaway_autocomplete(const char * const input)
char *result = NULL;
result = autocomplete_param_with_ac(input, "/autoaway mode", autoaway_mode_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/autoaway check",
prefs_autocomplete_boolean_choice);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/autoaway", autoaway_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2361,16 +2348,16 @@ _log_autocomplete(const char * const input)
result = autocomplete_param_with_func(input, "/log rotate",
prefs_autocomplete_boolean_choice);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_func(input, "/log shared",
prefs_autocomplete_boolean_choice);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/log", log_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2383,12 +2370,12 @@ _autoconnect_autocomplete(const char * const input)
char *result = NULL;
result = autocomplete_param_with_func(input, "/autoconnect set", accounts_find_enabled);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/autoconnect", autoconnect_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2401,12 +2388,12 @@ _otr_autocomplete(const char * const input)
char *found = NULL;
found = autocomplete_param_with_func(input, "/otr start", roster_contact_autocomplete);
- if (found != NULL) {
+ if (found) {
return found;
}
found = autocomplete_param_with_ac(input, "/otr log", otr_log_ac, TRUE);
- if (found != NULL) {
+ if (found) {
return found;
}
@@ -2421,7 +2408,7 @@ _otr_autocomplete(const char * const input)
found = autocomplete_param_with_func(input, beginning->str, roster_contact_autocomplete);
g_string_free(beginning, TRUE);
- if (found != NULL) {
+ if (found) {
g_strfreev(args);
return found;
}
@@ -2430,18 +2417,18 @@ _otr_autocomplete(const char * const input)
g_strfreev(args);
found = autocomplete_param_with_ac(input, "/otr policy", otr_policy_ac, TRUE);
- if (found != NULL) {
+ if (found) {
return found;
}
found = autocomplete_param_with_func(input, "/otr warn",
prefs_autocomplete_boolean_choice);
- if (found != NULL) {
+ if (found) {
return found;
}
found = autocomplete_param_with_ac(input, "/otr", otr_ac, TRUE);
- if (found != NULL) {
+ if (found) {
return found;
}
@@ -2452,24 +2439,25 @@ static char *
_theme_autocomplete(const char * const input)
{
char *result = NULL;
- if ((strncmp(input, "/theme set ", 11) == 0) && (strlen(input) > 11)) {
+ if ((strncmp(input, "/theme load ", 12) == 0) && (strlen(input) > 12)) {
if (theme_load_ac == NULL) {
theme_load_ac = autocomplete_new();
GSList *themes = theme_list();
- while (themes != NULL) {
- autocomplete_add(theme_load_ac, themes->data);
- themes = g_slist_next(themes);
+ GSList *curr = themes;
+ while (curr) {
+ autocomplete_add(theme_load_ac, curr->data);
+ curr = g_slist_next(curr);
}
- g_slist_free(themes);
+ g_slist_free_full(themes, g_free);
autocomplete_add(theme_load_ac, "default");
}
- result = autocomplete_param_with_ac(input, "/theme set", theme_load_ac, TRUE);
- if (result != NULL) {
+ result = autocomplete_param_with_ac(input, "/theme load", theme_load_ac, TRUE);
+ if (result) {
return result;
}
}
result = autocomplete_param_with_ac(input, "/theme", theme_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2488,24 +2476,24 @@ _resource_autocomplete(const char * const input)
if (contact) {
Autocomplete ac = p_contact_resource_ac(contact);
found = autocomplete_param_with_ac(input, "/resource set", ac, FALSE);
- if (found != NULL) {
+ if (found) {
return found;
}
}
}
found = autocomplete_param_with_func(input, "/resource title", prefs_autocomplete_boolean_choice);
- if (found != NULL) {
+ if (found) {
return found;
}
found = autocomplete_param_with_func(input, "/resource message", prefs_autocomplete_boolean_choice);
- if (found != NULL) {
+ if (found) {
return found;
}
found = autocomplete_param_with_ac(input, "/resource", resource_ac, FALSE);
- if (found != NULL) {
+ if (found) {
return found;
}
@@ -2518,17 +2506,17 @@ _titlebar_autocomplete(const char * const input)
char *found = NULL;
found = autocomplete_param_with_func(input, "/titlebar show", prefs_autocomplete_boolean_choice);
- if (found != NULL) {
+ if (found) {
return found;
}
found = autocomplete_param_with_func(input, "/titlebar goodbye", prefs_autocomplete_boolean_choice);
- if (found != NULL) {
+ if (found) {
return found;
}
found = autocomplete_param_with_ac(input, "/titlebar", titlebar_ac, FALSE);
- if (found != NULL) {
+ if (found) {
return found;
}
@@ -2541,12 +2529,12 @@ _inpblock_autocomplete(const char * const input)
char *found = NULL;
found = autocomplete_param_with_func(input, "/inpblock dynamic", prefs_autocomplete_boolean_choice);
- if (found != NULL) {
+ if (found) {
return found;
}
found = autocomplete_param_with_ac(input, "/inpblock", inpblock_ac, FALSE);
- if (found != NULL) {
+ if (found) {
return found;
}
@@ -2567,13 +2555,13 @@ _form_autocomplete(const char * const input)
DataForm *form = confwin->form;
if (form) {
found = autocomplete_param_with_ac(input, "/form help", form->tag_ac, TRUE);
- if (found != NULL) {
+ if (found) {
return found;
}
}
found = autocomplete_param_with_ac(input, "/form", form_ac, TRUE);
- if (found != NULL) {
+ if (found) {
return found;
}
@@ -2656,13 +2644,51 @@ _occupants_autocomplete(const char * const input)
{
char *found = NULL;
+ found = autocomplete_param_with_ac(input, "/occupants default show", occupants_show_ac, TRUE);
+ if (found) {
+ return found;
+ }
+
+ found = autocomplete_param_with_ac(input, "/occupants default hide", occupants_show_ac, TRUE);
+ if (found) {
+ return found;
+ }
+
found = autocomplete_param_with_ac(input, "/occupants default", occupants_default_ac, TRUE);
- if (found != NULL) {
+ if (found) {
+ return found;
+ }
+
+ found = autocomplete_param_with_ac(input, "/occupants show", occupants_show_ac, TRUE);
+ if (found) {
+ return found;
+ }
+
+ found = autocomplete_param_with_ac(input, "/occupants hide", occupants_show_ac, TRUE);
+ if (found) {
return found;
}
found = autocomplete_param_with_ac(input, "/occupants", occupants_ac, TRUE);
- if (found != NULL) {
+ if (found) {
+ return found;
+ }
+
+ return NULL;
+}
+
+static char *
+_time_autocomplete(const char * const input)
+{
+ char *found = NULL;
+
+ found = autocomplete_param_with_ac(input, "/time statusbar", time_statusbar_ac, TRUE);
+ if (found) {
+ return found;
+ }
+
+ found = autocomplete_param_with_ac(input, "/time", time_ac, TRUE);
+ if (found) {
return found;
}
@@ -2678,9 +2704,9 @@ _kick_autocomplete(const char * const input)
ProfMucWin *mucwin = wins_get_current_muc();
Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
- if (nick_ac != NULL) {
+ if (nick_ac) {
result = autocomplete_param_with_ac(input, "/kick", nick_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
}
@@ -2698,9 +2724,9 @@ _ban_autocomplete(const char * const input)
ProfMucWin *mucwin = wins_get_current_muc();
Autocomplete jid_ac = muc_roster_jid_ac(mucwin->roomjid);
- if (jid_ac != NULL) {
+ if (jid_ac) {
result = autocomplete_param_with_ac(input, "/ban", jid_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
}
@@ -2729,7 +2755,7 @@ _affiliation_autocomplete(const char * const input)
result = autocomplete_param_with_ac(input, beginning->str, jid_ac, TRUE);
g_string_free(beginning, TRUE);
- if (result != NULL) {
+ if (result) {
g_strfreev(args);
return result;
}
@@ -2739,17 +2765,17 @@ _affiliation_autocomplete(const char * const input)
}
result = autocomplete_param_with_ac(input, "/affiliation set", affiliation_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/affiliation list", affiliation_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/affiliation", privilege_cmd_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2776,7 +2802,7 @@ _role_autocomplete(const char * const input)
result = autocomplete_param_with_ac(input, beginning->str, nick_ac, TRUE);
g_string_free(beginning, TRUE);
- if (result != NULL) {
+ if (result) {
g_strfreev(args);
return result;
}
@@ -2786,17 +2812,17 @@ _role_autocomplete(const char * const input)
}
result = autocomplete_param_with_ac(input, "/role set", role_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/role list", role_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/role", privilege_cmd_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2809,22 +2835,45 @@ _statuses_autocomplete(const char * const input)
char *result = NULL;
result = autocomplete_param_with_ac(input, "/statuses console", statuses_setting_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/statuses chat", statuses_setting_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/statuses muc", statuses_setting_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/statuses", statuses_ac, TRUE);
- if (result != NULL) {
+ if (result) {
+ return result;
+ }
+
+ return NULL;
+}
+
+static char *
+_receipts_autocomplete(const char * const input)
+{
+ char *result = NULL;
+
+ result = autocomplete_param_with_func(input, "/receipts send", prefs_autocomplete_boolean_choice);
+ if (result) {
+ return result;
+ }
+
+ result = autocomplete_param_with_func(input, "/receipts request", prefs_autocomplete_boolean_choice);
+ if (result) {
+ return result;
+ }
+
+ result = autocomplete_param_with_ac(input, "/receipts", receipts_ac, TRUE);
+ if (result) {
return result;
}
@@ -2837,12 +2886,12 @@ _alias_autocomplete(const char * const input)
char *result = NULL;
result = autocomplete_param_with_ac(input, "/alias remove", aliases_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
result = autocomplete_param_with_ac(input, "/alias", alias_ac, TRUE);
- if (result != NULL) {
+ if (result) {
return result;
}
@@ -2860,7 +2909,7 @@ _connect_autocomplete(const char * const input)
if ((strncmp(input, "/connect", 8) == 0) && (result == TRUE)) {
GString *beginning = g_string_new("/connect ");
g_string_append(beginning, args[0]);
- if (args[1] != NULL && args[2] != NULL) {
+ if (args[1] && args[2]) {
g_string_append(beginning, " ");
g_string_append(beginning, args[1]);
g_string_append(beginning, " ");
@@ -2868,7 +2917,7 @@ _connect_autocomplete(const char * const input)
}
found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE);
g_string_free(beginning, TRUE);
- if (found != NULL) {
+ if (found) {
g_strfreev(args);
return found;
}
@@ -2877,7 +2926,7 @@ _connect_autocomplete(const char * const input)
g_strfreev(args);
found = autocomplete_param_with_func(input, "/connect", accounts_find_enabled);
- if (found != NULL) {
+ if (found) {
return found;
}
@@ -2891,7 +2940,7 @@ _join_autocomplete(const char * const input)
gboolean result = FALSE;
found = autocomplete_param_with_func(input, "/join", bookmark_find);
- if (found != NULL) {
+ if (found) {
return found;
}
@@ -2900,7 +2949,7 @@ _join_autocomplete(const char * const input)
if ((strncmp(input, "/join", 5) == 0) && (result == TRUE)) {
GString *beginning = g_string_new("/join ");
g_string_append(beginning, args[0]);
- if (args[1] != NULL && args[2] != NULL) {
+ if (args[1] && args[2]) {
g_string_append(beginning, " ");
g_string_append(beginning, args[1]);
g_string_append(beginning, " ");
@@ -2908,7 +2957,7 @@ _join_autocomplete(const char * const input)
}
found = autocomplete_param_with_ac(input, beginning->str, join_property_ac, TRUE);
g_string_free(beginning, TRUE);
- if (found != NULL) {
+ if (found) {
g_strfreev(args);
return found;
}
@@ -2935,14 +2984,14 @@ _account_autocomplete(const char * const input)
g_string_append(beginning, args[2]);
found = autocomplete_param_with_ac(input, beginning->str, otr_policy_ac, TRUE);
g_string_free(beginning, TRUE);
- if (found != NULL) {
+ if (found) {
g_strfreev(args);
return found;
}
} else {
found = autocomplete_param_with_ac(input, beginning->str, account_set_ac, TRUE);
g_string_free(beginning, TRUE);
- if (found != NULL) {
+ if (found) {
g_strfreev(args);
return found;
}
@@ -2954,7 +3003,7 @@ _account_autocomplete(const char * const input)
g_string_append(beginning, args[1]);
found = autocomplete_param_with_ac(input, beginning->str, account_clear_ac, TRUE);
g_string_free(beginning, TRUE);
- if (found != NULL) {
+ if (found) {
g_strfreev(args);
return found;
}
@@ -2974,7 +3023,7 @@ _account_autocomplete(const char * const input)
for (i = 0; i < ARRAY_SIZE(account_choice); i++) {
found = autocomplete_param_with_func(input, account_choice[i], accounts_find_all);
- if (found != NULL) {
+ if (found) {
return found;
}
}
@@ -2982,3 +3031,55 @@ _account_autocomplete(const char * const input)
found = autocomplete_param_with_ac(input, "/account", account_ac, TRUE);
return found;
}
+
+static int
+_cmp_command(Command *cmd1, Command *cmd2)
+{
+ return g_strcmp0(cmd1->cmd, cmd2->cmd);
+}
+
+void
+command_docgen(void)
+{
+ GList *cmds = NULL;
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(command_defs); i++) {
+ Command *pcmd = command_defs+i;
+ cmds = g_list_insert_sorted(cmds, pcmd, (GCompareFunc)_cmp_command);
+ }
+
+ FILE *toc_fragment = fopen("toc_fragment.html", "w");
+ FILE *main_fragment = fopen("main_fragment.html", "w");
+
+ fputs("- \n", toc_fragment);
+ fputs("
\n", main_fragment);
+
+ GList *curr = cmds;
+ while (curr) {
+ Command *pcmd = curr->data;
+
+ fprintf(toc_fragment, "%s,\n", &pcmd->cmd[1], pcmd->cmd);
+
+ fprintf(main_fragment, "\n", &pcmd->cmd[1]);
+ fprintf(main_fragment, "%s
\n", pcmd->cmd);
+ fputs("Usage:
\n", main_fragment);
+ fprintf(main_fragment, "%s
\n", pcmd->help.usage);
+
+ fputs("Details:
\n", main_fragment);
+ fputs("", main_fragment);
+ int i = 2;
+ while (pcmd->help.long_help[i]) {
+ fprintf(main_fragment, "%s\n", pcmd->help.long_help[i++]);
+ }
+ fputs("
\nback to top
\n", main_fragment);
+ fputs("\n", main_fragment);
+
+ curr = g_list_next(curr);
+ }
+
+ fputs("\n", toc_fragment);
+
+ fclose(toc_fragment);
+ fclose(main_fragment);
+ g_list_free(cmds);
+}
diff --git a/src/command/command.h b/src/command/command.h
index ffbccfa4..b500404b 100644
--- a/src/command/command.h
+++ b/src/command/command.h
@@ -1,7 +1,7 @@
/*
* command.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -66,4 +66,6 @@ void cmd_history_append(char *inp);
char *cmd_history_previous(char *inp);
char *cmd_history_next(char *inp);
+void command_docgen(void);
+
#endif
diff --git a/src/command/commands.c b/src/command/commands.c
index 02910f99..c5350519 100644
--- a/src/command/commands.c
+++ b/src/command/commands.c
@@ -1,7 +1,7 @@
/*
* commands.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -38,10 +38,8 @@
#include
#include
#include
+#include
#include
-#ifdef HAVE_LIBOTR
-#include
-#endif
#include "chat_session.h"
#include "command/commands.h"
@@ -67,12 +65,13 @@
#include "xmpp/bookmark.h"
#include "ui/ui.h"
#include "ui/windows.h"
+#include "event/client_events.h"
+#include "event/ui_events.h"
static void _update_presence(const resource_presence_t presence,
const char * const show, gchar **args);
static gboolean _cmd_set_boolean_preference(gchar *arg, struct cmd_help_t help,
const char * const display, preference_t pref);
-static int _strtoi(char *str, int *saveptr, int min, int max);
static void _cmd_show_filtered_help(char *heading, gchar *cmd_filter[], int filter_size);
static gint _compare_commands(Command *a, Command *b);
static void _who_room(gchar **args, struct cmd_help_t help);
@@ -81,115 +80,178 @@ static void _who_roster(gchar **args, struct cmd_help_t help);
extern GHashTable *commands;
gboolean
-cmd_connect(gchar **args, struct cmd_help_t help)
+cmd_execute_default(const char * inp)
{
- gboolean result = FALSE;
+ // handle escaped commands - treat as normal message
+ if (g_str_has_prefix(inp, "//")) {
+ inp++;
- jabber_conn_status_t conn_status = jabber_get_connection_status();
-
- if ((conn_status != JABBER_DISCONNECTED) && (conn_status != JABBER_STARTED)) {
- cons_show("You are either connected already, or a login is in process.");
- result = TRUE;
- } else {
- gchar *opt_keys[] = { "server", "port", NULL };
- gboolean parsed;
-
- GHashTable *options = parse_options(&args[args[0] ? 1 : 0], opt_keys, &parsed);
- if (!parsed) {
- cons_show("Usage: %s", help.usage);
- cons_show("");
- return TRUE;
- }
-
- char *altdomain = g_hash_table_lookup(options, "server");
-
- int port = 0;
- if (g_hash_table_contains(options, "port")) {
- char *port_str = g_hash_table_lookup(options, "port");
- if (_strtoi(port_str, &port, 1, 65535) != 0) {
- port = 0;
- cons_show("");
- return TRUE;
- }
- }
-
- char *user = args[0];
- char *def = prefs_get_string(PREF_DEFAULT_ACCOUNT);
- if(!user){
- if(def){
- user = def;
- cons_show("Using default account %s.", user);
- } else {
- cons_show("No default account.");
- g_free(def);
- return TRUE;
- }
- }
-
- char *lower = g_utf8_strdown(user, -1);
- char *jid;
- g_free(def);
- def = NULL;
-
- ProfAccount *account = accounts_get_account(lower);
- if (account != NULL) {
- jid = account_create_full_jid(account);
- if(account->eval_password){
- // Evaluate as shell command to retrieve password
- GString *cmd = g_string_append(g_string_new(account->eval_password), " 2>/dev/null");
- FILE *stream = popen(cmd->str, "r");
- g_string_free(cmd, TRUE);
- if(stream){
- // Limit to READ_BUF_SIZE bytes to prevent overflows in the case of a poorly chosen command
- account->password = g_malloc(READ_BUF_SIZE);
- if(!account->password){
- log_error("Failed to allocate enough memory to read eval_password output");
- cons_show("Error evaluating password, see logs for details.");
- return TRUE;
- }
- account->password = fgets(account->password, READ_BUF_SIZE, stream);
- pclose(stream);
- if(!account->password){
- log_error("No result from eval_password.");
- cons_show("Error evaluating password, see logs for details.");
- return TRUE;
- }
- g_strstrip(account->password);
- } else {
- log_error("popen failed when running eval_password.");
- cons_show("Error evaluating password, see logs for details.");
- return TRUE;
- }
- } else if (!account->password) {
- account->password = ui_ask_password();
- }
- cons_show("Connecting with account %s as %s", account->name, jid);
- if(g_hash_table_contains(options, "port") || g_hash_table_contains(options, "server"))
- cons_show("Ignoring extra connect options. Please set them with /account set");
- conn_status = jabber_connect_with_account(account);
- account_free(account);
- } else {
- char *passwd = ui_ask_password();
- jid = strdup(lower);
- cons_show("Connecting as %s", jid);
- conn_status = jabber_connect_with_details(jid, passwd, altdomain, port);
- free(passwd);
- }
- g_free(lower);
-
- if (conn_status == JABBER_DISCONNECTED) {
- cons_show_error("Connection attempt for %s failed.", jid);
- log_info("Connection attempt for %s failed", jid);
- }
-
- options_destroy(options);
-
- free(jid);
-
- result = TRUE;
+ // handle unknown commands
+ } else if ((inp[0] == '/') && (!g_str_has_prefix(inp, "/me "))) {
+ cons_show("Unknown command: %s", inp);
+ cons_alert();
+ return TRUE;
}
- return result;
+ // handle non commands in non chat windows
+ ProfWin *current = wins_get_current();
+ if (current->type != WIN_CHAT && current->type != WIN_MUC && current->type != WIN_PRIVATE) {
+ cons_show("Unknown command: %s", inp);
+ return TRUE;
+ }
+
+ jabber_conn_status_t status = jabber_get_connection_status();
+ if (status != JABBER_CONNECTED) {
+ ui_current_print_line("You are not currently connected.");
+ return TRUE;
+ }
+
+ switch (current->type) {
+ case WIN_CHAT:
+ {
+ ProfChatWin *chatwin = wins_get_current_chat();
+ cl_ev_send_msg(chatwin, inp);
+ break;
+ }
+ case WIN_PRIVATE:
+ {
+ ProfPrivateWin *privatewin = wins_get_current_private();
+ cl_ev_send_priv_msg(privatewin, inp);
+ break;
+ }
+ case WIN_MUC:
+ {
+ ProfMucWin *mucwin = wins_get_current_muc();
+ cl_ev_send_muc_msg(mucwin, inp);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+gboolean
+cmd_execute_alias(const char * const inp, gboolean *ran)
+{
+ if (inp[0] != '/') {
+ ran = FALSE;
+ return TRUE;
+ }
+
+ char *alias = strdup(inp+1);
+ char *value = prefs_get_alias(alias);
+ free(alias);
+ if (value) {
+ *ran = TRUE;
+ return cmd_process_input(value);
+ }
+
+ *ran = FALSE;
+ return TRUE;
+}
+
+gboolean
+cmd_connect(gchar **args, struct cmd_help_t help)
+{
+ jabber_conn_status_t conn_status = jabber_get_connection_status();
+ if ((conn_status != JABBER_DISCONNECTED) && (conn_status != JABBER_STARTED)) {
+ cons_show("You are either connected already, or a login is in process.");
+ return TRUE;
+ }
+
+ gchar *opt_keys[] = { "server", "port", NULL };
+ gboolean parsed;
+
+ GHashTable *options = parse_options(&args[args[0] ? 1 : 0], opt_keys, &parsed);
+ if (!parsed) {
+ cons_show("Usage: %s", help.usage);
+ cons_show("");
+ return TRUE;
+ }
+
+ char *altdomain = g_hash_table_lookup(options, "server");
+
+ int port = 0;
+ if (g_hash_table_contains(options, "port")) {
+ char *port_str = g_hash_table_lookup(options, "port");
+ char *err_msg = NULL;
+ gboolean res = strtoi_range(port_str, &port, 1, 65535, &err_msg);
+ if (!res) {
+ cons_show(err_msg);
+ cons_show("");
+ free(err_msg);
+ port = 0;
+ return TRUE;
+ }
+ }
+
+ char *user = args[0];
+ char *def = prefs_get_string(PREF_DEFAULT_ACCOUNT);
+ if (!user) {
+ if (def) {
+ user = def;
+ cons_show("Using default account %s.", user);
+ } else {
+ cons_show("No default account.");
+ g_free(def);
+ return TRUE;
+ }
+ }
+
+ char *lower = g_utf8_strdown(user, -1);
+ char *jid;
+ g_free(def);
+
+ // connect with account
+ ProfAccount *account = accounts_get_account(lower);
+ if (account) {
+ // use password if set
+ if (account->password) {
+ conn_status = cl_ev_connect_account(account);
+
+ // use eval_password if set
+ } else if (account->eval_password) {
+ gboolean res = account_eval_password(account);
+ if (res) {
+ conn_status = cl_ev_connect_account(account);
+ free(account->password);
+ account->password = NULL;
+ } else {
+ cons_show("Error evaluating password, see logs for details.");
+ g_free(lower);
+ return TRUE;
+ }
+
+ // no account password setting, prompt
+ } else {
+ account->password = ui_ask_password();
+ conn_status = cl_ev_connect_account(account);
+ free(account->password);
+ account->password = NULL;
+ }
+
+ jid = account_create_full_jid(account);
+
+ // connect with JID
+ } else {
+ jid = strdup(lower);
+ char *passwd = ui_ask_password();
+ conn_status = cl_ev_connect_jid(jid, passwd, altdomain, port);
+ free(passwd);
+ }
+
+ if (conn_status == JABBER_DISCONNECTED) {
+ cons_show_error("Connection attempt for %s failed.", jid);
+ log_info("Connection attempt for %s failed", jid);
+ }
+
+ options_destroy(options);
+ g_free(lower);
+ free(jid);
+
+ return TRUE;
}
gboolean
@@ -342,7 +404,7 @@ cmd_account(gchar **args, struct cmd_help_t help)
} else {
accounts_set_jid(account_name, jid->barejid);
cons_show("Updated jid for account %s: %s", account_name, jid->barejid);
- if (jid->resourcepart != NULL) {
+ if (jid->resourcepart) {
accounts_set_resource(account_name, jid->resourcepart);
cons_show("Updated resource for account %s: %s", account_name, jid->resourcepart);
}
@@ -355,8 +417,12 @@ cmd_account(gchar **args, struct cmd_help_t help)
cons_show("");
} else if (strcmp(property, "port") == 0) {
int port;
- if (_strtoi(value, &port, 1, 65535) != 0) {
+ char *err_msg = NULL;
+ gboolean res = strtoi_range(value, &port, 1, 65535, &err_msg);
+ if (!res) {
+ cons_show(err_msg);
cons_show("");
+ free(err_msg);
return TRUE;
} else {
accounts_set_port(account_name, port);
@@ -368,7 +434,7 @@ cmd_account(gchar **args, struct cmd_help_t help)
cons_show("Updated resource for account %s: %s", account_name, value);
cons_show("");
} else if (strcmp(property, "password") == 0) {
- if(accounts_get_account(account_name)->eval_password != NULL) {
+ if(accounts_get_account(account_name)->eval_password) {
cons_show("Cannot set password when eval_password is set.");
} else {
accounts_set_password(account_name, value);
@@ -376,7 +442,7 @@ cmd_account(gchar **args, struct cmd_help_t help)
cons_show("");
}
} else if (strcmp(property, "eval_password") == 0) {
- if(accounts_get_account(account_name)->password != NULL) {
+ if(accounts_get_account(account_name)->password) {
cons_show("Cannot set eval_password when password is set.");
} else {
accounts_set_eval_password(account_name, value);
@@ -410,42 +476,46 @@ cmd_account(gchar **args, struct cmd_help_t help)
}
cons_show("");
} else if (valid_resource_presence_string(property)) {
- int intval;
-
- if (_strtoi(value, &intval, -128, 127) == 0) {
- resource_presence_t presence_type = resource_presence_from_string(property);
- switch (presence_type)
- {
- case (RESOURCE_ONLINE):
- accounts_set_priority_online(account_name, intval);
- break;
- case (RESOURCE_CHAT):
- accounts_set_priority_chat(account_name, intval);
- break;
- case (RESOURCE_AWAY):
- accounts_set_priority_away(account_name, intval);
- break;
- case (RESOURCE_XA):
- accounts_set_priority_xa(account_name, intval);
- break;
- case (RESOURCE_DND):
- accounts_set_priority_dnd(account_name, intval);
- break;
- }
-
- jabber_conn_status_t conn_status = jabber_get_connection_status();
- if (conn_status == JABBER_CONNECTED) {
- char *connected_account = jabber_get_account_name();
- resource_presence_t last_presence = accounts_get_last_presence(connected_account);
-
- if (presence_type == last_presence) {
- char *message = jabber_get_presence_message();
- presence_update(last_presence, message, 0);
- }
- }
- cons_show("Updated %s priority for account %s: %s", property, account_name, value);
- cons_show("");
+ int intval;
+ char *err_msg = NULL;
+ gboolean res = strtoi_range(value, &intval, -128, 127, &err_msg);
+ if (res) {
+ resource_presence_t presence_type = resource_presence_from_string(property);
+ switch (presence_type)
+ {
+ case (RESOURCE_ONLINE):
+ accounts_set_priority_online(account_name, intval);
+ break;
+ case (RESOURCE_CHAT):
+ accounts_set_priority_chat(account_name, intval);
+ break;
+ case (RESOURCE_AWAY):
+ accounts_set_priority_away(account_name, intval);
+ break;
+ case (RESOURCE_XA):
+ accounts_set_priority_xa(account_name, intval);
+ break;
+ case (RESOURCE_DND):
+ accounts_set_priority_dnd(account_name, intval);
+ break;
}
+
+ jabber_conn_status_t conn_status = jabber_get_connection_status();
+ if (conn_status == JABBER_CONNECTED) {
+ char *connected_account = jabber_get_account_name();
+ resource_presence_t last_presence = accounts_get_last_presence(connected_account);
+
+ if (presence_type == last_presence) {
+ char *message = jabber_get_presence_message();
+ cl_ev_presence_send(last_presence, message, 0);
+ }
+ }
+ cons_show("Updated %s priority for account %s: %s", property, account_name, value);
+ cons_show("");
+ } else {
+ cons_show(err_msg);
+ free(err_msg);
+ }
} else {
cons_show("Invalid property: %s", property);
cons_show("");
@@ -652,10 +722,14 @@ gboolean
cmd_win(gchar **args, struct cmd_help_t help)
{
int num = atoi(args[0]);
- gboolean switched = ui_switch_win(num);
- if (switched == FALSE) {
+
+ ProfWin *window = wins_get_by_num(num);
+ if (!window) {
cons_show("Window %d does not exist.", num);
+ } else {
+ ui_ev_focus_win(window);
}
+
return TRUE;
}
@@ -681,7 +755,7 @@ cmd_help(gchar **args, struct cmd_help_t help)
}
GList *curr = ordered_commands;
- while (curr != NULL) {
+ while (curr) {
Command *cmd = curr->data;
cons_show("%-12s: %s", cmd->cmd, cmd->help.short_help);
curr = g_list_next(curr);
@@ -711,7 +785,7 @@ cmd_help(gchar **args, struct cmd_help_t help)
"/rooms", "/tiny", "/who", "/nick", "/privileges", "/info", "/occupants" };
_cmd_show_filtered_help("Groupchat commands", filter, ARRAY_SIZE(filter));
- } else if (strcmp(args[0], "presence") == 0) {
+ } else if (strcmp(args[0], "presences") == 0) {
gchar *filter[] = { "/autoaway", "/away", "/chat", "/dnd",
"/online", "/priority", "/account", "/status", "/statuses", "/who",
"/xa" };
@@ -727,7 +801,7 @@ cmd_help(gchar **args, struct cmd_help_t help)
} else if (strcmp(args[0], "settings") == 0) {
gchar *filter[] = { "/account", "/autoaway", "/autoping", "/autoconnect", "/beep",
- "/chlog", "/flash", "/gone", "/grlog", "/history", "/intype",
+ "/carbons", "/chlog", "/flash", "/gone", "/grlog", "/history", "/intype",
"/log", "/mouse", "/notify", "/outtype", "/prefs", "/priority",
"/reconnect", "/roster", "/splash", "/states", "/statuses", "/theme",
"/titlebar", "/vercheck", "/privileges", "/occupants", "/presence", "/wrap" };
@@ -743,12 +817,12 @@ cmd_help(gchar **args, struct cmd_help_t help)
const gchar **help_text = NULL;
Command *command = g_hash_table_lookup(commands, cmd_with_slash);
- if (command != NULL) {
+ if (command) {
help_text = command->help.long_help;
}
cons_show("");
- if (help_text != NULL) {
+ if (help_text) {
ProfWin *console = wins_get_console();
ui_show_lines(console, help_text);
} else {
@@ -819,7 +893,7 @@ cmd_theme(gchar **args, struct cmd_help_t help)
g_slist_free_full(themes, g_free);
// load a theme
- } else if (g_strcmp0(args[0], "set") == 0) {
+ } else if (g_strcmp0(args[0], "load") == 0) {
if (args[1] == NULL) {
cons_show("Usage: %s", help.usage);
} else if (theme_load(args[1])) {
@@ -854,13 +928,13 @@ cmd_theme(gchar **args, struct cmd_help_t help)
static void
_who_room(gchar **args, struct cmd_help_t help)
{
- if ((g_strv_length(args) == 2) && (args[1] != NULL)) {
+ if ((g_strv_length(args) == 2) && args[1]) {
cons_show("Argument group is not applicable to chat rooms.");
return;
}
// bad arg
- if (args[0] != NULL &&
+ if (args[0] &&
(g_strcmp0(args[0], "online") != 0) &&
(g_strcmp0(args[0], "available") != 0) &&
(g_strcmp0(args[0], "unavailable") != 0) &&
@@ -904,7 +978,7 @@ _who_room(gchar **args, struct cmd_help_t help)
} else if (strcmp("available", presence) == 0) {
GList *filtered = NULL;
- while (occupants != NULL) {
+ while (occupants) {
Occupant *occupant = occupants->data;
if (muc_occupant_available(occupant)) {
filtered = g_list_append(filtered, occupant);
@@ -918,7 +992,7 @@ _who_room(gchar **args, struct cmd_help_t help)
} else if (strcmp("unavailable", presence) == 0) {
GList *filtered = NULL;
- while (occupants != NULL) {
+ while (occupants) {
Occupant *occupant = occupants->data;
if (!muc_occupant_available(occupant)) {
filtered = g_list_append(filtered, occupant);
@@ -932,7 +1006,7 @@ _who_room(gchar **args, struct cmd_help_t help)
} else {
GList *filtered = NULL;
- while (occupants != NULL) {
+ while (occupants) {
Occupant *occupant = occupants->data;
const char *presence_str = string_from_resource_presence(occupant->presence);
if (strcmp(presence_str, presence) == 0) {
@@ -986,7 +1060,7 @@ _who_roster(gchar **args, struct cmd_help_t help)
char *presence = args[0];
// bad arg
- if ((presence != NULL)
+ if (presence
&& (strcmp(presence, "online") != 0)
&& (strcmp(presence, "available") != 0)
&& (strcmp(presence, "unavailable") != 0)
@@ -1001,13 +1075,13 @@ _who_roster(gchar **args, struct cmd_help_t help)
}
char *group = NULL;
- if ((g_strv_length(args) == 2) && (args[1] != NULL)) {
+ if ((g_strv_length(args) == 2) && args[1]) {
group = args[1];
}
cons_show("");
GSList *list = NULL;
- if (group != NULL) {
+ if (group) {
list = roster_get_group(group);
if (list == NULL) {
cons_show("No such group: %s.", group);
@@ -1023,7 +1097,7 @@ _who_roster(gchar **args, struct cmd_help_t help)
// no arg, show all contacts
if ((presence == NULL) || (g_strcmp0(presence, "any") == 0)) {
- if (group != NULL) {
+ if (group) {
if (list == NULL) {
cons_show("No contacts in group %s.", group);
} else {
@@ -1043,15 +1117,16 @@ _who_roster(gchar **args, struct cmd_help_t help)
} else if (strcmp("available", presence) == 0) {
GSList *filtered = NULL;
- while (list != NULL) {
- PContact contact = list->data;
+ GSList *curr = list;
+ while (curr) {
+ PContact contact = curr->data;
if (p_contact_is_available(contact)) {
filtered = g_slist_append(filtered, contact);
}
- list = g_slist_next(list);
+ curr = g_slist_next(curr);
}
- if (group != NULL) {
+ if (group) {
if (filtered == NULL) {
cons_show("No contacts in group %s are %s.", group, presence);
} else {
@@ -1066,20 +1141,22 @@ _who_roster(gchar **args, struct cmd_help_t help)
cons_show_contacts(filtered);
}
}
+ g_slist_free(filtered);
// unavailable
} else if (strcmp("unavailable", presence) == 0) {
GSList *filtered = NULL;
- while (list != NULL) {
- PContact contact = list->data;
+ GSList *curr = list;
+ while (curr) {
+ PContact contact = curr->data;
if (!p_contact_is_available(contact)) {
filtered = g_slist_append(filtered, contact);
}
- list = g_slist_next(list);
+ curr = g_slist_next(curr);
}
- if (group != NULL) {
+ if (group) {
if (filtered == NULL) {
cons_show("No contacts in group %s are %s.", group, presence);
} else {
@@ -1094,20 +1171,22 @@ _who_roster(gchar **args, struct cmd_help_t help)
cons_show_contacts(filtered);
}
}
+ g_slist_free(filtered);
// online, available resources
} else if (strcmp("online", presence) == 0) {
GSList *filtered = NULL;
- while (list != NULL) {
- PContact contact = list->data;
+ GSList *curr = list;
+ while (curr) {
+ PContact contact = curr->data;
if (p_contact_has_available_resource(contact)) {
filtered = g_slist_append(filtered, contact);
}
- list = g_slist_next(list);
+ curr = g_slist_next(curr);
}
- if (group != NULL) {
+ if (group) {
if (filtered == NULL) {
cons_show("No contacts in group %s are %s.", group, presence);
} else {
@@ -1122,20 +1201,22 @@ _who_roster(gchar **args, struct cmd_help_t help)
cons_show_contacts(filtered);
}
}
+ g_slist_free(filtered);
// offline, no available resources
} else if (strcmp("offline", presence) == 0) {
GSList *filtered = NULL;
- while (list != NULL) {
- PContact contact = list->data;
+ GSList *curr = list;
+ while (curr) {
+ PContact contact = curr->data;
if (!p_contact_has_available_resource(contact)) {
filtered = g_slist_append(filtered, contact);
}
- list = g_slist_next(list);
+ curr = g_slist_next(curr);
}
- if (group != NULL) {
+ if (group) {
if (filtered == NULL) {
cons_show("No contacts in group %s are %s.", group, presence);
} else {
@@ -1150,20 +1231,22 @@ _who_roster(gchar **args, struct cmd_help_t help)
cons_show_contacts(filtered);
}
}
+ g_slist_free(filtered);
// show specific status
} else {
GSList *filtered = NULL;
- while (list != NULL) {
- PContact contact = list->data;
+ GSList *curr = list;
+ while (curr) {
+ PContact contact = curr->data;
if (strcmp(p_contact_presence(contact), presence) == 0) {
filtered = g_slist_append(filtered, contact);
}
- list = g_slist_next(list);
+ curr = g_slist_next(curr);
}
- if (group != NULL) {
+ if (group) {
if (filtered == NULL) {
cons_show("No contacts in group %s are %s.", group, presence);
} else {
@@ -1178,6 +1261,7 @@ _who_roster(gchar **args, struct cmd_help_t help)
cons_show_contacts(filtered);
}
}
+ g_slist_free(filtered);
}
g_slist_free(list);
@@ -1218,6 +1302,7 @@ cmd_msg(gchar **args, struct cmd_help_t help)
return TRUE;
}
+ // send private message when in MUC room
if (win_type == WIN_MUC) {
ProfMucWin *mucwin = wins_get_current_muc();
if (muc_roster_contains_nick(mucwin->roomjid, usr)) {
@@ -1225,11 +1310,14 @@ cmd_msg(gchar **args, struct cmd_help_t help)
g_string_append(full_jid, "/");
g_string_append(full_jid, usr);
- if (msg != NULL) {
- message_send_private(full_jid->str, msg);
- ui_outgoing_private_msg("me", full_jid->str, msg);
- } else {
- ui_new_private_win(full_jid->str);
+ ProfPrivateWin *privwin = wins_get_private(full_jid->str);
+ if (!privwin) {
+ privwin = ui_ev_new_private_win(full_jid->str);
+ }
+ ui_ev_focus_win((ProfWin*)privwin);
+
+ if (msg) {
+ cl_ev_send_priv_msg(privwin, msg);
}
g_string_free(full_jid, TRUE);
@@ -1240,85 +1328,30 @@ cmd_msg(gchar **args, struct cmd_help_t help)
return TRUE;
+ // send chat message
} else {
- // get barejid
char *barejid = roster_barejid_from_name(usr);
if (barejid == NULL) {
barejid = usr;
}
- if (msg != NULL) {
-#ifdef HAVE_LIBOTR
- if (otr_is_secure(barejid)) {
- char *encrypted = otr_encrypt_message(barejid, msg);
- if (encrypted != NULL) {
- message_send_chat(barejid, encrypted);
- otr_free_message(encrypted);
- ui_outgoing_chat_msg("me", barejid, msg);
+ ProfChatWin *chatwin = wins_get_chat(barejid);
+ if (!chatwin) {
+ chatwin = ui_ev_new_chat_win(barejid);
+ }
+ ui_ev_focus_win((ProfWin*)chatwin);
- if (((win_type == WIN_CHAT) || (win_type == WIN_CONSOLE)) && prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
- char *pref_otr_log = prefs_get_string(PREF_OTR_LOG);
- if (strcmp(pref_otr_log, "on") == 0) {
- chat_log_chat(jidp->barejid, barejid, msg, PROF_OUT_LOG, NULL);
- } else if (strcmp(pref_otr_log, "redact") == 0) {
- chat_log_chat(jidp->barejid, barejid, "[redacted]", PROF_OUT_LOG, NULL);
- }
- prefs_free_string(pref_otr_log);
- jid_destroy(jidp);
- }
- } else {
- cons_show_error("Failed to encrypt and send message,");
- }
- } else {
- prof_otrpolicy_t policy = otr_get_policy(barejid);
-
- if (policy == PROF_OTRPOLICY_ALWAYS) {
- cons_show_error("Failed to send message. Please check OTR policy");
- return TRUE;
- } else if (policy == PROF_OTRPOLICY_OPPORTUNISTIC) {
- GString *otr_message = g_string_new(msg);
- g_string_append(otr_message, OTRL_MESSAGE_TAG_BASE);
- g_string_append(otr_message, OTRL_MESSAGE_TAG_V2);
- message_send_chat(barejid, otr_message->str);
-
- g_string_free(otr_message, TRUE);
- } else {
- message_send_chat(barejid, msg);
- }
- ui_outgoing_chat_msg("me", barejid, msg);
-
- if (((win_type == WIN_CHAT) || (win_type == WIN_CONSOLE)) && prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
- chat_log_chat(jidp->barejid, barejid, msg, PROF_OUT_LOG, NULL);
- jid_destroy(jidp);
- }
- }
- return TRUE;
-#else
- message_send_chat(barejid, msg);
- ui_outgoing_chat_msg("me", barejid, msg);
-
- if (((win_type == WIN_CHAT) || (win_type == WIN_CONSOLE)) && prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
- chat_log_chat(jidp->barejid, barejid, msg, PROF_OUT_LOG, NULL);
- jid_destroy(jidp);
- }
- return TRUE;
-#endif
-
- } else { // msg == NULL
- ui_new_chat_win(barejid);
+ if (msg) {
+ cl_ev_send_msg(chatwin, msg);
+ } else {
#ifdef HAVE_LIBOTR
if (otr_is_secure(barejid)) {
ui_gone_secure(barejid, otr_is_trusted(barejid));
}
#endif
- return TRUE;
}
+
+ return TRUE;
}
}
@@ -1336,9 +1369,9 @@ cmd_group(gchar **args, struct cmd_help_t help)
if (args[0] == NULL) {
GSList *groups = roster_get_groups();
GSList *curr = groups;
- if (curr != NULL) {
+ if (curr) {
cons_show("Groups:");
- while (curr != NULL) {
+ while (curr) {
cons_show(" %s", curr->data);
curr = g_slist_next(curr);
}
@@ -1455,11 +1488,14 @@ cmd_roster(gchar **args, struct cmd_help_t help)
// set roster size
} else if (g_strcmp0(args[0], "size") == 0) {
- int intval = 0;
if (!args[1]) {
cons_show("Usage: %s", help.usage);
return TRUE;
- } else if (_strtoi(args[1], &intval, 1, 99) == 0) {
+ }
+ int intval = 0;
+ char *err_msg = NULL;
+ gboolean res = strtoi_range(args[1], &intval, 1, 99, &err_msg);
+ if (res) {
prefs_set_roster_size(intval);
cons_show("Roster screen size set to: %d%%", intval);
if (prefs_get_boolean(PREF_ROSTER)) {
@@ -1467,6 +1503,8 @@ cmd_roster(gchar **args, struct cmd_help_t help)
}
return TRUE;
} else {
+ cons_show(err_msg);
+ free(err_msg);
return TRUE;
}
@@ -1701,35 +1739,35 @@ cmd_status(gchar **args, struct cmd_help_t help)
switch (win_type)
{
case WIN_MUC:
- if (usr != NULL) {
+ if (usr) {
ProfMucWin *mucwin = wins_get_current_muc();
ProfWin *window = (ProfWin*) mucwin;
Occupant *occupant = muc_roster_item(mucwin->roomjid, usr);
if (occupant) {
win_show_occupant(window, occupant);
} else {
- win_save_vprint(window, '-', NULL, 0, 0, "", "No such participant \"%s\" in room.", usr);
+ win_vprint(window, '-', NULL, 0, 0, "", "No such participant \"%s\" in room.", usr);
}
} else {
ui_current_print_line("You must specify a nickname.");
}
break;
case WIN_CHAT:
- if (usr != NULL) {
+ if (usr) {
ui_current_print_line("No parameter required when in chat.");
} else {
ProfChatWin *chatwin = wins_get_current_chat();
ProfWin *window = (ProfWin*) chatwin;
PContact pcontact = roster_get_contact(chatwin->barejid);
- if (pcontact != NULL) {
+ if (pcontact) {
win_show_contact(window, pcontact);
} else {
- win_save_println(window, "Error getting contact info.");
+ win_println(window, "Error getting contact info.");
}
}
break;
case WIN_PRIVATE:
- if (usr != NULL) {
+ if (usr) {
ui_current_print_line("No parameter required when in chat.");
} else {
ProfPrivateWin *privatewin = wins_get_current_private();
@@ -1739,13 +1777,13 @@ cmd_status(gchar **args, struct cmd_help_t help)
if (occupant) {
win_show_occupant(window, occupant);
} else {
- win_save_println(window, "Error getting contact info.");
+ win_println(window, "Error getting contact info.");
}
jid_destroy(jid);
}
break;
case WIN_CONSOLE:
- if (usr != NULL) {
+ if (usr) {
char *usr_jid = roster_barejid_from_name(usr);
if (usr_jid == NULL) {
usr_jid = usr;
@@ -1790,7 +1828,7 @@ cmd_info(gchar **args, struct cmd_help_t help)
}
} else {
ProfMucWin *mucwin = wins_get_current_muc();
- iq_room_info_request(mucwin->roomjid);
+ iq_room_info_request(mucwin->roomjid, TRUE);
ui_show_room_info(mucwin);
return TRUE;
}
@@ -1802,10 +1840,10 @@ cmd_info(gchar **args, struct cmd_help_t help)
ProfChatWin *chatwin = wins_get_current_chat();
ProfWin *window = (ProfWin*) chatwin;
PContact pcontact = roster_get_contact(chatwin->barejid);
- if (pcontact != NULL) {
+ if (pcontact) {
win_show_info(window, pcontact);
} else {
- win_save_println(window, "Error getting contact info.");
+ win_println(window, "Error getting contact info.");
}
}
break;
@@ -1820,7 +1858,7 @@ cmd_info(gchar **args, struct cmd_help_t help)
if (occupant) {
win_show_occupant_info(window, jid->barejid, occupant);
} else {
- win_save_println(window, "Error getting contact info.");
+ win_println(window, "Error getting contact info.");
}
jid_destroy(jid);
}
@@ -1832,7 +1870,7 @@ cmd_info(gchar **args, struct cmd_help_t help)
usr_jid = usr;
}
pcontact = roster_get_contact(usr_jid);
- if (pcontact != NULL) {
+ if (pcontact) {
cons_show_info(pcontact);
} else {
cons_show("No such contact \"%s\" in roster.", usr);
@@ -1864,7 +1902,7 @@ cmd_caps(gchar **args, struct cmd_help_t help)
switch (win_type)
{
case WIN_MUC:
- if (args[0] != NULL) {
+ if (args[0]) {
ProfMucWin *mucwin = wins_get_current_muc();
occupant = muc_roster_item(mucwin->roomjid, args[0]);
if (occupant) {
@@ -1880,7 +1918,7 @@ cmd_caps(gchar **args, struct cmd_help_t help)
break;
case WIN_CHAT:
case WIN_CONSOLE:
- if (args[0] != NULL) {
+ if (args[0]) {
Jid *jid = jid_create(args[0]);
if (jid->fulljid == NULL) {
@@ -1904,7 +1942,7 @@ cmd_caps(gchar **args, struct cmd_help_t help)
}
break;
case WIN_PRIVATE:
- if (args[0] != NULL) {
+ if (args[0]) {
cons_show("No parameter needed to /caps when in private chat.");
} else {
ProfPrivateWin *privatewin = wins_get_current_private();
@@ -1939,7 +1977,7 @@ cmd_software(gchar **args, struct cmd_help_t help)
switch (win_type)
{
case WIN_MUC:
- if (args[0] != NULL) {
+ if (args[0]) {
ProfMucWin *mucwin = wins_get_current_muc();
occupant = muc_roster_item(mucwin->roomjid, args[0]);
if (occupant) {
@@ -1955,7 +1993,7 @@ cmd_software(gchar **args, struct cmd_help_t help)
break;
case WIN_CHAT:
case WIN_CONSOLE:
- if (args[0] != NULL) {
+ if (args[0]) {
Jid *jid = jid_create(args[0]);
if (jid == NULL || jid->fulljid == NULL) {
@@ -1969,7 +2007,7 @@ cmd_software(gchar **args, struct cmd_help_t help)
}
break;
case WIN_PRIVATE:
- if (args[0] != NULL) {
+ if (args[0]) {
cons_show("No parameter needed to /software when in private chat.");
} else {
ProfPrivateWin *privatewin = wins_get_current_private();
@@ -1993,8 +2031,24 @@ cmd_join(gchar **args, struct cmd_help_t help)
}
if (args[0] == NULL) {
- cons_show("Usage: %s", help.usage);
- cons_show("");
+ uuid_t uuid;
+ uuid_generate(uuid);
+ char *uuid_str = malloc(sizeof(char) * 37);
+ uuid_unparse_lower(uuid, uuid_str);
+
+ char *account_name = jabber_get_account_name();
+ ProfAccount *account = accounts_get_account(account_name);
+
+ GString *room_str = g_string_new("");
+ g_string_append_printf(room_str, "private-chat-%s@%s", uuid_str, account->muc_service);
+
+ presence_join_room(room_str->str, account->muc_nick, NULL);
+ muc_join(room_str->str, account->muc_nick, NULL, FALSE);
+
+ g_string_free(room_str, TRUE);
+ free(uuid_str);
+ account_free(account);
+
return TRUE;
}
@@ -2013,7 +2067,7 @@ cmd_join(gchar **args, struct cmd_help_t help)
ProfAccount *account = accounts_get_account(account_name);
// full room jid supplied (room@server)
- if (room_arg->localpart != NULL) {
+ if (room_arg->localpart) {
room = args[0];
// server not supplied (room), use account preference
@@ -2041,10 +2095,15 @@ cmd_join(gchar **args, struct cmd_help_t help)
options_destroy(options);
// In the case that a nick wasn't provided by the optional args...
- if (nick == NULL) {
+ if (!nick) {
nick = account->muc_nick;
}
+ // When no password, check for invite with password
+ if (!passwd) {
+ passwd = muc_invite_password(room);
+ }
+
if (!muc_active(room)) {
presence_join_room(room, nick, passwd);
muc_join(room, nick, passwd, FALSE);
@@ -2083,7 +2142,7 @@ cmd_invite(gchar **args, struct cmd_help_t help)
ProfMucWin *mucwin = wins_get_current_muc();
message_send_invite(mucwin->roomjid, usr_jid, reason);
- if (reason != NULL) {
+ if (reason) {
cons_show("Room invite sent, contact: %s, room: %s, reason: \"%s\".",
contact, mucwin->roomjid, reason);
} else {
@@ -2368,7 +2427,7 @@ cmd_form(gchar **args, struct cmd_help_t help)
if (g_strcmp0(args[0], "help") == 0) {
char *tag = args[1];
- if (tag != NULL) {
+ if (tag) {
ui_show_form_field_help(confwin, tag);
} else {
ui_show_form_help(confwin);
@@ -2376,7 +2435,7 @@ cmd_form(gchar **args, struct cmd_help_t help)
const gchar **help_text = NULL;
Command *command = g_hash_table_lookup(commands, "/form");
- if (command != NULL) {
+ if (command) {
help_text = command->help.long_help;
}
@@ -2400,12 +2459,11 @@ cmd_form(gchar **args, struct cmd_help_t help)
cmd_autocomplete_remove_form_fields(confwin->form);
}
wins_close_current();
- ProfWin *current = (ProfWin*)wins_get_muc(confwin->roomjid);
- if (current == NULL) {
- current = wins_get_console();
+ ProfWin *new_current = (ProfWin*)wins_get_muc(confwin->roomjid);
+ if (!new_current) {
+ new_current = wins_get_console();
}
- int num = wins_get_num(current);
- ui_switch_win(num);
+ ui_ev_focus_win(new_current);
}
return TRUE;
@@ -2435,7 +2493,7 @@ cmd_kick(gchar **args, struct cmd_help_t help)
char *reason = args[1];
iq_room_kick_occupant(mucwin->roomjid, nick, reason);
} else {
- win_save_vprint((ProfWin*) mucwin, '!', NULL, 0, 0, "", "Occupant does not exist: %s", nick);
+ win_vprint((ProfWin*) mucwin, '!', NULL, 0, 0, "", "Occupant does not exist: %s", nick);
}
} else {
cons_show("Usage: %s", help.usage);
@@ -2494,10 +2552,10 @@ cmd_subject(gchar **args, struct cmd_help_t help)
if (args[0] == NULL) {
char *subject = muc_subject(mucwin->roomjid);
if (subject) {
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Room subject: ");
- win_save_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", subject);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Room subject: ");
+ win_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", subject);
} else {
- win_save_print(window, '!', NULL, 0, THEME_ROOMINFO, "", "Room has no subject");
+ win_print(window, '!', NULL, 0, THEME_ROOMINFO, "", "Room has no subject");
}
return TRUE;
}
@@ -2543,7 +2601,7 @@ cmd_affiliation(gchar **args, struct cmd_help_t help)
}
char *affiliation = args[1];
- if ((affiliation != NULL) &&
+ if (affiliation &&
(g_strcmp0(affiliation, "owner") != 0) &&
(g_strcmp0(affiliation, "admin") != 0) &&
(g_strcmp0(affiliation, "member") != 0) &&
@@ -2562,7 +2620,7 @@ cmd_affiliation(gchar **args, struct cmd_help_t help)
iq_room_affiliation_list(mucwin->roomjid, "member");
iq_room_affiliation_list(mucwin->roomjid, "outcast");
} else if (g_strcmp0(affiliation, "none") == 0) {
- win_save_print((ProfWin*) mucwin, '!', NULL, 0, 0, "", "Cannot list users with no affiliation.");
+ win_print((ProfWin*) mucwin, '!', NULL, 0, 0, "", "Cannot list users with no affiliation.");
} else {
iq_room_affiliation_list(mucwin->roomjid, affiliation);
}
@@ -2613,7 +2671,7 @@ cmd_role(gchar **args, struct cmd_help_t help)
}
char *role = args[1];
- if ((role != NULL ) &&
+ if (role &&
(g_strcmp0(role, "visitor") != 0) &&
(g_strcmp0(role, "participant") != 0) &&
(g_strcmp0(role, "moderator") != 0) &&
@@ -2630,7 +2688,7 @@ cmd_role(gchar **args, struct cmd_help_t help)
iq_room_role_list(mucwin->roomjid, "participant");
iq_room_role_list(mucwin->roomjid, "visitor");
} else if (g_strcmp0(role, "none") == 0) {
- win_save_print((ProfWin*) mucwin, '!', NULL, 0, 0, "", "Cannot list users with no role.");
+ win_print((ProfWin*) mucwin, '!', NULL, 0, 0, "", "Cannot list users with no role.");
} else {
iq_room_role_list(mucwin->roomjid, role);
}
@@ -2693,12 +2751,12 @@ cmd_room(gchar **args, struct cmd_help_t help)
if (g_strcmp0(args[0], "accept") == 0) {
gboolean requires_config = muc_requires_config(mucwin->roomjid);
if (!requires_config) {
- win_save_print(window, '!', NULL, 0, THEME_ROOMINFO, "", "Current room does not require configuration.");
+ win_print(window, '!', NULL, 0, THEME_ROOMINFO, "", "Current room does not require configuration.");
return TRUE;
} else {
iq_confirm_instant_room(mucwin->roomjid);
muc_set_requires_config(mucwin->roomjid, FALSE);
- win_save_print(window, '!', NULL, 0, THEME_ROOMINFO, "", "Room unlocked.");
+ win_print(window, '!', NULL, 0, THEME_ROOMINFO, "", "Room unlocked.");
return TRUE;
}
}
@@ -2711,9 +2769,8 @@ cmd_room(gchar **args, struct cmd_help_t help)
if (g_strcmp0(args[0], "config") == 0) {
ProfMucConfWin *confwin = wins_get_muc_conf(mucwin->roomjid);
- if (confwin != NULL) {
- num = wins_get_num(window);
- ui_switch_win(num);
+ if (confwin) {
+ ui_ev_focus_win((ProfWin*)confwin);
} else {
iq_request_room_config_form(mucwin->roomjid);
}
@@ -2734,26 +2791,44 @@ cmd_occupants(gchar **args, struct cmd_help_t help)
}
if (g_strcmp0(args[0], "size") == 0) {
- int intval = 0;
if (!args[1]) {
cons_show("Usage: %s", help.usage);
return TRUE;
- } else if (_strtoi(args[1], &intval, 1, 99) == 0) {
- prefs_set_occupants_size(intval);
- cons_show("Occupants screen size set to: %d%%", intval);
- wins_resize_all();
- return TRUE;
+ } else {
+ int intval = 0;
+ char *err_msg = NULL;
+ gboolean res = strtoi_range(args[1], &intval, 1, 99, &err_msg);
+ if (res) {
+ prefs_set_occupants_size(intval);
+ cons_show("Occupants screen size set to: %d%%", intval);
+ wins_resize_all();
+ return TRUE;
+ } else {
+ cons_show(err_msg);
+ free(err_msg);
+ return TRUE;
+ }
}
}
if (g_strcmp0(args[0], "default") == 0) {
if (g_strcmp0(args[1], "show") == 0) {
- cons_show("Occupant list enabled.");
- prefs_set_boolean(PREF_OCCUPANTS, TRUE);
+ if (g_strcmp0(args[2], "jid") == 0) {
+ cons_show("Occupant jids enabled.");
+ prefs_set_boolean(PREF_OCCUPANTS_JID, TRUE);
+ } else {
+ cons_show("Occupant list enabled.");
+ prefs_set_boolean(PREF_OCCUPANTS, TRUE);
+ }
return TRUE;
} else if (g_strcmp0(args[1], "hide") == 0) {
- cons_show("Occupant list disabled.");
- prefs_set_boolean(PREF_OCCUPANTS, FALSE);
+ if (g_strcmp0(args[2], "jid") == 0) {
+ cons_show("Occupant jids disabled.");
+ prefs_set_boolean(PREF_OCCUPANTS_JID, FALSE);
+ } else {
+ cons_show("Occupant list disabled.");
+ prefs_set_boolean(PREF_OCCUPANTS, FALSE);
+ }
return TRUE;
} else {
cons_show("Usage: %s", help.usage);
@@ -2763,16 +2838,26 @@ cmd_occupants(gchar **args, struct cmd_help_t help)
win_type_t win_type = ui_current_win_type();
if (win_type != WIN_MUC) {
- cons_show("Cannot show/hide occupant list when not in chat room.");
+ cons_show("Cannot apply setting when not in chat room.");
return TRUE;
}
ProfMucWin *mucwin = wins_get_current_muc();
if (g_strcmp0(args[0], "show") == 0) {
- ui_room_show_occupants(mucwin->roomjid);
+ if (g_strcmp0(args[1], "jid") == 0) {
+ mucwin->showjid = TRUE;
+ ui_room_update_occupants(mucwin->roomjid);
+ } else {
+ ui_room_show_occupants(mucwin->roomjid);
+ }
} else if (g_strcmp0(args[0], "hide") == 0) {
- ui_room_hide_occupants(mucwin->roomjid);
+ if (g_strcmp0(args[1], "jid") == 0) {
+ mucwin->showjid = FALSE;
+ ui_room_update_occupants(mucwin->roomjid);
+ } else {
+ ui_room_hide_occupants(mucwin->roomjid);
+ }
} else {
cons_show("Usage: %s", help.usage);
}
@@ -2876,7 +2961,7 @@ cmd_bookmark(gchar **args, struct cmd_help_t help)
char *password = g_hash_table_lookup(options, "password");
char *autojoin = g_hash_table_lookup(options, "autojoin");
- if (autojoin != NULL) {
+ if (autojoin) {
if ((strcmp(autojoin, "on") != 0) && (strcmp(autojoin, "off") != 0)) {
cons_show("Usage: %s", help.usage);
cons_show("");
@@ -2924,7 +3009,7 @@ cmd_disco(gchar **args, struct cmd_help_t help)
}
GString *jid = g_string_new("");
- if (args[1] != NULL) {
+ if (args[1]) {
jid = g_string_append(jid, args[1]);
} else {
Jid *jidp = jid_create(jabber_get_fulljid());
@@ -3040,83 +3125,49 @@ gboolean
cmd_tiny(gchar **args, struct cmd_help_t help)
{
char *url = args[0];
- win_type_t win_type = ui_current_win_type();
+ ProfWin *current = wins_get_current();
+
+ if (current->type != WIN_CHAT && current->type != WIN_MUC && current->type != WIN_PRIVATE) {
+ cons_show("/tiny can only be used in chat windows");
+ return TRUE;
+ }
if (!tinyurl_valid(url)) {
- GString *error = g_string_new("/tiny, badly formed URL: ");
- g_string_append(error, url);
- cons_show_error(error->str);
- if (win_type != WIN_CONSOLE) {
- ui_current_error_line(error->str);
- }
- g_string_free(error, TRUE);
- } else if (win_type != WIN_CONSOLE) {
- char *tiny = tinyurl_get(url);
-
- if (tiny != NULL) {
- if (win_type == WIN_CHAT) {
- ProfChatWin *chatwin = wins_get_current_chat();
-#ifdef HAVE_LIBOTR
- if (otr_is_secure(chatwin->barejid)) {
- char *encrypted = otr_encrypt_message(chatwin->barejid, tiny);
- if (encrypted != NULL) {
- message_send_chat(chatwin->barejid, encrypted);
- otr_free_message(encrypted);
- if (prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
- char *pref_otr_log = prefs_get_string(PREF_OTR_LOG);
- if (strcmp(pref_otr_log, "on") == 0) {
- chat_log_chat(jidp->barejid, chatwin->barejid, tiny, PROF_OUT_LOG, NULL);
- } else if (strcmp(pref_otr_log, "redact") == 0) {
- chat_log_chat(jidp->barejid, chatwin->barejid, "[redacted]", PROF_OUT_LOG, NULL);
- }
- prefs_free_string(pref_otr_log);
- jid_destroy(jidp);
- }
-
- ui_outgoing_chat_msg("me", chatwin->barejid, tiny);
- } else {
- cons_show_error("Failed to send message.");
- }
- } else {
- message_send_chat(chatwin->barejid, tiny);
- if (prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
- chat_log_chat(jidp->barejid, chatwin->barejid, tiny, PROF_OUT_LOG, NULL);
- jid_destroy(jidp);
- }
-
- ui_outgoing_chat_msg("me", chatwin->barejid, tiny);
- }
-#else
- message_send_chat(chatwin->barejid, tiny);
- if (prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
- chat_log_chat(jidp->barejid, chatwin->barejid, tiny, PROF_OUT_LOG, NULL);
- jid_destroy(jidp);
- }
-
- ui_outgoing_chat_msg("me", chatwin->barejid, tiny);
-#endif
- } else if (win_type == WIN_PRIVATE) {
- ProfPrivateWin *privatewin = wins_get_current_private();
- message_send_private(tiny, privatewin->fulljid);
- ui_outgoing_private_msg("me", privatewin->fulljid, tiny);
- } else if (win_type == WIN_MUC) {
- ProfMucWin *mucwin = wins_get_current_muc();
- message_send_groupchat(tiny, mucwin->roomjid);
- }
- free(tiny);
- } else {
- cons_show_error("Couldn't get tinyurl.");
- }
- } else {
- cons_show("/tiny can only be used in chat windows");
+ win_vprint(current, '-', NULL, 0, THEME_ERROR, "", "/tiny, badly formed URL: %s", url);
+ return TRUE;
}
+ char *tiny = tinyurl_get(url);
+ if (!tiny) {
+ win_print(current, '-', NULL, 0, THEME_ERROR, "", "Couldn't create tinyurl.");
+ return TRUE;
+ }
+
+ switch (current->type){
+ case WIN_CHAT:
+ {
+ ProfChatWin *chatwin = wins_get_current_chat();
+ cl_ev_send_msg(chatwin, tiny);
+ break;
+ }
+ case WIN_PRIVATE:
+ {
+ ProfPrivateWin *privatewin = wins_get_current_private();
+ cl_ev_send_priv_msg(privatewin, tiny);
+ break;
+ }
+ case WIN_MUC:
+ {
+ ProfMucWin *mucwin = wins_get_current_muc();
+ cl_ev_send_muc_msg(mucwin, tiny);
+ break;
+ }
+ default:
+ break;
+ }
+
+ free(tiny);
+
return TRUE;
}
@@ -3135,7 +3186,7 @@ cmd_close(gchar **args, struct cmd_help_t help)
int count = 0;
if (args[0] == NULL) {
- index = ui_current_win_index();
+ index = wins_get_current_num();
} else if (strcmp(args[0], "all") == 0) {
count = ui_close_all_wins();
if (count == 0) {
@@ -3170,19 +3221,15 @@ cmd_close(gchar **args, struct cmd_help_t help)
return TRUE;
}
- if (!ui_win_exists(index)) {
+ ProfWin *window = wins_get_by_num(index);
+ if (!window) {
cons_show("Window is not open.");
return TRUE;
}
// check for unsaved form
if (ui_win_has_unsaved_form(index)) {
- ProfWin *window = wins_get_current();
- if (wins_is_current(window)) {
- ui_current_print_line("You have unsaved changes, use /form submit or /form cancel");
- } else {
- cons_show("Cannot close form window with unsaved changes, use /form submit or /form cancel");
- }
+ ui_current_print_line("You have unsaved changes, use /form submit or /form cancel");
return TRUE;
}
@@ -3203,7 +3250,7 @@ cmd_leave(gchar **args, struct cmd_help_t help)
{
jabber_conn_status_t conn_status = jabber_get_connection_status();
win_type_t win_type = ui_current_win_type();
- int index = ui_current_win_index();
+ int index = wins_get_current_num();
if (win_type != WIN_MUC) {
cons_show("You can only use the /leave command in a chat room.");
@@ -3257,10 +3304,46 @@ cmd_wrap(gchar **args, struct cmd_help_t help)
gboolean
cmd_time(gchar **args, struct cmd_help_t help)
{
- prefs_set_string(PREF_TIME, args[0]);
- cons_show("Time format set to '%s'", args[0]);
- wins_resize_all();
- return TRUE;
+ if (g_strcmp0(args[0], "statusbar") == 0) {
+ if (args[1] == NULL) {
+ cons_show("Current status bar time format is '%s'.", prefs_get_string(PREF_TIME_STATUSBAR));
+ return TRUE;
+ } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) {
+ prefs_set_string(PREF_TIME_STATUSBAR, args[2]);
+ cons_show("Status bar time format set to '%s'.", args[2]);
+ ui_redraw();
+ return TRUE;
+ } else if (g_strcmp0(args[1], "off") == 0) {
+ prefs_set_string(PREF_TIME_STATUSBAR, "");
+ cons_show("Status bar time display disabled.");
+ ui_redraw();
+ return TRUE;
+ } else {
+ cons_show("Usage: %s", help.usage);
+ return TRUE;
+ }
+ } else if (g_strcmp0(args[0], "main") == 0) {
+ if (args[1] == NULL) {
+ cons_show("Current time format is '%s'.", prefs_get_string(PREF_TIME));
+ return TRUE;
+ } else if (g_strcmp0(args[1], "set") == 0 && args[2] != NULL) {
+ prefs_set_string(PREF_TIME, args[2]);
+ cons_show("Time format set to '%s'.", args[2]);
+ wins_resize_all();
+ return TRUE;
+ } else if (g_strcmp0(args[1], "off") == 0) {
+ prefs_set_string(PREF_TIME, "");
+ cons_show("Time display disabled.");
+ wins_resize_all();
+ return TRUE;
+ } else {
+ cons_show("Usage: %s", help.usage);
+ return TRUE;
+ }
+ } else {
+ cons_show("Usage: %s", help.usage);
+ return TRUE;
+ }
}
gboolean
@@ -3481,7 +3564,6 @@ cmd_inpblock(gchar **args, struct cmd_help_t help)
{
char *subcmd = args[0];
char *value = args[1];
- int intval;
if (g_strcmp0(subcmd, "timeout") == 0) {
if (value == NULL) {
@@ -3489,10 +3571,16 @@ cmd_inpblock(gchar **args, struct cmd_help_t help)
return TRUE;
}
- if (_strtoi(value, &intval, 1, 1000) == 0) {
+ int intval = 0;
+ char *err_msg = NULL;
+ gboolean res = strtoi_range(value, &intval, 1, 1000, &err_msg);
+ if (res) {
cons_show("Input blocking set to %d milliseconds.", intval);
prefs_set_inpblock(intval);
ui_input_nonblocking(FALSE);
+ } else {
+ cons_show(err_msg);
+ free(err_msg);
}
return TRUE;
@@ -3522,16 +3610,22 @@ cmd_log(gchar **args, struct cmd_help_t help)
{
char *subcmd = args[0];
char *value = args[1];
- int intval;
if (strcmp(subcmd, "maxsize") == 0) {
if (value == NULL) {
cons_show("Usage: %s", help.usage);
return TRUE;
}
- if (_strtoi(value, &intval, PREFS_MIN_LOG_SIZE, INT_MAX) == 0) {
+
+ int intval = 0;
+ char *err_msg = NULL;
+ gboolean res = strtoi_range(value, &intval, PREFS_MIN_LOG_SIZE, INT_MAX, &err_msg);
+ if (res) {
prefs_set_max_log_size(intval);
cons_show("Log maxinum size set to %d bytes", intval);
+ } else {
+ cons_show(err_msg);
+ free(err_msg);
}
return TRUE;
}
@@ -3571,9 +3665,11 @@ gboolean
cmd_reconnect(gchar **args, struct cmd_help_t help)
{
char *value = args[0];
- int intval;
- if (_strtoi(value, &intval, 0, INT_MAX) == 0) {
+ int intval = 0;
+ char *err_msg = NULL;
+ gboolean res = strtoi_range(value, &intval, 0, INT_MAX, &err_msg);
+ if (res) {
prefs_set_reconnect(intval);
if (intval == 0) {
cons_show("Reconnect disabled.", intval);
@@ -3581,7 +3677,9 @@ cmd_reconnect(gchar **args, struct cmd_help_t help)
cons_show("Reconnect interval set to %d seconds.", intval);
}
} else {
+ cons_show(err_msg);
cons_show("Usage: %s", help.usage);
+ free(err_msg);
}
return TRUE;
@@ -3591,9 +3689,11 @@ gboolean
cmd_autoping(gchar **args, struct cmd_help_t help)
{
char *value = args[0];
- int intval;
- if (_strtoi(value, &intval, 0, INT_MAX) == 0) {
+ int intval = 0;
+ char *err_msg = NULL;
+ gboolean res = strtoi_range(value, &intval, 0, INT_MAX, &err_msg);
+ if (res) {
prefs_set_autoping(intval);
iq_set_autoping(intval);
if (intval == 0) {
@@ -3602,7 +3702,9 @@ cmd_autoping(gchar **args, struct cmd_help_t help)
cons_show("Autoping interval set to %d seconds.", intval);
}
} else {
+ cons_show(err_msg);
cons_show("Usage: %s", help.usage);
+ free(err_msg);
}
return TRUE;
@@ -3633,7 +3735,6 @@ cmd_autoaway(gchar **args, struct cmd_help_t help)
{
char *setting = args[0];
char *value = args[1];
- int minutesval;
if ((strcmp(setting, "mode") != 0) && (strcmp(setting, "time") != 0) &&
(strcmp(setting, "message") != 0) && (strcmp(setting, "check") != 0)) {
@@ -3654,9 +3755,15 @@ cmd_autoaway(gchar **args, struct cmd_help_t help)
}
if (strcmp(setting, "time") == 0) {
- if (_strtoi(value, &minutesval, 1, INT_MAX) == 0) {
+ int minutesval = 0;
+ char *err_msg = NULL;
+ gboolean res = strtoi_range(value, &minutesval, 1, INT_MAX, &err_msg);
+ if (res) {
prefs_set_autoaway_time(minutesval);
cons_show("Auto away time set to: %d minutes.", minutesval);
+ } else {
+ cons_show(err_msg);
+ free(err_msg);
}
return TRUE;
@@ -3693,13 +3800,18 @@ cmd_priority(gchar **args, struct cmd_help_t help)
}
char *value = args[0];
- int intval;
- if (_strtoi(value, &intval, -128, 127) == 0) {
+ int intval = 0;
+ char *err_msg = NULL;
+ gboolean res = strtoi_range(value, &intval, -128, 127, &err_msg);
+ if (res) {
accounts_set_priority_all(jabber_get_account_name(), intval);
resource_presence_t last_presence = accounts_get_last_presence(jabber_get_account_name());
- presence_update(last_presence, jabber_get_presence_message(), 0);
+ cl_ev_presence_send(last_presence, jabber_get_presence_message(), 0);
cons_show("Priority set to %d.", intval);
+ } else {
+ cons_show(err_msg);
+ free(err_msg);
}
return TRUE;
@@ -3864,6 +3976,42 @@ cmd_history(gchar **args, struct cmd_help_t help)
return result;
}
+gboolean
+cmd_carbons(gchar **args, struct cmd_help_t help)
+{
+ gboolean result = _cmd_set_boolean_preference(args[0], help,
+ "Message carbons preference", PREF_CARBONS);
+
+ jabber_conn_status_t conn_status = jabber_get_connection_status();
+
+ if (conn_status == JABBER_CONNECTED) {
+ // enable carbons
+ if (strcmp(args[0], "on") == 0) {
+ iq_enable_carbons();
+ }
+ else if (strcmp(args[0], "off") == 0){
+ iq_disable_carbons();
+ }
+ }
+
+ return result;
+}
+
+gboolean
+cmd_receipts(gchar **args, struct cmd_help_t help)
+{
+ if (g_strcmp0(args[0], "send") == 0) {
+ return _cmd_set_boolean_preference(args[1], help,
+ "Send delivery receipts", PREF_RECEIPTS_SEND);
+ } else if (g_strcmp0(args[0], "request") == 0) {
+ return _cmd_set_boolean_preference(args[1], help,
+ "Request delivery receipets", PREF_RECEIPTS_REQUEST);
+ } else {
+ cons_show("Usage: %s", help.usage);
+ return TRUE;
+ }
+}
+
gboolean
cmd_away(gchar **args, struct cmd_help_t help)
{
@@ -4013,14 +4161,18 @@ cmd_otr(gchar **args, struct cmd_help_t help)
return TRUE;
} else if (strcmp(args[0], "start") == 0) {
- if (args[1] != NULL) {
+ if (args[1]) {
char *contact = args[1];
char *barejid = roster_barejid_from_name(contact);
if (barejid == NULL) {
barejid = contact;
}
- ui_new_chat_win(barejid);
+ ProfChatWin *chatwin = wins_get_chat(barejid);
+ if (!chatwin) {
+ chatwin = ui_ev_new_chat_win(barejid);
+ }
+ ui_ev_focus_win((ProfWin*)chatwin);
if (ui_current_win_is_otr()) {
ui_current_print_formatted_line('!', 0, "You are already in an OTR session.");
@@ -4029,7 +4181,7 @@ cmd_otr(gchar **args, struct cmd_help_t help)
ui_current_print_formatted_line('!', 0, "You have not generated or loaded a private key, use '/otr gen'");
} else if (!otr_is_secure(barejid)) {
char *otr_query_message = otr_start_query();
- message_send_chat(barejid, otr_query_message);
+ message_send_chat_encrypted(barejid, otr_query_message);
} else {
ui_gone_secure(barejid, otr_is_trusted(barejid));
}
@@ -4047,7 +4199,7 @@ cmd_otr(gchar **args, struct cmd_help_t help)
} else {
ProfChatWin *chatwin = ui_get_current_chat();
char *otr_query_message = otr_start_query();
- message_send_chat(chatwin->barejid, otr_query_message);
+ message_send_chat_encrypted(chatwin->barejid, otr_query_message);
}
}
}
@@ -4175,7 +4327,7 @@ _update_presence(const resource_presence_t resource_presence,
if (conn_status != JABBER_CONNECTED) {
cons_show("You are not currently connected.");
} else {
- presence_update(resource_presence, msg, 0);
+ cl_ev_presence_send(resource_presence, msg, 0);
ui_update_presence(resource_presence, msg, show);
}
}
@@ -4213,27 +4365,6 @@ _cmd_set_boolean_preference(gchar *arg, struct cmd_help_t help,
return TRUE;
}
-static int
-_strtoi(char *str, int *saveptr, int min, int max)
-{
- char *ptr;
- int val;
-
- errno = 0;
- val = (int)strtol(str, &ptr, 0);
- if (errno != 0 || *str == '\0' || *ptr != '\0') {
- cons_show("Could not convert \"%s\" to a number.", str);
- return -1;
- } else if (val < min || val > max) {
- cons_show("Value %s out of range. Must be in %d..%d.", str, min, max);
- return -1;
- }
-
- *saveptr = val;
-
- return 0;
-}
-
static void
_cmd_show_filtered_help(char *heading, gchar *cmd_filter[], int filter_size)
{
@@ -4249,7 +4380,7 @@ _cmd_show_filtered_help(char *heading, gchar *cmd_filter[], int filter_size)
}
GList *curr = ordered_commands;
- while (curr != NULL) {
+ while (curr) {
Command *cmd = curr->data;
cons_show("%-12s: %s", cmd->cmd, cmd->help.short_help);
curr = g_list_next(curr);
diff --git a/src/command/commands.h b/src/command/commands.h
index f4e040a9..7b7e7c93 100644
--- a/src/command/commands.h
+++ b/src/command/commands.h
@@ -1,7 +1,7 @@
/*
* commands.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -62,6 +62,9 @@ typedef struct cmd_t {
CommandHelp help;
} Command;
+gboolean cmd_execute_alias(const char * const inp, gboolean *ran);
+gboolean cmd_execute_default(const char * inp);
+
gboolean cmd_about(gchar **args, struct cmd_help_t help);
gboolean cmd_account(gchar **args, struct cmd_help_t help);
gboolean cmd_autoaway(gchar **args, struct cmd_help_t help);
@@ -85,6 +88,8 @@ gboolean cmd_grlog(gchar **args, struct cmd_help_t help);
gboolean cmd_group(gchar **args, struct cmd_help_t help);
gboolean cmd_help(gchar **args, struct cmd_help_t help);
gboolean cmd_history(gchar **args, struct cmd_help_t help);
+gboolean cmd_carbons(gchar **args, struct cmd_help_t help);
+gboolean cmd_receipts(gchar **args, struct cmd_help_t help);
gboolean cmd_info(gchar **args, struct cmd_help_t help);
gboolean cmd_intype(gchar **args, struct cmd_help_t help);
gboolean cmd_invite(gchar **args, struct cmd_help_t help);
diff --git a/src/common.c b/src/common.c
index 7638da31..772e24d3 100644
--- a/src/common.c
+++ b/src/common.c
@@ -1,7 +1,7 @@
/*
* common.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -202,6 +202,33 @@ str_contains(const char str[], int size, char ch)
return 0;
}
+gboolean
+strtoi_range(char *str, int *saveptr, int min, int max, char **err_msg)
+{
+ char *ptr;
+ int val;
+
+ errno = 0;
+ val = (int)strtol(str, &ptr, 0);
+ if (errno != 0 || *str == '\0' || *ptr != '\0') {
+ GString *err_str = g_string_new("");
+ g_string_printf(err_str, "Could not convert \"%s\" to a number.", str);
+ *err_msg = err_str->str;
+ g_string_free(err_str, FALSE);
+ return FALSE;
+ } else if (val < min || val > max) {
+ GString *err_str = g_string_new("");
+ g_string_printf(err_str, "Value %s out of range. Must be in %d..%d.", str, min, max);
+ *err_msg = err_str->str;
+ g_string_free(err_str, FALSE);
+ return FALSE;
+ }
+
+ *saveptr = val;
+
+ return TRUE;
+}
+
int
utf8_display_len(const char * const str)
{
@@ -224,6 +251,18 @@ utf8_display_len(const char * const str)
return len;
}
+gboolean
+utf8_is_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);
+}
+
char *
prof_getline(FILE *stream)
{
@@ -248,7 +287,7 @@ prof_getline(FILE *stream)
result = (char *)realloc(s, s_size + buf_size);
if (result == NULL) {
- if (s != NULL) {
+ if (s) {
free(s);
s = NULL;
}
@@ -286,7 +325,7 @@ release_get_latest()
curl_easy_perform(handle);
curl_easy_cleanup(handle);
- if (output.buffer != NULL) {
+ if (output.buffer) {
output.buffer[output.size++] = '\0';
return output.buffer;
} else {
@@ -393,10 +432,10 @@ gchar *
xdg_get_config_home(void)
{
gchar *xdg_config_home = getenv("XDG_CONFIG_HOME");
- if (xdg_config_home != NULL)
+ if (xdg_config_home)
g_strstrip(xdg_config_home);
- if ((xdg_config_home != NULL) && (strcmp(xdg_config_home, "") != 0)) {
+ if (xdg_config_home && (strcmp(xdg_config_home, "") != 0)) {
return strdup(xdg_config_home);
} else {
GString *default_path = g_string_new(getenv("HOME"));
@@ -412,10 +451,10 @@ gchar *
xdg_get_data_home(void)
{
gchar *xdg_data_home = getenv("XDG_DATA_HOME");
- if (xdg_data_home != NULL)
+ if (xdg_data_home)
g_strstrip(xdg_data_home);
- if ((xdg_data_home != NULL) && (strcmp(xdg_data_home, "") != 0)) {
+ if (xdg_data_home && (strcmp(xdg_data_home, "") != 0)) {
return strdup(xdg_data_home);
} else {
GString *default_path = g_string_new(getenv("HOME"));
@@ -435,7 +474,7 @@ create_unique_id(char *prefix)
GString *result_str = g_string_new("");
unique_id++;
- if (prefix != NULL) {
+ if (prefix) {
g_string_printf(result_str, "prof_%s_%lu", prefix, unique_id);
} else {
g_string_printf(result_str, "prof_%lu", unique_id);
@@ -488,25 +527,34 @@ cmp_win_num(gconstpointer a, gconstpointer b)
int
get_next_available_win_num(GList *used)
{
- used = g_list_sort(used, cmp_win_num);
// only console used
if (g_list_length(used) == 1) {
return 2;
} else {
+ GList *sorted = NULL;
+ GList *curr = used;
+ while (curr) {
+ sorted = g_list_insert_sorted(sorted, curr->data, cmp_win_num);
+ curr = g_list_next(curr);
+ }
+
int result = 0;
int last_num = 1;
- GList *curr = used;
+ curr = sorted;
// skip console
curr = g_list_next(curr);
- while (curr != NULL) {
+ while (curr) {
int curr_num = GPOINTER_TO_INT(curr->data);
+
if (((last_num != 9) && ((last_num + 1) != curr_num)) ||
((last_num == 9) && (curr_num != 0))) {
result = last_num + 1;
if (result == 10) {
result = 0;
}
+ g_list_free(sorted);
return (result);
+
} else {
last_num = curr_num;
if (last_num == 0) {
@@ -520,6 +568,7 @@ get_next_available_win_num(GList *used)
result = 0;
}
+ g_list_free(sorted);
return result;
}
}
@@ -566,3 +615,25 @@ get_file_or_linked(char *loc, char *basedir)
return true_loc;
}
+
+char *
+strip_arg_quotes(const char * const input)
+{
+ char *unquoted = strdup(input);
+
+ // Remove starting quote if it exists
+ if(strchr(unquoted, '"')) {
+ if(strchr(unquoted, ' ') + 1 == strchr(unquoted, '"')) {
+ memmove(strchr(unquoted, '"'), strchr(unquoted, '"')+1, strchr(unquoted, '\0') - strchr(unquoted, '"'));
+ }
+ }
+
+ // Remove ending quote if it exists
+ if(strchr(unquoted, '"')) {
+ if(strchr(unquoted, '\0') - 1 == strchr(unquoted, '"')) {
+ memmove(strchr(unquoted, '"'), strchr(unquoted, '"')+1, strchr(unquoted, '\0') - strchr(unquoted, '"'));
+ }
+ }
+
+ return unquoted;
+}
diff --git a/src/common.h b/src/common.h
index 26d4a99a..9521a701 100644
--- a/src/common.h
+++ b/src/common.h
@@ -1,7 +1,7 @@
/*
* common.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -36,6 +36,13 @@
#define COMMON_H
#include
+#include
+
+#ifdef HAVE_NCURSESW_NCURSES_H
+#include
+#elif HAVE_NCURSES_H
+#include
+#endif
#include
@@ -104,7 +111,9 @@ gboolean mkdir_recursive(const char *dir);
char * str_replace(const char *string, const char *substr,
const char *replacement);
int str_contains(const char str[], int size, char ch);
+gboolean strtoi_range(char *str, int *saveptr, int min, int max, char **err_msg);
int utf8_display_len(const char * const str);
+gboolean utf8_is_printable(const wint_t ch);
char * prof_getline(FILE *stream);
char* release_get_latest(void);
gboolean release_is_new(char *found_version);
@@ -123,5 +132,6 @@ int cmp_win_num(gconstpointer a, gconstpointer b);
int get_next_available_win_num(GList *used);
char* get_file_or_linked(char *loc, char *basedir);
+char * strip_arg_quotes(const char * const input);
#endif
diff --git a/src/config/account.c b/src/config/account.c
index 6df00382..857d049b 100644
--- a/src/config/account.c
+++ b/src/config/account.c
@@ -1,7 +1,7 @@
/*
* account.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -34,12 +34,14 @@
#include
#include
+#include
#include
#include "jid.h"
#include "config/account.h"
#include "common.h"
+#include "log.h"
ProfAccount*
account_new(const gchar * const name, const gchar * const jid,
@@ -55,19 +57,19 @@ account_new(const gchar * const name, const gchar * const jid,
new_account->name = strdup(name);
- if (jid != NULL) {
+ if (jid) {
new_account->jid = strdup(jid);
} else {
new_account->jid = strdup(name);
}
- if (password != NULL) {
+ if (password) {
new_account->password = strdup(password);
} else {
new_account->password = NULL;
}
- if (eval_password != NULL) {
+ if (eval_password) {
new_account->eval_password = strdup(eval_password);
} else {
new_account->eval_password = NULL;
@@ -75,13 +77,13 @@ account_new(const gchar * const name, const gchar * const jid,
new_account->enabled = enabled;
- if (server != NULL) {
+ if (server) {
new_account->server = strdup(server);
} else {
new_account->server = NULL;
}
- if (resource != NULL) {
+ if (resource) {
new_account->resource = strdup(resource);
} else {
new_account->resource = NULL;
@@ -132,7 +134,7 @@ account_new(const gchar * const name, const gchar * const jid,
new_account->muc_nick = strdup(muc_nick);
}
- if (otr_policy != NULL) {
+ if (otr_policy) {
new_account->otr_policy = strdup(otr_policy);
} else {
new_account->otr_policy = NULL;
@@ -148,17 +150,55 @@ account_new(const gchar * const name, const gchar * const jid,
char *
account_create_full_jid(ProfAccount *account)
{
- if (account->resource != NULL) {
+ if (account->resource) {
return create_fulljid(account->jid, account->resource);
} else {
return strdup(account->jid);
}
}
+gboolean
+account_eval_password(ProfAccount *account)
+{
+ assert(account != NULL);
+ assert(account->eval_password != NULL);
+
+ // Evaluate as shell command to retrieve password
+ GString *cmd = g_string_new("");
+ g_string_append_printf(cmd, "%s 2>/dev/null", account->eval_password);
+
+ FILE *stream = popen(cmd->str, "r");
+ g_string_free(cmd, TRUE);
+ if (stream) {
+ // Limit to READ_BUF_SIZE bytes to prevent overflows in the case of a poorly chosen command
+ account->password = g_malloc(READ_BUF_SIZE);
+ if (!account->password) {
+ log_error("Failed to allocate enough memory to read eval_password output");
+ return FALSE;
+ }
+ account->password = fgets(account->password, READ_BUF_SIZE, stream);
+ pclose(stream);
+ if (!account->password) {
+ log_error("No result from eval_password.");
+ return FALSE;
+ }
+
+ // strip trailing newline
+ if (g_str_has_suffix(account->password, "\n")) {
+ account->password[strlen(account->password)-1] = '\0';
+ }
+ } else {
+ log_error("popen failed when running eval_password.");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
void
account_free(ProfAccount *account)
{
- if (account != NULL) {
+ if (account) {
free(account->name);
free(account->jid);
free(account->password);
diff --git a/src/config/account.h b/src/config/account.h
index ab43234d..218f8ce7 100644
--- a/src/config/account.h
+++ b/src/config/account.h
@@ -1,7 +1,7 @@
/*
* account.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -69,9 +69,8 @@ ProfAccount* account_new(const gchar * const name, const gchar * const jid,
const gchar * const muc_service, const gchar * const muc_nick,
const gchar * const otr_policy, GList *otr_manual, GList *otr_opportunistic,
GList *otr_always);
-
char* account_create_full_jid(ProfAccount *account);
-
+gboolean account_eval_password(ProfAccount *account);
void account_free(ProfAccount *account);
#endif
diff --git a/src/config/accounts.c b/src/config/accounts.c
index 4d4d47d0..d68f3a55 100644
--- a/src/config/accounts.c
+++ b/src/config/accounts.c
@@ -1,7 +1,7 @@
/*
* accounts.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -147,9 +147,9 @@ accounts_add(const char *account_name, const char *altdomain, const int port)
const char *barejid = account_name;
const char *resource = "profanity";
Jid *jid = jid_create(account_name);
- if (jid != NULL) {
+ if (jid) {
barejid = jid->barejid;
- if (jid->resourcepart != NULL) {
+ if (jid->resourcepart) {
resource = jid->resourcepart;
}
}
@@ -159,7 +159,7 @@ accounts_add(const char *account_name, const char *altdomain, const int port)
g_key_file_set_boolean(accounts, account_name, "enabled", TRUE);
g_key_file_set_string(accounts, account_name, "jid", barejid);
g_key_file_set_string(accounts, account_name, "resource", resource);
- if (altdomain != NULL) {
+ if (altdomain) {
g_key_file_set_string(accounts, account_name, "server", altdomain);
}
if (port != 0) {
@@ -252,7 +252,7 @@ accounts_get_account(const char * const name)
gsize length;
GList *otr_manual = NULL;
gchar **manual = g_key_file_get_string_list(accounts, name, "otr.manual", &length, NULL);
- if (manual != NULL) {
+ if (manual) {
int i = 0;
for (i = 0; i < length; i++) {
otr_manual = g_list_append(otr_manual, strdup(manual[i]));
@@ -262,7 +262,7 @@ accounts_get_account(const char * const name)
GList *otr_opportunistic = NULL;
gchar **opportunistic = g_key_file_get_string_list(accounts, name, "otr.opportunistic", &length, NULL);
- if (opportunistic != NULL) {
+ if (opportunistic) {
int i = 0;
for (i = 0; i < length; i++) {
otr_opportunistic = g_list_append(otr_opportunistic, strdup(opportunistic[i]));
@@ -272,7 +272,7 @@ accounts_get_account(const char * const name)
GList *otr_always = NULL;
gchar **always = g_key_file_get_string_list(accounts, name, "otr.always", &length, NULL);
- if (always != NULL) {
+ if (always) {
int i = 0;
for (i = 0; i < length; i++) {
otr_always = g_list_append(otr_always, strdup(always[i]));
@@ -356,7 +356,7 @@ accounts_rename(const char * const account_name, const char * const new_name)
int i;
for (i = 0; i < ARRAY_SIZE(string_keys); i++) {
char *value = g_key_file_get_string(accounts, account_name, string_keys[i], NULL);
- if (value != NULL) {
+ if (value) {
g_key_file_set_string(accounts, new_name, string_keys[i], value);
g_free(value);
}
@@ -386,10 +386,10 @@ void
accounts_set_jid(const char * const account_name, const char * const value)
{
Jid *jid = jid_create(value);
- if (jid != NULL) {
+ if (jid) {
if (accounts_account_exists(account_name)) {
g_key_file_set_string(accounts, account_name, "jid", jid->barejid);
- if (jid->resourcepart != NULL) {
+ if (jid->resourcepart) {
g_key_file_set_string(accounts, account_name, "resource", jid->resourcepart);
}
@@ -509,7 +509,7 @@ accounts_add_otr_policy(const char * const account_name, const char * const cont
GList *glist = NULL;
// list found
- if (list != NULL) {
+ if (list) {
int i = 0;
for (i = 0; i < length; i++) {
// item already in list, exit function
@@ -529,7 +529,7 @@ accounts_add_otr_policy(const char * const account_name, const char * const cont
const gchar* new_list[g_list_length(glist)+1];
GList *curr = glist;
i = 0;
- while (curr != NULL) {
+ while (curr) {
new_list[i++] = strdup(curr->data);
curr = g_list_next(curr);
}
@@ -572,7 +572,7 @@ _remove_from_list(GKeyFile *accounts, const char * const account_name, const cha
gsize length;
gchar **list = g_key_file_get_string_list(accounts, account_name, key, &length, NULL);
- if (list != NULL) {
+ if (list) {
int i = 0;
GList *glist = NULL;
gboolean deleted = FALSE;
@@ -595,7 +595,7 @@ _remove_from_list(GKeyFile *accounts, const char * const account_name, const cha
const gchar* new_list[g_list_length(glist)+1];
GList *curr = glist;
i = 0;
- while (curr != NULL) {
+ while (curr) {
new_list[i++] = strdup(curr->data);
curr = g_list_next(curr);
}
@@ -766,7 +766,7 @@ accounts_get_last_presence(const char * const account_name)
result = RESOURCE_ONLINE;
}
- if (setting != NULL) {
+ if (setting) {
g_free(setting);
}
return result;
@@ -796,7 +796,7 @@ accounts_get_login_presence(const char * const account_name)
result = RESOURCE_ONLINE;
}
- if (setting != NULL) {
+ if (setting) {
g_free(setting);
}
return result;
@@ -809,9 +809,9 @@ _fix_legacy_accounts(const char * const account_name)
const char *barejid = account_name;
const char *resource = "profanity";
Jid *jid = jid_create(account_name);
- if (jid != NULL) {
+ if (jid) {
barejid = jid->barejid;
- if (jid->resourcepart != NULL) {
+ if (jid->resourcepart) {
resource = jid->resourcepart;
}
}
@@ -828,7 +828,7 @@ _fix_legacy_accounts(const char * const account_name)
_save_accounts();
}
- // acounts with no muc service or nick
+ // accounts with no muc service or nick
if (!g_key_file_has_key(accounts, account_name, "muc.service", NULL)) {
gchar *account_jid = g_key_file_get_string(accounts, account_name, "jid", NULL);
Jid *jidp = jid_create(account_jid);
diff --git a/src/config/accounts.h b/src/config/accounts.h
index cbbe88e6..50307b5b 100644
--- a/src/config/accounts.h
+++ b/src/config/accounts.h
@@ -1,7 +1,7 @@
/*
* accounts.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/config/preferences.c b/src/config/preferences.c
index 652d4ed9..c0d6f6e5 100644
--- a/src/config/preferences.c
+++ b/src/config/preferences.c
@@ -1,7 +1,7 @@
/*
* preferences.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -62,7 +62,7 @@
#define PREF_GROUP_ALIAS "alias"
#define PREF_GROUP_OTR "otr"
-#define INPBLOCK_DEFAULT 20
+#define INPBLOCK_DEFAULT 1000
static gchar *prefs_loc;
static GKeyFile *prefs;
@@ -95,35 +95,17 @@ prefs_load(void)
err = NULL;
log_maxsize = g_key_file_get_integer(prefs, PREF_GROUP_LOGGING, "maxsize", &err);
- if (err != NULL) {
+ if (err) {
log_maxsize = 0;
g_error_free(err);
}
- // move pre 0.4.1 OTR preferences to [otr] group
+ // move pre 0.4.6 OTR warn preferences to [ui] group
err = NULL;
- gboolean ui_otr_warn = g_key_file_get_boolean(prefs, PREF_GROUP_UI, "otr.warn", &err);
+ gboolean otr_warn = g_key_file_get_boolean(prefs, PREF_GROUP_OTR, "warn", &err);
if (err == NULL) {
- g_key_file_set_boolean(prefs, PREF_GROUP_OTR, _get_key(PREF_OTR_WARN), ui_otr_warn);
- g_key_file_remove_key(prefs, PREF_GROUP_UI, "otr.warn", NULL);
- } else {
- g_error_free(err);
- }
-
- err = NULL;
- gchar *ui_otr_log = g_key_file_get_string(prefs, PREF_GROUP_LOGGING, "otr", &err);
- if (err == NULL) {
- g_key_file_set_string(prefs, PREF_GROUP_OTR, _get_key(PREF_OTR_LOG), ui_otr_log);
- g_key_file_remove_key(prefs, PREF_GROUP_LOGGING, "otr", NULL);
- } else {
- g_error_free(err);
- }
-
- err = NULL;
- gchar *ui_otr_policy = g_key_file_get_string(prefs, "policy", "otr.policy", &err);
- if (err == NULL) {
- g_key_file_set_string(prefs, PREF_GROUP_OTR, _get_key(PREF_OTR_POLICY), ui_otr_policy);
- g_key_file_remove_group(prefs, "policy", NULL);
+ g_key_file_set_boolean(prefs, PREF_GROUP_UI, _get_key(PREF_OTR_WARN), otr_warn);
+ g_key_file_remove_key(prefs, PREF_GROUP_OTR, "warn", NULL);
} else {
g_error_free(err);
}
@@ -198,7 +180,7 @@ prefs_get_string(preference_t pref)
char *result = g_key_file_get_string(prefs, group, key, NULL);
if (result == NULL) {
- if (def != NULL) {
+ if (def) {
return strdup(def);
} else {
return NULL;
@@ -211,7 +193,7 @@ prefs_get_string(preference_t pref)
void
prefs_free_string(char *pref)
{
- if (pref != NULL) {
+ if (pref) {
free(pref);
}
pref = NULL;
@@ -358,7 +340,7 @@ prefs_get_occupants_size(void)
gint result = g_key_file_get_integer(prefs, PREF_GROUP_UI, "occupants.size", NULL);
if (result > 99 || result < 1) {
- return 20;
+ return 15;
} else {
return result;
}
@@ -377,7 +359,7 @@ prefs_get_roster_size(void)
gint result = g_key_file_get_integer(prefs, PREF_GROUP_UI, "roster.size", NULL);
if (result > 99 || result < 1) {
- return 20;
+ return 25;
} else {
return result;
}
@@ -437,7 +419,7 @@ prefs_get_aliases(void)
char *name = keys[i];
char *value = g_key_file_get_string(prefs, PREF_GROUP_ALIAS, name, NULL);
- if (value != NULL) {
+ if (value) {
ProfAlias *alias = malloc(sizeof(struct prof_alias_t));
alias->name = strdup(name);
alias->value = strdup(value);
@@ -517,6 +499,7 @@ _get_group(preference_t pref)
case PREF_HISTORY:
case PREF_MOUSE:
case PREF_OCCUPANTS:
+ case PREF_OCCUPANTS_JID:
case PREF_STATUSES:
case PREF_STATUSES_CONSOLE:
case PREF_STATUSES_CHAT:
@@ -525,12 +508,14 @@ _get_group(preference_t pref)
case PREF_PRESENCE:
case PREF_WRAP:
case PREF_TIME:
+ case PREF_TIME_STATUSBAR:
case PREF_ROSTER:
case PREF_ROSTER_OFFLINE:
case PREF_ROSTER_RESOURCE:
case PREF_ROSTER_BY:
case PREF_RESOURCE_TITLE:
case PREF_RESOURCE_MESSAGE:
+ case PREF_OTR_WARN:
case PREF_INPBLOCK_DYNAMIC:
return PREF_GROUP_UI;
case PREF_STATES:
@@ -558,8 +543,10 @@ _get_group(preference_t pref)
return PREF_GROUP_PRESENCE;
case PREF_CONNECT_ACCOUNT:
case PREF_DEFAULT_ACCOUNT:
+ case PREF_CARBONS:
+ case PREF_RECEIPTS_SEND:
+ case PREF_RECEIPTS_REQUEST:
return PREF_GROUP_CONNECTION;
- case PREF_OTR_WARN:
case PREF_OTR_LOG:
case PREF_OTR_POLICY:
return PREF_GROUP_OTR;
@@ -593,10 +580,18 @@ _get_key(preference_t pref)
return "intype";
case PREF_HISTORY:
return "history";
+ case PREF_CARBONS:
+ return "carbons";
+ case PREF_RECEIPTS_SEND:
+ return "receipts.send";
+ case PREF_RECEIPTS_REQUEST:
+ return "receipts.request";
case PREF_MOUSE:
return "mouse";
case PREF_OCCUPANTS:
return "occupants";
+ case PREF_OCCUPANTS_JID:
+ return "occupants.jid";
case PREF_MUC_PRIVILEGES:
return "privileges";
case PREF_STATUSES:
@@ -648,7 +643,7 @@ _get_key(preference_t pref)
case PREF_OTR_LOG:
return "log";
case PREF_OTR_WARN:
- return "warn";
+ return "otr.warn";
case PREF_OTR_POLICY:
return "policy";
case PREF_LOG_ROTATE:
@@ -661,6 +656,8 @@ _get_key(preference_t pref)
return "wrap";
case PREF_TIME:
return "time";
+ case PREF_TIME_STATUSBAR:
+ return "time.statusbar";
case PREF_ROSTER:
return "roster";
case PREF_ROSTER_OFFLINE:
@@ -691,15 +688,24 @@ _get_default_boolean(preference_t pref)
case PREF_AUTOAWAY_CHECK:
case PREF_LOG_ROTATE:
case PREF_LOG_SHARED:
+ case PREF_NOTIFY_MESSAGE:
case PREF_NOTIFY_MESSAGE_CURRENT:
case PREF_NOTIFY_ROOM_CURRENT:
+ case PREF_NOTIFY_TYPING:
case PREF_NOTIFY_TYPING_CURRENT:
+ case PREF_NOTIFY_SUB:
+ case PREF_NOTIFY_INVITE:
case PREF_SPLASH:
case PREF_OCCUPANTS:
case PREF_MUC_PRIVILEGES:
case PREF_PRESENCE:
case PREF_WRAP:
case PREF_INPBLOCK_DYNAMIC:
+ case PREF_RESOURCE_TITLE:
+ case PREF_RESOURCE_MESSAGE:
+ case PREF_ROSTER:
+ case PREF_ROSTER_OFFLINE:
+ case PREF_ROSTER_RESOURCE:
return TRUE;
default:
return FALSE;
@@ -715,7 +721,7 @@ _get_default_string(preference_t pref)
{
case PREF_AUTOAWAY_MODE:
case PREF_NOTIFY_ROOM:
- return "off";
+ return "on";
case PREF_OTR_LOG:
return "redact";
case PREF_OTR_POLICY:
@@ -725,9 +731,11 @@ _get_default_string(preference_t pref)
case PREF_STATUSES_MUC:
return "all";
case PREF_ROSTER_BY:
- return "none";
+ return "presence";
case PREF_TIME:
return "%H:%M:%S";
+ case PREF_TIME_STATUSBAR:
+ return "%H:%M";
default:
return NULL;
}
diff --git a/src/config/preferences.h b/src/config/preferences.h
index 68286f09..4455eca1 100644
--- a/src/config/preferences.h
+++ b/src/config/preferences.h
@@ -1,7 +1,7 @@
/*
* preferences.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -59,9 +59,13 @@ typedef enum {
PREF_FLASH,
PREF_INTYPE,
PREF_HISTORY,
+ PREF_CARBONS,
+ PREF_RECEIPTS_SEND,
+ PREF_RECEIPTS_REQUEST,
PREF_MOUSE,
PREF_OCCUPANTS,
PREF_OCCUPANTS_SIZE,
+ PREF_OCCUPANTS_JID,
PREF_ROSTER,
PREF_ROSTER_SIZE,
PREF_ROSTER_OFFLINE,
@@ -71,6 +75,7 @@ typedef enum {
PREF_PRESENCE,
PREF_WRAP,
PREF_TIME,
+ PREF_TIME_STATUSBAR,
PREF_STATUSES,
PREF_STATUSES_CONSOLE,
PREF_STATUSES_CHAT,
diff --git a/src/config/theme.c b/src/config/theme.c
index 6d3c5938..f73dee19 100644
--- a/src/config/theme.c
+++ b/src/config/theme.c
@@ -1,7 +1,7 @@
/*
* theme.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -121,6 +121,7 @@ static struct colours_t {
NCURSES_COLOR_T otruntrusted;
NCURSES_COLOR_T rosterheader;
NCURSES_COLOR_T occupantsheader;
+ NCURSES_COLOR_T receiptsent;
} colour_prefs;
static NCURSES_COLOR_T _lookup_colour(const char * const colour);
@@ -159,7 +160,7 @@ _theme_load_file(const char * const theme_name)
{
// use default theme
if (theme_name == NULL || strcmp(theme_name, "default") == 0) {
- if (theme != NULL) {
+ if (theme) {
g_key_file_free(theme);
}
theme = g_key_file_new();
@@ -172,12 +173,12 @@ _theme_load_file(const char * const theme_name)
return FALSE;
}
- if (theme_loc != NULL) {
+ if (theme_loc) {
g_string_free(theme_loc, TRUE);
}
theme_loc = new_theme_file;
log_info("Loading theme \"%s\"", theme_name);
- if (theme != NULL) {
+ if (theme) {
g_key_file_free(theme);
}
theme = g_key_file_new();
@@ -192,7 +193,9 @@ GSList *
theme_list(void)
{
GSList *result = NULL;
- _theme_list_dir(_get_themes_dir(), &result);
+ char *themes_dir = _get_themes_dir();
+ _theme_list_dir(themes_dir, &result);
+ free(themes_dir);
#ifdef THEMES_PATH
_theme_list_dir(THEMES_PATH, &result);
#endif
@@ -202,10 +205,10 @@ theme_list(void)
void
theme_close(void)
{
- if (theme != NULL) {
+ if (theme) {
g_key_file_free(theme);
}
- if (theme_loc != NULL) {
+ if (theme_loc) {
g_string_free(theme_loc, TRUE);
}
if (bold_items) {
@@ -249,47 +252,48 @@ theme_init_colours(void)
// chat
init_pair(25, colour_prefs.me, colour_prefs.bkgnd);
init_pair(26, colour_prefs.them, colour_prefs.bkgnd);
+ init_pair(27, colour_prefs.receiptsent, colour_prefs.bkgnd);
// room chat
- init_pair(27, colour_prefs.roominfo, colour_prefs.bkgnd);
- init_pair(28, colour_prefs.roommention, colour_prefs.bkgnd);
+ init_pair(28, colour_prefs.roominfo, colour_prefs.bkgnd);
+ init_pair(29, colour_prefs.roommention, colour_prefs.bkgnd);
// statuses
- init_pair(29, colour_prefs.online, colour_prefs.bkgnd);
- init_pair(30, colour_prefs.offline, colour_prefs.bkgnd);
- init_pair(31, colour_prefs.away, colour_prefs.bkgnd);
- init_pair(32, colour_prefs.chat, colour_prefs.bkgnd);
- init_pair(33, colour_prefs.dnd, colour_prefs.bkgnd);
- init_pair(34, colour_prefs.xa, colour_prefs.bkgnd);
+ init_pair(30, colour_prefs.online, colour_prefs.bkgnd);
+ init_pair(31, colour_prefs.offline, colour_prefs.bkgnd);
+ init_pair(32, colour_prefs.away, colour_prefs.bkgnd);
+ init_pair(33, colour_prefs.chat, colour_prefs.bkgnd);
+ init_pair(34, colour_prefs.dnd, colour_prefs.bkgnd);
+ init_pair(35, colour_prefs.xa, colour_prefs.bkgnd);
// states
- init_pair(35, colour_prefs.typing, colour_prefs.bkgnd);
- init_pair(36, colour_prefs.gone, colour_prefs.bkgnd);
+ init_pair(36, colour_prefs.typing, colour_prefs.bkgnd);
+ init_pair(37, colour_prefs.gone, colour_prefs.bkgnd);
// subscription status
- init_pair(37, colour_prefs.subscribed, colour_prefs.bkgnd);
- init_pair(38, colour_prefs.unsubscribed, colour_prefs.bkgnd);
+ init_pair(38, colour_prefs.subscribed, colour_prefs.bkgnd);
+ init_pair(39, colour_prefs.unsubscribed, colour_prefs.bkgnd);
// otr messages
- init_pair(39, colour_prefs.otrstartedtrusted, colour_prefs.bkgnd);
- init_pair(40, colour_prefs.otrstarteduntrusted, colour_prefs.bkgnd);
- init_pair(41, colour_prefs.otrended, colour_prefs.bkgnd);
- init_pair(42, colour_prefs.otrtrusted, colour_prefs.bkgnd);
- init_pair(43, colour_prefs.otruntrusted, colour_prefs.bkgnd);
+ init_pair(40, colour_prefs.otrstartedtrusted, colour_prefs.bkgnd);
+ init_pair(41, colour_prefs.otrstarteduntrusted, colour_prefs.bkgnd);
+ init_pair(42, colour_prefs.otrended, colour_prefs.bkgnd);
+ init_pair(43, colour_prefs.otrtrusted, colour_prefs.bkgnd);
+ init_pair(44, colour_prefs.otruntrusted, colour_prefs.bkgnd);
// subwin headers
- init_pair(44, colour_prefs.rosterheader, colour_prefs.bkgnd);
- init_pair(45, colour_prefs.occupantsheader, colour_prefs.bkgnd);
+ init_pair(45, colour_prefs.rosterheader, colour_prefs.bkgnd);
+ init_pair(46, colour_prefs.occupantsheader, colour_prefs.bkgnd);
// raw
- init_pair(46, COLOR_WHITE, colour_prefs.bkgnd);
- init_pair(47, COLOR_GREEN, colour_prefs.bkgnd);
- init_pair(48, COLOR_RED, colour_prefs.bkgnd);
- init_pair(49, COLOR_YELLOW, colour_prefs.bkgnd);
- init_pair(50, COLOR_BLUE, colour_prefs.bkgnd);
- init_pair(51, COLOR_CYAN, colour_prefs.bkgnd);
- init_pair(52, COLOR_BLACK, colour_prefs.bkgnd);
- init_pair(53, COLOR_MAGENTA, colour_prefs.bkgnd);
+ init_pair(47, COLOR_WHITE, colour_prefs.bkgnd);
+ init_pair(48, COLOR_GREEN, colour_prefs.bkgnd);
+ init_pair(49, COLOR_RED, colour_prefs.bkgnd);
+ init_pair(50, COLOR_YELLOW, colour_prefs.bkgnd);
+ init_pair(51, COLOR_BLUE, colour_prefs.bkgnd);
+ init_pair(52, COLOR_CYAN, colour_prefs.bkgnd);
+ init_pair(53, COLOR_BLACK, colour_prefs.bkgnd);
+ init_pair(54, COLOR_MAGENTA, colour_prefs.bkgnd);
}
static NCURSES_COLOR_T
@@ -395,6 +399,7 @@ _load_colours(void)
_set_colour("them", &colour_prefs.them, COLOR_GREEN, THEME_THEM);
_set_colour("roster.header", &colour_prefs.rosterheader, COLOR_YELLOW, THEME_ROSTER_HEADER);
_set_colour("occupants.header", &colour_prefs.occupantsheader, COLOR_YELLOW, THEME_OCCUPANTS_HEADER);
+ _set_colour("receipt.sent", &colour_prefs.receiptsent, COLOR_RED, THEME_RECEIPT_SENT);
}
static void
@@ -419,20 +424,22 @@ _set_boolean_preference(char *prefstr, preference_t pref)
static void
_load_preferences(void)
{
- _set_boolean_preference("intype", PREF_INTYPE);
_set_boolean_preference("beep", PREF_BEEP);
_set_boolean_preference("flash", PREF_FLASH);
- _set_boolean_preference("privileges", PREF_MUC_PRIVILEGES);
- _set_boolean_preference("presence", PREF_PRESENCE);
+ _set_boolean_preference("splash", PREF_SPLASH);
_set_boolean_preference("wrap", PREF_WRAP);
-
_set_string_preference("time", PREF_TIME);
- _set_string_preference("statuses.muc", PREF_STATUSES_MUC);
+ _set_string_preference("time.statusbar", PREF_TIME_STATUSBAR);
+
+ _set_boolean_preference("resource.title", PREF_RESOURCE_TITLE);
+ _set_boolean_preference("resource.message", PREF_RESOURCE_MESSAGE);
+
_set_string_preference("statuses.console", PREF_STATUSES_CONSOLE);
_set_string_preference("statuses.chat", PREF_STATUSES_CHAT);
+ _set_string_preference("statuses.muc", PREF_STATUSES_MUC);
_set_boolean_preference("occupants", PREF_OCCUPANTS);
-
+ _set_boolean_preference("occupants.jid", PREF_OCCUPANTS_JID);
if (g_key_file_has_key(theme, "ui", "occupants.size", NULL)) {
gint occupants_size = g_key_file_get_integer(theme, "ui", "occupants.size", NULL);
prefs_set_occupants_size(occupants_size);
@@ -442,12 +449,16 @@ _load_preferences(void)
_set_boolean_preference("roster.offline", PREF_ROSTER_OFFLINE);
_set_boolean_preference("roster.resource", PREF_ROSTER_RESOURCE);
_set_string_preference("roster.by", PREF_ROSTER_BY);
-
if (g_key_file_has_key(theme, "ui", "roster.size", NULL)) {
gint roster_size = g_key_file_get_integer(theme, "ui", "roster.size", NULL);
prefs_set_roster_size(roster_size);
}
+ _set_boolean_preference("privileges", PREF_MUC_PRIVILEGES);
+
+ _set_boolean_preference("presence", PREF_PRESENCE);
+ _set_boolean_preference("intype", PREF_INTYPE);
+
_set_boolean_preference("otr.warn", PREF_OTR_WARN);
}
@@ -465,9 +476,9 @@ void
_theme_list_dir(const gchar * const dir, GSList **result)
{
GDir *themes = g_dir_open(dir, 0, NULL);
- if (themes != NULL) {
+ if (themes) {
const gchar *theme = g_dir_read_name(themes);
- while (theme != NULL) {
+ while (theme) {
*result = g_slist_append(*result, strdup(theme));
theme = g_dir_read_name(themes);
}
@@ -481,7 +492,7 @@ _theme_find(const char * const theme_name)
GString *path = NULL;
gchar *themes_dir = _get_themes_dir();
- if (themes_dir != NULL) {
+ if (themes_dir) {
path = g_string_new(themes_dir);
g_free(themes_dir);
g_string_append(path, "/");
@@ -557,42 +568,43 @@ theme_attrs(theme_item_t attrs)
case THEME_STATUS_NEW: result = COLOR_PAIR(24); break;
case THEME_ME: result = COLOR_PAIR(25); break;
case THEME_THEM: result = COLOR_PAIR(26); break;
- case THEME_ROOMINFO: result = COLOR_PAIR(27); break;
- case THEME_ROOMMENTION: result = COLOR_PAIR(28); break;
- case THEME_ONLINE: result = COLOR_PAIR(29); break;
- case THEME_OFFLINE: result = COLOR_PAIR(30); break;
- case THEME_AWAY: result = COLOR_PAIR(31); break;
- case THEME_CHAT: result = COLOR_PAIR(32); break;
- case THEME_DND: result = COLOR_PAIR(33); break;
- case THEME_XA: result = COLOR_PAIR(34); break;
- case THEME_TYPING: result = COLOR_PAIR(35); break;
- case THEME_GONE: result = COLOR_PAIR(36); break;
- case THEME_SUBSCRIBED: result = COLOR_PAIR(37); break;
- case THEME_UNSUBSCRIBED: result = COLOR_PAIR(38); break;
- case THEME_OTR_STARTED_TRUSTED: result = COLOR_PAIR(39); break;
- case THEME_OTR_STARTED_UNTRUSTED: result = COLOR_PAIR(40); break;
- case THEME_OTR_ENDED: result = COLOR_PAIR(41); break;
- case THEME_OTR_TRUSTED: result = COLOR_PAIR(42); break;
- case THEME_OTR_UNTRUSTED: result = COLOR_PAIR(43); break;
- case THEME_ROSTER_HEADER: result = COLOR_PAIR(44); break;
- case THEME_OCCUPANTS_HEADER: result = COLOR_PAIR(45); break;
- case THEME_WHITE: result = COLOR_PAIR(46); break;
- case THEME_WHITE_BOLD: result = COLOR_PAIR(46); break;
- case THEME_GREEN: result = COLOR_PAIR(47); break;
- case THEME_GREEN_BOLD: result = COLOR_PAIR(47); break;
- case THEME_RED: result = COLOR_PAIR(48); break;
- case THEME_RED_BOLD: result = COLOR_PAIR(48); break;
- case THEME_YELLOW: result = COLOR_PAIR(49); break;
- case THEME_YELLOW_BOLD: result = COLOR_PAIR(49); break;
- case THEME_BLUE: result = COLOR_PAIR(50); break;
- case THEME_BLUE_BOLD: result = COLOR_PAIR(50); break;
- case THEME_CYAN: result = COLOR_PAIR(51); break;
- case THEME_CYAN_BOLD: result = COLOR_PAIR(51); break;
- case THEME_BLACK: result = COLOR_PAIR(52); break;
- case THEME_BLACK_BOLD: result = COLOR_PAIR(52); break;
- case THEME_MAGENTA: result = COLOR_PAIR(53); break;
- case THEME_MAGENTA_BOLD: result = COLOR_PAIR(53); break;
- default: break;
+ case THEME_RECEIPT_SENT: result = COLOR_PAIR(27); break;
+ case THEME_ROOMINFO: result = COLOR_PAIR(28); break;
+ case THEME_ROOMMENTION: result = COLOR_PAIR(29); break;
+ case THEME_ONLINE: result = COLOR_PAIR(30); break;
+ case THEME_OFFLINE: result = COLOR_PAIR(31); break;
+ case THEME_AWAY: result = COLOR_PAIR(32); break;
+ case THEME_CHAT: result = COLOR_PAIR(33); break;
+ case THEME_DND: result = COLOR_PAIR(34); break;
+ case THEME_XA: result = COLOR_PAIR(35); break;
+ case THEME_TYPING: result = COLOR_PAIR(36); break;
+ case THEME_GONE: result = COLOR_PAIR(37); break;
+ case THEME_SUBSCRIBED: result = COLOR_PAIR(38); break;
+ case THEME_UNSUBSCRIBED: result = COLOR_PAIR(39); break;
+ case THEME_OTR_STARTED_TRUSTED: result = COLOR_PAIR(40); break;
+ case THEME_OTR_STARTED_UNTRUSTED: result = COLOR_PAIR(41); break;
+ case THEME_OTR_ENDED: result = COLOR_PAIR(42); break;
+ case THEME_OTR_TRUSTED: result = COLOR_PAIR(43); break;
+ case THEME_OTR_UNTRUSTED: result = COLOR_PAIR(44); break;
+ case THEME_ROSTER_HEADER: result = COLOR_PAIR(45); break;
+ case THEME_OCCUPANTS_HEADER: result = COLOR_PAIR(46); break;
+ case THEME_WHITE: result = COLOR_PAIR(47); break;
+ case THEME_WHITE_BOLD: result = COLOR_PAIR(47); break;
+ case THEME_GREEN: result = COLOR_PAIR(48); break;
+ case THEME_GREEN_BOLD: result = COLOR_PAIR(48); break;
+ case THEME_RED: result = COLOR_PAIR(49); break;
+ case THEME_RED_BOLD: result = COLOR_PAIR(49); break;
+ case THEME_YELLOW: result = COLOR_PAIR(50); break;
+ case THEME_YELLOW_BOLD: result = COLOR_PAIR(50); break;
+ case THEME_BLUE: result = COLOR_PAIR(51); break;
+ case THEME_BLUE_BOLD: result = COLOR_PAIR(51); break;
+ case THEME_CYAN: result = COLOR_PAIR(52); break;
+ case THEME_CYAN_BOLD: result = COLOR_PAIR(52); break;
+ case THEME_BLACK: result = COLOR_PAIR(53); break;
+ case THEME_BLACK_BOLD: result = COLOR_PAIR(53); break;
+ case THEME_MAGENTA: result = COLOR_PAIR(54); break;
+ case THEME_MAGENTA_BOLD: result = COLOR_PAIR(54); break;
+ default: break;
}
if (g_hash_table_lookup(bold_items, GINT_TO_POINTER(attrs))) {
diff --git a/src/config/theme.h b/src/config/theme.h
index a6a580f8..13099eb4 100644
--- a/src/config/theme.h
+++ b/src/config/theme.h
@@ -1,7 +1,7 @@
/*
* theme.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -90,6 +90,7 @@ typedef enum {
THEME_OTR_UNTRUSTED,
THEME_OCCUPANTS_HEADER,
THEME_ROSTER_HEADER,
+ THEME_RECEIPT_SENT,
THEME_NONE,
THEME_WHITE,
THEME_WHITE_BOLD,
diff --git a/src/contact.c b/src/contact.c
index f16f1679..713af955 100644
--- a/src/contact.c
+++ b/src/contact.c
@@ -1,7 +1,7 @@
/*
* contact.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -45,7 +45,9 @@
struct p_contact_t {
char *barejid;
+ gchar *barejid_collate_key;
char *name;
+ gchar *name_collate_key;
GSList *groups;
char *subscription;
char *offline_message;
@@ -62,21 +64,24 @@ p_contact_new(const char * const barejid, const char * const name,
{
PContact contact = malloc(sizeof(struct p_contact_t));
contact->barejid = strdup(barejid);
+ contact->barejid_collate_key = g_utf8_collate_key(contact->barejid, -1);
- if (name != NULL) {
+ if (name) {
contact->name = strdup(name);
+ contact->name_collate_key = g_utf8_collate_key(contact->name, -1);
} else {
contact->name = NULL;
+ contact->name_collate_key = NULL;
}
contact->groups = groups;
- if (subscription != NULL)
+ if (subscription)
contact->subscription = strdup(subscription);
else
contact->subscription = strdup("none");
- if (offline_message != NULL)
+ if (offline_message)
contact->offline_message = strdup(offline_message);
else
contact->offline_message = NULL;
@@ -96,15 +101,17 @@ void
p_contact_set_name(const PContact contact, const char * const name)
{
FREE_SET_NULL(contact->name);
- if (name != NULL) {
+ FREE_SET_NULL(contact->name_collate_key);
+ if (name) {
contact->name = strdup(name);
+ contact->name_collate_key = g_utf8_collate_key(contact->name, -1);
}
}
void
p_contact_set_groups(const PContact contact, GSList *groups)
{
- if (contact->groups != NULL) {
+ if (contact->groups) {
g_slist_free_full(contact->groups, g_free);
contact->groups = NULL;
}
@@ -116,7 +123,7 @@ gboolean
p_contact_in_group(const PContact contact, const char * const group)
{
GSList *groups = contact->groups;
- while (groups != NULL) {
+ while (groups) {
if (strcmp(groups->data, group) == 0) {
return TRUE;
}
@@ -144,17 +151,19 @@ p_contact_remove_resource(PContact contact, const char * const resource)
void
p_contact_free(PContact contact)
{
- if (contact != NULL) {
+ if (contact) {
free(contact->barejid);
+ free(contact->barejid_collate_key);
free(contact->name);
+ free(contact->name_collate_key);
free(contact->subscription);
free(contact->offline_message);
- if (contact->groups != NULL) {
+ if (contact->groups) {
g_slist_free_full(contact->groups, g_free);
}
- if (contact->last_activity != NULL) {
+ if (contact->last_activity) {
g_date_time_unref(contact->last_activity);
}
@@ -170,16 +179,28 @@ p_contact_barejid(const PContact contact)
return contact->barejid;
}
+const char *
+p_contact_barejid_collate_key(const PContact contact)
+{
+ return contact->barejid_collate_key;
+}
+
const char *
p_contact_name(const PContact contact)
{
return contact->name;
}
+const char *
+p_contact_name_collate_key(const PContact contact)
+{
+ return contact->name_collate_key;
+}
+
const char *
p_contact_name_or_jid(const PContact contact)
{
- if (contact->name != NULL) {
+ if (contact->name) {
return contact->name;
} else {
return contact->barejid;
@@ -247,7 +268,7 @@ _get_most_available_resource(PContact contact)
Resource *current = curr->data;
Resource *highest = current;
curr = g_list_next(curr);
- while (curr != NULL) {
+ while (curr) {
current = curr->data;
// priority is same as current highest, choose presence
@@ -381,14 +402,14 @@ void
p_contact_set_presence(const PContact contact, Resource *resource)
{
g_hash_table_replace(contact->available_resources, strdup(resource->name), resource);
- autocomplete_add(contact->resource_ac, strdup(resource->name));
+ autocomplete_add(contact->resource_ac, resource->name);
}
void
p_contact_set_subscription(const PContact contact, const char * const subscription)
{
FREE_SET_NULL(contact->subscription);
- if (subscription != NULL) {
+ if (subscription) {
contact->subscription = strdup(subscription);
}
}
@@ -402,12 +423,12 @@ p_contact_set_pending_out(const PContact contact, gboolean pending_out)
void
p_contact_set_last_activity(const PContact contact, GDateTime *last_activity)
{
- if (contact->last_activity != NULL) {
+ if (contact->last_activity) {
g_date_time_unref(contact->last_activity);
contact->last_activity = NULL;
}
- if (last_activity != NULL) {
+ if (last_activity) {
contact->last_activity = g_date_time_ref(last_activity);
}
}
diff --git a/src/contact.h b/src/contact.h
index 17a3b210..343b230f 100644
--- a/src/contact.h
+++ b/src/contact.h
@@ -1,7 +1,7 @@
/*
* contact.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -47,7 +47,9 @@ void p_contact_add_resource(PContact contact, Resource *resource);
gboolean p_contact_remove_resource(PContact contact, const char * const resource);
void p_contact_free(PContact contact);
const char* p_contact_barejid(PContact contact);
+const char* p_contact_barejid_collate_key(PContact contact);
const char* p_contact_name(PContact contact);
+const char* p_contact_name_collate_key(PContact contact);
const char* p_contact_name_or_jid(const PContact contact);
const char* p_contact_presence(PContact contact);
const char* p_contact_status(PContact contact);
diff --git a/src/event/client_events.c b/src/event/client_events.c
new file mode 100644
index 00000000..f0f763a6
--- /dev/null
+++ b/src/event/client_events.c
@@ -0,0 +1,95 @@
+/*
+ * client_events.c
+ *
+ * Copyright (C) 2012 - 2015 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 .
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ */
+
+#include
+
+#include "config.h"
+#include "log.h"
+#include "ui/ui.h"
+#include "ui/windows.h"
+#include "xmpp/xmpp.h"
+#ifdef HAVE_LIBOTR
+#include "otr/otr.h"
+#endif
+
+jabber_conn_status_t
+cl_ev_connect_jid(const char * const jid, const char * const passwd, const char * const altdomain, const int port)
+{
+ cons_show("Connecting as %s", jid);
+ return jabber_connect_with_details(jid, passwd, altdomain, port);
+}
+
+jabber_conn_status_t
+cl_ev_connect_account(ProfAccount *account)
+{
+ char *jid = account_create_full_jid(account);
+ cons_show("Connecting with account %s as %s", account->name, jid);
+ free(jid);
+
+ return jabber_connect_with_account(account);
+}
+
+void
+cl_ev_presence_send(const resource_presence_t presence_type, const char * const msg, const int idle)
+{
+ presence_send(presence_type, msg, idle);
+}
+
+void
+cl_ev_send_msg(ProfChatWin *chatwin, const char * const msg)
+{
+ chat_state_active(chatwin->state);
+
+#ifdef HAVE_LIBOTR
+ otr_on_message_send(chatwin, msg);
+#else
+ char *id = message_send_chat(chatwin->barejid, msg);
+ chat_log_msg_out(chatwin->barejid, msg);
+ ui_outgoing_chat_msg(chatwin, msg, id);
+ free(id);
+#endif
+}
+
+void
+cl_ev_send_muc_msg(ProfMucWin *mucwin, const char * const msg)
+{
+ message_send_groupchat(mucwin->roomjid, msg);
+}
+
+void
+cl_ev_send_priv_msg(ProfPrivateWin *privwin, const char * const msg)
+{
+ message_send_private(privwin->fulljid, msg);
+ ui_outgoing_private_msg(privwin, msg);
+}
\ No newline at end of file
diff --git a/src/event/client_events.h b/src/event/client_events.h
new file mode 100644
index 00000000..207299c5
--- /dev/null
+++ b/src/event/client_events.h
@@ -0,0 +1,47 @@
+/*
+ * client_events.h
+ *
+ * Copyright (C) 2012 - 2015 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 .
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ */
+
+#ifndef CLIENT_EVENTS_H
+#define CLIENT_EVENTS_H
+
+jabber_conn_status_t cl_ev_connect_jid(const char * const jid, const char * const passwd, const char * const altdomain, const int port);
+jabber_conn_status_t cl_ev_connect_account(ProfAccount *account);
+
+void cl_ev_presence_send(const resource_presence_t presence_type, const char * const msg, const int idle);
+
+void cl_ev_send_msg(ProfChatWin *chatwin, const char * const msg);
+void cl_ev_send_muc_msg(ProfMucWin *mucwin, const char * const msg);
+void cl_ev_send_priv_msg(ProfPrivateWin *privwin, const char * const msg);
+
+#endif
\ No newline at end of file
diff --git a/src/event/server_events.c b/src/event/server_events.c
new file mode 100644
index 00000000..e2e910a3
--- /dev/null
+++ b/src/event/server_events.c
@@ -0,0 +1,522 @@
+/*
+ * server_events.c
+ *
+ * Copyright (C) 2012 - 2015 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 .
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ */
+
+#include
+#include
+
+#include "config.h"
+
+#include "chat_session.h"
+#include "log.h"
+#include "muc.h"
+#include "config/preferences.h"
+#include "config/account.h"
+#include "roster_list.h"
+
+#ifdef HAVE_LIBOTR
+#include "otr/otr.h"
+#endif
+
+#include "ui/ui.h"
+
+void
+sv_ev_login_account_success(char *account_name)
+{
+ ProfAccount *account = accounts_get_account(account_name);
+
+#ifdef HAVE_LIBOTR
+ otr_on_connect(account);
+#endif
+
+ ui_handle_login_account_success(account);
+
+ // attempt to rejoin rooms with passwords
+ GList *curr = muc_rooms();
+ while (curr) {
+ char *password = muc_password(curr->data);
+ if (password) {
+ char *nick = muc_nick(curr->data);
+ presence_join_room(curr->data, nick, password);
+ }
+ curr = g_list_next(curr);
+ }
+ g_list_free(curr);
+
+ log_info("%s logged in successfully", account->jid);
+ account_free(account);
+}
+
+void
+sv_ev_roster_received(void)
+{
+ if (prefs_get_boolean(PREF_ROSTER)) {
+ ui_show_roster();
+ }
+}
+
+void
+sv_ev_lost_connection(void)
+{
+ cons_show_error("Lost connection.");
+ roster_clear();
+ muc_invites_clear();
+ chat_sessions_clear();
+ ui_disconnected();
+}
+
+void
+sv_ev_failed_login(void)
+{
+ cons_show_error("Login failed.");
+ log_info("Login failed");
+}
+
+void
+sv_ev_room_invite(jabber_invite_t invite_type,
+ const char * const invitor, const char * const room,
+ const char * const reason, const char * const password)
+{
+ if (!muc_active(room) && !muc_invites_contain(room)) {
+ cons_show_room_invite(invitor, room, reason);
+ muc_invites_add(room, password);
+ }
+}
+
+void
+sv_ev_room_broadcast(const char *const room_jid,
+ const char * const message)
+{
+ if (muc_roster_complete(room_jid)) {
+ ui_room_broadcast(room_jid, message);
+ } else {
+ muc_pending_broadcasts_add(room_jid, message);
+ }
+}
+
+void
+sv_ev_room_subject(const char * const room, const char * const nick, const char * const subject)
+{
+ muc_set_subject(room, subject);
+ if (muc_roster_complete(room)) {
+ ui_room_subject(room, nick, subject);
+ }
+}
+
+void
+sv_ev_room_history(const char * const room_jid, const char * const nick,
+ GTimeVal tv_stamp, const char * const message)
+{
+ ui_room_history(room_jid, nick, tv_stamp, message);
+}
+
+void
+sv_ev_room_message(const char * const room_jid, const char * const nick,
+ const char * const message)
+{
+ ui_room_message(room_jid, nick, message);
+
+ if (prefs_get_boolean(PREF_GRLOG)) {
+ Jid *jid = jid_create(jabber_get_fulljid());
+ groupchat_log_chat(jid->barejid, room_jid, nick, message);
+ jid_destroy(jid);
+ }
+}
+
+void
+sv_ev_incoming_private_message(const char * const fulljid, char *message)
+{
+ ui_incoming_private_msg(fulljid, message, NULL);
+}
+
+void
+sv_ev_carbon(char *barejid, char *message)
+{
+ ui_outgoing_chat_msg_carbon(barejid, message);
+}
+
+void
+sv_ev_incoming_message(char *barejid, char *resource, char *message)
+{
+#ifdef HAVE_LIBOTR
+ otr_on_message_recv(barejid, resource, message);
+#else
+ ui_incoming_msg(barejid, resource, message, NULL);
+ chat_log_msg_in(barejid, message);
+#endif
+}
+
+void
+sv_ev_delayed_private_message(const char * const fulljid, char *message, GTimeVal tv_stamp)
+{
+ ui_incoming_private_msg(fulljid, message, &tv_stamp);
+}
+
+void
+sv_ev_delayed_message(char *barejid, char *message, GTimeVal tv_stamp)
+{
+ ui_incoming_msg(barejid, NULL, message, &tv_stamp);
+ chat_log_msg_in_delayed(barejid, message, &tv_stamp);
+}
+
+void
+sv_ev_message_receipt(char *barejid, char *id)
+{
+ ui_message_receipt(barejid, id);
+}
+
+void
+sv_ev_typing(char *barejid, char *resource)
+{
+ ui_contact_typing(barejid, resource);
+ if (ui_chat_win_exists(barejid)) {
+ chat_session_recipient_typing(barejid, resource);
+ }
+}
+
+void
+sv_ev_paused(char *barejid, char *resource)
+{
+ if (ui_chat_win_exists(barejid)) {
+ chat_session_recipient_paused(barejid, resource);
+ }
+}
+
+void
+sv_ev_inactive(char *barejid, char *resource)
+{
+ if (ui_chat_win_exists(barejid)) {
+ chat_session_recipient_inactive(barejid, resource);
+ }
+}
+
+void
+sv_ev_gone(const char * const barejid, const char * const resource)
+{
+ ui_recipient_gone(barejid, resource);
+ if (ui_chat_win_exists(barejid)) {
+ chat_session_recipient_gone(barejid, resource);
+ }
+}
+
+void
+sv_ev_activity(const char * const barejid, const char * const resource, gboolean send_states)
+{
+ if (ui_chat_win_exists(barejid)) {
+ chat_session_recipient_active(barejid, resource, send_states);
+ }
+}
+
+void
+sv_ev_subscription(const char *barejid, jabber_subscr_t type)
+{
+ switch (type) {
+ case PRESENCE_SUBSCRIBE:
+ /* TODO: auto-subscribe if needed */
+ cons_show("Received authorization request from %s", barejid);
+ log_info("Received authorization request from %s", barejid);
+ ui_print_system_msg_from_recipient(barejid, "Authorization request, type '/sub allow' to accept or '/sub deny' to reject");
+ if (prefs_get_boolean(PREF_NOTIFY_SUB)) {
+ notify_subscription(barejid);
+ }
+ break;
+ case PRESENCE_SUBSCRIBED:
+ cons_show("Subscription received from %s", barejid);
+ log_info("Subscription received from %s", barejid);
+ ui_print_system_msg_from_recipient(barejid, "Subscribed");
+ break;
+ case PRESENCE_UNSUBSCRIBED:
+ cons_show("%s deleted subscription", barejid);
+ log_info("%s deleted subscription", barejid);
+ ui_print_system_msg_from_recipient(barejid, "Unsubscribed");
+ break;
+ default:
+ /* unknown type */
+ break;
+ }
+}
+
+void
+sv_ev_contact_offline(char *barejid, char *resource, char *status)
+{
+ gboolean updated = roster_contact_offline(barejid, resource, status);
+
+ if (resource && updated) {
+ ui_contact_offline(barejid, resource, status);
+ }
+
+ rosterwin_roster();
+ chat_session_remove(barejid);
+}
+
+void
+sv_ev_contact_online(char *barejid, Resource *resource, GDateTime *last_activity)
+{
+ gboolean updated = roster_update_presence(barejid, resource, last_activity);
+
+ if (updated) {
+ ui_contact_online(barejid, resource, last_activity);
+ }
+
+ rosterwin_roster();
+ chat_session_remove(barejid);
+}
+
+void
+sv_ev_leave_room(const char * const room)
+{
+ muc_leave(room);
+ ui_leave_room(room);
+}
+
+void
+sv_ev_room_destroy(const char * const room)
+{
+ muc_leave(room);
+ ui_room_destroy(room);
+}
+
+void
+sv_ev_room_destroyed(const char * const room, const char * const new_jid, const char * const password,
+ const char * const reason)
+{
+ muc_leave(room);
+ ui_room_destroyed(room, reason, new_jid, password);
+}
+
+void
+sv_ev_room_kicked(const char * const room, const char * const actor, const char * const reason)
+{
+ muc_leave(room);
+ ui_room_kicked(room, actor, reason);
+}
+
+void
+sv_ev_room_banned(const char * const room, const char * const actor, const char * const reason)
+{
+ muc_leave(room);
+ ui_room_banned(room, actor, reason);
+}
+
+void
+sv_ev_room_occupant_offline(const char * const room, const char * const nick,
+ const char * const show, const char * const status)
+{
+ muc_roster_remove(room, nick);
+
+ char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
+ if (g_strcmp0(muc_status_pref, "none") != 0) {
+ ui_room_member_offline(room, nick);
+ }
+ prefs_free_string(muc_status_pref);
+ occupantswin_occupants(room);
+}
+
+void
+sv_ev_room_occupent_kicked(const char * const room, const char * const nick, const char * const actor,
+ const char * const reason)
+{
+ muc_roster_remove(room, nick);
+ ui_room_member_kicked(room, nick, actor, reason);
+ occupantswin_occupants(room);
+}
+
+void
+sv_ev_room_occupent_banned(const char * const room, const char * const nick, const char * const actor,
+ const char * const reason)
+{
+ muc_roster_remove(room, nick);
+ ui_room_member_banned(room, nick, actor, reason);
+ occupantswin_occupants(room);
+}
+
+void
+sv_ev_roster_update(const char * const barejid, const char * const name,
+ GSList *groups, const char * const subscription, gboolean pending_out)
+{
+ roster_update(barejid, name, groups, subscription, pending_out);
+ rosterwin_roster();
+}
+
+void
+sv_ev_xmpp_stanza(const char * const msg)
+{
+ ui_handle_stanza(msg);
+}
+
+void
+sv_ev_muc_self_online(const char * const room, const char * const nick, gboolean config_required,
+ const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
+ const char * const jid, const char * const show, const char * const status)
+{
+ muc_roster_add(room, nick, jid, role, affiliation, show, status);
+ char *old_role = muc_role_str(room);
+ char *old_affiliation = muc_affiliation_str(room);
+ muc_set_role(room, role);
+ muc_set_affiliation(room, affiliation);
+
+ // handle self nick change
+ if (muc_nick_change_pending(room)) {
+ muc_nick_change_complete(room, nick);
+ ui_room_nick_change(room, nick);
+
+ // handle roster complete
+ } else if (!muc_roster_complete(room)) {
+ if (muc_autojoin(room)) {
+ ui_room_join(room, FALSE);
+ } else {
+ ui_room_join(room, TRUE);
+ }
+
+ iq_room_info_request(room, FALSE);
+
+ muc_invites_remove(room);
+ muc_roster_set_complete(room);
+
+ // show roster if occupants list disabled by default
+ if (!prefs_get_boolean(PREF_OCCUPANTS)) {
+ GList *occupants = muc_roster(room);
+ ui_room_roster(room, occupants, NULL);
+ g_list_free(occupants);
+ }
+
+ char *subject = muc_subject(room);
+ if (subject) {
+ ui_room_subject(room, NULL, subject);
+ }
+
+ GList *pending_broadcasts = muc_pending_broadcasts(room);
+ if (pending_broadcasts) {
+ GList *curr = pending_broadcasts;
+ while (curr) {
+ ui_room_broadcast(room, curr->data);
+ curr = g_list_next(curr);
+ }
+ }
+
+ // room configuration required
+ if (config_required) {
+ muc_set_requires_config(room, TRUE);
+ ui_room_requires_config(room);
+ }
+
+ // check for change in role/affiliation
+ } else {
+ if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
+ // both changed
+ if ((g_strcmp0(role, old_role) != 0) && (g_strcmp0(affiliation, old_affiliation) != 0)) {
+ ui_room_role_and_affiliation_change(room, role, affiliation, actor, reason);
+
+ // role changed
+ } else if (g_strcmp0(role, old_role) != 0) {
+ ui_room_role_change(room, role, actor, reason);
+
+ // affiliation changed
+ } else if (g_strcmp0(affiliation, old_affiliation) != 0) {
+ ui_room_affiliation_change(room, affiliation, actor, reason);
+ }
+ }
+ }
+
+ occupantswin_occupants(room);
+}
+
+void
+sv_ev_muc_occupant_online(const char * const room, const char * const nick, const char * const jid,
+ const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
+ const char * const show, const char * const status)
+{
+ Occupant *occupant = muc_roster_item(room, nick);
+
+ const char *old_role = NULL;
+ const char *old_affiliation = NULL;
+ if (occupant) {
+ old_role = muc_occupant_role_str(occupant);
+ old_affiliation = muc_occupant_affiliation_str(occupant);
+ }
+
+ gboolean updated = muc_roster_add(room, nick, jid, role, affiliation, show, status);
+
+ // not yet finished joining room
+ if (!muc_roster_complete(room)) {
+ return;
+ }
+
+ // handle nickname change
+ char *old_nick = muc_roster_nick_change_complete(room, nick);
+ if (old_nick) {
+ ui_room_member_nick_change(room, old_nick, nick);
+ free(old_nick);
+ occupantswin_occupants(room);
+ return;
+ }
+
+ // joined room
+ if (!occupant) {
+ char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
+ if (g_strcmp0(muc_status_pref, "none") != 0) {
+ ui_room_member_online(room, nick, role, affiliation, show, status);
+ }
+ prefs_free_string(muc_status_pref);
+ occupantswin_occupants(room);
+ return;
+ }
+
+ // presence updated
+ if (updated) {
+ char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
+ if (g_strcmp0(muc_status_pref, "all") == 0) {
+ ui_room_member_presence(room, nick, show, status);
+ }
+ prefs_free_string(muc_status_pref);
+ occupantswin_occupants(room);
+
+ // presence unchanged, check for role/affiliation change
+ } else {
+ if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
+ // both changed
+ if ((g_strcmp0(role, old_role) != 0) && (g_strcmp0(affiliation, old_affiliation) != 0)) {
+ ui_room_occupant_role_and_affiliation_change(room, nick, role, affiliation, actor, reason);
+
+ // role changed
+ } else if (g_strcmp0(role, old_role) != 0) {
+ ui_room_occupant_role_change(room, nick, role, actor, reason);
+
+ // affiliation changed
+ } else if (g_strcmp0(affiliation, old_affiliation) != 0) {
+ ui_room_occupant_affiliation_change(room, nick, affiliation, actor, reason);
+ }
+ }
+ occupantswin_occupants(room);
+ }
+}
diff --git a/src/event/server_events.h b/src/event/server_events.h
new file mode 100644
index 00000000..46d485da
--- /dev/null
+++ b/src/event/server_events.h
@@ -0,0 +1,91 @@
+/*
+ * server_events.h
+ *
+ * Copyright (C) 2012 - 2015 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 .
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ */
+
+#ifndef SERVER_EVENTS_H
+#define SERVER_EVENTS_H
+
+#include "xmpp/xmpp.h"
+
+void sv_ev_login_account_success(char *account_name);
+void sv_ev_lost_connection(void);
+void sv_ev_failed_login(void);
+void sv_ev_room_invite(jabber_invite_t invite_type,
+ const char * const invitor, const char * const room,
+ const char * const reason, const char * const password);
+void sv_ev_room_broadcast(const char *const room_jid,
+ const char * const message);
+void sv_ev_room_subject(const char * const room, const char * const nick, const char * const subject);
+void sv_ev_room_history(const char * const room_jid, const char * const nick,
+ GTimeVal tv_stamp, const char * const message);
+void sv_ev_room_message(const char * const room_jid, const char * const nick,
+ const char * const message);
+void sv_ev_incoming_message(char *barejid, char *resource, char *message);
+void sv_ev_incoming_private_message(const char * const fulljid, char *message);
+void sv_ev_delayed_message(char *fulljid, char *message, GTimeVal tv_stamp);
+void sv_ev_delayed_private_message(const char * const fulljid, char *message, GTimeVal tv_stamp);
+void sv_ev_typing(char *barejid, char *resource);
+void sv_ev_paused(char *barejid, char *resource);
+void sv_ev_inactive(char *barejid, char *resource);
+void sv_ev_activity(char *barejid, char *resource, gboolean send_states);
+void sv_ev_gone(const char * const barejid, const char * const resource);
+void sv_ev_subscription(const char *from, jabber_subscr_t type);
+void sv_ev_message_receipt(char *barejid, char *id);
+void sv_ev_contact_offline(char *contact, char *resource, char *status);
+void sv_ev_contact_online(char *contact, Resource *resource,
+ GDateTime *last_activity);
+void sv_ev_leave_room(const char * const room);
+void sv_ev_room_destroy(const char * const room);
+void sv_ev_room_occupant_offline(const char * const room, const char * const nick,
+ const char * const show, const char * const status);
+void sv_ev_room_destroyed(const char * const room, const char * const new_jid, const char * const password,
+ const char * const reason);
+void sv_ev_room_kicked(const char * const room, const char * const actor, const char * const reason);
+void sv_ev_room_occupent_kicked(const char * const room, const char * const nick, const char * const actor,
+ const char * const reason);
+void sv_ev_room_banned(const char * const room, const char * const actor, const char * const reason);
+void sv_ev_room_occupent_banned(const char * const room, const char * const nick, const char * const actor,
+ const char * const reason);
+void sv_ev_carbon(char *barejid, char *message);
+void sv_ev_xmpp_stanza(const char * const msg);
+void sv_ev_muc_self_online(const char * const room, const char * const nick, gboolean config_required,
+ const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
+ const char * const jid, const char * const show, const char * const status);
+void sv_ev_muc_occupant_online(const char * const room, const char * const nick, const char * const jid,
+ const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
+ const char * const show_str, const char * const status_str);
+void sv_ev_roster_update(const char * const barejid, const char * const name,
+ GSList *groups, const char * const subscription, gboolean pending_out);
+void sv_ev_roster_received(void);
+
+#endif
diff --git a/src/event/ui_events.c b/src/event/ui_events.c
new file mode 100644
index 00000000..ff1d7273
--- /dev/null
+++ b/src/event/ui_events.c
@@ -0,0 +1,56 @@
+/*
+ * ui_events.c
+ *
+ * Copyright (C) 2012 - 2015 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 .
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ */
+
+#include "ui/ui.h"
+#include "ui/windows.h"
+
+void
+ui_ev_focus_win(ProfWin *win)
+{
+ if (!wins_is_current(win)) {
+ ui_switch_win(win);
+ }
+}
+
+ProfChatWin*
+ui_ev_new_chat_win(const char * const barejid)
+{
+ return ui_new_chat_win(barejid);
+}
+
+ProfPrivateWin*
+ui_ev_new_private_win(const char * const fulljid)
+{
+ return ui_new_private_win(fulljid);
+}
\ No newline at end of file
diff --git a/src/tools/history.h b/src/event/ui_events.h
similarity index 80%
rename from src/tools/history.h
rename to src/event/ui_events.h
index 7b334718..3f7fed02 100644
--- a/src/tools/history.h
+++ b/src/event/ui_events.h
@@ -1,7 +1,7 @@
/*
- * history.h
+ * ui_events.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -32,14 +32,11 @@
*
*/
-#ifndef HISTORY_H
-#define HISTORY_H
+#ifndef UI_EVENTS_H
+#define UI_EVENTS_H
-typedef struct history_t *History;
+void ui_ev_focus_win(ProfWin *win);
+ProfChatWin* ui_ev_new_chat_win(const char * const barejid);
+ProfPrivateWin* ui_ev_new_private_win(const char * const fulljid);
-History history_new(unsigned int size);
-char * history_previous(History history, char *item);
-char * history_next(History history, char *item);
-void history_append(History history, char *item);
-
-#endif
+#endif
\ No newline at end of file
diff --git a/src/jid.c b/src/jid.c
index 690f36ca..baeeb279 100644
--- a/src/jid.c
+++ b/src/jid.c
@@ -1,7 +1,7 @@
/*
* jid.c
*
- * Copyright (C) 2012 -2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -80,19 +80,20 @@ jid_create(const gchar * const str)
gchar *domain_start = trimmed;
- if (atp != NULL) {
+ if (atp) {
result->localpart = g_utf8_substring(trimmed, 0, g_utf8_pointer_to_offset(trimmed, atp));
domain_start = atp + 1;
}
- if (slashp != NULL) {
+ if (slashp) {
result->resourcepart = g_strdup(slashp + 1);
result->domainpart = g_utf8_substring(domain_start, 0, g_utf8_pointer_to_offset(domain_start, slashp));
- result->barejid = g_utf8_substring(trimmed, 0, g_utf8_pointer_to_offset(trimmed, slashp));
+ char *barejidraw = g_utf8_substring(trimmed, 0, g_utf8_pointer_to_offset(trimmed, slashp));
+ result->barejid = g_utf8_strdown(barejidraw, -1);
result->fulljid = g_strdup(trimmed);
} else {
result->domainpart = g_strdup(domain_start);
- result->barejid = g_strdup(trimmed);
+ result->barejid = g_utf8_strdown(trimmed, -1);
}
if (result->domainpart == NULL) {
@@ -119,7 +120,7 @@ jid_create_from_bare_and_resource(const char * const room, const char * const ni
void
jid_destroy(Jid *jid)
{
- if (jid != NULL) {
+ if (jid) {
g_free(jid->str);
g_free(jid->localpart);
g_free(jid->domainpart);
@@ -144,7 +145,9 @@ jid_is_valid_room_form(Jid *jid)
char *
create_fulljid(const char * const barejid, const char * const resource)
{
- GString *full_jid = g_string_new(barejid);
+ gchar *barejidlower = g_utf8_strdown(barejid, -1);
+ GString *full_jid = g_string_new(barejidlower);
+ g_free(barejidlower);
g_string_append(full_jid, "/");
g_string_append(full_jid, resource);
@@ -166,8 +169,8 @@ get_nick_from_full_jid(const char * const full_room_jid)
char **tokens = g_strsplit(full_room_jid, "/", 0);
char *nick_part = NULL;
- if (tokens != NULL) {
- if (tokens[0] != NULL && tokens[1] != NULL) {
+ if (tokens) {
+ if (tokens[0] && tokens[1]) {
nick_part = strdup(tokens[1]);
}
diff --git a/src/jid.h b/src/jid.h
index 64c147f9..6d530c5a 100644
--- a/src/jid.h
+++ b/src/jid.h
@@ -1,7 +1,7 @@
/*
* jid.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/log.c b/src/log.c
index c525c3d9..a7727e8b 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1,7 +1,7 @@
/*
* log.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -46,6 +46,7 @@
#include "common.h"
#include "config/preferences.h"
+#include "xmpp/xmpp.h"
#define PROF "prof"
@@ -66,7 +67,7 @@ struct dated_chat_log {
};
static gboolean _log_roll_needed(struct dated_chat_log *dated_log);
-static struct dated_chat_log * _create_log(char *other, const char * const login);
+static struct dated_chat_log * _create_log(const char * const other, const char * const login);
static struct dated_chat_log * _create_groupchat_log(char *room, const char * const login);
static void _free_chat_log(struct dated_chat_log *dated_log);
static gboolean _key_equals(void *key1, void *key2);
@@ -78,6 +79,8 @@ static gchar * _get_chatlog_dir(void);
static gchar * _get_main_log_file(void);
static void _rotate_log_file(void);
static char* _log_string_from_level(log_level_t level);
+static void _chat_log_chat(const char * const login, const char * const other,
+ const gchar * const msg, chat_log_direction_t direction, GTimeVal *tv_stamp);
void
log_debug(const char * const msg, ...)
@@ -163,7 +166,7 @@ log_close(void)
{
g_string_free(mainlogfile, TRUE);
g_time_zone_unref(tz);
- if (logp != NULL) {
+ if (logp) {
fclose(logp);
}
}
@@ -171,7 +174,7 @@ log_close(void)
void
log_msg(log_level_t level, const char * const area, const char * const msg)
{
- if (level >= level_filter && logp != NULL) {
+ if (level >= level_filter && logp) {
dt = g_date_time_new_now(tz);
char *level_str = _log_string_from_level(level);
@@ -236,7 +239,7 @@ chat_log_init(void)
{
session_started = g_date_time_new_now_local();
log_info("Initialising chat logs");
- logs = g_hash_table_new_full(g_str_hash, (GEqualFunc) _key_equals, g_free,
+ logs = g_hash_table_new_full(g_str_hash, (GEqualFunc) _key_equals, free,
(GDestroyNotify)_free_chat_log);
}
@@ -244,13 +247,80 @@ void
groupchat_log_init(void)
{
log_info("Initialising groupchat logs");
- groupchat_logs = g_hash_table_new_full(g_str_hash, (GEqualFunc) _key_equals, g_free,
+ groupchat_logs = g_hash_table_new_full(g_str_hash, (GEqualFunc) _key_equals, free,
(GDestroyNotify)_free_chat_log);
}
void
-chat_log_chat(const gchar * const login, gchar *other,
- const gchar * const msg, chat_log_direction_t direction, GTimeVal *tv_stamp)
+chat_log_msg_out(const char * const barejid, const char * const msg)
+{
+ if (prefs_get_boolean(PREF_CHLOG)) {
+ const char *jid = jabber_get_fulljid();
+ Jid *jidp = jid_create(jid);
+ _chat_log_chat(jidp->barejid, barejid, msg, PROF_OUT_LOG, NULL);
+ jid_destroy(jidp);
+ }
+}
+
+void
+chat_log_otr_msg_out(const char * const barejid, const char * const msg)
+{
+ if (prefs_get_boolean(PREF_CHLOG)) {
+ const char *jid = jabber_get_fulljid();
+ Jid *jidp = jid_create(jid);
+ char *pref_otr_log = prefs_get_string(PREF_OTR_LOG);
+ if (strcmp(pref_otr_log, "on") == 0) {
+ _chat_log_chat(jidp->barejid, barejid, msg, PROF_OUT_LOG, NULL);
+ } else if (strcmp(pref_otr_log, "redact") == 0) {
+ _chat_log_chat(jidp->barejid, barejid, "[redacted]", PROF_OUT_LOG, NULL);
+ }
+ prefs_free_string(pref_otr_log);
+ jid_destroy(jidp);
+ }
+}
+
+void
+chat_log_otr_msg_in(const char * const barejid, const char * const msg, gboolean was_decrypted)
+{
+ if (prefs_get_boolean(PREF_CHLOG)) {
+ const char *jid = jabber_get_fulljid();
+ Jid *jidp = jid_create(jid);
+ char *pref_otr_log = prefs_get_string(PREF_OTR_LOG);
+ if (!was_decrypted || (strcmp(pref_otr_log, "on") == 0)) {
+ _chat_log_chat(jidp->barejid, barejid, msg, PROF_IN_LOG, NULL);
+ } else if (strcmp(pref_otr_log, "redact") == 0) {
+ _chat_log_chat(jidp->barejid, barejid, "[redacted]", PROF_IN_LOG, NULL);
+ }
+ prefs_free_string(pref_otr_log);
+ jid_destroy(jidp);
+ }
+}
+
+void
+chat_log_msg_in(const char * const barejid, const char * const msg)
+{
+ if (prefs_get_boolean(PREF_CHLOG)) {
+ const char *jid = jabber_get_fulljid();
+ Jid *jidp = jid_create(jid);
+ _chat_log_chat(jidp->barejid, barejid, msg, PROF_IN_LOG, NULL);
+ jid_destroy(jidp);
+ }
+}
+
+void
+chat_log_msg_in_delayed(const char * const barejid, const char * msg, GTimeVal *tv_stamp)
+{
+ if (prefs_get_boolean(PREF_CHLOG)) {
+ const char *jid = jabber_get_fulljid();
+ Jid *jidp = jid_create(jid);
+ _chat_log_chat(jidp->barejid, barejid, msg, PROF_IN_LOG, tv_stamp);
+ jid_destroy(jidp);
+ }
+}
+
+static void
+_chat_log_chat(const char * const login, const char * const other,
+ const char * const msg, chat_log_direction_t direction, GTimeVal *tv_stamp)
{
struct dated_chat_log *dated_log = g_hash_table_lookup(logs, other);
@@ -277,7 +347,7 @@ chat_log_chat(const gchar * const login, gchar *other,
FILE *logp = fopen(dated_log->filename, "a");
g_chmod(dated_log->filename, S_IRUSR | S_IWUSR);
- if (logp != NULL) {
+ if (logp) {
if (direction == PROF_IN_LOG) {
if (strncmp(msg, "/me ", 4) == 0) {
fprintf(logp, "%s - *%s %s\n", date_fmt, other, msg + 4);
@@ -326,7 +396,7 @@ groupchat_log_chat(const gchar * const login, const gchar * const room,
FILE *logp = fopen(dated_log->filename, "a");
g_chmod(dated_log->filename, S_IRUSR | S_IWUSR);
- if (logp != NULL) {
+ if (logp) {
if (strncmp(msg, "/me ", 4) == 0) {
fprintf(logp, "%s - *%s %s\n", date_fmt, nick, msg + 4);
} else {
@@ -363,7 +433,7 @@ chat_log_get_previous(const gchar * const login, const gchar * const recipient)
char *filename = _get_log_filename(recipient, login, log_date, FALSE);
FILE *logp = fopen(filename, "r");
- if (logp != NULL) {
+ if (logp) {
GString *header = g_string_new("");
g_string_append_printf(header, "%d/%d/%d:",
g_date_time_get_day_of_month(log_date),
@@ -396,13 +466,13 @@ chat_log_get_previous(const gchar * const login, const gchar * const recipient)
void
chat_log_close(void)
{
- g_hash_table_remove_all(logs);
- g_hash_table_remove_all(groupchat_logs);
+ g_hash_table_destroy(logs);
+ g_hash_table_destroy(groupchat_logs);
g_date_time_unref(session_started);
}
static struct dated_chat_log *
-_create_log(char *other, const char * const login)
+_create_log(const char * const other, const char * const login)
{
GDateTime *now = g_date_time_new_now_local();
char *filename = _get_log_filename(other, login, now, TRUE);
@@ -448,12 +518,12 @@ _log_roll_needed(struct dated_chat_log *dated_log)
static void
_free_chat_log(struct dated_chat_log *dated_log)
{
- if (dated_log != NULL) {
- if (dated_log->filename != NULL) {
+ if (dated_log) {
+ if (dated_log->filename) {
g_free(dated_log->filename);
dated_log->filename = NULL;
}
- if (dated_log->date != NULL) {
+ if (dated_log->date) {
g_date_time_unref(dated_log->date);
dated_log->date = NULL;
}
diff --git a/src/log.h b/src/log.h
index 8ffc6f22..0689e2e6 100644
--- a/src/log.h
+++ b/src/log.h
@@ -1,7 +1,7 @@
/*
* log.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -64,8 +64,14 @@ void log_msg(log_level_t level, const char * const area,
log_level_t log_level_from_string(char *log_level);
void chat_log_init(void);
-void chat_log_chat(const gchar * const login, gchar *other,
- const gchar * const msg, chat_log_direction_t direction, GTimeVal *tv_stamp);
+
+void chat_log_msg_out(const char * const barejid, const char * const msg);
+void chat_log_otr_msg_out(const char * const barejid, const char * const msg);
+
+void chat_log_msg_in(const char * const barejid, const char * const msg);
+void chat_log_msg_in_delayed(const char * const barejid, const char * msg, GTimeVal *tv_stamp);
+void chat_log_otr_msg_in(const char * const barejid, const char * const msg, gboolean was_decrypted);
+
void chat_log_close(void);
GSList * chat_log_get_previous(const gchar * const login,
const gchar * const recipient);
diff --git a/src/main.c b/src/main.c
index f3b6a17f..3bb7eeb6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,7 +1,7 @@
/*
* main.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -40,13 +40,7 @@
#endif
#include "profanity.h"
-
-#ifdef HAVE_LIBOTR
-#include "otr/otr.h"
-#endif
-#include "xmpp/xmpp.h"
-
-#include "ui/ui.h"
+#include "command/command.h"
static gboolean disable_tls = FALSE;
static gboolean version = FALSE;
@@ -56,6 +50,11 @@ static char *account_name = NULL;
int
main(int argc, char **argv)
{
+ if (argc == 2 && g_strcmp0(argv[1], "docgen") == 0 && g_strcmp0(PACKAGE_STATUS, "development") == 0) {
+ command_docgen();
+ return 0;
+ }
+
static GOptionEntry entries[] =
{
{ "version", 'v', 0, G_OPTION_ARG_NONE, &version, "Show version information", NULL },
@@ -90,7 +89,7 @@ main(int argc, char **argv)
g_print("Profanity, version %s\n", PACKAGE_VERSION);
}
- g_print("Copyright (C) 2012 - 2014 James Booth <%s>.\n", PACKAGE_BUGREPORT);
+ g_print("Copyright (C) 2012 - 2015 James Booth <%s>.\n", PACKAGE_BUGREPORT);
g_print("License GPLv3+: GNU GPL version 3 or later \n");
g_print("\n");
g_print("This is free software; you are free to change and redistribute it.\n");
diff --git a/src/muc.c b/src/muc.c
index f50f3879..d283b55e 100644
--- a/src/muc.c
+++ b/src/muc.c
@@ -1,7 +1,7 @@
/*
* muc.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -62,9 +62,11 @@ typedef struct _muc_room_t {
Autocomplete jid_ac;
GHashTable *nick_changes;
gboolean roster_received;
+ muc_member_type_t member_type;
} ChatRoom;
GHashTable *rooms = NULL;
+GHashTable *invite_passwords = NULL;
Autocomplete invite_ac;
static void _free_room(ChatRoom *room);
@@ -82,6 +84,7 @@ muc_init(void)
{
invite_ac = autocomplete_new();
rooms = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)_free_room);
+ invite_passwords = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
}
void
@@ -89,19 +92,25 @@ muc_close(void)
{
autocomplete_free(invite_ac);
g_hash_table_destroy(rooms);
+ g_hash_table_destroy(invite_passwords);
rooms = NULL;
+ invite_passwords = NULL;
}
void
-muc_invites_add(const char * const room)
+muc_invites_add(const char * const room, const char * const password)
{
autocomplete_add(invite_ac, room);
+ if (password) {
+ g_hash_table_replace(invite_passwords, strdup(room), strdup(password));
+ }
}
void
muc_invites_remove(const char * const room)
{
autocomplete_remove(invite_ac, room);
+ g_hash_table_remove(invite_passwords, room);
}
gint
@@ -116,6 +125,12 @@ muc_invites(void)
return autocomplete_create_list(invite_ac);
}
+char *
+muc_invite_password(const char * const room)
+{
+ return g_hash_table_lookup(invite_passwords, room);
+}
+
gboolean
muc_invites_contain(const char * const room)
{
@@ -150,6 +165,7 @@ void
muc_invites_clear(void)
{
autocomplete_clear(invite_ac);
+ g_hash_table_remove_all(invite_passwords);
}
void
@@ -177,6 +193,7 @@ muc_join(const char * const room, const char * const nick,
new_room->roster_received = FALSE;
new_room->pending_nick_change = FALSE;
new_room->autojoin = autojoin;
+ new_room->member_type = MUC_MEMBER_TYPE_UNKNOWN;
g_hash_table_insert(rooms, strdup(room), new_room);
}
@@ -208,6 +225,19 @@ muc_set_requires_config(const char * const room, gboolean val)
}
}
+void
+muc_set_features(const char * const room, GSList *features)
+{
+ ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
+ if (chat_room && features) {
+ if (g_slist_find_custom(features, "muc_membersonly", (GCompareFunc)g_strcmp0)) {
+ chat_room->member_type = MUC_MEMBER_TYPE_MEMBERS_ONLY;
+ } else {
+ chat_room->member_type = MUC_MEMBER_TYPE_PUBLIC;
+ }
+ }
+}
+
/*
* Returns TRUE if the user is currently in the room
*/
@@ -315,7 +345,7 @@ muc_nick_change_pending(const char * const room)
}
/*
- * Change the current nuck name for the room, call once
+ * Change the current nick name for the room, call once
* the service has responded
*/
void
@@ -763,6 +793,18 @@ muc_set_affiliation(const char * const room, const char * const affiliation)
}
}
+muc_member_type_t
+muc_member_type(const char * const room)
+{
+ ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
+ if (chat_room) {
+ return chat_room->member_type;
+ } else {
+ return MUC_MEMBER_TYPE_UNKNOWN;
+ }
+}
+
+
static void
_free_room(ChatRoom *room)
{
@@ -790,16 +832,10 @@ _free_room(ChatRoom *room)
static
gint _compare_occupants(Occupant *a, Occupant *b)
{
- const char * utf8_str_a = a->nick;
- const char * utf8_str_b = b->nick;
+ const char * utf8_str_a = a->nick_collate_key;
+ const char * utf8_str_b = b->nick_collate_key;
- gchar *key_a = g_utf8_collate_key(utf8_str_a, -1);
- gchar *key_b = g_utf8_collate_key(utf8_str_b, -1);
-
- gint result = g_strcmp0(key_a, key_b);
-
- g_free(key_a);
- g_free(key_b);
+ gint result = g_strcmp0(utf8_str_a, utf8_str_b);
return result;
}
@@ -905,8 +941,10 @@ _muc_occupant_new(const char *const nick, const char * const jid, muc_role_t rol
if (nick) {
occupant->nick = strdup(nick);
+ occupant->nick_collate_key = g_utf8_collate_key(occupant->nick, -1);
} else {
occupant->nick = NULL;
+ occupant->nick_collate_key = NULL;
}
if (jid) {
@@ -934,6 +972,7 @@ _occupant_free(Occupant *occupant)
{
if (occupant) {
free(occupant->nick);
+ free(occupant->nick_collate_key);
free(occupant->jid);
free(occupant->status);
free(occupant);
diff --git a/src/muc.h b/src/muc.h
index 01f8b44b..ad96f3d9 100644
--- a/src/muc.h
+++ b/src/muc.h
@@ -1,7 +1,7 @@
/*
* muc.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -56,8 +56,15 @@ typedef enum {
MUC_AFFILIATION_OWNER
} muc_affiliation_t;
+typedef enum {
+ MUC_MEMBER_TYPE_UNKNOWN,
+ MUC_MEMBER_TYPE_PUBLIC,
+ MUC_MEMBER_TYPE_MEMBERS_ONLY
+} muc_member_type_t;
+
typedef struct _muc_occupant_t {
char *nick;
+ gchar *nick_collate_key;
char *jid;
muc_role_t role;
muc_affiliation_t affiliation;
@@ -76,6 +83,8 @@ gboolean muc_autojoin(const char * const room);
GList* muc_rooms(void);
+void muc_set_features(const char * const room, GSList *features);
+
char* muc_nick(const char * const room);
char* muc_password(const char * const room);
@@ -108,7 +117,7 @@ GSList * muc_occupants_by_affiliation(const char * const room, muc_affiliation_t
void muc_occupant_nick_change_start(const char * const room, const char * const new_nick, const char * const old_nick);
char* muc_roster_nick_change_complete(const char * const room, const char * const nick);
-void muc_invites_add(const char * const room);
+void muc_invites_add(const char * const room, const char * const password);
void muc_invites_remove(const char * const room);
gint muc_invites_count(void);
GSList* muc_invites(void);
@@ -116,6 +125,7 @@ gboolean muc_invites_contain(const char * const room);
void muc_invites_reset_ac(void);
char* muc_invites_find(const char * const search_str);
void muc_invites_clear(void);
+char* muc_invite_password(const char * const room);
void muc_set_subject(const char * const room, const char * const subject);
char* muc_subject(const char * const room);
@@ -134,4 +144,6 @@ void muc_set_affiliation(const char * const room, const char * const affiliation
char *muc_role_str(const char * const room);
char *muc_affiliation_str(const char * const room);
+muc_member_type_t muc_member_type(const char * const room);
+
#endif
diff --git a/src/otr/otr.c b/src/otr/otr.c
index bd1c2ce3..e568af56 100644
--- a/src/otr/otr.c
+++ b/src/otr/otr.c
@@ -1,7 +1,7 @@
/*
* otr.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -110,7 +110,7 @@ static void
cb_inject_message(void *opdata, const char *accountname,
const char *protocol, const char *recipient, const char *message)
{
- message_send_chat(recipient, message);
+ message_send_chat_encrypted(recipient, message);
}
static void
@@ -179,7 +179,7 @@ otr_init(void)
void
otr_shutdown(void)
{
- if (jid != NULL) {
+ if (jid) {
free(jid);
}
}
@@ -193,7 +193,7 @@ otr_poll(void)
void
otr_on_connect(ProfAccount *account)
{
- if (jid != NULL) {
+ if (jid) {
free(jid);
}
jid = strdup(account->jid);
@@ -269,6 +269,89 @@ otr_on_connect(ProfAccount *account)
return;
}
+void
+otr_on_message_recv(const char * const barejid, const char * const resource, const char * const message)
+{
+ gboolean was_decrypted = FALSE;
+ char *decrypted;
+
+ prof_otrpolicy_t policy = otr_get_policy(barejid);
+ char *whitespace_base = strstr(message, OTRL_MESSAGE_TAG_BASE);
+
+ //check for OTR whitespace (opportunistic or always)
+ if (policy == PROF_OTRPOLICY_OPPORTUNISTIC || policy == PROF_OTRPOLICY_ALWAYS) {
+ if (whitespace_base) {
+ if (strstr(message, OTRL_MESSAGE_TAG_V2) || strstr(message, OTRL_MESSAGE_TAG_V1)) {
+ // Remove whitespace pattern for proper display in UI
+ // Handle both BASE+TAGV1/2(16+8) and BASE+TAGV1+TAGV2(16+8+8)
+ int tag_length = 24;
+ if (strstr(message, OTRL_MESSAGE_TAG_V2) && strstr(message, OTRL_MESSAGE_TAG_V1)) {
+ tag_length = 32;
+ }
+ memmove(whitespace_base, whitespace_base+tag_length, tag_length);
+ char *otr_query_message = otr_start_query();
+ cons_show("OTR Whitespace pattern detected. Attempting to start OTR session...");
+ message_send_chat_encrypted(barejid, otr_query_message);
+ }
+ }
+ }
+ decrypted = otr_decrypt_message(barejid, message, &was_decrypted);
+
+ // internal OTR message
+ if (decrypted == NULL) {
+ return;
+ }
+
+ if (policy == PROF_OTRPOLICY_ALWAYS && !was_decrypted && !whitespace_base) {
+ char *otr_query_message = otr_start_query();
+ cons_show("Attempting to start OTR session...");
+ message_send_chat_encrypted(barejid, otr_query_message);
+ }
+
+ ui_incoming_msg(barejid, resource, decrypted, NULL);
+ chat_log_otr_msg_in(barejid, decrypted, was_decrypted);
+ otr_free_message(decrypted);
+}
+
+void
+otr_on_message_send(ProfChatWin *chatwin, const char * const message)
+{
+ char *id = NULL;
+
+ prof_otrpolicy_t policy = otr_get_policy(chatwin->barejid);
+
+ if (otr_is_secure(chatwin->barejid)) {
+ char *encrypted = otr_encrypt_message(chatwin->barejid, message);
+ if (encrypted) {
+ id = message_send_chat_encrypted(chatwin->barejid, encrypted);
+ chat_log_otr_msg_out(chatwin->barejid, message);
+ ui_outgoing_chat_msg(chatwin, message, id);
+ otr_free_message(encrypted);
+ } else {
+ ui_win_error_line((ProfWin*)chatwin, "Failed to encrypt and send message.");
+ return;
+ }
+
+ } else if (policy == PROF_OTRPOLICY_ALWAYS) {
+ ui_win_error_line((ProfWin*)chatwin, "Failed to send message. OTR policy set to: always");
+ return;
+
+ } else if (policy == PROF_OTRPOLICY_OPPORTUNISTIC) {
+ char *otr_tagged_msg = otr_tag_message(message);
+ id = message_send_chat_encrypted(chatwin->barejid, otr_tagged_msg);
+ ui_outgoing_chat_msg(chatwin, message, id);
+ chat_log_msg_out(chatwin->barejid, message);
+ free(otr_tagged_msg);
+
+ } else {
+ id = message_send_chat(chatwin->barejid, message);
+ ui_outgoing_chat_msg(chatwin, message, id);
+ chat_log_msg_out(chatwin->barejid, message);
+ }
+
+ free(id);
+}
+
void
otr_keygen(ProfAccount *account)
{
@@ -277,7 +360,7 @@ otr_keygen(ProfAccount *account)
return;
}
- if (jid != NULL) {
+ if (jid) {
free(jid);
}
jid = strdup(account->jid);
@@ -365,6 +448,18 @@ otr_key_loaded(void)
return data_loaded;
}
+char *
+otr_tag_message(const char * const msg)
+{
+ GString *otr_message = g_string_new(msg);
+ g_string_append(otr_message, OTRL_MESSAGE_TAG_BASE);
+ g_string_append(otr_message, OTRL_MESSAGE_TAG_V2);
+ char *result = otr_message->str;
+ g_string_free(otr_message, FALSE);
+
+ return result;
+}
+
gboolean
otr_is_secure(const char * const recipient)
{
@@ -421,7 +516,7 @@ otr_trust(const char * const recipient)
}
if (context->active_fingerprint) {
- if (context->active_fingerprint->trust != NULL) {
+ if (context->active_fingerprint->trust) {
free(context->active_fingerprint->trust);
}
context->active_fingerprint->trust = strdup("trusted");
@@ -445,7 +540,7 @@ otr_untrust(const char * const recipient)
}
if (context->active_fingerprint) {
- if (context->active_fingerprint->trust != NULL) {
+ if (context->active_fingerprint->trust) {
free(context->active_fingerprint->trust);
}
context->active_fingerprint->trust = NULL;
@@ -534,7 +629,7 @@ otr_get_their_fingerprint(const char * const recipient)
{
ConnContext *context = otrlib_context_find(user_state, recipient, jid);
- if (context != NULL) {
+ if (context) {
Fingerprint *fingerprint = context->active_fingerprint;
char readable[45];
otrl_privkey_hash_to_human(readable, fingerprint->fingerprint);
@@ -563,7 +658,7 @@ otr_get_policy(const char * const recipient)
}
// check default account setting
- if (account->otr_policy != NULL) {
+ if (account->otr_policy) {
prof_otrpolicy_t result;
if (g_strcmp0(account->otr_policy, "manual") == 0) {
result = PROF_OTRPOLICY_MANUAL;
@@ -625,7 +720,7 @@ otr_decrypt_message(const char * const from, const char * const message, gboolea
OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
if (tlv) {
- if (context != NULL) {
+ if (context) {
otrl_context_force_plaintext(context);
ui_gone_insecure(from);
}
@@ -637,7 +732,7 @@ otr_decrypt_message(const char * const from, const char * const message, gboolea
return NULL;
// message was decrypted, return to user
- } else if (decrypted != NULL) {
+ } else if (decrypted) {
*was_decrypted = TRUE;
return decrypted;
diff --git a/src/otr/otr.h b/src/otr/otr.h
index 155e287b..e020c0c8 100644
--- a/src/otr/otr.h
+++ b/src/otr/otr.h
@@ -1,7 +1,7 @@
/*
* otr.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -39,6 +39,7 @@
#include
#include "config/accounts.h"
+#include "ui/window.h"
typedef enum {
PROF_OTRPOLICY_MANUAL,
@@ -56,8 +57,14 @@ char* otr_libotr_version(void);
char* otr_start_query(void);
void otr_poll(void);
void otr_on_connect(ProfAccount *account);
+
+void otr_on_message_recv(const char * const barejid, const char * const resource, const char * const message);
+void otr_on_message_send(ProfChatWin *chatwin, const char * const message);
+
void otr_keygen(ProfAccount *account);
+char* otr_tag_message(const char * const msg);
+
gboolean otr_key_loaded(void);
gboolean otr_is_secure(const char * const recipient);
diff --git a/src/otr/otrlib.h b/src/otr/otrlib.h
index da1c8547..0310c9e6 100644
--- a/src/otr/otrlib.h
+++ b/src/otr/otrlib.h
@@ -1,7 +1,7 @@
/*
* otrlib.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/otr/otrlibv3.c b/src/otr/otrlibv3.c
index 77b00660..0b81796c 100644
--- a/src/otr/otrlibv3.c
+++ b/src/otr/otrlibv3.c
@@ -1,7 +1,7 @@
/*
* otrlibv3.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -87,7 +87,7 @@ otrlib_end_session(OtrlUserState user_state, const char * const recipient, char
ConnContext *context = otrl_context_find(user_state, recipient, jid, "xmpp",
0, NULL, NULL, NULL);
- if (context != NULL) {
+ if (context) {
otrl_message_disconnect(user_state, ops, NULL, jid, "xmpp", recipient);
}
}
@@ -171,7 +171,7 @@ otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext
} else {
context->smstate->nextExpected = OTRL_SMP_EXPECT1;
if (context->smstate->received_question == 0) {
- if ((context->active_fingerprint->trust != NULL) && (context->active_fingerprint->trust[0] != '\0')) {
+ if (context->active_fingerprint->trust && (context->active_fingerprint->trust[0] != '\0')) {
ui_smp_successful(context->username);
ui_trust(context->username);
} else {
@@ -193,7 +193,7 @@ otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext
otrl_message_abort_smp(user_state, ops, NULL, context);
} else {
context->smstate->nextExpected = OTRL_SMP_EXPECT1;
- if ((context->active_fingerprint->trust != NULL) && (context->active_fingerprint->trust[0] != '\0')) {
+ if (context->active_fingerprint->trust && (context->active_fingerprint->trust[0] != '\0')) {
ui_smp_successful(context->username);
ui_trust(context->username);
} else {
diff --git a/src/otr/otrlibv4.c b/src/otr/otrlibv4.c
index 62379d0f..fc1f5285 100644
--- a/src/otr/otrlibv4.c
+++ b/src/otr/otrlibv4.c
@@ -1,7 +1,7 @@
/*
* otrlibv4.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -113,12 +113,57 @@ cb_handle_msg_event(void *opdata, OtrlMessageEvent msg_event,
ConnContext *context, const char *message,
gcry_error_t err)
{
- if (err != 0) {
- if (message != NULL) {
- cons_show_error("%s", message);
- } else {
- cons_show_error("OTR error event with no message.");
- }
+ GString *err_msg;
+ switch (msg_event)
+ {
+ case OTRL_MSGEVENT_ENCRYPTION_REQUIRED:
+ ui_handle_otr_error(context->username, "OTR: Policy requires encryption, but attempting to send an unencrypted message.");
+ break;
+ case OTRL_MSGEVENT_ENCRYPTION_ERROR:
+ ui_handle_otr_error(context->username, "OTR: Error occured while encrypting a message, message not sent.");
+ break;
+ case OTRL_MSGEVENT_CONNECTION_ENDED:
+ ui_handle_otr_error(context->username, "OTR: Message not sent because contact has ended the private conversation.");
+ break;
+ case OTRL_MSGEVENT_SETUP_ERROR:
+ ui_handle_otr_error(context->username, "OTR: A private conversation could not be set up.");
+ break;
+ case OTRL_MSGEVENT_MSG_REFLECTED:
+ ui_handle_otr_error(context->username, "OTR: Received our own OTR message.");
+ break;
+ case OTRL_MSGEVENT_MSG_RESENT:
+ ui_handle_otr_error(context->username, "OTR: The previous message was resent.");
+ break;
+ case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE:
+ ui_handle_otr_error(context->username, "OTR: Received an encrypted message but no private connection established.");
+ break;
+ case OTRL_MSGEVENT_RCVDMSG_UNREADABLE:
+ ui_handle_otr_error(context->username, "OTR: Cannot read the received message.");
+ break;
+ case OTRL_MSGEVENT_RCVDMSG_MALFORMED:
+ ui_handle_otr_error(context->username, "OTR: The message received contains malformed data.");
+ break;
+ case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR:
+ err_msg = g_string_new("OTR: Received error: ");
+ g_string_append(err_msg, message);
+ g_string_append(err_msg, ".");
+ ui_handle_otr_error(context->username, err_msg->str);
+ g_string_free(err_msg, TRUE);
+ break;
+ case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED:
+ err_msg = g_string_new("OTR: Received an unencrypted message: ");
+ g_string_append(err_msg, message);
+ ui_handle_otr_error(context->username, err_msg->str);
+ g_string_free(err_msg, TRUE);
+ break;
+ case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED:
+ ui_handle_otr_error(context->username, "OTR: Cannot recognize the type of message received.");
+ break;
+ case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE:
+ ui_handle_otr_error(context->username, "OTR: Received and discarded a message intended for another instance.");
+ break;
+ default:
+ break;
}
}
@@ -208,7 +253,7 @@ otrlib_end_session(OtrlUserState user_state, const char * const recipient, char
ConnContext *context = otrl_context_find(user_state, recipient, jid, "xmpp",
OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL);
- if (context != NULL) {
+ if (context) {
otrl_message_disconnect(user_state, ops, NULL, jid, "xmpp", recipient, 0);
}
}
diff --git a/src/profanity.c b/src/profanity.c
index 13297124..55a73430 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -1,7 +1,7 @@
/*
* profanity.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -63,6 +63,7 @@
#include "xmpp/xmpp.h"
#include "ui/ui.h"
#include "ui/windows.h"
+#include "event/client_events.h"
static void _check_autoaway(void);
static void _init(const int disable_tls, char *log_level);
@@ -71,6 +72,7 @@ static void _create_directories(void);
static void _connect_default(const char * const account);
static gboolean idle = FALSE;
+static gboolean cont = TRUE;
void
prof_run(const int disable_tls, char *log_level, char *account_name)
@@ -79,25 +81,27 @@ prof_run(const int disable_tls, char *log_level, char *account_name)
_connect_default(account_name);
ui_update();
- char *line = NULL;
- gboolean cmd_result = TRUE;
-
log_info("Starting main event loop");
- while(cmd_result) {
- while(!line) {
- _check_autoaway();
- line = ui_readline();
-#ifdef HAVE_LIBOTR
- otr_poll();
-#endif
- notify_remind();
- jabber_process_events();
- ui_update();
+ char *line = NULL;
+ while(cont) {
+ _check_autoaway();
+
+ line = ui_readline();
+ if (line) {
+ cont = cmd_process_input(line);
+ free(line);
+ line = NULL;
+ } else {
+ cont = TRUE;
}
- cmd_result = cmd_process_input(line);
- ui_input_clear();
- FREE_SET_NULL(line);
+
+#ifdef HAVE_LIBOTR
+ otr_poll();
+#endif
+ notify_remind();
+ jabber_process_events();
+ ui_update();
}
}
@@ -109,14 +113,14 @@ prof_handle_idle(void)
GSList *recipients = ui_get_chat_recipients();
GSList *curr = recipients;
- while (curr != NULL) {
+ while (curr) {
char *barejid = curr->data;
ProfChatWin *chatwin = wins_get_chat(barejid);
chat_state_handle_idle(chatwin->barejid, chatwin->state);
curr = g_slist_next(curr);
}
- if (recipients != NULL) {
+ if (recipients) {
g_slist_free(recipients);
}
}
@@ -169,12 +173,12 @@ _check_autoaway()
// handle away mode
if (strcmp(pref_autoaway_mode, "away") == 0) {
- presence_update(RESOURCE_AWAY, pref_autoaway_message, 0);
+ cl_ev_presence_send(RESOURCE_AWAY, pref_autoaway_message, 0);
ui_auto_away();
// handle idle mode
} else if (strcmp(pref_autoaway_mode, "idle") == 0) {
- presence_update(RESOURCE_ONLINE, pref_autoaway_message, idle_ms / 1000);
+ cl_ev_presence_send(RESOURCE_ONLINE, pref_autoaway_message, idle_ms / 1000);
}
prefs_free_string(pref_autoaway_message);
@@ -188,10 +192,10 @@ _check_autoaway()
// handle check
if (prefs_get_boolean(PREF_AUTOAWAY_CHECK)) {
if (strcmp(pref_autoaway_mode, "away") == 0) {
- presence_update(RESOURCE_ONLINE, NULL, 0);
+ cl_ev_presence_send(RESOURCE_ONLINE, NULL, 0);
ui_end_auto_away();
} else if (strcmp(pref_autoaway_mode, "idle") == 0) {
- presence_update(RESOURCE_ONLINE, NULL, 0);
+ cl_ev_presence_send(RESOURCE_ONLINE, NULL, 0);
ui_titlebar_presence(CONTACT_ONLINE);
}
}
@@ -209,6 +213,7 @@ _init(const int disable_tls, char *log_level)
signal(SIGPIPE, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
+ signal(SIGWINCH, ui_sigwinch_handler);
_create_directories();
log_level_t prof_log_level = log_level_from_string(log_level);
prefs_load();
diff --git a/src/profanity.h b/src/profanity.h
index f01169f8..269c616a 100644
--- a/src/profanity.h
+++ b/src/profanity.h
@@ -1,7 +1,7 @@
/*
* profanity.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/resource.c b/src/resource.c
index 844cb1d3..1598c7b2 100644
--- a/src/resource.c
+++ b/src/resource.c
@@ -1,7 +1,7 @@
/*
* resource.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -46,7 +46,7 @@ Resource * resource_new(const char * const name, resource_presence_t presence,
Resource *new_resource = malloc(sizeof(struct resource_t));
new_resource->name = strdup(name);
new_resource->presence = presence;
- if (status != NULL) {
+ if (status) {
new_resource->status = strdup(status);
} else {
new_resource->status = NULL;
@@ -88,7 +88,7 @@ resource_compare_availability(Resource *first, Resource *second)
void resource_destroy(Resource *resource)
{
- if (resource != NULL) {
+ if (resource) {
free(resource->name);
free(resource->status);
free(resource);
diff --git a/src/resource.h b/src/resource.h
index 5c39d969..43bb6d18 100644
--- a/src/resource.h
+++ b/src/resource.h
@@ -1,7 +1,7 @@
/*
* resource.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/roster_list.c b/src/roster_list.c
index 44d05ff0..2d9df860 100644
--- a/src/roster_list.c
+++ b/src/roster_list.c
@@ -1,7 +1,7 @@
/*
* roster_list.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -42,6 +42,7 @@
#include "contact.h"
#include "jid.h"
#include "tools/autocomplete.h"
+#include "config/preferences.h"
// nicknames
static Autocomplete name_ac;
@@ -91,7 +92,7 @@ roster_update_presence(const char * const barejid, Resource *resource,
assert(barejid != NULL);
assert(resource != NULL);
- PContact contact = g_hash_table_lookup(contacts, barejid);
+ PContact contact = roster_get_contact(barejid);
if (contact == NULL) {
return FALSE;
}
@@ -109,14 +110,45 @@ roster_update_presence(const char * const barejid, Resource *resource,
PContact
roster_get_contact(const char * const barejid)
{
- return g_hash_table_lookup(contacts, barejid);
+ gchar *barejidlower = g_utf8_strdown(barejid, -1);
+ PContact contact = g_hash_table_lookup(contacts, barejidlower);
+ g_free(barejidlower);
+
+ return contact;
+}
+
+char *
+roster_get_msg_display_name(const char * const barejid, const char * const resource)
+{
+ GString *result = g_string_new("");
+
+ PContact contact = roster_get_contact(barejid);
+ if (contact) {
+ if (p_contact_name(contact)) {
+ g_string_append(result, p_contact_name(contact));
+ } else {
+ g_string_append(result, barejid);
+ }
+ } else {
+ g_string_append(result, barejid);
+ }
+
+ if (resource && prefs_get_boolean(PREF_RESOURCE_MESSAGE)) {
+ g_string_append(result, "/");
+ g_string_append(result, resource);
+ }
+
+ char *result_str = result->str;
+ g_string_free(result, FALSE);
+
+ return result_str;
}
gboolean
roster_contact_offline(const char * const barejid,
const char * const resource, const char * const status)
{
- PContact contact = g_hash_table_lookup(contacts, barejid);
+ PContact contact = roster_get_contact(barejid);
if (contact == NULL) {
return FALSE;
@@ -174,7 +206,7 @@ roster_change_name(PContact contact, const char * const new_name)
const char *current_name = NULL;
const char *barejid = p_contact_barejid(contact);
- if (p_contact_name(contact) != NULL) {
+ if (p_contact_name(contact)) {
current_name = strdup(p_contact_name(contact));
}
@@ -191,9 +223,9 @@ roster_remove(const char * const name, const char * const barejid)
// remove each fulljid
PContact contact = roster_get_contact(barejid);
- if (contact != NULL) {
+ if (contact) {
GList *resources = p_contact_get_available_resources(contact);
- while (resources != NULL) {
+ while (resources) {
GString *fulljid = g_string_new(strdup(barejid));
g_string_append(fulljid, "/");
g_string_append(fulljid, resources->data);
@@ -212,7 +244,7 @@ void
roster_update(const char * const barejid, const char * const name,
GSList *groups, const char * const subscription, gboolean pending_out)
{
- PContact contact = g_hash_table_lookup(contacts, barejid);
+ PContact contact = roster_get_contact(barejid);
assert(contact != NULL);
p_contact_set_subscription(contact, subscription);
@@ -220,7 +252,7 @@ roster_update(const char * const barejid, const char * const name,
const char * const new_name = name;
const char * current_name = NULL;
- if (p_contact_name(contact) != NULL) {
+ if (p_contact_name(contact)) {
current_name = strdup(p_contact_name(contact));
}
@@ -229,7 +261,7 @@ roster_update(const char * const barejid, const char * const name,
_replace_name(current_name, new_name, barejid);
// add groups
- while (groups != NULL) {
+ while (groups) {
autocomplete_add(groups_ac, groups->data);
groups = g_slist_next(groups);
}
@@ -239,8 +271,8 @@ gboolean
roster_add(const char * const barejid, const char * const name, GSList *groups,
const char * const subscription, gboolean pending_out)
{
- PContact contact = g_hash_table_lookup(contacts, barejid);
- if (contact != NULL) {
+ PContact contact = roster_get_contact(barejid);
+ if (contact) {
return FALSE;
}
@@ -248,7 +280,7 @@ roster_add(const char * const barejid, const char * const name, GSList *groups,
pending_out);
// add groups
- while (groups != NULL) {
+ while (groups) {
autocomplete_add(groups_ac, groups->data);
groups = g_slist_next(groups);
}
@@ -286,7 +318,7 @@ roster_get_contacts_by_presence(const char * const presence)
}
}
- // resturn all contact structs
+ // return all contact structs
return result;
}
@@ -303,7 +335,7 @@ roster_get_contacts(void)
result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts);
}
- // resturn all contact structs
+ // return all contact structs
return result;
}
@@ -321,7 +353,7 @@ roster_get_contacts_online(void)
result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts);
}
- // resturn all contact structs
+ // return all contact structs
return result;
}
@@ -371,7 +403,7 @@ roster_get_nogroup(void)
}
}
- // resturn all contact structs
+ // return all contact structs
return result;
}
@@ -386,7 +418,7 @@ roster_get_group(const char * const group)
g_hash_table_iter_init(&iter, contacts);
while (g_hash_table_iter_next(&iter, &key, &value)) {
GSList *groups = p_contact_groups(value);
- while (groups != NULL) {
+ while (groups) {
if (strcmp(groups->data, group) == 0) {
result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts);
break;
@@ -395,7 +427,7 @@ roster_get_group(const char * const group)
}
}
- // resturn all contact structs
+ // return all contact structs
return result;
}
@@ -445,12 +477,12 @@ _replace_name(const char * const current_name, const char * const new_name,
const char * const barejid)
{
// current handle exists already
- if (current_name != NULL) {
+ if (current_name) {
autocomplete_remove(name_ac, current_name);
g_hash_table_remove(name_to_barejid, current_name);
_add_name_and_barejid(new_name, barejid);
// no current handle
- } else if (new_name != NULL) {
+ } else if (new_name) {
autocomplete_remove(name_ac, barejid);
g_hash_table_remove(name_to_barejid, barejid);
_add_name_and_barejid(new_name, barejid);
@@ -460,7 +492,7 @@ _replace_name(const char * const current_name, const char * const new_name,
static void
_add_name_and_barejid(const char * const name, const char * const barejid)
{
- if (name != NULL) {
+ if (name) {
autocomplete_add(name_ac, name);
g_hash_table_insert(name_to_barejid, strdup(name), strdup(barejid));
} else {
@@ -475,24 +507,18 @@ gint _compare_contacts(PContact a, PContact b)
const char * utf8_str_a = NULL;
const char * utf8_str_b = NULL;
- if (p_contact_name(a) != NULL) {
- utf8_str_a = p_contact_name(a);
+ if (p_contact_name_collate_key(a)) {
+ utf8_str_a = p_contact_name_collate_key(a);
} else {
- utf8_str_a = p_contact_barejid(a);
+ utf8_str_a = p_contact_barejid_collate_key(a);
}
- if (p_contact_name(b) != NULL) {
- utf8_str_b = p_contact_name(b);
+ if (p_contact_name_collate_key(b)) {
+ utf8_str_b = p_contact_name_collate_key(b);
} else {
- utf8_str_b = p_contact_barejid(b);
+ utf8_str_b = p_contact_barejid_collate_key(b);
}
- gchar *key_a = g_utf8_collate_key(utf8_str_a, -1);
- gchar *key_b = g_utf8_collate_key(utf8_str_b, -1);
-
- gint result = g_strcmp0(key_a, key_b);
-
- g_free(key_a);
- g_free(key_b);
+ gint result = g_strcmp0(utf8_str_a, utf8_str_b);
return result;
}
diff --git a/src/roster_list.h b/src/roster_list.h
index e193085b..4417c763 100644
--- a/src/roster_list.h
+++ b/src/roster_list.h
@@ -1,7 +1,7 @@
/*
* roster_list.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -67,5 +67,6 @@ char * roster_group_autocomplete(const char * const search_str);
char * roster_barejid_autocomplete(const char * const search_str);
GSList * roster_get_contacts_by_presence(const char * const presence);
GSList * roster_get_nogroup(void);
+char * roster_get_msg_display_name(const char * const barejid, const char * const resource);
#endif
diff --git a/src/server_events.c b/src/server_events.c
deleted file mode 100644
index fbf534ac..00000000
--- a/src/server_events.c
+++ /dev/null
@@ -1,822 +0,0 @@
-/*
- * server_events.c
- *
- * Copyright (C) 2012 - 2014 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 .
- *
- * In addition, as a special exception, the copyright holders give permission to
- * link the code of portions of this program with the OpenSSL library under
- * certain conditions as described in each individual source file, and
- * distribute linked combinations including the two.
- *
- * You must obey the GNU General Public License in all respects for all of the
- * code used other than OpenSSL. If you modify file(s) with this exception, you
- * may extend this exception to your version of the file(s), but you are not
- * obligated to do so. If you do not wish to do so, delete this exception
- * statement from your version. If you delete this exception statement from all
- * source files in the program, then also delete it here.
- *
- */
-
-#include
-#include
-
-#include "config.h"
-
-#include "chat_session.h"
-#include "log.h"
-#include "muc.h"
-#include "config/preferences.h"
-#include "config/account.h"
-#include "roster_list.h"
-
-#ifdef HAVE_LIBOTR
-#include "otr/otr.h"
-#include
-#endif
-
-#include "ui/ui.h"
-
-void
-handle_room_join_error(const char * const room, const char * const err)
-{
- if (muc_active(room)) {
- muc_leave(room);
- }
- ui_handle_room_join_error(room, err);
-}
-
-// handle presence stanza errors
-void
-handle_presence_error(const char *from, const char * const type,
- const char *err_msg)
-{
- // handle error from recipient
- if (from != NULL) {
- ui_handle_recipient_error(from, err_msg);
-
- // handle errors from no recipient
- } else {
- ui_handle_error(err_msg);
- }
-}
-
-// handle message stanza errors
-void
-handle_message_error(const char * const jid, const char * const type,
- const char * const err_msg)
-{
- // handle errors from no recipient
- if (jid == NULL) {
- ui_handle_error(err_msg);
-
- // handle recipient not found ('from' contains a value and type is 'cancel')
- } else if (type != NULL && (strcmp(type, "cancel") == 0)) {
- log_info("Recipient %s not found: %s", jid, err_msg);
- Jid *jidp = jid_create(jid);
- chat_session_remove(jidp->barejid);
-
- // handle any other error from recipient
- } else {
- ui_handle_recipient_error(jid, err_msg);
- }
-}
-
-void
-handle_login_account_success(char *account_name)
-{
- ProfAccount *account = accounts_get_account(account_name);
-
-#ifdef HAVE_LIBOTR
- otr_on_connect(account);
-#endif
-
- ui_handle_login_account_success(account);
-
- // attempt to rejoin rooms with passwords
- GList *curr = muc_rooms();
- while (curr != NULL) {
- char *password = muc_password(curr->data);
- if (password != NULL) {
- char *nick = muc_nick(curr->data);
- presence_join_room(curr->data, nick, password);
- }
- curr = g_list_next(curr);
- }
- g_list_free(curr);
-
- log_info("%s logged in successfully", account->jid);
- account_free(account);
-}
-
-void
-handle_roster_received(void)
-{
- if (prefs_get_boolean(PREF_ROSTER)) {
- ui_show_roster();
- }
-}
-
-void
-handle_lost_connection(void)
-{
- cons_show_error("Lost connection.");
- roster_clear();
- muc_invites_clear();
- chat_sessions_clear();
- ui_disconnected();
-}
-
-void
-handle_failed_login(void)
-{
- cons_show_error("Login failed.");
- log_info("Login failed");
-}
-
-void
-handle_software_version_result(const char * const jid, const char * const presence,
- const char * const name, const char * const version, const char * const os)
-{
- cons_show_software_version(jid, presence, name, version, os);
-}
-
-void
-handle_disco_info(const char *from, GSList *identities, GSList *features)
-{
- cons_show_disco_info(from, identities, features);
-}
-
-void
-handle_room_disco_info(const char * const room, GSList *identities, GSList *features)
-{
- ui_show_room_disco_info(room, identities, features);
-}
-
-void
-handle_disco_info_error(const char * const from, const char * const error)
-{
- if (from) {
- cons_show_error("Service discovery failed for %s: %s", from, error);
- } else {
- cons_show_error("Service discovery failed: %s", error);
- }
-}
-
-void
-handle_room_info_error(const char * const room, const char * const error)
-{
- ui_handle_room_info_error(room, error);
-}
-
-void
-handle_room_list(GSList *rooms, const char *conference_node)
-{
- cons_show_room_list(rooms, conference_node);
-}
-
-void
-handle_room_affiliation_list_result_error(const char * const room, const char * const affiliation,
- const char * const error)
-{
- log_debug("Error retrieving %s list for room %s: %s", affiliation, room, error);
- ui_handle_room_affiliation_list_error(room, affiliation, error);
-}
-
-void
-handle_room_affiliation_list(const char * const room, const char * const affiliation, GSList *jids)
-{
- muc_jid_autocomplete_add_all(room, jids);
- ui_handle_room_affiliation_list(room, affiliation, jids);
-}
-
-void
-handle_room_role_set_error(const char * const room, const char * const nick, const char * const role,
- const char * const error)
-{
- log_debug("Error setting role %s list for room %s, user %s: %s", role, room, nick, error);
- ui_handle_room_role_set_error(room, nick, role, error);
-}
-
-void
-handle_room_role_list_result_error(const char * const room, const char * const role, const char * const error)
-{
- log_debug("Error retrieving %s list for room %s: %s", role, room, error);
- ui_handle_room_role_list_error(room, role, error);
-}
-
-void
-handle_room_role_list(const char * const room, const char * const role, GSList *nicks)
-{
- ui_handle_room_role_list(room, role, nicks);
-}
-
-void
-handle_room_affiliation_set_error(const char * const room, const char * const jid, const char * const affiliation,
- const char * const error)
-{
- log_debug("Error setting affiliation %s list for room %s, user %s: %s", affiliation, room, jid, error);
- ui_handle_room_affiliation_set_error(room, jid, affiliation, error);
-}
-
-void
-handle_disco_items(GSList *items, const char *jid)
-{
- cons_show_disco_items(items, jid);
-}
-
-void
-handle_room_invite(jabber_invite_t invite_type,
- const char * const invitor, const char * const room,
- const char * const reason)
-{
- if (!muc_active(room) && !muc_invites_contain(room)) {
- cons_show_room_invite(invitor, room, reason);
- muc_invites_add(room);
- }
-}
-
-void
-handle_room_broadcast(const char *const room_jid,
- const char * const message)
-{
- if (muc_roster_complete(room_jid)) {
- ui_room_broadcast(room_jid, message);
- } else {
- muc_pending_broadcasts_add(room_jid, message);
- }
-}
-
-void
-handle_room_subject(const char * const room, const char * const nick, const char * const subject)
-{
- muc_set_subject(room, subject);
- if (muc_roster_complete(room)) {
- ui_room_subject(room, nick, subject);
- }
-}
-
-void
-handle_room_history(const char * const room_jid, const char * const nick,
- GTimeVal tv_stamp, const char * const message)
-{
- ui_room_history(room_jid, nick, tv_stamp, message);
-}
-
-void
-handle_room_message(const char * const room_jid, const char * const nick,
- const char * const message)
-{
- ui_room_message(room_jid, nick, message);
-
- if (prefs_get_boolean(PREF_GRLOG)) {
- Jid *jid = jid_create(jabber_get_fulljid());
- groupchat_log_chat(jid->barejid, room_jid, nick, message);
- jid_destroy(jid);
- }
-}
-
-void
-handle_incoming_private_message(char *fulljid, char *message)
-{
- ui_incoming_private_msg(fulljid, message, NULL);
-}
-
-void
-handle_incoming_message(char *barejid, char *resource, char *message)
-{
-#ifdef HAVE_LIBOTR
- gboolean was_decrypted = FALSE;
- char *newmessage;
-
- prof_otrpolicy_t policy = otr_get_policy(barejid);
- char *whitespace_base = strstr(message,OTRL_MESSAGE_TAG_BASE);
-
- //check for OTR whitespace (opportunistic or always)
- if (policy == PROF_OTRPOLICY_OPPORTUNISTIC || policy == PROF_OTRPOLICY_ALWAYS) {
- if (whitespace_base) {
- if (strstr(message, OTRL_MESSAGE_TAG_V2) || strstr(message, OTRL_MESSAGE_TAG_V1)) {
- // Remove whitespace pattern for proper display in UI
- // Handle both BASE+TAGV1/2(16+8) and BASE+TAGV1+TAGV2(16+8+8)
- int tag_length = 24;
- if (strstr(message, OTRL_MESSAGE_TAG_V2) && strstr(message, OTRL_MESSAGE_TAG_V1)) {
- tag_length = 32;
- }
- memmove(whitespace_base, whitespace_base+tag_length, tag_length);
- char *otr_query_message = otr_start_query();
- cons_show("OTR Whitespace pattern detected. Attempting to start OTR session...");
- message_send_chat(barejid, otr_query_message);
- }
- }
- }
- newmessage = otr_decrypt_message(barejid, message, &was_decrypted);
-
- // internal OTR message
- if (newmessage == NULL) {
- return;
- }
-
- if (policy == PROF_OTRPOLICY_ALWAYS && !was_decrypted && !whitespace_base) {
- char *otr_query_message = otr_start_query();
- cons_show("Attempting to start OTR session...");
- message_send_chat(barejid, otr_query_message);
- }
-
- ui_incoming_msg(barejid, resource, newmessage, NULL);
-
- if (prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
-
- char *pref_otr_log = prefs_get_string(PREF_OTR_LOG);
- if (!was_decrypted || (strcmp(pref_otr_log, "on") == 0)) {
- chat_log_chat(jidp->barejid, barejid, newmessage, PROF_IN_LOG, NULL);
- } else if (strcmp(pref_otr_log, "redact") == 0) {
- chat_log_chat(jidp->barejid, barejid, "[redacted]", PROF_IN_LOG, NULL);
- }
- prefs_free_string(pref_otr_log);
-
- jid_destroy(jidp);
- }
-
- otr_free_message(newmessage);
-#else
- ui_incoming_msg(barejid, resource, message, NULL);
-
- if (prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
- chat_log_chat(jidp->barejid, barejid, message, PROF_IN_LOG, NULL);
- jid_destroy(jidp);
- }
-#endif
-}
-
-void
-handle_delayed_private_message(char *fulljid, char *message, GTimeVal tv_stamp)
-{
- ui_incoming_private_msg(fulljid, message, &tv_stamp);
-}
-
-void
-handle_delayed_message(char *barejid, char *message, GTimeVal tv_stamp)
-{
- ui_incoming_msg(barejid, NULL, message, &tv_stamp);
-
- if (prefs_get_boolean(PREF_CHLOG)) {
- const char *jid = jabber_get_fulljid();
- Jid *jidp = jid_create(jid);
- chat_log_chat(jidp->barejid, barejid, message, PROF_IN_LOG, &tv_stamp);
- jid_destroy(jidp);
- }
-}
-
-void
-handle_typing(char *barejid, char *resource)
-{
- ui_contact_typing(barejid, resource);
- if (ui_chat_win_exists(barejid)) {
- chat_session_recipient_typing(barejid, resource);
- }
-}
-
-void
-handle_paused(char *barejid, char *resource)
-{
- if (ui_chat_win_exists(barejid)) {
- chat_session_recipient_paused(barejid, resource);
- }
-}
-
-void
-handle_inactive(char *barejid, char *resource)
-{
- if (ui_chat_win_exists(barejid)) {
- chat_session_recipient_inactive(barejid, resource);
- }
-}
-
-void
-handle_gone(const char * const barejid, const char * const resource)
-{
- ui_recipient_gone(barejid, resource);
- if (ui_chat_win_exists(barejid)) {
- chat_session_recipient_gone(barejid, resource);
- }
-}
-
-void
-handle_activity(const char * const barejid, const char * const resource, gboolean send_states)
-{
- if (ui_chat_win_exists(barejid)) {
- chat_session_recipient_active(barejid, resource, send_states);
- }
-}
-
-void
-handle_subscription(const char *barejid, jabber_subscr_t type)
-{
- switch (type) {
- case PRESENCE_SUBSCRIBE:
- /* TODO: auto-subscribe if needed */
- cons_show("Received authorization request from %s", barejid);
- log_info("Received authorization request from %s", barejid);
- ui_print_system_msg_from_recipient(barejid, "Authorization request, type '/sub allow' to accept or '/sub deny' to reject");
- if (prefs_get_boolean(PREF_NOTIFY_SUB)) {
- notify_subscription(barejid);
- }
- break;
- case PRESENCE_SUBSCRIBED:
- cons_show("Subscription received from %s", barejid);
- log_info("Subscription received from %s", barejid);
- ui_print_system_msg_from_recipient(barejid, "Subscribed");
- break;
- case PRESENCE_UNSUBSCRIBED:
- cons_show("%s deleted subscription", barejid);
- log_info("%s deleted subscription", barejid);
- ui_print_system_msg_from_recipient(barejid, "Unsubscribed");
- break;
- default:
- /* unknown type */
- break;
- }
-}
-
-void
-handle_contact_offline(char *barejid, char *resource, char *status)
-{
- gboolean updated = roster_contact_offline(barejid, resource, status);
-
- if (resource != NULL && updated) {
- ui_contact_offline(barejid, resource, status);
- }
-
- rosterwin_roster();
- chat_session_remove(barejid);
-}
-
-void
-handle_contact_online(char *barejid, Resource *resource,
- GDateTime *last_activity)
-{
- gboolean updated = roster_update_presence(barejid, resource, last_activity);
-
- if (updated) {
- char *show_console = prefs_get_string(PREF_STATUSES_CONSOLE);
- char *show_chat_win = prefs_get_string(PREF_STATUSES_CHAT);
- PContact contact = roster_get_contact(barejid);
- if (p_contact_subscription(contact) != NULL) {
- if (strcmp(p_contact_subscription(contact), "none") != 0) {
-
- // show in console if "all"
- if (g_strcmp0(show_console, "all") == 0) {
- cons_show_contact_online(contact, resource, last_activity);
-
- // show in console of "online" and presence online
- } else if (g_strcmp0(show_console, "online") == 0 &&
- resource->presence == RESOURCE_ONLINE) {
- cons_show_contact_online(contact, resource, last_activity);
-
- }
-
- // show in chat win if "all"
- if (g_strcmp0(show_chat_win, "all") == 0) {
- ui_chat_win_contact_online(contact, resource, last_activity);
-
- // show in char win if "online" and presence online
- } else if (g_strcmp0(show_chat_win, "online") == 0 &&
- resource->presence == RESOURCE_ONLINE) {
- ui_chat_win_contact_online(contact, resource, last_activity);
- }
- }
- }
- prefs_free_string(show_console);
- prefs_free_string(show_chat_win);
- }
-
- rosterwin_roster();
- chat_session_remove(barejid);
-}
-
-void
-handle_leave_room(const char * const room)
-{
- muc_leave(room);
- ui_leave_room(room);
-}
-
-void
-handle_room_destroy(const char * const room)
-{
- muc_leave(room);
- ui_room_destroy(room);
-}
-
-void
-handle_room_destroyed(const char * const room, const char * const new_jid, const char * const password,
- const char * const reason)
-{
- muc_leave(room);
- ui_room_destroyed(room, reason, new_jid, password);
-}
-
-void
-handle_room_kicked(const char * const room, const char * const actor, const char * const reason)
-{
- muc_leave(room);
- ui_room_kicked(room, actor, reason);
-}
-
-void
-handle_room_banned(const char * const room, const char * const actor, const char * const reason)
-{
- muc_leave(room);
- ui_room_banned(room, actor, reason);
-}
-
-void
-handle_room_configure(const char * const room, DataForm *form)
-{
- ui_handle_room_configuration(room, form);
-}
-
-void
-handle_room_configuration_form_error(const char * const room, const char * const message)
-{
- ui_handle_room_configuration_form_error(room, message);
-}
-
-void
-handle_room_config_submit_result(const char * const room)
-{
- ui_handle_room_config_submit_result(room);
-}
-
-void
-handle_room_config_submit_result_error(const char * const room, const char * const message)
-{
- ui_handle_room_config_submit_result_error(room, message);
-}
-
-void
-handle_room_kick_result_error(const char * const room, const char * const nick, const char * const error)
-{
- ui_handle_room_kick_error(room, nick, error);
-}
-
-void
-handle_room_occupant_offline(const char * const room, const char * const nick,
- const char * const show, const char * const status)
-{
- muc_roster_remove(room, nick);
-
- char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
- if (g_strcmp0(muc_status_pref, "none") != 0) {
- ui_room_member_offline(room, nick);
- }
- prefs_free_string(muc_status_pref);
- occupantswin_occupants(room);
-}
-
-void
-handle_room_occupent_kicked(const char * const room, const char * const nick, const char * const actor,
- const char * const reason)
-{
- muc_roster_remove(room, nick);
- ui_room_member_kicked(room, nick, actor, reason);
- occupantswin_occupants(room);
-}
-
-void
-handle_room_occupent_banned(const char * const room, const char * const nick, const char * const actor,
- const char * const reason)
-{
- muc_roster_remove(room, nick);
- ui_room_member_banned(room, nick, actor, reason);
- occupantswin_occupants(room);
-}
-
-void
-handle_group_add(const char * const contact,
- const char * const group)
-{
- ui_group_added(contact, group);
-}
-
-void
-handle_group_remove(const char * const contact,
- const char * const group)
-{
- ui_group_removed(contact, group);
-}
-
-void
-handle_roster_remove(const char * const barejid)
-{
- ui_roster_remove(barejid);
-}
-
-void
-handle_roster_add(const char * const barejid, const char * const name)
-{
- ui_roster_add(barejid, name);
-}
-
-void
-handle_roster_update(const char * const barejid, const char * const name,
- GSList *groups, const char * const subscription, gboolean pending_out)
-{
- roster_update(barejid, name, groups, subscription, pending_out);
- rosterwin_roster();
-}
-
-void
-handle_autoping_cancel(void)
-{
- prefs_set_autoping(0);
- cons_show_error("Server ping not supported, autoping disabled.");
-}
-
-void
-handle_xmpp_stanza(const char * const msg)
-{
- ui_handle_stanza(msg);
-}
-
-void
-handle_ping_result(const char * const from, int millis)
-{
- if (from == NULL) {
- cons_show("Ping response from server: %dms.", millis);
- } else {
- cons_show("Ping response from %s: %dms.", from, millis);
- }
-}
-
-void
-handle_ping_error_result(const char * const from, const char * const error)
-{
- if (error == NULL) {
- cons_show_error("Error returned from pinging %s.", from);
- } else {
- cons_show_error("Error returned from pinging %s: %s.", from, error);
- }
-}
-
-void
-handle_muc_self_online(const char * const room, const char * const nick, gboolean config_required,
- const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
- const char * const jid, const char * const show, const char * const status)
-{
- muc_roster_add(room, nick, jid, role, affiliation, show, status);
- char *old_role = muc_role_str(room);
- char *old_affiliation = muc_affiliation_str(room);
- muc_set_role(room, role);
- muc_set_affiliation(room, affiliation);
-
- // handle self nick change
- if (muc_nick_change_pending(room)) {
- muc_nick_change_complete(room, nick);
- ui_room_nick_change(room, nick);
-
- // handle roster complete
- } else if (!muc_roster_complete(room)) {
- if (muc_autojoin(room)) {
- ui_room_join(room, FALSE);
- } else {
- ui_room_join(room, TRUE);
- }
- muc_invites_remove(room);
- muc_roster_set_complete(room);
-
- // show roster if occupants list disabled by default
- if (!prefs_get_boolean(PREF_OCCUPANTS)) {
- GList *occupants = muc_roster(room);
- ui_room_roster(room, occupants, NULL);
- g_list_free(occupants);
- }
-
- char *subject = muc_subject(room);
- if (subject != NULL) {
- ui_room_subject(room, NULL, subject);
- }
-
- GList *pending_broadcasts = muc_pending_broadcasts(room);
- if (pending_broadcasts != NULL) {
- GList *curr = pending_broadcasts;
- while (curr != NULL) {
- ui_room_broadcast(room, curr->data);
- curr = g_list_next(curr);
- }
- }
-
- // room configuration required
- if (config_required) {
- muc_set_requires_config(room, TRUE);
- ui_room_requires_config(room);
- }
-
- // check for change in role/affiliation
- } else {
- if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
- // both changed
- if ((g_strcmp0(role, old_role) != 0) && (g_strcmp0(affiliation, old_affiliation) != 0)) {
- ui_room_role_and_affiliation_change(room, role, affiliation, actor, reason);
-
- // role changed
- } else if (g_strcmp0(role, old_role) != 0) {
- ui_room_role_change(room, role, actor, reason);
-
- // affiliation changed
- } else if (g_strcmp0(affiliation, old_affiliation) != 0) {
- ui_room_affiliation_change(room, affiliation, actor, reason);
- }
- }
- }
-
- occupantswin_occupants(room);
-}
-
-void
-handle_muc_occupant_online(const char * const room, const char * const nick, const char * const jid,
- const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
- const char * const show, const char * const status)
-{
- Occupant *occupant = muc_roster_item(room, nick);
-
- const char *old_role = NULL;
- const char *old_affiliation = NULL;
- if (occupant) {
- old_role = muc_occupant_role_str(occupant);
- old_affiliation = muc_occupant_affiliation_str(occupant);
- }
-
- gboolean updated = muc_roster_add(room, nick, jid, role, affiliation, show, status);
-
- // not yet finished joining room
- if (!muc_roster_complete(room)) {
- return;
- }
-
- // handle nickname change
- char *old_nick = muc_roster_nick_change_complete(room, nick);
- if (old_nick) {
- ui_room_member_nick_change(room, old_nick, nick);
- free(old_nick);
- occupantswin_occupants(room);
- return;
- }
-
- // joined room
- if (!occupant) {
- char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
- if (g_strcmp0(muc_status_pref, "none") != 0) {
- ui_room_member_online(room, nick, role, affiliation, show, status);
- }
- prefs_free_string(muc_status_pref);
- occupantswin_occupants(room);
- return;
- }
-
- // presence updated
- if (updated) {
- char *muc_status_pref = prefs_get_string(PREF_STATUSES_MUC);
- if (g_strcmp0(muc_status_pref, "all") == 0) {
- ui_room_member_presence(room, nick, show, status);
- }
- prefs_free_string(muc_status_pref);
- occupantswin_occupants(room);
-
- // presence unchanged, check for role/affiliation change
- } else {
- if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
- // both changed
- if ((g_strcmp0(role, old_role) != 0) && (g_strcmp0(affiliation, old_affiliation) != 0)) {
- ui_room_occupant_role_and_affiliation_change(room, nick, role, affiliation, actor, reason);
-
- // role changed
- } else if (g_strcmp0(role, old_role) != 0) {
- ui_room_occupant_role_change(room, nick, role, actor, reason);
-
- // affiliation changed
- } else if (g_strcmp0(affiliation, old_affiliation) != 0) {
- ui_room_occupant_affiliation_change(room, nick, affiliation, actor, reason);
- }
- }
- occupantswin_occupants(room);
- }
-}
\ No newline at end of file
diff --git a/src/server_events.h b/src/server_events.h
deleted file mode 100644
index 6a12dc6e..00000000
--- a/src/server_events.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * server_events.h
- *
- * Copyright (C) 2012 - 2014 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 .
- *
- * In addition, as a special exception, the copyright holders give permission to
- * link the code of portions of this program with the OpenSSL library under
- * certain conditions as described in each individual source file, and
- * distribute linked combinations including the two.
- *
- * You must obey the GNU General Public License in all respects for all of the
- * code used other than OpenSSL. If you modify file(s) with this exception, you
- * may extend this exception to your version of the file(s), but you are not
- * obligated to do so. If you do not wish to do so, delete this exception
- * statement from your version. If you delete this exception statement from all
- * source files in the program, then also delete it here.
- *
- */
-
-#ifndef SERVER_EVENTS_H
-#define SERVER_EVENTS_H
-
-#include "xmpp/xmpp.h"
-
-void handle_login_account_success(char *account_name);
-void handle_lost_connection(void);
-void handle_failed_login(void);
-void handle_software_version_result(const char * const jid, const char * const presence,
- const char * const name, const char * const version, const char * const os);
-void handle_disco_info(const char *from, GSList *identities, GSList *features);
-void handle_disco_info_error(const char * const from, const char * const error);
-void handle_room_list(GSList *rooms, const char *conference_node);
-void handle_disco_items(GSList *items, const char *jid);
-void handle_room_invite(jabber_invite_t invite_type,
- const char * const invitor, const char * const room,
- const char * const reason);
-void handle_room_broadcast(const char *const room_jid,
- const char * const message);
-void handle_room_subject(const char * const room, const char * const nick, const char * const subject);
-void handle_room_history(const char * const room_jid, const char * const nick,
- GTimeVal tv_stamp, const char * const message);
-void handle_room_message(const char * const room_jid, const char * const nick,
- const char * const message);
-void handle_room_join_error(const char * const room, const char * const err);
-void handle_room_info_error(const char * const room, const char * const error);
-void handle_room_disco_info(const char * const room, GSList *identities, GSList *features);
-void handle_room_affiliation_list_result_error(const char * const room, const char * const affiliation,
- const char * const error);
-void handle_room_affiliation_list(const char * const room, const char * const affiliation, GSList *jids);
-void handle_room_affiliation_set_error(const char * const room, const char * const jid, const char * const affiliation,
- const char * const error);
-void handle_room_role_list_result_error(const char * const from, const char * const role, const char * const error);
-void handle_room_role_list(const char * const from, const char * const role, GSList *nicks);
-void handle_room_role_set_error(const char * const room, const char * const nick, const char * const role,
- const char * const error);
-void handle_room_kick_result_error(const char * const room, const char * const nick, const char * const error);
-void handle_incoming_message(char *barejid, char *resource, char *message);
-void handle_incoming_private_message(char *fulljid, char *message);
-void handle_delayed_message(char *fulljid, char *message, GTimeVal tv_stamp);
-void handle_delayed_private_message(char *fulljid, char *message, GTimeVal tv_stamp);
-void handle_typing(char *barejid, char *resource);
-void handle_paused(char *barejid, char *resource);
-void handle_inactive(char *barejid, char *resource);
-void handle_activity(char *barejid, char *resource, gboolean send_states);
-void handle_gone(const char * const barejid, const char * const resource);
-void handle_subscription(const char *from, jabber_subscr_t type);
-void handle_contact_offline(char *contact, char *resource, char *status);
-void handle_contact_online(char *contact, Resource *resource,
- GDateTime *last_activity);
-void handle_leave_room(const char * const room);
-void handle_room_destroy(const char * const room);
-void handle_room_occupant_offline(const char * const room, const char * const nick,
- const char * const show, const char * const status);
-void handle_room_destroyed(const char * const room, const char * const new_jid, const char * const password,
- const char * const reason);
-void handle_room_kicked(const char * const room, const char * const actor, const char * const reason);
-void handle_room_occupent_kicked(const char * const room, const char * const nick, const char * const actor,
- const char * const reason);
-void handle_room_banned(const char * const room, const char * const actor, const char * const reason);
-void handle_room_occupent_banned(const char * const room, const char * const nick, const char * const actor,
- const char * const reason);
-void handle_group_add(const char * const contact,
- const char * const group);
-void handle_group_remove(const char * const contact,
- const char * const group);
-void handle_roster_remove(const char * const barejid);
-void handle_roster_add(const char * const barejid, const char * const name);
-void handle_autoping_cancel(void);
-void handle_message_error(const char * const from, const char * const type,
- const char * const err_msg);
-void handle_presence_error(const char *from, const char * const type,
- const char *err_msg);
-void handle_xmpp_stanza(const char * const msg);
-void handle_ping_result(const char * const from, int millis);
-void handle_ping_error_result(const char * const from, const char * const error);
-void handle_room_configure(const char * const room, DataForm *form);
-void handle_room_configuration_form_error(const char * const from, const char * const message);
-void handle_room_config_submit_result(const char * const room);
-void handle_room_config_submit_result_error(const char * const room, const char * const message);
-void handle_muc_self_online(const char * const room, const char * const nick, gboolean config_required,
- const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
- const char * const jid, const char * const show, const char * const status);
-void handle_muc_occupant_online(const char * const room, const char * const nick, const char * const jid,
- const char * const role, const char * const affiliation, const char * const actor, const char * const reason,
- const char * const show_str, const char * const status_str);
-void handle_roster_update(const char * const barejid, const char * const name,
- GSList *groups, const char * const subscription, gboolean pending_out);
-void handle_roster_received(void);
-
-#endif
diff --git a/src/tools/autocomplete.c b/src/tools/autocomplete.c
index 2623c828..7624f1df 100644
--- a/src/tools/autocomplete.c
+++ b/src/tools/autocomplete.c
@@ -1,7 +1,7 @@
/*
* autocomplete.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/tools/autocomplete.h b/src/tools/autocomplete.h
index 70cd8f30..c4b94b09 100644
--- a/src/tools/autocomplete.h
+++ b/src/tools/autocomplete.h
@@ -1,7 +1,7 @@
/*
* autocomplete.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/tools/history.c b/src/tools/history.c
deleted file mode 100644
index def10feb..00000000
--- a/src/tools/history.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * history.c
- *
- * Copyright (C) 2012 - 2014 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 .
- *
- * In addition, as a special exception, the copyright holders give permission to
- * link the code of portions of this program with the OpenSSL library under
- * certain conditions as described in each individual source file, and
- * distribute linked combinations including the two.
- *
- * You must obey the GNU General Public License in all respects for all of the
- * code used other than OpenSSL. If you modify file(s) with this exception, you
- * may extend this exception to your version of the file(s), but you are not
- * obligated to do so. If you do not wish to do so, delete this exception
- * statement from your version. If you delete this exception statement from all
- * source files in the program, then also delete it here.
- *
- */
-
-#include
-#include
-
-#include
-
-#include "history.h"
-
-struct history_session_t {
- GList *items;
- GList *sess_curr;
- GList *sess_new;
- GList *orig_curr;
-};
-
-struct history_t {
- GList *items;
- guint max_size;
- struct history_session_t session;
-};
-
-static void _replace_history_with_session(History history);
-static gboolean _adding_new(History history);
-static void _reset_session(History history);
-static gboolean _has_session(History history);
-static void _remove_first(History history);
-static void _update_current_session_item(History history, char *item);
-static void _add_to_history(History history, char *item);
-static void _remove_last_session_item(History history);
-static void _replace_current_with_original(History history);
-static void _create_session(History history);
-static void _session_previous(History history);
-static void _session_next(History history);
-
-History
-history_new(unsigned int size)
-{
- History new_history = malloc(sizeof(struct history_t));
- new_history->items = NULL;
- new_history->max_size = size;
-
- _reset_session(new_history);
-
- return new_history;
-}
-
-void
-history_append(History history, char *item)
-{
- char *copied = "";
- if (item != NULL) {
- copied = strdup(item);
- }
-
- if (history->items == NULL) {
- _add_to_history(history, copied);
- return;
- }
-
- if (!_has_session(history)) {
- if (g_list_length(history->items) == history->max_size) {
- _remove_first(history);
- }
-
- _add_to_history(history, copied);
-
- } else {
- _update_current_session_item(history, copied);
-
- if (_adding_new(history)) {
- if (strcmp(history->session.sess_curr->data, "") == 0) {
- _remove_last_session_item(history);
- }
-
- _replace_history_with_session(history);
-
- } else {
- _remove_last_session_item(history);
-
- char *new = strdup(history->session.sess_curr->data);
- history->session.items = g_list_append(history->session.items, new);
-
- _replace_current_with_original(history);
- _replace_history_with_session(history);
- }
- }
-}
-
-char *
-history_previous(History history, char *item)
-{
- // no history
- if (history->items == NULL) {
- return NULL;
- }
-
- char *copied = "";
- if (item != NULL) {
- copied = strdup(item);
- }
-
- if (!_has_session(history)) {
- _create_session(history);
-
- // add the new item
- history->session.items = g_list_append(history->session.items, copied);
- history->session.sess_new = g_list_last(history->session.items);
-
- char *result = strdup(history->session.sess_curr->data);
- return result;
- } else {
- _update_current_session_item(history, copied);
- _session_previous(history);
- }
-
- char *result = strdup(history->session.sess_curr->data);
- return result;
-}
-
-char *
-history_next(History history, char *item)
-{
- // no history, or no session, return NULL
- if ((history->items == NULL) || (history->session.items == NULL)) {
- return NULL;
- }
-
- if (g_list_next(history->session.sess_curr) == NULL) {
- return NULL;
- }
-
- char *copied = "";
- if (item != NULL) {
- copied = strdup(item);
- }
-
- _update_current_session_item(history, copied);
- _session_next(history);
-
- char *result = strdup(history->session.sess_curr->data);
- return result;
-}
-
-static void
-_replace_history_with_session(History history)
-{
- g_list_free(history->items);
- history->items = g_list_copy(history->session.items);
-
- if (g_list_length(history->items) > history->max_size) {
- _remove_first(history);
- }
-
- _reset_session(history);
-}
-
-static gboolean
-_adding_new(History history)
-{
- return (history->session.sess_curr ==
- g_list_last(history->session.items));
-}
-
-static void
-_reset_session(History history)
-{
- history->session.items = NULL;
- history->session.sess_curr = NULL;
- history->session.sess_new = NULL;
- history->session.orig_curr = NULL;
-}
-
-static gboolean
-_has_session(History history)
-{
- return (history->session.items != NULL);
-}
-
-static void
-_remove_first(History history)
-{
- GList *first = g_list_first(history->items);
- char *first_item = first->data;
- history->items = g_list_remove(history->items, first_item);
-}
-
-static void
-_update_current_session_item(History history, char *item)
-{
- history->session.sess_curr->data = item;
-}
-
-static void
-_add_to_history(History history, char *item)
-{
- history->items = g_list_append(history->items, item);
-}
-
-static void
-_remove_last_session_item(History history)
-{
- history->session.items = g_list_reverse(history->session.items);
- GList *first = g_list_first(history->session.items);
- history->session.items =
- g_list_remove(history->session.items, first->data);
- history->session.items = g_list_reverse(history->session.items);
-}
-
-static void
-_replace_current_with_original(History history)
-{
- history->session.sess_curr->data = strdup(history->session.orig_curr->data);
-}
-
-static void
-_create_session(History history)
-{
- history->session.items = g_list_copy(history->items);
- history->session.sess_curr = g_list_last(history->session.items);
- history->session.orig_curr = g_list_last(history->items);
-}
-
-static void
-_session_previous(History history)
-{
- history->session.sess_curr =
- g_list_previous(history->session.sess_curr);
- if (history->session.orig_curr == NULL)
- history->session.orig_curr = g_list_last(history->items);
- else
- history->session.orig_curr =
- g_list_previous(history->session.orig_curr);
-
- if (history->session.sess_curr == NULL) {
- history->session.sess_curr = g_list_first(history->session.items);
- history->session.orig_curr = g_list_first(history->items);
- }
-}
-
-static void
-_session_next(History history)
-{
- history->session.sess_curr = g_list_next(history->session.sess_curr);
- history->session.orig_curr = g_list_next(history->session.orig_curr);
-
- if (history->session.sess_curr == NULL) {
- history->session.sess_curr = g_list_last(history->session.items);
- history->session.orig_curr = NULL;
- }
-}
diff --git a/src/tools/parser.c b/src/tools/parser.c
index e91b227d..d3a23264 100644
--- a/src/tools/parser.c
+++ b/src/tools/parser.c
@@ -1,7 +1,7 @@
/*
* parser.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -47,9 +47,9 @@
*
* inp - The line of input
* min - The minimum allowed number of arguments
- * max - The maxmimum allowed number of arguments
+ * max - The maximum allowed number of arguments
*
- * Returns - An NULL terminated array of strings representing the aguments
+ * Returns - An NULL terminated array of strings representing the arguments
* of the command, or NULL if the validation fails.
*
* E.g. the following input line:
@@ -69,7 +69,7 @@ parse_args(const char * const inp, int min, int max, gboolean *result)
return NULL;
}
- // copy and strip input of leading/trailing whitepsace
+ // copy and strip input of leading/trailing whitespace
char *copy = strdup(inp);
g_strstrip(copy);
@@ -156,7 +156,7 @@ parse_args(const char * const inp, int min, int max, gboolean *result)
token = g_slist_next(token);
int arg_count = 0;
- while (token != NULL) {
+ while (token) {
args[arg_count++] = strdup(token->data);
token = g_slist_next(token);
}
@@ -181,9 +181,9 @@ parse_args(const char * const inp, int min, int max, gboolean *result)
*
* inp - The line of input
* min - The minimum allowed number of arguments
- * max - The maxmimum allowed number of arguments
+ * max - The maximum allowed number of arguments
*
- * Returns - An NULL terminated array of strings representing the aguments
+ * Returns - An NULL terminated array of strings representing the arguments
* of the command, or NULL if the validation fails.
*
* E.g. the following input line:
@@ -303,7 +303,7 @@ parse_args_with_freetext(const char * const inp, int min, int max, gboolean *res
token = g_slist_next(token);
int arg_count = 0;
- while (token != NULL) {
+ while (token) {
args[arg_count++] = strdup(token->data);
token = g_slist_next(token);
}
@@ -419,7 +419,7 @@ parse_options(gchar **args, gchar **opt_keys, gboolean *res)
}
// check if duplicate
- if (g_list_find_custom(found_keys, args[curr], (GCompareFunc)g_strcmp0) != NULL) {
+ if (g_list_find_custom(found_keys, args[curr], (GCompareFunc)g_strcmp0)) {
*res = FALSE;
g_list_free(keys);
return options;
@@ -450,7 +450,7 @@ parse_options(gchar **args, gchar **opt_keys, gboolean *res)
void
options_destroy(GHashTable *options)
{
- if (options != NULL) {
+ if (options) {
g_hash_table_destroy(options);
}
}
diff --git a/src/tools/parser.h b/src/tools/parser.h
index eeb97df3..34fa55a0 100644
--- a/src/tools/parser.h
+++ b/src/tools/parser.h
@@ -1,7 +1,7 @@
/*
* parser.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/tools/tinyurl.c b/src/tools/tinyurl.c
index 3addc646..92ff97b8 100644
--- a/src/tools/tinyurl.c
+++ b/src/tools/tinyurl.c
@@ -1,7 +1,7 @@
/*
* tinyurl.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -74,7 +74,7 @@ tinyurl_get(char *url)
g_string_free(full_url, TRUE);
- if (output.buffer != NULL) {
+ if (output.buffer) {
output.buffer[output.size++] = '\0';
return output.buffer;
} else {
diff --git a/src/tools/tinyurl.h b/src/tools/tinyurl.h
index 9557228f..f69570c3 100644
--- a/src/tools/tinyurl.h
+++ b/src/tools/tinyurl.h
@@ -1,7 +1,7 @@
/*
* tinyurl.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/ui/buffer.c b/src/ui/buffer.c
index 52397b4b..0848b60f 100644
--- a/src/ui/buffer.c
+++ b/src/ui/buffer.c
@@ -1,7 +1,7 @@
/*
* buffer.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -81,7 +81,7 @@ buffer_free(ProfBuff buffer)
void
buffer_push(ProfBuff buffer, const char show_char, GDateTime *time,
- int flags, theme_item_t theme_item, const char * const from, const char * const message)
+ int flags, theme_item_t theme_item, const char * const from, const char * const message, DeliveryReceipt *receipt)
{
ProfBuffEntry *e = malloc(sizeof(struct prof_buff_entry_t));
e->show_char = show_char;
@@ -90,6 +90,7 @@ buffer_push(ProfBuff buffer, const char show_char, GDateTime *time,
e->time = time;
e->from = strdup(from);
e->message = strdup(message);
+ e->receipt = receipt;
if (g_slist_length(buffer->entries) == BUFF_SIZE) {
_free_entry(buffer->entries->data);
@@ -99,6 +100,24 @@ buffer_push(ProfBuff buffer, const char show_char, GDateTime *time,
buffer->entries = g_slist_append(buffer->entries, e);
}
+gboolean
+buffer_mark_received(ProfBuff buffer, const char * const id)
+{
+ GSList *entries = buffer->entries;
+ while (entries) {
+ ProfBuffEntry *entry = entries->data;
+ if (entry->receipt && g_strcmp0(entry->receipt->id, id) == 0) {
+ if (!entry->receipt->received) {
+ entry->receipt->received = TRUE;
+ return TRUE;
+ }
+ }
+ entries = g_slist_next(entries);
+ }
+
+ return FALSE;
+}
+
ProfBuffEntry*
buffer_yield_entry(ProfBuff buffer, int entry)
{
@@ -112,5 +131,9 @@ _free_entry(ProfBuffEntry *entry)
free(entry->message);
free(entry->from);
g_date_time_unref(entry->time);
+ if (entry->receipt) {
+ free(entry->receipt->id);
+ free(entry->receipt);
+ }
free(entry);
}
\ No newline at end of file
diff --git a/src/ui/buffer.h b/src/ui/buffer.h
index 34d6b04f..cad7eee0 100644
--- a/src/ui/buffer.h
+++ b/src/ui/buffer.h
@@ -1,7 +1,7 @@
/*
* buffer.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -40,6 +40,11 @@
#include
+typedef struct delivery_receipt_t {
+ char *id;
+ gboolean received;
+} DeliveryReceipt;
+
typedef struct prof_buff_entry_t {
char show_char;
GDateTime *time;
@@ -47,13 +52,18 @@ typedef struct prof_buff_entry_t {
theme_item_t theme_item;
char *from;
char *message;
+ DeliveryReceipt *receipt;
} ProfBuffEntry;
typedef struct prof_buff_t *ProfBuff;
ProfBuff buffer_create();
void buffer_free(ProfBuff buffer);
-void buffer_push(ProfBuff buffer, const char show_char, GDateTime *time, int flags, theme_item_t theme_item, const char * const from, const char * const message);
+void buffer_push(ProfBuff buffer, const char show_char, GDateTime *time, int flags, theme_item_t theme_item,
+ const char * const from, const char * const message, DeliveryReceipt *receipt);
int buffer_size(ProfBuff buffer);
ProfBuffEntry* buffer_yield_entry(ProfBuff buffer, int entry);
+gboolean buffer_mark_received(ProfBuff buffer, const char * const id);
+
+
#endif
diff --git a/src/ui/console.c b/src/ui/console.c
index 689f218c..895efda4 100644
--- a/src/ui/console.c
+++ b/src/ui/console.c
@@ -1,7 +1,7 @@
/*
* console.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -67,14 +67,14 @@ void
cons_show_time(void)
{
ProfWin *console = wins_get_console();
- win_save_print(console, '-', NULL, NO_EOL, 0, "", "");
+ win_print(console, '-', NULL, NO_EOL, 0, "", "");
}
void
cons_show_word(const char * const word)
{
ProfWin *console = wins_get_console();
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", word);
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", word);
}
void
@@ -86,7 +86,7 @@ cons_debug(const char * const msg, ...)
va_start(arg, msg);
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, msg, arg);
- win_save_println(console, fmt_msg->str);
+ win_println(console, fmt_msg->str);
g_string_free(fmt_msg, TRUE);
va_end(arg);
}
@@ -100,7 +100,7 @@ cons_show(const char * const msg, ...)
va_start(arg, msg);
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, msg, arg);
- win_save_println(console, fmt_msg->str);
+ win_println(console, fmt_msg->str);
g_string_free(fmt_msg, TRUE);
va_end(arg);
}
@@ -113,7 +113,7 @@ cons_show_error(const char * const msg, ...)
va_start(arg, msg);
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, msg, arg);
- win_save_print(console, '-', NULL, 0, THEME_ERROR, "", fmt_msg->str);
+ win_print(console, '-', NULL, 0, THEME_ERROR, "", fmt_msg->str);
g_string_free(fmt_msg, TRUE);
va_end(arg);
@@ -126,8 +126,8 @@ cons_show_typing(const char * const barejid)
ProfWin *console = wins_get_console();
const char * display_usr = NULL;
PContact contact = roster_get_contact(barejid);
- if (contact != NULL) {
- if (p_contact_name(contact) != NULL) {
+ if (contact) {
+ if (p_contact_name(contact)) {
display_usr = p_contact_name(contact);
} else {
display_usr = barejid;
@@ -136,7 +136,7 @@ cons_show_typing(const char * const barejid)
display_usr = barejid;
}
- win_save_vprint(console, '-', NULL, 0, THEME_TYPING, "", "!! %s is typing a message...", display_usr);
+ win_vprint(console, '-', NULL, 0, THEME_TYPING, "", "!! %s is typing a message...", display_usr);
cons_alert();
}
@@ -149,7 +149,7 @@ cons_show_incoming_message(const char * const short_from, const int win_index)
if (ui_index == 10) {
ui_index = 0;
}
- win_save_vprint(console, '-', NULL, 0, THEME_INCOMING, "", "<< incoming from %s (%d)", short_from, ui_index);
+ win_vprint(console, '-', NULL, 0, THEME_INCOMING, "", "<< incoming from %s (%d)", short_from, ui_index);
cons_alert();
}
@@ -167,23 +167,23 @@ cons_about(void)
if (strcmp(PACKAGE_STATUS, "development") == 0) {
#ifdef HAVE_GIT_VERSION
- win_save_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %sdev.%s.%s", PACKAGE_VERSION, PROF_GIT_BRANCH, PROF_GIT_REVISION);
+ win_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %sdev.%s.%s", PACKAGE_VERSION, PROF_GIT_BRANCH, PROF_GIT_REVISION);
#else
- win_save_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %sdev", PACKAGE_VERSION);
+ win_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %sdev", PACKAGE_VERSION);
#endif
} else {
- win_save_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %s", PACKAGE_VERSION);
+ win_vprint(console, '-', NULL, 0, 0, "", "Welcome to Profanity, version %s", PACKAGE_VERSION);
}
}
- win_save_vprint(console, '-', NULL, 0, 0, "", "Copyright (C) 2012 - 2014 James Booth <%s>.", PACKAGE_BUGREPORT);
- win_save_println(console, "License GPLv3+: GNU GPL version 3 or later ");
- win_save_println(console, "");
- win_save_println(console, "This is free software; you are free to change and redistribute it.");
- win_save_println(console, "There is NO WARRANTY, to the extent permitted by law.");
- win_save_println(console, "");
- win_save_println(console, "Type '/help' to show complete help.");
- win_save_println(console, "");
+ win_vprint(console, '-', NULL, 0, 0, "", "Copyright (C) 2012 - 2015 James Booth <%s>.", PACKAGE_BUGREPORT);
+ win_println(console, "License GPLv3+: GNU GPL version 3 or later ");
+ win_println(console, "");
+ win_println(console, "This is free software; you are free to change and redistribute it.");
+ win_println(console, "There is NO WARRANTY, to the extent permitted by law.");
+ win_println(console, "");
+ win_println(console, "Type '/help' to show complete help.");
+ win_println(console, "");
if (prefs_get_boolean(PREF_VERCHECK)) {
cons_check_version(FALSE);
@@ -200,18 +200,18 @@ cons_check_version(gboolean not_available_msg)
ProfWin *console = wins_get_console();
char *latest_release = release_get_latest();
- if (latest_release != NULL) {
+ if (latest_release) {
gboolean relase_valid = g_regex_match_simple("^\\d+\\.\\d+\\.\\d+$", latest_release, 0, 0);
if (relase_valid) {
if (release_is_new(latest_release)) {
- win_save_vprint(console, '-', NULL, 0, 0, "", "A new version of Profanity is available: %s", latest_release);
- win_save_println(console, "Check for details.");
- win_save_println(console, "");
+ win_vprint(console, '-', NULL, 0, 0, "", "A new version of Profanity is available: %s", latest_release);
+ win_println(console, "Check for details.");
+ win_println(console, "");
} else {
if (not_available_msg) {
- win_save_println(console, "No new version available.");
- win_save_println(console, "");
+ win_println(console, "No new version available.");
+ win_println(console, "");
}
}
@@ -225,16 +225,16 @@ void
cons_show_login_success(ProfAccount *account)
{
ProfWin *console = wins_get_console();
- win_save_vprint(console, '-', NULL, NO_EOL, 0, "", "%s logged in successfully, ", account->jid);
+ win_vprint(console, '-', NULL, NO_EOL, 0, "", "%s logged in successfully, ", account->jid);
resource_presence_t presence = accounts_get_login_presence(account->name);
const char *presence_str = string_from_resource_presence(presence);
theme_item_t presence_colour = theme_main_presence_attrs(presence_str);
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "%s", presence_str);
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " (priority %d)",
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "%s", presence_str);
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " (priority %d)",
accounts_get_priority_for_presence_type(account->name, presence));
- win_save_print(console, '-', NULL, NO_DATE, 0, "", ".");
+ win_print(console, '-', NULL, NO_DATE, 0, "", ".");
cons_alert();
}
@@ -247,10 +247,11 @@ cons_show_wins(void)
GSList *window_strings = wins_create_summary();
GSList *curr = window_strings;
- while (curr != NULL) {
- win_save_println(console, curr->data);
+ while (curr) {
+ win_println(console, curr->data);
curr = g_slist_next(curr);
}
+ g_slist_free_full(window_strings, free);
cons_show("");
cons_alert();
@@ -264,7 +265,7 @@ cons_show_room_invites(GSList *invites)
cons_show("No outstanding chat room invites.");
} else {
cons_show("Chat room invites, use /join or /decline commands:");
- while (invites != NULL) {
+ while (invites) {
cons_show(" %s", invites->data);
invites = g_slist_next(invites);
}
@@ -293,53 +294,53 @@ cons_show_caps(const char * const fulljid, resource_presence_t presence)
const char *resource_presence = string_from_resource_presence(presence);
theme_item_t presence_colour = theme_main_presence_attrs(resource_presence);
- win_save_vprint(console, '-', NULL, NO_EOL, presence_colour, "", "%s", fulljid);
- win_save_print(console, '-', NULL, NO_DATE, 0, "", ":");
+ win_vprint(console, '-', NULL, NO_EOL, presence_colour, "", "%s", fulljid);
+ win_print(console, '-', NULL, NO_DATE, 0, "", ":");
// show identity
- if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) {
- win_save_print(console, '-', NULL, NO_EOL, 0, "", "Identity: ");
- if (caps->name != NULL) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
- if ((caps->category != NULL) || (caps->type != NULL)) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
+ if (caps->category || caps->type || caps->name) {
+ win_print(console, '-', NULL, NO_EOL, 0, "", "Identity: ");
+ if (caps->name) {
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
+ if (caps->category || caps->type) {
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
- if (caps->type != NULL) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
- if (caps->category != NULL) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
+ if (caps->type) {
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
+ if (caps->category) {
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
- if (caps->category != NULL) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
+ if (caps->category) {
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
}
- win_save_newline(console);
+ win_newline(console);
}
- if (caps->software != NULL) {
- win_save_vprint(console, '-', NULL, NO_EOL, 0, "", "Software: %s", caps->software);
+ if (caps->software) {
+ win_vprint(console, '-', NULL, NO_EOL, 0, "", "Software: %s", caps->software);
}
- if (caps->software_version != NULL) {
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
+ if (caps->software_version) {
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
}
- if ((caps->software != NULL) || (caps->software_version != NULL)) {
- win_save_newline(console);
+ if (caps->software || caps->software_version) {
+ win_newline(console);
}
- if (caps->os != NULL) {
- win_save_vprint(console, '-', NULL, NO_EOL, 0, "", "OS: %s", caps->os);
+ if (caps->os) {
+ win_vprint(console, '-', NULL, NO_EOL, 0, "", "OS: %s", caps->os);
}
- if (caps->os_version != NULL) {
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
+ if (caps->os_version) {
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
}
- if ((caps->os != NULL) || (caps->os_version != NULL)) {
- win_save_newline(console);
+ if (caps->os || caps->os_version) {
+ win_newline(console);
}
- if (caps->features != NULL) {
- win_save_println(console, "Features:");
+ if (caps->features) {
+ win_println(console, "Features:");
GSList *feature = caps->features;
- while (feature != NULL) {
- win_save_vprint(console, '-', NULL, 0, 0, "", " %s", feature->data);
+ while (feature) {
+ win_vprint(console, '-', NULL, 0, 0, "", " %s", feature->data);
feature = g_slist_next(feature);
}
}
@@ -357,19 +358,19 @@ cons_show_software_version(const char * const jid, const char * const presence,
const char * const name, const char * const version, const char * const os)
{
ProfWin *console = wins_get_console();
- if ((name != NULL) || (version != NULL) || (os != NULL)) {
+ if (name || version || os) {
cons_show("");
theme_item_t presence_colour = theme_main_presence_attrs(presence);
- win_save_vprint(console, '-', NULL, NO_EOL, presence_colour, "", "%s", jid);
- win_save_print(console, '-', NULL, NO_DATE, 0, "", ":");
+ win_vprint(console, '-', NULL, NO_EOL, presence_colour, "", "%s", jid);
+ win_print(console, '-', NULL, NO_DATE, 0, "", ":");
}
- if (name != NULL) {
+ if (name) {
cons_show("Name : %s", name);
}
- if (version != NULL) {
+ if (version) {
cons_show("Version : %s", version);
}
- if (os != NULL) {
+ if (os) {
cons_show("OS : %s", os);
}
@@ -385,7 +386,7 @@ cons_show_received_subs(void)
} else {
cons_show("Outstanding subscription requests from:",
g_slist_length(received));
- while (received != NULL) {
+ while (received) {
cons_show(" %s", received->data);
received = g_slist_next(received);
}
@@ -402,17 +403,18 @@ cons_show_sent_subs(void)
GSList *contacts = roster_get_contacts();
PContact contact = NULL;
cons_show("Awaiting subscription responses from:");
- while (contacts != NULL) {
- contact = (PContact) contacts->data;
+ GSList *curr = contacts;
+ while (curr) {
+ contact = (PContact) curr->data;
if (p_contact_pending_out(contact)) {
cons_show(" %s", p_contact_barejid(contact));
}
- contacts = g_slist_next(contacts);
+ curr = g_slist_next(curr);
}
+ g_slist_free(contacts);
} else {
cons_show("No pending requests sent.");
}
-
cons_alert();
}
@@ -420,15 +422,15 @@ void
cons_show_room_list(GSList *rooms, const char * const conference_node)
{
ProfWin *console = wins_get_console();
- if ((rooms != NULL) && (g_slist_length(rooms) > 0)) {
+ if (rooms && (g_slist_length(rooms) > 0)) {
cons_show("Chat rooms at %s:", conference_node);
- while (rooms != NULL) {
+ while (rooms) {
DiscoItem *room = rooms->data;
- win_save_vprint(console, '-', NULL, NO_EOL, 0, "", " %s", room->jid);
- if (room->name != NULL) {
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", (%s)", room->name);
+ win_vprint(console, '-', NULL, NO_EOL, 0, "", " %s", room->jid);
+ if (room->name) {
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", (%s)", room->name);
}
- win_save_newline(console);
+ win_newline(console);
rooms = g_slist_next(rooms);
}
} else {
@@ -450,7 +452,7 @@ cons_show_bookmarks(const GList *list)
cons_show("");
cons_show("Bookmarks:");
- while (list != NULL) {
+ while (list) {
Bookmark *item = list->data;
theme_item_t presence_colour = THEME_TEXT;
@@ -458,24 +460,24 @@ cons_show_bookmarks(const GList *list)
if (muc_active(item->jid)) {
presence_colour = THEME_ONLINE;
}
- win_save_vprint(console, '-', NULL, NO_EOL, presence_colour, "", " %s", item->jid);
- if (item->nick != NULL) {
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "/%s", item->nick);
+ win_vprint(console, '-', NULL, NO_EOL, presence_colour, "", " %s", item->jid);
+ if (item->nick) {
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "/%s", item->nick);
}
if (item->autojoin) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (autojoin)");
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (autojoin)");
}
- if (item->password != NULL) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (private)");
+ if (item->password) {
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (private)");
}
if (muc_active(item->jid)) {
ProfWin *roomwin = (ProfWin*)wins_get_muc(item->jid);
- if (roomwin != NULL) {
+ if (roomwin) {
int num = wins_get_num(roomwin);
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (%d)", num);
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (%d)", num);
}
}
- win_save_newline(console);
+ win_newline(console);
list = g_list_next(list);
}
}
@@ -485,26 +487,26 @@ cons_show_bookmarks(const GList *list)
void
cons_show_disco_info(const char *jid, GSList *identities, GSList *features)
{
- if (((identities != NULL) && (g_slist_length(identities) > 0)) ||
- ((features != NULL) && (g_slist_length(features) > 0))) {
+ if ((identities && (g_slist_length(identities) > 0)) ||
+ (features && (g_slist_length(features) > 0))) {
cons_show("");
cons_show("Service disovery info for %s", jid);
- if (identities != NULL) {
+ if (identities) {
cons_show(" Identities");
}
- while (identities != NULL) {
+ while (identities) {
DiscoIdentity *identity = identities->data; // anme trpe, cat
GString *identity_str = g_string_new(" ");
- if (identity->name != NULL) {
+ if (identity->name) {
identity_str = g_string_append(identity_str, identity->name);
identity_str = g_string_append(identity_str, " ");
}
- if (identity->type != NULL) {
+ if (identity->type) {
identity_str = g_string_append(identity_str, identity->type);
identity_str = g_string_append(identity_str, " ");
}
- if (identity->category != NULL) {
+ if (identity->category) {
identity_str = g_string_append(identity_str, identity->category);
}
cons_show(identity_str->str);
@@ -512,10 +514,10 @@ cons_show_disco_info(const char *jid, GSList *identities, GSList *features)
identities = g_slist_next(identities);
}
- if (features != NULL) {
+ if (features) {
cons_show(" Features:");
}
- while (features != NULL) {
+ while (features) {
cons_show(" %s", features->data);
features = g_slist_next(features);
}
@@ -528,16 +530,16 @@ void
cons_show_disco_items(GSList *items, const char * const jid)
{
ProfWin *console = wins_get_console();
- if ((items != NULL) && (g_slist_length(items) > 0)) {
+ if (items && (g_slist_length(items) > 0)) {
cons_show("");
cons_show("Service discovery items for %s:", jid);
- while (items != NULL) {
+ while (items) {
DiscoItem *item = items->data;
- win_save_vprint(console, '-', NULL, NO_EOL, 0, "", " %s", item->jid);
- if (item->name != NULL) {
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", (%s)", item->name);
+ win_vprint(console, '-', NULL, NO_EOL, 0, "", " %s", item->jid);
+ if (item->name) {
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", (%s)", item->name);
}
- win_save_vprint(console, '-', NULL, NO_DATE, 0, "", "");
+ win_vprint(console, '-', NULL, NO_DATE, 0, "", "");
items = g_slist_next(items);
}
} else {
@@ -554,7 +556,7 @@ cons_show_status(const char * const barejid)
ProfWin *console = wins_get_console();
PContact pcontact = roster_get_contact(barejid);
- if (pcontact != NULL) {
+ if (pcontact) {
win_show_contact(console, pcontact);
} else {
cons_show("No such contact \"%s\" in roster.", barejid);
@@ -569,8 +571,8 @@ cons_show_room_invite(const char * const invitor, const char * const room,
{
char *display_from = NULL;
PContact contact = roster_get_contact(invitor);
- if (contact != NULL) {
- if (p_contact_name(contact) != NULL) {
+ if (contact) {
+ if (p_contact_name(contact)) {
display_from = strdup(p_contact_name(contact));
} else {
display_from = strdup(invitor);
@@ -584,7 +586,7 @@ cons_show_room_invite(const char * const invitor, const char * const room,
cons_show(" From : %s", display_from);
cons_show(" Room : %s", room);
- if (reason != NULL) {
+ if (reason) {
cons_show(" Message: %s", reason);
}
@@ -612,7 +614,7 @@ cons_show_account_list(gchar **accounts)
(g_strcmp0(jabber_get_account_name(), accounts[i]) == 0)) {
resource_presence_t presence = accounts_get_last_presence(accounts[i]);
theme_item_t presence_colour = theme_main_presence_attrs(string_from_resource_presence(presence));
- win_save_vprint(console, '-', NULL, 0, presence_colour, "", "%s", accounts[i]);
+ win_vprint(console, '-', NULL, 0, presence_colour, "", "%s", accounts[i]);
} else {
cons_show(accounts[i]);
}
@@ -671,9 +673,9 @@ cons_show_account(ProfAccount *account)
if (g_list_length(account->otr_manual) > 0) {
GString *manual = g_string_new("OTR manual : ");
GList *curr = account->otr_manual;
- while (curr != NULL) {
+ while (curr) {
g_string_append(manual, curr->data);
- if (curr->next != NULL) {
+ if (curr->next) {
g_string_append(manual, ", ");
}
curr = curr->next;
@@ -684,9 +686,9 @@ cons_show_account(ProfAccount *account)
if (g_list_length(account->otr_opportunistic) > 0) {
GString *opportunistic = g_string_new("OTR opportunistic : ");
GList *curr = account->otr_opportunistic;
- while (curr != NULL) {
+ while (curr) {
g_string_append(opportunistic, curr->data);
- if (curr->next != NULL) {
+ if (curr->next) {
g_string_append(opportunistic, ", ");
}
curr = curr->next;
@@ -697,9 +699,9 @@ cons_show_account(ProfAccount *account)
if (g_list_length(account->otr_always) > 0) {
GString *always = g_string_new("OTR always : ");
GList *curr = account->otr_always;
- while (curr != NULL) {
+ while (curr) {
g_string_append(always, curr->data);
- if (curr->next != NULL) {
+ if (curr->next) {
g_string_append(always, ", ");
}
curr = curr->next;
@@ -717,76 +719,81 @@ cons_show_account(ProfAccount *account)
GList *resources = jabber_get_available_resources();
GList *ordered_resources = NULL;
- if (resources != NULL) {
- win_save_println(console, "Resources:");
+ GList *curr = resources;
+ if (curr) {
+ win_println(console, "Resources:");
- // sort in order of availabiltiy
- while (resources != NULL) {
- Resource *resource = resources->data;
+ // sort in order of availability
+ while (curr) {
+ Resource *resource = curr->data;
ordered_resources = g_list_insert_sorted(ordered_resources,
resource, (GCompareFunc)resource_compare_availability);
- resources = g_list_next(resources);
+ curr = g_list_next(curr);
}
}
- while (ordered_resources != NULL) {
- Resource *resource = ordered_resources->data;
+ g_list_free(resources);
+
+ curr = ordered_resources;
+ while (curr) {
+ Resource *resource = curr->data;
const char *resource_presence = string_from_resource_presence(resource->presence);
theme_item_t presence_colour = theme_main_presence_attrs(resource_presence);
- win_save_vprint(console, '-', NULL, NO_EOL, presence_colour, "", " %s (%d), %s", resource->name, resource->priority, resource_presence);
+ win_vprint(console, '-', NULL, NO_EOL, presence_colour, "", " %s (%d), %s", resource->name, resource->priority, resource_presence);
- if (resource->status != NULL) {
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", resource->status);
+ if (resource->status) {
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", resource->status);
}
- win_save_vprint(console, '-', NULL, NO_DATE, 0, "", "");
+ win_vprint(console, '-', NULL, NO_DATE, 0, "", "");
Jid *jidp = jid_create_from_bare_and_resource(account->jid, resource->name);
Capabilities *caps = caps_lookup(jidp->fulljid);
jid_destroy(jidp);
- if (caps != NULL) {
+ if (caps) {
// show identity
- if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) {
- win_save_print(console, '-', NULL, NO_EOL, 0, "", " Identity: ");
- if (caps->name != NULL) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
- if ((caps->category != NULL) || (caps->type != NULL)) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
+ if (caps->category || caps->type || caps->name) {
+ win_print(console, '-', NULL, NO_EOL, 0, "", " Identity: ");
+ if (caps->name) {
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
+ if (caps->category || caps->type) {
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
- if (caps->type != NULL) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
- if (caps->category != NULL) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
+ if (caps->type) {
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
+ if (caps->category) {
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
- if (caps->category != NULL) {
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
+ if (caps->category) {
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
}
- win_save_newline(console);
+ win_newline(console);
}
- if (caps->software != NULL) {
- win_save_vprint(console, '-', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
+ if (caps->software) {
+ win_vprint(console, '-', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
}
- if (caps->software_version != NULL) {
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
+ if (caps->software_version) {
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
}
- if ((caps->software != NULL) || (caps->software_version != NULL)) {
- win_save_newline(console);
+ if (caps->software || caps->software_version) {
+ win_newline(console);
}
- if (caps->os != NULL) {
- win_save_vprint(console, '-', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
+ if (caps->os) {
+ win_vprint(console, '-', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
}
- if (caps->os_version != NULL) {
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
+ if (caps->os_version) {
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
}
- if ((caps->os != NULL) || (caps->os_version != NULL)) {
- win_save_newline(console);
+ if (caps->os || caps->os_version) {
+ win_newline(console);
}
caps_destroy(caps);
}
- ordered_resources = g_list_next(ordered_resources);
+ curr = g_list_next(curr);
}
+ g_list_free(ordered_resources);
}
cons_alert();
@@ -801,10 +808,10 @@ cons_show_aliases(GList *aliases)
}
GList *curr = aliases;
- if (curr != NULL) {
+ if (curr) {
cons_show("Command aliases:");
}
- while (curr != NULL) {
+ while (curr) {
ProfAlias *alias = curr->data;
cons_show(" /%s -> %s", alias->name, alias->value);
curr = g_list_next(curr);
@@ -850,9 +857,9 @@ cons_resource_setting(void)
else
cons_show("Resource title (/resource) : OFF");
if (prefs_get_boolean(PREF_RESOURCE_MESSAGE))
- cons_show("Message title (/resource) : ON");
+ cons_show("Resource message (/resource) : ON");
else
- cons_show("Message title (/resource) : OFF");
+ cons_show("Resource message (/resource) : OFF");
}
void
@@ -899,6 +906,11 @@ cons_occupants_setting(void)
else
cons_show("Occupants (/occupants) : hide");
+ if (prefs_get_boolean(PREF_OCCUPANTS_JID))
+ cons_show("Occupant jids (/occupants) : show");
+ else
+ cons_show("Occupant jids (/occupants) : hide");
+
int size = prefs_get_occupants_size();
cons_show("Occupants size (/occupants) : %d", size);
}
@@ -907,7 +919,7 @@ void
cons_autoconnect_setting(void)
{
char *pref_connect_account = prefs_get_string(PREF_CONNECT_ACCOUNT);
- if (pref_connect_account != NULL)
+ if (pref_connect_account)
cons_show("Autoconnect (/autoconnect) : %s", pref_connect_account);
else
cons_show("Autoconnect (/autoconnect) : OFF");
@@ -925,6 +937,16 @@ cons_time_setting(void)
cons_show("Time (/time) : %s", pref_time);
prefs_free_string(pref_time);
+
+ char *pref_time_statusbar = prefs_get_string(PREF_TIME_STATUSBAR);
+ if (g_strcmp0(pref_time_statusbar, "minutes") == 0)
+ cons_show("Time statusbar (/time) : minutes");
+ else if (g_strcmp0(pref_time_statusbar, "off") == 0)
+ cons_show("Time statusbar (/time) : OFF");
+ else
+ cons_show("Time statusbar (/time) : seconds");
+
+ prefs_free_string(pref_time_statusbar);
}
void
@@ -994,6 +1016,9 @@ cons_roster_setting(void)
else
cons_show("Roster resource (/roster) : hide");
+ char *by = prefs_get_string(PREF_ROSTER_BY);
+ cons_show("Roster by (/roster) : %s", by);
+
int size = prefs_get_roster_size();
cons_show("Roster size (/roster) : %d", size);
}
@@ -1120,27 +1145,27 @@ void
cons_states_setting(void)
{
if (prefs_get_boolean(PREF_STATES))
- cons_show("Send chat states (/states) : ON");
+ cons_show("Send chat states (/states) : ON");
else
- cons_show("Send chat states (/states) : OFF");
+ cons_show("Send chat states (/states) : OFF");
}
void
cons_outtype_setting(void)
{
if (prefs_get_boolean(PREF_OUTTYPE))
- cons_show("Send composing (/outtype) : ON");
+ cons_show("Send composing (/outtype) : ON");
else
- cons_show("Send composing (/outtype) : OFF");
+ cons_show("Send composing (/outtype) : OFF");
}
void
cons_intype_setting(void)
{
if (prefs_get_boolean(PREF_INTYPE))
- cons_show("Show typing (/intype) : ON");
+ cons_show("Show typing (/intype) : ON");
else
- cons_show("Show typing (/intype) : OFF");
+ cons_show("Show typing (/intype) : OFF");
}
void
@@ -1148,11 +1173,11 @@ cons_gone_setting(void)
{
gint gone_time = prefs_get_gone();
if (gone_time == 0) {
- cons_show("Leave conversation (/gone) : OFF");
+ cons_show("Leave conversation (/gone) : OFF");
} else if (gone_time == 1) {
- cons_show("Leave conversation (/gone) : 1 minute");
+ cons_show("Leave conversation (/gone) : 1 minute");
} else {
- cons_show("Leave conversation (/gone) : %d minutes", gone_time);
+ cons_show("Leave conversation (/gone) : %d minutes", gone_time);
}
}
@@ -1160,9 +1185,33 @@ void
cons_history_setting(void)
{
if (prefs_get_boolean(PREF_HISTORY))
- cons_show("Chat history (/history) : ON");
+ cons_show("Chat history (/history) : ON");
else
- cons_show("Chat history (/history) : OFF");
+ cons_show("Chat history (/history) : OFF");
+}
+
+void
+cons_carbons_setting(void)
+{
+ if (prefs_get_boolean(PREF_CARBONS))
+ cons_show("Message carbons (/carbons) : ON");
+ else
+ cons_show("Message carbons (/carbons) : OFF");
+}
+
+void
+cons_receipts_setting(void)
+{
+ if (prefs_get_boolean(PREF_RECEIPTS_REQUEST))
+ cons_show("Request receipts (/receipts) : ON");
+ else
+ cons_show("Request receipts (/receipts) : OFF");
+
+ if (prefs_get_boolean(PREF_RECEIPTS_SEND))
+ cons_show("Send receipts (/receipts) : ON");
+ else
+ cons_show("Send receipts (/receipts) : OFF");
+
}
void
@@ -1175,6 +1224,8 @@ cons_show_chat_prefs(void)
cons_intype_setting();
cons_gone_setting();
cons_history_setting();
+ cons_carbons_setting();
+ cons_receipts_setting();
cons_alert();
}
@@ -1359,7 +1410,7 @@ cons_show_themes(GSList *themes)
cons_show("No available themes.");
} else {
cons_show("Available themes:");
- while (themes != NULL) {
+ while (themes) {
cons_show(themes->data);
themes = g_slist_next(themes);
}
@@ -1400,7 +1451,7 @@ cons_help(void)
cons_show("/help basic - List basic commands for getting started.");
cons_show("/help chatting - List chat commands.");
cons_show("/help groupchat - List groupchat commands.");
- cons_show("/help presence - List commands to change presence.");
+ cons_show("/help presences - List commands to change presence.");
cons_show("/help contacts - List commands for manipulating your roster.");
cons_show("/help service - List service discovery commands.");
cons_show("/help settings - List commands for changing settings.");
@@ -1417,27 +1468,10 @@ cons_navigation_help(void)
cons_show("");
cons_show("Navigation:");
cons_show("");
- cons_show("Alt-1 : This console window.");
- cons_show("F1 : This console window.");
- cons_show("Alt-2..Alt-0 : Chat windows.");
- cons_show("F2..F10 : Chat windows.");
+ cons_show("Alt-1..Alt-0, F1..F10 : Choose window.");
cons_show("Alt-LEFT, Alt-RIGHT : Previous/next chat window");
- cons_show("UP, DOWN : Navigate input history.");
- cons_show("Ctrl-n, Ctrl-p : Navigate input history.");
- cons_show("LEFT, RIGHT, HOME, END : Move cursor.");
- cons_show("Ctrl-b, Ctrl-f, Ctrl-a, Ctrl-e : Move cursor.");
- cons_show("Ctrl-LEFT, Ctrl-RIGHT : Jump word.");
- cons_show("Ctrl-w : Delete previous word.");
- cons_show("Alt-Backspace : Delete previous word.");
- cons_show("Backspace : Delete previous character.");
- cons_show("DEL : Delete next character.");
- cons_show("Ctrl-d : Delete next character.");
- cons_show("ESC : Clear current input.");
- cons_show("Ctrl-u : Delete all previous characters.");
- cons_show("TAB : Autocomplete.");
- cons_show("PAGE UP, PAGE DOWN : Page the main window.");
- cons_show("Shift-UP, Shift-DOWN : Page occupants/roster panel.");
- cons_show("Ctrl-UP, Ctrl-DOWN : Page occupants/roster panel.");
+ cons_show("PAGEUP, PAGEDOWN : Page the main window.");
+ cons_show("Alt-PAGEUP, Alt-PAGEDOWN : Page occupants/roster panel.");
cons_show("");
cons_alert();
@@ -1448,7 +1482,7 @@ cons_show_roster_group(const char * const group, GSList *list)
{
cons_show("");
- if (list != NULL) {
+ if (list) {
cons_show("%s:", group);
} else {
cons_show("No group named %s exists.", group);
@@ -1537,22 +1571,22 @@ cons_theme_colours(void)
ProfWin *console = wins_get_console();
cons_show("Theme colours:");
- win_save_print(console, '-', NULL, NO_EOL, THEME_WHITE, "", " white ");
- win_save_print(console, '-', NULL, NO_DATE, THEME_WHITE_BOLD, "", " bold_white");
- win_save_print(console, '-', NULL, NO_EOL, THEME_GREEN, "", " green ");
- win_save_print(console, '-', NULL, NO_DATE, THEME_GREEN_BOLD, "", " bold_green");
- win_save_print(console, '-', NULL, NO_EOL, THEME_RED, "", " red ");
- win_save_print(console, '-', NULL, NO_DATE, THEME_RED_BOLD, "", " bold_red");
- win_save_print(console, '-', NULL, NO_EOL, THEME_YELLOW, "", " yellow ");
- win_save_print(console, '-', NULL, NO_DATE, THEME_YELLOW_BOLD, "", " bold_yellow");
- win_save_print(console, '-', NULL, NO_EOL, THEME_BLUE, "", " blue ");
- win_save_print(console, '-', NULL, NO_DATE, THEME_BLUE_BOLD, "", " bold_blue");
- win_save_print(console, '-', NULL, NO_EOL, THEME_CYAN, "", " cyan ");
- win_save_print(console, '-', NULL, NO_DATE, THEME_CYAN_BOLD, "", " bold_cyan");
- win_save_print(console, '-', NULL, NO_EOL, THEME_MAGENTA, "", " magenta ");
- win_save_print(console, '-', NULL, NO_DATE, THEME_MAGENTA_BOLD, "", " bold_magenta");
- win_save_print(console, '-', NULL, NO_EOL, THEME_BLACK, "", " black ");
- win_save_print(console, '-', NULL, NO_DATE, THEME_BLACK_BOLD, "", " bold_black");
+ win_print(console, '-', NULL, NO_EOL, THEME_WHITE, "", " white ");
+ win_print(console, '-', NULL, NO_DATE, THEME_WHITE_BOLD, "", " bold_white");
+ win_print(console, '-', NULL, NO_EOL, THEME_GREEN, "", " green ");
+ win_print(console, '-', NULL, NO_DATE, THEME_GREEN_BOLD, "", " bold_green");
+ win_print(console, '-', NULL, NO_EOL, THEME_RED, "", " red ");
+ win_print(console, '-', NULL, NO_DATE, THEME_RED_BOLD, "", " bold_red");
+ win_print(console, '-', NULL, NO_EOL, THEME_YELLOW, "", " yellow ");
+ win_print(console, '-', NULL, NO_DATE, THEME_YELLOW_BOLD, "", " bold_yellow");
+ win_print(console, '-', NULL, NO_EOL, THEME_BLUE, "", " blue ");
+ win_print(console, '-', NULL, NO_DATE, THEME_BLUE_BOLD, "", " bold_blue");
+ win_print(console, '-', NULL, NO_EOL, THEME_CYAN, "", " cyan ");
+ win_print(console, '-', NULL, NO_DATE, THEME_CYAN_BOLD, "", " bold_cyan");
+ win_print(console, '-', NULL, NO_EOL, THEME_MAGENTA, "", " magenta ");
+ win_print(console, '-', NULL, NO_DATE, THEME_MAGENTA_BOLD, "", " bold_magenta");
+ win_print(console, '-', NULL, NO_EOL, THEME_BLACK, "", " black ");
+ win_print(console, '-', NULL, NO_DATE, THEME_BLACK_BOLD, "", " bold_black");
cons_show("");
}
@@ -1560,25 +1594,25 @@ static void
_cons_splash_logo(void)
{
ProfWin *console = wins_get_console();
- win_save_println(console, "Welcome to");
+ win_println(console, "Welcome to");
- win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", " ___ _ ");
- win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", " / __) (_)_ ");
- win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", " ____ ____ ___ | |__ ____ ____ _| |_ _ _ ");
- win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", "| _ \\ / ___) _ \\| __) _ | _ \\| | _) | | |");
- win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", "| | | | | | |_| | | ( ( | | | | | | |_| |_| |");
- win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", "| ||_/|_| \\___/|_| \\_||_|_| |_|_|\\___)__ |");
- win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", "|_| (____/ ");
- win_save_print(console, '-', NULL, 0, THEME_SPLASH, "", "");
+ win_print(console, '-', NULL, 0, THEME_SPLASH, "", " ___ _ ");
+ win_print(console, '-', NULL, 0, THEME_SPLASH, "", " / __) (_)_ ");
+ win_print(console, '-', NULL, 0, THEME_SPLASH, "", " ____ ____ ___ | |__ ____ ____ _| |_ _ _ ");
+ win_print(console, '-', NULL, 0, THEME_SPLASH, "", "| _ \\ / ___) _ \\| __) _ | _ \\| | _) | | |");
+ win_print(console, '-', NULL, 0, THEME_SPLASH, "", "| | | | | | |_| | | ( ( | | | | | | |_| |_| |");
+ win_print(console, '-', NULL, 0, THEME_SPLASH, "", "| ||_/|_| \\___/|_| \\_||_|_| |_|_|\\___)__ |");
+ win_print(console, '-', NULL, 0, THEME_SPLASH, "", "|_| (____/ ");
+ win_print(console, '-', NULL, 0, THEME_SPLASH, "", "");
if (strcmp(PACKAGE_STATUS, "development") == 0) {
#ifdef HAVE_GIT_VERSION
- win_save_vprint(console, '-', NULL, 0, 0, "", "Version %sdev.%s.%s", PACKAGE_VERSION, PROF_GIT_BRANCH, PROF_GIT_REVISION);
+ win_vprint(console, '-', NULL, 0, 0, "", "Version %sdev.%s.%s", PACKAGE_VERSION, PROF_GIT_BRANCH, PROF_GIT_REVISION);
#else
- win_save_vprint(console, '-', NULL, 0, 0, "", "Version %sdev", PACKAGE_VERSION);
+ win_vprint(console, '-', NULL, 0, 0, "", "Version %sdev", PACKAGE_VERSION);
#endif
} else {
- win_save_vprint(console, '-', NULL, 0, 0, "", "Version %s", PACKAGE_VERSION);
+ win_vprint(console, '-', NULL, 0, 0, "", "Version %s", PACKAGE_VERSION);
}
}
@@ -1592,7 +1626,7 @@ _show_roster_contacts(GSList *list, gboolean show_groups)
PContact contact = curr->data;
GString *title = g_string_new(" ");
title = g_string_append(title, p_contact_barejid(contact));
- if (p_contact_name(contact) != NULL) {
+ if (p_contact_name(contact)) {
title = g_string_append(title, " (");
title = g_string_append(title, p_contact_name(contact));
title = g_string_append(title, ")");
@@ -1605,11 +1639,11 @@ _show_roster_contacts(GSList *list, gboolean show_groups)
} else {
presence_colour = theme_main_presence_attrs("offline");
}
- win_save_vprint(console, '-', NULL, NO_EOL, presence_colour, "", title->str);
+ win_vprint(console, '-', NULL, NO_EOL, presence_colour, "", title->str);
g_string_free(title, TRUE);
- win_save_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " - ");
+ win_print(console, '-', NULL, NO_DATE | NO_EOL, 0, "", " - ");
GString *sub = g_string_new("");
sub = g_string_append(sub, p_contact_subscription(contact));
if (p_contact_pending_out(contact)) {
@@ -1625,28 +1659,28 @@ _show_roster_contacts(GSList *list, gboolean show_groups)
}
if (show_groups) {
- win_save_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "%s", sub->str);
+ win_vprint(console, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", "%s", sub->str);
} else {
- win_save_vprint(console, '-', NULL, NO_DATE, presence_colour, "", "%s", sub->str);
+ win_vprint(console, '-', NULL, NO_DATE, presence_colour, "", "%s", sub->str);
}
g_string_free(sub, TRUE);
if (show_groups) {
GSList *groups = p_contact_groups(contact);
- if (groups != NULL) {
+ if (groups) {
GString *groups_str = g_string_new(" - ");
- while (groups != NULL) {
+ while (groups) {
g_string_append(groups_str, groups->data);
- if (g_slist_next(groups) != NULL) {
+ if (g_slist_next(groups)) {
g_string_append(groups_str, ", ");
}
groups = g_slist_next(groups);
}
- win_save_vprint(console, '-', NULL, NO_DATE, 0, "", "%s", groups_str->str);
+ win_vprint(console, '-', NULL, NO_DATE, 0, "", "%s", groups_str->str);
g_string_free(groups_str, TRUE);
} else {
- win_save_print(console, '-', NULL, NO_DATE, 0, "", " ");
+ win_print(console, '-', NULL, NO_DATE, 0, "", " ");
}
}
diff --git a/src/ui/core.c b/src/ui/core.c
index 85d5748a..e7059ef0 100644
--- a/src/ui/core.c
+++ b/src/ui/core.c
@@ -1,7 +1,7 @@
/*
* core.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -41,6 +41,9 @@
#include
#include
#include
+#include
+#include
+
#ifdef HAVE_LIBXSS
#include
#endif
@@ -71,19 +74,22 @@
#include "ui/window.h"
#include "ui/windows.h"
#include "xmpp/xmpp.h"
+#include "event/ui_events.h"
static char *win_title;
static int inp_size;
+static gboolean perform_resize = FALSE;
+
#ifdef HAVE_LIBXSS
static Display *display;
#endif
static GTimer *ui_idle_time;
-static void _win_handle_switch(const wint_t ch);
-static void _win_show_history(int win_index, const char * const contact);
+//static void _win_handle_switch(const wint_t ch);
+static void _win_show_history(ProfChatWin *chatwin, const char * const contact);
static void _ui_draw_term_title(void);
void
@@ -91,7 +97,9 @@ ui_init(void)
{
log_info("Initialising UI");
initscr();
- raw();
+ nonl();
+ cbreak();
+ noecho();
keypad(stdscr, TRUE);
if (prefs_get_boolean(PREF_MOUSE)) {
mousemask(ALL_MOUSE_EVENTS, NULL);
@@ -115,6 +123,12 @@ ui_init(void)
win_update_virtual(window);
}
+void
+ui_sigwinch_handler(int sig)
+{
+ perform_resize = TRUE;
+}
+
void
ui_update(void)
{
@@ -132,6 +146,13 @@ ui_update(void)
status_bar_update_virtual();
inp_put_back();
doupdate();
+
+ if (perform_resize) {
+ signal(SIGWINCH, SIG_IGN);
+ ui_resize();
+ perform_resize = FALSE;
+ signal(SIGWINCH, ui_sigwinch_handler);
+ }
}
void
@@ -147,13 +168,13 @@ 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) {
+ if (info && display) {
XScreenSaverQueryInfo(display, DefaultRootWindow(display), info);
unsigned long result = info->idle;
XFree(info);
return result;
}
- if (info != NULL) {
+ if (info) {
XFree(info);
}
// if no libxss or xss idle time failed, use profanity idle time
@@ -174,84 +195,66 @@ ui_close(void)
{
notifier_uninit();
wins_destroy();
+ inp_close();
endwin();
}
-char*
+char *
ui_readline(void)
{
- int key_type;
- wint_t ch;
-
- char *line = inp_read(&key_type, &ch);
- _win_handle_switch(ch);
-
- ProfWin *current = wins_get_current();
- win_handle_page(current, ch, key_type);
-
- if (ch == KEY_RESIZE) {
- ui_resize();
- }
-
- if (ch != ERR && key_type != ERR) {
- ui_reset_idle_time();
- ui_input_nonblocking(TRUE);
- } else {
- ui_input_nonblocking(FALSE);
- }
-
- return line;
+ return inp_readline();
}
void
-ui_inp_history_append(char *inp)
+ui_page_up(void)
{
- inp_history_append(inp);
+ ProfWin *current = wins_get_current();
+ win_page_up(current);
+}
+
+void
+ui_page_down(void)
+{
+ ProfWin *current = wins_get_current();
+ win_page_down(current);
+}
+
+void
+ui_subwin_page_up(void)
+{
+ ProfWin *current = wins_get_current();
+ win_sub_page_up(current);
+}
+
+void
+ui_subwin_page_down(void)
+{
+ ProfWin *current = wins_get_current();
+ win_sub_page_down(current);
}
void
ui_input_clear(void)
{
- inp_win_reset();
+ inp_win_clear();
}
void
ui_input_nonblocking(gboolean reset)
{
- static gint timeout = 0;
- static gint no_input_count = 0;
-
- if (! prefs_get_boolean(PREF_INPBLOCK_DYNAMIC)) {
- inp_non_block(prefs_get_inpblock());
- return;
- }
-
- if (reset) {
- timeout = 0;
- no_input_count = 0;
- }
-
- if (timeout < prefs_get_inpblock()) {
- no_input_count++;
-
- if (no_input_count % 10 == 0) {
- timeout += no_input_count;
-
- if (timeout > prefs_get_inpblock()) {
- timeout = prefs_get_inpblock();
- }
- }
- }
-
- inp_non_block(timeout);
+ inp_nonblocking(reset);
}
void
ui_resize(void)
{
- log_info("Resizing UI");
+ struct winsize w;
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
erase();
+ resizeterm(w.ws_row, w.ws_col);
refresh();
+
+ log_info("Resizing UI");
title_bar_resize();
wins_resize_all();
status_bar_resize();
@@ -279,13 +282,6 @@ ui_load_colours(void)
}
}
-gboolean
-ui_win_exists(int index)
-{
- ProfWin *window = wins_get_by_num(index);
- return (window != NULL);
-}
-
gboolean
ui_xmlconsole_exists(void)
{
@@ -305,13 +301,13 @@ ui_handle_stanza(const char * const msg)
ProfWin *window = (ProfWin*) xmlconsole;
if (g_str_has_prefix(msg, "SENT:")) {
- win_save_print(window, '-', NULL, 0, 0, "", "SENT:");
- win_save_print(window, '-', NULL, 0, THEME_ONLINE, "", &msg[6]);
- win_save_print(window, '-', NULL, 0, THEME_ONLINE, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "SENT:");
+ win_print(window, '-', NULL, 0, THEME_ONLINE, "", &msg[6]);
+ win_print(window, '-', NULL, 0, THEME_ONLINE, "", "");
} else if (g_str_has_prefix(msg, "RECV:")) {
- win_save_print(window, '-', NULL, 0, 0, "", "RECV:");
- win_save_print(window, '-', NULL, 0, THEME_AWAY, "", &msg[6]);
- win_save_print(window, '-', NULL, 0, THEME_AWAY, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "RECV:");
+ win_print(window, '-', NULL, 0, THEME_AWAY, "", &msg[6]);
+ win_print(window, '-', NULL, 0, THEME_AWAY, "", "");
}
}
}
@@ -323,6 +319,42 @@ ui_chat_win_exists(const char * const barejid)
return (chatwin != NULL);
}
+void
+ui_contact_online(char *barejid, Resource *resource, GDateTime *last_activity)
+{
+ char *show_console = prefs_get_string(PREF_STATUSES_CONSOLE);
+ char *show_chat_win = prefs_get_string(PREF_STATUSES_CHAT);
+ PContact contact = roster_get_contact(barejid);
+
+ // show nothing
+ if (g_strcmp0(p_contact_subscription(contact), "none") == 0) {
+ free(show_console);
+ free(show_chat_win);
+ return;
+ }
+
+ // show in console if "all"
+ if (g_strcmp0(show_console, "all") == 0) {
+ cons_show_contact_online(contact, resource, last_activity);
+
+ // show in console of "online" and presence online
+ } else if (g_strcmp0(show_console, "online") == 0 && resource->presence == RESOURCE_ONLINE) {
+ cons_show_contact_online(contact, resource, last_activity);
+ }
+
+ // show in chat win if "all"
+ if (g_strcmp0(show_chat_win, "all") == 0) {
+ ui_chat_win_contact_online(contact, resource, last_activity);
+
+ // show in char win if "online" and presence online
+ } else if (g_strcmp0(show_chat_win, "online") == 0 && resource->presence == RESOURCE_ONLINE) {
+ ui_chat_win_contact_online(contact, resource, last_activity);
+ }
+
+ free(show_console);
+ free(show_chat_win);
+}
+
void
ui_contact_typing(const char * const barejid, const char * const resource)
{
@@ -356,7 +388,7 @@ ui_contact_typing(const char * const barejid, const char * const resource)
if ( !is_current || (is_current && prefs_get_boolean(PREF_NOTIFY_TYPING_CURRENT)) ) {
PContact contact = roster_get_contact(barejid);
char const *display_usr = NULL;
- if (p_contact_name(contact) != NULL) {
+ if (p_contact_name(contact)) {
display_usr = p_contact_name(contact);
} else {
display_usr = barejid;
@@ -379,54 +411,43 @@ ui_get_current_chat(void)
return wins_get_current_chat();
}
+void
+ui_message_receipt(const char * const barejid, const char * const id)
+{
+ ProfChatWin *chatwin = wins_get_chat(barejid);
+ if (chatwin) {
+ ProfWin *win = (ProfWin*) chatwin;
+ win_mark_received(win, id);
+ }
+}
+
void
ui_incoming_msg(const char * const barejid, const char * const resource, const char * const message, GTimeVal *tv_stamp)
{
gboolean win_created = FALSE;
- GString *user = g_string_new("");
-
- PContact contact = roster_get_contact(barejid);
- if (contact != NULL) {
- if (p_contact_name(contact) != NULL) {
- g_string_append(user, p_contact_name(contact));
- } else {
- g_string_append(user, barejid);
- }
- } else {
- g_string_append(user, barejid);
- }
-
- if (resource && prefs_get_boolean(PREF_RESOURCE_MESSAGE)) {
- g_string_append(user, "/");
- g_string_append(user, resource);
- }
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin == NULL) {
ProfWin *window = wins_new_chat(barejid);
chatwin = (ProfChatWin*)window;
-#ifdef HAVE_LIBOTR
- if (otr_is_secure(barejid)) {
- chatwin->is_otr = TRUE;
- }
-#endif
win_created = TRUE;
}
ProfWin *window = (ProfWin*) chatwin;
-
int num = wins_get_num(window);
+ char *display_name = roster_get_msg_display_name(barejid, resource);
+
// currently viewing chat window with sender
if (wins_is_current(window)) {
- win_print_incoming_message(window, tv_stamp, user->str, message);
+ win_print_incoming_message(window, tv_stamp, display_name, message);
title_bar_set_typing(FALSE);
status_bar_active(num);
// not currently viewing chat window with sender
} else {
status_bar_new(num);
- cons_show_incoming_message(user->str, num);
+ cons_show_incoming_message(display_name, num);
if (prefs_get_boolean(PREF_FLASH)) {
flash();
@@ -434,23 +455,18 @@ ui_incoming_msg(const char * const barejid, const char * const resource, const c
chatwin->unread++;
if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) {
- _win_show_history(num, barejid);
+ _win_show_history(chatwin, barejid);
}
// show users status first, when receiving message via delayed delivery
- if ((tv_stamp != NULL) && (win_created)) {
+ if (tv_stamp && (win_created)) {
PContact pcontact = roster_get_contact(barejid);
- if (pcontact != NULL) {
+ if (pcontact) {
win_show_contact(window, pcontact);
}
}
- win_print_incoming_message(window, tv_stamp, user->str, message);
- }
-
- int ui_index = num;
- if (ui_index == 10) {
- ui_index = 0;
+ win_print_incoming_message(window, tv_stamp, display_name, message);
}
if (prefs_get_boolean(PREF_BEEP)) {
@@ -458,17 +474,10 @@ ui_incoming_msg(const char * const barejid, const char * const resource, const c
}
if (prefs_get_boolean(PREF_NOTIFY_MESSAGE)) {
- gboolean is_current = wins_is_current(window);
- if ( !is_current || (is_current && prefs_get_boolean(PREF_NOTIFY_MESSAGE_CURRENT)) ) {
- if (prefs_get_boolean(PREF_NOTIFY_MESSAGE_TEXT)) {
- notify_message(user->str, ui_index, message);
- } else {
- notify_message(user->str, ui_index, NULL);
- }
- }
+ notify_message(window, display_name, message);
}
- g_string_free(user, TRUE);
+ free(display_name);
}
void
@@ -494,24 +503,14 @@ ui_incoming_private_msg(const char * const fulljid, const char * const message,
// not currently viewing chat window with sender
} else {
+ privatewin->unread++;
status_bar_new(num);
cons_show_incoming_message(display_from, num);
+ win_print_incoming_message(window, tv_stamp, display_from, message);
if (prefs_get_boolean(PREF_FLASH)) {
flash();
}
-
- privatewin->unread++;
- if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) {
- _win_show_history(num, fulljid);
- }
-
- win_print_incoming_message(window, tv_stamp, display_from, message);
- }
-
- int ui_index = num;
- if (ui_index == 10) {
- ui_index = 0;
}
if (prefs_get_boolean(PREF_BEEP)) {
@@ -519,14 +518,7 @@ ui_incoming_private_msg(const char * const fulljid, const char * const message,
}
if (prefs_get_boolean(PREF_NOTIFY_MESSAGE)) {
- gboolean is_current = wins_is_current(window);
- if ( !is_current || (is_current && prefs_get_boolean(PREF_NOTIFY_MESSAGE_CURRENT)) ) {
- if (prefs_get_boolean(PREF_NOTIFY_MESSAGE_TEXT)) {
- notify_message(display_from, ui_index, message);
- } else {
- notify_message(display_from, ui_index, NULL);
- }
- }
+ notify_message(window, display_from, message);
}
free(display_from);
@@ -535,7 +527,7 @@ ui_incoming_private_msg(const char * const fulljid, const char * const message,
void
ui_roster_add(const char * const barejid, const char * const name)
{
- if (name != NULL) {
+ if (name) {
cons_show("Roster item added: %s (%s)", barejid, name);
} else {
cons_show("Roster item added: %s", barejid);
@@ -582,7 +574,7 @@ void
ui_auto_away(void)
{
char *pref_autoaway_message = prefs_get_string(PREF_AUTOAWAY_MESSAGE);
- if (pref_autoaway_message != NULL) {
+ if (pref_autoaway_message) {
int pri =
accounts_get_priority_for_presence_type(jabber_get_account_name(),
RESOURCE_AWAY);
@@ -622,7 +614,12 @@ ui_handle_login_account_success(ProfAccount *account)
contact_presence_t contact_presence = contact_presence_from_resource_presence(resource_presence);
cons_show_login_success(account);
title_bar_set_presence(contact_presence);
- status_bar_print_message(account->jid);
+
+ GString *fulljid = g_string_new(account->jid);
+ g_string_append(fulljid, "/");
+ g_string_append(fulljid, account->resource);
+ status_bar_print_message(fulljid->str);
+ g_string_free(fulljid, TRUE);
status_bar_update_virtual();
}
@@ -633,7 +630,7 @@ ui_update_presence(const resource_presence_t resource_presence,
contact_presence_t contact_presence = contact_presence_from_resource_presence(resource_presence);
title_bar_set_presence(contact_presence);
gint priority = accounts_get_priority_for_presence_type(jabber_get_account_name(), resource_presence);
- if (message != NULL) {
+ if (message) {
cons_show("Status set to %s (priority %d), \"%s\".", show, priority, message);
} else {
cons_show("Status set to %s (priority %d).", show, priority);
@@ -647,7 +644,7 @@ ui_handle_recipient_not_found(const char * const recipient, const char * const e
ProfMucWin *mucwin = wins_get_muc(recipient);
if (mucwin) {
cons_show_error("Room %s not found: %s", recipient, err_msg);
- win_save_vprint((ProfWin*) mucwin, '!', NULL, 0, THEME_ERROR, "", "Room %s not found: %s", recipient, err_msg);
+ win_vprint((ProfWin*) mucwin, '!', NULL, 0, THEME_ERROR, "", "Room %s not found: %s", recipient, err_msg);
return;
}
}
@@ -660,19 +657,19 @@ ui_handle_recipient_error(const char * const recipient, const char * const err_m
ProfChatWin *chatwin = wins_get_chat(recipient);
if (chatwin) {
- win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, THEME_ERROR, "", "Error from %s: %s", recipient, err_msg);
+ win_vprint((ProfWin*)chatwin, '!', NULL, 0, THEME_ERROR, "", "Error from %s: %s", recipient, err_msg);
return;
}
ProfMucWin *mucwin = wins_get_muc(recipient);
if (mucwin) {
- win_save_vprint((ProfWin*)mucwin, '!', NULL, 0, THEME_ERROR, "", "Error from %s: %s", recipient, err_msg);
+ win_vprint((ProfWin*)mucwin, '!', NULL, 0, THEME_ERROR, "", "Error from %s: %s", recipient, err_msg);
return;
}
ProfPrivateWin *privatewin = wins_get_private(recipient);
if (privatewin) {
- win_save_vprint((ProfWin*)privatewin, '!', NULL, 0, THEME_ERROR, "", "Error from %s: %s", recipient, err_msg);
+ win_vprint((ProfWin*)privatewin, '!', NULL, 0, THEME_ERROR, "", "Error from %s: %s", recipient, err_msg);
return;
}
}
@@ -691,7 +688,7 @@ ui_handle_error(const char * const err_msg)
void
ui_invalid_command_usage(const char * const usage, void (*setting_func)(void))
{
- if (setting_func != NULL) {
+ if (setting_func) {
cons_show("");
(*setting_func)();
cons_show("Usage: %s", usage);
@@ -729,7 +726,7 @@ ui_close_connected_win(int index)
ProfChatWin *chatwin = (ProfChatWin*) window;
assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
#ifdef HAVE_LIBOTR
- if (chatwin->is_otr) {
+ if (chatwin->enc_mode == PROF_ENC_OTR) {
otr_end_session(chatwin->barejid);
}
#endif
@@ -748,7 +745,7 @@ ui_close_all_wins(void)
GList *win_nums = wins_get_nums();
GList *curr = win_nums;
- while (curr != NULL) {
+ while (curr) {
int num = GPOINTER_TO_INT(curr->data);
if ((num != 1) && (!ui_win_has_unsaved_form(num))) {
if (conn_status == JABBER_CONNECTED) {
@@ -775,7 +772,7 @@ ui_close_read_wins(void)
GList *win_nums = wins_get_nums();
GList *curr = win_nums;
- while (curr != NULL) {
+ while (curr) {
int num = GPOINTER_TO_INT(curr->data);
if ((num != 1) && (ui_win_unread(num) == 0) && (!ui_win_has_unsaved_form(num))) {
if (conn_status == JABBER_CONNECTED) {
@@ -799,7 +796,7 @@ ui_redraw_all_room_rosters(void)
GList *win_nums = wins_get_nums();
GList *curr = win_nums;
- while (curr != NULL) {
+ while (curr) {
int num = GPOINTER_TO_INT(curr->data);
ProfWin *window = wins_get_by_num(num);
if (window->type == WIN_MUC && win_has_active_subwin(window)) {
@@ -820,7 +817,7 @@ ui_hide_all_room_rosters(void)
GList *win_nums = wins_get_nums();
GList *curr = win_nums;
- while (curr != NULL) {
+ while (curr) {
int num = GPOINTER_TO_INT(curr->data);
ProfWin *window = wins_get_by_num(num);
if (window->type == WIN_MUC && win_has_active_subwin(window)) {
@@ -841,7 +838,7 @@ ui_show_all_room_rosters(void)
GList *win_nums = wins_get_nums();
GList *curr = win_nums;
- while (curr != NULL) {
+ while (curr) {
int num = GPOINTER_TO_INT(curr->data);
ProfWin *window = wins_get_by_num(num);
if (window->type == WIN_MUC && !win_has_active_subwin(window)) {
@@ -870,95 +867,32 @@ ui_win_has_unsaved_form(int num)
}
}
-gboolean
-ui_switch_win(const int i)
-{
- if (ui_win_exists(i)) {
- ProfWin *old_current = wins_get_current();
- if (old_current->type == WIN_MUC_CONFIG) {
- ProfMucConfWin *confwin = (ProfMucConfWin*)old_current;
- cmd_autocomplete_remove_form_fields(confwin->form);
- }
-
- ProfWin *new_current = wins_get_by_num(i);
- if (new_current->type == WIN_MUC_CONFIG) {
- ProfMucConfWin *confwin = (ProfMucConfWin*)new_current;
- cmd_autocomplete_add_form_fields(confwin->form);
- }
-
- wins_set_current_by_num(i);
-
- if (i == 1) {
- title_bar_console();
- status_bar_current(1);
- status_bar_active(1);
- } else {
- title_bar_switch();
- status_bar_current(i);
- status_bar_active(i);
- }
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
void
-ui_previous_win(void)
+ui_switch_win(ProfWin *window)
{
+ assert(window != NULL);
+
ProfWin *old_current = wins_get_current();
if (old_current->type == WIN_MUC_CONFIG) {
ProfMucConfWin *confwin = (ProfMucConfWin*)old_current;
cmd_autocomplete_remove_form_fields(confwin->form);
}
- ProfWin *new_current = wins_get_previous();
- if (new_current->type == WIN_MUC_CONFIG) {
- ProfMucConfWin *confwin = (ProfMucConfWin*)new_current;
+ if (window->type == WIN_MUC_CONFIG) {
+ ProfMucConfWin *confwin = (ProfMucConfWin*)window;
cmd_autocomplete_add_form_fields(confwin->form);
}
- int i = wins_get_num(new_current);
+ int i = wins_get_num(window);
wins_set_current_by_num(i);
if (i == 1) {
title_bar_console();
- status_bar_current(1);
- status_bar_active(1);
} else {
title_bar_switch();
- status_bar_current(i);
- status_bar_active(i);
- }
-}
-
-void
-ui_next_win(void)
-{
- ProfWin *old_current = wins_get_current();
- if (old_current->type == WIN_MUC_CONFIG) {
- ProfMucConfWin *confwin = (ProfMucConfWin*)old_current;
- cmd_autocomplete_remove_form_fields(confwin->form);
- }
-
- ProfWin *new_current = wins_get_next();
- if (new_current->type == WIN_MUC_CONFIG) {
- ProfMucConfWin *confwin = (ProfMucConfWin*)new_current;
- cmd_autocomplete_add_form_fields(confwin->form);
- }
-
- int i = wins_get_num(new_current);
- wins_set_current_by_num(i);
-
- if (i == 1) {
- title_bar_console();
- status_bar_current(1);
- status_bar_active(1);
- } else {
- title_bar_switch();
- status_bar_current(i);
- status_bar_active(i);
}
+ status_bar_current(i);
+ status_bar_active(i);
}
void
@@ -974,12 +908,12 @@ ui_gone_secure(const char * const barejid, gboolean trusted)
chatwin = (ProfChatWin*)window;
}
- chatwin->is_otr = TRUE;
+ chatwin->enc_mode = PROF_ENC_OTR;
chatwin->is_trusted = trusted;
if (trusted) {
- win_save_print(window, '!', NULL, 0, THEME_OTR_STARTED_TRUSTED, "", "OTR session started (trusted).");
+ win_print(window, '!', NULL, 0, THEME_OTR_STARTED_TRUSTED, "", "OTR session started (trusted).");
} else {
- win_save_print(window, '!', NULL, 0, THEME_OTR_STARTED_UNTRUSTED, "", "OTR session started (untrusted).");
+ win_print(window, '!', NULL, 0, THEME_OTR_STARTED_UNTRUSTED, "", "OTR session started (untrusted).");
}
if (wins_is_current(window)) {
@@ -1002,11 +936,11 @@ ui_gone_insecure(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- chatwin->is_otr = FALSE;
+ chatwin->enc_mode = PROF_ENC_NONE;
chatwin->is_trusted = FALSE;
ProfWin *window = (ProfWin*)chatwin;
- win_save_print(window, '!', NULL, 0, THEME_OTR_ENDED, "", "OTR session ended.");
+ win_print(window, '!', NULL, 0, THEME_OTR_ENDED, "", "OTR session ended.");
if (wins_is_current(window)) {
title_bar_switch();
}
@@ -1018,7 +952,7 @@ ui_smp_recipient_initiated(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s wants to authenticate your identity, use '/otr secret '.", barejid);
+ win_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s wants to authenticate your identity, use '/otr secret '.", barejid);
}
}
@@ -1027,9 +961,9 @@ ui_smp_recipient_initiated_q(const char * const barejid, const char *question)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s wants to authenticate your identity with the following question:", barejid);
- win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", " %s", question);
- win_save_print((ProfWin*)chatwin, '!', NULL, 0, 0, "", "use '/otr answer '.");
+ win_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s wants to authenticate your identity with the following question:", barejid);
+ win_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", " %s", question);
+ win_print((ProfWin*)chatwin, '!', NULL, 0, 0, "", "use '/otr answer '.");
}
}
@@ -1038,7 +972,7 @@ ui_smp_unsuccessful_sender(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authentication failed, the secret you entered does not match the secret entered by %s.", barejid);
+ win_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authentication failed, the secret you entered does not match the secret entered by %s.", barejid);
}
}
@@ -1047,7 +981,7 @@ ui_smp_unsuccessful_receiver(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authentication failed, the secret entered by %s does not match yours.", barejid);
+ win_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authentication failed, the secret entered by %s does not match yours.", barejid);
}
}
@@ -1056,7 +990,7 @@ ui_smp_aborted(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- win_save_print((ProfWin*)chatwin, '!', NULL, 0, 0, "", "SMP session aborted.");
+ win_print((ProfWin*)chatwin, '!', NULL, 0, 0, "", "SMP session aborted.");
}
}
@@ -1065,7 +999,7 @@ ui_smp_successful(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- win_save_print((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authentication successful.");
+ win_print((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authentication successful.");
}
}
@@ -1074,7 +1008,7 @@ ui_smp_answer_success(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s successfully authenticated you.", barejid);
+ win_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s successfully authenticated you.", barejid);
}
}
@@ -1083,7 +1017,7 @@ ui_smp_answer_failure(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s failed to authenticate you.", barejid);
+ win_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "%s failed to authenticate you.", barejid);
}
}
@@ -1092,7 +1026,7 @@ ui_otr_authenticating(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authenticating %s...", barejid);
+ win_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Authenticating %s...", barejid);
}
}
@@ -1101,7 +1035,18 @@ ui_otr_authetication_waiting(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Awaiting authentication from %s...", barejid);
+ win_vprint((ProfWin*)chatwin, '!', NULL, 0, 0, "", "Awaiting authentication from %s...", barejid);
+ }
+}
+
+void
+ui_handle_otr_error(const char * const barejid, const char * const message)
+{
+ ProfChatWin *chatwin = wins_get_chat(barejid);
+ if (chatwin) {
+ win_print((ProfWin*)chatwin, '!', NULL, 0, THEME_ERROR, "", message);
+ } else {
+ cons_show_error("%s - %s", barejid, message);
}
}
@@ -1110,11 +1055,11 @@ ui_trust(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- chatwin->is_otr = TRUE;
+ chatwin->enc_mode = PROF_ENC_OTR;
chatwin->is_trusted = TRUE;
ProfWin *window = (ProfWin*)chatwin;
- win_save_print(window, '!', NULL, 0, THEME_OTR_TRUSTED, "", "OTR session trusted.");
+ win_print(window, '!', NULL, 0, THEME_OTR_TRUSTED, "", "OTR session trusted.");
if (wins_is_current(window)) {
title_bar_switch();
}
@@ -1126,11 +1071,11 @@ ui_untrust(const char * const barejid)
{
ProfChatWin *chatwin = wins_get_chat(barejid);
if (chatwin) {
- chatwin->is_otr = TRUE;
+ chatwin->enc_mode = PROF_ENC_OTR;
chatwin->is_trusted = FALSE;
ProfWin *window = (ProfWin*)chatwin;
- win_save_print(window, '!', NULL, 0, THEME_OTR_UNTRUSTED, "", "OTR session untrusted.");
+ win_print(window, '!', NULL, 0, THEME_OTR_UNTRUSTED, "", "OTR session untrusted.");
if (wins_is_current(window)) {
title_bar_switch();
}
@@ -1179,12 +1124,12 @@ ui_prune_wins(void)
gboolean pruned = FALSE;
GSList *wins = wins_get_prune_wins();
- if (wins != NULL) {
+ if (wins) {
pruned = TRUE;
}
GSList *curr = wins;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_CHAT) {
if (conn_status == JABBER_CONNECTED) {
@@ -1199,7 +1144,7 @@ ui_prune_wins(void)
curr = g_slist_next(curr);
}
- if (wins != NULL) {
+ if (wins) {
g_slist_free(wins);
}
@@ -1231,18 +1176,12 @@ ui_current_win_is_otr(void)
if (current->type == WIN_CHAT) {
ProfChatWin *chatwin = (ProfChatWin*)current;
assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
- return chatwin->is_otr;
+ return chatwin->enc_mode == PROF_ENC_OTR;
} else {
return FALSE;
}
}
-int
-ui_current_win_index(void)
-{
- return wins_get_current_num();
-}
-
win_type_t
ui_win_type(int index)
{
@@ -1258,7 +1197,7 @@ ui_current_print_line(const char * const msg, ...)
va_start(arg, msg);
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, msg, arg);
- win_save_println(window, fmt_msg->str);
+ win_println(window, fmt_msg->str);
va_end(arg);
g_string_free(fmt_msg, TRUE);
}
@@ -1271,16 +1210,22 @@ ui_current_print_formatted_line(const char show_char, int attrs, const char * co
va_start(arg, msg);
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, msg, arg);
- win_save_print(current, show_char, NULL, 0, attrs, "", fmt_msg->str);
+ win_print(current, show_char, NULL, 0, attrs, "", fmt_msg->str);
va_end(arg);
g_string_free(fmt_msg, TRUE);
}
+void
+ui_win_error_line(ProfWin *window, const char * const msg)
+{
+ win_print(window, '-', NULL, 0, THEME_ERROR, "", msg);
+}
+
void
ui_current_error_line(const char * const msg)
{
ProfWin *current = wins_get_current();
- win_save_print(current, '-', NULL, 0, THEME_ERROR, "", msg);
+ win_print(current, '-', NULL, 0, THEME_ERROR, "", msg);
}
void
@@ -1293,7 +1238,7 @@ ui_print_system_msg_from_recipient(const char * const barejid, const char *messa
if (window == NULL) {
int num = 0;
window = wins_new_chat(barejid);
- if (window != NULL) {
+ if (window) {
num = wins_get_num(window);
status_bar_active(num);
} else {
@@ -1303,7 +1248,7 @@ ui_print_system_msg_from_recipient(const char * const barejid, const char *messa
}
}
- win_save_vprint(window, '-', NULL, 0, 0, "", "*%s %s", barejid, message);
+ win_vprint(window, '-', NULL, 0, 0, "", "*%s %s", barejid, message);
}
void
@@ -1325,8 +1270,8 @@ ui_recipient_gone(const char * const barejid, const char * const resource)
if (show_message) {
const char * display_usr = NULL;
PContact contact = roster_get_contact(barejid);
- if (contact != NULL) {
- if (p_contact_name(contact) != NULL) {
+ if (contact) {
+ if (p_contact_name(contact)) {
display_usr = p_contact_name(contact);
} else {
display_usr = barejid;
@@ -1335,175 +1280,128 @@ ui_recipient_gone(const char * const barejid, const char * const resource)
display_usr = barejid;
}
- win_save_vprint((ProfWin*)chatwin, '!', NULL, 0, THEME_GONE, "", "<- %s has left the conversation.", display_usr);
+ win_vprint((ProfWin*)chatwin, '!', NULL, 0, THEME_GONE, "", "<- %s has left the conversation.", display_usr);
}
}
}
-void
+ProfPrivateWin*
ui_new_private_win(const char * const fulljid)
{
- ProfWin *window = (ProfWin*)wins_get_private(fulljid);
- int num = 0;
-
- // create new window
- if (window == NULL) {
- window = wins_new_private(fulljid);
- num = wins_get_num(window);
- } else {
- num = wins_get_num(window);
- }
-
- ui_switch_win(num);
-}
-
-void
-ui_new_chat_win(const char * const barejid)
-{
- ProfWin *window = (ProfWin*)wins_get_chat(barejid);
- int num = 0;
-
- // create new window
- if (window == NULL) {
- window = wins_new_chat(barejid);
-
- num = wins_get_num(window);
-
- if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) {
- _win_show_history(num, barejid);
- }
-
- // if the contact is offline, show a message
- PContact contact = roster_get_contact(barejid);
- 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);
- win_show_status_string(window, barejid, show, status, NULL, "--", "offline");
- }
- }
- } else {
- num = wins_get_num(window);
- }
-
- ui_switch_win(num);
+ ProfWin *window = wins_new_private(fulljid);
+ return (ProfPrivateWin*)window;
}
void
ui_create_xmlconsole_win(void)
{
ProfWin *window = wins_new_xmlconsole();
- int num = wins_get_num(window);
- ui_switch_win(num);
+ ui_ev_focus_win(window);
}
void
ui_open_xmlconsole_win(void)
{
ProfXMLWin *xmlwin = wins_get_xmlconsole();
- if (xmlwin != NULL) {
- int num = wins_get_num((ProfWin*)xmlwin);
- ui_switch_win(num);
+ if (xmlwin) {
+ ui_ev_focus_win((ProfWin*)xmlwin);
+ }
+}
+
+ProfChatWin*
+ui_new_chat_win(const char * const barejid)
+{
+ ProfWin *window = wins_new_chat(barejid);
+ ProfChatWin *chatwin = (ProfChatWin *)window;
+
+#ifdef HAVE_LIBOTR
+ if (otr_is_secure(barejid)) {
+ chatwin->enc_mode = PROF_ENC_OTR;
+ }
+#endif
+
+ if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) {
+ _win_show_history(chatwin, barejid);
+ }
+
+ // if the contact is offline, show a message
+ PContact contact = roster_get_contact(barejid);
+ if (contact) {
+ if (strcmp(p_contact_presence(contact), "offline") == 0) {
+ const char * const show = p_contact_presence(contact);
+ const char * const status = p_contact_status(contact);
+ win_show_status_string(window, barejid, show, status, NULL, "--", "offline");
+ }
+ }
+
+ return chatwin;
+}
+
+void
+ui_outgoing_chat_msg(ProfChatWin *chatwin, const char * const message, char *id)
+{
+ if (prefs_get_boolean(PREF_RECEIPTS_REQUEST) && id) {
+ win_print_with_receipt((ProfWin*)chatwin, '-', NULL, 0, THEME_TEXT_ME, "me", message, id);
+ } else {
+ win_print((ProfWin*)chatwin, '-', NULL, 0, THEME_TEXT_ME, "me", message);
}
}
void
-ui_outgoing_chat_msg(const char * const from, const char * const barejid,
- const char * const message)
+ui_outgoing_chat_msg_carbon(const char * const barejid, const char * const message)
{
- PContact contact = roster_get_contact(barejid);
- ProfWin *window = (ProfWin*)wins_get_chat(barejid);
- int num = 0;
+ ProfChatWin *chatwin = wins_get_chat(barejid);
// create new window
- if (window == NULL) {
- window = wins_new_chat(barejid);
-#ifdef HAVE_LIBOTR
- ProfChatWin *chatwin = (ProfChatWin*)window;
- if (otr_is_secure(barejid)) {
- chatwin->is_otr = TRUE;
- }
-#endif
- num = wins_get_num(window);
-
- if (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) {
- _win_show_history(num, barejid);
- }
-
- if (contact != NULL) {
- if (strcmp(p_contact_presence(contact), "offline") == 0) {
- const char *show = p_contact_presence(contact);
- const char *status = p_contact_status(contact);
- win_show_status_string(window, barejid, show, status, NULL, "--", "offline");
- }
- }
-
- // use existing window
- } else {
- num = wins_get_num(window);
+ if (!chatwin) {
+ chatwin = ui_new_chat_win(barejid);
}
- ProfChatWin *chatwin = (ProfChatWin*)window;
+
chat_state_active(chatwin->state);
- win_save_print(window, '-', NULL, 0, THEME_TEXT_ME, from, message);
- ui_switch_win(num);
+ win_print((ProfWin*)chatwin, '-', NULL, 0, THEME_TEXT_ME, "me", message);
+
+ int num = wins_get_num((ProfWin*)chatwin);
+ status_bar_active(num);
}
void
-ui_outgoing_private_msg(const char * const from, const char * const fulljid,
- const char * const message)
+ui_outgoing_private_msg(ProfPrivateWin *privwin, const char * const message)
{
- ProfWin *window = (ProfWin*)wins_get_private(fulljid);
- int num = 0;
-
- // create new window
- if (window == NULL) {
- window = wins_new_private(fulljid);
- num = wins_get_num(window);
-
- // use existing window
- } else {
- num = wins_get_num(window);
- }
-
- win_save_print(window, '-', NULL, 0, THEME_TEXT_ME, from, message);
- ui_switch_win(num);
+ win_print((ProfWin*)privwin, '-', NULL, 0, THEME_TEXT_ME, "me", message);
}
void
ui_room_join(const char * const roomjid, gboolean focus)
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
- int num = 0;
-
- // create new window
- if (window == NULL) {
+ if (!window) {
window = wins_new_muc(roomjid);
}
char *nick = muc_nick(roomjid);
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "-> You have joined the room as %s", nick);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "-> You have joined the room as %s", nick);
if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
char *role = muc_role_str(roomjid);
char *affiliation = muc_affiliation_str(roomjid);
if (role) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", role: %s", role);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", role: %s", role);
}
if (affiliation) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", affiliation: %s", affiliation);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", affiliation: %s", affiliation);
}
}
- win_save_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
+ win_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
- num = wins_get_num(window);
if (focus) {
- ui_switch_win(num);
+ ui_ev_focus_win(window);
} else {
+ int num = wins_get_num(window);
status_bar_active(num);
ProfWin *console = wins_get_console();
char *nick = muc_nick(roomjid);
- win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "-> Autojoined %s as %s (%d).", roomjid, nick, num);
+ win_vprint(console, '!', NULL, 0, THEME_TYPING, "", "-> Autojoined %s as %s (%d).", roomjid, nick, num);
}
}
@@ -1511,9 +1409,7 @@ void
ui_switch_to_room(const char * const roomjid)
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
- int num = wins_get_num(window);
- num = wins_get_num(window);
- ui_switch_win(num);
+ ui_ev_focus_win(window);
}
void
@@ -1521,14 +1417,14 @@ ui_room_role_change(const char * const roomjid, const char * const role, const c
const char * const reason)
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Your role has been changed to: %s", role);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Your role has been changed to: %s", role);
if (actor) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
}
if (reason) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
}
- win_save_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
+ win_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
}
void
@@ -1536,14 +1432,14 @@ ui_room_affiliation_change(const char * const roomjid, const char * const affili
const char * const reason)
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Your affiliation has been changed to: %s", affiliation);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Your affiliation has been changed to: %s", affiliation);
if (actor) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
}
if (reason) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
}
- win_save_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
+ win_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
}
void
@@ -1551,14 +1447,14 @@ ui_room_role_and_affiliation_change(const char * const roomjid, const char * con
const char * const actor, const char * const reason)
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Your role and affiliation have been changed, role: %s, affiliation: %s", role, affiliation);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Your role and affiliation have been changed, role: %s, affiliation: %s", role, affiliation);
if (actor) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
}
if (reason) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
}
- win_save_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
+ win_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
}
@@ -1567,14 +1463,14 @@ ui_room_occupant_role_change(const char * const roomjid, const char * const nick
const char * const actor, const char * const reason)
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%s's role has been changed to: %s", nick, role);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%s's role has been changed to: %s", nick, role);
if (actor) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
}
if (reason) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
}
- win_save_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
+ win_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
}
void
@@ -1582,14 +1478,14 @@ ui_room_occupant_affiliation_change(const char * const roomjid, const char * con
const char * const actor, const char * const reason)
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%s's affiliation has been changed to: %s", nick, affiliation);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%s's affiliation has been changed to: %s", nick, affiliation);
if (actor) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
}
if (reason) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
}
- win_save_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
+ win_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
}
void
@@ -1597,14 +1493,14 @@ ui_room_occupant_role_and_affiliation_change(const char * const roomjid, const c
const char * const affiliation, const char * const actor, const char * const reason)
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%s's role and affiliation have been changed, role: %s, affiliation: %s", nick, role, affiliation);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%s's role and affiliation have been changed, role: %s, affiliation: %s", nick, role, affiliation);
if (actor) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", by: %s", actor);
}
if (reason) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ROOMINFO, "", ", reason: %s", reason);
}
- win_save_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
+ win_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
}
void
@@ -1612,8 +1508,8 @@ ui_handle_room_info_error(const char * const roomjid, const char * const error)
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
if (window) {
- win_save_vprint(window, '!', NULL, 0, 0, "", "Room info request failed: %s", error);
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_vprint(window, '!', NULL, 0, 0, "", "Room info request failed: %s", error);
+ win_print(window, '-', NULL, 0, 0, "", "");
}
}
@@ -1622,38 +1518,38 @@ ui_show_room_disco_info(const char * const roomjid, GSList *identities, GSList *
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
if (window) {
- if (((identities != NULL) && (g_slist_length(identities) > 0)) ||
- ((features != NULL) && (g_slist_length(features) > 0))) {
- if (identities != NULL) {
- win_save_print(window, '!', NULL, 0, 0, "", "Identities:");
+ if ((identities && (g_slist_length(identities) > 0)) ||
+ (features && (g_slist_length(features) > 0))) {
+ if (identities) {
+ win_print(window, '!', NULL, 0, 0, "", "Identities:");
}
- while (identities != NULL) {
+ while (identities) {
DiscoIdentity *identity = identities->data; // anme trpe, cat
GString *identity_str = g_string_new(" ");
- if (identity->name != NULL) {
+ if (identity->name) {
identity_str = g_string_append(identity_str, identity->name);
identity_str = g_string_append(identity_str, " ");
}
- if (identity->type != NULL) {
+ if (identity->type) {
identity_str = g_string_append(identity_str, identity->type);
identity_str = g_string_append(identity_str, " ");
}
- if (identity->category != NULL) {
+ if (identity->category) {
identity_str = g_string_append(identity_str, identity->category);
}
- win_save_print(window, '!', NULL, 0, 0, "", identity_str->str);
+ win_print(window, '!', NULL, 0, 0, "", identity_str->str);
g_string_free(identity_str, TRUE);
identities = g_slist_next(identities);
}
- if (features != NULL) {
- win_save_print(window, '!', NULL, 0, 0, "", "Features:");
+ if (features) {
+ win_print(window, '!', NULL, 0, 0, "", "Features:");
}
- while (features != NULL) {
- win_save_vprint(window, '!', NULL, 0, 0, "", " %s", features->data);
+ while (features) {
+ win_vprint(window, '!', NULL, 0, 0, "", " %s", features->data);
features = g_slist_next(features);
}
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "");
}
}
}
@@ -1667,32 +1563,32 @@ ui_room_roster(const char * const roomjid, GList *roster, const char * const pre
} else {
if ((roster == NULL) || (g_list_length(roster) == 0)) {
if (presence == NULL) {
- win_save_print(window, '!', NULL, 0, THEME_ROOMINFO, "", "Room is empty.");
+ win_print(window, '!', NULL, 0, THEME_ROOMINFO, "", "Room is empty.");
} else {
- win_save_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "", "No occupants %s.", presence);
+ win_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "", "No occupants %s.", presence);
}
} else {
int length = g_list_length(roster);
if (presence == NULL) {
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%d occupants: ", length);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%d occupants: ", length);
} else {
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%d %s: ", length, presence);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "%d %s: ", length, presence);
}
- while (roster != NULL) {
+ while (roster) {
Occupant *occupant = roster->data;
const char *presence_str = string_from_resource_presence(occupant->presence);
theme_item_t presence_colour = theme_main_presence_attrs(presence_str);
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, presence_colour, "", "%s", occupant->nick);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, presence_colour, "", "%s", occupant->nick);
- if (roster->next != NULL) {
- win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", ");
+ if (roster->next) {
+ win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", ");
}
roster = g_list_next(roster);
}
- win_save_print(window, '!', NULL, NO_DATE, THEME_ONLINE, "", "");
+ win_print(window, '!', NULL, NO_DATE, THEME_ONLINE, "", "");
}
}
@@ -1711,7 +1607,7 @@ ui_room_member_offline(const char * const roomjid, const char * const nick)
if (window == NULL) {
log_error("Received offline presence for room participant %s, but no window open for %s.", nick, roomjid);
} else {
- win_save_vprint(window, '!', NULL, 0, THEME_OFFLINE, "", "<- %s has left the room.", nick);
+ win_vprint(window, '!', NULL, 0, THEME_OFFLINE, "", "<- %s has left the room.", nick);
}
}
@@ -1734,7 +1630,7 @@ ui_room_member_kicked(const char * const roomjid, const char * const nick, const
g_string_append(message, reason);
}
- win_save_vprint(window, '!', NULL, 0, THEME_OFFLINE, "", "<- %s", message->str);
+ win_vprint(window, '!', NULL, 0, THEME_OFFLINE, "", "<- %s", message->str);
g_string_free(message, TRUE);
}
}
@@ -1758,7 +1654,7 @@ ui_room_member_banned(const char * const roomjid, const char * const nick, const
g_string_append(message, reason);
}
- win_save_vprint(window, '!', NULL, 0, THEME_OFFLINE, "", "<- %s", message->str);
+ win_vprint(window, '!', NULL, 0, THEME_OFFLINE, "", "<- %s", message->str);
g_string_free(message, TRUE);
}
}
@@ -1771,16 +1667,16 @@ ui_room_member_online(const char * const roomjid, const char * const nick, const
if (window == NULL) {
log_error("Received online presence for room participant %s, but no window open for %s.", nick, roomjid);
} else {
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ONLINE, "", "-> %s has joined the room", nick);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ONLINE, "", "-> %s has joined the room", nick);
if (prefs_get_boolean(PREF_MUC_PRIVILEGES)) {
if (role) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", ", role: %s", role);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", ", role: %s", role);
}
if (affiliation) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", ", affiliation: %s", affiliation);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", ", affiliation: %s", affiliation);
}
}
- win_save_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
+ win_print(window, '!', NULL, NO_DATE, THEME_ROOMINFO, "", "");
}
}
@@ -1804,7 +1700,7 @@ ui_room_member_nick_change(const char * const roomjid,
if (window == NULL) {
log_error("Received nick change for room participant %s, but no window open for %s.", old_nick, roomjid);
} else {
- win_save_vprint(window, '!', NULL, 0, THEME_THEM, "", "** %s is now known as %s", old_nick, nick);
+ win_vprint(window, '!', NULL, 0, THEME_THEM, "", "** %s is now known as %s", old_nick, nick);
}
}
@@ -1815,7 +1711,7 @@ ui_room_nick_change(const char * const roomjid, const char * const nick)
if (window == NULL) {
log_error("Received self nick change %s, but no window open for %s.", nick, roomjid);
} else {
- win_save_vprint(window, '!', NULL, 0, THEME_ME, "", "** You are now known as %s", nick);
+ win_vprint(window, '!', NULL, 0, THEME_ME, "", "** You are now known as %s", nick);
}
}
@@ -1840,7 +1736,7 @@ ui_room_history(const char * const roomjid, const char * const nick,
g_string_append(line, message);
}
- win_save_print(window, '-', &tv_stamp, NO_COLOUR_DATE, 0, "", line->str);
+ win_print(window, '-', &tv_stamp, NO_COLOUR_DATE, 0, "", line->str);
g_string_free(line, TRUE);
}
}
@@ -1852,77 +1748,79 @@ ui_room_message(const char * const roomjid, const char * const nick,
ProfMucWin *mucwin = wins_get_muc(roomjid);
if (mucwin == NULL) {
log_error("Room message received from %s, but no window open for %s", nick, roomjid);
+ return;
+ }
+
+ ProfWin *window = (ProfWin*) mucwin;
+ int num = wins_get_num(window);
+ char *my_nick = muc_nick(roomjid);
+
+ if (g_strcmp0(nick, my_nick) != 0) {
+ if (g_strrstr(message, my_nick)) {
+ win_print(window, '-', NULL, NO_ME, THEME_ROOMMENTION, nick, message);
+ } else {
+ win_print(window, '-', NULL, NO_ME, THEME_TEXT_THEM, nick, message);
+ }
} else {
- ProfWin *window = (ProfWin*) mucwin;
- int num = wins_get_num(window);
- char *my_nick = muc_nick(roomjid);
+ win_print(window, '-', NULL, 0, THEME_TEXT_ME, nick, message);
+ }
- if (g_strcmp0(nick, my_nick) != 0) {
- if (g_strrstr(message, my_nick) != NULL) {
- win_save_print(window, '-', NULL, NO_ME, THEME_ROOMMENTION, nick, message);
+ // currently in groupchat window
+ if (wins_is_current(window)) {
+ status_bar_active(num);
+
+ // not currently on groupchat window
+ } else {
+ status_bar_new(num);
+ cons_show_incoming_message(nick, num);
+
+ if (prefs_get_boolean(PREF_FLASH) && (strcmp(nick, my_nick) != 0)) {
+ flash();
+ }
+
+ mucwin->unread++;
+ }
+
+ int ui_index = num;
+ if (ui_index == 10) {
+ ui_index = 0;
+ }
+
+ // don't notify self messages
+ if (strcmp(nick, my_nick) == 0) {
+ return;
+ }
+
+ if (prefs_get_boolean(PREF_BEEP)) {
+ beep();
+ }
+
+ gboolean notify = FALSE;
+ char *room_setting = prefs_get_string(PREF_NOTIFY_ROOM);
+ if (g_strcmp0(room_setting, "on") == 0) {
+ notify = TRUE;
+ }
+ if (g_strcmp0(room_setting, "mention") == 0) {
+ char *message_lower = g_utf8_strdown(message, -1);
+ char *nick_lower = g_utf8_strdown(nick, -1);
+ if (g_strrstr(message_lower, nick_lower)) {
+ notify = TRUE;
+ }
+ g_free(message_lower);
+ g_free(nick_lower);
+ }
+ prefs_free_string(room_setting);
+
+ if (notify) {
+ gboolean is_current = wins_is_current(window);
+ if ( !is_current || (is_current && prefs_get_boolean(PREF_NOTIFY_ROOM_CURRENT)) ) {
+ Jid *jidp = jid_create(roomjid);
+ if (prefs_get_boolean(PREF_NOTIFY_ROOM_TEXT)) {
+ notify_room_message(nick, jidp->localpart, ui_index, message);
} else {
- win_save_print(window, '-', NULL, NO_ME, THEME_TEXT_THEM, nick, message);
- }
- } else {
- win_save_print(window, '-', NULL, 0, THEME_TEXT_ME, nick, message);
- }
-
- // currently in groupchat window
- if (wins_is_current(window)) {
- status_bar_active(num);
-
- // not currenlty on groupchat window
- } else {
- status_bar_new(num);
- cons_show_incoming_message(nick, num);
-
- if (strcmp(nick, my_nick) != 0) {
- if (prefs_get_boolean(PREF_FLASH)) {
- flash();
- }
- }
-
- mucwin->unread++;
- }
-
- int ui_index = num;
- if (ui_index == 10) {
- ui_index = 0;
- }
-
- if (strcmp(nick, muc_nick(roomjid)) != 0) {
- if (prefs_get_boolean(PREF_BEEP)) {
- beep();
- }
-
- gboolean notify = FALSE;
- char *room_setting = prefs_get_string(PREF_NOTIFY_ROOM);
- if (g_strcmp0(room_setting, "on") == 0) {
- notify = TRUE;
- }
- if (g_strcmp0(room_setting, "mention") == 0) {
- char *message_lower = g_utf8_strdown(message, -1);
- char *nick_lower = g_utf8_strdown(nick, -1);
- if (g_strrstr(message_lower, nick_lower) != NULL) {
- notify = TRUE;
- }
- g_free(message_lower);
- g_free(nick_lower);
- }
- prefs_free_string(room_setting);
-
- if (notify) {
- gboolean is_current = wins_is_current(window);
- if ( !is_current || (is_current && prefs_get_boolean(PREF_NOTIFY_ROOM_CURRENT)) ) {
- Jid *jidp = jid_create(roomjid);
- if (prefs_get_boolean(PREF_NOTIFY_ROOM_TEXT)) {
- notify_room_message(nick, jidp->localpart, ui_index, message);
- } else {
- notify_room_message(nick, jidp->localpart, ui_index, NULL);
- }
- jid_destroy(jidp);
- }
+ notify_room_message(nick, jidp->localpart, ui_index, NULL);
}
+ jid_destroy(jidp);
}
}
}
@@ -1940,22 +1838,22 @@ ui_room_requires_config(const char * const roomjid)
ui_index = 0;
}
- win_save_print(window, '-', NULL, 0, 0, "", "");
- win_save_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "",
+ win_print(window, '-', NULL, 0, 0, "", "");
+ win_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "",
"Room locked, requires configuration.");
- win_save_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "",
+ win_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "",
"Use '/room accept' to accept the defaults");
- win_save_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "",
+ win_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "",
"Use '/room destroy' to cancel and destroy the room");
- win_save_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "",
+ win_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "",
"Use '/room config' to edit the room configuration");
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "");
// currently in groupchat window
if (wins_is_current(window)) {
status_bar_active(num);
- // not currenlty on groupchat window
+ // not currently on groupchat window
} else {
status_bar_new(num);
}
@@ -1998,16 +1896,16 @@ ui_room_destroyed(const char * const roomjid, const char * const reason, const c
ProfWin *console = wins_get_console();
if (reason) {
- win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- Room destroyed: %s, reason: %s", roomjid, reason);
+ win_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- Room destroyed: %s, reason: %s", roomjid, reason);
} else {
- win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- Room destroyed: %s", roomjid);
+ win_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- Room destroyed: %s", roomjid);
}
if (new_jid) {
if (password) {
- win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "Replacement room: %s, password: %s", new_jid, password);
+ win_vprint(console, '!', NULL, 0, THEME_TYPING, "", "Replacement room: %s, password: %s", new_jid, password);
} else {
- win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "Replacement room: %s", new_jid);
+ win_vprint(console, '!', NULL, 0, THEME_TYPING, "", "Replacement room: %s", new_jid);
}
}
}
@@ -2035,7 +1933,7 @@ ui_room_kicked(const char * const roomjid, const char * const actor, const char
}
ProfWin *console = wins_get_console();
- win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- %s", message->str);
+ win_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- %s", message->str);
g_string_free(message, TRUE);
}
}
@@ -2062,7 +1960,7 @@ ui_room_banned(const char * const roomjid, const char * const actor, const char
}
ProfWin *console = wins_get_console();
- win_save_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- %s", message->str);
+ win_vprint(console, '!', NULL, 0, THEME_TYPING, "", "<- %s", message->str);
g_string_free(message, TRUE);
}
}
@@ -2078,17 +1976,17 @@ ui_room_subject(const char * const roomjid, const char * const nick, const char
if (subject) {
if (nick) {
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "*%s has set the room subject: ", nick);
- win_save_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", subject);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "*%s has set the room subject: ", nick);
+ win_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", subject);
} else {
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Room subject: ");
- win_save_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", subject);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Room subject: ");
+ win_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", subject);
}
} else {
if (nick) {
- win_save_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "", "*%s has cleared the room subject: ", nick);
+ win_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "", "*%s has cleared the room subject: ", nick);
} else {
- win_save_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "", "Room subject cleared");
+ win_vprint(window, '!', NULL, 0, THEME_ROOMINFO, "", "Room subject cleared");
}
}
@@ -2096,7 +1994,7 @@ ui_room_subject(const char * const roomjid, const char * const nick, const char
if (wins_is_current(window)) {
status_bar_active(num);
- // not currenlty on groupchat window
+ // not currently on groupchat window
} else {
status_bar_active(num);
}
@@ -2110,7 +2008,7 @@ ui_handle_room_kick_error(const char * const roomjid, const char * const nick, c
if (window == NULL) {
log_error("Kick error received for %s, but no window open for %s.", nick, roomjid);
} else {
- win_save_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error kicking %s: %s", nick, error);
+ win_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error kicking %s: %s", nick, error);
}
}
@@ -2123,14 +2021,14 @@ ui_room_broadcast(const char * const roomjid, const char * const message)
} else {
int num = wins_get_num(window);
- win_save_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Room message: ");
- win_save_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", message);
+ win_vprint(window, '!', NULL, NO_EOL, THEME_ROOMINFO, "", "Room message: ");
+ win_vprint(window, '!', NULL, NO_DATE, 0, "", "%s", message);
// currently in groupchat window
if (wins_is_current(window)) {
status_bar_active(num);
- // not currenlty on groupchat window
+ // not currently on groupchat window
} else {
status_bar_new(num);
}
@@ -2143,7 +2041,7 @@ ui_handle_room_affiliation_list_error(const char * const roomjid, const char * c
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
if (window) {
- win_save_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error retrieving %s list: %s", affiliation, error);
+ win_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error retrieving %s list: %s", affiliation, error);
}
}
@@ -2153,17 +2051,17 @@ ui_handle_room_affiliation_list(const char * const roomjid, const char * const a
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
if (window) {
if (jids) {
- win_save_vprint(window, '!', NULL, 0, 0, "", "Affiliation: %s", affiliation);
+ win_vprint(window, '!', NULL, 0, 0, "", "Affiliation: %s", affiliation);
GSList *curr_jid = jids;
while (curr_jid) {
char *jid = curr_jid->data;
- win_save_vprint(window, '!', NULL, 0, 0, "", " %s", jid);
+ win_vprint(window, '!', NULL, 0, 0, "", " %s", jid);
curr_jid = g_slist_next(curr_jid);
}
- win_save_print(window, '!', NULL, 0, 0, "", "");
+ win_print(window, '!', NULL, 0, 0, "", "");
} else {
- win_save_vprint(window, '!', NULL, 0, 0, "", "No users found with affiliation: %s", affiliation);
- win_save_print(window, '!', NULL, 0, 0, "", "");
+ win_vprint(window, '!', NULL, 0, 0, "", "No users found with affiliation: %s", affiliation);
+ win_print(window, '!', NULL, 0, 0, "", "");
}
}
}
@@ -2173,7 +2071,7 @@ ui_handle_room_role_list_error(const char * const roomjid, const char * const ro
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
if (window) {
- win_save_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error retrieving %s list: %s", role, error);
+ win_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error retrieving %s list: %s", role, error);
}
}
@@ -2183,26 +2081,26 @@ ui_handle_room_role_list(const char * const roomjid, const char * const role, GS
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
if (window) {
if (nicks) {
- win_save_vprint(window, '!', NULL, 0, 0, "", "Role: %s", role);
+ win_vprint(window, '!', NULL, 0, 0, "", "Role: %s", role);
GSList *curr_nick = nicks;
while (curr_nick) {
char *nick = curr_nick->data;
Occupant *occupant = muc_roster_item(roomjid, nick);
if (occupant) {
if (occupant->jid) {
- win_save_vprint(window, '!', NULL, 0, 0, "", " %s (%s)", nick, occupant->jid);
+ win_vprint(window, '!', NULL, 0, 0, "", " %s (%s)", nick, occupant->jid);
} else {
- win_save_vprint(window, '!', NULL, 0, 0, "", " %s", nick);
+ win_vprint(window, '!', NULL, 0, 0, "", " %s", nick);
}
} else {
- win_save_vprint(window, '!', NULL, 0, 0, "", " %s", nick);
+ win_vprint(window, '!', NULL, 0, 0, "", " %s", nick);
}
curr_nick = g_slist_next(curr_nick);
}
- win_save_print(window, '!', NULL, 0, 0, "", "");
+ win_print(window, '!', NULL, 0, 0, "", "");
} else {
- win_save_vprint(window, '!', NULL, 0, 0, "", "No occupants found with role: %s", role);
- win_save_print(window, '!', NULL, 0, 0, "", "");
+ win_vprint(window, '!', NULL, 0, 0, "", "No occupants found with role: %s", role);
+ win_print(window, '!', NULL, 0, 0, "", "");
}
}
}
@@ -2213,7 +2111,7 @@ ui_handle_room_affiliation_set_error(const char * const roomjid, const char * co
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
if (window) {
- win_save_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error setting %s affiliation for %s: %s", affiliation, jid, error);
+ win_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error setting %s affiliation for %s: %s", affiliation, jid, error);
}
}
@@ -2223,7 +2121,7 @@ ui_handle_room_role_set_error(const char * const roomjid, const char * const nic
{
ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
if (window) {
- win_save_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error setting %s role for %s: %s", role, nick, error);
+ win_vprint(window, '!', NULL, 0, THEME_ERROR, "", "Error setting %s role for %s: %s", role, nick, error);
}
}
@@ -2237,7 +2135,7 @@ int
ui_win_unread(int index)
{
ProfWin *window = wins_get_by_num(index);
- if (window != NULL) {
+ if (window) {
return win_unread(window);
} else {
return 0;
@@ -2247,14 +2145,9 @@ ui_win_unread(int index)
char *
ui_ask_password(void)
{
- char *passwd = malloc(sizeof(char) * (MAX_PASSWORD_SIZE + 1));
status_bar_get_password();
status_bar_update_virtual();
- inp_block();
- inp_get_password(passwd);
- inp_non_block(prefs_get_inpblock());
-
- return passwd;
+ return inp_get_password();
}
void
@@ -2265,7 +2158,7 @@ ui_chat_win_contact_online(PContact contact, Resource *resource, GDateTime *last
const char *barejid = p_contact_barejid(contact);
ProfWin *window = (ProfWin*)wins_get_chat(barejid);
- if (window != NULL) {
+ if (window) {
win_show_status_string(window, display_str, show, resource->status,
last_activity, "++", "online");
@@ -2281,7 +2174,7 @@ ui_chat_win_contact_offline(PContact contact, char *resource, char *status)
const char *barejid = p_contact_barejid(contact);
ProfWin *window = (ProfWin*)wins_get_chat(barejid);
- if (window != NULL) {
+ if (window) {
win_show_status_string(window, display_str, "offline", status, NULL, "--",
"offline");
}
@@ -2296,7 +2189,7 @@ ui_contact_offline(char *barejid, char *resource, char *status)
char *show_chat_win = prefs_get_string(PREF_STATUSES_CHAT);
Jid *jid = jid_create_from_bare_and_resource(barejid, resource);
PContact contact = roster_get_contact(barejid);
- if (p_contact_subscription(contact) != NULL) {
+ if (p_contact_subscription(contact)) {
if (strcmp(p_contact_subscription(contact), "none") != 0) {
// show in console if "all"
@@ -2377,7 +2270,7 @@ _ui_draw_term_title(void)
if (res == -1) {
log_error("Error writing terminal window title.");
}
- if (win_title != NULL) {
+ if (win_title) {
free(win_title);
}
win_title = strdup(new_win_title);
@@ -2391,10 +2284,10 @@ ui_show_room_info(ProfMucWin *mucwin)
char *affiliation = muc_affiliation_str(mucwin->roomjid);
ProfWin *window = (ProfWin*) mucwin;
- win_save_vprint(window, '!', NULL, 0, 0, "", "Room: %s", mucwin->roomjid);
- win_save_vprint(window, '!', NULL, 0, 0, "", "Affiliation: %s", affiliation);
- win_save_vprint(window, '!', NULL, 0, 0, "", "Role: %s", role);
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_vprint(window, '!', NULL, 0, 0, "", "Room: %s", mucwin->roomjid);
+ win_vprint(window, '!', NULL, 0, 0, "", "Affiliation: %s", affiliation);
+ win_vprint(window, '!', NULL, 0, 0, "", "Role: %s", role);
+ win_print(window, '-', NULL, 0, 0, "", "");
}
void
@@ -2406,28 +2299,28 @@ ui_show_room_role_list(ProfMucWin *mucwin, muc_role_t role)
if (!occupants) {
switch (role) {
case MUC_ROLE_MODERATOR:
- win_save_print(window, '!', NULL, 0, 0, "", "No moderators found.");
+ win_print(window, '!', NULL, 0, 0, "", "No moderators found.");
break;
case MUC_ROLE_PARTICIPANT:
- win_save_print(window, '!', NULL, 0, 0, "", "No participants found.");
+ win_print(window, '!', NULL, 0, 0, "", "No participants found.");
break;
case MUC_ROLE_VISITOR:
- win_save_print(window, '!', NULL, 0, 0, "", "No visitors found.");
+ win_print(window, '!', NULL, 0, 0, "", "No visitors found.");
break;
default:
break;
}
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "");
} else {
switch (role) {
case MUC_ROLE_MODERATOR:
- win_save_print(window, '!', NULL, 0, 0, "", "Moderators:");
+ win_print(window, '!', NULL, 0, 0, "", "Moderators:");
break;
case MUC_ROLE_PARTICIPANT:
- win_save_print(window, '!', NULL, 0, 0, "", "Participants:");
+ win_print(window, '!', NULL, 0, 0, "", "Participants:");
break;
case MUC_ROLE_VISITOR:
- win_save_print(window, '!', NULL, 0, 0, "", "Visitors:");
+ win_print(window, '!', NULL, 0, 0, "", "Visitors:");
break;
default:
break;
@@ -2438,16 +2331,16 @@ ui_show_room_role_list(ProfMucWin *mucwin, muc_role_t role)
Occupant *occupant = curr_occupant->data;
if (occupant->role == role) {
if (occupant->jid) {
- win_save_vprint(window, '!', NULL, 0, 0, "", " %s (%s)", occupant->nick, occupant->jid);
+ win_vprint(window, '!', NULL, 0, 0, "", " %s (%s)", occupant->nick, occupant->jid);
} else {
- win_save_vprint(window, '!', NULL, 0, 0, "", " %s", occupant->nick);
+ win_vprint(window, '!', NULL, 0, 0, "", " %s", occupant->nick);
}
}
curr_occupant = g_slist_next(curr_occupant);
}
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "");
}
}
@@ -2460,34 +2353,34 @@ ui_show_room_affiliation_list(ProfMucWin *mucwin, muc_affiliation_t affiliation)
if (!occupants) {
switch (affiliation) {
case MUC_AFFILIATION_OWNER:
- win_save_print(window, '!', NULL, 0, 0, "", "No owners found.");
+ win_print(window, '!', NULL, 0, 0, "", "No owners found.");
break;
case MUC_AFFILIATION_ADMIN:
- win_save_print(window, '!', NULL, 0, 0, "", "No admins found.");
+ win_print(window, '!', NULL, 0, 0, "", "No admins found.");
break;
case MUC_AFFILIATION_MEMBER:
- win_save_print(window, '!', NULL, 0, 0, "", "No members found.");
+ win_print(window, '!', NULL, 0, 0, "", "No members found.");
break;
case MUC_AFFILIATION_OUTCAST:
- win_save_print(window, '!', NULL, 0, 0, "", "No outcasts found.");
+ win_print(window, '!', NULL, 0, 0, "", "No outcasts found.");
break;
default:
break;
}
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "");
} else {
switch (affiliation) {
case MUC_AFFILIATION_OWNER:
- win_save_print(window, '!', NULL, 0, 0, "", "Owners:");
+ win_print(window, '!', NULL, 0, 0, "", "Owners:");
break;
case MUC_AFFILIATION_ADMIN:
- win_save_print(window, '!', NULL, 0, 0, "", "Admins:");
+ win_print(window, '!', NULL, 0, 0, "", "Admins:");
break;
case MUC_AFFILIATION_MEMBER:
- win_save_print(window, '!', NULL, 0, 0, "", "Members:");
+ win_print(window, '!', NULL, 0, 0, "", "Members:");
break;
case MUC_AFFILIATION_OUTCAST:
- win_save_print(window, '!', NULL, 0, 0, "", "Outcasts:");
+ win_print(window, '!', NULL, 0, 0, "", "Outcasts:");
break;
default:
break;
@@ -2498,28 +2391,28 @@ ui_show_room_affiliation_list(ProfMucWin *mucwin, muc_affiliation_t affiliation)
Occupant *occupant = curr_occupant->data;
if (occupant->affiliation == affiliation) {
if (occupant->jid) {
- win_save_vprint(window, '!', NULL, 0, 0, "", " %s (%s)", occupant->nick, occupant->jid);
+ win_vprint(window, '!', NULL, 0, 0, "", " %s (%s)", occupant->nick, occupant->jid);
} else {
- win_save_vprint(window, '!', NULL, 0, 0, "", " %s", occupant->nick);
+ win_vprint(window, '!', NULL, 0, 0, "", " %s", occupant->nick);
}
}
curr_occupant = g_slist_next(curr_occupant);
}
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "");
}
}
static void
_ui_handle_form_field(ProfWin *window, char *tag, FormField *field)
{
- win_save_vprint(window, '-', NULL, NO_EOL, THEME_AWAY, "", "[%s] ", tag);
- win_save_vprint(window, '-', NULL, NO_EOL | NO_DATE, 0, "", "%s", field->label);
+ win_vprint(window, '-', NULL, NO_EOL, THEME_AWAY, "", "[%s] ", tag);
+ win_vprint(window, '-', NULL, NO_EOL | NO_DATE, 0, "", "%s", field->label);
if (field->required) {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " (required): ");
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " (required): ");
} else {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ": ");
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ": ");
}
GSList *values = field->values;
@@ -2529,113 +2422,113 @@ _ui_handle_form_field(ProfWin *window, char *tag, FormField *field)
case FIELD_HIDDEN:
break;
case FIELD_TEXT_SINGLE:
- if (curr_value != NULL) {
+ if (curr_value) {
char *value = curr_value->data;
- if (value != NULL) {
+ if (value) {
if (g_strcmp0(field->var, "muc#roomconfig_roomsecret") == 0) {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", "[hidden]");
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", "[hidden]");
} else {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", value);
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", value);
}
}
}
- win_save_newline(window);
+ win_newline(window);
break;
case FIELD_TEXT_PRIVATE:
- if (curr_value != NULL) {
+ if (curr_value) {
char *value = curr_value->data;
- if (value != NULL) {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", "[hidden]");
+ if (value) {
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", "[hidden]");
}
}
- win_save_newline(window);
+ win_newline(window);
break;
case FIELD_TEXT_MULTI:
- win_save_newline(window);
+ win_newline(window);
int index = 1;
- while (curr_value != NULL) {
+ while (curr_value) {
char *value = curr_value->data;
GString *val_tag = g_string_new("");
g_string_printf(val_tag, "val%d", index++);
- win_save_vprint(window, '-', NULL, 0, THEME_ONLINE, "", " [%s] %s", val_tag->str, value);
+ win_vprint(window, '-', NULL, 0, THEME_ONLINE, "", " [%s] %s", val_tag->str, value);
g_string_free(val_tag, TRUE);
curr_value = g_slist_next(curr_value);
}
break;
case FIELD_BOOLEAN:
if (curr_value == NULL) {
- win_save_print(window, '-', NULL, NO_DATE, THEME_OFFLINE, "", "FALSE");
+ win_print(window, '-', NULL, NO_DATE, THEME_OFFLINE, "", "FALSE");
} else {
char *value = curr_value->data;
if (value == NULL) {
- win_save_print(window, '-', NULL, NO_DATE, THEME_OFFLINE, "", "FALSE");
+ win_print(window, '-', NULL, NO_DATE, THEME_OFFLINE, "", "FALSE");
} else {
if (g_strcmp0(value, "0") == 0) {
- win_save_print(window, '-', NULL, NO_DATE, THEME_OFFLINE, "", "FALSE");
+ win_print(window, '-', NULL, NO_DATE, THEME_OFFLINE, "", "FALSE");
} else {
- win_save_print(window, '-', NULL, NO_DATE, THEME_ONLINE, "", "TRUE");
+ win_print(window, '-', NULL, NO_DATE, THEME_ONLINE, "", "TRUE");
}
}
}
break;
case FIELD_LIST_SINGLE:
- if (curr_value != NULL) {
- win_save_newline(window);
+ if (curr_value) {
+ win_newline(window);
char *value = curr_value->data;
GSList *options = field->options;
GSList *curr_option = options;
- while (curr_option != NULL) {
+ while (curr_option) {
FormOption *option = curr_option->data;
if (g_strcmp0(option->value, value) == 0) {
- win_save_vprint(window, '-', NULL, 0, THEME_ONLINE, "", " [%s] %s", option->value, option->label);
+ win_vprint(window, '-', NULL, 0, THEME_ONLINE, "", " [%s] %s", option->value, option->label);
} else {
- win_save_vprint(window, '-', NULL, 0, THEME_OFFLINE, "", " [%s] %s", option->value, option->label);
+ win_vprint(window, '-', NULL, 0, THEME_OFFLINE, "", " [%s] %s", option->value, option->label);
}
curr_option = g_slist_next(curr_option);
}
}
break;
case FIELD_LIST_MULTI:
- if (curr_value != NULL) {
- win_save_newline(window);
+ if (curr_value) {
+ win_newline(window);
GSList *options = field->options;
GSList *curr_option = options;
- while (curr_option != NULL) {
+ while (curr_option) {
FormOption *option = curr_option->data;
- if (g_slist_find_custom(curr_value, option->value, (GCompareFunc)g_strcmp0) != NULL) {
- win_save_vprint(window, '-', NULL, 0, THEME_ONLINE, "", " [%s] %s", option->value, option->label);
+ if (g_slist_find_custom(curr_value, option->value, (GCompareFunc)g_strcmp0)) {
+ win_vprint(window, '-', NULL, 0, THEME_ONLINE, "", " [%s] %s", option->value, option->label);
} else {
- win_save_vprint(window, '-', NULL, 0, THEME_OFFLINE, "", " [%s] %s", option->value, option->label);
+ win_vprint(window, '-', NULL, 0, THEME_OFFLINE, "", " [%s] %s", option->value, option->label);
}
curr_option = g_slist_next(curr_option);
}
}
break;
case FIELD_JID_SINGLE:
- if (curr_value != NULL) {
+ if (curr_value) {
char *value = curr_value->data;
- if (value != NULL) {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", value);
+ if (value) {
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, THEME_ONLINE, "", value);
}
}
- win_save_newline(window);
+ win_newline(window);
break;
case FIELD_JID_MULTI:
- win_save_newline(window);
- while (curr_value != NULL) {
+ win_newline(window);
+ while (curr_value) {
char *value = curr_value->data;
- win_save_vprint(window, '-', NULL, 0, THEME_ONLINE, "", " %s", value);
+ win_vprint(window, '-', NULL, 0, THEME_ONLINE, "", " %s", value);
curr_value = g_slist_next(curr_value);
}
break;
case FIELD_FIXED:
- if (curr_value != NULL) {
+ if (curr_value) {
char *value = curr_value->data;
- if (value != NULL) {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", value);
+ if (value) {
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", value);
}
}
- win_save_newline(window);
+ win_newline(window);
break;
default:
break;
@@ -2646,25 +2539,25 @@ void
ui_show_form(ProfMucConfWin *confwin)
{
ProfWin *window = (ProfWin*) confwin;
- if (confwin->form->title != NULL) {
- win_save_print(window, '-', NULL, NO_EOL, 0, "", "Form title: ");
- win_save_print(window, '-', NULL, NO_DATE, 0, "", confwin->form->title);
+ if (confwin->form->title) {
+ win_print(window, '-', NULL, NO_EOL, 0, "", "Form title: ");
+ win_print(window, '-', NULL, NO_DATE, 0, "", confwin->form->title);
} else {
- win_save_vprint(window, '-', NULL, 0, 0, "", "Configuration for room %s.", confwin->roomjid);
+ win_vprint(window, '-', NULL, 0, 0, "", "Configuration for room %s.", confwin->roomjid);
}
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "");
ui_show_form_help(confwin);
GSList *fields = confwin->form->fields;
GSList *curr_field = fields;
- while (curr_field != NULL) {
+ while (curr_field) {
FormField *field = curr_field->data;
if ((g_strcmp0(field->type, "fixed") == 0) && field->values) {
if (field->values) {
char *value = field->values->data;
- win_save_print(window, '-', NULL, 0, 0, "", value);
+ win_print(window, '-', NULL, 0, 0, "", value);
}
} else if (g_strcmp0(field->type, "hidden") != 0 && field->var) {
char *tag = g_hash_table_lookup(confwin->form->var_to_tag, field->var);
@@ -2680,7 +2573,7 @@ ui_show_form_field(ProfWin *window, DataForm *form, char *tag)
{
FormField *field = form_get_field_by_tag(form, tag);
_ui_handle_form_field(window, tag, field);
- win_save_println(window, "");
+ win_println(window, "");
}
void
@@ -2690,16 +2583,14 @@ ui_handle_room_configuration(const char * const roomjid, DataForm *form)
ProfMucConfWin *confwin = (ProfMucConfWin*)window;
assert(confwin->memcheck == PROFCONFWIN_MEMCHECK);
- int num = wins_get_num(window);
- ui_switch_win(num);
-
+ ui_ev_focus_win(window);
ui_show_form(confwin);
- win_save_print(window, '-', NULL, 0, 0, "", "");
- win_save_print(window, '-', NULL, 0, 0, "", "Use '/form submit' to save changes.");
- win_save_print(window, '-', NULL, 0, 0, "", "Use '/form cancel' to cancel changes.");
- win_save_print(window, '-', NULL, 0, 0, "", "See '/form help' for more information.");
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "Use '/form submit' to save changes.");
+ win_print(window, '-', NULL, 0, 0, "", "Use '/form cancel' to cancel changes.");
+ win_print(window, '-', NULL, 0, 0, "", "See '/form help' for more information.");
+ win_print(window, '-', NULL, 0, 0, "", "");
}
void
@@ -2721,7 +2612,7 @@ ui_handle_room_configuration_form_error(const char * const roomjid, const char *
g_string_append(message_str, message);
}
- win_save_print(window, '-', NULL, 0, THEME_ERROR, "", message_str->str);
+ win_print(window, '-', NULL, 0, THEME_ERROR, "", message_str->str);
g_string_free(message_str, TRUE);
}
@@ -2747,11 +2638,11 @@ ui_handle_room_config_submit_result(const char * const roomjid)
}
if (muc_window) {
- int num = wins_get_num(muc_window);
- ui_switch_win(num);
- win_save_print(muc_window, '!', NULL, 0, THEME_ROOMINFO, "", "Room configuration successful");
+ ui_ev_focus_win((ProfWin*)muc_window);
+ win_print(muc_window, '!', NULL, 0, THEME_ROOMINFO, "", "Room configuration successful");
} else {
- ui_switch_win(1);
+ ProfWin *console = wins_get_console();
+ ui_ev_focus_win(console);
cons_show("Room configuration successful: %s", roomjid);
}
} else {
@@ -2776,25 +2667,25 @@ ui_handle_room_config_submit_result_error(const char * const roomjid, const char
if (form_window) {
if (message) {
- win_save_vprint(form_window, '!', NULL, 0, THEME_ERROR, "", "Configuration error: %s", message);
+ win_vprint(form_window, '!', NULL, 0, THEME_ERROR, "", "Configuration error: %s", message);
} else {
- win_save_print(form_window, '!', NULL, 0, THEME_ERROR, "", "Configuration error");
+ win_print(form_window, '!', NULL, 0, THEME_ERROR, "", "Configuration error");
}
} else if (muc_window) {
if (message) {
- win_save_vprint(muc_window, '!', NULL, 0, THEME_ERROR, "", "Configuration error: %s", message);
+ win_vprint(muc_window, '!', NULL, 0, THEME_ERROR, "", "Configuration error: %s", message);
} else {
- win_save_print(muc_window, '!', NULL, 0, THEME_ERROR, "", "Configuration error");
+ win_print(muc_window, '!', NULL, 0, THEME_ERROR, "", "Configuration error");
}
} else {
if (message) {
- win_save_vprint(console, '!', NULL, 0, THEME_ERROR, "", "Configuration error for %s: %s", roomjid, message);
+ win_vprint(console, '!', NULL, 0, THEME_ERROR, "", "Configuration error for %s: %s", roomjid, message);
} else {
- win_save_vprint(console, '!', NULL, 0, THEME_ERROR, "", "Configuration error for %s", roomjid);
+ win_vprint(console, '!', NULL, 0, THEME_ERROR, "", "Configuration error for %s", roomjid);
}
}
} else {
- win_save_print(console, '!', NULL, 0, THEME_ERROR, "", "Configuration error");
+ win_print(console, '!', NULL, 0, THEME_ERROR, "", "Configuration error");
}
}
@@ -2803,17 +2694,17 @@ ui_show_form_field_help(ProfMucConfWin *confwin, char *tag)
{
ProfWin *window = (ProfWin*) confwin;
FormField *field = form_get_field_by_tag(confwin->form, tag);
- if (field != NULL) {
- win_save_print(window, '-', NULL, NO_EOL, 0, "", field->label);
+ if (field) {
+ win_print(window, '-', NULL, NO_EOL, 0, "", field->label);
if (field->required) {
- win_save_print(window, '-', NULL, NO_DATE, 0, "", " (Required):");
+ win_print(window, '-', NULL, NO_DATE, 0, "", " (Required):");
} else {
- win_save_print(window, '-', NULL, NO_DATE, 0, "", ":");
+ win_print(window, '-', NULL, NO_DATE, 0, "", ":");
}
- if (field->description != NULL) {
- win_save_vprint(window, '-', NULL, 0, 0, "", " Description : %s", field->description);
+ if (field->description) {
+ win_vprint(window, '-', NULL, 0, 0, "", " Description : %s", field->description);
}
- win_save_vprint(window, '-', NULL, 0, 0, "", " Type : %s", field->type);
+ win_vprint(window, '-', NULL, 0, 0, "", " Type : %s", field->type);
int num_values = 0;
GSList *curr_option = NULL;
@@ -2822,51 +2713,51 @@ ui_show_form_field_help(ProfMucConfWin *confwin, char *tag)
switch (field->type_t) {
case FIELD_TEXT_SINGLE:
case FIELD_TEXT_PRIVATE:
- win_save_vprint(window, '-', NULL, 0, 0, "", " Set : /%s ", tag);
- win_save_print(window, '-', NULL, 0, 0, "", " Where : is any text");
+ win_vprint(window, '-', NULL, 0, 0, "", " Set : /%s ", tag);
+ win_print(window, '-', NULL, 0, 0, "", " Where : is any text");
break;
case FIELD_TEXT_MULTI:
num_values = form_get_value_count(confwin->form, tag);
- win_save_vprint(window, '-', NULL, 0, 0, "", " Add : /%s add ", tag);
- win_save_print(window, '-', NULL, 0, 0, "", " Where : is any text");
+ win_vprint(window, '-', NULL, 0, 0, "", " Add : /%s add ", tag);
+ win_print(window, '-', NULL, 0, 0, "", " Where : is any text");
if (num_values > 0) {
- win_save_vprint(window, '-', NULL, 0, 0, "", " Remove : /%s remove ", tag);
- win_save_vprint(window, '-', NULL, 0, 0, "", " Where : between 'val1' and 'val%d'", num_values);
+ win_vprint(window, '-', NULL, 0, 0, "", " Remove : /%s remove ", tag);
+ win_vprint(window, '-', NULL, 0, 0, "", " Where : between 'val1' and 'val%d'", num_values);
}
break;
case FIELD_BOOLEAN:
- win_save_vprint(window, '-', NULL, 0, 0, "", " Set : /%s ", tag);
- win_save_print(window, '-', NULL, 0, 0, "", " Where : is either 'on' or 'off'");
+ win_vprint(window, '-', NULL, 0, 0, "", " Set : /%s ", tag);
+ win_print(window, '-', NULL, 0, 0, "", " Where : is either 'on' or 'off'");
break;
case FIELD_LIST_SINGLE:
- win_save_vprint(window, '-', NULL, 0, 0, "", " Set : /%s ", tag);
- win_save_print(window, '-', NULL, 0, 0, "", " Where : is one of");
+ win_vprint(window, '-', NULL, 0, 0, "", " Set : /%s ", tag);
+ win_print(window, '-', NULL, 0, 0, "", " Where : is one of");
curr_option = field->options;
- while (curr_option != NULL) {
+ while (curr_option) {
option = curr_option->data;
- win_save_vprint(window, '-', NULL, 0, 0, "", " %s", option->value);
+ win_vprint(window, '-', NULL, 0, 0, "", " %s", option->value);
curr_option = g_slist_next(curr_option);
}
break;
case FIELD_LIST_MULTI:
- win_save_vprint(window, '-', NULL, 0, 0, "", " Add : /%s add ", tag);
- win_save_vprint(window, '-', NULL, 0, 0, "", " Remove : /%s remove ", tag);
- win_save_print(window, '-', NULL, 0, 0, "", " Where : is one of");
+ win_vprint(window, '-', NULL, 0, 0, "", " Add : /%s add ", tag);
+ win_vprint(window, '-', NULL, 0, 0, "", " Remove : /%s remove ", tag);
+ win_print(window, '-', NULL, 0, 0, "", " Where : is one of");
curr_option = field->options;
- while (curr_option != NULL) {
+ while (curr_option) {
option = curr_option->data;
- win_save_vprint(window, '-', NULL, 0, 0, "", " %s", option->value);
+ win_vprint(window, '-', NULL, 0, 0, "", " %s", option->value);
curr_option = g_slist_next(curr_option);
}
break;
case FIELD_JID_SINGLE:
- win_save_vprint(window, '-', NULL, 0, 0, "", " Set : /%s ", tag);
- win_save_print(window, '-', NULL, 0, 0, "", " Where : is a valid Jabber ID");
+ win_vprint(window, '-', NULL, 0, 0, "", " Set : /%s ", tag);
+ win_print(window, '-', NULL, 0, 0, "", " Where : is a valid Jabber ID");
break;
case FIELD_JID_MULTI:
- win_save_vprint(window, '-', NULL, 0, 0, "", " Add : /%s add ", tag);
- win_save_vprint(window, '-', NULL, 0, 0, "", " Remove : /%s remove ", tag);
- win_save_print(window, '-', NULL, 0, 0, "", " Where : is a valid Jabber ID");
+ win_vprint(window, '-', NULL, 0, 0, "", " Add : /%s add ", tag);
+ win_vprint(window, '-', NULL, 0, 0, "", " Remove : /%s remove ", tag);
+ win_print(window, '-', NULL, 0, 0, "", " Where : is a valid Jabber ID");
break;
case FIELD_FIXED:
case FIELD_UNKNOWN:
@@ -2875,32 +2766,41 @@ ui_show_form_field_help(ProfMucConfWin *confwin, char *tag)
break;
}
} else {
- win_save_vprint(window, '-', NULL, 0, 0, "", "No such field %s", tag);
+ win_vprint(window, '-', NULL, 0, 0, "", "No such field %s", tag);
}
}
void
ui_show_form_help(ProfMucConfWin *confwin)
{
- if (confwin->form->instructions != NULL) {
+ if (confwin->form->instructions) {
ProfWin *window = (ProfWin*) confwin;
- win_save_print(window, '-', NULL, 0, 0, "", "Supplied instructions:");
- win_save_print(window, '-', NULL, 0, 0, "", confwin->form->instructions);
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "Supplied instructions:");
+ win_print(window, '-', NULL, 0, 0, "", confwin->form->instructions);
+ win_print(window, '-', NULL, 0, 0, "", "");
}
}
void
ui_show_lines(ProfWin *window, const gchar** lines)
{
- if (lines != NULL) {
+ if (lines) {
int i;
for (i = 0; lines[i] != NULL; i++) {
- win_save_print(window, '-', NULL, 0, 0, "", lines[i]);
+ win_print(window, '-', NULL, 0, 0, "", lines[i]);
}
}
}
+void
+ui_room_update_occupants(const char * const roomjid)
+{
+ ProfWin *window = (ProfWin*)wins_get_muc(roomjid);
+ if (window && win_has_active_subwin(window)) {
+ occupantswin_occupants(roomjid);
+ }
+}
+
void
ui_room_show_occupants(const char * const roomjid)
{
@@ -2940,65 +2840,34 @@ ui_hide_roster(void)
}
static void
-_win_handle_switch(const wint_t ch)
+_win_show_history(ProfChatWin *chatwin, const char * const contact)
{
- if (ch == KEY_F(1)) {
- ui_switch_win(1);
- } else if (ch == KEY_F(2)) {
- ui_switch_win(2);
- } else if (ch == KEY_F(3)) {
- ui_switch_win(3);
- } else if (ch == KEY_F(4)) {
- ui_switch_win(4);
- } else if (ch == KEY_F(5)) {
- ui_switch_win(5);
- } else if (ch == KEY_F(6)) {
- ui_switch_win(6);
- } else if (ch == KEY_F(7)) {
- ui_switch_win(7);
- } else if (ch == KEY_F(8)) {
- ui_switch_win(8);
- } else if (ch == KEY_F(9)) {
- ui_switch_win(9);
- } else if (ch == KEY_F(10)) {
- ui_switch_win(0);
- }
-}
-
-static void
-_win_show_history(int win_index, const char * const contact)
-{
- ProfWin *window = wins_get_by_num(win_index);
- if (window->type == WIN_CHAT) {
- ProfChatWin *chatwin = (ProfChatWin*) window;
- assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
- if (!chatwin->history_shown) {
- Jid *jid = jid_create(jabber_get_fulljid());
- GSList *history = chat_log_get_previous(jid->barejid, contact);
- jid_destroy(jid);
- GSList *curr = history;
- while (curr != NULL) {
- char *line = curr->data;
- // entry
- if (line[2] == ':') {
- char hh[3]; memcpy(hh, &line[0], 2); hh[2] = '\0'; int ihh = atoi(hh);
- char mm[3]; memcpy(mm, &line[3], 2); mm[2] = '\0'; int imm = atoi(mm);
- char ss[3]; memcpy(ss, &line[6], 2); ss[2] = '\0'; int iss = atoi(ss);
- GDateTime *time = g_date_time_new_local(2000, 1, 1, ihh, imm, iss);
- GTimeVal tv;
- g_date_time_to_timeval(time, &tv);
- win_save_print(window, '-', &tv, NO_COLOUR_DATE, 0, "", curr->data+11);
- g_date_time_unref(time);
- // header
- } else {
- win_save_print(window, '-', NULL, 0, 0, "", curr->data);
- }
- curr = g_slist_next(curr);
+ if (!chatwin->history_shown) {
+ Jid *jid = jid_create(jabber_get_fulljid());
+ GSList *history = chat_log_get_previous(jid->barejid, contact);
+ jid_destroy(jid);
+ GSList *curr = history;
+ while (curr) {
+ char *line = curr->data;
+ // entry
+ if (line[2] == ':') {
+ char hh[3]; memcpy(hh, &line[0], 2); hh[2] = '\0'; int ihh = atoi(hh);
+ char mm[3]; memcpy(mm, &line[3], 2); mm[2] = '\0'; int imm = atoi(mm);
+ char ss[3]; memcpy(ss, &line[6], 2); ss[2] = '\0'; int iss = atoi(ss);
+ GDateTime *time = g_date_time_new_local(2000, 1, 1, ihh, imm, iss);
+ GTimeVal tv;
+ g_date_time_to_timeval(time, &tv);
+ win_print((ProfWin*)chatwin, '-', &tv, NO_COLOUR_DATE, 0, "", curr->data+11);
+ g_date_time_unref(time);
+ // header
+ } else {
+ win_print((ProfWin*)chatwin, '-', NULL, 0, 0, "", curr->data);
}
- chatwin->history_shown = TRUE;
-
- g_slist_free_full(history, free);
+ curr = g_slist_next(curr);
}
+ chatwin->history_shown = TRUE;
+
+ g_slist_free_full(history, free);
}
}
diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c
index 85ddc79a..caea8ea9 100644
--- a/src/ui/inputwin.c
+++ b/src/ui/inputwin.c
@@ -1,7 +1,7 @@
/*
* inputwin.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -38,6 +38,11 @@
#include
#include
#include
+#include
+#include
+
+#include
+#include
#ifdef HAVE_NCURSESW_NCURSES_H
#include
@@ -50,7 +55,6 @@
#include "config/accounts.h"
#include "config/preferences.h"
#include "config/theme.h"
-#include "tools/history.h"
#include "log.h"
#include "muc.h"
#include "profanity.h"
@@ -59,39 +63,48 @@
#include "ui/statusbar.h"
#include "ui/inputwin.h"
#include "ui/windows.h"
+#include "event/ui_events.h"
#include "xmpp/xmpp.h"
-#define _inp_win_update_virtual() pnoutrefresh(inp_win, 0, pad_start, rows-1, 0, rows-1, cols-1)
-
-#define KEY_CTRL_A 0001
-#define KEY_CTRL_B 0002
-#define KEY_CTRL_D 0004
-#define KEY_CTRL_E 0005
-#define KEY_CTRL_F 0006
-#define KEY_CTRL_N 0016
-#define KEY_CTRL_P 0020
-#define KEY_CTRL_U 0025
-#define KEY_CTRL_W 0027
-
-#define MAX_HISTORY 100
-#define INP_WIN_MAX 1000
-
static WINDOW *inp_win;
-static History history;
-
-static char input[INP_WIN_MAX];
-static int input_len_bytes;
-
static int pad_start = 0;
-static int rows, cols;
-static int _handle_edit(int key_type, const wint_t ch);
-static int _handle_alt_key(int key);
-static void _handle_backspace(void);
-static int _printable(const wint_t ch);
-static void _clear_input(void);
-static void _go_to_end(void);
-static void _delete_previous_word(void);
+static struct timeval p_rl_timeout;
+static gint inp_timeout = 0;
+static gint no_input_count = 0;
+
+static fd_set fds;
+static int r;
+static char *inp_line = NULL;
+static gboolean get_password = FALSE;
+
+static void _inp_win_update_virtual(void);
+static int _inp_printable(const wint_t ch);
+static void _inp_win_handle_scroll(void);
+static int _inp_offset_to_col(char *str, int offset);
+static void _inp_write(char *line, int offset);
+
+static int _inp_rl_getc(FILE *stream);
+static void _inp_rl_linehandler(char *line);
+static int _inp_rl_tab_handler(int count, int key);
+static int _inp_rl_clear_handler(int count, int key);
+static int _inp_rl_win1_handler(int count, int key);
+static int _inp_rl_win2_handler(int count, int key);
+static int _inp_rl_win3_handler(int count, int key);
+static int _inp_rl_win4_handler(int count, int key);
+static int _inp_rl_win5_handler(int count, int key);
+static int _inp_rl_win6_handler(int count, int key);
+static int _inp_rl_win7_handler(int count, int key);
+static int _inp_rl_win8_handler(int count, int key);
+static int _inp_rl_win9_handler(int count, int key);
+static int _inp_rl_win0_handler(int count, int key);
+static int _inp_rl_altleft_handler(int count, int key);
+static int _inp_rl_altright_handler(int count, int key);
+static int _inp_rl_pageup_handler(int count, int key);
+static int _inp_rl_pagedown_handler(int count, int key);
+static int _inp_rl_altpageup_handler(int count, int key);
+static int _inp_rl_altpagedown_handler(int count, int key);
+static int _inp_rl_startup_hook(void);
void
create_input_window(void)
@@ -101,25 +114,84 @@ create_input_window(void)
#else
ESCDELAY = 25;
#endif
- getmaxyx(stdscr, rows, cols);
+ if (inp_timeout == 1000) {
+ p_rl_timeout.tv_sec = 1;
+ p_rl_timeout.tv_usec = 0;
+ } else {
+ p_rl_timeout.tv_sec = 0;
+ p_rl_timeout.tv_usec = inp_timeout * 1000;
+ }
+
+ rl_readline_name = "profanity";
+ rl_getc_function = _inp_rl_getc;
+ rl_startup_hook = _inp_rl_startup_hook;
+ rl_callback_handler_install(NULL, _inp_rl_linehandler);
+
inp_win = newpad(1, INP_WIN_MAX);
wbkgd(inp_win, theme_attrs(THEME_INPUT_TEXT));;
keypad(inp_win, TRUE);
wmove(inp_win, 0, 0);
+
_inp_win_update_virtual();
- history = history_new(MAX_HISTORY);
+}
+
+char *
+inp_readline(void)
+{
+ free(inp_line);
+ inp_line = NULL;
+ FD_ZERO(&fds);
+ FD_SET(fileno(rl_instream), &fds);
+ errno = 0;
+ r = select(FD_SETSIZE, &fds, NULL, NULL, &p_rl_timeout);
+ if (r < 0) {
+ char *err_msg = strerror(errno);
+ log_error("Readline failed: %s", err_msg);
+ return NULL;
+ }
+
+ if (FD_ISSET(fileno(rl_instream), &fds)) {
+ rl_callback_read_char();
+
+ if (rl_line_buffer &&
+ rl_line_buffer[0] != '/' &&
+ rl_line_buffer[0] != '\0' &&
+ rl_line_buffer[0] != '\n') {
+ prof_handle_activity();
+ }
+
+ ui_reset_idle_time();
+ _inp_write(rl_line_buffer, rl_point);
+ inp_nonblocking(TRUE);
+ } else {
+ inp_nonblocking(FALSE);
+ prof_handle_idle();
+ }
+
+ if (inp_timeout == 1000) {
+ p_rl_timeout.tv_sec = 1;
+ p_rl_timeout.tv_usec = 0;
+ } else {
+ p_rl_timeout.tv_sec = 0;
+ p_rl_timeout.tv_usec = inp_timeout * 1000;
+ }
+
+ if (inp_line) {
+ return strdup(inp_line);
+ } else {
+ return NULL;
+ }
}
void
inp_win_resize(void)
{
- int inp_x;
- getmaxyx(stdscr, rows, cols);
- inp_x = getcurx(inp_win);
+ int col = getcurx(inp_win);
+ int wcols = getmaxx(stdscr);
// if lost cursor off screen, move contents to show it
- if (inp_x >= pad_start + cols) {
- pad_start = inp_x - (cols / 2);
+ if (col >= pad_start + wcols) {
+ pad_start = col - (wcols / 2);
if (pad_start < 0) {
pad_start = 0;
}
@@ -130,127 +202,60 @@ inp_win_resize(void)
}
void
-inp_non_block(gint timeout)
+inp_nonblocking(gboolean reset)
{
- wtimeout(inp_win, timeout);
-}
-
-void
-inp_block(void)
-{
- wtimeout(inp_win, -1);
-}
-
-char *
-inp_read(int *key_type, wint_t *ch)
-{
- int display_size = utf8_display_len(input);
-
- // echo off, and get some more input
- noecho();
- *key_type = 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_boolean(PREF_INPBLOCK_DYNAMIC)) {
+ inp_timeout = prefs_get_inpblock();
+ return;
}
- if (*key_type == ERR) {
- prof_handle_idle();
- }
- if ((*key_type != ERR) && (*key_type != KEY_CODE_YES) && !in_command && _printable(*ch)) {
- prof_handle_activity();
+ if (reset) {
+ inp_timeout = 0;
+ no_input_count = 0;
}
- // if it wasn't an arrow key etc
- if (!_handle_edit(*key_type, *ch)) {
- if (_printable(*ch) && *key_type != KEY_CODE_YES) {
- if (input_len_bytes >= INP_WIN_MAX) {
- *ch = ERR;
- return NULL;
+ if (inp_timeout < prefs_get_inpblock()) {
+ no_input_count++;
+
+ if (no_input_count % 10 == 0) {
+ inp_timeout += no_input_count;
+
+ if (inp_timeout > prefs_get_inpblock()) {
+ inp_timeout = prefs_get_inpblock();
}
-
- int 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[input_len_bytes - 1]; offset >= next_ch; offset--) {
- *(offset + utf_len) = *offset;
- }
- int i;
- for (i = 0; i < utf_len; i++) {
- *(next_ch + i) = bytes[i];
- }
-
- input_len_bytes += utf_len;
- input[input_len_bytes] = '\0';
- waddstr(inp_win, next_ch);
- wmove(inp_win, 0, inp_x + 1);
-
- if (inp_x - pad_start > cols-3) {
- pad_start++;
- _inp_win_update_virtual();
- }
-
- // 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) {
- int i;
- for (i = 0 ; i < utf_len; i++) {
- input[input_len_bytes++] = bytes[i];
- }
- input[input_len_bytes] = '\0';
-
- bytes[utf_len] = '\0';
- waddstr(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_update_virtual();
- }
- }
- }
-
- cmd_reset_autocomplete();
}
}
-
- echo();
-
- if (*ch == '\n') {
- input[input_len_bytes] = '\0';
- input_len_bytes = 0;
- return strdup(input);
- } else {
- return NULL;
- }
}
void
-inp_get_password(char *passwd)
+inp_close(void)
{
- _clear_input();
+ rl_callback_handler_remove();
+}
+
+char*
+inp_get_password(void)
+{
+ werase(inp_win);
+ wmove(inp_win, 0, 0);
+ pad_start = 0;
_inp_win_update_virtual();
doupdate();
- noecho();
- mvwgetnstr(inp_win, 0, 1, passwd, MAX_PASSWORD_SIZE);
- wmove(inp_win, 0, 0);
- echo();
+ char *password = NULL;
+ get_password = TRUE;
+ while (!password) {
+ password = inp_readline();
+ ui_update();
+ werase(inp_win);
+ wmove(inp_win, 0, 0);
+ pad_start = 0;
+ _inp_win_update_virtual();
+ doupdate();
+ }
+ get_password = FALSE;
+
status_bar_clear();
+ return password;
}
void
@@ -260,525 +265,314 @@ inp_put_back(void)
}
void
-inp_replace_input(const char * const new_input)
+inp_win_clear(void)
{
- strncpy(input, new_input, INP_WIN_MAX);
- input_len_bytes = strlen(input);
- inp_win_reset();
- input[input_len_bytes] = '\0';
- waddstr(inp_win, input);
- _go_to_end();
-}
-
-void
-inp_win_reset(void)
-{
- _clear_input();
+ werase(inp_win);
+ wmove(inp_win, 0, 0);
pad_start = 0;
_inp_win_update_virtual();
}
-void
-inp_history_append(char *inp)
+static void
+_inp_win_update_virtual(void)
{
- history_append(history, inp);
+ int wrows, wcols;
+ getmaxyx(stdscr, wrows, wcols);
+ pnoutrefresh(inp_win, 0, pad_start, wrows-1, 0, wrows-1, wcols-2);
}
static void
-_clear_input(void)
+_inp_write(char *line, int offset)
{
+ int col = _inp_offset_to_col(line, offset);
werase(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 wasn't
- */
-static int
-_handle_edit(int key_type, const wint_t ch)
-{
- char *prev = NULL;
- char *next = NULL;
- int inp_x = getcurx(inp_win);
- int next_ch;
- int display_size = utf8_display_len(input);
-
- // CTRL-LEFT
- if ((key_type == KEY_CODE_YES) && (ch == 547 || ch == 545 || ch == 544 || ch == 540 || ch == 539) && (inp_x > 0)) {
- input[input_len_bytes] = '\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_update_virtual();
- }
- return 1;
-
- // CTRL-RIGHT
- } else if ((key_type == KEY_CODE_YES) && (ch == 562 || ch == 560 || ch == 555 || ch == 559 || ch == 554) && (inp_x < display_size)) {
- input[input_len_bytes] = '\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_update_virtual();
- }
-
- return 1;
-
- // ALT-LEFT
- } else if ((key_type == KEY_CODE_YES) && (ch == 537 || ch == 542)) {
- ui_previous_win();
- return 1;
-
- // ALT-RIGHT
- } else if ((key_type == KEY_CODE_YES) && (ch == 552 || ch == 557)) {
- ui_next_win();
- return 1;
-
- // other editing keys
- } else {
- switch(ch) {
-
- case 27: // ESC
- // check for ALT-key
- next_ch = wgetch(inp_win);
- if (next_ch != ERR) {
- return _handle_alt_key(next_ch);
- } else {
- input_len_bytes = 0;
- inp_win_reset();
- return 1;
- }
-
- case 127:
- _handle_backspace();
- return 1;
- case KEY_BACKSPACE:
- if (key_type != KEY_CODE_YES) {
- return 0;
- }
- _handle_backspace();
- return 1;
-
- case KEY_DC: // DEL
- if (key_type != KEY_CODE_YES) {
- return 0;
- }
- case KEY_CTRL_D:
- if (inp_x == display_size-1) {
- gchar *start = g_utf8_substring(input, 0, inp_x);
- for (input_len_bytes = 0; input_len_bytes < strlen(start); input_len_bytes++) {
- input[input_len_bytes] = start[input_len_bytes];
- }
- input[input_len_bytes] = '\0';
-
- g_free(start);
-
- _clear_input();
- waddstr(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, input_len_bytes);
- GString *new = g_string_new(start);
- g_string_append(new, end);
-
- for (input_len_bytes = 0; input_len_bytes < strlen(new->str); input_len_bytes++) {
- input[input_len_bytes] = new->str[input_len_bytes];
- }
- input[input_len_bytes] = '\0';
-
- g_free(start);
- g_free(end);
- g_string_free(new, FALSE);
-
- _clear_input();
- waddstr(inp_win, input);
- wmove(inp_win, 0, inp_x);
- }
- return 1;
-
- case KEY_LEFT:
- if (key_type != KEY_CODE_YES) {
- return 0;
- }
- case KEY_CTRL_B:
- 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_update_virtual();
- }
- }
- return 1;
-
- case KEY_RIGHT:
- if (key_type != KEY_CODE_YES) {
- return 0;
- }
- case KEY_CTRL_F:
- 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_update_virtual();
- }
- }
- return 1;
-
- case KEY_UP:
- if (key_type != KEY_CODE_YES) {
- return 0;
- }
- case KEY_CTRL_P:
- input[input_len_bytes] = '\0';
- prev = history_previous(history, input);
- if (prev) {
- inp_replace_input(prev);
- }
- return 1;
-
- case KEY_DOWN:
- if (key_type != KEY_CODE_YES) {
- return 0;
- }
- case KEY_CTRL_N:
- input[input_len_bytes] = '\0';
- next = history_next(history, input);
- if (next) {
- inp_replace_input(next);
- } else if (input_len_bytes != 0) {
- input[input_len_bytes] = '\0';
- history_append(history, input);
- inp_replace_input("");
- }
- return 1;
-
- case KEY_HOME:
- if (key_type != KEY_CODE_YES) {
- return 0;
- }
- case KEY_CTRL_A:
- wmove(inp_win, 0, 0);
- pad_start = 0;
- _inp_win_update_virtual();
- return 1;
-
- case KEY_END:
- if (key_type != KEY_CODE_YES) {
- return 0;
- }
- case KEY_CTRL_E:
- _go_to_end();
- return 1;
-
- case 9: // tab
- if (input_len_bytes != 0) {
- input[input_len_bytes] = '\0';
- if ((strncmp(input, "/", 1) != 0) && (ui_current_win_type() == WIN_MUC)) {
- char *result = muc_autocomplete(input);
- if (result) {
- inp_replace_input(result);
- free(result);
- }
- } else if (strncmp(input, "/", 1) == 0) {
- char *result = cmd_autocomplete(input);
- if (result) {
- inp_replace_input(result);
- free(result);
- }
- }
- }
- return 1;
-
- case KEY_CTRL_W:
- _delete_previous_word();
- return 1;
- break;
-
- case KEY_CTRL_U:
- while (getcurx(inp_win) > 0) {
- _delete_previous_word();
- }
- return 1;
- break;
-
- default:
- return 0;
- }
- }
-}
-
-static void
-_handle_backspace(void)
-{
- int inp_x = getcurx(inp_win);
- int display_size = utf8_display_len(input);
- roster_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 (input_len_bytes = 0; input_len_bytes < strlen(start); input_len_bytes++) {
- input[input_len_bytes] = start[input_len_bytes];
- }
- input[input_len_bytes] = '\0';
-
- g_free(start);
-
- _clear_input();
- waddstr(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, input_len_bytes);
- GString *new = g_string_new(start);
- g_string_append(new, end);
-
- for (input_len_bytes = 0; input_len_bytes < strlen(new->str); input_len_bytes++) {
- input[input_len_bytes] = new->str[input_len_bytes];
- }
- input[input_len_bytes] = '\0';
-
- g_free(start);
- g_free(end);
- g_string_free(new, FALSE);
-
- _clear_input();
- waddstr(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_update_virtual();
- }
- }
+ waddstr(inp_win, line);
+ wmove(inp_win, 0, col);
+ _inp_win_handle_scroll();
+ _inp_win_update_virtual();
}
static int
-_handle_alt_key(int key)
-{
- switch (key)
- {
- case '1':
- ui_switch_win(1);
- break;
- case '2':
- ui_switch_win(2);
- break;
- case '3':
- ui_switch_win(3);
- break;
- case '4':
- ui_switch_win(4);
- break;
- case '5':
- ui_switch_win(5);
- break;
- case '6':
- ui_switch_win(6);
- break;
- case '7':
- ui_switch_win(7);
- break;
- case '8':
- ui_switch_win(8);
- break;
- case '9':
- ui_switch_win(9);
- break;
- case '0':
- ui_switch_win(0);
- break;
- case KEY_LEFT:
- ui_previous_win();
- break;
- case KEY_RIGHT:
- ui_next_win();
- break;
- case 263:
- case 127:
- _delete_previous_word();
- break;
- default:
- break;
- }
- return 1;
-}
-
-static void
-_delete_previous_word(void)
-{
- int end_del = getcurx(inp_win);
- int start_del = end_del;
-
- input[input_len_bytes] = '\0';
- gchar *curr_ch = g_utf8_offset_to_pointer(input, end_del);
- 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) {
- start_del = 0;
- } else {
- start_del = g_utf8_pointer_to_offset(input, curr_ch);
- }
-
- gint len = g_utf8_strlen(input, -1);
- gchar *start_string = g_utf8_substring(input, 0, start_del);
- gchar *end_string = g_utf8_substring(input, end_del, len);
-
- int i;
- for (i = 0; i < strlen(start_string); i++) {
- input[i] = start_string[i];
- }
- for (i = 0; i < strlen(end_string); i++) {
- input[strlen(start_string)+i] = end_string[i];
- }
-
- input_len_bytes = strlen(start_string)+i;
- input[input_len_bytes] = '\0';
-
- _clear_input();
- waddstr(inp_win, input);
- wmove(inp_win, 0, start_del);
-
- // if gone off screen to left, jump left (half a screen worth)
- if (start_del <= pad_start) {
- pad_start = pad_start - (cols / 2);
- if (pad_start < 0) {
- pad_start = 0;
- }
-
- _inp_win_update_virtual();
- }
-}
-
-static void
-_go_to_end(void)
-{
- int display_size = utf8_display_len(input);
- wmove(inp_win, 0, display_size);
- if (display_size > cols-2) {
- pad_start = display_size - cols + 1;
- _inp_win_update_virtual();
- }
-}
-
-static int
-_printable(const wint_t ch)
+_inp_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);
}
+
+static int
+_inp_offset_to_col(char *str, int offset)
+{
+ int i = 0;
+ int col = 0;
+
+ while (i < offset && str[i] != '\0') {
+ gunichar uni = g_utf8_get_char(&str[i]);
+ size_t ch_len = mbrlen(&str[i], 4, NULL);
+ i += ch_len;
+ col++;
+ if (g_unichar_iswide(uni)) {
+ col++;
+ }
+ }
+
+ return col;
+}
+
+static void
+_inp_win_handle_scroll(void)
+{
+ int col = getcurx(inp_win);
+ int wcols = getmaxx(stdscr);
+
+ if (col == 0) {
+ pad_start = 0;
+ } else if (col >= pad_start + (wcols -2)) {
+ pad_start = col - (wcols / 2);
+ if (pad_start < 0) {
+ pad_start = 0;
+ }
+ } else if (col <= pad_start) {
+ pad_start = pad_start - (wcols / 2);
+ if (pad_start < 0) {
+ pad_start = 0;
+ }
+ }
+}
+
+// Readline callbacks
+
+static int
+_inp_rl_startup_hook(void)
+{
+ rl_bind_keyseq("\\e1", _inp_rl_win1_handler);
+ rl_bind_keyseq("\\e2", _inp_rl_win2_handler);
+ rl_bind_keyseq("\\e3", _inp_rl_win3_handler);
+ rl_bind_keyseq("\\e4", _inp_rl_win4_handler);
+ rl_bind_keyseq("\\e5", _inp_rl_win5_handler);
+ rl_bind_keyseq("\\e6", _inp_rl_win6_handler);
+ rl_bind_keyseq("\\e7", _inp_rl_win7_handler);
+ rl_bind_keyseq("\\e8", _inp_rl_win8_handler);
+ rl_bind_keyseq("\\e9", _inp_rl_win9_handler);
+ rl_bind_keyseq("\\e0", _inp_rl_win0_handler);
+
+ rl_bind_keyseq("\\eOP", _inp_rl_win1_handler);
+ rl_bind_keyseq("\\eOQ", _inp_rl_win2_handler);
+ rl_bind_keyseq("\\eOR", _inp_rl_win3_handler);
+ rl_bind_keyseq("\\eOS", _inp_rl_win4_handler);
+ rl_bind_keyseq("\\e[15~", _inp_rl_win5_handler);
+ rl_bind_keyseq("\\e[17~", _inp_rl_win6_handler);
+ rl_bind_keyseq("\\e[18~", _inp_rl_win7_handler);
+ rl_bind_keyseq("\\e[19~", _inp_rl_win8_handler);
+ rl_bind_keyseq("\\e[20~", _inp_rl_win9_handler);
+ rl_bind_keyseq("\\e[21~", _inp_rl_win0_handler);
+
+ rl_bind_keyseq("\\e[1;9D", _inp_rl_altleft_handler);
+ rl_bind_keyseq("\\e[1;3D", _inp_rl_altleft_handler);
+ rl_bind_keyseq("\\e\\e[D", _inp_rl_altleft_handler);
+
+ rl_bind_keyseq("\\e[1;9C", _inp_rl_altright_handler);
+ rl_bind_keyseq("\\e[1;3C", _inp_rl_altright_handler);
+ rl_bind_keyseq("\\e\\e[C", _inp_rl_altright_handler);
+
+ rl_bind_keyseq("\\e\\e[5~", _inp_rl_altpageup_handler);
+ rl_bind_keyseq("\\e[5;3~", _inp_rl_altpageup_handler);
+ rl_bind_keyseq("\\e\\eOy", _inp_rl_altpageup_handler);
+
+ rl_bind_keyseq("\\e\\e[6~", _inp_rl_altpagedown_handler);
+ rl_bind_keyseq("\\e[6;3~", _inp_rl_altpagedown_handler);
+ rl_bind_keyseq("\\e\\eOs", _inp_rl_altpagedown_handler);
+
+ rl_bind_keyseq("\\e[5~", _inp_rl_pageup_handler);
+ rl_bind_keyseq("\\eOy", _inp_rl_pageup_handler);
+ rl_bind_keyseq("\\e[6~", _inp_rl_pagedown_handler);
+ rl_bind_keyseq("\\eOs", _inp_rl_pagedown_handler);
+
+ rl_bind_key('\t', _inp_rl_tab_handler);
+ rl_bind_key(CTRL('L'), _inp_rl_clear_handler);
+
+ return 0;
+}
+
+static void
+_inp_rl_linehandler(char *line)
+{
+ if (line && *line) {
+ if (!get_password) {
+ add_history(line);
+ }
+ }
+ inp_line = line;
+}
+
+static int
+_inp_rl_getc(FILE *stream)
+{
+ int ch = rl_getc(stream);
+ if (_inp_printable(ch)) {
+ cmd_reset_autocomplete();
+ }
+ return ch;
+}
+
+static int
+_inp_rl_clear_handler(int count, int key)
+{
+ ui_clear_current();
+ return 0;
+}
+
+static int
+_inp_rl_tab_handler(int count, int key)
+{
+ if (rl_point != rl_end || !rl_line_buffer) {
+ return 0;
+ }
+
+ if ((strncmp(rl_line_buffer, "/", 1) != 0) && (ui_current_win_type() == WIN_MUC)) {
+ char *result = muc_autocomplete(rl_line_buffer);
+ if (result) {
+ rl_replace_line(result, 0);
+ rl_point = rl_end;
+ }
+ } else if (strncmp(rl_line_buffer, "/", 1) == 0) {
+ char *result = cmd_autocomplete(rl_line_buffer);
+ if (result) {
+ rl_replace_line(result, 0);
+ rl_point = rl_end;
+ }
+ }
+
+ return 0;
+}
+
+static void
+_go_to_win(int i)
+{
+ ProfWin *window = wins_get_by_num(i);
+ if (window) {
+ ui_ev_focus_win(window);
+ }
+}
+
+static int
+_inp_rl_win1_handler(int count, int key)
+{
+ _go_to_win(1);
+ return 0;
+}
+
+static int
+_inp_rl_win2_handler(int count, int key)
+{
+ _go_to_win(2);
+ return 0;
+}
+
+static int
+_inp_rl_win3_handler(int count, int key)
+{
+ _go_to_win(3);
+ return 0;
+}
+
+static int
+_inp_rl_win4_handler(int count, int key)
+{
+ _go_to_win(4);
+ return 0;
+}
+
+static int
+_inp_rl_win5_handler(int count, int key)
+{
+ _go_to_win(5);
+ return 0;
+}
+
+static int
+_inp_rl_win6_handler(int count, int key)
+{
+ _go_to_win(6);
+ return 0;
+}
+
+static int
+_inp_rl_win7_handler(int count, int key)
+{
+ _go_to_win(7);
+ return 0;
+}
+
+static int
+_inp_rl_win8_handler(int count, int key)
+{
+ _go_to_win(8);
+ return 0;
+}
+
+static int
+_inp_rl_win9_handler(int count, int key)
+{
+ _go_to_win(9);
+ return 0;
+}
+
+static int
+_inp_rl_win0_handler(int count, int key)
+{
+ _go_to_win(0);
+ return 0;
+}
+
+static int
+_inp_rl_altleft_handler(int count, int key)
+{
+ ProfWin *window = wins_get_previous();
+ if (window) {
+ ui_ev_focus_win(window);
+ }
+ return 0;
+}
+
+static int
+_inp_rl_altright_handler(int count, int key)
+{
+ ProfWin *window = wins_get_next();
+ if (window) {
+ ui_ev_focus_win(window);
+ }
+ return 0;
+}
+
+static int
+_inp_rl_pageup_handler(int count, int key)
+{
+ ui_page_up();
+ return 0;
+}
+
+static int
+_inp_rl_pagedown_handler(int count, int key)
+{
+ ui_page_down();
+ return 0;
+}
+
+static int
+_inp_rl_altpageup_handler(int count, int key)
+{
+ ui_subwin_page_up();
+ return 0;
+}
+
+static int
+_inp_rl_altpagedown_handler(int count, int key)
+{
+ ui_subwin_page_down();
+ return 0;
+}
diff --git a/src/ui/inputwin.h b/src/ui/inputwin.h
index 39fde720..f49a6a76 100644
--- a/src/ui/inputwin.h
+++ b/src/ui/inputwin.h
@@ -1,7 +1,7 @@
/*
* inputwin.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -35,15 +35,17 @@
#ifndef UI_INPUTWIN_H
#define UI_INPUTWIN_H
+#include
+
+#define INP_WIN_MAX 1000
+
void create_input_window(void);
-char* inp_read(int *key_type, wint_t *ch);
-void inp_win_reset(void);
+char* inp_readline(void);
+void inp_nonblocking(gboolean reset);
+void inp_close(void);
+void inp_win_clear(void);
void inp_win_resize(void);
void inp_put_back(void);
-void inp_non_block(gint);
-void inp_block(void);
-void inp_get_password(char *passwd);
-void inp_replace_input(const char * const new_input);
-void inp_history_append(char *inp);
+char* inp_get_password(void);
#endif
diff --git a/src/ui/notifier.c b/src/ui/notifier.c
index 7ca8f705..76290daf 100644
--- a/src/ui/notifier.c
+++ b/src/ui/notifier.c
@@ -1,7 +1,7 @@
/*
* notifier.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -48,10 +48,10 @@
#include "log.h"
#include "muc.h"
#include "ui/ui.h"
+#include "ui/windows.h"
#include "config/preferences.h"
-static void _notify(const char * const message, int timeout,
- const char * const category);
+static void _notify(const char * const message, int timeout, const char * const category);
static GTimer *remind_timer;
@@ -89,7 +89,7 @@ notify_invite(const char * const from, const char * const room,
g_string_append(message, from);
g_string_append(message, "\nto: ");
g_string_append(message, room);
- if (reason != NULL) {
+ if (reason) {
g_string_append_printf(message, "\n\"%s\"", reason);
}
@@ -99,17 +99,25 @@ notify_invite(const char * const from, const char * const room,
}
void
-notify_message(const char * const handle, int win, const char * const text)
+notify_message(ProfWin *window, const char * const name, const char * const text)
{
- GString *message = g_string_new("");
- g_string_append_printf(message, "%s (win %d)", handle, win);
- if (text != NULL) {
- g_string_append_printf(message, "\n%s", text);
+ int num = wins_get_num(window);
+ if (num == 10) {
+ num = 0;
}
- _notify(message->str, 10000, "incoming message");
+ gboolean is_current = wins_is_current(window);
+ if (!is_current || (is_current && prefs_get_boolean(PREF_NOTIFY_MESSAGE_CURRENT)) ) {
+ GString *message = g_string_new("");
+ g_string_append_printf(message, "%s (win %d)", name, num);
- g_string_free(message, TRUE);
+ if (prefs_get_boolean(PREF_NOTIFY_MESSAGE_TEXT) && text) {
+ g_string_append_printf(message, "\n%s", text);
+ }
+
+ _notify(message->str, 10000, "incoming message");
+ g_string_free(message, TRUE);
+ }
}
void
@@ -117,7 +125,7 @@ notify_room_message(const char * const handle, const char * const room, int win,
{
GString *message = g_string_new("");
g_string_append_printf(message, "%s in %s (win %d)", handle, room, win);
- if (text != NULL) {
+ if (text) {
g_string_append_printf(message, "\n%s", text);
}
@@ -243,10 +251,9 @@ _notify(const char * const message, int timeout,
Shell_NotifyIcon(NIM_MODIFY, &nid);
#endif
#ifdef HAVE_OSXNOTIFY
- GString *notify_command = g_string_new("terminal-notifier -title \"Profanity\" -message \"");
+ GString *notify_command = g_string_new("terminal-notifier -title \"Profanity\" -message '");
- char *escaped_double = str_replace(message, "\"", "\\\"");
- char *escaped_single = str_replace(escaped_double, "`", "\\`");
+ char *escaped_single = str_replace(message, "'", "'\\''");
if (escaped_single[0] == '<') {
g_string_append(notify_command, "\\<");
@@ -264,8 +271,7 @@ _notify(const char * const message, int timeout,
g_string_append(notify_command, escaped_single);
}
- g_string_append(notify_command, "\"");
- free(escaped_double);
+ g_string_append(notify_command, "'");
free(escaped_single);
char *term_name = getenv("TERM_PROGRAM");
@@ -276,7 +282,7 @@ _notify(const char * const message, int timeout,
app_id = "com.googlecode.iterm2";
}
- if (app_id != NULL) {
+ if (app_id) {
g_string_append(notify_command, " -sender ");
g_string_append(notify_command, app_id);
}
@@ -288,4 +294,4 @@ _notify(const char * const message, int timeout,
g_string_free(notify_command, TRUE);
#endif
-}
\ No newline at end of file
+}
diff --git a/src/ui/occupantswin.c b/src/ui/occupantswin.c
index 429c2fdf..bba9d0b9 100644
--- a/src/ui/occupantswin.c
+++ b/src/ui/occupantswin.c
@@ -1,7 +1,7 @@
/*
* occupantswin.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -40,7 +40,7 @@
#include "config/preferences.h"
static void
-_occuptantswin_occupant(ProfLayoutSplit *layout, Occupant *occupant)
+_occuptantswin_occupant(ProfLayoutSplit *layout, Occupant *occupant, gboolean showjid)
{
const char *presence_str = string_from_resource_presence(occupant->presence);
theme_item_t presence_colour = theme_main_presence_attrs(presence_str);
@@ -51,6 +51,13 @@ _occuptantswin_occupant(ProfLayoutSplit *layout, Occupant *occupant)
win_printline_nowrap(layout->subwin, msg->str);
g_string_free(msg, TRUE);
+ if (showjid && occupant->jid) {
+ GString *msg = g_string_new(" ");
+ g_string_append(msg, occupant->jid);
+ win_printline_nowrap(layout->subwin, msg->str);
+ g_string_free(msg, TRUE);
+ }
+
wattroff(layout->subwin, theme_attrs(presence_colour));
}
@@ -74,7 +81,7 @@ occupantswin_occupants(const char * const roomjid)
while (roster_curr) {
Occupant *occupant = roster_curr->data;
if (occupant->role == MUC_ROLE_MODERATOR) {
- _occuptantswin_occupant(layout, occupant);
+ _occuptantswin_occupant(layout, occupant, mucwin->showjid);
}
roster_curr = g_list_next(roster_curr);
}
@@ -86,7 +93,7 @@ occupantswin_occupants(const char * const roomjid)
while (roster_curr) {
Occupant *occupant = roster_curr->data;
if (occupant->role == MUC_ROLE_PARTICIPANT) {
- _occuptantswin_occupant(layout, occupant);
+ _occuptantswin_occupant(layout, occupant, mucwin->showjid);
}
roster_curr = g_list_next(roster_curr);
}
@@ -98,7 +105,7 @@ occupantswin_occupants(const char * const roomjid)
while (roster_curr) {
Occupant *occupant = roster_curr->data;
if (occupant->role == MUC_ROLE_VISITOR) {
- _occuptantswin_occupant(layout, occupant);
+ _occuptantswin_occupant(layout, occupant, mucwin->showjid);
}
roster_curr = g_list_next(roster_curr);
}
@@ -109,7 +116,7 @@ occupantswin_occupants(const char * const roomjid)
GList *roster_curr = occupants;
while (roster_curr) {
Occupant *occupant = roster_curr->data;
- _occuptantswin_occupant(layout, occupant);
+ _occuptantswin_occupant(layout, occupant, mucwin->showjid);
roster_curr = g_list_next(roster_curr);
}
}
diff --git a/src/ui/rosterwin.c b/src/ui/rosterwin.c
index 828ed429..763490c3 100644
--- a/src/ui/rosterwin.c
+++ b/src/ui/rosterwin.c
@@ -1,7 +1,7 @@
/*
* rosterwin.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/ui/statusbar.c b/src/ui/statusbar.c
index 2ef20913..581e63df 100644
--- a/src/ui/statusbar.c
+++ b/src/ui/statusbar.c
@@ -1,7 +1,7 @@
/*
* statusbar.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -48,6 +48,7 @@
#include "ui/ui.h"
#include "ui/statusbar.h"
#include "ui/inputwin.h"
+#include "config/preferences.h"
#define TIME_CHECK 60000000
@@ -94,7 +95,7 @@ create_status_bar(void)
mvwprintw(status_bar, 0, cols - 34 + ((current - 1) * 3), bracket);
wattroff(status_bar, bracket_attrs);
- if (last_time != NULL) {
+ if (last_time) {
g_date_time_unref(last_time);
}
last_time = g_date_time_new_now_local();
@@ -126,10 +127,17 @@ status_bar_resize(void)
mvwprintw(status_bar, 0, cols - 34 + ((current - 1) * 3), bracket);
wattroff(status_bar, bracket_attrs);
- if (message != NULL) {
- mvwprintw(status_bar, 0, 10, message);
+ if (message) {
+ char *time_pref = prefs_get_string(PREF_TIME_STATUSBAR);
+ if (g_strcmp0(time_pref, "minutes") == 0) {
+ mvwprintw(status_bar, 0, 10, message);
+ } else if (g_strcmp0(time_pref, "seconds") == 0) {
+ mvwprintw(status_bar, 0, 13, message);
+ } else {
+ mvwprintw(status_bar, 0, 1, message);
+ }
}
- if (last_time != NULL) {
+ if (last_time) {
g_date_time_unref(last_time);
}
last_time = g_date_time_new_now_local();
@@ -192,7 +200,7 @@ status_bar_inactive(const int win)
is_new[11] = TRUE;
_mark_new(11);
- // still have active winsows
+ // still have active windows
} else if (g_hash_table_size(remaining_active) != 0) {
is_active[11] = TRUE;
is_new[11] = FALSE;
@@ -241,7 +249,7 @@ status_bar_active(const int win)
_mark_active(11);
}
- // visible winsow indicators
+ // visible window indicators
} else {
is_active[true_win] = TRUE;
is_new[true_win] = FALSE;
@@ -289,11 +297,19 @@ status_bar_print_message(const char * const msg)
{
werase(status_bar);
- if (message != NULL) {
+ if (message) {
free(message);
}
message = strdup(msg);
- mvwprintw(status_bar, 0, 10, message);
+
+ char *time_pref = prefs_get_string(PREF_TIME_STATUSBAR);
+ if (g_strcmp0(time_pref, "minutes") == 0) {
+ mvwprintw(status_bar, 0, 10, message);
+ } else if (g_strcmp0(time_pref, "seconds") == 0) {
+ mvwprintw(status_bar, 0, 13, message);
+ } else {
+ mvwprintw(status_bar, 0, 1, message);
+ }
int cols = getmaxx(stdscr);
int bracket_attrs = theme_attrs(THEME_STATUS_BRACKET);
@@ -309,7 +325,7 @@ status_bar_print_message(const char * const msg)
void
status_bar_clear(void)
{
- if (message != NULL) {
+ if (message) {
free(message);
message = NULL;
}
@@ -330,7 +346,7 @@ status_bar_clear(void)
void
status_bar_clear_message(void)
{
- if (message != NULL) {
+ if (message) {
free(message);
message = NULL;
}
@@ -412,23 +428,37 @@ _mark_inactive(int num)
static void
_status_bar_draw(void)
{
- if (last_time != NULL) {
+ if (last_time) {
g_date_time_unref(last_time);
}
last_time = g_date_time_new_now_local();
- gchar *date_fmt = g_date_time_format(last_time, "%H:%M");
- assert(date_fmt != NULL);
int bracket_attrs = theme_attrs(THEME_STATUS_BRACKET);
- wattron(status_bar, bracket_attrs);
- mvwaddch(status_bar, 0, 1, '[');
- wattroff(status_bar, bracket_attrs);
- mvwprintw(status_bar, 0, 2, date_fmt);
- wattron(status_bar, bracket_attrs);
- mvwaddch(status_bar, 0, 7, ']');
- wattroff(status_bar, bracket_attrs);
- g_free(date_fmt);
+ char *time_pref = prefs_get_string(PREF_TIME_STATUSBAR);
+ if (g_strcmp0(time_pref, "minutes") == 0) {
+ gchar *date_fmt = g_date_time_format(last_time, "%H:%M");
+ assert(date_fmt != NULL);
+ wattron(status_bar, bracket_attrs);
+ mvwaddch(status_bar, 0, 1, '[');
+ wattroff(status_bar, bracket_attrs);
+ mvwprintw(status_bar, 0, 2, date_fmt);
+ wattron(status_bar, bracket_attrs);
+ mvwaddch(status_bar, 0, 7, ']');
+ wattroff(status_bar, bracket_attrs);
+ g_free(date_fmt);
+ } else if (g_strcmp0(time_pref, "seconds") == 0) {
+ gchar *date_fmt = g_date_time_format(last_time, "%H:%M:%S");
+ assert(date_fmt != NULL);
+ wattron(status_bar, bracket_attrs);
+ mvwaddch(status_bar, 0, 1, '[');
+ wattroff(status_bar, bracket_attrs);
+ mvwprintw(status_bar, 0, 2, date_fmt);
+ wattron(status_bar, bracket_attrs);
+ mvwaddch(status_bar, 0, 10, ']');
+ wattroff(status_bar, bracket_attrs);
+ g_free(date_fmt);
+ }
_update_win_statuses();
wnoutrefresh(status_bar);
diff --git a/src/ui/statusbar.h b/src/ui/statusbar.h
index 5c37867b..7d2c5ea0 100644
--- a/src/ui/statusbar.h
+++ b/src/ui/statusbar.h
@@ -1,7 +1,7 @@
/*
* statusbar.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/ui/titlebar.c b/src/ui/titlebar.c
index 326dbf8b..9bb84f9d 100644
--- a/src/ui/titlebar.c
+++ b/src/ui/titlebar.c
@@ -1,7 +1,7 @@
/*
* titlebar.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -80,7 +80,7 @@ title_bar_update_virtual(void)
{
ProfWin *window = wins_get_current();
if (window->type != WIN_CONSOLE) {
- if (typing_elapsed != NULL) {
+ if (typing_elapsed) {
gdouble seconds = g_timer_elapsed(typing_elapsed, NULL);
if (seconds >= 10) {
@@ -109,8 +109,11 @@ void
title_bar_console(void)
{
werase(win);
- typing = FALSE;
+ if (typing_elapsed) {
+ g_timer_destroy(typing_elapsed);
+ }
typing_elapsed = NULL;
+ typing = FALSE;
_title_bar_draw();
}
@@ -125,7 +128,7 @@ title_bar_set_presence(contact_presence_t presence)
void
title_bar_switch(void)
{
- if (typing_elapsed != NULL) {
+ if (typing_elapsed) {
g_timer_destroy(typing_elapsed);
typing_elapsed = NULL;
typing = FALSE;
@@ -138,7 +141,7 @@ void
title_bar_set_typing(gboolean is_typing)
{
if (is_typing) {
- if (typing_elapsed != NULL) {
+ if (typing_elapsed) {
g_timer_start(typing_elapsed);
} else {
typing_elapsed = g_timer_new();
@@ -249,7 +252,7 @@ _show_privacy(ProfChatWin *chatwin)
{
int bracket_attrs = theme_attrs(THEME_TITLE_BRACKET);
- if (!chatwin->is_otr) {
+ if (chatwin->enc_mode == PROF_ENC_NONE) {
if (prefs_get_boolean(PREF_OTR_WARN)) {
int unencrypted_attrs = theme_attrs(THEME_TITLE_UNENCRYPTED);
wprintw(win, " ");
diff --git a/src/ui/titlebar.h b/src/ui/titlebar.h
index 08a56514..66237f86 100644
--- a/src/ui/titlebar.h
+++ b/src/ui/titlebar.h
@@ -1,7 +1,7 @@
/*
* titlebar.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 99e73b4a..0ee21be4 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -1,7 +1,7 @@
/*
* ui.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -59,9 +59,8 @@ void ui_close(void);
void ui_redraw(void);
void ui_resize(void);
GSList* ui_get_chat_recipients(void);
-gboolean ui_switch_win(const int i);
-void ui_next_win(void);
-void ui_previous_win(void);
+void ui_switch_win(ProfWin *window);
+void ui_sigwinch_handler(int sig);
void ui_gone_secure(const char * const barejid, gboolean trusted);
void ui_gone_insecure(const char * const barejid);
@@ -81,10 +80,12 @@ void ui_smp_answer_failure(const char * const barejid);
void ui_otr_authenticating(const char * const barejid);
void ui_otr_authetication_waiting(const char * const recipient);
+void ui_handle_otr_error(const char * const barejid, const char * const message);
+
unsigned long ui_get_idle_time(void);
void ui_reset_idle_time(void);
-void ui_new_chat_win(const char * const barejid);
-void ui_new_private_win(const char * const fulljid);
+ProfPrivateWin* ui_new_private_win(const char * const fulljid);
+ProfChatWin* ui_new_chat_win(const char * const barejid);
void ui_print_system_msg_from_recipient(const char * const barejid, const char *message);
gint ui_unread(void);
void ui_close_connected_win(int index);
@@ -94,7 +95,6 @@ int ui_close_read_wins(void);
// current window actions
void ui_clear_current(void);
win_type_t ui_current_win_type(void);
-int ui_current_win_index(void);
gboolean ui_current_win_is_otr(void);
ProfChatWin *ui_get_current_chat(void);
@@ -102,27 +102,28 @@ ProfChatWin *ui_get_current_chat(void);
void ui_current_print_line(const char * const msg, ...);
void ui_current_print_formatted_line(const char show_char, int attrs, const char * const msg, ...);
void ui_current_error_line(const char * const msg);
+void ui_win_error_line(ProfWin *window, const char * const msg);
win_type_t ui_win_type(int index);
void ui_close_win(int index);
-gboolean ui_win_exists(int index);
int ui_win_unread(int index);
char * ui_ask_password(void);
void ui_handle_stanza(const char * const msg);
// ui events
+void ui_contact_online(char *barejid, Resource *resource, GDateTime *last_activity);
void ui_contact_typing(const char * const barejid, const char * const resource);
void ui_incoming_msg(const char * const from, const char * const resource, const char * const message, GTimeVal *tv_stamp);
void ui_incoming_private_msg(const char * const fulljid, const char * const message, GTimeVal *tv_stamp);
+void ui_message_receipt(const char * const barejid, const char * const id);
void ui_disconnected(void);
void ui_recipient_gone(const char * const barejid, const char * const resource);
-void ui_outgoing_chat_msg(const char * const from, const char * const barejid,
- const char * const message);
-void ui_outgoing_private_msg(const char * const from, const char * const fulljid,
- const char * const message);
+void ui_outgoing_chat_msg(ProfChatWin *chatwin, const char * const message, char *id);
+void ui_outgoing_chat_msg_carbon(const char * const barejid, const char * const message);
+void ui_outgoing_private_msg(ProfPrivateWin *privwin, const char * const message);
void ui_room_join(const char * const roomjid, gboolean focus);
void ui_switch_to_room(const char * const roomjid);
@@ -171,6 +172,7 @@ void ui_room_member_nick_change(const char * const roomjid,
void ui_room_nick_change(const char * const roomjid, const char * const nick);
void ui_room_member_presence(const char * const roomjid,
const char * const nick, const char * const show, const char * const status);
+void ui_room_update_occupants(const char * const roomjid);
void ui_room_show_occupants(const char * const roomjid);
void ui_room_hide_occupants(const char * const roomjid);
void ui_show_roster(void);
@@ -218,6 +220,11 @@ void ui_tidy_wins(void);
void ui_prune_wins(void);
gboolean ui_swap_wins(int source_win, int target_win);
+void ui_page_up(void);
+void ui_page_down(void);
+void ui_subwin_page_up(void);
+void ui_subwin_page_down(void);
+
void ui_auto_away(void);
void ui_end_auto_away(void);
void ui_titlebar_presence(contact_presence_t presence);
@@ -227,9 +234,10 @@ void ui_update_presence(const resource_presence_t resource_presence,
void ui_about(void);
void ui_statusbar_new(const int win);
-char * ui_readline(void);
+char* ui_readline(void);
void ui_input_clear(void);
void ui_input_nonblocking(gboolean);
+void ui_write(char *line, int offset);
void ui_invalid_command_usage(const char * const usage, void (*setting_func)(void));
@@ -308,6 +316,8 @@ void cons_outtype_setting(void);
void cons_intype_setting(void);
void cons_gone_setting(void);
void cons_history_setting(void);
+void cons_carbons_setting(void);
+void cons_receipts_setting(void);
void cons_log_setting(void);
void cons_chlog_setting(void);
void cons_grlog_setting(void);
@@ -332,7 +342,7 @@ void notifier_initialise(void);
void notifier_uninit(void);
void notify_typing(const char * const handle);
-void notify_message(const char * const handle, int win, const char * const text);
+void notify_message(ProfWin *window, const char * const name, const char * const text);
void notify_room_message(const char * const handle, const char * const room,
int win, const char * const text);
void notify_remind(void);
diff --git a/src/ui/window.c b/src/ui/window.c
index 7757fe39..d2462a61 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1,7 +1,7 @@
/*
* window.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include
#ifdef HAVE_NCURSESW_NCURSES_H
@@ -59,7 +60,7 @@
#define CEILING(X) (X-(int)(X) > 0 ? (int)(X+1) : (int)(X))
static void _win_print(ProfWin *window, const char show_char, GDateTime *time,
- int flags, theme_item_t theme_item, const char * const from, const char * const message);
+ int flags, theme_item_t theme_item, const char * const from, const char * const message, DeliveryReceipt *receipt);
static void _win_print_wrapped(WINDOW *win, const char * const message);
int
@@ -134,7 +135,7 @@ win_create_chat(const char * const barejid)
new_win->barejid = strdup(barejid);
new_win->resource_override = NULL;
- new_win->is_otr = FALSE;
+ new_win->enc_mode = PROF_ENC_NONE;
new_win->is_trusted = FALSE;
new_win->history_shown = FALSE;
new_win->unread = 0;
@@ -177,6 +178,11 @@ win_create_muc(const char * const roomjid)
new_win->roomjid = strdup(roomjid);
new_win->unread = 0;
+ if (prefs_get_boolean(PREF_OCCUPANTS_JID)) {
+ new_win->showjid = TRUE;
+ } else {
+ new_win->showjid = FALSE;
+ }
new_win->memcheck = PROFMUCWIN_MEMCHECK;
@@ -331,12 +337,13 @@ win_free(ProfWin* window)
buffer_free(window->layout->buffer);
delwin(window->layout->win);
}
+ free(window->layout);
if (window->type == WIN_CHAT) {
ProfChatWin *chatwin = (ProfChatWin*)window;
free(chatwin->barejid);
free(chatwin->resource_override);
- free(chatwin->state);
+ chat_state_free(chatwin->state);
}
if (window->type == WIN_MUC) {
@@ -359,7 +366,101 @@ win_free(ProfWin* window)
}
void
-win_handle_page(ProfWin *window, const wint_t ch, const int result)
+win_page_up(ProfWin *window)
+{
+ int rows = getmaxy(stdscr);
+ int y = getcury(window->layout->win);
+ int page_space = rows - 4;
+ int *page_start = &(window->layout->y_pos);
+
+ *page_start -= page_space;
+
+ // went past beginning, show first page
+ if (*page_start < 0)
+ *page_start = 0;
+
+ window->layout->paged = 1;
+ win_update_virtual(window);
+
+ // switch off page if last line and space line visible
+ if ((y) - *page_start == page_space) {
+ window->layout->paged = 0;
+ }
+}
+
+void
+win_page_down(ProfWin *window)
+{
+ int rows = getmaxy(stdscr);
+ int y = getcury(window->layout->win);
+ int page_space = rows - 4;
+ int *page_start = &(window->layout->y_pos);
+
+ *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 - 1;
+
+ window->layout->paged = 1;
+ win_update_virtual(window);
+
+ // switch off page if last line and space line visible
+ if ((y) - *page_start == page_space) {
+ window->layout->paged = 0;
+ }
+}
+
+void
+win_sub_page_down(ProfWin *window)
+{
+
+ if (window->layout->type == LAYOUT_SPLIT) {
+ int rows = getmaxy(stdscr);
+ int page_space = rows - 4;
+ ProfLayoutSplit *split_layout = (ProfLayoutSplit*)window->layout;
+ int sub_y = getcury(split_layout->subwin);
+ int *sub_y_pos = &(split_layout->sub_y_pos);
+
+ *sub_y_pos += page_space;
+
+ // only got half a screen, show full screen
+ if ((sub_y- (*sub_y_pos)) < page_space)
+ *sub_y_pos = sub_y - page_space;
+
+ // went past end, show full screen
+ else if (*sub_y_pos >= sub_y)
+ *sub_y_pos = sub_y - page_space - 1;
+
+ win_update_virtual(window);
+ }
+}
+
+void
+win_sub_page_up(ProfWin *window)
+{
+ if (window->layout->type == LAYOUT_SPLIT) {
+ int rows = getmaxy(stdscr);
+ int page_space = rows - 4;
+ ProfLayoutSplit *split_layout = (ProfLayoutSplit*)window->layout;
+ int *sub_y_pos = &(split_layout->sub_y_pos);
+
+ *sub_y_pos -= page_space;
+
+ // went past beginning, show first page
+ if (*sub_y_pos < 0)
+ *sub_y_pos = 0;
+
+ win_update_virtual(window);
+ }
+}
+
+void
+win_mouse(ProfWin *window, const wint_t ch, const int result)
{
int rows = getmaxy(stdscr);
int y = getcury(window->layout->win);
@@ -403,69 +504,6 @@ win_handle_page(ProfWin *window, const wint_t ch, const int result)
}
}
}
-
- // page up
- if (ch == KEY_PPAGE) {
- *page_start -= page_space;
-
- // went past beginning, show first page
- if (*page_start < 0)
- *page_start = 0;
-
- window->layout->paged = 1;
- win_update_virtual(window);
-
- // 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 - 1;
-
- window->layout->paged = 1;
- win_update_virtual(window);
- }
-
- // switch off page if last line and space line visible
- if ((y) - *page_start == page_space) {
- window->layout->paged = 0;
- }
-
- if (window->layout->type == LAYOUT_SPLIT) {
- ProfLayoutSplit *split_layout = (ProfLayoutSplit*)window->layout;
- int sub_y = getcury(split_layout->subwin);
- int *sub_y_pos = &(split_layout->sub_y_pos);
-
- // alt up arrow
- if ((result == KEY_CODE_YES) && ((ch == 565) || (ch == 337))) {
- *sub_y_pos -= page_space;
-
- // went past beginning, show first page
- if (*sub_y_pos < 0)
- *sub_y_pos = 0;
-
- win_update_virtual(window);
-
- // alt down arrow
- } else if ((result == KEY_CODE_YES) && ((ch == 524) || (ch == 336))) {
- *sub_y_pos += page_space;
-
- // only got half a screen, show full screen
- if ((sub_y- (*sub_y_pos)) < page_space)
- *sub_y_pos = sub_y - page_space;
-
- // went past end, show full screen
- else if (*sub_y_pos >= sub_y)
- *sub_y_pos = sub_y - page_space - 1;
-
- win_update_virtual(window);
- }
- }
}
void
@@ -515,14 +553,14 @@ win_show_occupant(ProfWin *window, Occupant *occupant)
theme_item_t presence_colour = theme_main_presence_attrs(presence_str);
- win_save_print(window, '-', NULL, NO_EOL, presence_colour, "", occupant->nick);
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence_str);
+ win_print(window, '-', NULL, NO_EOL, presence_colour, "", occupant->nick);
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence_str);
if (occupant->status) {
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", occupant->status);
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", occupant->status);
}
- win_save_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
+ win_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
}
void
@@ -536,15 +574,15 @@ win_show_contact(ProfWin *window, PContact contact)
theme_item_t presence_colour = theme_main_presence_attrs(presence);
- if (name != NULL) {
- win_save_print(window, '-', NULL, NO_EOL, presence_colour, "", name);
+ if (name) {
+ win_print(window, '-', NULL, NO_EOL, presence_colour, "", name);
} else {
- win_save_print(window, '-', NULL, NO_EOL, presence_colour, "", barejid);
+ win_print(window, '-', NULL, NO_EOL, presence_colour, "", barejid);
}
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence);
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence);
- if (last_activity != NULL) {
+ if (last_activity) {
GDateTime *now = g_date_time_new_now_local();
GTimeSpan span = g_date_time_difference(now, last_activity);
@@ -555,18 +593,18 @@ win_show_contact(ProfWin *window, PContact contact)
int seconds = span / G_TIME_SPAN_SECOND;
if (hours > 0) {
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dh%dm%ds", hours, minutes, seconds);
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dh%dm%ds", hours, minutes, seconds);
}
else {
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dm%ds", minutes, seconds);
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dm%ds", minutes, seconds);
}
}
- if (status != NULL) {
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", p_contact_status(contact));
+ if (status) {
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", p_contact_status(contact));
}
- win_save_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
+ win_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
}
void
@@ -578,21 +616,21 @@ win_show_occupant_info(ProfWin *window, const char * const room, Occupant *occup
theme_item_t presence_colour = theme_main_presence_attrs(presence_str);
- win_save_print(window, '!', NULL, NO_EOL, presence_colour, "", occupant->nick);
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence_str);
+ win_print(window, '!', NULL, NO_EOL, presence_colour, "", occupant->nick);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", presence_str);
if (occupant->status) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", occupant->status);
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", occupant->status);
}
- win_save_newline(window);
+ win_newline(window);
if (occupant->jid) {
- win_save_vprint(window, '!', NULL, 0, 0, "", " Jid: %s", occupant->jid);
+ win_vprint(window, '!', NULL, 0, 0, "", " Jid: %s", occupant->jid);
}
- win_save_vprint(window, '!', NULL, 0, 0, "", " Affiliation: %s", occupant_affiliation);
- win_save_vprint(window, '!', NULL, 0, 0, "", " Role: %s", occupant_role);
+ win_vprint(window, '!', NULL, 0, 0, "", " Affiliation: %s", occupant_affiliation);
+ win_vprint(window, '!', NULL, 0, 0, "", " Role: %s", occupant_role);
Jid *jidp = jid_create_from_bare_and_resource(room, occupant->nick);
Capabilities *caps = caps_lookup(jidp->fulljid);
@@ -600,47 +638,47 @@ win_show_occupant_info(ProfWin *window, const char * const room, Occupant *occup
if (caps) {
// show identity
- if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) {
- win_save_print(window, '!', NULL, NO_EOL, 0, "", " Identity: ");
- if (caps->name != NULL) {
- win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
- if ((caps->category != NULL) || (caps->type != NULL)) {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
+ if (caps->category || caps->type || caps->name) {
+ win_print(window, '!', NULL, NO_EOL, 0, "", " Identity: ");
+ if (caps->name) {
+ win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
+ if (caps->category || caps->type) {
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
- if (caps->type != NULL) {
- win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
- if (caps->category != NULL) {
- win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", " ");
+ if (caps->type) {
+ win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
+ if (caps->category) {
+ win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
- if (caps->category != NULL) {
- win_save_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
+ if (caps->category) {
+ win_print(window, '!', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
}
- win_save_newline(window);
+ win_newline(window);
}
- if (caps->software != NULL) {
- win_save_vprint(window, '!', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
+ if (caps->software) {
+ win_vprint(window, '!', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
}
- if (caps->software_version != NULL) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
+ if (caps->software_version) {
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
}
- if ((caps->software != NULL) || (caps->software_version != NULL)) {
- win_save_newline(window);
+ if (caps->software || caps->software_version) {
+ win_newline(window);
}
- if (caps->os != NULL) {
- win_save_vprint(window, '!', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
+ if (caps->os) {
+ win_vprint(window, '!', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
}
- if (caps->os_version != NULL) {
- win_save_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
+ if (caps->os_version) {
+ win_vprint(window, '!', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
}
- if ((caps->os != NULL) || (caps->os_version != NULL)) {
- win_save_newline(window);
+ if (caps->os || caps->os_version) {
+ win_newline(window);
}
caps_destroy(caps);
}
- win_save_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, 0, 0, "", "");
}
void
@@ -650,24 +688,22 @@ win_show_info(ProfWin *window, PContact contact)
const char *name = p_contact_name(contact);
const char *presence = p_contact_presence(contact);
const char *sub = p_contact_subscription(contact);
- GList *resources = p_contact_get_available_resources(contact);
- GList *ordered_resources = NULL;
GDateTime *last_activity = p_contact_last_activity(contact);
theme_item_t presence_colour = theme_main_presence_attrs(presence);
- win_save_print(window, '-', NULL, 0, 0, "", "");
- win_save_print(window, '-', NULL, NO_EOL, presence_colour, "", barejid);
- if (name != NULL) {
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (%s)", name);
+ win_print(window, '-', NULL, 0, 0, "", "");
+ win_print(window, '-', NULL, NO_EOL, presence_colour, "", barejid);
+ if (name) {
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " (%s)", name);
}
- win_save_print(window, '-', NULL, NO_DATE, 0, "", ":");
+ win_print(window, '-', NULL, NO_DATE, 0, "", ":");
- if (sub != NULL) {
- win_save_vprint(window, '-', NULL, 0, 0, "", "Subscription: %s", sub);
+ if (sub) {
+ win_vprint(window, '-', NULL, 0, 0, "", "Subscription: %s", sub);
}
- if (last_activity != NULL) {
+ if (last_activity) {
GDateTime *now = g_date_time_new_now_local();
GTimeSpan span = g_date_time_difference(now, last_activity);
@@ -678,36 +714,41 @@ win_show_info(ProfWin *window, PContact contact)
int seconds = span / G_TIME_SPAN_SECOND;
if (hours > 0) {
- win_save_vprint(window, '-', NULL, 0, 0, "", "Last activity: %dh%dm%ds", hours, minutes, seconds);
+ win_vprint(window, '-', NULL, 0, 0, "", "Last activity: %dh%dm%ds", hours, minutes, seconds);
}
else {
- win_save_vprint(window, '-', NULL, 0, 0, "", "Last activity: %dm%ds", minutes, seconds);
+ win_vprint(window, '-', NULL, 0, 0, "", "Last activity: %dm%ds", minutes, seconds);
}
g_date_time_unref(now);
}
- if (resources != NULL) {
- win_save_print(window, '-', NULL, 0, 0, "", "Resources:");
+ GList *resources = p_contact_get_available_resources(contact);
+ GList *ordered_resources = NULL;
+ if (resources) {
+ win_print(window, '-', NULL, 0, 0, "", "Resources:");
- // sort in order of availabiltiy
- while (resources != NULL) {
- Resource *resource = resources->data;
+ // sort in order of availability
+ GList *curr = resources;
+ while (curr) {
+ Resource *resource = curr->data;
ordered_resources = g_list_insert_sorted(ordered_resources,
resource, (GCompareFunc)resource_compare_availability);
- resources = g_list_next(resources);
+ curr = g_list_next(curr);
}
}
+ g_list_free(resources);
- while (ordered_resources != NULL) {
- Resource *resource = ordered_resources->data;
+ GList *curr = ordered_resources;
+ while (curr) {
+ Resource *resource = curr->data;
const char *resource_presence = string_from_resource_presence(resource->presence);
theme_item_t presence_colour = theme_main_presence_attrs(resource_presence);
- win_save_vprint(window, '-', NULL, NO_EOL, presence_colour, "", " %s (%d), %s", resource->name, resource->priority, resource_presence);
- if (resource->status != NULL) {
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", resource->status);
+ win_vprint(window, '-', NULL, NO_EOL, presence_colour, "", " %s (%d), %s", resource->name, resource->priority, resource_presence);
+ if (resource->status) {
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", resource->status);
}
- win_save_newline(window);
+ win_newline(window);
Jid *jidp = jid_create_from_bare_and_resource(barejid, resource->name);
Capabilities *caps = caps_lookup(jidp->fulljid);
@@ -715,48 +756,49 @@ win_show_info(ProfWin *window, PContact contact)
if (caps) {
// show identity
- if ((caps->category != NULL) || (caps->type != NULL) || (caps->name != NULL)) {
- win_save_print(window, '-', NULL, NO_EOL, 0, "", " Identity: ");
- if (caps->name != NULL) {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
- if ((caps->category != NULL) || (caps->type != NULL)) {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
+ if (caps->category || caps->type || caps->name) {
+ win_print(window, '-', NULL, NO_EOL, 0, "", " Identity: ");
+ if (caps->name) {
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->name);
+ if (caps->category || caps->type) {
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
- if (caps->type != NULL) {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
- if (caps->category != NULL) {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
+ if (caps->type) {
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->type);
+ if (caps->category) {
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", " ");
}
}
- if (caps->category != NULL) {
- win_save_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
+ if (caps->category) {
+ win_print(window, '-', NULL, NO_DATE | NO_EOL, 0, "", caps->category);
}
- win_save_newline(window);
+ win_newline(window);
}
- if (caps->software != NULL) {
- win_save_vprint(window, '-', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
+ if (caps->software) {
+ win_vprint(window, '-', NULL, NO_EOL, 0, "", " Software: %s", caps->software);
}
- if (caps->software_version != NULL) {
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
+ if (caps->software_version) {
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->software_version);
}
- if ((caps->software != NULL) || (caps->software_version != NULL)) {
- win_save_newline(window);
+ if (caps->software || caps->software_version) {
+ win_newline(window);
}
- if (caps->os != NULL) {
- win_save_vprint(window, '-', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
+ if (caps->os) {
+ win_vprint(window, '-', NULL, NO_EOL, 0, "", " OS: %s", caps->os);
}
- if (caps->os_version != NULL) {
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
+ if (caps->os_version) {
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, 0, "", ", %s", caps->os_version);
}
- if ((caps->os != NULL) || (caps->os_version != NULL)) {
- win_save_newline(window);
+ if (caps->os || caps->os_version) {
+ win_newline(window);
}
caps_destroy(caps);
}
- ordered_resources = g_list_next(ordered_resources);
+ curr = g_list_next(curr);
}
+ g_list_free(ordered_resources);
}
void
@@ -767,7 +809,7 @@ win_show_status_string(ProfWin *window, const char * const from,
{
theme_item_t presence_colour;
- if (show != NULL) {
+ if (show) {
presence_colour = theme_main_presence_attrs(show);
} else if (strcmp(default_show, "online") == 0) {
presence_colour = THEME_ONLINE;
@@ -776,14 +818,14 @@ win_show_status_string(ProfWin *window, const char * const from,
}
- win_save_vprint(window, '-', NULL, NO_EOL, presence_colour, "", "%s %s", pre, from);
+ win_vprint(window, '-', NULL, NO_EOL, presence_colour, "", "%s %s", pre, from);
- if (show != NULL)
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", show);
+ if (show)
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", show);
else
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", default_show);
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", " is %s", default_show);
- if (last_activity != NULL) {
+ if (last_activity) {
GDateTime *now = g_date_time_new_now_local();
GTimeSpan span = g_date_time_difference(now, last_activity);
g_date_time_unref(now);
@@ -795,17 +837,17 @@ win_show_status_string(ProfWin *window, const char * const from,
int seconds = span / G_TIME_SPAN_SECOND;
if (hours > 0) {
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dh%dm%ds", hours, minutes, seconds);
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dh%dm%ds", hours, minutes, seconds);
}
else {
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dm%ds", minutes, seconds);
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", idle %dm%ds", minutes, seconds);
}
}
- if (status != NULL)
- win_save_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", status);
+ if (status)
+ win_vprint(window, '-', NULL, NO_DATE | NO_EOL, presence_colour, "", ", \"%s\"", status);
- win_save_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
+ win_print(window, '-', NULL, NO_DATE, presence_colour, "", "");
}
@@ -817,7 +859,7 @@ win_print_incoming_message(ProfWin *window, GTimeVal *tv_stamp,
{
case WIN_CHAT:
case WIN_PRIVATE:
- win_save_print(window, '-', tv_stamp, NO_ME, THEME_TEXT_THEM, from, message);
+ win_print(window, '-', tv_stamp, NO_ME, THEME_TEXT_THEM, from, message);
break;
default:
assert(FALSE);
@@ -826,19 +868,19 @@ win_print_incoming_message(ProfWin *window, GTimeVal *tv_stamp,
}
void
-win_save_vprint(ProfWin *window, const char show_char, GTimeVal *tstamp,
+win_vprint(ProfWin *window, const char show_char, GTimeVal *tstamp,
int flags, theme_item_t theme_item, const char * const from, const char * const message, ...)
{
va_list arg;
va_start(arg, message);
GString *fmt_msg = g_string_new(NULL);
g_string_vprintf(fmt_msg, message, arg);
- win_save_print(window, show_char, tstamp, flags, theme_item, from, fmt_msg->str);
+ win_print(window, show_char, tstamp, flags, theme_item, from, fmt_msg->str);
g_string_free(fmt_msg, TRUE);
}
void
-win_save_print(ProfWin *window, const char show_char, GTimeVal *tstamp,
+win_print(ProfWin *window, const char show_char, GTimeVal *tstamp,
int flags, theme_item_t theme_item, const char * const from, const char * const message)
{
GDateTime *time;
@@ -849,27 +891,58 @@ win_save_print(ProfWin *window, const char show_char, GTimeVal *tstamp,
time = g_date_time_new_from_timeval_utc(tstamp);
}
- buffer_push(window->layout->buffer, show_char, time, flags, theme_item, from, message);
- _win_print(window, show_char, time, flags, theme_item, from, message);
+ buffer_push(window->layout->buffer, show_char, time, flags, theme_item, from, message, NULL);
+ _win_print(window, show_char, time, flags, theme_item, from, message, NULL);
// TODO: cross-reference.. this should be replaced by a real event-based system
ui_input_nonblocking(TRUE);
}
void
-win_save_println(ProfWin *window, const char * const message)
+win_print_with_receipt(ProfWin *window, const char show_char, GTimeVal *tstamp,
+ int flags, theme_item_t theme_item, const char * const from, const char * const message, char *id)
{
- win_save_print(window, '-', NULL, 0, 0, "", message);
+ GDateTime *time;
+
+ if (tstamp == NULL) {
+ time = g_date_time_new_now_local();
+ } else {
+ time = g_date_time_new_from_timeval_utc(tstamp);
+ }
+
+ DeliveryReceipt *receipt = malloc(sizeof(struct delivery_receipt_t));
+ receipt->id = strdup(id);
+ receipt->received = FALSE;
+
+ buffer_push(window->layout->buffer, show_char, time, flags, theme_item, from, message, receipt);
+ _win_print(window, show_char, time, flags, theme_item, from, message, receipt);
+ // TODO: cross-reference.. this should be replaced by a real event-based system
+ ui_input_nonblocking(TRUE);
}
void
-win_save_newline(ProfWin *window)
+win_mark_received(ProfWin *window, const char * const id)
{
- win_save_print(window, '-', NULL, NO_DATE, 0, "", "");
+ gboolean received = buffer_mark_received(window->layout->buffer, id);
+ if (received) {
+ win_redraw(window);
+ }
+}
+
+void
+win_println(ProfWin *window, const char * const message)
+{
+ win_print(window, '-', NULL, 0, 0, "", message);
+}
+
+void
+win_newline(ProfWin *window)
+{
+ win_print(window, '-', NULL, NO_DATE, 0, "", "");
}
static void
_win_print(ProfWin *window, const char show_char, GDateTime *time,
- int flags, theme_item_t theme_item, const char * const from, const char * const message)
+ int flags, theme_item_t theme_item, const char * const from, const char * const message, DeliveryReceipt *receipt)
{
// flags : 1st bit = 0/1 - me/not me
// 2nd bit = 0/1 - date/no date
@@ -907,6 +980,10 @@ _win_print(ProfWin *window, const char show_char, GDateTime *time,
colour = 0;
}
+ if (receipt && !receipt->received) {
+ colour = theme_attrs(THEME_RECEIPT_SENT);
+ }
+
wattron(window->layout->win, colour);
if (strncmp(message, "/me ", 4) == 0) {
wprintw(window->layout->win, "*%s ", from);
@@ -919,7 +996,11 @@ _win_print(ProfWin *window, const char show_char, GDateTime *time,
}
if (!me_message) {
- wattron(window->layout->win, theme_attrs(theme_item));
+ if (receipt && !receipt->received) {
+ wattron(window->layout->win, theme_attrs(THEME_RECEIPT_SENT));
+ } else {
+ wattron(window->layout->win, theme_attrs(theme_item));
+ }
}
if (prefs_get_boolean(PREF_WRAP)) {
@@ -935,7 +1016,11 @@ _win_print(ProfWin *window, const char show_char, GDateTime *time,
if (me_message) {
wattroff(window->layout->win, colour);
} else {
- wattroff(window->layout->win, theme_attrs(theme_item));
+ if (receipt && !receipt->received) {
+ wattroff(window->layout->win, theme_attrs(THEME_RECEIPT_SENT));
+ } else {
+ wattroff(window->layout->win, theme_attrs(theme_item));
+ }
}
}
@@ -951,7 +1036,6 @@ _win_indent(WINDOW *win, int size)
static void
_win_print_wrapped(WINDOW *win, const char * const message)
{
- int linei = 0;
int wordi = 0;
char *word = malloc(strlen(message) + 1);
@@ -964,18 +1048,26 @@ _win_print_wrapped(WINDOW *win, const char * const message)
}
free(time_pref);
- while (message[linei] != '\0') {
- if (message[linei] == ' ') {
+ gchar *curr_ch = g_utf8_offset_to_pointer(message, 0);
+
+ while (*curr_ch != '\0') {
+ if (*curr_ch == ' ') {
waddch(win, ' ');
- linei++;
- } else if (message[linei] == '\n') {
+ curr_ch = g_utf8_next_char(curr_ch);
+ } else if (*curr_ch == '\n') {
waddch(win, '\n');
_win_indent(win, indent);
- linei++;
+ curr_ch = g_utf8_next_char(curr_ch);
} else {
+ // get word
wordi = 0;
- while (message[linei] != ' ' && message[linei] != '\n' && message[linei] != '\0') {
- word[wordi++] = message[linei++];
+ while (*curr_ch != ' ' && *curr_ch != '\n' && *curr_ch != '\0') {
+ size_t ch_len = mbrlen(curr_ch, 4, NULL);
+ int offset = 0;
+ while (offset < ch_len) {
+ word[wordi++] = curr_ch[offset++];
+ }
+ curr_ch = g_utf8_next_char(curr_ch);
}
word[wordi] = '\0';
@@ -983,17 +1075,27 @@ _win_print_wrapped(WINDOW *win, const char * const message)
int maxx = getmaxx(win);
// word larger than line
- if (strlen(word) > (maxx - indent)) {
- int i;
- for (i = 0; i < wordi; i++) {
+ if (utf8_display_len(word) > (maxx - indent)) {
+ gchar *word_ch = g_utf8_offset_to_pointer(word, 0);
+ while(*word_ch != '\0') {
curx = getcurx(win);
if (curx < indent) {
_win_indent(win, indent);
}
- waddch(win, word[i]);
+
+ gchar copy[wordi++];
+ g_utf8_strncpy(copy, word_ch, 1);
+
+ if (curx + utf8_display_len(copy) > maxx) {
+ waddch(win, '\n');
+ _win_indent(win, indent);
+ }
+ waddstr(win, copy);
+
+ word_ch = g_utf8_next_char(word_ch);
}
} else {
- if (curx + strlen(word) > maxx) {
+ if (curx + utf8_display_len(word) > maxx) {
waddch(win, '\n');
_win_indent(win, indent);
}
@@ -1017,7 +1119,7 @@ win_redraw(ProfWin *window)
for (i = 0; i < size; i++) {
ProfBuffEntry *e = buffer_yield_entry(window->layout->buffer, i);
- _win_print(window, e->show_char, e->time, e->flags, e->theme_item, e->from, e->message);
+ _win_print(window, e->show_char, e->time, e->flags, e->theme_item, e->from, e->message, e->receipt);
}
}
diff --git a/src/ui/window.h b/src/ui/window.h
index fd10a1d7..d5e57971 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -1,7 +1,7 @@
/*
* window.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -99,6 +99,11 @@ typedef enum {
WIN_XML
} win_type_t;
+typedef enum {
+ PROF_ENC_NONE,
+ PROF_ENC_OTR
+} prof_enc_t;
+
typedef struct prof_win_t {
win_type_t type;
ProfLayout *layout;
@@ -113,7 +118,7 @@ typedef struct prof_chat_win_t {
char *barejid;
int unread;
ChatState *state;
- gboolean is_otr;
+ prof_enc_t enc_mode;
gboolean is_trusted;
char *resource_override;
gboolean history_shown;
@@ -124,6 +129,7 @@ typedef struct prof_muc_win_t {
ProfWin window;
char *roomjid;
int unread;
+ gboolean showjid;
unsigned long memcheck;
} ProfMucWin;
@@ -168,19 +174,27 @@ void win_print_incoming_message(ProfWin *window, GTimeVal *tv_stamp,
const char * const from, const char * const message);
void win_show_info(ProfWin *window, PContact contact);
void win_show_occupant_info(ProfWin *window, const char * const room, Occupant *occupant);
-void win_save_vprint(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message, ...);
-void win_save_print(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message);
-void win_save_println(ProfWin *window, const char * const message);
-void win_save_newline(ProfWin *window);
+void win_vprint(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message, ...);
+void win_print(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags, theme_item_t theme_item, const char * const from, const char * const message);
+void win_print_with_receipt(ProfWin *window, const char show_char, GTimeVal *tstamp, int flags,
+ theme_item_t theme_item, const char * const from, const char * const message, char *id);
+void win_println(ProfWin *window, const char * const message);
+void win_newline(ProfWin *window);
void win_redraw(ProfWin *window);
void win_hide_subwin(ProfWin *window);
void win_show_subwin(ProfWin *window);
int win_roster_cols(void);
int win_occpuants_cols(void);
void win_printline_nowrap(WINDOW *win, char *msg);
-void win_handle_page(ProfWin *current, const wint_t ch, const int result);
+void win_mouse(ProfWin *current, const wint_t ch, const int result);
+void win_mark_received(ProfWin *window, const char * const id);
int win_unread(ProfWin *window);
gboolean win_has_active_subwin(ProfWin *window);
+void win_page_up(ProfWin *window);
+void win_page_down(ProfWin *window);
+void win_sub_page_down(ProfWin *window);
+void win_sub_page_up(ProfWin *window);
+
#endif
diff --git a/src/ui/windows.c b/src/ui/windows.c
index 5ecada12..2334efc8 100644
--- a/src/ui/windows.c
+++ b/src/ui/windows.c
@@ -1,7 +1,7 @@
/*
* windows.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -53,6 +53,7 @@
#include "ui/statusbar.h"
#include "ui/window.h"
#include "ui/windows.h"
+#include "event/ui_events.h"
static GHashTable *windows;
static int current;
@@ -83,7 +84,7 @@ wins_get_chat(const char * const barejid)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_CHAT) {
ProfChatWin *chatwin = (ProfChatWin*)window;
@@ -105,7 +106,7 @@ wins_get_muc_conf(const char * const roomjid)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_MUC_CONFIG) {
ProfMucConfWin *confwin = (ProfMucConfWin*)window;
@@ -127,11 +128,12 @@ wins_get_muc(const char * const roomjid)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_MUC) {
ProfMucWin *mucwin = (ProfMucWin*)window;
if (g_strcmp0(mucwin->roomjid, roomjid) == 0) {
+ g_list_free(values);
return mucwin;
}
}
@@ -148,11 +150,12 @@ wins_get_private(const char * const fulljid)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_PRIVATE) {
ProfPrivateWin *privatewin = (ProfPrivateWin*)window;
if (g_strcmp0(privatewin->fulljid, fulljid) == 0) {
+ g_list_free(values);
return privatewin;
}
}
@@ -166,7 +169,7 @@ wins_get_private(const char * const fulljid)
ProfWin *
wins_get_current(void)
{
- if (windows != NULL) {
+ if (windows) {
return g_hash_table_lookup(windows, GINT_TO_POINTER(current));
} else {
return NULL;
@@ -283,7 +286,7 @@ wins_get_next(void)
GList *curr = keys;
// find our place in the list
- while (curr != NULL) {
+ while (curr) {
if (current == GPOINTER_TO_INT(curr->data)) {
break;
}
@@ -292,7 +295,7 @@ wins_get_next(void)
// if there is a next window return it
curr = g_list_next(curr);
- if (curr != NULL) {
+ if (curr) {
int next = GPOINTER_TO_INT(curr->data);
g_list_free(keys);
return wins_get_by_num(next);
@@ -312,7 +315,7 @@ wins_get_previous(void)
GList *curr = keys;
// find our place in the list
- while (curr != NULL) {
+ while (curr) {
if (current == GPOINTER_TO_INT(curr->data)) {
break;
}
@@ -321,7 +324,7 @@ wins_get_previous(void)
// if there is a previous window return it
curr = g_list_previous(curr);
- if (curr != NULL) {
+ if (curr) {
int previous = GPOINTER_TO_INT(curr->data);
g_list_free(keys);
return wins_get_by_num(previous);
@@ -339,7 +342,7 @@ wins_get_num(ProfWin *window)
GList *keys = g_hash_table_get_keys(windows);
GList *curr = keys;
- while (curr != NULL) {
+ while (curr) {
gconstpointer num_p = curr->data;
ProfWin *curr_win = g_hash_table_lookup(windows, num_p);
if (curr_win == window) {
@@ -408,9 +411,9 @@ wins_new_xmlconsole(void)
{
GList *keys = g_hash_table_get_keys(windows);
int result = get_next_available_win_num(keys);
+ g_list_free(keys);
ProfWin *newwin = win_create_xmlconsole();
g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
- g_list_free(keys);
return newwin;
}
@@ -419,9 +422,9 @@ wins_new_chat(const char * const barejid)
{
GList *keys = g_hash_table_get_keys(windows);
int result = get_next_available_win_num(keys);
+ g_list_free(keys);
ProfWin *newwin = win_create_chat(barejid);
g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
- g_list_free(keys);
return newwin;
}
@@ -430,9 +433,9 @@ wins_new_muc(const char * const roomjid)
{
GList *keys = g_hash_table_get_keys(windows);
int result = get_next_available_win_num(keys);
+ g_list_free(keys);
ProfWin *newwin = win_create_muc(roomjid);
g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
- g_list_free(keys);
return newwin;
}
@@ -441,9 +444,9 @@ wins_new_muc_config(const char * const roomjid, DataForm *form)
{
GList *keys = g_hash_table_get_keys(windows);
int result = get_next_available_win_num(keys);
+ g_list_free(keys);
ProfWin *newwin = win_create_muc_config(roomjid, form);
g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
- g_list_free(keys);
return newwin;
}
@@ -452,9 +455,9 @@ wins_new_private(const char * const fulljid)
{
GList *keys = g_hash_table_get_keys(windows);
int result = get_next_available_win_num(keys);
+ g_list_free(keys);
ProfWin *newwin = win_create_private(fulljid);
g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
- g_list_free(keys);
return newwin;
}
@@ -465,7 +468,7 @@ wins_get_total_unread(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = curr->data;
result += win_unread(window);
curr = g_list_next(curr);
@@ -481,7 +484,7 @@ wins_resize_all(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = curr->data;
int subwin_cols = 0;
@@ -495,7 +498,13 @@ wins_resize_all(void)
}
wresize(layout->base.win, PAD_SIZE, cols - subwin_cols);
wresize(layout->subwin, PAD_SIZE, subwin_cols);
- rosterwin_roster();
+ if (window->type == WIN_CONSOLE) {
+ rosterwin_roster();
+ } else if (window->type == WIN_MUC) {
+ ProfMucWin *mucwin = (ProfMucWin *)window;
+ assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
+ occupantswin_occupants(mucwin->roomjid);
+ }
} else {
wresize(layout->base.win, PAD_SIZE, cols);
}
@@ -555,7 +564,7 @@ wins_get_xmlconsole(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_XML) {
ProfXMLWin *xmlwin = (ProfXMLWin*)window;
@@ -577,7 +586,7 @@ wins_get_chat_recipients(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = curr->data;
if (window->type == WIN_CHAT) {
ProfChatWin *chatwin = (ProfChatWin*)window;
@@ -596,7 +605,7 @@ wins_get_prune_wins(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = curr->data;
if (win_unread(window) == 0 &&
window->type != WIN_MUC &&
@@ -617,10 +626,10 @@ wins_lost_connection(void)
GList *values = g_hash_table_get_values(windows);
GList *curr = values;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = curr->data;
if (window->type != WIN_CONSOLE) {
- win_save_print(window, '-', NULL, 0, THEME_ERROR, "", "Lost connection.");
+ win_print(window, '-', NULL, 0, THEME_ERROR, "", "Lost connection.");
// if current win, set current_win_dirty
if (wins_is_current(window)) {
@@ -636,22 +645,24 @@ gboolean
wins_swap(int source_win, int target_win)
{
ProfWin *source = g_hash_table_lookup(windows, GINT_TO_POINTER(source_win));
+ ProfWin *console = wins_get_console();
- if (source != NULL) {
+ if (source) {
ProfWin *target = g_hash_table_lookup(windows, GINT_TO_POINTER(target_win));
// target window empty
- if (target == NULL) {
+ if (!target) {
g_hash_table_steal(windows, GINT_TO_POINTER(source_win));
- status_bar_inactive(source_win);
g_hash_table_insert(windows, GINT_TO_POINTER(target_win), source);
+ status_bar_inactive(source_win);
if (win_unread(source) > 0) {
status_bar_new(target_win);
} else {
status_bar_active(target_win);
}
- if ((wins_get_current_num() == source_win) || (wins_get_current_num() == target_win)) {
- ui_switch_win(1);
+ if (wins_get_current_num() == source_win) {
+ wins_set_current_by_num(target_win);
+ ui_ev_focus_win(console);
}
return TRUE;
@@ -672,7 +683,7 @@ wins_swap(int source_win, int target_win)
status_bar_active(source_win);
}
if ((wins_get_current_num() == source_win) || (wins_get_current_num() == target_win)) {
- ui_switch_win(1);
+ ui_ev_focus_win(console);
}
return TRUE;
}
@@ -708,7 +719,7 @@ wins_tidy(void)
int num = 1;
GList *curr = keys;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = g_hash_table_lookup(windows, curr->data);
if (num == 10) {
g_hash_table_insert(new_windows, GINT_TO_POINTER(0), window);
@@ -731,7 +742,8 @@ wins_tidy(void)
windows = new_windows;
current = 1;
- ui_switch_win(1);
+ ProfWin *console = wins_get_console();
+ ui_ev_focus_win(console);
g_list_free(keys);
return TRUE;
} else {
@@ -749,7 +761,7 @@ wins_create_summary(void)
keys = g_list_sort(keys, cmp_win_num);
GList *curr = keys;
- while (curr != NULL) {
+ while (curr) {
ProfWin *window = g_hash_table_lookup(windows, curr->data);
int ui_index = GPOINTER_TO_INT(curr->data);
diff --git a/src/ui/windows.h b/src/ui/windows.h
index c144a5a2..97183d51 100644
--- a/src/ui/windows.h
+++ b/src/ui/windows.h
@@ -1,7 +1,7 @@
/*
* windows.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/xmpp/bookmark.c b/src/xmpp/bookmark.c
index 94adabea..68e66569 100644
--- a/src/xmpp/bookmark.c
+++ b/src/xmpp/bookmark.c
@@ -1,7 +1,7 @@
/*
* bookmark.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -42,7 +42,7 @@
#include "common.h"
#include "log.h"
#include "muc.h"
-#include "server_events.h"
+#include "event/server_events.h"
#include "xmpp/connection.h"
#include "xmpp/stanza.h"
#include "xmpp/xmpp.h"
@@ -74,7 +74,7 @@ bookmark_request(void)
autocomplete_free(bookmark_ac);
bookmark_ac = autocomplete_new();
- if (bookmark_list != NULL) {
+ if (bookmark_list) {
g_list_free_full(bookmark_list, _bookmark_item_destroy);
bookmark_list = NULL;
}
@@ -96,12 +96,12 @@ bookmark_add(const char *jid, const char *nick, const char *password, const char
} else {
Bookmark *item = malloc(sizeof(*item));
item->jid = strdup(jid);
- if (nick != NULL) {
+ if (nick) {
item->nick = strdup(nick);
} else {
item->nick = NULL;
}
- if (password != NULL) {
+ if (password) {
item->password = strdup(password);
} else {
item->password = NULL;
@@ -136,15 +136,15 @@ bookmark_update(const char *jid, const char *nick, const char *password, const c
return FALSE;
} else {
Bookmark *bm = found->data;
- if (nick != NULL) {
+ if (nick) {
free(bm->nick);
bm->nick = strdup(nick);
}
- if (password != NULL) {
+ if (password) {
free(bm->password);
bm->password = strdup(password);
}
- if (autojoin_str != NULL) {
+ if (autojoin_str) {
if (g_strcmp0(autojoin_str, "on") == 0) {
bm->autojoin = TRUE;
} else if (g_strcmp0(autojoin_str, "off") == 0) {
@@ -228,7 +228,7 @@ bookmark_find(const char * const search_str)
void
bookmark_autocomplete_reset(void)
{
- if (bookmark_ac != NULL) {
+ if (bookmark_ac) {
autocomplete_reset(bookmark_ac);
}
}
@@ -413,14 +413,14 @@ _send_bookmarks(void)
xmpp_stanza_set_ns(storage, "storage:bookmarks");
GList *curr = bookmark_list;
- while (curr != NULL) {
+ while (curr) {
Bookmark *bookmark = curr->data;
xmpp_stanza_t *conference = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(conference, STANZA_NAME_CONFERENCE);
xmpp_stanza_set_attribute(conference, STANZA_ATTR_JID, bookmark->jid);
Jid *jidp = jid_create(bookmark->jid);
- if (jidp->localpart != NULL) {
+ if (jidp->localpart) {
xmpp_stanza_set_attribute(conference, STANZA_ATTR_NAME, jidp->localpart);
}
jid_destroy(jidp);
@@ -431,7 +431,7 @@ _send_bookmarks(void)
xmpp_stanza_set_attribute(conference, STANZA_ATTR_AUTOJOIN, "false");
}
- if (bookmark->nick != NULL) {
+ if (bookmark->nick) {
xmpp_stanza_t *nick_st = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(nick_st, STANZA_NAME_NICK);
xmpp_stanza_t *nick_text = xmpp_stanza_new(ctx);
@@ -443,7 +443,7 @@ _send_bookmarks(void)
xmpp_stanza_release(nick_st);
}
- if (bookmark->password != NULL) {
+ if (bookmark->password) {
xmpp_stanza_t *password_st = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(password_st, STANZA_NAME_PASSWORD);
xmpp_stanza_t *password_text = xmpp_stanza_new(ctx);
diff --git a/src/xmpp/bookmark.h b/src/xmpp/bookmark.h
index f9392182..c8de8147 100644
--- a/src/xmpp/bookmark.h
+++ b/src/xmpp/bookmark.h
@@ -1,7 +1,7 @@
/*
* bookmark.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/xmpp/capabilities.c b/src/xmpp/capabilities.c
index 164313e1..56475da1 100644
--- a/src/xmpp/capabilities.c
+++ b/src/xmpp/capabilities.c
@@ -1,7 +1,7 @@
/*
* capabilities.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -154,56 +154,56 @@ _caps_by_ver(const char * const ver)
char *category = g_key_file_get_string(cache, ver, "category", NULL);
if (category) {
- new_caps->category = strdup(category);
+ new_caps->category = category;
} else {
new_caps->category = NULL;
}
char *type = g_key_file_get_string(cache, ver, "type", NULL);
if (type) {
- new_caps->type = strdup(type);
+ new_caps->type = type;
} else {
new_caps->type = NULL;
}
char *name = g_key_file_get_string(cache, ver, "name", NULL);
if (name) {
- new_caps->name = strdup(name);
+ new_caps->name = name;
} else {
new_caps->name = NULL;
}
char *software = g_key_file_get_string(cache, ver, "software", NULL);
if (software) {
- new_caps->software = strdup(software);
+ new_caps->software = software;
} else {
new_caps->software = NULL;
}
char *software_version = g_key_file_get_string(cache, ver, "software_version", NULL);
if (software_version) {
- new_caps->software_version = strdup(software_version);
+ new_caps->software_version = software_version;
} else {
new_caps->software_version = NULL;
}
char *os = g_key_file_get_string(cache, ver, "os", NULL);
if (os) {
- new_caps->os = strdup(os);
+ new_caps->os = os;
} else {
new_caps->os = NULL;
}
char *os_version = g_key_file_get_string(cache, ver, "os_version", NULL);
if (os_version) {
- new_caps->os_version = strdup(os_version);
+ new_caps->os_version = os_version;
} else {
new_caps->os_version = NULL;
}
gsize features_len = 0;
gchar **features = g_key_file_get_string_list(cache, ver, "features", &features_len, NULL);
- if (features != NULL && features_len > 0) {
+ if (features && features_len > 0) {
GSList *features_list = NULL;
int i;
for (i = 0; i < features_len; i++) {
@@ -395,16 +395,16 @@ caps_create(xmpp_stanza_t *query)
GSList *features = NULL;
xmpp_stanza_t *softwareinfo = xmpp_stanza_get_child_by_ns(query, STANZA_NS_DATA);
- if (softwareinfo != NULL) {
+ if (softwareinfo) {
DataForm *form = form_create(softwareinfo);
FormField *formField = NULL;
char *form_type = form_get_form_type_field(form);
if (g_strcmp0(form_type, STANZA_DATAFORM_SOFTWARE) == 0) {
GSList *field = form->fields;
- while (field != NULL) {
+ while (field) {
formField = field->data;
- if (formField->values != NULL) {
+ if (formField->values) {
if (strcmp(formField->var, "software") == 0) {
software = strdup(formField->values->data);
} else if (strcmp(formField->var, "software_version") == 0) {
@@ -424,7 +424,7 @@ caps_create(xmpp_stanza_t *query)
xmpp_stanza_t *child = xmpp_stanza_get_children(query);
GSList *identity_stanzas = NULL;
- while (child != NULL) {
+ while (child) {
if (g_strcmp0(xmpp_stanza_get_name(child), "feature") == 0) {
features = g_slist_append(features, strdup(xmpp_stanza_get_attribute(child, "var")));
}
@@ -490,42 +490,42 @@ caps_create(xmpp_stanza_t *query)
Capabilities *new_caps = malloc(sizeof(struct capabilities_t));
- if (category != NULL) {
+ if (category) {
new_caps->category = strdup(category);
} else {
new_caps->category = NULL;
}
- if (type != NULL) {
+ if (type) {
new_caps->type = strdup(type);
} else {
new_caps->type = NULL;
}
- if (name != NULL) {
+ if (name) {
new_caps->name = strdup(name);
} else {
new_caps->name = NULL;
}
- if (software != NULL) {
+ if (software) {
new_caps->software = software;
} else {
new_caps->software = NULL;
}
- if (software_version != NULL) {
+ if (software_version) {
new_caps->software_version = software_version;
} else {
new_caps->software_version = NULL;
}
- if (os != NULL) {
+ if (os) {
new_caps->os = os;
} else {
new_caps->os = NULL;
}
- if (os_version != NULL) {
+ if (os_version) {
new_caps->os_version = os_version;
} else {
new_caps->os_version = NULL;
}
- if (features != NULL) {
+ if (features) {
new_caps->features = features;
} else {
new_caps->features = NULL;
@@ -635,7 +635,7 @@ caps_close(void)
void
caps_destroy(Capabilities *caps)
{
- if (caps != NULL) {
+ if (caps) {
free(caps->category);
free(caps->type);
free(caps->name);
@@ -643,7 +643,7 @@ caps_destroy(Capabilities *caps)
free(caps->software_version);
free(caps->os);
free(caps->os_version);
- if (caps->features != NULL) {
+ if (caps->features) {
g_slist_free_full(caps->features, free);
}
free(caps);
diff --git a/src/xmpp/capabilities.h b/src/xmpp/capabilities.h
index 692ac49d..85f1d989 100644
--- a/src/xmpp/capabilities.h
+++ b/src/xmpp/capabilities.h
@@ -1,7 +1,7 @@
/*
* capabilities.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c
index 915525e4..70d49b7c 100644
--- a/src/xmpp/connection.c
+++ b/src/xmpp/connection.c
@@ -1,7 +1,7 @@
/*
* connection.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -45,7 +45,7 @@
#include "log.h"
#include "muc.h"
#include "profanity.h"
-#include "server_events.h"
+#include "event/server_events.h"
#include "xmpp/bookmark.h"
#include "xmpp/capabilities.h"
#include "xmpp/connection.h"
@@ -129,11 +129,11 @@ jabber_connect_with_account(const ProfAccount * const account)
log_info("Connecting using account: %s", account->name);
// save account name and password for reconnect
- if (saved_account.name != NULL) {
+ if (saved_account.name) {
free(saved_account.name);
}
saved_account.name = strdup(account->name);
- if (saved_account.passwd != NULL) {
+ if (saved_account.passwd) {
free(saved_account.passwd);
}
saved_account.passwd = strdup(account->password);
@@ -157,7 +157,7 @@ jabber_connect_with_details(const char * const jid,
// save details for reconnect, remember name for account creating on success
saved_details.name = strdup(jid);
saved_details.passwd = strdup(passwd);
- if (altdomain != NULL) {
+ if (altdomain) {
saved_details.altdomain = strdup(altdomain);
} else {
saved_details.altdomain = NULL;
@@ -199,11 +199,11 @@ jabber_disconnect(void)
_connection_free_saved_account();
_connection_free_saved_details();
_connection_free_session_data();
- if (jabber_conn.conn != NULL) {
+ if (jabber_conn.conn) {
xmpp_conn_release(jabber_conn.conn);
jabber_conn.conn = NULL;
}
- if (jabber_conn.ctx != NULL) {
+ if (jabber_conn.ctx) {
xmpp_ctx_free(jabber_conn.ctx);
jabber_conn.ctx = NULL;
}
@@ -238,7 +238,7 @@ jabber_process_events(void)
break;
case JABBER_DISCONNECTED:
reconnect_sec = prefs_get_reconnect();
- if ((reconnect_sec != 0) && (reconnect_timer != NULL)) {
+ if ((reconnect_sec != 0) && reconnect_timer) {
int elapsed_sec = g_timer_elapsed(reconnect_timer, NULL);
if (elapsed_sec > reconnect_sec) {
_jabber_reconnect();
@@ -302,7 +302,7 @@ void
connection_set_presence_message(const char * const message)
{
FREE_SET_NULL(jabber_conn.presence_message);
- if (message != NULL) {
+ if (message) {
jabber_conn.presence_message = strdup(message);
}
}
@@ -371,15 +371,15 @@ _jabber_connect(const char * const fulljid, const char * const passwd,
jid_destroy(jid);
log_info("Connecting as %s", fulljid);
- if (jabber_conn.log != NULL) {
+ if (jabber_conn.log) {
free(jabber_conn.log);
}
jabber_conn.log = _xmpp_get_file_logger();
- if (jabber_conn.conn != NULL) {
+ if (jabber_conn.conn) {
xmpp_conn_release(jabber_conn.conn);
}
- if (jabber_conn.ctx != NULL) {
+ if (jabber_conn.ctx) {
xmpp_ctx_free(jabber_conn.ctx);
}
jabber_conn.ctx = xmpp_ctx_new(NULL, jabber_conn.log);
@@ -436,9 +436,9 @@ _connection_handler(xmpp_conn_t * const conn,
log_debug("Connection handler: XMPP_CONN_CONNECT");
// logged in with account
- if (saved_account.name != NULL) {
+ if (saved_account.name) {
log_debug("Connection handler: logged in with account name: %s", saved_account.name);
- handle_login_account_success(saved_account.name);
+ sv_ev_login_account_success(saved_account.name);
// logged in without account, use details to create new account
} else {
@@ -446,7 +446,7 @@ _connection_handler(xmpp_conn_t * const conn,
accounts_add(saved_details.name, saved_details.altdomain, saved_details.port);
accounts_set_jid(saved_details.name, saved_details.jid);
- handle_login_account_success(saved_details.name);
+ sv_ev_login_account_success(saved_details.name);
saved_account.name = strdup(saved_details.name);
saved_account.passwd = strdup(saved_details.passwd);
@@ -466,10 +466,15 @@ _connection_handler(xmpp_conn_t * const conn,
roster_request();
bookmark_request();
+
+ if (prefs_get_boolean(PREF_CARBONS)){
+ iq_enable_carbons();
+ }
+
jabber_conn.conn_status = JABBER_CONNECTED;
if (prefs_get_reconnect() != 0) {
- if (reconnect_timer != NULL) {
+ if (reconnect_timer) {
g_timer_destroy(reconnect_timer);
reconnect_timer = NULL;
}
@@ -481,7 +486,7 @@ _connection_handler(xmpp_conn_t * const conn,
// lost connection for unknown reason
if (jabber_conn.conn_status == JABBER_CONNECTED) {
log_debug("Connection handler: Lost connection for unknown reason");
- handle_lost_connection();
+ sv_ev_lost_connection();
if (prefs_get_reconnect() != 0) {
assert(reconnect_timer == NULL);
reconnect_timer = g_timer_new();
@@ -498,7 +503,7 @@ _connection_handler(xmpp_conn_t * const conn,
log_debug("Connection handler: Login failed");
if (reconnect_timer == NULL) {
log_debug("Connection handler: No reconnect timer");
- handle_failed_login();
+ sv_ev_failed_login();
_connection_free_saved_account();
_connection_free_saved_details();
_connection_free_session_data();
@@ -558,7 +563,7 @@ _xmpp_file_logger(void * const userdata, const xmpp_log_level_t level,
log_level_t prof_level = _get_log_level(level);
log_msg(prof_level, area, msg);
if ((g_strcmp0(area, "xmpp") == 0) || (g_strcmp0(area, "conn")) == 0) {
- handle_xmpp_stanza(msg);
+ sv_ev_xmpp_stanza(msg);
}
}
diff --git a/src/xmpp/connection.h b/src/xmpp/connection.h
index f9e2cf22..63f7cde0 100644
--- a/src/xmpp/connection.h
+++ b/src/xmpp/connection.h
@@ -1,7 +1,7 @@
/*
* connection.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/xmpp/form.c b/src/xmpp/form.c
index 1facc754..e6213b64 100644
--- a/src/xmpp/form.c
+++ b/src/xmpp/form.c
@@ -1,7 +1,7 @@
/*
* form.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -211,7 +211,7 @@ form_create(xmpp_stanza_t * const form_stanza)
field->var = _get_attr(field_stanza, "var");
- if (field->type_t != FIELD_HIDDEN && field->var != NULL) {
+ if (field->type_t != FIELD_HIDDEN && field->var) {
GString *tag = g_string_new("");
g_string_printf(tag, "field%d", tag_num++);
g_hash_table_insert(form->var_to_tag, strdup(field->var), strdup(tag->str));
diff --git a/src/xmpp/form.h b/src/xmpp/form.h
index fa14e1c5..86cd4b7b 100644
--- a/src/xmpp/form.h
+++ b/src/xmpp/form.h
@@ -1,7 +1,7 @@
/*
* form.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index 7fedf0ed..18abad36 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -1,7 +1,7 @@
/*
* iq.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -47,8 +47,9 @@
#include "log.h"
#include "muc.h"
#include "profanity.h"
+#include "ui/ui.h"
#include "config/preferences.h"
-#include "server_events.h"
+#include "event/server_events.h"
#include "xmpp/capabilities.h"
#include "xmpp/connection.h"
#include "xmpp/stanza.h"
@@ -58,48 +59,35 @@
#define HANDLE(ns, type, func) xmpp_handler_add(conn, func, ns, STANZA_NAME_IQ, type, ctx)
-static int _error_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _ping_get_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _version_get_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _disco_info_get_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _disco_info_response_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _version_result_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _disco_items_result_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _disco_items_get_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _destroy_room_result_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _room_config_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _room_config_submit_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _room_affiliation_list_result_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _room_affiliation_set_result_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _room_role_set_result_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _room_role_list_result_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _room_kick_result_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _manual_pong_handler(xmpp_conn_t *const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _ping_timed_handler(xmpp_conn_t * const conn,
- void * const userdata);
-static int _caps_response_handler(xmpp_conn_t *const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _caps_response_handler_for_jid(xmpp_conn_t *const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _caps_response_handler_legacy(xmpp_conn_t *const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
+typedef struct p_room_info_data_t {
+ char *room;
+ gboolean display;
+} ProfRoomInfoData;
+
+static int _error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _ping_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _version_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _disco_info_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _disco_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _room_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _disco_items_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _disco_items_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _destroy_room_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _room_config_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _room_config_submit_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _room_affiliation_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _room_affiliation_set_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _room_role_set_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _room_role_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _room_kick_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _enable_carbons_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _disable_carbons_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _ping_timed_handler(xmpp_conn_t * const conn, void * const userdata);
+static int _caps_response_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _caps_response_handler_for_jid(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza, void * const userdata);
void
iq_add_handlers(void)
@@ -152,6 +140,34 @@ iq_room_list_request(gchar *conferencejid)
xmpp_stanza_release(iq);
}
+void
+iq_enable_carbons()
+{
+ xmpp_conn_t * const conn = connection_get_conn();
+ xmpp_ctx_t * const ctx = connection_get_ctx();
+ xmpp_stanza_t *iq = stanza_enable_carbons(ctx);
+ char *id = xmpp_stanza_get_id(iq);
+
+ xmpp_id_handler_add(conn, _enable_carbons_handler, id, NULL);
+
+ xmpp_send(conn, iq);
+ xmpp_stanza_release(iq);
+}
+
+void
+iq_disable_carbons()
+{
+ xmpp_conn_t * const conn = connection_get_conn();
+ xmpp_ctx_t * const ctx = connection_get_ctx();
+ xmpp_stanza_t *iq = stanza_disable_carbons(ctx);
+ char *id = xmpp_stanza_get_id(iq);
+
+ xmpp_id_handler_add(conn, _disable_carbons_handler, id, NULL);
+
+ xmpp_send(conn, iq);
+ xmpp_stanza_release(iq);
+}
+
void
iq_disco_info_request(gchar *jid)
{
@@ -169,14 +185,18 @@ iq_disco_info_request(gchar *jid)
}
void
-iq_room_info_request(gchar *room)
+iq_room_info_request(const char * const room, gboolean display_result)
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
char *id = create_unique_id("room_disco_info");
xmpp_stanza_t *iq = stanza_create_disco_info_iq(ctx, id, room, NULL);
- xmpp_id_handler_add(conn, _disco_info_response_handler, id, room);
+ ProfRoomInfoData *cb_data = malloc(sizeof(ProfRoomInfoData));
+ cb_data->room = strdup(room);
+ cb_data->display = display_result;
+
+ xmpp_id_handler_add(conn, _room_info_response_handler, id, cb_data);
free(id);
@@ -456,7 +476,7 @@ _error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
char *error_msg = stanza_get_error_message(stanza);
- if (id != NULL) {
+ if (id) {
log_debug("IQ error handler fired, id: %s, error: %s", id, error_msg);
log_error("IQ error received, id: %s, error: %s", id, error_msg);
} else {
@@ -476,13 +496,13 @@ _pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
char *id = xmpp_stanza_get_id(stanza);
char *type = xmpp_stanza_get_type(stanza);
- if (id != NULL) {
+ if (id) {
log_debug("IQ pong handler fired, id: %s.", id);
} else {
log_debug("IQ pong handler fired.");
}
- if (id != NULL && type != NULL) {
+ if (id && type) {
// show warning if error
if (strcmp(type, STANZA_TYPE_ERROR) == 0) {
char *error_msg = stanza_get_error_message(stanza);
@@ -491,12 +511,13 @@ _pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
// turn off autoping if error type is 'cancel'
xmpp_stanza_t *error = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
- if (error != NULL) {
+ if (error) {
char *errtype = xmpp_stanza_get_type(error);
- if (errtype != NULL) {
+ if (errtype) {
if (strcmp(errtype, "cancel") == 0) {
log_warning("Server ping (id=%s) error type 'cancel', disabling autoping.", id);
- handle_autoping_cancel();
+ prefs_set_autoping(0);
+ cons_show_error("Server ping not supported, autoping disabled.");
xmpp_timed_handler_delete(conn, _ping_timed_handler);
}
}
@@ -586,12 +607,14 @@ static int
_caps_response_handler_for_jid(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
void * const userdata)
{
+ char *jid = (char *)userdata;
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
char *type = xmpp_stanza_get_type(stanza);
// ignore non result
if ((g_strcmp0(type, "get") == 0) || (g_strcmp0(type, "set") == 0)) {
+ free(jid);
return 1;
}
@@ -604,6 +627,7 @@ _caps_response_handler_for_jid(xmpp_conn_t *const conn, xmpp_stanza_t * const st
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (!from) {
log_info("No from attribute");
+ free(jid);
return 0;
}
@@ -612,25 +636,29 @@ _caps_response_handler_for_jid(xmpp_conn_t *const conn, xmpp_stanza_t * const st
char *error_message = stanza_get_error_message(stanza);
log_warning("Error received for capabilities response from %s: ", from, error_message);
free(error_message);
+ free(jid);
return 0;
}
if (query == NULL) {
log_warning("No query element found.");
+ free(jid);
return 0;
}
char *node = xmpp_stanza_get_attribute(query, STANZA_ATTR_NODE);
if (node == NULL) {
log_warning("No node attribute found");
+ free(jid);
return 0;
}
- char *jid = (char *)userdata;
log_info("Associating capabilities with: %s", jid);
Capabilities *capabilities = caps_create(query);
caps_add_by_jid(jid, capabilities);
+ free(jid);
+
return 0;
}
@@ -640,10 +668,12 @@ _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t * const sta
{
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
+ char *expected_node = (char *)userdata;
char *type = xmpp_stanza_get_type(stanza);
// ignore non result
if ((g_strcmp0(type, "get") == 0) || (g_strcmp0(type, "set") == 0)) {
+ free(expected_node);
return 1;
}
@@ -656,6 +686,7 @@ _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t * const sta
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (!from) {
log_info("No from attribute");
+ free(expected_node);
return 0;
}
@@ -664,22 +695,23 @@ _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t * const sta
char *error_message = stanza_get_error_message(stanza);
log_warning("Error received for capabilities response from %s: ", from, error_message);
free(error_message);
+ free(expected_node);
return 0;
}
if (query == NULL) {
log_warning("No query element found.");
+ free(expected_node);
return 0;
}
char *node = xmpp_stanza_get_attribute(query, STANZA_ATTR_NODE);
if (node == NULL) {
log_warning("No node attribute found");
+ free(expected_node);
return 0;
}
- char *expected_node = (char *)userdata;
-
// nodes match
if (g_strcmp0(expected_node, node) == 0) {
log_info("Legacy capabilities, nodes match %s", node);
@@ -703,6 +735,36 @@ _caps_response_handler_legacy(xmpp_conn_t *const conn, xmpp_stanza_t * const sta
return 0;
}
+static int
+_enable_carbons_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
+{
+ char *type = xmpp_stanza_get_type(stanza);
+ if (g_strcmp0(type, "error") == 0) {
+ char *error_message = stanza_get_error_message(stanza);
+ cons_show_error("Server error enabling message carbons: %s", error_message);
+ log_debug("Error enabling carbons: %s", error_message);
+ } else {
+ log_debug("Message carbons enabled.");
+ }
+
+ return 0;
+}
+
+static int
+_disable_carbons_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
+{
+ char *type = xmpp_stanza_get_type(stanza);
+ if (g_strcmp0(type, "error") == 0) {
+ char *error_message = stanza_get_error_message(stanza);
+ cons_show_error("Server error disabling message carbons: %s", error_message);
+ log_debug("Error disabling carbons: %s", error_message);
+ } else {
+ log_debug("Message carbons disabled.");
+ }
+
+ return 0;
+}
+
static int
_manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
void * const userdata)
@@ -714,7 +776,12 @@ _manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
- handle_ping_error_result(from, error_message);
+ if (!error_message) {
+ cons_show_error("Error returned from pinging %s.", from);
+ } else {
+ cons_show_error("Error returned from pinging %s: %s.", from, error_message);
+ }
+
free(error_message);
g_date_time_unref(sent);
return 0;
@@ -728,7 +795,11 @@ _manual_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
g_date_time_unref(sent);
g_date_time_unref(now);
- handle_ping_result(from, elapsed_millis);
+ if (from == NULL) {
+ cons_show("Ping response from server: %dms.", elapsed_millis);
+ } else {
+ cons_show("Ping response from %s: %dms.", from, elapsed_millis);
+ }
return 0;
}
@@ -759,7 +830,7 @@ _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
{
char *id = xmpp_stanza_get_id(stanza);
- if (id != NULL) {
+ if (id) {
log_debug("IQ version result handler fired, id: %s.", id);
} else {
log_debug("IQ version result handler fired.");
@@ -784,13 +855,13 @@ _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
xmpp_stanza_t *version = xmpp_stanza_get_child_by_name(query, "version");
xmpp_stanza_t *os = xmpp_stanza_get_child_by_name(query, "os");
- if (name != NULL) {
+ if (name) {
name_str = xmpp_stanza_get_text(name);
}
- if (version != NULL) {
+ if (version) {
version_str = xmpp_stanza_get_text(version);
}
- if (os != NULL) {
+ if (os) {
os_str = xmpp_stanza_get_text(os);
}
@@ -805,7 +876,7 @@ _version_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
presence = string_from_resource_presence(resource->presence);
}
- handle_software_version_result(jid, presence, name_str, version_str, os_str);
+ cons_show_software_version(jid, presence, name_str, version_str, os_str);
jid_destroy(jidp);
@@ -821,7 +892,7 @@ _ping_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *to = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TO);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
- if (id != NULL) {
+ if (id) {
log_debug("IQ ping get handler fired, id: %s.", id);
} else {
log_debug("IQ ping get handler fired.");
@@ -837,7 +908,7 @@ _ping_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
xmpp_stanza_set_attribute(pong, STANZA_ATTR_FROM, to);
xmpp_stanza_set_attribute(pong, STANZA_ATTR_TYPE, STANZA_TYPE_RESULT);
- if (id != NULL) {
+ if (id) {
xmpp_stanza_set_attribute(pong, STANZA_ATTR_ID, id);
}
@@ -855,16 +926,16 @@ _version_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
- if (id != NULL) {
+ if (id) {
log_debug("IQ version get handler fired, id: %s.", id);
} else {
log_debug("IQ version get handler fired.");
}
- if (from != NULL) {
+ if (from) {
xmpp_stanza_t *response = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(response, STANZA_NAME_IQ);
- if (id != NULL) {
+ if (id) {
xmpp_stanza_set_id(response, id);
}
xmpp_stanza_set_attribute(response, STANZA_ATTR_TO, from);
@@ -923,13 +994,13 @@ _disco_items_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
- if (id != NULL) {
+ if (id) {
log_debug("IQ disco items get handler fired, id: %s.", id);
} else {
log_debug("IQ disco items get handler fired.");
}
- if (from != NULL) {
+ if (from) {
xmpp_stanza_t *response = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(response, STANZA_NAME_IQ);
xmpp_stanza_set_id(response, xmpp_stanza_get_id(stanza));
@@ -960,20 +1031,20 @@ _disco_info_get_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
- if (id != NULL) {
+ if (id) {
log_debug("IQ disco info get handler fired, id: %s.", id);
} else {
log_debug("IQ disco info get handler fired.");
}
- if (from != NULL) {
+ if (from) {
xmpp_stanza_t *response = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(response, STANZA_NAME_IQ);
xmpp_stanza_set_id(response, xmpp_stanza_get_id(stanza));
xmpp_stanza_set_attribute(response, STANZA_ATTR_TO, from);
xmpp_stanza_set_type(response, STANZA_TYPE_RESULT);
xmpp_stanza_t *query = caps_create_query_response_stanza(ctx);
- if (node_str != NULL) {
+ if (node_str) {
xmpp_stanza_set_attribute(query, STANZA_ATTR_NODE, node_str);
}
xmpp_stanza_add_child(response, query);
@@ -992,7 +1063,7 @@ _destroy_room_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const sta
{
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
- if (id != NULL) {
+ if (id) {
log_debug("IQ destroy room result handler fired, id: %s.", id);
} else {
log_debug("IQ destroy room result handler fired.");
@@ -1002,7 +1073,7 @@ _destroy_room_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const sta
if (from == NULL) {
log_error("No from attribute for IQ destroy room result");
} else {
- handle_room_destroy(from);
+ sv_ev_room_destroy(from);
}
return 0;
@@ -1016,7 +1087,7 @@ _room_config_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
const char *type = xmpp_stanza_get_type(stanza);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
- if (id != NULL) {
+ if (id) {
log_debug("IQ room config handler fired, id: %s.", id);
} else {
log_debug("IQ room config handler fired.");
@@ -1025,40 +1096,40 @@ _room_config_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
- handle_room_configuration_form_error(from, error_message);
+ ui_handle_room_configuration_form_error(from, error_message);
free(error_message);
return 0;
}
if (from == NULL) {
log_warning("No from attribute for IQ config request result");
- handle_room_configuration_form_error(from, "No from attribute for room cofig response.");
+ ui_handle_room_configuration_form_error(from, "No from attribute for room cofig response.");
return 0;
}
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
if (query == NULL) {
log_warning("No query element found parsing room config response");
- handle_room_configuration_form_error(from, "No query element found parsing room config response");
+ ui_handle_room_configuration_form_error(from, "No query element found parsing room config response");
return 0;
}
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(query, STANZA_NS_DATA);
if (x == NULL) {
log_warning("No x element found with %s namespace parsing room config response", STANZA_NS_DATA);
- handle_room_configuration_form_error(from, "No form configuration options available");
+ ui_handle_room_configuration_form_error(from, "No form configuration options available");
return 0;
}
char *form_type = xmpp_stanza_get_attribute(x, STANZA_ATTR_TYPE);
if (g_strcmp0(form_type, "form") != 0) {
log_warning("x element not of type 'form' parsing room config response");
- handle_room_configuration_form_error(from, "Form not of type 'form' parsing room config response.");
+ ui_handle_room_configuration_form_error(from, "Form not of type 'form' parsing room config response.");
return 0;
}
DataForm *form = form_create(x);
- handle_room_configure(from, form);
+ ui_handle_room_configuration(from, form);
return 0;
}
@@ -1071,7 +1142,7 @@ static int _room_affiliation_set_result_handler(xmpp_conn_t * const conn, xmpp_s
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
struct privilege_set_t *affiliation_set = (struct privilege_set_t *)userdata;
- if (id != NULL) {
+ if (id) {
log_debug("IQ affiliation set handler fired, id: %s.", id);
} else {
log_debug("IQ affiliation set handler fired.");
@@ -1080,7 +1151,8 @@ static int _room_affiliation_set_result_handler(xmpp_conn_t * const conn, xmpp_s
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
- handle_room_affiliation_set_error(from, affiliation_set->item, affiliation_set->privilege, error_message);
+ log_debug("Error setting affiliation %s list for room %s, user %s: %s", affiliation_set->privilege, from, affiliation_set->item, error_message);
+ ui_handle_room_affiliation_set_error(from, affiliation_set->item, affiliation_set->privilege, error_message);
free(error_message);
}
@@ -1099,7 +1171,7 @@ static int _room_role_set_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
struct privilege_set_t *role_set = (struct privilege_set_t *)userdata;
- if (id != NULL) {
+ if (id) {
log_debug("IQ role set handler fired, id: %s.", id);
} else {
log_debug("IQ role set handler fired.");
@@ -1108,7 +1180,8 @@ static int _room_role_set_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
- handle_room_role_set_error(from, role_set->item, role_set->privilege, error_message);
+ log_debug("Error setting role %s list for room %s, user %s: %s", role_set->privilege, from, role_set->item, error_message);
+ ui_handle_room_role_set_error(from, role_set->item, role_set->privilege, error_message);
free(error_message);
}
@@ -1127,7 +1200,7 @@ _room_affiliation_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t *
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
char *affiliation = (char *)userdata;
- if (id != NULL) {
+ if (id) {
log_debug("IQ affiliation list result handler fired, id: %s.", id);
} else {
log_debug("IQ affiliation list result handler fired.");
@@ -1136,7 +1209,8 @@ _room_affiliation_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t *
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
- handle_room_affiliation_list_result_error(from, affiliation, error_message);
+ log_debug("Error retrieving %s list for room %s: %s", affiliation, from, error_message);
+ ui_handle_room_affiliation_list_error(from, affiliation, error_message);
free(error_message);
free(affiliation);
return 0;
@@ -1158,7 +1232,8 @@ _room_affiliation_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t *
}
}
- handle_room_affiliation_list(from, affiliation, jids);
+ muc_jid_autocomplete_add_all(from, jids);
+ ui_handle_room_affiliation_list(from, affiliation, jids);
free(affiliation);
g_slist_free(jids);
@@ -1173,7 +1248,7 @@ _room_role_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const s
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
char *role = (char *)userdata;
- if (id != NULL) {
+ if (id) {
log_debug("IQ role list result handler fired, id: %s.", id);
} else {
log_debug("IQ role list result handler fired.");
@@ -1182,7 +1257,8 @@ _room_role_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const s
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
- handle_room_role_list_result_error(from, role, error_message);
+ log_debug("Error retrieving %s list for room %s: %s", role, from, error_message);
+ ui_handle_room_role_list_error(from, role, error_message);
free(error_message);
free(role);
return 0;
@@ -1204,7 +1280,7 @@ _room_role_list_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const s
}
}
- handle_room_role_list(from, role, nicks);
+ ui_handle_room_role_list(from, role, nicks);
free(role);
g_slist_free(nicks);
@@ -1219,7 +1295,7 @@ _room_config_submit_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stan
const char *type = xmpp_stanza_get_type(stanza);
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
- if (id != NULL) {
+ if (id) {
log_debug("IQ room config submit handler fired, id: %s.", id);
} else {
log_debug("IQ room config submit handler fired.");
@@ -1228,12 +1304,12 @@ _room_config_submit_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stan
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
- handle_room_config_submit_result_error(from, error_message);
+ ui_handle_room_config_submit_result_error(from, error_message);
free(error_message);
return 0;
}
- handle_room_config_submit_result(from);
+ ui_handle_room_config_submit_result(from);
return 0;
}
@@ -1246,7 +1322,7 @@ _room_kick_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
char *nick = (char *)userdata;
- if (id != NULL) {
+ if (id) {
log_debug("IQ kick result handler fired, id: %s.", id);
} else {
log_debug("IQ kick result handler fired.");
@@ -1255,7 +1331,7 @@ _room_kick_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
char *error_message = stanza_get_error_message(stanza);
- handle_room_kick_result_error(from, nick, error_message);
+ ui_handle_room_kick_error(from, nick, error_message);
free(error_message);
free(nick);
return 0;
@@ -1269,7 +1345,7 @@ _room_kick_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza
static void
_identity_destroy(DiscoIdentity *identity)
{
- if (identity != NULL) {
+ if (identity) {
free(identity->name);
free(identity->type);
free(identity->category);
@@ -1280,7 +1356,7 @@ _identity_destroy(DiscoIdentity *identity)
static void
_item_destroy(DiscoItem *item)
{
- if (item != NULL) {
+ if (item) {
free(item->jid);
free(item->name);
free(item);
@@ -1288,48 +1364,36 @@ _item_destroy(DiscoItem *item)
}
static int
-_disco_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
+_room_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
{
- const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
const char *type = xmpp_stanza_get_type(stanza);
-
- char *room = NULL;
- if (userdata) {
- room = (char *) userdata;
- log_info("Received diso#info response for room: %s", room);
- } else {
- room = NULL;
- if (from) {
- log_info("Received diso#info response from: %s", from);
- } else {
- log_info("Received diso#info response");
- }
- }
+ ProfRoomInfoData *cb_data = (ProfRoomInfoData *)userdata;
+ log_info("Received diso#info response for room: %s", cb_data->room);
// handle error responses
if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
- char *error_message = stanza_get_error_message(stanza);
- if (room) {
- handle_room_info_error(room, error_message);
- } else {
- handle_disco_info_error(from, error_message);
+ if (cb_data->display) {
+ char *error_message = stanza_get_error_message(stanza);
+ ui_handle_room_info_error(cb_data->room, error_message);
+ free(error_message);
}
- free(error_message);
+ free(cb_data->room);
+ free(cb_data);
return 0;
}
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
- if (query != NULL) {
+ if (query) {
xmpp_stanza_t *child = xmpp_stanza_get_children(query);
GSList *identities = NULL;
GSList *features = NULL;
- while (child != NULL) {
+ while (child) {
const char *stanza_name = xmpp_stanza_get_name(child);
if (g_strcmp0(stanza_name, STANZA_NAME_FEATURE) == 0) {
const char *var = xmpp_stanza_get_attribute(child, STANZA_ATTR_VAR);
- if (var != NULL) {
+ if (var) {
features = g_slist_append(features, strdup(var));
}
} else if (g_strcmp0(stanza_name, STANZA_NAME_IDENTITY) == 0) {
@@ -1337,20 +1401,20 @@ _disco_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const sta
const char *type = xmpp_stanza_get_attribute(child, STANZA_ATTR_TYPE);
const char *category = xmpp_stanza_get_attribute(child, STANZA_ATTR_CATEGORY);
- if ((name != NULL) || (category != NULL) || (type != NULL)) {
+ if (name || category || type) {
DiscoIdentity *identity = malloc(sizeof(struct disco_identity_t));
- if (name != NULL) {
+ if (name) {
identity->name = strdup(name);
} else {
identity->name = NULL;
}
- if (category != NULL) {
+ if (category) {
identity->category = strdup(category);
} else {
identity->category = NULL;
}
- if (type != NULL) {
+ if (type) {
identity->type = strdup(type);
} else {
identity->type = NULL;
@@ -1363,16 +1427,97 @@ _disco_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const sta
child = xmpp_stanza_get_next(child);
}
- if (room) {
- handle_room_disco_info(room, identities, features);
- } else {
- handle_disco_info(from, identities, features);
+ muc_set_features(cb_data->room, features);
+ if (cb_data->display) {
+ ui_show_room_disco_info(cb_data->room, identities, features);
}
g_slist_free_full(features, free);
g_slist_free_full(identities, (GDestroyNotify)_identity_destroy);
}
- return 1;
+
+ free(cb_data->room);
+ free(cb_data);
+
+ return 0;
+}
+
+static int
+_disco_info_response_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
+ void * const userdata)
+{
+ const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
+ const char *type = xmpp_stanza_get_type(stanza);
+
+ if (from) {
+ log_info("Received diso#info response from: %s", from);
+ } else {
+ log_info("Received diso#info response");
+ }
+
+ // handle error responses
+ if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) {
+ char *error_message = stanza_get_error_message(stanza);
+ if (from) {
+ cons_show_error("Service discovery failed for %s: %s", from, error_message);
+ } else {
+ cons_show_error("Service discovery failed: %s", error_message);
+ }
+ free(error_message);
+ return 0;
+ }
+
+ xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
+
+ if (query) {
+ xmpp_stanza_t *child = xmpp_stanza_get_children(query);
+ GSList *identities = NULL;
+ GSList *features = NULL;
+ while (child) {
+ const char *stanza_name = xmpp_stanza_get_name(child);
+ if (g_strcmp0(stanza_name, STANZA_NAME_FEATURE) == 0) {
+ const char *var = xmpp_stanza_get_attribute(child, STANZA_ATTR_VAR);
+ if (var) {
+ features = g_slist_append(features, strdup(var));
+ }
+ } else if (g_strcmp0(stanza_name, STANZA_NAME_IDENTITY) == 0) {
+ const char *name = xmpp_stanza_get_attribute(child, STANZA_ATTR_NAME);
+ const char *type = xmpp_stanza_get_attribute(child, STANZA_ATTR_TYPE);
+ const char *category = xmpp_stanza_get_attribute(child, STANZA_ATTR_CATEGORY);
+
+ if (name || category || type) {
+ DiscoIdentity *identity = malloc(sizeof(struct disco_identity_t));
+
+ if (name) {
+ identity->name = strdup(name);
+ } else {
+ identity->name = NULL;
+ }
+ if (category) {
+ identity->category = strdup(category);
+ } else {
+ identity->category = NULL;
+ }
+ if (type) {
+ identity->type = strdup(type);
+ } else {
+ identity->type = NULL;
+ }
+
+ identities = g_slist_append(identities, identity);
+ }
+ }
+
+ child = xmpp_stanza_get_next(child);
+ }
+
+ cons_show_disco_info(from, identities, features);
+
+ g_slist_free_full(features, free);
+ g_slist_free_full(identities, (GDestroyNotify)_identity_destroy);
+ }
+
+ return 0;
}
static int
@@ -1389,17 +1534,17 @@ _disco_items_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stan
log_debug("Response to query: %s", id);
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
- if (query != NULL) {
+ if (query) {
xmpp_stanza_t *child = xmpp_stanza_get_children(query);
- while (child != NULL) {
+ while (child) {
const char *stanza_name = xmpp_stanza_get_name(child);
- if ((stanza_name != NULL) && (g_strcmp0(stanza_name, STANZA_NAME_ITEM) == 0)) {
+ if (stanza_name && (g_strcmp0(stanza_name, STANZA_NAME_ITEM) == 0)) {
const char *item_jid = xmpp_stanza_get_attribute(child, STANZA_ATTR_JID);
- if (item_jid != NULL) {
+ if (item_jid) {
DiscoItem *item = malloc(sizeof(struct disco_item_t));
item->jid = strdup(item_jid);
const char *item_name = xmpp_stanza_get_attribute(child, STANZA_ATTR_NAME);
- if (item_name != NULL) {
+ if (item_name) {
item->name = strdup(item_name);
} else {
item->name = NULL;
@@ -1414,9 +1559,9 @@ _disco_items_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stan
}
if (g_strcmp0(id, "confreq") == 0) {
- handle_room_list(items, from);
+ cons_show_room_list(items, from);
} else if (g_strcmp0(id, "discoitemsreq") == 0) {
- handle_disco_items(items, from);
+ cons_show_disco_items(items, from);
}
g_slist_free_full(items, (GDestroyNotify)_item_destroy);
diff --git a/src/xmpp/iq.h b/src/xmpp/iq.h
index 8c803ab5..d3a22fe4 100644
--- a/src/xmpp/iq.h
+++ b/src/xmpp/iq.h
@@ -1,7 +1,7 @@
/*
* iq.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index e96c1a74..bc702199 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -1,7 +1,7 @@
/*
* message.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -42,7 +42,8 @@
#include "log.h"
#include "muc.h"
#include "profanity.h"
-#include "server_events.h"
+#include "ui/ui.h"
+#include "event/server_events.h"
#include "xmpp/connection.h"
#include "xmpp/message.h"
#include "xmpp/roster.h"
@@ -52,18 +53,13 @@
#define HANDLE(ns, type, func) xmpp_handler_add(conn, func, ns, STANZA_NAME_MESSAGE, type, ctx)
-static int _groupchat_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _chat_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _muc_user_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _conference_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _captcha_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
-static int _message_error_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata);
+static int _groupchat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _conference_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _captcha_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
+static int _receipt_received_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata);
void
message_add_handlers(void)
@@ -77,34 +73,89 @@ message_add_handlers(void)
HANDLE(STANZA_NS_MUC_USER, NULL, _muc_user_handler);
HANDLE(STANZA_NS_CONFERENCE, NULL, _conference_handler);
HANDLE(STANZA_NS_CAPTCHA, NULL, _captcha_handler);
+ HANDLE(STANZA_NS_RECEIPTS, NULL, _receipt_received_handler);
}
-void
+char *
message_send_chat(const char * const barejid, const char * const msg)
{
- xmpp_stanza_t *message;
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
ChatSession *session = chat_session_get(barejid);
+ char *state = NULL;
+ char *jid = NULL;
if (session) {
- char *state = NULL;
if (prefs_get_boolean(PREF_STATES) && session->send_states) {
state = STANZA_NAME_ACTIVE;
}
Jid *jidp = jid_create_from_bare_and_resource(session->barejid, session->resource);
- message = stanza_create_message(ctx, jidp->fulljid, STANZA_TYPE_CHAT, msg, state);
+ jid = strdup(jidp->fulljid);
jid_destroy(jidp);
+
} else {
- char *state = NULL;
if (prefs_get_boolean(PREF_STATES)) {
state = STANZA_NAME_ACTIVE;
}
- message = stanza_create_message(ctx, barejid, STANZA_TYPE_CHAT, msg, state);
+ jid = strdup(barejid);
+ }
+
+ char *id = create_unique_id("msg");
+ xmpp_stanza_t *message = stanza_create_message(ctx, id, jid, STANZA_TYPE_CHAT, msg);
+ free(jid);
+
+ if (state) {
+ stanza_attach_state(ctx, message, state);
+ }
+ if (prefs_get_boolean(PREF_RECEIPTS_REQUEST)) {
+ stanza_attach_receipt_request(ctx, message);
}
xmpp_send(conn, message);
xmpp_stanza_release(message);
+
+ return id;
+}
+
+char *
+message_send_chat_encrypted(const char * const barejid, const char * const msg)
+{
+ xmpp_conn_t * const conn = connection_get_conn();
+ xmpp_ctx_t * const ctx = connection_get_ctx();
+
+ ChatSession *session = chat_session_get(barejid);
+ char *state = NULL;
+ char *jid = NULL;
+ if (session) {
+ if (prefs_get_boolean(PREF_STATES) && session->send_states) {
+ state = STANZA_NAME_ACTIVE;
+ }
+ Jid *jidp = jid_create_from_bare_and_resource(session->barejid, session->resource);
+ jid = strdup(jidp->fulljid);
+ jid_destroy(jidp);
+ } else {
+ if (prefs_get_boolean(PREF_STATES)) {
+ state = STANZA_NAME_ACTIVE;
+ }
+ jid = strdup(barejid);
+ }
+
+ char *id = create_unique_id("msg");
+ xmpp_stanza_t *message = stanza_create_message(ctx, id, barejid, STANZA_TYPE_CHAT, msg);
+ free(jid);
+
+ if (state) {
+ stanza_attach_state(ctx, message, state);
+ }
+ stanza_attach_carbons_private(ctx, message);
+ if (prefs_get_boolean(PREF_RECEIPTS_REQUEST)) {
+ stanza_attach_receipt_request(ctx, message);
+ }
+
+ xmpp_send(conn, message);
+ xmpp_stanza_release(message);
+
+ return id;
}
void
@@ -112,7 +163,9 @@ message_send_private(const char * const fulljid, const char * const msg)
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
- xmpp_stanza_t *message = stanza_create_message(ctx, fulljid, STANZA_TYPE_CHAT, msg, NULL);
+ char *id = create_unique_id("prv");
+ xmpp_stanza_t *message = stanza_create_message(ctx, id, fulljid, STANZA_TYPE_CHAT, msg);
+ free(id);
xmpp_send(conn, message);
xmpp_stanza_release(message);
@@ -123,7 +176,9 @@ message_send_groupchat(const char * const roomjid, const char * const msg)
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
- xmpp_stanza_t *message = stanza_create_message(ctx, roomjid, STANZA_TYPE_GROUPCHAT, msg, NULL);
+ char *id = create_unique_id("muc");
+ xmpp_stanza_t *message = stanza_create_message(ctx, id, roomjid, STANZA_TYPE_GROUPCHAT, msg);
+ free(id);
xmpp_send(conn, message);
xmpp_stanza_release(message);
@@ -146,7 +201,18 @@ message_send_invite(const char * const roomjid, const char * const contact,
{
xmpp_conn_t * const conn = connection_get_conn();
xmpp_ctx_t * const ctx = connection_get_ctx();
- xmpp_stanza_t *stanza = stanza_create_invite(ctx, roomjid, contact, reason);
+ xmpp_stanza_t *stanza;
+
+
+ muc_member_type_t member_type = muc_member_type(roomjid);
+ if (member_type == MUC_MEMBER_TYPE_PUBLIC) {
+ log_debug("Sending direct invite to %s, for %s", contact, roomjid);
+ char *password = muc_password(roomjid);
+ stanza = stanza_create_invite(ctx, roomjid, contact, reason, password);
+ } else {
+ log_debug("Sending mediated invite to %s, for %s", contact, roomjid);
+ stanza = stanza_create_mediated_invite(ctx, roomjid, contact, reason);
+ }
xmpp_send(conn, stanza);
xmpp_stanza_release(stanza);
@@ -196,14 +262,13 @@ message_send_gone(const char * const jid)
}
static int
-_message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
- void * const userdata)
+_message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
char *id = xmpp_stanza_get_id(stanza);
char *jid = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
char *type = NULL;
- if (error_stanza != NULL) {
+ if (error_stanza) {
type = xmpp_stanza_get_attribute(error_stanza, STANZA_ATTR_TYPE);
}
@@ -211,15 +276,15 @@ _message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
char *err_msg = stanza_get_error_message(stanza);
GString *log_msg = g_string_new("message stanza error received");
- if (id != NULL) {
+ if (id) {
g_string_append(log_msg, " id=");
g_string_append(log_msg, id);
}
- if (jid != NULL) {
+ if (jid) {
g_string_append(log_msg, " from=");
g_string_append(log_msg, jid);
}
- if (type != NULL) {
+ if (type) {
g_string_append(log_msg, " type=");
g_string_append(log_msg, type);
}
@@ -230,7 +295,16 @@ _message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
g_string_free(log_msg, TRUE);
- handle_message_error(jid, type, err_msg);
+ if (!jid) {
+ ui_handle_error(err_msg);
+ } else if (type && (strcmp(type, "cancel") == 0)) {
+ log_info("Recipient %s not found: %s", jid, err_msg);
+ Jid *jidp = jid_create(jid);
+ chat_session_remove(jidp->barejid);
+ jid_destroy(jidp);
+ } else {
+ ui_handle_recipient_error(jid, err_msg);
+ }
free(err_msg);
@@ -238,113 +312,120 @@ _message_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
}
static int
-_muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
- void * const userdata)
+_muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_stanza_t *xns_muc_user = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
char *room = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
- if (room == NULL) {
+ if (!room) {
log_warning("Message received with no from attribute, ignoring");
return 1;
}
// XEP-0045
xmpp_stanza_t *invite = xmpp_stanza_get_child_by_name(xns_muc_user, STANZA_NAME_INVITE);
- if (invite != NULL) {
- char *invitor_jid = xmpp_stanza_get_attribute(invite, STANZA_ATTR_FROM);
- if (invitor_jid == NULL) {
- log_warning("Chat room invite received with no from attribute");
- return 1;
- }
+ if (!invite) {
+ return 1;
+ }
- Jid *jidp = jid_create(invitor_jid);
- if (jidp == NULL) {
- return 1;
- }
- char *invitor = jidp->barejid;
+ char *invitor_jid = xmpp_stanza_get_attribute(invite, STANZA_ATTR_FROM);
+ if (!invitor_jid) {
+ log_warning("Chat room invite received with no from attribute");
+ return 1;
+ }
- char *reason = NULL;
- xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_name(invite, STANZA_NAME_REASON);
- if (reason_st != NULL) {
- reason = xmpp_stanza_get_text(reason_st);
- }
+ Jid *jidp = jid_create(invitor_jid);
+ if (!jidp) {
+ return 1;
+ }
+ char *invitor = jidp->barejid;
- handle_room_invite(INVITE_MEDIATED, invitor, room, reason);
- jid_destroy(jidp);
- if (reason != NULL) {
- xmpp_free(ctx, reason);
- }
+ char *reason = NULL;
+ xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_name(invite, STANZA_NAME_REASON);
+ if (reason_st) {
+ reason = xmpp_stanza_get_text(reason_st);
+ }
+
+ char *password = NULL;
+ xmpp_stanza_t *password_st = xmpp_stanza_get_child_by_name(xns_muc_user, STANZA_NAME_PASSWORD);
+ if (password_st) {
+ password = xmpp_stanza_get_text(password_st);
+ }
+
+ sv_ev_room_invite(INVITE_MEDIATED, invitor, room, reason, password);
+ jid_destroy(jidp);
+ if (reason) {
+ xmpp_free(ctx, reason);
+ }
+ if (password) {
+ xmpp_free(ctx, password);
}
return 1;
}
static int
-_conference_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
- void * const userdata)
+_conference_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
xmpp_stanza_t *xns_conference = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE);
- char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
- char *room = NULL;
- char *invitor = NULL;
- char *reason = NULL;
- if (from == NULL) {
+ char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
+ if (!from) {
log_warning("Message received with no from attribute, ignoring");
return 1;
}
- // XEP-0429
- room = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_JID);
- if (room == NULL) {
- return 1;
- }
-
Jid *jidp = jid_create(from);
- if (jidp == NULL) {
+ if (!jidp) {
return 1;
}
- invitor = jidp->barejid;
- reason = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_REASON);
+ // XEP-0249
+ char *room = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_JID);
+ if (!room) {
+ return 1;
+ }
- handle_room_invite(INVITE_DIRECT, invitor, room, reason);
+ char *reason = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_REASON);
+ char *password = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_PASSWORD);
+ sv_ev_room_invite(INVITE_DIRECT, jidp->barejid, room, reason, password);
jid_destroy(jidp);
return 1;
}
static int
-_captcha_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
- void * const userdata)
+_captcha_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
xmpp_ctx_t *ctx = connection_get_ctx();
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
- if (from == NULL) {
+ if (!from) {
log_warning("Message received with no from attribute, ignoring");
return 1;
}
// XEP-0158
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
- if (body != NULL) {
- char *message = xmpp_stanza_get_text(body);
- if (message != NULL) {
- handle_room_broadcast(from, message);
- xmpp_free(ctx, message);
- }
+ if (!body) {
+ return 1;
}
+ char *message = xmpp_stanza_get_text(body);
+ if (!message) {
+ return 1;
+ }
+
+ sv_ev_room_broadcast(from, message);
+ xmpp_free(ctx, message);
+
return 1;
}
static int
-_groupchat_handler(xmpp_conn_t * const conn,
- xmpp_stanza_t * const stanza, void * const userdata)
+_groupchat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
xmpp_ctx_t *ctx = connection_get_ctx();
char *message = NULL;
@@ -353,9 +434,9 @@ _groupchat_handler(xmpp_conn_t * const conn,
// handle room subject
xmpp_stanza_t *subject = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SUBJECT);
- if (subject != NULL) {
+ if (subject) {
message = xmpp_stanza_get_text(subject);
- handle_room_subject(jid->barejid, jid->resourcepart, message);
+ sv_ev_room_subject(jid->barejid, jid->resourcepart, message);
xmpp_free(ctx, message);
jid_destroy(jid);
@@ -363,16 +444,22 @@ _groupchat_handler(xmpp_conn_t * const conn,
}
// handle room broadcasts
- if (jid->resourcepart == NULL) {
+ if (!jid->resourcepart) {
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
- if (body != NULL) {
- message = xmpp_stanza_get_text(body);
- if (message != NULL) {
- handle_room_broadcast(room_jid, message);
- xmpp_free(ctx, message);
- }
+ if (!body) {
+ jid_destroy(jid);
+ return 1;
}
+ message = xmpp_stanza_get_text(body);
+ if (!message) {
+ jid_destroy(jid);
+ return 1;
+ }
+
+ sv_ev_room_broadcast(room_jid, message);
+ xmpp_free(ctx, message);
+
jid_destroy(jid);
return 1;
}
@@ -390,32 +477,191 @@ _groupchat_handler(xmpp_conn_t * const conn,
return 1;
}
- // determine if the notifications happened whilst offline
- GTimeVal tv_stamp;
- gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
// check for and deal with message
- if (body != NULL) {
- message = xmpp_stanza_get_text(body);
- if (message != NULL) {
- if (delayed) {
- handle_room_history(jid->barejid, jid->resourcepart, tv_stamp, message);
- } else {
- handle_room_message(jid->barejid, jid->resourcepart, message);
- }
- xmpp_free(ctx, message);
- }
+ if (!body) {
+ jid_destroy(jid);
+ return 1;
}
+ message = xmpp_stanza_get_text(body);
+ if (!message) {
+ jid_destroy(jid);
+ return 1;
+ }
+
+ // determine if the notifications happened whilst offline
+ GTimeVal tv_stamp;
+ gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
+ if (delayed) {
+ sv_ev_room_history(jid->barejid, jid->resourcepart, tv_stamp, message);
+ } else {
+ sv_ev_room_message(jid->barejid, jid->resourcepart, message);
+ }
+
+ xmpp_free(ctx, message);
jid_destroy(jid);
return 1;
}
+void
+_message_send_receipt(const char * const fulljid, const char * const message_id)
+{
+ xmpp_conn_t * const conn = connection_get_conn();
+ xmpp_ctx_t * const ctx = connection_get_ctx();
+ xmpp_stanza_t *message = xmpp_stanza_new(ctx);
+ char *id = create_unique_id("receipt");
+ xmpp_stanza_set_name(message, STANZA_NAME_MESSAGE);
+ xmpp_stanza_set_id(message, id);
+ xmpp_stanza_set_attribute(message, STANZA_ATTR_TO, fulljid);
+
+ xmpp_stanza_t *receipt = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(receipt, "received");
+ xmpp_stanza_set_ns(receipt, STANZA_NS_RECEIPTS);
+ xmpp_stanza_set_attribute(receipt, STANZA_ATTR_ID, message_id);
+
+ xmpp_stanza_add_child(message, receipt);
+ xmpp_stanza_release(receipt);
+
+ xmpp_send(conn, message);
+ xmpp_stanza_release(message);
+}
+
static int
-_chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
- void * const userdata)
+_receipt_received_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
+{
+ xmpp_stanza_t *receipt = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_RECEIPTS);
+ char *name = xmpp_stanza_get_name(receipt);
+ if (g_strcmp0(name, "received") != 0) {
+ return 1;
+ }
+
+ char *id = xmpp_stanza_get_attribute(receipt, STANZA_ATTR_ID);
+ if (!id) {
+ return 1;
+ }
+
+ char *fulljid = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
+ if (!fulljid) {
+ return 1;
+ }
+
+ Jid *jidp = jid_create(fulljid);
+ sv_ev_message_receipt(jidp->barejid, id);
+ jid_destroy(jidp);
+
+ return 1;
+}
+
+void
+_receipt_request_handler(xmpp_stanza_t * const stanza)
+{
+ if (!prefs_get_boolean(PREF_RECEIPTS_SEND)) {
+ return;
+ }
+
+ char *id = xmpp_stanza_get_id(stanza);
+ if (!id) {
+ return;
+ }
+
+ xmpp_stanza_t *receipts = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_RECEIPTS);
+ if (!receipts) {
+ return;
+ }
+
+ char *receipts_name = xmpp_stanza_get_name(receipts);
+ if (g_strcmp0(receipts_name, "request") != 0) {
+ return;
+ }
+
+ gchar *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
+ Jid *jid = jid_create(from);
+ _message_send_receipt(jid->fulljid, id);
+ jid_destroy(jid);
+}
+
+void
+_private_chat_handler(xmpp_stanza_t * const stanza, const char * const fulljid)
+{
+ xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
+ if (!body) {
+ return;
+ }
+
+ char *message = xmpp_stanza_get_text(body);
+ if (!message) {
+ return;
+ }
+
+ GTimeVal tv_stamp;
+ gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
+ if (delayed) {
+ sv_ev_delayed_private_message(fulljid, message, tv_stamp);
+ } else {
+ sv_ev_incoming_private_message(fulljid, message);
+ }
+
+ xmpp_ctx_t *ctx = connection_get_ctx();
+ xmpp_free(ctx, message);
+}
+
+static gboolean
+_handle_carbons(xmpp_stanza_t * const stanza)
+{
+ xmpp_stanza_t *carbons = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CARBONS);
+ if (!carbons) {
+ return FALSE;
+ }
+
+ char *name = xmpp_stanza_get_name(carbons);
+ if ((g_strcmp0(name, "received") == 0) || (g_strcmp0(name, "sent")) == 0) {
+ xmpp_stanza_t *forwarded = xmpp_stanza_get_child_by_ns(carbons, STANZA_NS_FORWARD);
+ xmpp_stanza_t *message = xmpp_stanza_get_child_by_name(forwarded, STANZA_NAME_MESSAGE);
+
+ xmpp_ctx_t *ctx = connection_get_ctx();
+
+ gchar *to = xmpp_stanza_get_attribute(message, STANZA_ATTR_TO);
+ gchar *from = xmpp_stanza_get_attribute(message, STANZA_ATTR_FROM);
+
+ // happens when receive a carbon of a self sent message
+ if (!to) to = from;
+
+ Jid *jid_from = jid_create(from);
+ Jid *jid_to = jid_create(to);
+ Jid *my_jid = jid_create(jabber_get_fulljid());
+
+ // check for and deal with message
+ xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(message, STANZA_NAME_BODY);
+ if (body) {
+ char *message = xmpp_stanza_get_text(body);
+ if (message) {
+ // if we are the recipient, treat as standard incoming message
+ if(g_strcmp0(my_jid->barejid, jid_to->barejid) == 0){
+ sv_ev_incoming_message(jid_from->barejid, jid_from->resourcepart, message);
+ }
+ // else treat as a sent message
+ else{
+ sv_ev_carbon(jid_to->barejid, message);
+ }
+ xmpp_free(ctx, message);
+ }
+ }
+
+ jid_destroy(jid_from);
+ jid_destroy(jid_to);
+ jid_destroy(my_jid);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int
+_chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
// ignore if type not chat or absent
char *type = xmpp_stanza_get_type(stanza);
@@ -423,6 +669,12 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
return 1;
}
+ // check if carbon message
+ gboolean res = _handle_carbons(stanza);
+ if (res) {
+ return 1;
+ }
+
// ignore handled namespaces
xmpp_stanza_t *conf = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE);
xmpp_stanza_t *mucuser = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
@@ -431,76 +683,57 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
return 1;
}
- xmpp_ctx_t *ctx = connection_get_ctx();
gchar *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
-
Jid *jid = jid_create(from);
// private message from chat room use full jid (room/nick)
if (muc_active(jid->barejid)) {
- // determine if the notifications happened whilst offline
- GTimeVal tv_stamp;
- gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
-
- // check for and deal with message
- xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
- if (body != NULL) {
- char *message = xmpp_stanza_get_text(body);
- if (message != NULL) {
- if (delayed) {
- handle_delayed_private_message(jid->str, message, tv_stamp);
- } else {
- handle_incoming_private_message(jid->str, message);
- }
- xmpp_free(ctx, message);
- }
- }
-
- jid_destroy(jid);
- return 1;
-
- // standard chat message, use jid without resource
- } else {
- // determine if the notifications happened whilst offline
- GTimeVal tv_stamp;
- gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
-
- // check for and deal with message
- xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
- if (body != NULL) {
- char *message = xmpp_stanza_get_text(body);
- if (message != NULL) {
- if (delayed) {
- handle_delayed_message(jid->barejid, message, tv_stamp);
- } else {
- handle_incoming_message(jid->barejid, jid->resourcepart, message);
- }
- xmpp_free(ctx, message);
- }
- }
-
- // handle chat sessions and states
- if (!delayed && jid->resourcepart) {
- gboolean gone = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL;
- gboolean typing = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_COMPOSING) != NULL;
- gboolean paused = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PAUSED) != NULL;
- gboolean inactive = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_INACTIVE) != NULL;
- if (gone) {
- handle_gone(jid->barejid, jid->resourcepart);
- } else if (typing) {
- handle_typing(jid->barejid, jid->resourcepart);
- } else if (paused) {
- handle_paused(jid->barejid, jid->resourcepart);
- } else if (inactive) {
- handle_inactive(jid->barejid, jid->resourcepart);
- } else if (stanza_contains_chat_state(stanza)) {
- handle_activity(jid->barejid, jid->resourcepart, TRUE);
- } else {
- handle_activity(jid->barejid, jid->resourcepart, FALSE);
- }
- }
-
- jid_destroy(jid);
+ _private_chat_handler(stanza, jid->fulljid);
return 1;
}
-}
\ No newline at end of file
+
+ // standard chat message, use jid without resource
+ GTimeVal tv_stamp;
+ gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
+
+ xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
+ if (body) {
+ char *message = xmpp_stanza_get_text(body);
+ if (message) {
+ if (delayed) {
+ sv_ev_delayed_message(jid->barejid, message, tv_stamp);
+ } else {
+ sv_ev_incoming_message(jid->barejid, jid->resourcepart, message);
+ }
+
+ _receipt_request_handler(stanza);
+
+ xmpp_ctx_t *ctx = connection_get_ctx();
+ xmpp_free(ctx, message);
+ }
+ }
+
+ // handle chat sessions and states
+ if (!delayed && jid->resourcepart) {
+ gboolean gone = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL;
+ gboolean typing = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_COMPOSING) != NULL;
+ gboolean paused = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PAUSED) != NULL;
+ gboolean inactive = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_INACTIVE) != NULL;
+ if (gone) {
+ sv_ev_gone(jid->barejid, jid->resourcepart);
+ } else if (typing) {
+ sv_ev_typing(jid->barejid, jid->resourcepart);
+ } else if (paused) {
+ sv_ev_paused(jid->barejid, jid->resourcepart);
+ } else if (inactive) {
+ sv_ev_inactive(jid->barejid, jid->resourcepart);
+ } else if (stanza_contains_chat_state(stanza)) {
+ sv_ev_activity(jid->barejid, jid->resourcepart, TRUE);
+ } else {
+ sv_ev_activity(jid->barejid, jid->resourcepart, FALSE);
+ }
+ }
+
+ jid_destroy(jid);
+ return 1;
+}
diff --git a/src/xmpp/message.h b/src/xmpp/message.h
index b3410dc9..6fbc27bd 100644
--- a/src/xmpp/message.h
+++ b/src/xmpp/message.h
@@ -1,7 +1,7 @@
/*
* message.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/xmpp/presence.c b/src/xmpp/presence.c
index 65384a0d..e46730e3 100644
--- a/src/xmpp/presence.c
+++ b/src/xmpp/presence.c
@@ -1,7 +1,7 @@
/*
* presence.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -44,7 +44,8 @@
#include "log.h"
#include "muc.h"
#include "profanity.h"
-#include "server_events.h"
+#include "ui/ui.h"
+#include "event/server_events.h"
#include "xmpp/capabilities.h"
#include "xmpp/connection.h"
#include "xmpp/stanza.h"
@@ -170,7 +171,7 @@ presence_sub_request_exists(const char * const bare_jid)
GSList *requests_p = autocomplete_create_list(sub_requests_ac);
GSList *requests = requests_p;
- while (requests != NULL) {
+ while (requests) {
if (strcmp(requests->data, bare_jid) == 0) {
result = TRUE;
break;
@@ -178,7 +179,7 @@ presence_sub_request_exists(const char * const bare_jid)
requests = g_slist_next(requests);
}
- if (requests_p != NULL) {
+ if (requests_p) {
g_slist_free_full(requests_p, free);
}
@@ -192,27 +193,22 @@ presence_reset_sub_request_search(void)
}
void
-presence_update(const resource_presence_t presence_type, const char * const msg,
- const int idle)
+presence_send(const resource_presence_t presence_type, const char * const msg, const int idle)
{
if (jabber_get_connection_status() != JABBER_CONNECTED) {
log_warning("Error setting presence, not connected.");
return;
}
- if (msg != NULL) {
- log_debug("Updating presence: %s, \"%s\"",
- string_from_resource_presence(presence_type), msg);
+ if (msg) {
+ log_debug("Updating presence: %s, \"%s\"", string_from_resource_presence(presence_type), msg);
} else {
- log_debug("Updating presence: %s",
- string_from_resource_presence(presence_type));
+ log_debug("Updating presence: %s", string_from_resource_presence(presence_type));
}
xmpp_ctx_t * const ctx = connection_get_ctx();
xmpp_conn_t * const conn = connection_get_conn();
- const int pri =
- accounts_get_priority_for_presence_type(jabber_get_account_name(),
- presence_type);
+ const int pri = accounts_get_priority_for_presence_type(jabber_get_account_name(), presence_type);
const char *show = stanza_get_presence_string_from_type(presence_type);
connection_set_presence_message(msg);
@@ -245,11 +241,11 @@ _send_room_presence(xmpp_conn_t *conn, xmpp_stanza_t *presence)
GList *rooms_p = muc_rooms();
GList *rooms = rooms_p;
- while (rooms != NULL) {
+ while (rooms) {
const char *room = rooms->data;
const char *nick = muc_nick(room);
- if (nick != NULL) {
+ if (nick) {
char *full_room_jid = create_fulljid(room, nick);
xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, full_room_jid);
@@ -261,7 +257,7 @@ _send_room_presence(xmpp_conn_t *conn, xmpp_stanza_t *presence)
rooms = g_list_next(rooms);
}
- if (rooms_p != NULL) {
+ if (rooms_p) {
g_list_free(rooms_p);
}
}
@@ -333,7 +329,7 @@ presence_leave_chat_room(const char * const room_jid)
xmpp_conn_t *conn = connection_get_conn();
char *nick = muc_nick(room_jid);
- if (nick != NULL) {
+ if (nick) {
xmpp_stanza_t *presence = stanza_create_room_leave_presence(ctx, room_jid,
nick);
xmpp_send(conn, presence);
@@ -350,11 +346,11 @@ _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
char *xmlns = NULL;
- if (x != NULL) {
+ if (x) {
xmlns = xmpp_stanza_get_ns(x);
}
char *type = NULL;
- if (error_stanza != NULL) {
+ if (error_stanza) {
type = xmpp_stanza_get_attribute(error_stanza, STANZA_ATTR_TYPE);
}
@@ -364,7 +360,7 @@ _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
char *error_cond = NULL;
xmpp_stanza_t *reason_st = xmpp_stanza_get_child_by_ns(error_stanza, STANZA_NS_STANZAS);
- if (reason_st != NULL) {
+ if (reason_st) {
error_cond = xmpp_stanza_get_name(reason_st);
}
if (error_cond == NULL) {
@@ -372,7 +368,10 @@ _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
}
log_info("Error joining room: %s, reason: %s", fulljid->barejid, error_cond);
- handle_room_join_error(fulljid->barejid, error_cond);
+ if (muc_active(fulljid->barejid)) {
+ muc_leave(fulljid->barejid);
+ }
+ ui_handle_room_join_error(fulljid->barejid, error_cond);
jid_destroy(fulljid);
return 1;
}
@@ -381,15 +380,15 @@ _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
char *err_msg = stanza_get_error_message(stanza);
GString *log_msg = g_string_new("presence stanza error received");
- if (id != NULL) {
+ if (id) {
g_string_append(log_msg, " id=");
g_string_append(log_msg, id);
}
- if (from != NULL) {
+ if (from) {
g_string_append(log_msg, " from=");
g_string_append(log_msg, from);
}
- if (type != NULL) {
+ if (type) {
g_string_append(log_msg, " type=");
g_string_append(log_msg, type);
}
@@ -400,7 +399,11 @@ _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
g_string_free(log_msg, TRUE);
- handle_presence_error(from, type, err_msg);
+ if (from) {
+ ui_handle_recipient_error(from, err_msg);
+ } else {
+ ui_handle_error(err_msg);
+ }
free(err_msg);
@@ -416,7 +419,7 @@ _unsubscribed_handler(xmpp_conn_t * const conn,
Jid *from_jid = jid_create(from);
log_debug("Unsubscribed presence handler fired for %s", from);
- handle_subscription(from_jid->barejid, PRESENCE_UNSUBSCRIBED);
+ sv_ev_subscription(from_jid->barejid, PRESENCE_UNSUBSCRIBED);
autocomplete_remove(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid);
@@ -432,7 +435,7 @@ _subscribed_handler(xmpp_conn_t * const conn,
Jid *from_jid = jid_create(from);
log_debug("Subscribed presence handler fired for %s", from);
- handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBED);
+ sv_ev_subscription(from_jid->barejid, PRESENCE_SUBSCRIBED);
autocomplete_remove(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid);
@@ -452,7 +455,7 @@ _subscribe_handler(xmpp_conn_t * const conn,
return 1;
}
- handle_subscription(from_jid->barejid, PRESENCE_SUBSCRIBE);
+ sv_ev_subscription(from_jid->barejid, PRESENCE_SUBSCRIBE);
autocomplete_add(sub_requests_ac, from_jid->barejid);
jid_destroy(from_jid);
@@ -464,6 +467,8 @@ static int
_unavailable_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata)
{
+ ui_input_nonblocking(TRUE);
+
const char *jid = xmpp_conn_get_jid(conn);
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
log_debug("Unavailable presence handler fired for %s", from);
@@ -479,15 +484,15 @@ _unavailable_handler(xmpp_conn_t * const conn,
char *status_str = stanza_get_status(stanza, NULL);
if (strcmp(my_jid->barejid, from_jid->barejid) !=0) {
- if (from_jid->resourcepart != NULL) {
- handle_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str);
+ if (from_jid->resourcepart) {
+ sv_ev_contact_offline(from_jid->barejid, from_jid->resourcepart, status_str);
// hack for servers that do not send full jid with unavailable presence
} else {
- handle_contact_offline(from_jid->barejid, "__prof_default", status_str);
+ sv_ev_contact_offline(from_jid->barejid, "__prof_default", status_str);
}
} else {
- if (from_jid->resourcepart != NULL) {
+ if (from_jid->resourcepart) {
connection_remove_available_resource(from_jid->resourcepart);
}
}
@@ -517,7 +522,7 @@ _handle_caps(char *jid, XMPPCaps *caps)
}
}
- // unsupported hash, xep-0115, assoiciate with JID, no cache
+ // unsupported hash, xep-0115, associate with JID, no cache
} else if (caps->hash) {
log_info("Hash %s not supported: %s, sending service discovery request", caps->hash, jid);
char *id = create_unique_id("caps");
@@ -539,6 +544,8 @@ static int
_available_handler(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza, void * const userdata)
{
+ ui_input_nonblocking(TRUE);
+
// handler still fires if error
if (g_strcmp0(xmpp_stanza_get_type(stanza), STANZA_TYPE_ERROR) == 0) {
return 1;
@@ -596,7 +603,7 @@ _available_handler(xmpp_conn_t * const conn,
if (g_strcmp0(xmpp_presence->jid->barejid, my_jid->barejid) == 0) {
connection_add_available_resource(resource);
} else {
- handle_contact_online(xmpp_presence->jid->barejid, resource, xmpp_presence->last_activity);
+ sv_ev_contact_online(xmpp_presence->jid->barejid, resource, xmpp_presence->last_activity);
}
jid_destroy(my_jid);
@@ -611,7 +618,7 @@ _send_caps_request(char *node, char *caps_key, char *id, char *from)
xmpp_ctx_t *ctx = connection_get_ctx();
xmpp_conn_t *conn = connection_get_conn();
- if (node != NULL) {
+ if (node) {
log_debug("Node string: %s.", node);
if (!caps_contains(caps_key)) {
log_debug("Capabilities not cached for '%s', sending discovery IQ.", from);
@@ -629,6 +636,8 @@ _send_caps_request(char *node, char *caps_key, char *id, char *from)
static int
_muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
+ ui_input_nonblocking(TRUE);
+
char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE);
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
@@ -682,27 +691,27 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void *
char *new_jid = stanza_get_muc_destroy_alternative_room(stanza);
char *password = stanza_get_muc_destroy_alternative_password(stanza);
char *reason = stanza_get_muc_destroy_reason(stanza);
- handle_room_destroyed(room, new_jid, password, reason);
+ sv_ev_room_destroyed(room, new_jid, password, reason);
free(password);
free(reason);
// kicked from room
- } else if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0) != NULL) {
+ } else if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0)) {
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
- handle_room_kicked(room, actor, reason);
+ sv_ev_room_kicked(room, actor, reason);
free(reason);
// banned from room
- } else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0) != NULL) {
+ } else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0)) {
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
- handle_room_banned(room, actor, reason);
+ sv_ev_room_banned(room, actor, reason);
free(reason);
// normal exit
} else {
- handle_leave_room(room);
+ sv_ev_leave_room(room);
}
g_slist_free_full(status_codes, free);
@@ -713,7 +722,7 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void *
gboolean config_required = stanza_muc_requires_config(stanza);
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
- handle_muc_self_online(room, nick, config_required, role, affiliation, actor, reason, jid, show_str, status_str);
+ sv_ev_muc_self_online(room, nick, config_required, role, affiliation, actor, reason, jid, show_str, status_str);
}
// handle presence from room members
@@ -732,22 +741,22 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void *
GSList *status_codes = stanza_get_status_codes_by_ns(stanza, STANZA_NS_MUC_USER);
// kicked from room
- if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0) != NULL) {
+ if (g_slist_find_custom(status_codes, "307", (GCompareFunc)g_strcmp0)) {
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
- handle_room_occupent_kicked(room, nick, actor, reason);
+ sv_ev_room_occupent_kicked(room, nick, actor, reason);
free(reason);
// banned from room
- } else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0) != NULL) {
+ } else if (g_slist_find_custom(status_codes, "301", (GCompareFunc)g_strcmp0)) {
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
- handle_room_occupent_banned(room, nick, actor, reason);
+ sv_ev_room_occupent_banned(room, nick, actor, reason);
free(reason);
// normal exit
} else {
- handle_room_occupant_offline(room, nick, "offline", status_str);
+ sv_ev_room_occupant_offline(room, nick, "offline", status_str);
}
g_slist_free_full(status_codes, free);
@@ -765,7 +774,7 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void *
char *actor = stanza_get_actor(stanza);
char *reason = stanza_get_reason(stanza);
- handle_muc_occupant_online(room, nick, jid, role, affiliation, actor, reason, show_str, status_str);
+ sv_ev_muc_occupant_online(room, nick, jid, role, affiliation, actor, reason, show_str, status_str);
}
}
diff --git a/src/xmpp/presence.h b/src/xmpp/presence.h
index e704aea0..90b83473 100644
--- a/src/xmpp/presence.h
+++ b/src/xmpp/presence.h
@@ -1,7 +1,7 @@
/*
* presence.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/xmpp/roster.c b/src/xmpp/roster.c
index 3449c8d5..5c9fa5d4 100644
--- a/src/xmpp/roster.c
+++ b/src/xmpp/roster.c
@@ -1,7 +1,7 @@
/*
* roster.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -41,7 +41,9 @@
#include "log.h"
#include "profanity.h"
-#include "server_events.h"
+#include "ui/ui.h"
+#include "event/server_events.h"
+#include "event/client_events.h"
#include "tools/autocomplete.h"
#include "xmpp/connection.h"
#include "xmpp/roster.h"
@@ -131,7 +133,7 @@ roster_send_add_to_group(const char * const group, PContact contact)
{
GSList *groups = p_contact_groups(contact);
GSList *new_groups = NULL;
- while (groups != NULL) {
+ while (groups) {
new_groups = g_slist_append(new_groups, strdup(groups->data));
groups = g_slist_next(groups);
}
@@ -141,7 +143,7 @@ roster_send_add_to_group(const char * const group, PContact contact)
char *unique_id = create_unique_id(NULL);
GroupData *data = malloc(sizeof(GroupData));
data->group = strdup(group);
- if (p_contact_name(contact) != NULL) {
+ if (p_contact_name(contact)) {
data->name = strdup(p_contact_name(contact));
} else {
data->name = strdup(p_contact_barejid(contact));
@@ -161,9 +163,9 @@ static int
_group_add_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
{
- if (userdata != NULL) {
+ if (userdata) {
GroupData *data = userdata;
- handle_group_add(data->name, data->group);
+ ui_group_added(data->name, data->group);
free(data->name);
free(data->group);
free(userdata);
@@ -176,7 +178,7 @@ roster_send_remove_from_group(const char * const group, PContact contact)
{
GSList *groups = p_contact_groups(contact);
GSList *new_groups = NULL;
- while (groups != NULL) {
+ while (groups) {
if (strcmp(groups->data, group) != 0) {
new_groups = g_slist_append(new_groups, strdup(groups->data));
}
@@ -190,7 +192,7 @@ roster_send_remove_from_group(const char * const group, PContact contact)
char *unique_id = create_unique_id(NULL);
GroupData *data = malloc(sizeof(GroupData));
data->group = strdup(group);
- if (p_contact_name(contact) != NULL) {
+ if (p_contact_name(contact)) {
data->name = strdup(p_contact_name(contact));
} else {
data->name = strdup(p_contact_barejid(contact));
@@ -208,9 +210,9 @@ static int
_group_remove_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
void * const userdata)
{
- if (userdata != NULL) {
+ if (userdata) {
GroupData *data = userdata;
- handle_group_remove(data->name, data->group);
+ ui_group_removed(data->name, data->group);
free(data->name);
free(data->group);
free(userdata);
@@ -234,13 +236,14 @@ _roster_set_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
// if from attribute exists and it is not current users barejid, ignore push
Jid *my_jid = jid_create(jabber_get_fulljid());
const char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
- if ((from != NULL) && (strcmp(from, my_jid->barejid) != 0)) {
+ if (from && (strcmp(from, my_jid->barejid) != 0)) {
jid_destroy(my_jid);
return 1;
}
jid_destroy(my_jid);
const char *barejid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID);
+ gchar *barejid_lower = g_utf8_strdown(barejid, -1);
const char *name = xmpp_stanza_get_attribute(item, STANZA_ATTR_NAME);
const char *sub = xmpp_stanza_get_attribute(item, STANZA_ATTR_SUBSCRIPTION);
const char *ask = xmpp_stanza_get_attribute(item, STANZA_ATTR_ASK);
@@ -254,83 +257,83 @@ _roster_set_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
if (g_strcmp0(sub, "remove") == 0) {
// remove barejid and name
if (name == NULL) {
- name = barejid;
+ name = barejid_lower;
}
-
- roster_remove(name, barejid);
-
- handle_roster_remove(barejid);
+ roster_remove(name, barejid_lower);
+ ui_roster_remove(barejid_lower);
// otherwise update local roster
} else {
// check for pending out subscriptions
gboolean pending_out = FALSE;
- if ((ask != NULL) && (strcmp(ask, "subscribe") == 0)) {
+ if (ask && (strcmp(ask, "subscribe") == 0)) {
pending_out = TRUE;
}
GSList *groups = _get_groups_from_item(item);
// update the local roster
- PContact contact = roster_get_contact(barejid);
+ PContact contact = roster_get_contact(barejid_lower);
if (contact == NULL) {
- gboolean added = roster_add(barejid, name, groups, sub, pending_out);
+ gboolean added = roster_add(barejid_lower, name, groups, sub, pending_out);
if (added) {
- handle_roster_add(barejid, name);
+ ui_roster_add(barejid_lower, name);
}
} else {
- handle_roster_update(barejid, name, groups, sub, pending_out);
+ sv_ev_roster_update(barejid_lower, name, groups, sub, pending_out);
}
}
+ g_free(barejid_lower);
+
return 1;
}
static int
-_roster_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
- void * const userdata)
+_roster_result_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata)
{
const char *id = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_ID);
+ if (g_strcmp0(id, "roster") != 0) {
+ return 1;
+ }
+
// handle initial roster response
- if (g_strcmp0(id, "roster") == 0) {
- xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
- xmpp_stanza_t *item = xmpp_stanza_get_children(query);
+ xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
+ xmpp_stanza_t *item = xmpp_stanza_get_children(query);
- while (item != NULL) {
- const char *barejid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID);
- const char *name = xmpp_stanza_get_attribute(item, STANZA_ATTR_NAME);
- const char *sub = xmpp_stanza_get_attribute(item, STANZA_ATTR_SUBSCRIPTION);
+ while (item) {
+ const char *barejid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID);
+ gchar *barejid_lower = g_utf8_strdown(barejid, -1);
+ const char *name = xmpp_stanza_get_attribute(item, STANZA_ATTR_NAME);
+ const char *sub = xmpp_stanza_get_attribute(item, STANZA_ATTR_SUBSCRIPTION);
- // do not set nickname to empty string, set to NULL instead
- if (name && (strlen(name) == 0)) {
- name = NULL;
- }
+ // do not set nickname to empty string, set to NULL instead
+ if (name && (strlen(name) == 0)) name = NULL;
- gboolean pending_out = FALSE;
- const char *ask = xmpp_stanza_get_attribute(item, STANZA_ATTR_ASK);
- if (g_strcmp0(ask, "subscribe") == 0) {
- pending_out = TRUE;
- }
-
- GSList *groups = _get_groups_from_item(item);
-
- gboolean added = roster_add(barejid, name, groups, sub, pending_out);
-
- if (!added) {
- log_warning("Attempt to add contact twice: %s", barejid);
- }
-
- item = xmpp_stanza_get_next(item);
+ gboolean pending_out = FALSE;
+ const char *ask = xmpp_stanza_get_attribute(item, STANZA_ATTR_ASK);
+ if (g_strcmp0(ask, "subscribe") == 0) {
+ pending_out = TRUE;
}
- handle_roster_received();
+ GSList *groups = _get_groups_from_item(item);
- resource_presence_t conn_presence = accounts_get_login_presence(jabber_get_account_name());
- presence_update(conn_presence, NULL, 0);
+ gboolean added = roster_add(barejid_lower, name, groups, sub, pending_out);
+ if (!added) {
+ log_warning("Attempt to add contact twice: %s", barejid_lower);
+ }
+
+ g_free(barejid_lower);
+ item = xmpp_stanza_get_next(item);
}
+ sv_ev_roster_received();
+
+ resource_presence_t conn_presence = accounts_get_login_presence(jabber_get_account_name());
+ cl_ev_presence_send(conn_presence, NULL, 0);
+
return 1;
}
@@ -340,10 +343,10 @@ _get_groups_from_item(xmpp_stanza_t *item)
GSList *groups = NULL;
xmpp_stanza_t *group_element = xmpp_stanza_get_children(item);
- while (group_element != NULL) {
+ while (group_element) {
if (strcmp(xmpp_stanza_get_name(group_element), STANZA_NAME_GROUP) == 0) {
char *groupname = xmpp_stanza_get_text(group_element);
- if (groupname != NULL) {
+ if (groupname) {
groups = g_slist_append(groups, groupname);
}
}
diff --git a/src/xmpp/roster.h b/src/xmpp/roster.h
index c29a674a..68811a5c 100644
--- a/src/xmpp/roster.h
+++ b/src/xmpp/roster.h
@@ -1,7 +1,7 @@
/*
* roster.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index 4f1d412d..1f25239b 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -1,7 +1,7 @@
/*
* stanza.c
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -141,7 +141,7 @@ stanza_create_bookmarks_pubsub_add(xmpp_ctx_t *ctx, const char * const jid,
xmpp_stanza_set_attribute(conference, STANZA_ATTR_AUTOJOIN, "false");
}
- if (nick != NULL) {
+ if (nick) {
xmpp_stanza_t *nick_st = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(nick_st, STANZA_NAME_NICK);
xmpp_stanza_set_text(nick_st, nick);
@@ -198,6 +198,44 @@ stanza_create_bookmarks_pubsub_add(xmpp_ctx_t *ctx, const char * const jid,
}
#endif
+xmpp_stanza_t *
+stanza_enable_carbons(xmpp_ctx_t *ctx){
+ xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
+ char *id = create_unique_id("carbons");
+
+ xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
+ xmpp_stanza_set_type(iq, STANZA_TYPE_SET);
+ xmpp_stanza_set_id(iq, id);
+ free(id);
+
+ xmpp_stanza_t *carbons_enable = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(carbons_enable, STANZA_NAME_ENABLE);
+ xmpp_stanza_set_ns(carbons_enable, STANZA_NS_CARBONS);
+
+ xmpp_stanza_add_child(iq, carbons_enable);
+
+ return iq;
+}
+
+xmpp_stanza_t *
+stanza_disable_carbons(xmpp_ctx_t *ctx){
+ xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
+ char *id = create_unique_id("carbons");
+
+ xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
+ xmpp_stanza_set_type(iq, STANZA_TYPE_SET);
+ xmpp_stanza_set_id(iq, id);
+ free(id);
+
+ xmpp_stanza_t *carbons_disable = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(carbons_disable, STANZA_NAME_DISABLE);
+ xmpp_stanza_set_ns(carbons_disable, STANZA_NS_CARBONS);
+
+ xmpp_stanza_add_child(iq, carbons_disable);
+
+ return iq;
+}
+
xmpp_stanza_t *
stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const fulljid, const char * const state)
{
@@ -244,9 +282,44 @@ stanza_create_room_subject_message(xmpp_ctx_t *ctx, const char * const room, con
}
xmpp_stanza_t *
-stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient,
- const char * const type, const char * const message,
- const char * const state)
+stanza_attach_state(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char * const state)
+{
+ xmpp_stanza_t *chat_state = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(chat_state, state);
+ xmpp_stanza_set_ns(chat_state, STANZA_NS_CHATSTATES);
+ xmpp_stanza_add_child(stanza, chat_state);
+ xmpp_stanza_release(chat_state);
+
+ return stanza;
+}
+
+xmpp_stanza_t *
+stanza_attach_carbons_private(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza)
+{
+ xmpp_stanza_t *private_carbon = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(private_carbon, "private");
+ xmpp_stanza_set_ns(private_carbon, STANZA_NS_CARBONS);
+ xmpp_stanza_add_child(stanza, private_carbon);
+ xmpp_stanza_release(private_carbon);
+
+ return stanza;
+}
+
+xmpp_stanza_t *
+stanza_attach_receipt_request(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza)
+{
+ xmpp_stanza_t *receipet_request = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(receipet_request, "request");
+ xmpp_stanza_set_ns(receipet_request, STANZA_NS_RECEIPTS);
+ xmpp_stanza_add_child(stanza, receipet_request);
+ xmpp_stanza_release(receipet_request);
+
+ return stanza;
+}
+
+xmpp_stanza_t *
+stanza_create_message(xmpp_ctx_t *ctx, char *id, const char * const recipient,
+ const char * const type, const char * const message)
{
xmpp_stanza_t *msg, *body, *text;
@@ -254,9 +327,7 @@ stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient,
xmpp_stanza_set_name(msg, STANZA_NAME_MESSAGE);
xmpp_stanza_set_type(msg, type);
xmpp_stanza_set_attribute(msg, STANZA_ATTR_TO, recipient);
- char *id = create_unique_id(NULL);
xmpp_stanza_set_id(msg, id);
- free(id);
body = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(body, STANZA_NAME_BODY);
@@ -268,14 +339,6 @@ stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient,
xmpp_stanza_add_child(msg, body);
xmpp_stanza_release(body);
- if (state != NULL) {
- xmpp_stanza_t *chat_state = xmpp_stanza_new(ctx);
- xmpp_stanza_set_name(chat_state, state);
- xmpp_stanza_set_ns(chat_state, STANZA_NS_CHATSTATES);
- xmpp_stanza_add_child(msg, chat_state);
- xmpp_stanza_release(chat_state);
- }
-
return msg;
}
@@ -311,7 +374,7 @@ stanza_create_roster_set(xmpp_ctx_t *ctx, const char * const id,
xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
xmpp_stanza_set_type(iq, STANZA_TYPE_SET);
- if (id != NULL) {
+ if (id) {
xmpp_stanza_set_id(iq, id);
}
@@ -323,13 +386,13 @@ stanza_create_roster_set(xmpp_ctx_t *ctx, const char * const id,
xmpp_stanza_set_name(item, STANZA_NAME_ITEM);
xmpp_stanza_set_attribute(item, STANZA_ATTR_JID, jid);
- if (handle != NULL) {
+ if (handle) {
xmpp_stanza_set_attribute(item, STANZA_ATTR_NAME, handle);
} else {
xmpp_stanza_set_attribute(item, STANZA_ATTR_NAME, "");
}
- while (groups != NULL) {
+ while (groups) {
xmpp_stanza_t *group = xmpp_stanza_new(ctx);
xmpp_stanza_t *groupname = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(group, STANZA_NAME_GROUP);
@@ -351,7 +414,7 @@ stanza_create_roster_set(xmpp_ctx_t *ctx, const char * const id,
xmpp_stanza_t *
stanza_create_invite(xmpp_ctx_t *ctx, const char * const room,
- const char * const contact, const char * const reason)
+ const char * const contact, const char * const reason, const char * const password)
{
xmpp_stanza_t *message, *x;
@@ -367,9 +430,12 @@ stanza_create_invite(xmpp_ctx_t *ctx, const char * const room,
xmpp_stanza_set_ns(x, STANZA_NS_CONFERENCE);
xmpp_stanza_set_attribute(x, STANZA_ATTR_JID, room);
- if (reason != NULL) {
+ if (reason) {
xmpp_stanza_set_attribute(x, STANZA_ATTR_REASON, reason);
}
+ if (password) {
+ xmpp_stanza_set_attribute(x, STANZA_ATTR_PASSWORD, password);
+ }
xmpp_stanza_add_child(message, x);
xmpp_stanza_release(x);
@@ -377,6 +443,46 @@ stanza_create_invite(xmpp_ctx_t *ctx, const char * const room,
return message;
}
+xmpp_stanza_t *
+stanza_create_mediated_invite(xmpp_ctx_t *ctx, const char * const room,
+ const char * const contact, const char * const reason)
+{
+ xmpp_stanza_t *message, *x, *invite;
+
+ message = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(message, STANZA_NAME_MESSAGE);
+ xmpp_stanza_set_attribute(message, STANZA_ATTR_TO, room);
+ char *id = create_unique_id(NULL);
+ xmpp_stanza_set_id(message, id);
+ free(id);
+
+ x = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(x, STANZA_NAME_X);
+ xmpp_stanza_set_ns(x, STANZA_NS_MUC_USER);
+
+ invite = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(invite, STANZA_NAME_INVITE);
+ xmpp_stanza_set_attribute(invite, STANZA_ATTR_TO, contact);
+
+ if (reason) {
+ xmpp_stanza_t *reason_st = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(reason_st, STANZA_NAME_REASON);
+ xmpp_stanza_t *reason_txt = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_text(reason_txt, reason);
+ xmpp_stanza_add_child(reason_st, reason_txt);
+ xmpp_stanza_release(reason_txt);
+ xmpp_stanza_add_child(invite, reason_st);
+ xmpp_stanza_release(reason_st);
+ }
+
+ xmpp_stanza_add_child(x, invite);
+ xmpp_stanza_release(invite);
+ xmpp_stanza_add_child(message, x);
+ xmpp_stanza_release(x);
+
+ return message;
+}
+
xmpp_stanza_t *
stanza_create_room_join_presence(xmpp_ctx_t * const ctx,
const char * const full_room_jid, const char * const passwd)
@@ -393,7 +499,7 @@ stanza_create_room_join_presence(xmpp_ctx_t * const ctx,
xmpp_stanza_set_ns(x, STANZA_NS_MUC);
// if a password was given
- if (passwd != NULL) {
+ if (passwd) {
xmpp_stanza_t *pass = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(pass, "password");
xmpp_stanza_t *text = xmpp_stanza_new(ctx);
@@ -787,7 +893,7 @@ stanza_create_disco_info_iq(xmpp_ctx_t *ctx, const char * const id, const char *
xmpp_stanza_t *query = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(query, STANZA_NAME_QUERY);
xmpp_stanza_set_ns(query, XMPP_NS_DISCO_INFO);
- if (node != NULL) {
+ if (node) {
xmpp_stanza_set_attribute(query, STANZA_ATTR_NODE, node);
}
@@ -858,7 +964,7 @@ stanza_create_ping_iq(xmpp_ctx_t *ctx, const char * const target)
xmpp_stanza_t *iq = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(iq, STANZA_NAME_IQ);
xmpp_stanza_set_type(iq, STANZA_TYPE_GET);
- if (target != NULL) {
+ if (target) {
xmpp_stanza_set_attribute(iq, STANZA_ATTR_TO, target);
}
char *id = create_unique_id("ping");
@@ -881,11 +987,11 @@ stanza_get_delay(xmpp_stanza_t * const stanza, GTimeVal *tv_stamp)
{
// first check for XEP-0203 delayed delivery
xmpp_stanza_t *delay = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_DELAY);
- if (delay != NULL) {
+ if (delay) {
char *xmlns = xmpp_stanza_get_attribute(delay, STANZA_ATTR_XMLNS);
- if ((xmlns != NULL) && (strcmp(xmlns, "urn:xmpp:delay") == 0)) {
+ if (xmlns && (strcmp(xmlns, "urn:xmpp:delay") == 0)) {
char *stamp = xmpp_stanza_get_attribute(delay, STANZA_ATTR_STAMP);
- if ((stamp != NULL) && (g_time_val_from_iso8601(stamp, tv_stamp))) {
+ if (stamp && (g_time_val_from_iso8601(stamp, tv_stamp))) {
return TRUE;
}
}
@@ -894,11 +1000,11 @@ stanza_get_delay(xmpp_stanza_t * const stanza, GTimeVal *tv_stamp)
// otherwise check for XEP-0091 legacy delayed delivery
// stanp format : CCYYMMDDThh:mm:ss
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
- if (x != NULL) {
+ if (x) {
char *xmlns = xmpp_stanza_get_attribute(x, STANZA_ATTR_XMLNS);
- if ((xmlns != NULL) && (strcmp(xmlns, "jabber:x:delay") == 0)) {
+ if (xmlns && (strcmp(xmlns, "jabber:x:delay") == 0)) {
char *stamp = xmpp_stanza_get_attribute(x, STANZA_ATTR_STAMP);
- if ((stamp != NULL) && (g_time_val_from_iso8601(stamp, tv_stamp))) {
+ if (stamp && (g_time_val_from_iso8601(stamp, tv_stamp))) {
return TRUE;
}
}
@@ -914,17 +1020,17 @@ stanza_get_status(xmpp_stanza_t *stanza, char *def)
xmpp_stanza_t *status =
xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_STATUS);
- if (status != NULL) {
+ if (status) {
// xmpp_free and free may be different functions so convert all to
// libc malloc
char *s1, *s2 = NULL;
s1 = xmpp_stanza_get_text(status);
- if (s1 != NULL) {
+ if (s1) {
s2 = strdup(s1);
xmpp_free(ctx, s1);
}
return s2;
- } else if (def != NULL) {
+ } else if (def) {
return strdup(def);
} else {
return NULL;
@@ -938,17 +1044,17 @@ stanza_get_show(xmpp_stanza_t *stanza, char *def)
xmpp_stanza_t *show =
xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_SHOW);
- if (show != NULL) {
+ if (show) {
// xmpp_free and free may be different functions so convert all to
// libc malloc
char *s1, *s2 = NULL;
s1 = xmpp_stanza_get_text(show);
- if (s1 != NULL) {
+ if (s1) {
s2 = strdup(s1);
xmpp_free(ctx, s1);
}
return s2;
- } else if (def != NULL) {
+ } else if (def) {
return strdup(def);
} else {
return NULL;
@@ -984,7 +1090,7 @@ stanza_muc_requires_config(xmpp_stanza_t * const stanza)
// muc user namespaced x element
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
- if (x != NULL) {
+ if (x) {
// check for item element with owner affiliation
xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, "item");
@@ -998,7 +1104,7 @@ stanza_muc_requires_config(xmpp_stanza_t * const stanza)
// check for status code 201
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x);
- while (x_children != NULL) {
+ while (x_children) {
if (g_strcmp0(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) {
char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE);
if (g_strcmp0(code, "201") == 0) {
@@ -1240,11 +1346,11 @@ stanza_is_room_nick_change(xmpp_stanza_t * const stanza)
// muc user namespaced x element
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
- if (x != NULL) {
+ if (x) {
// check for status child element with 303 code
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x);
- while (x_children != NULL) {
+ while (x_children) {
if (g_strcmp0(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) {
char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE);
if (g_strcmp0(code, "303") == 0) {
@@ -1268,7 +1374,7 @@ stanza_get_new_nick(xmpp_stanza_t * const stanza)
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x);
- while (x_children != NULL) {
+ while (x_children) {
if (strcmp(xmpp_stanza_get_name(x_children), STANZA_NAME_ITEM) == 0) {
char *nick = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_NICK);
if (nick) {
@@ -1382,9 +1488,9 @@ stanza_get_error_message(xmpp_stanza_t *stanza)
xmpp_stanza_t *text_stanza = xmpp_stanza_get_child_by_name(error_stanza, STANZA_NAME_TEXT);
// check for text
- if (text_stanza != NULL) {
+ if (text_stanza) {
gchar *err_msg = xmpp_stanza_get_text(text_stanza);
- if (err_msg != NULL) {
+ if (err_msg) {
char *result = strdup(err_msg);
xmpp_free(ctx, err_msg);
return result;
@@ -1419,7 +1525,7 @@ stanza_get_error_message(xmpp_stanza_t *stanza)
int i;
for (i = 0; i < ARRAY_SIZE(defined_conditions); i++) {
xmpp_stanza_t *cond_stanza = xmpp_stanza_get_child_by_name(error_stanza, defined_conditions[i]);
- if (cond_stanza != NULL) {
+ if (cond_stanza) {
char *result = strdup(xmpp_stanza_get_name(cond_stanza));
return result;
}
@@ -1456,7 +1562,7 @@ void
stanza_attach_show(xmpp_ctx_t * const ctx, xmpp_stanza_t * const presence,
const char * const show)
{
- if (show != NULL) {
+ if (show) {
xmpp_stanza_t *show_stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(show_stanza, STANZA_NAME_SHOW);
xmpp_stanza_t *text = xmpp_stanza_new(ctx);
@@ -1472,7 +1578,7 @@ void
stanza_attach_status(xmpp_ctx_t * const ctx, xmpp_stanza_t * const presence,
const char * const status)
{
- if (status != NULL) {
+ if (status) {
xmpp_stanza_t *status_stanza = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(status_stanza, STANZA_NAME_STATUS);
xmpp_stanza_t *text = xmpp_stanza_new(ctx);
@@ -1619,9 +1725,9 @@ stanza_parse_presence(xmpp_stanza_t *stanza, int *err)
result->priority = 0;
xmpp_stanza_t *priority_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PRIORITY);
- if (priority_stanza != NULL) {
+ if (priority_stanza) {
char *priority_str = xmpp_stanza_get_text(priority_stanza);
- if (priority_str != NULL) {
+ if (priority_str) {
result->priority = atoi(priority_str);
}
free(priority_str);
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index 84282401..89dbda57 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -1,7 +1,7 @@
/*
* stanza.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -77,6 +77,8 @@
#define STANZA_NAME_VALUE "value"
#define STANZA_NAME_DESTROY "destroy"
#define STANZA_NAME_ACTOR "actor"
+#define STANZA_NAME_ENABLE "enable"
+#define STANZA_NAME_DISABLE "disable"
// error conditions
#define STANZA_NAME_BAD_REQUEST "bad-request"
@@ -133,6 +135,7 @@
#define STANZA_ATTR_CATEGORY "category"
#define STANZA_ATTR_REASON "reason"
#define STANZA_ATTR_AUTOJOIN "autojoin"
+#define STANZA_ATTR_PASSWORD "password"
#define STANZA_TEXT_AWAY "away"
#define STANZA_TEXT_DND "dnd"
@@ -154,6 +157,9 @@
#define STANZA_NS_CONFERENCE "jabber:x:conference"
#define STANZA_NS_CAPTCHA "urn:xmpp:captcha"
#define STANZA_NS_PUBSUB "http://jabber.org/protocol/pubsub"
+#define STANZA_NS_CARBONS "urn:xmpp:carbons:2"
+#define STANZA_NS_FORWARD "urn:xmpp:forward:0"
+#define STANZA_NS_RECEIPTS "urn:xmpp:receipts"
#define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
@@ -178,12 +184,19 @@ typedef enum {
xmpp_stanza_t* stanza_create_bookmarks_storage_request(xmpp_ctx_t *ctx);
+xmpp_stanza_t * stanza_enable_carbons(xmpp_ctx_t *ctx);
+
+xmpp_stanza_t * stanza_disable_carbons(xmpp_ctx_t *ctx);
+
xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx,
const char * const fulljid, const char * const state);
-xmpp_stanza_t* stanza_create_message(xmpp_ctx_t *ctx,
- const char * const recipient, const char * const type,
- const char * const message, const char * const state);
+xmpp_stanza_t * stanza_attach_state(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza, const char * const state);
+xmpp_stanza_t * stanza_attach_carbons_private(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza);
+xmpp_stanza_t * stanza_attach_receipt_request(xmpp_ctx_t *ctx, xmpp_stanza_t *stanza);
+
+xmpp_stanza_t* stanza_create_message(xmpp_ctx_t *ctx, char *id,
+ const char * const recipient, const char * const type, const char * const message);
xmpp_stanza_t* stanza_create_room_join_presence(xmpp_ctx_t * const ctx,
const char * const full_room_jid, const char * const passwd);
@@ -202,6 +215,8 @@ xmpp_stanza_t* stanza_create_disco_info_iq(xmpp_ctx_t *ctx, const char * const i
const char * const to, const char * const node);
xmpp_stanza_t* stanza_create_invite(xmpp_ctx_t *ctx, const char * const room,
+ const char * const contact, const char * const reason, const char * const password);
+xmpp_stanza_t* stanza_create_mediated_invite(xmpp_ctx_t *ctx, const char * const room,
const char * const contact, const char * const reason);
gboolean stanza_contains_chat_state(xmpp_stanza_t *stanza);
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index a004a4bf..398c9f46 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -1,7 +1,7 @@
/*
* xmpp.h
*
- * Copyright (C) 2012 - 2014 James Booth
+ * Copyright (C) 2012 - 2015 James Booth
*
* This file is part of Profanity.
*
@@ -145,7 +145,8 @@ char* jabber_get_account_name(void);
GList * jabber_get_available_resources(void);
// message functions
-void message_send_chat(const char * const barejid, const char * const msg);
+char* message_send_chat(const char * const barejid, const char * const msg);
+char* message_send_chat_encrypted(const char * const barejid, const char * const msg);
void message_send_private(const char * const fulljid, const char * const msg);
void message_send_groupchat(const char * const roomjid, const char * const msg);
void message_send_groupchat_subject(const char * const roomjid, const char * const subject);
@@ -167,11 +168,13 @@ char * presence_sub_request_find(const char * const search_str);
void presence_join_room(char *room, char *nick, char * passwd);
void presence_change_room_nick(const char * const room, const char * const nick);
void presence_leave_chat_room(const char * const room_jid);
-void presence_update(resource_presence_t status, const char * const msg,
+void presence_send(resource_presence_t status, const char * const msg,
int idle);
gboolean presence_sub_request_exists(const char * const bare_jid);
// iq functions
+void iq_enable_carbons();
+void iq_disable_carbons();
void iq_send_software_version(const char * const fulljid);
void iq_room_list_request(gchar *conferencejid);
void iq_disco_info_request(gchar *jid);
@@ -189,7 +192,7 @@ void iq_send_caps_request_for_jid(const char * const to, const char * const id,
const char * const node, const char * const ver);
void iq_send_caps_request_legacy(const char * const to, const char * const id,
const char * const node, const char * const ver);
-void iq_room_info_request(gchar *room);
+void iq_room_info_request(const char * const room, gboolean display_result);
void iq_room_affiliation_list(const char * const room, char *affiliation);
void iq_room_affiliation_set(const char * const room, const char * const jid, char *affiliation,
const char * const reason);
diff --git a/tests/helpers.c b/tests/helpers.c
index 10310886..564b2716 100644
--- a/tests/helpers.c
+++ b/tests/helpers.c
@@ -85,6 +85,24 @@ void close_chat_sessions(void **state)
close_preferences(NULL);
}
+int
+utf8_pos_to_col(char *str, int utf8_pos)
+{
+ int col = 0;
+
+ int i = 0;
+ for (i = 0; i