mirror of
https://github.com/Tha14/toxic.git
synced 2025-12-06 23:36:34 +01:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ee7a48910 | ||
|
|
daf4614ba6 | ||
|
|
919d36369c | ||
|
|
618704df76 | ||
|
|
9a70dd9651 | ||
|
|
e2d310b10f | ||
|
|
a1015a366a | ||
|
|
913ec7b3fe | ||
|
|
4a52b06954 | ||
|
|
89f9c07b9e | ||
|
|
388d78d11e | ||
|
|
a2a23b3932 | ||
|
|
f405ae8b42 | ||
|
|
cf3f6750eb | ||
|
|
4de22d067a | ||
|
|
51e274ea38 | ||
|
|
0a6ce62363 | ||
|
|
13c5de5531 | ||
|
|
21f8e7f398 | ||
|
|
bcf4a5af90 | ||
|
|
09f90d095b | ||
|
|
416ebc9ab8 | ||
|
|
3ca22aa714 | ||
|
|
8dd25e1f0b | ||
|
|
5b9bd603ea | ||
|
|
3c2c1f15ce | ||
|
|
6876df4a45 | ||
|
|
1ff97161fb | ||
|
|
667410e879 | ||
|
|
a862874740 | ||
|
|
79bde4e5bf | ||
|
|
833b724e9f | ||
|
|
96b68058bb | ||
|
|
e823233149 | ||
|
|
3ac22fafe4 | ||
|
|
71f2ac170c | ||
|
|
0ef888eea3 | ||
|
|
a9b0028a15 | ||
|
|
b18e6cff5a | ||
|
|
424a1c94d9 | ||
|
|
009095af24 |
@@ -9,7 +9,7 @@ before_script:
|
|||||||
# Installing libsodium, needed for toxcore
|
# Installing libsodium, needed for toxcore
|
||||||
- git clone https://github.com/jedisct1/libsodium.git libsodium
|
- git clone https://github.com/jedisct1/libsodium.git libsodium
|
||||||
- cd libsodium
|
- cd libsodium
|
||||||
- git checkout tags/0.4.2 > /dev/null
|
- git checkout tags/0.7.0 > /dev/null
|
||||||
- ./autogen.sh > /dev/null
|
- ./autogen.sh > /dev/null
|
||||||
- ./configure > /dev/null
|
- ./configure > /dev/null
|
||||||
- make check -j2 || make check || exit 1 > /dev/null
|
- make check -j2 || make check || exit 1 > /dev/null
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly
|
|||||||
* You can add specific flags to the Makefile with `USER_CFLAGS=""` and/or `USER_LDFLAGS=""`
|
* You can add specific flags to the Makefile with `USER_CFLAGS=""` and/or `USER_LDFLAGS=""`
|
||||||
* You can pass your own flags to the Makefile with `CFLAGS=""` and/or `LDFLAGS=""` (this will supersede the default ones)
|
* You can pass your own flags to the Makefile with `CFLAGS=""` and/or `LDFLAGS=""` (this will supersede the default ones)
|
||||||
* Additional features are automatically enabled if all dependencies are found, but you can disable them by using special variables:
|
* Additional features are automatically enabled if all dependencies are found, but you can disable them by using special variables:
|
||||||
|
* `DISABLE_X11=1` → build toxic without X11 support (needed for focus tracking)
|
||||||
* `DISABLE_AV=1` → build toxic without audio call support
|
* `DISABLE_AV=1` → build toxic without audio call support
|
||||||
* `DISABLE_SOUND_NOTIFY=1` → build toxic without sound notifications support
|
* `DISABLE_SOUND_NOTIFY=1` → build toxic without sound notifications support
|
||||||
* `DISABLE_DESKTOP_NOTIFY=1` → build toxic without desktop notifications support
|
* `DISABLE_DESKTOP_NOTIFY=1` → build toxic without desktop notifications support
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ CFG_DIR = $(BASE_DIR)/cfg
|
|||||||
LIBS = libtoxcore ncursesw libconfig
|
LIBS = libtoxcore ncursesw libconfig
|
||||||
|
|
||||||
CFLAGS = -std=gnu99 -pthread -Wall -g
|
CFLAGS = -std=gnu99 -pthread -Wall -g
|
||||||
CFLAGS += -DTOXICVER="\"$(VERSION)\"" -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED
|
CFLAGS += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED
|
||||||
CFLAGS += -DPACKAGE_DATADIR="\"$(abspath $(DATADIR))\""
|
CFLAGS += -DPACKAGE_DATADIR="\"$(abspath $(DATADIR))\""
|
||||||
CFLAGS += $(USER_CFLAGS)
|
CFLAGS += $(USER_CFLAGS)
|
||||||
LDFLAGS = $(USER_LDFLAGS)
|
LDFLAGS = $(USER_LDFLAGS)
|
||||||
|
|
||||||
OBJ = chat.o chat_commands.o configdir.o dns.o execute.o file_senders.o notify.o
|
OBJ = chat.o chat_commands.o configdir.o dns.o execute.o file_senders.o notify.o
|
||||||
OBJ += friendlist.o global_commands.o groupchat.o line_info.o input.o help.o autocomplete.o
|
OBJ += friendlist.o global_commands.o groupchat.o line_info.o input.o help.o autocomplete.o
|
||||||
OBJ += log.o misc_tools.o prompt.o settings.o toxic.o toxic_strings.o windows.o
|
OBJ += log.o misc_tools.o prompt.o settings.o toxic.o toxic_strings.o windows.o message_queue.o
|
||||||
|
|
||||||
# Check on wich system we are running
|
# Check on wich system we are running
|
||||||
UNAME_S = $(shell uname -s)
|
UNAME_S = $(shell uname -s)
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
CHECKS_DIR = $(CFG_DIR)/checks
|
CHECKS_DIR = $(CFG_DIR)/checks
|
||||||
|
|
||||||
# Check if we can use X11
|
# Check if we want build X11 support
|
||||||
CHECK_X11_LIBS = $(shell pkg-config --exists x11 || echo -n "error")
|
X11 = $(shell if [ -z "$(DISABLE_X11)" ] || [ "$(DISABLE_X11)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||||
ifneq ($(CHECK_X11_LIBS), error)
|
ifneq ($(X11), disabled)
|
||||||
LIBS += x11
|
-include $(CHECKS_DIR)/x11.mk
|
||||||
CFLAGS += -D_X11
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Check if we want build audio support
|
# Check if we want build audio support
|
||||||
|
|||||||
17
cfg/checks/x11.mk
Normal file
17
cfg/checks/x11.mk
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Variables for X11 support
|
||||||
|
X11_LIBS = x11
|
||||||
|
X11_CFLAGS = -D_X11
|
||||||
|
|
||||||
|
# Check if we can build X11 support
|
||||||
|
CHECK_X11_LIBS = $(shell pkg-config --exists $(X11_LIBS) || echo -n "error")
|
||||||
|
ifneq ($(CHECK_X11_LIBS), error)
|
||||||
|
LIBS += $(X11_LIBS)
|
||||||
|
CFLAGS += $(X11_CFLAGS)
|
||||||
|
else
|
||||||
|
ifneq ($(MAKECMDGOALS), clean)
|
||||||
|
MISSING_X11_LIBS = $(shell for lib in $(X11_LIBS) ; do if ! pkg-config --exists $$lib ; then echo $$lib ; fi ; done)
|
||||||
|
$(warning WARNING -- Toxic will be compiled without x11 support (needed for focus tracking))
|
||||||
|
$(warning WARNING -- You need these libraries for x11 support)
|
||||||
|
$(warning WARNING -- $(MISSING_X11_LIBS))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
@@ -9,6 +9,7 @@ help:
|
|||||||
@echo " help: This help"
|
@echo " help: This help"
|
||||||
@echo
|
@echo
|
||||||
@echo "-- Variables --"
|
@echo "-- Variables --"
|
||||||
|
@echo " DISABLE_X11: Set to \"1\" to force building without X11 support"
|
||||||
@echo " DISABLE_AV: Set to \"1\" to force building without audio call support"
|
@echo " DISABLE_AV: Set to \"1\" to force building without audio call support"
|
||||||
@echo " DISABLE_SOUND_NOTIFY: Set to \"1\" to force building without sound notification support"
|
@echo " DISABLE_SOUND_NOTIFY: Set to \"1\" to force building without sound notification support"
|
||||||
@echo " DISABLE_DESKTOP_NOTIFY: Set to \"1\" to force building without desktop notifications support"
|
@echo " DISABLE_DESKTOP_NOTIFY: Set to \"1\" to force building without desktop notifications support"
|
||||||
|
|||||||
16
doc/toxic.1
16
doc/toxic.1
@@ -2,12 +2,12 @@
|
|||||||
.\" Title: toxic
|
.\" Title: toxic
|
||||||
.\" Author: [see the "AUTHORS" section]
|
.\" Author: [see the "AUTHORS" section]
|
||||||
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
|
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
|
||||||
.\" Date: 2014-08-21
|
.\" Date: 2014-09-19
|
||||||
.\" Manual: Toxic Manual
|
.\" Manual: Toxic Manual
|
||||||
.\" Source: toxic __VERSION__
|
.\" Source: toxic __VERSION__
|
||||||
.\" Language: English
|
.\" Language: English
|
||||||
.\"
|
.\"
|
||||||
.TH "TOXIC" "1" "2014\-08\-21" "toxic __VERSION__" "Toxic Manual"
|
.TH "TOXIC" "1" "2014\-09\-19" "toxic __VERSION__" "Toxic Manual"
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
.\" * Define some portability stuff
|
.\" * Define some portability stuff
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
@@ -55,11 +55,16 @@ instead of
|
|||||||
\fI~/\&.config/tox/toxic\&.conf\fR
|
\fI~/\&.config/tox/toxic\&.conf\fR
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
\-d, \-\-default_locale
|
\-d, \-\-default\-locale
|
||||||
.RS 4
|
.RS 4
|
||||||
Use default locale
|
Use default locale
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
|
\-e, \-\-encrypt\-data
|
||||||
|
.RS 4
|
||||||
|
Encrypt an unencrypted data file\&. An error will occur if this option is used with an encrypted data file\&.
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
\-f, \-\-file data\-file
|
\-f, \-\-file data\-file
|
||||||
.RS 4
|
.RS 4
|
||||||
Use specified
|
Use specified
|
||||||
@@ -101,6 +106,11 @@ Use specified DNSservers file
|
|||||||
Force TCP connection (use this with proxies)
|
Force TCP connection (use this with proxies)
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
|
\-u, \-\-unencrypt\-data
|
||||||
|
.RS 4
|
||||||
|
Unencrypt a data file\&. A warning will appear if this option is used with a data file that is already unencrypted\&.
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
\-x, \-\-nodata
|
\-x, \-\-nodata
|
||||||
.RS 4
|
.RS 4
|
||||||
Ignore data file
|
Ignore data file
|
||||||
|
|||||||
@@ -27,11 +27,15 @@ OPTIONS
|
|||||||
-c, --config config-file::
|
-c, --config config-file::
|
||||||
Use specified 'config-file' instead of '~/.config/tox/toxic.conf'
|
Use specified 'config-file' instead of '~/.config/tox/toxic.conf'
|
||||||
|
|
||||||
-d, --default_locale::
|
-d, --default-locale::
|
||||||
Use default locale
|
Use default locale
|
||||||
|
|
||||||
|
-e, --encrypt-data::
|
||||||
|
Encrypt an unencrypted data file. An error will occur if this option
|
||||||
|
is used with an encrypted data file.
|
||||||
|
|
||||||
-f, --file data-file::
|
-f, --file data-file::
|
||||||
Use specified 'data-file' instead of '~/.config/tox/data'
|
Use specified 'data-file' instead of '~/.config/tox/data'
|
||||||
|
|
||||||
-h, --help::
|
-h, --help::
|
||||||
Show help message
|
Show help message
|
||||||
@@ -52,6 +56,10 @@ OPTIONS
|
|||||||
-t, --force-tcp::
|
-t, --force-tcp::
|
||||||
Force TCP connection (use this with proxies)
|
Force TCP connection (use this with proxies)
|
||||||
|
|
||||||
|
-u, --unencrypt-data::
|
||||||
|
Unencrypt a data file. A warning will appear if this option is used
|
||||||
|
with a data file that is already unencrypted.
|
||||||
|
|
||||||
-x, --nodata::
|
-x, --nodata::
|
||||||
Ignore data file
|
Ignore data file
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
.\" Title: toxic.conf
|
.\" Title: toxic.conf
|
||||||
.\" Author: [see the "AUTHORS" section]
|
.\" Author: [see the "AUTHORS" section]
|
||||||
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
|
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
|
||||||
.\" Date: 2014-08-21
|
.\" Date: 2014-08-26
|
||||||
.\" Manual: Toxic Manual
|
.\" Manual: Toxic Manual
|
||||||
.\" Source: toxic __VERSION__
|
.\" Source: toxic __VERSION__
|
||||||
.\" Language: English
|
.\" Language: English
|
||||||
.\"
|
.\"
|
||||||
.TH "TOXIC\&.CONF" "5" "2014\-08\-21" "toxic __VERSION__" "Toxic Manual"
|
.TH "TOXIC\&.CONF" "5" "2014\-08\-26" "toxic __VERSION__" "Toxic Manual"
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
.\" * Define some portability stuff
|
.\" * Define some portability stuff
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
@@ -96,6 +96,11 @@ Show when others are typing in a 1\-on\-1 chat\&. true or false
|
|||||||
Show others when you\(cqre typing in a 1\-on\-1 chat\&. true or false
|
Show others when you\(cqre typing in a 1\-on\-1 chat\&. true or false
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
|
\fBshow_welcome_msg\fR
|
||||||
|
.RS 4
|
||||||
|
Show welcome message on startup\&. true or false
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
\fBhistory_size\fR
|
\fBhistory_size\fR
|
||||||
.RS 4
|
.RS 4
|
||||||
Maximum lines for chat window history\&. Integer value\&. (for example: 700)
|
Maximum lines for chat window history\&. Integer value\&. (for example: 700)
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ OPTIONS
|
|||||||
*show_typing_self*;;
|
*show_typing_self*;;
|
||||||
Show others when you're typing in a 1-on-1 chat. true or false
|
Show others when you're typing in a 1-on-1 chat. true or false
|
||||||
|
|
||||||
|
*show_welcome_msg*;;
|
||||||
|
Show welcome message on startup. true or false
|
||||||
|
|
||||||
*history_size*;;
|
*history_size*;;
|
||||||
Maximum lines for chat window history. Integer value. (for example: 700)
|
Maximum lines for chat window history. Integer value. (for example: 700)
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
54.199.139.199 33445 7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029
|
54.199.139.199 33445 7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029
|
||||||
192.210.149.121 33445 F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67
|
192.210.149.121 33445 F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67
|
||||||
37.59.102.176 33445 B98A2CEAA6C6A2FADC2C3632D284318B60FE5375CCB41EFA081AB67F500C1B0B
|
37.59.102.176 33445 B98A2CEAA6C6A2FADC2C3632D284318B60FE5375CCB41EFA081AB67F500C1B0B
|
||||||
95.85.13.245 33445 7187969BB10B54C98538BAE94C069CE5C84E650D54F7E596543D8FB1ECF4CF23
|
|
||||||
178.21.112.187 33445 4B2C19E924972CB9B57732FB172F8A8604DE13EEDA2A6234E348983344B23057
|
178.21.112.187 33445 4B2C19E924972CB9B57732FB172F8A8604DE13EEDA2A6234E348983344B23057
|
||||||
76.191.23.96 33445 4BA57660DE3E854C530EED601BF8D54B7EFAE960523B6CFC10210CC08E2CB808
|
107.161.17.51 33445 7BE3951B97CA4B9ECDDA768E8C52BA19E9E2690AB584787BF4C90E04DBB75111
|
||||||
|
31.7.57.236 443 2A4B50D1D525DA2E669592A20C327B5FAD6C7E5962DC69296F9FEC77C4436E4E
|
||||||
|
63.165.243.15 443 8CD087E31C67568103E8C2A28653337E90E6B8EDA0D765D57C6B5172B4F1F04C
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ ui = {
|
|||||||
// true to show others when you're typing a message in 1-on-1 chats
|
// true to show others when you're typing a message in 1-on-1 chats
|
||||||
show_typing_self=true;
|
show_typing_self=true;
|
||||||
|
|
||||||
|
// true to show the welcome message on startup
|
||||||
|
show_welcome_msg=true;
|
||||||
|
|
||||||
// maximum lines for chat window history
|
// maximum lines for chat window history
|
||||||
history_size=700;
|
history_size=700;
|
||||||
};
|
};
|
||||||
|
|||||||
46
src/chat.c
46
src/chat.c
@@ -43,6 +43,7 @@
|
|||||||
#include "help.h"
|
#include "help.h"
|
||||||
#include "autocomplete.h"
|
#include "autocomplete.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
|
#include "message_queue.h"
|
||||||
|
|
||||||
#ifdef _AUDIO
|
#ifdef _AUDIO
|
||||||
#include "audio_call.h"
|
#include "audio_call.h"
|
||||||
@@ -134,6 +135,7 @@ void kill_chat_window(ToxWindow *self, Tox *m)
|
|||||||
close_all_file_receivers(m, self->num);
|
close_all_file_receivers(m, self->num);
|
||||||
log_disable(ctx->log);
|
log_disable(ctx->log);
|
||||||
line_info_cleanup(ctx->hst);
|
line_info_cleanup(ctx->hst);
|
||||||
|
cqueue_cleanup(ctx->cqueue);
|
||||||
|
|
||||||
#ifdef _AUDIO
|
#ifdef _AUDIO
|
||||||
stop_current_call(self);
|
stop_current_call(self);
|
||||||
@@ -144,7 +146,6 @@ void kill_chat_window(ToxWindow *self, Tox *m)
|
|||||||
delwin(statusbar->topline);
|
delwin(statusbar->topline);
|
||||||
|
|
||||||
free(ctx->log);
|
free(ctx->log);
|
||||||
free(ctx->hst);
|
|
||||||
free(ctx);
|
free(ctx);
|
||||||
free(self->help);
|
free(self->help);
|
||||||
free(statusbar);
|
free(statusbar);
|
||||||
@@ -239,7 +240,7 @@ static void chat_onAction(ToxWindow *self, Tox *m, int32_t num, const char *acti
|
|||||||
char timefrmt[TIME_STR_SIZE];
|
char timefrmt[TIME_STR_SIZE];
|
||||||
get_time_str(timefrmt, sizeof(timefrmt));
|
get_time_str(timefrmt, sizeof(timefrmt));
|
||||||
|
|
||||||
line_info_add(self, timefrmt, nick, NULL, ACTION, 0, 0, "%s", action);
|
line_info_add(self, timefrmt, nick, NULL, IN_ACTION, 0, 0, "%s", action);
|
||||||
write_to_log(action, nick, ctx->log, true);
|
write_to_log(action, nick, ctx->log, true);
|
||||||
|
|
||||||
if (self->active_box != -1)
|
if (self->active_box != -1)
|
||||||
@@ -287,14 +288,17 @@ static void chat_onStatusMessageChange(ToxWindow *self, int32_t num, const char
|
|||||||
statusbar->statusmsg_len = strlen(statusbar->statusmsg);
|
statusbar->statusmsg_len = strlen(statusbar->statusmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void chat_onReadReceipt(ToxWindow *self, Tox *m, int32_t num, uint32_t receipt)
|
||||||
|
{
|
||||||
|
cqueue_remove(self, m, receipt);
|
||||||
|
}
|
||||||
|
|
||||||
static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum,
|
static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum,
|
||||||
uint64_t filesize, const char *pathname, uint16_t path_len)
|
uint64_t filesize, const char *pathname, uint16_t path_len)
|
||||||
{
|
{
|
||||||
if (self->num != num)
|
if (self->num != num)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const char *errmsg;
|
|
||||||
|
|
||||||
/* holds the filename appended to the user specified path */
|
/* holds the filename appended to the user specified path */
|
||||||
char filename_path[MAX_STR_SIZE] = {0};
|
char filename_path[MAX_STR_SIZE] = {0};
|
||||||
|
|
||||||
@@ -308,8 +312,7 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
|
|||||||
filename_nopath, sizestr);
|
filename_nopath, sizestr);
|
||||||
|
|
||||||
if (filenum >= MAX_FILES) {
|
if (filenum >= MAX_FILES) {
|
||||||
errmsg = "Too many pending file requests; discarding.";
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Too many pending file requests; discarding.");
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,8 +323,7 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (len >= sizeof(Friends.list[num].file_receiver[filenum].filename)) {
|
if (len >= sizeof(Friends.list[num].file_receiver[filenum].filename)) {
|
||||||
errmsg = "File name too long; discarding.";
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File name too long; discarding.");
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,8 +353,7 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
|
|||||||
filename[len + d_len] = '\0';
|
filename[len + d_len] = '\0';
|
||||||
|
|
||||||
if (count > 999) {
|
if (count > 999) {
|
||||||
errmsg = "Error saving file to disk.";
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error saving file to disk.");
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -494,7 +495,10 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
|
|||||||
case TOX_FILECONTROL_FINISHED:
|
case TOX_FILECONTROL_FINISHED:
|
||||||
if (receive_send == 0) {
|
if (receive_send == 0) {
|
||||||
print_progress_bar(self, filenum, num, 100.0);
|
print_progress_bar(self, filenum, num, 100.0);
|
||||||
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename);
|
|
||||||
|
char filename_nopath[MAX_STR_SIZE];
|
||||||
|
get_file_name(filename_nopath, sizeof(filename_nopath), filename);
|
||||||
|
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename_nopath);
|
||||||
chat_close_file_receiver(m, filenum, num, TOX_FILECONTROL_FINISHED);
|
chat_close_file_receiver(m, filenum, num, TOX_FILECONTROL_FINISHED);
|
||||||
} else {
|
} else {
|
||||||
snprintf(msg, sizeof(msg), "File '%s' successfuly sent.", filename);
|
snprintf(msg, sizeof(msg), "File '%s' successfuly sent.", filename);
|
||||||
@@ -832,13 +836,8 @@ static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
|
|||||||
char timefrmt[TIME_STR_SIZE];
|
char timefrmt[TIME_STR_SIZE];
|
||||||
get_time_str(timefrmt, sizeof(timefrmt));
|
get_time_str(timefrmt, sizeof(timefrmt));
|
||||||
|
|
||||||
line_info_add(self, timefrmt, selfname, NULL, ACTION, 0, 0, "%s", action);
|
line_info_add(self, timefrmt, selfname, NULL, OUT_ACTION, 0, 0, "%s", action);
|
||||||
|
cqueue_add(ctx->cqueue, action, strlen(action), OUT_ACTION, ctx->hst->line_end->id + 1);
|
||||||
if (tox_send_action(m, self->num, (uint8_t *) action, strlen(action)) == 0) {
|
|
||||||
line_info_add(self, NULL, selfname, NULL, SYS_MSG, 0, RED, " * Failed to send action.");
|
|
||||||
} else {
|
|
||||||
write_to_log(action, selfname, ctx->log, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||||
@@ -919,12 +918,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
|||||||
get_time_str(timefrmt, sizeof(timefrmt));
|
get_time_str(timefrmt, sizeof(timefrmt));
|
||||||
|
|
||||||
line_info_add(self, timefrmt, selfname, NULL, OUT_MSG, 0, 0, "%s", line);
|
line_info_add(self, timefrmt, selfname, NULL, OUT_MSG, 0, 0, "%s", line);
|
||||||
|
cqueue_add(ctx->cqueue, line, strlen(line), OUT_MSG, ctx->hst->line_end->id + 1);
|
||||||
if (!statusbar->is_online || tox_send_message(m, self->num, (uint8_t *) line, strlen(line)) == 0) {
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send message.");
|
|
||||||
} else {
|
|
||||||
write_to_log(line, selfname, ctx->log, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wclear(ctx->linewin);
|
wclear(ctx->linewin);
|
||||||
@@ -1090,8 +1084,9 @@ static void chat_onInit(ToxWindow *self, Tox *m)
|
|||||||
|
|
||||||
ctx->hst = calloc(1, sizeof(struct history));
|
ctx->hst = calloc(1, sizeof(struct history));
|
||||||
ctx->log = calloc(1, sizeof(struct chatlog));
|
ctx->log = calloc(1, sizeof(struct chatlog));
|
||||||
|
ctx->cqueue = calloc(1, sizeof(struct chat_queue));
|
||||||
|
|
||||||
if (ctx->log == NULL || ctx->hst == NULL)
|
if (ctx->log == NULL || ctx->hst == NULL || ctx->cqueue == NULL)
|
||||||
exit_toxic_err("failed in chat_onInit", FATALERR_MEMORY);
|
exit_toxic_err("failed in chat_onInit", FATALERR_MEMORY);
|
||||||
|
|
||||||
line_info_init(ctx->hst);
|
line_info_init(ctx->hst);
|
||||||
@@ -1127,6 +1122,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
|
|||||||
ret.onFileSendRequest = &chat_onFileSendRequest;
|
ret.onFileSendRequest = &chat_onFileSendRequest;
|
||||||
ret.onFileControl = &chat_onFileControl;
|
ret.onFileControl = &chat_onFileControl;
|
||||||
ret.onFileData = &chat_onFileData;
|
ret.onFileData = &chat_onFileData;
|
||||||
|
ret.onReadReceipt = &chat_onReadReceipt;
|
||||||
|
|
||||||
#ifdef _AUDIO
|
#ifdef _AUDIO
|
||||||
ret.onInvite = &chat_onInvite;
|
ret.onInvite = &chat_onInvite;
|
||||||
|
|||||||
@@ -55,11 +55,11 @@ static struct cmd_func global_commands[] = {
|
|||||||
{ "/quit", cmd_quit },
|
{ "/quit", cmd_quit },
|
||||||
{ "/requests", cmd_requests },
|
{ "/requests", cmd_requests },
|
||||||
{ "/status", cmd_status },
|
{ "/status", cmd_status },
|
||||||
|
|
||||||
#ifdef _AUDIO
|
#ifdef _AUDIO
|
||||||
{ "/lsdev", cmd_list_devices },
|
{ "/lsdev", cmd_list_devices },
|
||||||
{ "/sdev", cmd_change_device },
|
{ "/sdev", cmd_change_device },
|
||||||
#endif /* _AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct cmd_func chat_commands[] = {
|
static struct cmd_func chat_commands[] = {
|
||||||
@@ -68,7 +68,6 @@ static struct cmd_func chat_commands[] = {
|
|||||||
{ "/join", cmd_join_group },
|
{ "/join", cmd_join_group },
|
||||||
{ "/savefile", cmd_savefile },
|
{ "/savefile", cmd_savefile },
|
||||||
{ "/sendfile", cmd_sendfile },
|
{ "/sendfile", cmd_sendfile },
|
||||||
|
|
||||||
#ifdef _AUDIO
|
#ifdef _AUDIO
|
||||||
{ "/call", cmd_call },
|
{ "/call", cmd_call },
|
||||||
{ "/answer", cmd_answer },
|
{ "/answer", cmd_answer },
|
||||||
@@ -78,6 +77,7 @@ static struct cmd_func chat_commands[] = {
|
|||||||
{ "/mute", cmd_mute },
|
{ "/mute", cmd_mute },
|
||||||
{ "/sense", cmd_sense },
|
{ "/sense", cmd_sense },
|
||||||
#endif /* _AUDIO */
|
#endif /* _AUDIO */
|
||||||
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Parses input command and puts args into arg array.
|
/* Parses input command and puts args into arg array.
|
||||||
@@ -101,7 +101,7 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
|
|||||||
i = char_find(1, cmd, '\"');
|
i = char_find(1, cmd, '\"');
|
||||||
|
|
||||||
if (cmd[i] == '\0') {
|
if (cmd[i] == '\0') {
|
||||||
char *errmsg = "Invalid argument. Did you forget a closing \"?";
|
const char *errmsg = "Invalid argument. Did you forget a closing \"?";
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -118,7 +118,7 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
|
|||||||
|
|
||||||
char tmp[MAX_STR_SIZE];
|
char tmp[MAX_STR_SIZE];
|
||||||
snprintf(tmp, sizeof(tmp), "%s", &cmd[i + 1]);
|
snprintf(tmp, sizeof(tmp), "%s", &cmd[i + 1]);
|
||||||
strcpy(cmd, tmp);
|
strcpy(cmd, tmp); /* tmp will always fit inside cmd */
|
||||||
}
|
}
|
||||||
|
|
||||||
free(cmd);
|
free(cmd);
|
||||||
@@ -126,12 +126,12 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Matches command to respective function. Returns 0 on match, 1 on no match */
|
/* Matches command to respective function. Returns 0 on match, 1 on no match */
|
||||||
static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, int num_cmds,
|
static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct cmd_func *commands,
|
||||||
struct cmd_func *commands, char (*args)[MAX_STR_SIZE])
|
char (*args)[MAX_STR_SIZE])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < num_cmds; ++i) {
|
for (i = 0; commands[i].name != NULL; ++i) {
|
||||||
if (strcmp(args[0], commands[i].name) == 0) {
|
if (strcmp(args[0], commands[i].name) == 0) {
|
||||||
(commands[i].func)(w, self, m, num_args - 1, args);
|
(commands[i].func)(w, self, m, num_args - 1, args);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -158,7 +158,7 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
|
|||||||
Note: Global commands must come last in case of duplicate command names */
|
Note: Global commands must come last in case of duplicate command names */
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case CHAT_COMMAND_MODE:
|
case CHAT_COMMAND_MODE:
|
||||||
if (do_command(w, self, m, num_args, CHAT_NUM_COMMANDS, chat_commands, args) == 0)
|
if (do_command(w, self, m, num_args, chat_commands, args) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -167,7 +167,7 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_command(w, self, m, num_args, GLOBAL_NUM_COMMANDS, global_commands, args) == 0)
|
if (do_command(w, self, m, num_args, global_commands, args) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid command.");
|
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid command.");
|
||||||
|
|||||||
@@ -28,14 +28,6 @@
|
|||||||
|
|
||||||
#define MAX_NUM_ARGS 4 /* Includes command */
|
#define MAX_NUM_ARGS 4 /* Includes command */
|
||||||
|
|
||||||
#ifdef _AUDIO
|
|
||||||
#define GLOBAL_NUM_COMMANDS 18
|
|
||||||
#define CHAT_NUM_COMMANDS 12
|
|
||||||
#else
|
|
||||||
#define GLOBAL_NUM_COMMANDS 16
|
|
||||||
#define CHAT_NUM_COMMANDS 5
|
|
||||||
#endif /* _AUDIO */
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
GLOBAL_COMMAND_MODE,
|
GLOBAL_COMMAND_MODE,
|
||||||
CHAT_COMMAND_MODE,
|
CHAT_COMMAND_MODE,
|
||||||
|
|||||||
@@ -276,6 +276,7 @@ void do_file_senders(Tox *m)
|
|||||||
box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg);
|
box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg);
|
||||||
else
|
else
|
||||||
box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", msg);
|
box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", msg);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -130,11 +130,12 @@ static int save_blocklist(char *path)
|
|||||||
exit_toxic_err("Failed in save_blocklist", FATALERR_MEMORY);
|
exit_toxic_err("Failed in save_blocklist", FATALERR_MEMORY);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
int ret = -1;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (i = 0; i < Blocked.max_idx; ++i) {
|
for (i = 0; i < Blocked.max_idx; ++i) {
|
||||||
if (count > Blocked.num_blocked)
|
if (count > Blocked.num_blocked)
|
||||||
return -1;
|
goto on_error;
|
||||||
|
|
||||||
if (Blocked.list[i].active) {
|
if (Blocked.list[i].active) {
|
||||||
BlockedFriend tmp;
|
BlockedFriend tmp;
|
||||||
@@ -155,17 +156,14 @@ static int save_blocklist(char *path)
|
|||||||
|
|
||||||
FILE *fp = fopen(path, "wb");
|
FILE *fp = fopen(path, "wb");
|
||||||
|
|
||||||
if (fp == NULL) {
|
if (fp == NULL)
|
||||||
free(data);
|
goto on_error;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret = 0;
|
if (fwrite(data, len, 1, fp) == 1)
|
||||||
|
ret = 0;
|
||||||
if (fwrite(data, len, 1, fp) != 1)
|
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
on_error:
|
||||||
free(data);
|
free(data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1001,7 +999,6 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index)
|
|||||||
{
|
{
|
||||||
int id = toxav_get_peer_id(av, call_index, 0);
|
int id = toxav_get_peer_id(av, call_index, 0);
|
||||||
|
|
||||||
/*id++;*/
|
|
||||||
if ( id != ErrorInternal && id >= Friends.max_idx)
|
if ( id != ErrorInternal && id >= Friends.max_idx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ void kill_groupchat_window(ToxWindow *self)
|
|||||||
delwin(ctx->history);
|
delwin(ctx->history);
|
||||||
delwin(ctx->sidebar);
|
delwin(ctx->sidebar);
|
||||||
free(ctx->log);
|
free(ctx->log);
|
||||||
free(ctx->hst);
|
|
||||||
free(ctx);
|
free(ctx);
|
||||||
free(self->help);
|
free(self->help);
|
||||||
del_window(self);
|
del_window(self);
|
||||||
@@ -198,7 +197,7 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p
|
|||||||
char timefrmt[TIME_STR_SIZE];
|
char timefrmt[TIME_STR_SIZE];
|
||||||
get_time_str(timefrmt, sizeof(timefrmt));
|
get_time_str(timefrmt, sizeof(timefrmt));
|
||||||
|
|
||||||
line_info_add(self, timefrmt, nick, NULL, ACTION, 0, 0, "%s", action);
|
line_info_add(self, timefrmt, nick, NULL, IN_ACTION, 0, 0, "%s", action);
|
||||||
write_to_log(action, nick, ctx->log, true);
|
write_to_log(action, nick, ctx->log, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
#include "groupchat.h"
|
#include "groupchat.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
|
#include "message_queue.h"
|
||||||
|
#include "misc_tools.h"
|
||||||
|
|
||||||
extern struct user_settings *user_settings_;
|
extern struct user_settings *user_settings_;
|
||||||
|
|
||||||
@@ -89,6 +91,8 @@ void line_info_cleanup(struct history *hst)
|
|||||||
if (hst->queue[i])
|
if (hst->queue[i])
|
||||||
free(hst->queue[i]);
|
free(hst->queue[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(hst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* moves root forward and frees previous root */
|
/* moves root forward and frees previous root */
|
||||||
@@ -107,15 +111,6 @@ static void line_info_root_fwd(struct history *hst)
|
|||||||
hst->line_root = tmp;
|
hst->line_root = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* adds a line_info line to queue */
|
|
||||||
static void line_info_add_queue(struct history *hst, struct line_info *line)
|
|
||||||
{
|
|
||||||
if (hst->queue_sz >= MAX_QUEUE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
hst->queue[hst->queue_sz++] = line;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* returns ptr to queue item 0 and removes it from queue */
|
/* returns ptr to queue item 0 and removes it from queue */
|
||||||
static struct line_info *line_info_ret_queue(struct history *hst)
|
static struct line_info *line_info_ret_queue(struct history *hst)
|
||||||
{
|
{
|
||||||
@@ -134,12 +129,15 @@ static struct line_info *line_info_ret_queue(struct history *hst)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* creates new line_info line and puts it in the queue.
|
/* creates new line_info line and puts it in the queue. */
|
||||||
SYS_MSG lines may contain an arbitrary number of arguments for string formatting */
|
void line_info_add(ToxWindow *self, char *timestr, char *name1, char *name2, uint8_t type, uint8_t bold,
|
||||||
void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint8_t type, uint8_t bold,
|
|
||||||
uint8_t colour, const char *msg, ...)
|
uint8_t colour, const char *msg, ...)
|
||||||
{
|
{
|
||||||
struct history *hst = self->chatwin->hst;
|
struct history *hst = self->chatwin->hst;
|
||||||
|
|
||||||
|
if (hst->queue_sz >= MAX_QUEUE)
|
||||||
|
return;
|
||||||
|
|
||||||
struct line_info *new_line = calloc(1, sizeof(struct line_info));
|
struct line_info *new_line = calloc(1, sizeof(struct line_info));
|
||||||
|
|
||||||
if (new_line == NULL)
|
if (new_line == NULL)
|
||||||
@@ -156,7 +154,16 @@ void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint
|
|||||||
|
|
||||||
/* for type-specific formatting in print function */
|
/* for type-specific formatting in print function */
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ACTION:
|
case IN_ACTION:
|
||||||
|
case OUT_ACTION:
|
||||||
|
len += 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IN_MSG:
|
||||||
|
case OUT_MSG:
|
||||||
|
len += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
case CONNECTION:
|
case CONNECTION:
|
||||||
len += 3;
|
len += 3;
|
||||||
break;
|
break;
|
||||||
@@ -185,9 +192,9 @@ void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmstmp) {
|
if (timestr) {
|
||||||
snprintf(new_line->timestamp, sizeof(new_line->timestamp), "%s", tmstmp);
|
snprintf(new_line->timestr, sizeof(new_line->timestr), "%s", timestr);
|
||||||
len += strlen(new_line->timestamp);
|
len += strlen(new_line->timestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name1) {
|
if (name1) {
|
||||||
@@ -204,8 +211,10 @@ void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint
|
|||||||
new_line->type = type;
|
new_line->type = type;
|
||||||
new_line->bold = bold;
|
new_line->bold = bold;
|
||||||
new_line->colour = colour;
|
new_line->colour = colour;
|
||||||
|
new_line->noread_flag = false;
|
||||||
|
new_line->timestamp = get_unix_time();
|
||||||
|
|
||||||
line_info_add_queue(hst, new_line);
|
hst->queue[hst->queue_sz++] = new_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* adds a single queue item to hst if possible. only called once per call to line_info_print() */
|
/* adds a single queue item to hst if possible. only called once per call to line_info_print() */
|
||||||
@@ -247,6 +256,8 @@ static void line_info_check_queue(ToxWindow *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NOREAD_FLAG_TIMEOUT 5 /* seconds before a sent message with no read receipt is flagged as unread */
|
||||||
|
|
||||||
void line_info_print(ToxWindow *self)
|
void line_info_print(ToxWindow *self)
|
||||||
{
|
{
|
||||||
ChatContext *ctx = self->chatwin;
|
ChatContext *ctx = self->chatwin;
|
||||||
@@ -280,9 +291,10 @@ void line_info_print(ToxWindow *self)
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case OUT_MSG:
|
case OUT_MSG:
|
||||||
|
case OUT_MSG_READ:
|
||||||
case IN_MSG:
|
case IN_MSG:
|
||||||
wattron(win, COLOR_PAIR(BLUE));
|
wattron(win, COLOR_PAIR(BLUE));
|
||||||
wprintw(win, "%s", line->timestamp);
|
wprintw(win, "%s", line->timestr);
|
||||||
wattroff(win, COLOR_PAIR(BLUE));
|
wattroff(win, COLOR_PAIR(BLUE));
|
||||||
|
|
||||||
int nameclr = GREEN;
|
int nameclr = GREEN;
|
||||||
@@ -299,28 +311,54 @@ void line_info_print(ToxWindow *self)
|
|||||||
if (line->msg[0] == '>')
|
if (line->msg[0] == '>')
|
||||||
wattron(win, COLOR_PAIR(GREEN));
|
wattron(win, COLOR_PAIR(GREEN));
|
||||||
|
|
||||||
wprintw(win, "%s\n", line->msg);
|
wprintw(win, "%s", line->msg);
|
||||||
|
|
||||||
if (line->msg[0] == '>')
|
if (line->msg[0] == '>')
|
||||||
wattroff(win, COLOR_PAIR(GREEN));
|
wattroff(win, COLOR_PAIR(GREEN));
|
||||||
|
|
||||||
|
if (type == OUT_MSG && timed_out(line->timestamp, get_unix_time(), NOREAD_FLAG_TIMEOUT)) {
|
||||||
|
wattron(win, COLOR_PAIR(RED));
|
||||||
|
wprintw(win, " x", line->msg);
|
||||||
|
wattroff(win, COLOR_PAIR(RED));
|
||||||
|
|
||||||
|
if (line->noread_flag == false) {
|
||||||
|
line->noread_flag = true;
|
||||||
|
line->len += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wprintw(win, "\n", line->msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACTION:
|
case OUT_ACTION_READ:
|
||||||
|
case OUT_ACTION:
|
||||||
|
case IN_ACTION:
|
||||||
wattron(win, COLOR_PAIR(BLUE));
|
wattron(win, COLOR_PAIR(BLUE));
|
||||||
wprintw(win, "%s", line->timestamp);
|
wprintw(win, "%s", line->timestr);
|
||||||
wattroff(win, COLOR_PAIR(BLUE));
|
wattroff(win, COLOR_PAIR(BLUE));
|
||||||
|
|
||||||
wattron(win, COLOR_PAIR(YELLOW));
|
wattron(win, COLOR_PAIR(YELLOW));
|
||||||
wprintw(win, "* %s %s\n", line->name1, line->msg);
|
wprintw(win, "* %s %s", line->name1, line->msg);
|
||||||
wattroff(win, COLOR_PAIR(YELLOW));
|
wattroff(win, COLOR_PAIR(YELLOW));
|
||||||
|
|
||||||
|
if (type == OUT_ACTION && timed_out(line->timestamp, get_unix_time(), NOREAD_FLAG_TIMEOUT)) {
|
||||||
|
wattron(win, COLOR_PAIR(RED));
|
||||||
|
wprintw(win, " x", line->msg);
|
||||||
|
wattroff(win, COLOR_PAIR(RED));
|
||||||
|
|
||||||
|
if (line->noread_flag == false) {
|
||||||
|
line->noread_flag = true;
|
||||||
|
line->len += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wprintw(win, "\n", line->msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYS_MSG:
|
case SYS_MSG:
|
||||||
if (line->timestamp[0]) {
|
if (line->timestr[0]) {
|
||||||
wattron(win, COLOR_PAIR(BLUE));
|
wattron(win, COLOR_PAIR(BLUE));
|
||||||
wprintw(win, "%s", line->timestamp);
|
wprintw(win, "%s", line->timestr);
|
||||||
wattroff(win, COLOR_PAIR(BLUE));
|
wattroff(win, COLOR_PAIR(BLUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +391,7 @@ void line_info_print(ToxWindow *self)
|
|||||||
|
|
||||||
case CONNECTION:
|
case CONNECTION:
|
||||||
wattron(win, COLOR_PAIR(BLUE));
|
wattron(win, COLOR_PAIR(BLUE));
|
||||||
wprintw(win, "%s", line->timestamp);
|
wprintw(win, "%s", line->timestr);
|
||||||
wattroff(win, COLOR_PAIR(BLUE));
|
wattroff(win, COLOR_PAIR(BLUE));
|
||||||
|
|
||||||
wattron(win, COLOR_PAIR(line->colour));
|
wattron(win, COLOR_PAIR(line->colour));
|
||||||
@@ -367,7 +405,7 @@ void line_info_print(ToxWindow *self)
|
|||||||
|
|
||||||
case NAME_CHANGE:
|
case NAME_CHANGE:
|
||||||
wattron(win, COLOR_PAIR(BLUE));
|
wattron(win, COLOR_PAIR(BLUE));
|
||||||
wprintw(win, "%s", line->timestamp);
|
wprintw(win, "%s", line->timestr);
|
||||||
wattroff(win, COLOR_PAIR(BLUE));
|
wattroff(win, COLOR_PAIR(BLUE));
|
||||||
|
|
||||||
wattron(win, COLOR_PAIR(MAGENTA));
|
wattron(win, COLOR_PAIR(MAGENTA));
|
||||||
@@ -393,6 +431,7 @@ void line_info_print(ToxWindow *self)
|
|||||||
line_info_print(self);
|
line_info_print(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* puts msg in specified line_info msg buffer */
|
||||||
void line_info_set(ToxWindow *self, uint32_t id, char *msg)
|
void line_info_set(ToxWindow *self, uint32_t id, char *msg)
|
||||||
{
|
{
|
||||||
struct line_info *line = self->chatwin->hst->line_end;
|
struct line_info *line = self->chatwin->hst->line_end;
|
||||||
|
|||||||
@@ -34,22 +34,27 @@ enum {
|
|||||||
SYS_MSG,
|
SYS_MSG,
|
||||||
IN_MSG,
|
IN_MSG,
|
||||||
OUT_MSG,
|
OUT_MSG,
|
||||||
|
OUT_MSG_READ, /* for sent messages that have received a read reply. don't set this with line_info_add */
|
||||||
|
IN_ACTION,
|
||||||
|
OUT_ACTION,
|
||||||
|
OUT_ACTION_READ, /* same as OUT_MSG_READ but for actions */
|
||||||
PROMPT,
|
PROMPT,
|
||||||
ACTION,
|
|
||||||
CONNECTION,
|
CONNECTION,
|
||||||
NAME_CHANGE,
|
NAME_CHANGE,
|
||||||
} LINE_TYPE;
|
} LINE_TYPE;
|
||||||
|
|
||||||
struct line_info {
|
struct line_info {
|
||||||
char timestamp[TIME_STR_SIZE];
|
char timestr[TIME_STR_SIZE];
|
||||||
char name1[TOXIC_MAX_NAME_LENGTH];
|
char name1[TOXIC_MAX_NAME_LENGTH];
|
||||||
char name2[TOXIC_MAX_NAME_LENGTH];
|
char name2[TOXIC_MAX_NAME_LENGTH];
|
||||||
char msg[TOX_MAX_MESSAGE_LENGTH];
|
char msg[TOX_MAX_MESSAGE_LENGTH];
|
||||||
|
uint64_t timestamp;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t bold;
|
uint8_t bold;
|
||||||
uint8_t colour;
|
uint8_t colour;
|
||||||
|
uint8_t noread_flag; /* true if a line should be flagged as unread */
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint16_t len; /* combined len of all strings */
|
uint16_t len; /* combined len of entire line */
|
||||||
uint8_t newlines;
|
uint8_t newlines;
|
||||||
|
|
||||||
struct line_info *prev;
|
struct line_info *prev;
|
||||||
@@ -67,9 +72,8 @@ struct history {
|
|||||||
int queue_sz;
|
int queue_sz;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* creates new line_info line and puts it in the queue.
|
/* creates new line_info line and puts it in the queue. */
|
||||||
SYS_MSG lines may contain an arbitrary number of arguments for string formatting */
|
void line_info_add(ToxWindow *self, char *timestr, char *name1, char *name2, uint8_t type, uint8_t bold,
|
||||||
void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint8_t type, uint8_t bold,
|
|
||||||
uint8_t colour, const char *msg, ...);
|
uint8_t colour, const char *msg, ...);
|
||||||
|
|
||||||
/* Prints a section of history starting at line_start */
|
/* Prints a section of history starting at line_start */
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ void init_logging_session(char *name, const char *key, struct chatlog *log)
|
|||||||
fprintf(log->file, "\n*** NEW SESSION ***\n\n");
|
fprintf(log->file, "\n*** NEW SESSION ***\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define LOG_FLUSH_LIMIT 1 /* limits calls to fflush to a max of one per LOG_FLUSH_LIMIT seconds */
|
||||||
|
|
||||||
void write_to_log(const char *msg, const char *name, struct chatlog *log, bool event)
|
void write_to_log(const char *msg, const char *name, struct chatlog *log, bool event)
|
||||||
{
|
{
|
||||||
if (!log->log_on)
|
if (!log->log_on)
|
||||||
|
|||||||
@@ -23,12 +23,9 @@
|
|||||||
#ifndef _log_h
|
#ifndef _log_h
|
||||||
#define _log_h
|
#define _log_h
|
||||||
|
|
||||||
#define LOG_FLUSH_LIMIT 2 /* limits calls to fflush(logfile) to a max of one per LOG_FLUSH_LIMIT seconds */
|
|
||||||
|
|
||||||
struct chatlog {
|
struct chatlog {
|
||||||
FILE *file;
|
FILE *file;
|
||||||
uint64_t lastwrite;
|
uint64_t lastwrite;
|
||||||
int pos;
|
|
||||||
bool log_on; /* specific to current chat window */
|
bool log_on; /* specific to current chat window */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
156
src/message_queue.c
Normal file
156
src/message_queue.c
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
/* message_queue.c
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Toxic All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Toxic.
|
||||||
|
*
|
||||||
|
* Toxic 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.
|
||||||
|
*
|
||||||
|
* Toxic 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 Toxic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "toxic.h"
|
||||||
|
#include "windows.h"
|
||||||
|
#include "message_queue.h"
|
||||||
|
#include "misc_tools.h"
|
||||||
|
#include "line_info.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
void cqueue_cleanup(struct chat_queue *q)
|
||||||
|
{
|
||||||
|
struct cqueue_msg *tmp1 = q->root;
|
||||||
|
|
||||||
|
while (tmp1) {
|
||||||
|
struct cqueue_msg *tmp2 = tmp1->next;
|
||||||
|
free(tmp1);
|
||||||
|
tmp1 = tmp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cqueue_add(struct chat_queue *q, const char *msg, int len, uint8_t type, uint32_t line_id)
|
||||||
|
{
|
||||||
|
struct cqueue_msg *new_m = malloc(sizeof(struct cqueue_msg));
|
||||||
|
|
||||||
|
if (new_m == NULL)
|
||||||
|
exit_toxic_err("failed in cqueue_message", FATALERR_MEMORY);
|
||||||
|
|
||||||
|
snprintf(new_m->message, sizeof(new_m->message), "%s", msg);
|
||||||
|
new_m->len = len;
|
||||||
|
new_m->type = type;
|
||||||
|
new_m->line_id = line_id;
|
||||||
|
new_m->last_send_try = 0;
|
||||||
|
new_m->receipt = 0;
|
||||||
|
new_m->next = NULL;
|
||||||
|
|
||||||
|
if (q->root == NULL) {
|
||||||
|
new_m->prev = NULL;
|
||||||
|
q->root = new_m;
|
||||||
|
} else {
|
||||||
|
new_m->prev = q->end;
|
||||||
|
q->end->next = new_m;
|
||||||
|
}
|
||||||
|
|
||||||
|
q->end = new_m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update line to show receipt was received after queue removal */
|
||||||
|
static void cqueue_mark_read(ToxWindow *self, struct cqueue_msg *msg)
|
||||||
|
{
|
||||||
|
struct line_info *line = self->chatwin->hst->line_end;
|
||||||
|
|
||||||
|
while (line) {
|
||||||
|
if (line->id != msg->line_id) {
|
||||||
|
line = line->prev;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
line->type = msg->type == OUT_ACTION ? OUT_ACTION_READ : OUT_MSG_READ;
|
||||||
|
|
||||||
|
if (line->noread_flag == true) {
|
||||||
|
line->len -= 2;
|
||||||
|
line->noread_flag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* removes message with matching receipt from queue, writes to log and updates line to show the message was received. */
|
||||||
|
void cqueue_remove(ToxWindow *self, Tox *m, uint32_t receipt)
|
||||||
|
{
|
||||||
|
struct chat_queue *q = self->chatwin->cqueue;
|
||||||
|
struct cqueue_msg *msg = q->root;
|
||||||
|
|
||||||
|
while (msg) {
|
||||||
|
if (msg->receipt != receipt) {
|
||||||
|
msg = msg->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char selfname[TOX_MAX_NAME_LENGTH];
|
||||||
|
uint16_t len = tox_get_self_name(m, (uint8_t *) selfname);
|
||||||
|
selfname[len] = '\0';
|
||||||
|
|
||||||
|
write_to_log(msg->message, selfname, self->chatwin->log, msg->type == OUT_ACTION);
|
||||||
|
cqueue_mark_read(self, msg);
|
||||||
|
|
||||||
|
struct cqueue_msg *next = msg->next;
|
||||||
|
|
||||||
|
if (msg->prev == NULL) { /* root */
|
||||||
|
if (next)
|
||||||
|
next->prev = NULL;
|
||||||
|
|
||||||
|
free(msg);
|
||||||
|
q->root = next;
|
||||||
|
} else {
|
||||||
|
struct cqueue_msg *prev = msg->prev;
|
||||||
|
free(msg);
|
||||||
|
prev->next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CQUEUE_TRY_SEND_INTERVAL 10
|
||||||
|
|
||||||
|
/* Tries to send the oldest unsent message in queue. */
|
||||||
|
void cqueue_try_send(ToxWindow *self, Tox *m)
|
||||||
|
{
|
||||||
|
struct chat_queue *q = self->chatwin->cqueue;
|
||||||
|
struct cqueue_msg *msg = q->root;
|
||||||
|
uint64_t curtime = get_unix_time();
|
||||||
|
|
||||||
|
while (msg) {
|
||||||
|
if (msg->receipt != 0 && !timed_out(msg->last_send_try, curtime, CQUEUE_TRY_SEND_INTERVAL)) {
|
||||||
|
msg = msg->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t receipt = 0;
|
||||||
|
|
||||||
|
if (msg->type == OUT_MSG)
|
||||||
|
receipt = tox_send_message(m, self->num, (uint8_t *) msg->message, msg->len);
|
||||||
|
else
|
||||||
|
receipt = tox_send_action(m, self->num, (uint8_t *) msg->message, msg->len);
|
||||||
|
|
||||||
|
msg->last_send_try = curtime;
|
||||||
|
msg->receipt = receipt;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/message_queue.h
Normal file
46
src/message_queue.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/* message_queue.h
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Toxic All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Toxic.
|
||||||
|
*
|
||||||
|
* Toxic 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.
|
||||||
|
*
|
||||||
|
* Toxic 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 Toxic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct cqueue_msg {
|
||||||
|
char message[MAX_STR_SIZE];
|
||||||
|
int len;
|
||||||
|
int line_id;
|
||||||
|
uint8_t type;
|
||||||
|
uint32_t receipt;
|
||||||
|
uint64_t last_send_try;
|
||||||
|
struct cqueue_msg *next;
|
||||||
|
struct cqueue_msg *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct chat_queue {
|
||||||
|
struct cqueue_msg *root;
|
||||||
|
struct cqueue_msg *end;
|
||||||
|
};
|
||||||
|
|
||||||
|
void cqueue_cleanup(struct chat_queue *q);
|
||||||
|
void cqueue_add(struct chat_queue *q, const char *msg, int len, uint8_t type, uint32_t line_id);
|
||||||
|
|
||||||
|
/* Tries to send the oldest unsent message in queue. */
|
||||||
|
void cqueue_try_send(ToxWindow *self, Tox *m);
|
||||||
|
|
||||||
|
/* removes message with matching receipt from queue, writes to log and updates line to show the message was received. */
|
||||||
|
void cqueue_remove(ToxWindow *self, Tox *m, uint32_t receipt);
|
||||||
@@ -306,8 +306,8 @@ void bytes_convert_str(char *buf, int size, uint64_t bytes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* checks if a file exists. Returns true or false */
|
/* checks if a file exists. Returns true or false */
|
||||||
bool file_exists(const char *fp)
|
bool file_exists(const char *path)
|
||||||
{
|
{
|
||||||
struct stat s;
|
struct stat s;
|
||||||
return stat(fp, &s) == 0;
|
return stat(path, &s) == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,6 @@ int char_rfind(const char *s, char ch, int len);
|
|||||||
void bytes_convert_str(char *buf, int size, uint64_t bytes);
|
void bytes_convert_str(char *buf, int size, uint64_t bytes);
|
||||||
|
|
||||||
/* checks if a file exists. Returns true or false */
|
/* checks if a file exists. Returns true or false */
|
||||||
bool file_exists(const char *fp);
|
bool file_exists(const char *path);
|
||||||
|
|
||||||
#endif /* #define _misc_tools_h */
|
#endif /* #define _misc_tools_h */
|
||||||
|
|||||||
131
src/notify.c
131
src/notify.c
@@ -24,10 +24,12 @@
|
|||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "line_info.h"
|
#include "line_info.h"
|
||||||
|
#include "misc_tools.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -59,6 +61,7 @@
|
|||||||
#include <libnotify/notify.h>
|
#include <libnotify/notify.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MAX_BOX_MSG_LEN 127
|
||||||
#define SOUNDS_SIZE 10
|
#define SOUNDS_SIZE 10
|
||||||
#define ACTIVE_NOTIFS_MAX 50
|
#define ACTIVE_NOTIFS_MAX 50
|
||||||
|
|
||||||
@@ -67,14 +70,14 @@ extern struct user_settings *user_settings_;
|
|||||||
struct _Control {
|
struct _Control {
|
||||||
time_t cooldown;
|
time_t cooldown;
|
||||||
time_t notif_timeout;
|
time_t notif_timeout;
|
||||||
unsigned long this_window;
|
|
||||||
#ifdef _X11
|
#ifdef _X11
|
||||||
Display *display;
|
Display *display;
|
||||||
|
unsigned long this_window;
|
||||||
#endif /* _X11 */
|
#endif /* _X11 */
|
||||||
|
|
||||||
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
|
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
|
||||||
pthread_mutex_t poll_mutex[1];
|
pthread_mutex_t poll_mutex[1];
|
||||||
_Bool poll_active;
|
bool poll_active;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _SOUND_NOTIFY
|
#ifdef _SOUND_NOTIFY
|
||||||
@@ -87,13 +90,13 @@ struct _ActiveNotifications {
|
|||||||
#ifdef _SOUND_NOTIFY
|
#ifdef _SOUND_NOTIFY
|
||||||
uint32_t source;
|
uint32_t source;
|
||||||
uint32_t buffer;
|
uint32_t buffer;
|
||||||
_Bool looping;
|
bool looping;
|
||||||
#endif
|
#endif
|
||||||
_Bool active;
|
bool active;
|
||||||
int *id_indicator;
|
int *id_indicator;
|
||||||
#ifdef _BOX_NOTIFY
|
#ifdef _BOX_NOTIFY
|
||||||
NotifyNotification* box;
|
NotifyNotification* box;
|
||||||
char messages[128][128];
|
char messages[MAX_BOX_MSG_LEN + 1][MAX_BOX_MSG_LEN + 1];
|
||||||
char title[24];
|
char title[24];
|
||||||
size_t size;
|
size_t size;
|
||||||
time_t n_timeout;
|
time_t n_timeout;
|
||||||
@@ -105,18 +108,40 @@ struct _ActiveNotifications {
|
|||||||
/**********************************************************************************/
|
/**********************************************************************************/
|
||||||
/**********************************************************************************/
|
/**********************************************************************************/
|
||||||
|
|
||||||
|
/* coloured tab notifications: primary notification type */
|
||||||
|
static void tab_notify(ToxWindow *self, uint64_t flags)
|
||||||
|
{
|
||||||
|
if (self == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (flags & NT_WNDALERT_0)
|
||||||
|
self->alert = WINDOW_ALERT_0;
|
||||||
|
else if ( (flags & NT_WNDALERT_1) && (!self->alert || self->alert > WINDOW_ALERT_0) )
|
||||||
|
self->alert = WINDOW_ALERT_1;
|
||||||
|
else if ( (flags & NT_WNDALERT_2) && (!self->alert || self->alert > WINDOW_ALERT_1) )
|
||||||
|
self->alert = WINDOW_ALERT_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _X11
|
||||||
long unsigned int get_focused_window_id()
|
long unsigned int get_focused_window_id()
|
||||||
{
|
{
|
||||||
#ifdef _X11
|
|
||||||
if (!Control.display) return 0;
|
if (!Control.display) return 0;
|
||||||
|
|
||||||
Window focus;
|
Window focus;
|
||||||
int revert;
|
int revert;
|
||||||
XGetInputFocus(Control.display, &focus, &revert);
|
XGetInputFocus(Control.display, &focus, &revert);
|
||||||
return focus;
|
return focus;
|
||||||
#else
|
}
|
||||||
return 0;
|
|
||||||
#endif /* _X11 */
|
#endif /* _X11 */
|
||||||
|
|
||||||
|
static bool notifications_are_disabled(uint64_t flags)
|
||||||
|
{
|
||||||
|
bool res = flags & NT_RESTOL && Control.cooldown > get_unix_time();
|
||||||
|
#ifdef _X11
|
||||||
|
return res || (flags & NT_NOFOCUS && Control.this_window == get_focused_window_id());
|
||||||
|
#else
|
||||||
|
return res;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void control_lock()
|
static void control_lock()
|
||||||
@@ -134,14 +159,14 @@ static void control_unlock()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _SOUND_NOTIFY
|
#ifdef _SOUND_NOTIFY
|
||||||
_Bool is_playing(int source)
|
bool is_playing(int source)
|
||||||
{
|
{
|
||||||
int ready;
|
int ready;
|
||||||
alGetSourcei(source, AL_SOURCE_STATE, &ready);
|
alGetSourcei(source, AL_SOURCE_STATE, &ready);
|
||||||
return ready == AL_PLAYING;
|
return ready == AL_PLAYING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Terminate all sounds but wait them to finish first */
|
/* Terminate all sounds but wait for them to finish first */
|
||||||
void graceful_clear()
|
void graceful_clear()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -167,7 +192,6 @@ void graceful_clear()
|
|||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == ACTIVE_NOTIFS_MAX) {
|
if (i == ACTIVE_NOTIFS_MAX) {
|
||||||
@@ -224,7 +248,7 @@ void* do_playing(void* _p)
|
|||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int play_source(uint32_t source, uint32_t buffer, _Bool looping)
|
int play_source(uint32_t source, uint32_t buffer, bool looping)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; i < ACTIVE_NOTIFS_MAX && actives[i].active; i ++);
|
for (; i < ACTIVE_NOTIFS_MAX && actives[i].active; i ++);
|
||||||
@@ -317,8 +341,6 @@ int init_notify(int login_cooldown, int notification_timeout)
|
|||||||
#ifdef _X11
|
#ifdef _X11
|
||||||
Control.display = XOpenDisplay(NULL);
|
Control.display = XOpenDisplay(NULL);
|
||||||
Control.this_window = get_focused_window_id();
|
Control.this_window = get_focused_window_id();
|
||||||
#else
|
|
||||||
Control.this_window = 1;
|
|
||||||
#endif /* _X11 */
|
#endif /* _X11 */
|
||||||
|
|
||||||
|
|
||||||
@@ -365,7 +387,7 @@ int set_sound(Notification sound, const char* value)
|
|||||||
return stat(value, &buf) == 0;
|
return stat(value, &buf) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int play_sound_internal(Notification what, _Bool loop)
|
int play_sound_internal(Notification what, bool loop)
|
||||||
{
|
{
|
||||||
uint32_t source;
|
uint32_t source;
|
||||||
uint32_t buffer;
|
uint32_t buffer;
|
||||||
@@ -442,15 +464,9 @@ void m_notify_action(NotifyNotification *box, char *action, void* data)
|
|||||||
|
|
||||||
int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator)
|
int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator)
|
||||||
{
|
{
|
||||||
/* Consider colored notify as primary */
|
tab_notify(self, flags);
|
||||||
if (self) {
|
|
||||||
if (flags & NT_WNDALERT_0) self->alert = WINDOW_ALERT_0;
|
|
||||||
else if ( (flags & NT_WNDALERT_1) && (!self->alert || self->alert > WINDOW_ALERT_0) ) self->alert = WINDOW_ALERT_1;
|
|
||||||
else if ( (flags & NT_WNDALERT_2) && (!self->alert || self->alert > WINDOW_ALERT_1) ) self->alert = WINDOW_ALERT_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
|
if (notifications_are_disabled(flags))
|
||||||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int id = -1;
|
int id = -1;
|
||||||
@@ -486,15 +502,9 @@ int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_in
|
|||||||
|
|
||||||
int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
|
int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
|
||||||
{
|
{
|
||||||
/* Consider colored notify as primary */
|
tab_notify(self, flags);
|
||||||
if (self) {
|
|
||||||
if (flags & NT_WNDALERT_0) self->alert = WINDOW_ALERT_0;
|
|
||||||
else if ( (flags & NT_WNDALERT_1) && (!self->alert || self->alert > WINDOW_ALERT_0) ) self->alert = WINDOW_ALERT_1;
|
|
||||||
else if ( (flags & NT_WNDALERT_2) && (!self->alert || self->alert > WINDOW_ALERT_1) ) self->alert = WINDOW_ALERT_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
|
if (notifications_are_disabled(flags))
|
||||||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (id < 0 || id >= ACTIVE_NOTIFS_MAX) return -1;
|
if (id < 0 || id >= ACTIVE_NOTIFS_MAX) return -1;
|
||||||
@@ -532,9 +542,10 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
|
|||||||
|
|
||||||
int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, char* title, const char* format, ...)
|
int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator, char* title, const char* format, ...)
|
||||||
{
|
{
|
||||||
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
|
if (notifications_are_disabled(flags)) {
|
||||||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
|
tab_notify(self, flags);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _BOX_NOTIFY
|
#ifdef _BOX_NOTIFY
|
||||||
|
|
||||||
@@ -561,11 +572,11 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi
|
|||||||
if (strlen(title) > 23) strcpy(actives[id].title + 20, "...");
|
if (strlen(title) > 23) strcpy(actives[id].title + 20, "...");
|
||||||
|
|
||||||
va_list __ARGS__; va_start (__ARGS__, format);
|
va_list __ARGS__; va_start (__ARGS__, format);
|
||||||
vsnprintf (actives[id].messages[0], 127, format, __ARGS__);
|
vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__);
|
||||||
va_end (__ARGS__);
|
va_end (__ARGS__);
|
||||||
|
|
||||||
if (strlen(actives[id].messages[0]) > 124)
|
if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3)
|
||||||
strcpy(actives[id].messages[0] + 124, "...");
|
strcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "...");
|
||||||
|
|
||||||
actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL);
|
actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL);
|
||||||
actives[id].size ++;
|
actives[id].size ++;
|
||||||
@@ -585,9 +596,10 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi
|
|||||||
|
|
||||||
int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, const char* format, ...)
|
int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, const char* format, ...)
|
||||||
{
|
{
|
||||||
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
|
if (notifications_are_disabled(flags)) {
|
||||||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
|
tab_notify(self, flags);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _BOX_NOTIFY
|
#ifdef _BOX_NOTIFY
|
||||||
|
|
||||||
@@ -596,18 +608,17 @@ int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, con
|
|||||||
|
|
||||||
control_lock();
|
control_lock();
|
||||||
|
|
||||||
if (!actives[id].box || actives[id].size >= 128 ) {
|
if (!actives[id].box || actives[id].size >= MAX_BOX_MSG_LEN + 1) {
|
||||||
control_unlock();
|
control_unlock();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
va_list __ARGS__; va_start (__ARGS__, format);
|
va_list __ARGS__; va_start (__ARGS__, format);
|
||||||
vsnprintf (actives[id].messages[actives[id].size], 127, format, __ARGS__);
|
vsnprintf (actives[id].messages[actives[id].size], MAX_BOX_MSG_LEN, format, __ARGS__);
|
||||||
va_end (__ARGS__);
|
va_end (__ARGS__);
|
||||||
|
|
||||||
if (strlen(actives[id].messages[actives[id].size]) > 124)
|
if (strlen(actives[id].messages[actives[id].size]) > MAX_BOX_MSG_LEN - 3)
|
||||||
strcpy(actives[id].messages[actives[id].size] + 124, "...");
|
strcpy(actives[id].messages[actives[id].size] + MAX_BOX_MSG_LEN - 3, "...");
|
||||||
|
|
||||||
actives[id].size ++;
|
actives[id].size ++;
|
||||||
actives[id].n_timeout = time(NULL) + Control.notif_timeout / 1000;
|
actives[id].n_timeout = time(NULL) + Control.notif_timeout / 1000;
|
||||||
@@ -635,15 +646,9 @@ int box_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id, con
|
|||||||
|
|
||||||
int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const char* title, const char* format, ...)
|
int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const char* title, const char* format, ...)
|
||||||
{
|
{
|
||||||
/* Always do colored notify */
|
tab_notify(self, flags);
|
||||||
if (self) {
|
|
||||||
if (flags & NT_WNDALERT_0) self->alert = WINDOW_ALERT_0;
|
|
||||||
else if ( (flags & NT_WNDALERT_1) && (!self->alert || self->alert > WINDOW_ALERT_0) ) self->alert = WINDOW_ALERT_1;
|
|
||||||
else if ( (flags & NT_WNDALERT_2) && (!self->alert || self->alert > WINDOW_ALERT_1) ) self->alert = WINDOW_ALERT_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
|
if (notifications_are_disabled(flags))
|
||||||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef _BOX_NOTIFY
|
#ifdef _BOX_NOTIFY
|
||||||
@@ -666,11 +671,11 @@ int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const
|
|||||||
if (strlen(title) > 23) strcpy(actives[id].title + 20, "...");
|
if (strlen(title) > 23) strcpy(actives[id].title + 20, "...");
|
||||||
|
|
||||||
va_list __ARGS__; va_start (__ARGS__, format);
|
va_list __ARGS__; va_start (__ARGS__, format);
|
||||||
vsnprintf (actives[id].messages[0], 127, format, __ARGS__);
|
vsnprintf (actives[id].messages[0], MAX_BOX_MSG_LEN, format, __ARGS__);
|
||||||
va_end (__ARGS__);
|
va_end (__ARGS__);
|
||||||
|
|
||||||
if (strlen(actives[id].messages[0]) > 124)
|
if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3)
|
||||||
strcpy(actives[id].messages[0] + 124, "...");
|
strcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "...");
|
||||||
|
|
||||||
actives[id].active = 1;
|
actives[id].active = 1;
|
||||||
actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL);
|
actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL);
|
||||||
@@ -691,32 +696,26 @@ int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const
|
|||||||
|
|
||||||
int box_silent_notify2(ToxWindow* self, uint64_t flags, int id, const char* format, ...)
|
int box_silent_notify2(ToxWindow* self, uint64_t flags, int id, const char* format, ...)
|
||||||
{
|
{
|
||||||
/* Always do colored notify */
|
tab_notify(self, flags);
|
||||||
if (self) {
|
|
||||||
if (flags & NT_WNDALERT_0) self->alert = WINDOW_ALERT_0;
|
|
||||||
else if ( (flags & NT_WNDALERT_1) && (!self->alert || self->alert > WINDOW_ALERT_0) ) self->alert = WINDOW_ALERT_1;
|
|
||||||
else if ( (flags & NT_WNDALERT_2) && (!self->alert || self->alert > WINDOW_ALERT_1) ) self->alert = WINDOW_ALERT_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
|
if (notifications_are_disabled(flags))
|
||||||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef _BOX_NOTIFY
|
#ifdef _BOX_NOTIFY
|
||||||
control_lock();
|
control_lock();
|
||||||
|
|
||||||
if (id < 0 || id >= ACTIVE_NOTIFS_MAX || !actives[id].box || actives[id].size >= 128 ) {
|
if (id < 0 || id >= ACTIVE_NOTIFS_MAX || !actives[id].box || actives[id].size >= MAX_BOX_MSG_LEN + 1 ) {
|
||||||
control_unlock();
|
control_unlock();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
va_list __ARGS__; va_start (__ARGS__, format);
|
va_list __ARGS__; va_start (__ARGS__, format);
|
||||||
vsnprintf (actives[id].messages[actives[id].size], 127, format, __ARGS__);
|
vsnprintf (actives[id].messages[actives[id].size], MAX_BOX_MSG_LEN, format, __ARGS__);
|
||||||
va_end (__ARGS__);
|
va_end (__ARGS__);
|
||||||
|
|
||||||
if (strlen(actives[id].messages[actives[id].size]) > 124)
|
if (strlen(actives[id].messages[actives[id].size]) > MAX_BOX_MSG_LEN - 3)
|
||||||
strcpy(actives[id].messages[actives[id].size] + 124, "...");
|
strcpy(actives[id].messages[actives[id].size] + MAX_BOX_MSG_LEN - 3, "...");
|
||||||
|
|
||||||
actives[id].size ++;
|
actives[id].size ++;
|
||||||
actives[id].n_timeout = time(NULL) + Control.notif_timeout / 1000;
|
actives[id].n_timeout = time(NULL) + Control.notif_timeout / 1000;
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ void kill_prompt_window(ToxWindow *self)
|
|||||||
delwin(statusbar->topline);
|
delwin(statusbar->topline);
|
||||||
|
|
||||||
free(ctx->log);
|
free(ctx->log);
|
||||||
free(ctx->hst);
|
|
||||||
free(ctx);
|
free(ctx);
|
||||||
free(self->help);
|
free(self->help);
|
||||||
free(statusbar);
|
free(statusbar);
|
||||||
@@ -465,7 +464,8 @@ static void prompt_onInit(ToxWindow *self, Tox *m)
|
|||||||
scrollok(ctx->history, 0);
|
scrollok(ctx->history, 0);
|
||||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||||
|
|
||||||
print_welcome_msg(self);
|
if (user_settings_->show_welcome_msg == SHOW_WELCOME_MSG_ON)
|
||||||
|
print_welcome_msg(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxWindow new_prompt(void)
|
ToxWindow new_prompt(void)
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ static struct _ui_strings {
|
|||||||
const char* history_size;
|
const char* history_size;
|
||||||
const char* show_typing_self;
|
const char* show_typing_self;
|
||||||
const char* show_typing_other;
|
const char* show_typing_other;
|
||||||
|
const char* show_welcome_msg;
|
||||||
} ui_strings = {
|
} ui_strings = {
|
||||||
"ui",
|
"ui",
|
||||||
"timestamps",
|
"timestamps",
|
||||||
@@ -64,6 +65,7 @@ static struct _ui_strings {
|
|||||||
"history_size",
|
"history_size",
|
||||||
"show_typing_self",
|
"show_typing_self",
|
||||||
"show_typing_other",
|
"show_typing_other",
|
||||||
|
"show_welcome_msg",
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ui_defaults(struct user_settings* settings)
|
static void ui_defaults(struct user_settings* settings)
|
||||||
@@ -76,6 +78,7 @@ static void ui_defaults(struct user_settings* settings)
|
|||||||
settings->history_size = 700;
|
settings->history_size = 700;
|
||||||
settings->show_typing_self = SHOW_TYPING_ON;
|
settings->show_typing_self = SHOW_TYPING_ON;
|
||||||
settings->show_typing_other = SHOW_TYPING_ON;
|
settings->show_typing_other = SHOW_TYPING_ON;
|
||||||
|
settings->show_welcome_msg = SHOW_WELCOME_MSG_ON;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct _keys_strings {
|
static const struct _keys_strings {
|
||||||
@@ -250,6 +253,7 @@ int settings_load(struct user_settings *s, const char *patharg)
|
|||||||
config_setting_lookup_int(setting, ui_strings.history_size, &s->history_size);
|
config_setting_lookup_int(setting, ui_strings.history_size, &s->history_size);
|
||||||
config_setting_lookup_bool(setting, ui_strings.show_typing_self, &s->show_typing_self);
|
config_setting_lookup_bool(setting, ui_strings.show_typing_self, &s->show_typing_self);
|
||||||
config_setting_lookup_bool(setting, ui_strings.show_typing_other, &s->show_typing_other);
|
config_setting_lookup_bool(setting, ui_strings.show_typing_other, &s->show_typing_other);
|
||||||
|
config_setting_lookup_bool(setting, ui_strings.show_welcome_msg, &s->show_welcome_msg);
|
||||||
config_setting_lookup_int(setting, ui_strings.time_format, &s->time);
|
config_setting_lookup_int(setting, ui_strings.time_format, &s->time);
|
||||||
s->time = s->time == TIME_24 || s->time == TIME_12 ? s->time : TIME_24; /* Check defaults */
|
s->time = s->time == TIME_24 || s->time == TIME_12 ? s->time : TIME_24; /* Check defaults */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ struct user_settings {
|
|||||||
int history_size; /* int between MIN_HISTORY and MAX_HISTORY */
|
int history_size; /* int between MIN_HISTORY and MAX_HISTORY */
|
||||||
int show_typing_self; /* boolean */
|
int show_typing_self; /* boolean */
|
||||||
int show_typing_other; /* boolean */
|
int show_typing_other; /* boolean */
|
||||||
|
int show_welcome_msg; /* boolean */
|
||||||
|
|
||||||
char download_path[PATH_MAX];
|
char download_path[PATH_MAX];
|
||||||
char chatlogs_path[PATH_MAX];
|
char chatlogs_path[PATH_MAX];
|
||||||
@@ -74,6 +75,9 @@ enum {
|
|||||||
SHOW_TYPING_OFF = 0,
|
SHOW_TYPING_OFF = 0,
|
||||||
SHOW_TYPING_ON = 1,
|
SHOW_TYPING_ON = 1,
|
||||||
|
|
||||||
|
SHOW_WELCOME_MSG_OFF = 0,
|
||||||
|
SHOW_WELCOME_MSG_ON = 1,
|
||||||
|
|
||||||
DFLT_HST_SIZE = 700,
|
DFLT_HST_SIZE = 700,
|
||||||
} settings_values;
|
} settings_values;
|
||||||
|
|
||||||
|
|||||||
316
src/toxic.c
316
src/toxic.c
@@ -38,8 +38,10 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
#include <tox/tox.h>
|
#include <tox/tox.h>
|
||||||
|
#include <tox/toxencryptsave.h>
|
||||||
|
|
||||||
#include "configdir.h"
|
#include "configdir.h"
|
||||||
#include "toxic.h"
|
#include "toxic.h"
|
||||||
@@ -53,6 +55,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
#include "message_queue.h"
|
||||||
|
|
||||||
#ifdef _AUDIO
|
#ifdef _AUDIO
|
||||||
#include "audio_call.h"
|
#include "audio_call.h"
|
||||||
@@ -74,9 +77,19 @@ ToxWindow *prompt = NULL;
|
|||||||
#define AUTOSAVE_FREQ 60
|
#define AUTOSAVE_FREQ 60
|
||||||
|
|
||||||
struct _Winthread Winthread;
|
struct _Winthread Winthread;
|
||||||
|
struct _cqueue_thread cqueue_thread;
|
||||||
struct arg_opts arg_opts;
|
struct arg_opts arg_opts;
|
||||||
struct user_settings *user_settings_ = NULL;
|
struct user_settings *user_settings_ = NULL;
|
||||||
|
|
||||||
|
#define MIN_PASSWORD_LEN 6
|
||||||
|
#define MAX_PASSWORD_LEN 64
|
||||||
|
|
||||||
|
static struct _user_password {
|
||||||
|
bool data_is_encrypted;
|
||||||
|
char pass[MAX_PASSWORD_LEN + 1];
|
||||||
|
int len;
|
||||||
|
} user_password;
|
||||||
|
|
||||||
static void catch_SIGINT(int sig)
|
static void catch_SIGINT(int sig)
|
||||||
{
|
{
|
||||||
Winthread.sig_exit_toxic = true;
|
Winthread.sig_exit_toxic = true;
|
||||||
@@ -105,6 +118,7 @@ static void init_signal_catchers(void)
|
|||||||
void exit_toxic_success(Tox *m)
|
void exit_toxic_success(Tox *m)
|
||||||
{
|
{
|
||||||
store_data(m, DATA_FILE);
|
store_data(m, DATA_FILE);
|
||||||
|
memset(&user_password, 0, sizeof(struct _user_password));
|
||||||
close_all_file_senders(m);
|
close_all_file_senders(m);
|
||||||
kill_all_windows(m);
|
kill_all_windows(m);
|
||||||
|
|
||||||
@@ -182,8 +196,15 @@ static struct _init_messages {
|
|||||||
} init_messages;
|
} init_messages;
|
||||||
|
|
||||||
/* One-time queue for messages created during init. Do not use after program init. */
|
/* One-time queue for messages created during init. Do not use after program init. */
|
||||||
static void queue_init_message(const char *msg)
|
static void queue_init_message(const char *msg, ...)
|
||||||
{
|
{
|
||||||
|
char frmt_msg[MAX_STR_SIZE] = {0};
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, msg);
|
||||||
|
vsnprintf(frmt_msg, sizeof(frmt_msg), msg, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
int i = init_messages.num;
|
int i = init_messages.num;
|
||||||
++init_messages.num;
|
++init_messages.num;
|
||||||
|
|
||||||
@@ -197,7 +218,7 @@ static void queue_init_message(const char *msg)
|
|||||||
if (new_msgs[i] == NULL)
|
if (new_msgs[i] == NULL)
|
||||||
exit_toxic_err("Failed in queue_init_message", FATALERR_MEMORY);
|
exit_toxic_err("Failed in queue_init_message", FATALERR_MEMORY);
|
||||||
|
|
||||||
snprintf(new_msgs[i], MAX_STR_SIZE, "%s", msg);
|
snprintf(new_msgs[i], MAX_STR_SIZE, "%s", frmt_msg);
|
||||||
init_messages.msgs = new_msgs;
|
init_messages.msgs = new_msgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,16 +258,16 @@ static Tox *init_tox(void)
|
|||||||
char tmp[48];
|
char tmp[48];
|
||||||
snprintf(tmp, sizeof(tmp), "Using proxy %s : %d",
|
snprintf(tmp, sizeof(tmp), "Using proxy %s : %d",
|
||||||
arg_opts.proxy_address, arg_opts.proxy_port);
|
arg_opts.proxy_address, arg_opts.proxy_port);
|
||||||
queue_init_message(tmp);
|
queue_init_message("%s", tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tox_opts.udp_disabled) {
|
if (tox_opts.udp_disabled) {
|
||||||
queue_init_message("UDP disabled");
|
queue_init_message("UDP disabled");
|
||||||
} else if (tox_opts.proxy_enabled) {
|
} else if (tox_opts.proxy_enabled) {
|
||||||
const char *msg = "WARNING: Using a proxy without disabling UDP may leak your real IP address.";
|
const char *msg = "WARNING: Using a proxy without disabling UDP may leak your real IP address.";
|
||||||
queue_init_message(msg);
|
queue_init_message("%s", msg);
|
||||||
msg = "Use the -t option to disable UDP.";
|
msg = "Use the -t option to disable UDP.";
|
||||||
queue_init_message(msg);
|
queue_init_message("%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init core */
|
/* Init core */
|
||||||
@@ -283,6 +304,7 @@ static Tox *init_tox(void)
|
|||||||
tox_callback_file_send_request(m, on_file_sendrequest, NULL);
|
tox_callback_file_send_request(m, on_file_sendrequest, NULL);
|
||||||
tox_callback_file_control(m, on_file_control, NULL);
|
tox_callback_file_control(m, on_file_control, NULL);
|
||||||
tox_callback_file_data(m, on_file_data, NULL);
|
tox_callback_file_data(m, on_file_data, NULL);
|
||||||
|
tox_callback_read_receipt(m, on_read_receipt, NULL);
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
tox_set_name(m, (uint8_t *) "Cool dude", strlen("Cool dude"));
|
tox_set_name(m, (uint8_t *) "Cool dude", strlen("Cool dude"));
|
||||||
@@ -456,6 +478,104 @@ static void load_friendlist(Tox *m)
|
|||||||
sort_friendlist_index();
|
sort_friendlist_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return length of password on success, 0 on failure */
|
||||||
|
static int password_prompt(char *buf, int size)
|
||||||
|
{
|
||||||
|
buf[0] = '\0';
|
||||||
|
|
||||||
|
/* disable terminal echo */
|
||||||
|
struct termios oflags, nflags;
|
||||||
|
tcgetattr(fileno(stdin), &oflags);
|
||||||
|
nflags = oflags;
|
||||||
|
nflags.c_lflag &= ~ECHO;
|
||||||
|
nflags.c_lflag |= ECHONL;
|
||||||
|
|
||||||
|
if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const char *p = fgets(buf, size, stdin);
|
||||||
|
int len = strlen(buf);
|
||||||
|
|
||||||
|
/* re-enable terminal echo */
|
||||||
|
tcsetattr(fileno(stdin), TCSANOW, &oflags);
|
||||||
|
|
||||||
|
if (p == NULL || len <= 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* eat overflowed stdin and return error */
|
||||||
|
if (buf[--len] != '\n') {
|
||||||
|
int ch;
|
||||||
|
while ((ch = getchar()) != '\n' && ch > 0)
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[len] = '\0';
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ask user if they would like to encrypt the data file and set password */
|
||||||
|
static void first_time_encrypt(const char *msg)
|
||||||
|
{
|
||||||
|
char ch[256] = {0};
|
||||||
|
|
||||||
|
do {
|
||||||
|
system("clear");
|
||||||
|
printf("%s ", msg);
|
||||||
|
|
||||||
|
if (!strcasecmp(ch, "y\n") || !strcasecmp(ch, "n\n") || !strcasecmp(ch, "yes\n")
|
||||||
|
|| !strcasecmp(ch, "no\n") || !strcasecmp(ch, "q\n"))
|
||||||
|
break;
|
||||||
|
|
||||||
|
} while (fgets(ch, sizeof(ch), stdin));
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if (ch[0] == 'q' || ch[0] == 'Q')
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
if (ch[0] == 'y' || ch[0] == 'Y') {
|
||||||
|
int len = 0;
|
||||||
|
bool valid_password = false;
|
||||||
|
char passconfirm[MAX_PASSWORD_LEN + 1] = {0};
|
||||||
|
printf("Enter a new password (must be at least %d characters) ", MIN_PASSWORD_LEN);
|
||||||
|
|
||||||
|
while (valid_password == false) {
|
||||||
|
len = password_prompt(user_password.pass, sizeof(user_password.pass));
|
||||||
|
user_password.len = len;
|
||||||
|
|
||||||
|
if (strcasecmp(user_password.pass, "q") == 0)
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
if (string_is_empty(passconfirm) && (len < MIN_PASSWORD_LEN || len > MAX_PASSWORD_LEN)) {
|
||||||
|
printf("Password must be between %d and %d characters long. ", MIN_PASSWORD_LEN, MAX_PASSWORD_LEN);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string_is_empty(passconfirm)) {
|
||||||
|
printf("Enter password again ");
|
||||||
|
snprintf(passconfirm, sizeof(passconfirm), "%s", user_password.pass);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(user_password.pass, passconfirm) != 0) {
|
||||||
|
memset(passconfirm, 0, sizeof(passconfirm));
|
||||||
|
memset(user_password.pass, 0, sizeof(user_password.pass));
|
||||||
|
printf("Passwords don't match. Try again. ");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_password = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_init_message("Data file '%s' has been encrypted", DATA_FILE);
|
||||||
|
memset(passconfirm, 0, sizeof(passconfirm));
|
||||||
|
user_password.data_is_encrypted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
system("clear");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store Messenger to given location
|
* Store Messenger to given location
|
||||||
* Return 0 stored successfully or ignoring data file
|
* Return 0 stored successfully or ignoring data file
|
||||||
@@ -464,7 +584,7 @@ static void load_friendlist(Tox *m)
|
|||||||
* Return -3 opening path failed
|
* Return -3 opening path failed
|
||||||
* Return -4 fwrite failed
|
* Return -4 fwrite failed
|
||||||
*/
|
*/
|
||||||
int store_data(Tox *m, char *path)
|
int store_data(Tox *m, const char *path)
|
||||||
{
|
{
|
||||||
if (arg_opts.ignore_data_file)
|
if (arg_opts.ignore_data_file)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -472,13 +592,16 @@ int store_data(Tox *m, char *path)
|
|||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int len = tox_size(m);
|
int len = user_password.data_is_encrypted ? tox_encrypted_size(m) : tox_size(m);
|
||||||
char *buf = malloc(len);
|
char *buf = malloc(len);
|
||||||
|
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
tox_save(m, (uint8_t *) buf);
|
if (user_password.data_is_encrypted && !arg_opts.unencrypt_data)
|
||||||
|
tox_encrypted_save(m, (uint8_t *) buf, (uint8_t *) user_password.pass, user_password.len);
|
||||||
|
else
|
||||||
|
tox_save(m, (uint8_t *) buf);
|
||||||
|
|
||||||
FILE *fd = fopen(path, "wb");
|
FILE *fd = fopen(path, "wb");
|
||||||
|
|
||||||
@@ -523,7 +646,51 @@ static void load_data(Tox *m, char *path)
|
|||||||
exit_toxic_err("failed in load_data", FATALERR_FREAD);
|
exit_toxic_err("failed in load_data", FATALERR_FREAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
tox_load(m, (uint8_t *) buf, len);
|
bool is_encrypted = tox_is_data_encrypted((uint8_t *) buf);
|
||||||
|
|
||||||
|
/* attempt to encrypt an already encrypted data file */
|
||||||
|
if (arg_opts.encrypt_data && is_encrypted)
|
||||||
|
exit_toxic_err("failed in load_data", FATALERR_ENCRYPT);
|
||||||
|
|
||||||
|
if (arg_opts.unencrypt_data && is_encrypted)
|
||||||
|
queue_init_message("Data file '%s' has been unencrypted", path);
|
||||||
|
else if (arg_opts.unencrypt_data)
|
||||||
|
queue_init_message("Warning: passed --unencrypt-data option with unencrypted data file '%s'", path);
|
||||||
|
|
||||||
|
if (is_encrypted) {
|
||||||
|
if (!arg_opts.unencrypt_data)
|
||||||
|
user_password.data_is_encrypted = true;
|
||||||
|
|
||||||
|
int pwlen = 0;
|
||||||
|
system("clear");
|
||||||
|
printf("Enter password (q to quit) ");
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
pwlen = password_prompt(user_password.pass, sizeof(user_password.pass));
|
||||||
|
user_password.len = pwlen;
|
||||||
|
|
||||||
|
if (strcasecmp(user_password.pass, "q") == 0)
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
if (pwlen < MIN_PASSWORD_LEN) {
|
||||||
|
system("clear");
|
||||||
|
sleep(1);
|
||||||
|
printf("Invalid password. Try again. ");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tox_encrypted_load(m, (uint8_t *) buf, len, (uint8_t *) user_password.pass, pwlen) == 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
system("clear");
|
||||||
|
sleep(1);
|
||||||
|
printf("Invalid password. Try again. ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tox_load(m, (uint8_t *) buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
load_friendlist(m);
|
load_friendlist(m);
|
||||||
load_blocklist(BLOCK_FILE);
|
load_blocklist(BLOCK_FILE);
|
||||||
|
|
||||||
@@ -573,13 +740,34 @@ void *thread_winref(void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *thread_cqueue(void *data)
|
||||||
|
{
|
||||||
|
Tox *m = (Tox *) data;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
pthread_mutex_lock(&Winthread.lock);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 2; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
ToxWindow *toxwin = get_window_ptr(i);
|
||||||
|
|
||||||
|
if (toxwin != NULL && toxwin->is_chat && tox_get_friend_connection_status(m, toxwin->num) == 1)
|
||||||
|
cqueue_try_send(toxwin, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&Winthread.lock);
|
||||||
|
usleep(7000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void print_usage(void)
|
static void print_usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: toxic [OPTION] [FILE ...]\n");
|
fprintf(stderr, "usage: toxic [OPTION] [FILE ...]\n");
|
||||||
fprintf(stderr, " -4, --ipv4 Force IPv4 connection\n");
|
fprintf(stderr, " -4, --ipv4 Force IPv4 connection\n");
|
||||||
fprintf(stderr, " -b --debug Enable stderr for debugging\n");
|
fprintf(stderr, " -b, --debug Enable stderr for debugging\n");
|
||||||
fprintf(stderr, " -c, --config Use specified config file\n");
|
fprintf(stderr, " -c, --config Use specified config file\n");
|
||||||
fprintf(stderr, " -d, --default-locale Use default POSIX locale\n");
|
fprintf(stderr, " -d, --default-locale Use default POSIX locale\n");
|
||||||
|
fprintf(stderr, " -e, --encrypt-data Encrypt an unencrypted data file\n");
|
||||||
fprintf(stderr, " -f, --file Use specified data file\n");
|
fprintf(stderr, " -f, --file Use specified data file\n");
|
||||||
fprintf(stderr, " -h, --help Show this message and exit\n");
|
fprintf(stderr, " -h, --help Show this message and exit\n");
|
||||||
fprintf(stderr, " -n, --nodes Use specified DHTnodes file\n");
|
fprintf(stderr, " -n, --nodes Use specified DHTnodes file\n");
|
||||||
@@ -587,19 +775,15 @@ static void print_usage(void)
|
|||||||
fprintf(stderr, " -p, --proxy Use proxy: Requires [IP] [port]\n");
|
fprintf(stderr, " -p, --proxy Use proxy: Requires [IP] [port]\n");
|
||||||
fprintf(stderr, " -r, --dnslist Use specified DNSservers file\n");
|
fprintf(stderr, " -r, --dnslist Use specified DNSservers file\n");
|
||||||
fprintf(stderr, " -t, --force-tcp Force TCP connection (use this with proxies)\n");
|
fprintf(stderr, " -t, --force-tcp Force TCP connection (use this with proxies)\n");
|
||||||
|
fprintf(stderr, " -u, --unencrypt-data Unencrypt an encrypted data file\n");
|
||||||
fprintf(stderr, " -x, --nodata Ignore data file\n");
|
fprintf(stderr, " -x, --nodata Ignore data file\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_default_opts(void)
|
static void set_default_opts(void)
|
||||||
{
|
{
|
||||||
arg_opts.use_ipv4 = 0;
|
memset(&arg_opts, 0, sizeof(struct arg_opts));
|
||||||
arg_opts.ignore_data_file = 0;
|
|
||||||
arg_opts.debug = 0;
|
/* set any non-zero defaults here*/
|
||||||
arg_opts.default_locale = 0;
|
|
||||||
arg_opts.use_custom_data = 0;
|
|
||||||
arg_opts.no_connect = 0;
|
|
||||||
arg_opts.force_tcp = 0;
|
|
||||||
arg_opts.use_proxy = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_args(int argc, char *argv[])
|
static void parse_args(int argc, char *argv[])
|
||||||
@@ -613,16 +797,18 @@ static void parse_args(int argc, char *argv[])
|
|||||||
{"debug", no_argument, 0, 'b'},
|
{"debug", no_argument, 0, 'b'},
|
||||||
{"default-locale", no_argument, 0, 'd'},
|
{"default-locale", no_argument, 0, 'd'},
|
||||||
{"config", required_argument, 0, 'c'},
|
{"config", required_argument, 0, 'c'},
|
||||||
|
{"encrypt-data", no_argument, 0, 'e'},
|
||||||
{"nodes", required_argument, 0, 'n'},
|
{"nodes", required_argument, 0, 'n'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"noconnect", no_argument, 0, 'o'},
|
{"noconnect", no_argument, 0, 'o'},
|
||||||
{"dnslist", required_argument, 0, 'r'},
|
{"dnslist", required_argument, 0, 'r'},
|
||||||
{"force-tcp", no_argument, 0, 't'},
|
{"force-tcp", no_argument, 0, 't'},
|
||||||
{"proxy", required_argument, 0, 'p'},
|
{"proxy", required_argument, 0, 'p'},
|
||||||
|
{"unencrypt-data", no_argument, 0, 'u'},
|
||||||
{NULL, no_argument, NULL, 0},
|
{NULL, no_argument, NULL, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *opts_str = "4bdhotxc:f:n:r:p:";
|
const char *opts_str = "4bdehotuxc:f:n:r:p:";
|
||||||
int opt, indexptr;
|
int opt, indexptr;
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, opts_str, long_opts, &indexptr)) != -1) {
|
while ((opt = getopt_long(argc, argv, opts_str, long_opts, &indexptr)) != -1) {
|
||||||
@@ -649,6 +835,10 @@ static void parse_args(int argc, char *argv[])
|
|||||||
queue_init_message("Using default POSIX locale");
|
queue_init_message("Using default POSIX locale");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
arg_opts.encrypt_data = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
arg_opts.use_custom_data = 1;
|
arg_opts.use_custom_data = 1;
|
||||||
DATA_FILE = strdup(optarg);
|
DATA_FILE = strdup(optarg);
|
||||||
@@ -660,9 +850,8 @@ static void parse_args(int argc, char *argv[])
|
|||||||
strcpy(BLOCK_FILE, optarg);
|
strcpy(BLOCK_FILE, optarg);
|
||||||
strcat(BLOCK_FILE, "-blocklist");
|
strcat(BLOCK_FILE, "-blocklist");
|
||||||
|
|
||||||
char tmp[PATH_MAX];
|
queue_init_message("Using '%s' data file", DATA_FILE);
|
||||||
snprintf(tmp, sizeof(tmp), "Using '%s' data file", DATA_FILE);
|
|
||||||
queue_init_message(tmp);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
@@ -700,6 +889,10 @@ static void parse_args(int argc, char *argv[])
|
|||||||
arg_opts.force_tcp = 1;
|
arg_opts.force_tcp = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
arg_opts.unencrypt_data = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
arg_opts.ignore_data_file = 1;
|
arg_opts.ignore_data_file = 1;
|
||||||
queue_init_message("Ignoring data file");
|
queue_init_message("Ignoring data file");
|
||||||
@@ -715,7 +908,7 @@ static void parse_args(int argc, char *argv[])
|
|||||||
|
|
||||||
#define DATANAME "data"
|
#define DATANAME "data"
|
||||||
#define BLOCKNAME "data-blocklist"
|
#define BLOCKNAME "data-blocklist"
|
||||||
static int init_data_files(void)
|
static int init_default_data_files(void)
|
||||||
{
|
{
|
||||||
if (arg_opts.use_custom_data)
|
if (arg_opts.use_custom_data)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -723,28 +916,26 @@ static int init_data_files(void)
|
|||||||
char *user_config_dir = get_user_config_dir();
|
char *user_config_dir = get_user_config_dir();
|
||||||
int config_err = create_user_config_dirs(user_config_dir);
|
int config_err = create_user_config_dirs(user_config_dir);
|
||||||
|
|
||||||
if (DATA_FILE == NULL ) {
|
if (config_err) {
|
||||||
if (config_err) {
|
DATA_FILE = strdup(DATANAME);
|
||||||
DATA_FILE = strdup(DATANAME);
|
BLOCK_FILE = strdup(BLOCKNAME);
|
||||||
BLOCK_FILE = strdup(BLOCKNAME);
|
|
||||||
|
|
||||||
if (DATA_FILE == NULL || BLOCK_FILE == NULL)
|
if (DATA_FILE == NULL || BLOCK_FILE == NULL)
|
||||||
exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY);
|
exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY);
|
||||||
} else {
|
} else {
|
||||||
DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(DATANAME) + 1);
|
DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(DATANAME) + 1);
|
||||||
BLOCK_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(BLOCKNAME) + 1);
|
BLOCK_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(BLOCKNAME) + 1);
|
||||||
|
|
||||||
if (DATA_FILE == NULL || BLOCK_FILE == NULL)
|
if (DATA_FILE == NULL || BLOCK_FILE == NULL)
|
||||||
exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY);
|
exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY);
|
||||||
|
|
||||||
strcpy(DATA_FILE, user_config_dir);
|
strcpy(DATA_FILE, user_config_dir);
|
||||||
strcat(DATA_FILE, CONFIGDIR);
|
strcat(DATA_FILE, CONFIGDIR);
|
||||||
strcat(DATA_FILE, DATANAME);
|
strcat(DATA_FILE, DATANAME);
|
||||||
|
|
||||||
strcpy(BLOCK_FILE, user_config_dir);
|
strcpy(BLOCK_FILE, user_config_dir);
|
||||||
strcat(BLOCK_FILE, CONFIGDIR);
|
strcat(BLOCK_FILE, CONFIGDIR);
|
||||||
strcat(BLOCK_FILE, BLOCKNAME);
|
strcat(BLOCK_FILE, BLOCKNAME);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(user_config_dir);
|
free(user_config_dir);
|
||||||
@@ -775,9 +966,28 @@ int main(int argc, char *argv[])
|
|||||||
init_signal_catchers();
|
init_signal_catchers();
|
||||||
parse_args(argc, argv);
|
parse_args(argc, argv);
|
||||||
|
|
||||||
|
if (arg_opts.encrypt_data && arg_opts.unencrypt_data) {
|
||||||
|
arg_opts.encrypt_data = 0;
|
||||||
|
arg_opts.unencrypt_data = 0;
|
||||||
|
queue_init_message("Warning: Using --unencrypt-data and --encrypt-data simultaneously has no effect");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use the -b flag to enable stderr */
|
||||||
|
if (!arg_opts.debug)
|
||||||
|
freopen("/dev/null", "w", stderr);
|
||||||
|
|
||||||
/* Make sure all written files are read/writeable only by the current user. */
|
/* Make sure all written files are read/writeable only by the current user. */
|
||||||
umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||||
int config_err = init_data_files();
|
|
||||||
|
int config_err = init_default_data_files();
|
||||||
|
bool datafile_exists = file_exists(DATA_FILE);
|
||||||
|
|
||||||
|
if (!arg_opts.ignore_data_file) {
|
||||||
|
if (!datafile_exists && !arg_opts.unencrypt_data)
|
||||||
|
first_time_encrypt("Creating new data file. Would you like to encrypt it? Y/n (q to quit)");
|
||||||
|
else if (arg_opts.encrypt_data)
|
||||||
|
first_time_encrypt("Encrypt existing data file? Y/n (q to quit)");
|
||||||
|
}
|
||||||
|
|
||||||
/* init user_settings struct and load settings from conf file */
|
/* init user_settings struct and load settings from conf file */
|
||||||
user_settings_ = calloc(1, sizeof(struct user_settings));
|
user_settings_ = calloc(1, sizeof(struct user_settings));
|
||||||
@@ -785,22 +995,23 @@ int main(int argc, char *argv[])
|
|||||||
if (user_settings_ == NULL)
|
if (user_settings_ == NULL)
|
||||||
exit_toxic_err("failed in main", FATALERR_MEMORY);
|
exit_toxic_err("failed in main", FATALERR_MEMORY);
|
||||||
|
|
||||||
char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
|
const char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
|
||||||
int settings_err = settings_load(user_settings_, p);
|
int settings_err = settings_load(user_settings_, p);
|
||||||
|
|
||||||
Tox *m = init_tox();
|
Tox *m = init_tox();
|
||||||
init_term();
|
|
||||||
|
|
||||||
/* enable stderr for debugging */
|
|
||||||
if (!arg_opts.debug)
|
|
||||||
freopen("/dev/null", "w", stderr);
|
|
||||||
|
|
||||||
if (m == NULL)
|
if (m == NULL)
|
||||||
exit_toxic_err("failed in main", FATALERR_NETWORKINIT);
|
exit_toxic_err("failed in main", FATALERR_NETWORKINIT);
|
||||||
|
|
||||||
if (!arg_opts.ignore_data_file)
|
if (!arg_opts.ignore_data_file) {
|
||||||
|
if (arg_opts.encrypt_data && !datafile_exists)
|
||||||
|
arg_opts.encrypt_data = 0;
|
||||||
|
|
||||||
load_data(m, DATA_FILE);
|
load_data(m, DATA_FILE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
init_term();
|
||||||
prompt = init_windows(m);
|
prompt = init_windows(m);
|
||||||
prompt_init_statusbar(prompt, m);
|
prompt_init_statusbar(prompt, m);
|
||||||
|
|
||||||
@@ -811,11 +1022,14 @@ int main(int argc, char *argv[])
|
|||||||
if (pthread_create(&Winthread.tid, NULL, thread_winref, (void *) m) != 0)
|
if (pthread_create(&Winthread.tid, NULL, thread_winref, (void *) m) != 0)
|
||||||
exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);
|
exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);
|
||||||
|
|
||||||
|
/* thread for message queue */
|
||||||
|
if (pthread_create(&cqueue_thread.tid, NULL, thread_cqueue, (void *) m) != 0)
|
||||||
|
exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);
|
||||||
|
|
||||||
#ifdef _AUDIO
|
#ifdef _AUDIO
|
||||||
|
|
||||||
av = init_audio(prompt, m);
|
av = init_audio(prompt, m);
|
||||||
|
|
||||||
|
|
||||||
set_primary_device(input, user_settings_->audio_in_dev);
|
set_primary_device(input, user_settings_->audio_in_dev);
|
||||||
set_primary_device(output, user_settings_->audio_out_dev);
|
set_primary_device(output, user_settings_->audio_out_dev);
|
||||||
|
|
||||||
@@ -835,7 +1049,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (config_err) {
|
if (config_err) {
|
||||||
msg = "Unable to determine configuration directory. Defaulting to 'data' for data file...";
|
msg = "Unable to determine configuration directory. Defaulting to 'data' for data file...";
|
||||||
queue_init_message(msg);
|
queue_init_message("%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings_err == -1)
|
if (settings_err == -1)
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ typedef enum _FATAL_ERRS {
|
|||||||
FATALERR_INFLOOP = -9, /* infinite loop detected */
|
FATALERR_INFLOOP = -9, /* infinite loop detected */
|
||||||
FATALERR_WININIT = -10, /* window init failed */
|
FATALERR_WININIT = -10, /* window init failed */
|
||||||
FATALERR_PROXY = -11, /* Tox network failed to init using a proxy */
|
FATALERR_PROXY = -11, /* Tox network failed to init using a proxy */
|
||||||
|
FATALERR_ENCRYPT = -12, /* Data file encryption failure */
|
||||||
} FATAL_ERRS;
|
} FATAL_ERRS;
|
||||||
|
|
||||||
/* Fixes text color problem on some terminals.
|
/* Fixes text color problem on some terminals.
|
||||||
@@ -88,7 +89,7 @@ typedef enum _FATAL_ERRS {
|
|||||||
void exit_toxic_success(Tox *m);
|
void exit_toxic_success(Tox *m);
|
||||||
void exit_toxic_err(const char *errmsg, int errcode);
|
void exit_toxic_err(const char *errmsg, int errcode);
|
||||||
|
|
||||||
int store_data(Tox *m, char *path);
|
int store_data(Tox *m, const char *path);
|
||||||
|
|
||||||
void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata);
|
void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata);
|
||||||
void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata);
|
void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata);
|
||||||
@@ -108,5 +109,6 @@ void on_file_control(Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t
|
|||||||
const uint8_t *data, uint16_t length, void *userdata);
|
const uint8_t *data, uint16_t length, void *userdata);
|
||||||
void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata);
|
void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata);
|
||||||
void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata);
|
void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata);
|
||||||
|
void on_read_receipt(Tox *m, int32_t, uint32_t, void *userdata);
|
||||||
|
|
||||||
#endif /* #define _toxic_h */
|
#endif /* #define _toxic_h */
|
||||||
|
|||||||
@@ -219,6 +219,15 @@ void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void on_read_receipt(Tox *m, int32_t friendnumber, uint32_t receipt, void *userdata)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||||
|
if (windows[i].onReadReceipt != NULL)
|
||||||
|
windows[i].onReadReceipt(&windows[i], m, friendnumber, receipt);
|
||||||
|
}
|
||||||
|
}
|
||||||
/* CALLBACKS END */
|
/* CALLBACKS END */
|
||||||
|
|
||||||
int add_window(Tox *m, ToxWindow w)
|
int add_window(Tox *m, ToxWindow w)
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ struct _Winthread {
|
|||||||
bool flag_resize;
|
bool flag_resize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _cqueue_thread {
|
||||||
|
pthread_t tid;
|
||||||
|
};
|
||||||
|
|
||||||
struct arg_opts {
|
struct arg_opts {
|
||||||
int ignore_data_file;
|
int ignore_data_file;
|
||||||
int use_ipv4;
|
int use_ipv4;
|
||||||
@@ -79,7 +83,8 @@ struct arg_opts {
|
|||||||
int default_locale;
|
int default_locale;
|
||||||
int use_custom_data;
|
int use_custom_data;
|
||||||
int no_connect;
|
int no_connect;
|
||||||
|
int encrypt_data;
|
||||||
|
int unencrypt_data;
|
||||||
char dns_path[MAX_STR_SIZE];
|
char dns_path[MAX_STR_SIZE];
|
||||||
char config_path[MAX_STR_SIZE];
|
char config_path[MAX_STR_SIZE];
|
||||||
char nodes_path[MAX_STR_SIZE];
|
char nodes_path[MAX_STR_SIZE];
|
||||||
@@ -115,6 +120,7 @@ struct ToxWindow {
|
|||||||
void(*onFileControl)(ToxWindow *, Tox *, int32_t, uint8_t, uint8_t, uint8_t, const char *, uint16_t);
|
void(*onFileControl)(ToxWindow *, Tox *, int32_t, uint8_t, uint8_t, uint8_t, const char *, uint16_t);
|
||||||
void(*onFileData)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t);
|
void(*onFileData)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t);
|
||||||
void(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t);
|
void(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t);
|
||||||
|
void(*onReadReceipt)(ToxWindow *, Tox *, int32_t, uint32_t);
|
||||||
|
|
||||||
#ifdef _AUDIO
|
#ifdef _AUDIO
|
||||||
|
|
||||||
@@ -208,6 +214,7 @@ struct ChatContext {
|
|||||||
|
|
||||||
struct history *hst;
|
struct history *hst;
|
||||||
struct chatlog *log;
|
struct chatlog *log;
|
||||||
|
struct chat_queue *cqueue;
|
||||||
|
|
||||||
#ifdef _AUDIO
|
#ifdef _AUDIO
|
||||||
struct infobox infobox;
|
struct infobox infobox;
|
||||||
|
|||||||
Reference in New Issue
Block a user