1
0
mirror of https://github.com/Tha14/toxic.git synced 2025-12-06 19:56:35 +01:00

Compare commits

...

82 Commits

Author SHA1 Message Date
Jfreegman
97a8ecd115 small fix and bump version to 0.5.2 2014-09-29 13:56:17 -04:00
JFreegman
64d782569a add asciidoc and libnotify-dev to install script 2014-09-29 01:54:53 -04:00
Jfreegman
6248baf98b fix segfault 2014-09-29 01:30:22 -04:00
Jfreegman
33cfca7ecc bug fixes and code cleanup 2014-09-28 17:49:48 -04:00
mannol
a01cc35368 Merge branch 'master' of github.com:Tox/toxic 2014-09-28 16:48:09 +02:00
mannol
b10eebd77e This should fix audio problem 2014-09-28 16:47:31 +02:00
Jfreegman
05661ca9b6 core API update and refactor group invites a bit 2014-09-27 22:50:20 -04:00
mannol
784883f773 What if, like, photosynthesis is a lie?! 2014-09-28 00:13:45 +02:00
Jfreegman
a9e5723ca4 a couple fixes 2014-09-27 03:08:19 -04:00
Jfreegman
95dfea8d29 keep chatlog names consistent with friend name changes 2014-09-27 02:28:11 -04:00
Jfreegman
e574af7d68 fix CPU usage issue regarding audio drivers, courtesy of mannol 2014-09-26 20:32:48 -04:00
JFreegman
2918ca45a2 Merge pull request #255 from Ansa89/trivial-fix
Fix "error: unknown type name 'off_t'"
2014-09-26 13:01:44 -04:00
Ansa89
6ad744f770 Add stdlib.h header to allow off_t type 2014-09-26 10:50:42 +02:00
Ansa89
5b394e6f35 notify.c: better headers order 2014-09-26 10:46:14 +02:00
Jfreegman
940af2c711 a few fixes, update example config file 2014-09-26 03:39:36 -04:00
Jfreegman
544c402f78 implement avatars (setting only) and generalize path tab-complete 2014-09-26 03:10:44 -04:00
Jfreegman
cee9e624b8 more UI changes 2014-09-25 15:23:50 -04:00
Jfreegman
2e65ee3609 a few UI changes 2014-09-25 04:31:45 -04:00
Jfreegman
3a176e1cab move to page end after pressing return 2014-09-25 00:42:08 -04:00
Jfreegman
00cccad22c a few general fixes 2014-09-24 15:20:15 -04:00
Jfreegman
a432d733d7 use 64-bit off_t for file sizes 2014-09-24 14:23:08 -04:00
Jfreegman
893e88294b more succinct way to get file sizes 2014-09-24 00:06:02 -04:00
Jfreegman
b071a9e992 more thorough error checking 2014-09-23 22:51:56 -04:00
Jfreegman
48cf4ebf02 fix for issue #254 2014-09-23 21:32:05 -04:00
Jfreegman
773a75b948 update makefile checks 2014-09-22 21:51:55 -04:00
Jfreegman
133c0e8d63 rename reserved identifiers per C standard 2014-09-22 21:24:45 -04:00
Jfreegman
bf54cb36ef set signal handlers at more appropriate places 2014-09-22 20:00:36 -04:00
Jfreegman
032853b5c9 Merge branch 'Pyrohh-master' 2014-09-22 19:41:23 -04:00
Michael Reed
650c13ca7a There's no need for rm -rf, just rm -f 2014-09-22 18:45:45 -04:00
Jfreegman
9d5fe03285 small fix 2014-09-22 18:38:46 -04:00
Jfreegman
c3f68b60d3 bigger log identifiers to reduce chance of collision 2014-09-22 17:34:30 -04:00
Jfreegman
1c16467eb9 don't share chatlogs across data files (changes log naming convention) 2014-09-22 17:09:39 -04:00
Jfreegman
3c74385f5c use proper variable type for sig handler flags 2014-09-22 14:27:33 -04:00
Jfreegman
c07c0028bb increase line_info msg buffer size so won't cut off long log lines 2014-09-22 13:49:09 -04:00
Jfreegman
dc3b2e04ab load chatlog history when opening a chatwindow 2014-09-22 04:29:28 -04:00
JFreegman
7fd3aa9164 Merge pull request #246 from urras/patch-2
Update screenshot
2014-09-21 13:17:13 -04:00
Urras
4c60312e2d Update screenshot 2014-09-21 12:42:04 -04:00
JFreegman
16e29aa4e0 Merge pull request #243 from Ansa89/trivial-fix
Makefile: use single quotes also for PACKAGE_DATADIR
2014-09-19 12:28:32 -04:00
Ansa89
bd7b073155 Makefile: fix typo 2014-09-19 10:47:25 +02:00
Ansa89
f25cf870e6 Makefile: use single quotes also for PACKAGE_DATADIR 2014-09-19 10:45:27 +02:00
Jfreegman
13291d0365 bump version to 0.5.1 2014-09-19 01:24:39 -04:00
Jfreegman
9ee7a48910 add setting to disable welcome message 2014-09-19 01:11:23 -04:00
Jfreegman
daf4614ba6 improve behaviour of misused encryption options 2014-09-19 00:29:30 -04:00
Jfreegman
919d36369c add option to unencrypt an encrypted data file 2014-09-18 23:50:51 -04:00
Jfreegman
618704df76 remove duplicate DHT node 2014-09-18 22:52:05 -04:00
Jfreegman
9a70dd9651 possibly fix display bug on some platforms 2014-09-18 13:14:15 -04:00
Sean
e2d310b10f Add TCP nodes on 443 2014-09-17 14:00:41 -07:00
Jfreegman
a1015a366a update DHTnodes, small fixes 2014-09-17 13:52:27 -04:00
mannol
913ec7b3fe Merge pull request #242 from Ansa89/trivial-fix
Usage help: add missing comma
2014-09-16 13:55:20 +02:00
Ansa89
4a52b06954 Usage help: add missing comma 2014-09-16 11:54:58 +02:00
Jfreegman
89f9c07b9e add confirmation when creating new password 2014-09-15 19:00:36 -04:00
Jfreegman
388d78d11e add option to encrypt an existing unencrypted data file 2014-09-15 16:17:58 -04:00
Jfreegman
a2a23b3932 password prompt fixes 2014-09-15 04:13:12 -04:00
Jfreegman
f405ae8b42 improvements to password entry screen 2014-09-14 21:49:38 -04:00
Jfreegman
cf3f6750eb small fix 2014-09-14 18:25:13 -04:00
JFreegman
4de22d067a Update .travis.yml 2014-09-14 18:08:42 -04:00
Jfreegman
51e274ea38 implement data file encryption 2014-09-14 17:46:28 -04:00
Jfreegman
0a6ce62363 don't write unsent messages to log 2014-09-11 01:36:33 -04:00
Jfreegman
13c5de5531 increase time between message send retries 2014-09-10 16:18:37 -04:00
Jfreegman
21f8e7f398 couple small fixes 2014-09-09 15:16:27 -04:00
Jfreegman
bcf4a5af90 message queue improvements 2014-09-09 14:06:28 -04:00
Jfreegman
09f90d095b properly flag lines with unread mark 2014-09-07 22:28:54 -04:00
Jfreegman
416ebc9ab8 another fix 2014-09-07 22:05:17 -04:00
Jfreegman
3ca22aa714 fix 2014-09-07 21:43:16 -04:00
Jfreegman
8dd25e1f0b code cleanup, add delay for unread message notification 2014-09-07 15:08:01 -04:00
Jfreegman
5b9bd603ea implement read receipts 2014-09-07 02:43:53 -04:00
Jfreegman
3c2c1f15ce message sending queue for fake offline messaging 2014-09-06 13:18:42 -04:00
JFreegman
6876df4a45 Merge pull request #240 from s3erios/master
Fix some 'clang --analyze' warnings
2014-09-05 13:16:43 -04:00
Andriy Voskoboinyk
1ff97161fb temporarily revert a862874740. 2014-09-05 14:15:25 +03:00
Andriy Voskoboinyk
667410e879 fix another potential memory leak 2014-09-05 13:17:10 +03:00
Andriy Voskoboinyk
a862874740 mark exit_toxic_* functions as noreturn 2014-09-05 13:15:56 +03:00
Andriy Voskoboinyk
79bde4e5bf fix potential memory leak and move cleanup to the end of the function 2014-09-05 13:02:26 +03:00
Jfreegman
833b724e9f fix bug 2014-09-04 18:48:55 -04:00
Jfreegman
96b68058bb code cleanup and fix bug that sometimes prevented tab notifications from working 2014-09-04 18:28:20 -04:00
JFreegman
e823233149 Merge pull request #238 from Ansa89/trivial-fix
Addition to Tox/toxic#235
2014-09-04 13:23:33 -04:00
Ansa89
3ac22fafe4 Add info about DISABLE_X11 usage 2014-09-04 19:20:51 +02:00
JFreegman
71f2ac170c Merge pull request #235 from s3erios/master_cfg
Add X11 option
2014-09-04 13:18:46 -04:00
mannol
0ef888eea3 Merge pull request #236 from s3erios/master
Some code simplification
2014-09-04 11:10:55 +02:00
Andriy Voskoboinyk
a9b0028a15 move some code inside _X11 ifdef 2014-09-04 01:41:02 +03:00
Andriy Voskoboinyk
b18e6cff5a move duplicate code into separate function 2014-09-04 01:36:37 +03:00
Andriy Voskoboinyk
424a1c94d9 Add X11 option 2014-09-04 01:19:32 +03:00
Jfreegman
009095af24 slight simplification for command list iteration 2014-09-02 02:23:44 -04:00
61 changed files with 1793 additions and 822 deletions

View File

@@ -5,11 +5,11 @@ compiler:
before_script:
# Installing yasm (needed for compiling vpx) and openal
- sudo apt-get -yq install yasm libopenal-dev libconfig-dev libalut-dev
- sudo apt-get -yq install yasm libopenal-dev libconfig-dev libalut-dev libnotify-dev asciidoc
# Installing libsodium, needed for toxcore
- git clone https://github.com/jedisct1/libsodium.git libsodium
- cd libsodium
- git checkout tags/0.4.2 > /dev/null
- git checkout tags/0.7.0 > /dev/null
- ./autogen.sh > /dev/null
- ./configure > /dev/null
- make check -j2 || make check || exit 1 > /dev/null

View File

@@ -1,7 +1,7 @@
# Toxic [![Build Status](https://travis-ci.org/Tox/toxic.png?branch=master)](https://travis-ci.org/Tox/toxic)
Toxic is a [Tox](https://tox.im)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/irungentoo/toxcore), and is now available as a standalone application.
![Toxic Screenshot](https://i.imgur.com/ryaEmQZ.png "Home Screen")
![Toxic Screenshot](https://i.imgur.com/san99Z2.png "Home Screen")
## Installation
@@ -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 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:
* `DISABLE_X11=1` → build toxic without X11 support (needed for focus tracking)
* `DISABLE_AV=1` → build toxic without audio call support
* `DISABLE_SOUND_NOTIFY=1` → build toxic without sound notifications support
* `DISABLE_DESKTOP_NOTIFY=1` → build toxic without desktop notifications support

View File

@@ -6,14 +6,14 @@ CFG_DIR = $(BASE_DIR)/cfg
LIBS = libtoxcore ncursesw libconfig
CFLAGS = -std=gnu99 -pthread -Wall -g
CFLAGS += -DTOXICVER="\"$(VERSION)\"" -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED
CFLAGS += -DPACKAGE_DATADIR="\"$(abspath $(DATADIR))\""
CFLAGS += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED -D_FILE_OFFSET_BITS=64
CFLAGS += '-DPACKAGE_DATADIR="$(abspath $(DATADIR))"'
CFLAGS += $(USER_CFLAGS)
LDFLAGS = $(USER_LDFLAGS)
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 += 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
UNAME_S = $(shell uname -s)
@@ -58,7 +58,7 @@ toxic: $(OBJ)
@$(CC) -MM $(CFLAGS) $(SRC_DIR)/$*.c > $*.d
clean:
rm -rf *.d *.o toxic
rm -f *.d *.o toxic
-include $(OBJ:.o=.d)

View File

@@ -1,6 +1,6 @@
# Variables for audio call support
AUDIO_LIBS = libtoxav openal
AUDIO_CFLAGS = -D_AUDIO
AUDIO_CFLAGS = -DAUDIO
ifneq (, $(findstring device.o, $(OBJ)))
AUDIO_OBJ = audio_call.o
else

View File

@@ -1,10 +1,9 @@
CHECKS_DIR = $(CFG_DIR)/checks
# Check if we can use X11
CHECK_X11_LIBS = $(shell pkg-config --exists x11 || echo -n "error")
ifneq ($(CHECK_X11_LIBS), error)
LIBS += x11
CFLAGS += -D_X11
# Check if we want build X11 support
X11 = $(shell if [ -z "$(DISABLE_X11)" ] || [ "$(DISABLE_X11)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
ifneq ($(X11), disabled)
-include $(CHECKS_DIR)/x11.mk
endif
# Check if we want build audio support

View File

@@ -1,6 +1,6 @@
# Variables for desktop notifications support
DESK_NOTIFY_LIBS = libnotify
DESK_NOTIFY_CFLAGS = -D_BOX_NOTIFY
DESK_NOTIFY_CFLAGS = -DBOX_NOTIFY
# Check if we can build desktop notifications support
CHECK_DESK_NOTIFY_LIBS = $(shell pkg-config --exists $(DESK_NOTIFY_LIBS) || echo -n "error")

View File

@@ -1,6 +1,6 @@
# Variables for sound notifications support
SND_NOTIFY_LIBS = openal freealut
SND_NOTIFY_CFLAGS = -D_SOUND_NOTIFY
SND_NOTIFY_CFLAGS = -DSOUND_NOTIFY
ifneq (, $(findstring device.o, $(OBJ)))
SND_NOTIFY_OBJ =
else

17
cfg/checks/x11.mk Normal file
View File

@@ -0,0 +1,17 @@
# Variables for X11 support
X11_LIBS = x11
X11_CFLAGS = -DX11
# 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

View File

@@ -1,5 +1,5 @@
# Version
TOXIC_VERSION = 0.5.0
TOXIC_VERSION = 0.5.2
REV = $(shell git rev-list HEAD --count)
VERSION = $(TOXIC_VERSION)_r$(REV)

View File

@@ -9,6 +9,7 @@ help:
@echo " help: This help"
@echo
@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_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"

View File

@@ -2,12 +2,12 @@
.\" Title: toxic
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Date: 2014-08-21
.\" Date: 2014-09-19
.\" Manual: Toxic Manual
.\" Source: toxic __VERSION__
.\" 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
.\" -----------------------------------------------------------------
@@ -55,11 +55,16 @@ instead of
\fI~/\&.config/tox/toxic\&.conf\fR
.RE
.PP
\-d, \-\-default_locale
\-d, \-\-default\-locale
.RS 4
Use default locale
.RE
.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
.RS 4
Use specified
@@ -101,6 +106,11 @@ Use specified DNSservers file
Force TCP connection (use this with proxies)
.RE
.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
.RS 4
Ignore data file

View File

@@ -27,9 +27,13 @@ OPTIONS
-c, --config config-file::
Use specified 'config-file' instead of '~/.config/tox/toxic.conf'
-d, --default_locale::
-d, --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::
Use specified 'data-file' instead of '~/.config/tox/data'
@@ -52,6 +56,10 @@ OPTIONS
-t, --force-tcp::
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::
Ignore data file

View File

@@ -2,12 +2,12 @@
.\" Title: toxic.conf
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Date: 2014-08-21
.\" Date: 2014-09-19
.\" Manual: Toxic Manual
.\" Source: toxic __VERSION__
.\" Language: English
.\"
.TH "TOXIC\&.CONF" "5" "2014\-08\-21" "toxic __VERSION__" "Toxic Manual"
.TH "TOXIC\&.CONF" "5" "2014\-09\-19" "toxic __VERSION__" "Toxic Manual"
.\" -----------------------------------------------------------------
.\" * 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
.RE
.PP
\fBshow_welcome_msg\fR
.RS 4
Show welcome message on startup\&. true or false
.RE
.PP
\fBhistory_size\fR
.RS 4
Maximum lines for chat window history\&. Integer value\&. (for example: 700)
@@ -133,6 +138,11 @@ Configuration related to paths\&.
Default path for downloads\&. String value\&. Absolute path for downloaded files\&.
.RE
.PP
\fBavatar_path\fR
.RS 4
Path for your avatar (file must be a \&.png and cannot exceed 16\&.3 KiB)
.RE
.PP
\fBchatlogs_path\fR
.RS 4
Default path for chatlogs\&. String value\&. Absolute path for chatlog files\&.

View File

@@ -60,6 +60,9 @@ OPTIONS
*show_typing_self*;;
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*;;
Maximum lines for chat window history. Integer value. (for example: 700)
@@ -84,6 +87,9 @@ OPTIONS
Default path for downloads. String value. Absolute path for downloaded
files.
*avatar_path*;;
Path for your avatar (file must be a .png and cannot exceed 16.3 KiB)
*chatlogs_path*;;
Default path for chatlogs. String value. Absolute path for chatlog files.

View File

@@ -5,6 +5,7 @@
54.199.139.199 33445 7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029
192.210.149.121 33445 F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67
37.59.102.176 33445 B98A2CEAA6C6A2FADC2C3632D284318B60FE5375CCB41EFA081AB67F500C1B0B
95.85.13.245 33445 7187969BB10B54C98538BAE94C069CE5C84E650D54F7E596543D8FB1ECF4CF23
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

View File

@@ -23,6 +23,9 @@ ui = {
// true to show others when you're typing a message in 1-on-1 chats
show_typing_self=true;
// true to show the welcome message on startup
show_welcome_msg=true;
// maximum lines for chat window history
history_size=700;
};
@@ -42,6 +45,9 @@ tox = {
// Path for downloaded files
// download_path="/home/USERNAME/Downloads/";
// Path for your avatar (file must be a .png and cannot exceed 16.3 KiB)
// avatar_path="/home/USERNAME/Pictures/youravatar.png";
// Path for chatlogs
// chatlogs_path="/home/USERNAME/toxic_chatlogs/";
};

View File

@@ -29,6 +29,7 @@
#include "line_info.h"
#include "notify.h"
#include <stdbool.h>
#include <curses.h>
#include <string.h>
#include <pthread.h>
@@ -48,36 +49,41 @@
#endif
#endif
#define _cbend pthread_exit(NULL)
#define cbend pthread_exit(NULL)
#define MAX_CALLS 10
#define frame_size (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000)
typedef struct _Call {
typedef struct Call {
pthread_t ttid; /* Transmission thread id */
_Bool ttas, has_output; /* Transmission thread active status (0 - stopped, 1- running) */
bool ttas, has_output; /* Transmission thread active status (0 - stopped, 1- running) */
uint32_t in_idx, out_idx;
pthread_mutex_t mutex;
} Call;
void set_call(Call* call, _Bool start)
static int set_call(Call* call, bool start)
{
call->in_idx = -1;
call->out_idx = -1;
if ( start ) {
call->ttas = _True;
pthread_mutex_init(&call->mutex, NULL);
call->ttas = true;
if (pthread_mutex_init(&call->mutex, NULL) != 0)
return -1;
}
else {
call->ttid = 0;
pthread_mutex_destroy(&call->mutex);
}
if (pthread_mutex_destroy(&call->mutex) != 0)
return -1;
}
struct _ASettings {
return 0;
}
struct ASettings {
AudioError errors;
ToxAv *av;
@@ -198,7 +204,8 @@ int start_transmission(ToxWindow *self)
!toxav_capability_supported(ASettins.av, self->call_idx, AudioEncoding) )
return -1;
set_call(&ASettins.calls[self->call_idx], _True);
if (set_call(&ASettins.calls[self->call_idx], true) == -1)
return -1;
ToxAvCSettings csettings;
toxav_get_peer_csettings(ASettins.av, self->call_idx, 0, &csettings);
@@ -208,7 +215,7 @@ int start_transmission(ToxWindow *self)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open input device!");
if ( register_device_callback(self->call_idx, ASettins.calls[self->call_idx].in_idx,
read_device_callback, &self->call_idx, _True) != de_None)
read_device_callback, &self->call_idx, true) != de_None)
/* Set VAD as true for all; TODO: Make it more dynamic */
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to register input handler!");
@@ -225,7 +232,7 @@ int stop_transmission(int call_index)
{
if ( ASettins.calls[call_index].ttas ) {
toxav_kill_transmission(ASettins.av, call_index);
ASettins.calls[call_index].ttas = _False;
ASettins.calls[call_index].ttas = false;
if ( ASettins.calls[call_index].in_idx != -1 )
close_device(input, ASettins.calls[call_index].in_idx);
@@ -233,7 +240,9 @@ int stop_transmission(int call_index)
if ( ASettins.calls[call_index].out_idx != -1 )
close_device(output, ASettins.calls[call_index].out_idx);
set_call(&ASettins.calls[call_index], _False);
if (set_call(&ASettins.calls[call_index], false) == -1)
return -1;
return 0;
}
@@ -452,7 +461,7 @@ void cmd_hangup(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
if (toxav_get_call_state(ASettins.av, self->call_idx) == av_CallInviting) {
error = toxav_cancel(ASettins.av, self->call_idx, self->num,
"Only those who appreciate small things know the beauty that is life");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call canceled!");
@@ -610,7 +619,7 @@ void cmd_ccur_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
open_device(input, selection, &this_call->in_idx, csettings.audio_sample_rate,
csettings.audio_frame_duration, csettings.audio_channels);
/* Set VAD as true for all; TODO: Make it more dynamic */
register_device_callback(self->call_idx, this_call->in_idx, read_device_callback, &self->call_idx, _True);
register_device_callback(self->call_idx, this_call->in_idx, read_device_callback, &self->call_idx, true);
}
}
}

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _audio_h
#define _audio_h
#ifndef AUDIO_H
#define AUDIO_H
#include <tox/toxav.h>
@@ -42,4 +42,4 @@ void terminate_audio();
void stop_current_call(ToxWindow *self);
#endif /* _audio_h */
#endif /* AUDIO_H */

View File

@@ -104,7 +104,9 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size)
if (wcs_to_mbs_buf(ubuf, ctx->line, sizeof(ubuf)) == -1)
return -1;
bool dir_search = strncmp(ubuf, "/sendfile", strlen("/sendfile")) == 0;
/* TODO: generalize this */
bool dir_search = !strncmp(ubuf, "/sendfile", strlen("/sendfile"))
|| !strncmp(ubuf, "/avatar", strlen("/avatar"));
/* isolate substring from space behind pos to pos */
char tmp[MAX_STR_SIZE];
@@ -202,8 +204,8 @@ int complete_line(ToxWindow *self, const void *list, int n_items, int size)
return diff;
}
/* transforms a sendfile tab complete contaning the shorthand "~/" into the full home directory.*/
static void complt_home_dir(ToxWindow *self, char *path, int pathsize)
/* transforms a tab complete starting with the shorthand "~" into the full home directory.*/
static void complt_home_dir(ToxWindow *self, char *path, int pathsize, const char *cmd, int cmdlen)
{
ChatContext *ctx = self->chatwin;
@@ -211,8 +213,8 @@ static void complt_home_dir(ToxWindow *self, char *path, int pathsize)
get_home_dir(homedir, sizeof(homedir));
char newline[MAX_STR_SIZE];
snprintf(newline, sizeof(newline), "/sendfile \"%s%s", homedir, path + 1);
snprintf(path, pathsize, "%s", &newline[11]);
snprintf(newline, sizeof(newline), "%s \"%s%s", cmd, homedir, path + 1);
snprintf(path, pathsize, "%s", &newline[cmdlen]);
wchar_t wline[MAX_STR_SIZE];
@@ -229,23 +231,27 @@ static void complt_home_dir(ToxWindow *self, char *path, int pathsize)
ctx->len = ctx->pos;
}
/* attempts to match /sendfile "<incomplete-dir>" line to matching directories.
/* attempts to match /command "<incomplete-dir>" line to matching directories.
if only one match, auto-complete line.
return diff between old len and new len of ctx->line, -1 if no matches or > 1 match */
#define MAX_DIRS 512
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line)
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd)
{
char b_path[MAX_STR_SIZE];
char b_name[MAX_STR_SIZE];
const wchar_t *tmpline = &line[11]; /* start after "/sendfile \"" */
char b_cmd[MAX_STR_SIZE];
const wchar_t *tmpline = &line[wcslen(cmd) + 2]; /* start after "/command \"" */
if (wcs_to_mbs_buf(b_path, tmpline, sizeof(b_path)) == -1)
return -1;
if (wcs_to_mbs_buf(b_cmd, cmd, sizeof(b_cmd)) == -1)
return -1;
if (b_path[0] == '~')
complt_home_dir(self, b_path, sizeof(b_path));
complt_home_dir(self, b_path, sizeof(b_path), b_cmd, strlen(b_cmd) + 2);
int si = char_rfind(b_path, '/', strlen(b_path));
@@ -261,7 +267,6 @@ int dir_match(ToxWindow *self, Tox *m, const wchar_t *line)
strcpy(b_name, &b_path[si + 1]);
b_path[si + 1] = '\0';
int b_name_len = strlen(b_name);
DIR *dp = opendir(b_path);
if (dp == NULL)

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _autocomplete_h
#define _autocomplete_h
#ifndef AUTOCOMPLETE_H
#define AUTOCOMPLETE_H
/* looks for all instances in list that begin with the last entered word in line according to pos,
then fills line with the complete word. e.g. "Hello jo" would complete the line
@@ -33,10 +33,10 @@
Returns the difference between the old len and new len of line on success, -1 if error */
int complete_line(ToxWindow *self, const void *list, int n_items, int size);
/* attempts to match /sendfile "<incomplete-dir>" line to matching directories.
/* attempts to match /command "<incomplete-dir>" line to matching directories.
if only one match, auto-complete line.
return diff between old len and new len of ctx->line, -1 if no matches or > 1 match */
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line);
int dir_match(ToxWindow *self, Tox *m, const wchar_t *line, const wchar_t *cmd);
#endif /* #define _autocomplete_h */
#endif /* #define AUTOCOMPLETE_H */

View File

@@ -43,35 +43,37 @@
#include "help.h"
#include "autocomplete.h"
#include "notify.h"
#include "message_queue.h"
#ifdef _AUDIO
#ifdef AUDIO
#include "audio_call.h"
#endif /* _AUDIO */
#endif /* AUDIO */
extern char *DATA_FILE;
extern FileSender file_senders[MAX_FILES];
extern _Friends Friends;
extern FriendsList Friends;
extern struct _Winthread Winthread;
extern struct user_settings *user_settings_;
extern struct Winthread Winthread;
extern struct user_settings *user_settings;
#ifdef _AUDIO
#ifdef AUDIO
static void init_infobox(ToxWindow *self);
static void kill_infobox(ToxWindow *self);
#endif /* _AUDIO */
#endif /* AUDIO */
#ifdef _AUDIO
#define AC_NUM_CHAT_COMMANDS 26
#ifdef AUDIO
#define AC_NUM_CHAT_COMMANDS 27
#else
#define AC_NUM_CHAT_COMMANDS 19
#endif /* _AUDIO */
#define AC_NUM_CHAT_COMMANDS 20
#endif /* AUDIO */
/* Array of chat command names used for tab completion. */
static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/accept" },
{ "/add" },
{ "/avatar" },
{ "/cancel" },
{ "/clear" },
{ "/close" },
@@ -90,7 +92,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/sendfile" },
{ "/status" },
#ifdef _AUDIO
#ifdef AUDIO
{ "/call" },
{ "/answer" },
@@ -100,12 +102,12 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/mute" },
{ "/sense" },
#endif /* _AUDIO */
#endif /* AUDIO */
};
static void set_self_typingstatus(ToxWindow *self, Tox *m, uint8_t is_typing)
{
if (user_settings_->show_typing_self == SHOW_TYPING_OFF)
if (user_settings->show_typing_self == SHOW_TYPING_OFF)
return;
ChatContext *ctx = self->chatwin;
@@ -134,8 +136,9 @@ void kill_chat_window(ToxWindow *self, Tox *m)
close_all_file_receivers(m, self->num);
log_disable(ctx->log);
line_info_cleanup(ctx->hst);
cqueue_cleanup(ctx->cqueue);
#ifdef _AUDIO
#ifdef AUDIO
stop_current_call(self);
#endif
@@ -144,7 +147,6 @@ void kill_chat_window(ToxWindow *self, Tox *m)
delwin(statusbar->topline);
free(ctx->log);
free(ctx->hst);
free(ctx);
free(self->help);
free(statusbar);
@@ -196,7 +198,7 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, int32_t num, uint8_
if (status == 1) { /* Friend goes online */
statusbar->is_online = true;
Friends.list[num].is_typing = user_settings_->show_typing_other == SHOW_TYPING_ON
Friends.list[num].is_typing = user_settings->show_typing_other == SHOW_TYPING_ON
? tox_get_is_typing(m, num) : 0;
chat_resume_file_transfers(m, num);
@@ -239,7 +241,7 @@ static void chat_onAction(ToxWindow *self, Tox *m, int32_t num, const char *acti
char timefrmt[TIME_STR_SIZE];
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);
if (self->active_box != -1)
@@ -287,14 +289,17 @@ static void chat_onStatusMessageChange(ToxWindow *self, int32_t num, const char
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,
uint64_t filesize, const char *pathname, uint16_t path_len)
{
if (self->num != num)
return;
const char *errmsg;
/* holds the filename appended to the user specified path */
char filename_path[MAX_STR_SIZE] = {0};
@@ -308,20 +313,18 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
filename_nopath, sizestr);
if (filenum >= MAX_FILES) {
errmsg = "Too many pending file requests; discarding.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Too many pending file requests; discarding.");
return;
}
/* use specified path in config if possible */
if (user_settings_->download_path[0]) {
snprintf(filename_path, sizeof(filename_path), "%s%s", user_settings_->download_path, filename_nopath);
len += strlen(user_settings_->download_path);
if (user_settings->download_path[0]) {
snprintf(filename_path, sizeof(filename_path), "%s%s", user_settings->download_path, filename_nopath);
len += strlen(user_settings->download_path);
}
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, errmsg);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File name too long; discarding.");
return;
}
@@ -351,8 +354,7 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
filename[len + d_len] = '\0';
if (count > 999) {
errmsg = "Error saving file to disk.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error saving file to disk.");
return;
}
}
@@ -494,7 +496,10 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
case TOX_FILECONTROL_FINISHED:
if (receive_send == 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);
} else {
snprintf(msg, sizeof(msg), "File '%s' successfuly sent.", filename);
@@ -524,7 +529,12 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
uint64_t datapos;
memcpy(&datapos, tmp, sizeof(uint64_t));
fseek(fp, datapos, SEEK_SET);
if (fseek(fp, datapos, SEEK_SET) == -1) {
snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", filename);
close_file_sender(self, m, send_idx, NULL, TOX_FILECONTROL_FINISHED, filenum, num);
break;
}
tox_file_send_control(m, num, 0, filenum, TOX_FILECONTROL_ACCEPT, 0, 0);
file_senders[send_idx].noconnection = false;
break;
@@ -553,32 +563,40 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu
Friends.list[num].file_receiver[filenum].bytes_recv += length;
}
static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, const char *group_pub_key)
static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, const char *group_pub_key, uint16_t length)
{
if (self->num != friendnumber)
return;
if (Friends.list[friendnumber].group_invite.key != NULL)
free(Friends.list[friendnumber].group_invite.key);
char *k = malloc(length);
if (k == NULL)
exit_toxic_err("Failed in chat_onGroupInvite", FATALERR_MEMORY);
memcpy(k, group_pub_key, length);
Friends.list[friendnumber].group_invite.key = k;
Friends.list[friendnumber].group_invite.pending = true;
Friends.list[friendnumber].group_invite.length = length;
char name[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, name, friendnumber);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat.");
memcpy(Friends.list[friendnumber].groupchat_key, group_pub_key,
sizeof(Friends.list[friendnumber].groupchat_key));
Friends.list[friendnumber].groupchat_pending = true;
sound_notify(self, generic_message, NT_WNDALERT_2, NULL);
if (self->active_box != -1)
box_silent_notify2(self, NT_WNDALERT_2 | NT_NOFOCUS, self->active_box, "invites you to join group chat");
else
box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join group chat");
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat.");
}
/* Av Stuff */
#ifdef _AUDIO
#ifdef AUDIO
void chat_onInvite (ToxWindow *self, ToxAv *av, int call_index)
{
@@ -607,10 +625,10 @@ void chat_onRinging (ToxWindow *self, ToxAv *av, int call_index)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ringing...type \"/hangup\" to cancel it.");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
if (self->ringing_sound == -1)
sound_notify(self, call_outgoing, NT_LOOP, &self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onStarting (ToxWindow *self, ToxAv *av, int call_index)
@@ -622,9 +640,9 @@ void chat_onStarting (ToxWindow *self, ToxAv *av, int call_index)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call started! Type: \"/hangup\" to end it.");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onEnding (ToxWindow *self, ToxAv *av, int call_index)
@@ -636,9 +654,9 @@ void chat_onEnding (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call ended!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onError (ToxWindow *self, ToxAv *av, int call_index)
@@ -649,9 +667,9 @@ void chat_onError (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onStart (ToxWindow *self, ToxAv *av, int call_index)
@@ -663,9 +681,9 @@ void chat_onStart (ToxWindow *self, ToxAv *av, int call_index)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call started! Type: \"/hangup\" to end it.");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onCancel (ToxWindow *self, ToxAv *av, int call_index)
@@ -677,9 +695,9 @@ void chat_onCancel (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call canceled!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onReject (ToxWindow *self, ToxAv *av, int call_index)
@@ -690,9 +708,9 @@ void chat_onReject (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Rejected!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onEnd (ToxWindow *self, ToxAv *av, int call_index)
@@ -704,9 +722,9 @@ void chat_onEnd (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call ended!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onRequestTimeout (ToxWindow *self, ToxAv *av, int call_index)
@@ -717,9 +735,9 @@ void chat_onRequestTimeout (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No answer!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
void chat_onPeerTimeout (ToxWindow *self, ToxAv *av, int call_index)
@@ -731,9 +749,9 @@ void chat_onPeerTimeout (ToxWindow *self, ToxAv *av, int call_index)
self->call_idx = -1;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer disconnected; call ended!");
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
static void init_infobox(ToxWindow *self)
@@ -748,7 +766,7 @@ static void init_infobox(ToxWindow *self)
ctx->infobox.win = newwin(INFOBOX_HEIGHT, INFOBOX_WIDTH + 1, 1, x2 - INFOBOX_WIDTH);
ctx->infobox.starttime = get_unix_time();
ctx->infobox.vad_lvl = user_settings_->VAD_treshold;
ctx->infobox.vad_lvl = user_settings->VAD_treshold;
ctx->infobox.active = true;
strcpy(ctx->infobox.timestr, "00");
}
@@ -818,7 +836,7 @@ static void draw_infobox(ToxWindow *self)
wrefresh(infobox->win);
}
#endif /* _AUDIO */
#endif /* AUDIO */
static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
{
@@ -832,13 +850,8 @@ static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, selfname, NULL, ACTION, 0, 0, "%s", action);
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);
}
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);
}
static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
@@ -875,8 +888,11 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (key == '\t' && ctx->len > 1 && ctx->line[0] == '/') { /* TAB key: auto-complete */
int diff = -1;
/* TODO: make this not suck */
if (wcsncmp(ctx->line, L"/sendfile \"", wcslen(L"/sendfile \"")) == 0) {
diff = dir_match(self, m, ctx->line);
diff = dir_match(self, m, ctx->line, L"/sendfile");
} else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
diff = dir_match(self, m, ctx->line, L"/avatar");
} else {
diff = complete_line(self, chat_cmd_list, AC_NUM_CHAT_COMMANDS, MAX_CMDNAME_SIZE);
}
@@ -919,12 +935,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, selfname, NULL, OUT_MSG, 0, 0, "%s", line);
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);
}
cqueue_add(ctx->cqueue, line, strlen(line), OUT_MSG, ctx->hst->line_end->id + 1);
}
wclear(ctx->linewin);
@@ -1023,7 +1034,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
}
if (statusbar->statusmsg[0])
wprintw(statusbar->topline, "- %s ", statusbar->statusmsg);
wprintw(statusbar->topline, ": %s ", statusbar->statusmsg);
wclrtoeol(statusbar->topline);
wmove(statusbar->topline, 0, x2 - (KEY_IDENT_DIGITS * 2) - 3);
@@ -1046,7 +1057,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
wrefresh(self->window);
#ifdef _AUDIO
#ifdef AUDIO
if (ctx->infobox.active) {
draw_infobox(self);
wrefresh(self->window);
@@ -1090,14 +1101,21 @@ static void chat_onInit(ToxWindow *self, Tox *m)
ctx->hst = calloc(1, sizeof(struct history));
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);
line_info_init(ctx->hst);
if (Friends.list[self->num].logging_on)
log_enable(nick, Friends.list[self->num].pub_key, ctx->log);
char myid[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid);
log_enable(nick, myid, Friends.list[self->num].pub_key, ctx->log, LOG_CHAT);
load_chat_history(self, ctx->log);
if (!Friends.list[self->num].logging_on)
log_disable(ctx->log);
execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);
@@ -1127,8 +1145,9 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
ret.onFileSendRequest = &chat_onFileSendRequest;
ret.onFileControl = &chat_onFileControl;
ret.onFileData = &chat_onFileData;
ret.onReadReceipt = &chat_onReadReceipt;
#ifdef _AUDIO
#ifdef AUDIO
ret.onInvite = &chat_onInvite;
ret.onRinging = &chat_onRinging;
ret.onStarting = &chat_onStarting;
@@ -1144,7 +1163,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
ret.call_idx = -1;
ret.device_selection[0] = ret.device_selection[1] = -1;
ret.ringing_sound = -1;
#endif /* _AUDIO */
#endif /* AUDIO */
ret.active_box = -1;

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef CHAT_H_6489PZ13
#define CHAT_H_6489PZ13
#ifndef CHAT_H
#define CHAT_H
#include "windows.h"
#include "toxic.h"
@@ -32,4 +32,4 @@ void chat_close_file_receiver(Tox *m, int filenum, int friendnum, int CTRL);
void kill_chat_window(ToxWindow *self, Tox *m);
ToxWindow new_chat(Tox *m, int32_t friendnum);
#endif /* end of include guard: CHAT_H_6489PZ13 */
#endif /* end of include guard: CHAT_H */

View File

@@ -34,7 +34,7 @@
#include "file_senders.h"
extern ToxWindow *prompt;
extern _Friends Friends;
extern FriendsList Friends;
extern FileSender file_senders[MAX_FILES];
extern uint8_t max_file_senders_index;
@@ -123,14 +123,15 @@ void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
return;
}
const char *groupkey = Friends.list[self->num].groupchat_key;
const char *groupkey = Friends.list[self->num].group_invite.key;
uint16_t length = Friends.list[self->num].group_invite.length;
if (!Friends.list[self->num].groupchat_pending) {
if (!Friends.list[self->num].group_invite.pending) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending group chat invite.");
return;
}
int groupnum = tox_join_groupchat(m, self->num, (uint8_t *) groupkey);
int groupnum = tox_join_groupchat(m, self->num, (uint8_t *) groupkey, length);
if (groupnum == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize.");
@@ -224,9 +225,13 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
return;
}
fseek(file_to_send, 0, SEEK_END);
uint64_t filesize = ftell(file_to_send);
fseek(file_to_send, 0, SEEK_SET);
off_t filesize = file_size(path);
if (filesize == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File corrupt.");
fclose(file_to_send);
return;
}
char filename[MAX_STR_SIZE] = {0};
get_file_name(filename, sizeof(filename), path);
@@ -235,6 +240,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
if (filenum == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error sending file.");
fclose(file_to_send);
return;
}

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _chat_commands_h
#define _chat_commands_h
#ifndef CHAT_COMMANDS_H
#define CHAT_COMMANDS_H
#include "windows.h"
#include "toxic.h"
@@ -32,7 +32,7 @@ void cmd_join_group(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR
void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
#ifdef _AUDIO
#ifdef AUDIO
void cmd_call(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_answer(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_reject(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
@@ -41,6 +41,6 @@ void cmd_cancel(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZ
void cmd_ccur_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_mute(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_sense(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
#endif /* _AUDIO */
#endif /* AUDIO */
#endif /* #define _chat_commands_h */
#endif /* #define CHAT_COMMANDS_H */

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _configdir_h
#define _configdir_h
#ifndef CONFIGDIR_H
#define CONFIGDIR_H
#ifndef NSS_BUFLEN_PASSWD
#define NSS_BUFLEN_PASSWD 4096
@@ -38,4 +38,4 @@ char *get_user_config_dir(void);
void get_home_dir(char *home, int size);
int create_user_config_dirs(char *path);
#endif /* #define _configdir_h */
#endif /* #define CONFIGDIR_H */

View File

@@ -22,7 +22,7 @@
#include "device.h"
#ifdef _AUDIO
#ifdef AUDIO
#include "audio_call.h"
#endif
@@ -41,6 +41,7 @@
#endif
#endif
#include <stdbool.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
@@ -50,9 +51,9 @@
#define OPENAL_BUFS 5
#define inline__ inline __attribute__((always_inline))
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
typedef struct _Device {
typedef struct Device {
ALCdevice *dhndl; /* Handle of device selected/opened */
ALCcontext *ctx; /* Device context */
DataHandleCallback cb; /* Use this to handle data from input device usually */
@@ -60,15 +61,15 @@ typedef struct _Device {
int32_t call_idx; /* ToxAv call index */
uint32_t source, buffers[OPENAL_BUFS]; /* Playback source/buffers */
size_t ref_count;
uint32_t ref_count;
int32_t selection;
_Bool enable_VAD;
_Bool muted;
bool enable_VAD;
bool muted;
pthread_mutex_t mutex[1];
uint32_t sample_rate;
uint32_t frame_duration;
int32_t sound_mode;
#ifdef _AUDIO
#ifdef AUDIO
float VAD_treshold; /* 40 is usually recommended value */
#endif
} Device;
@@ -76,12 +77,12 @@ typedef struct _Device {
const char *ddevice_names[2]; /* Default device */
const char *devices_names[2][MAX_DEVICES]; /* Container of available devices */
static int size[2]; /* Size of above containers */
Device *running[2][MAX_DEVICES]; /* Running devices */
Device *running[2][MAX_DEVICES] = {{NULL}}; /* Running devices */
uint32_t primary_device[2]; /* Primary device */
#ifdef _AUDIO
#ifdef AUDIO
static ToxAv* av = NULL;
#endif /* _AUDIO */
#endif /* AUDIO */
/* q_mutex */
#define lock pthread_mutex_lock(&mutex)
@@ -89,21 +90,19 @@ static ToxAv* av = NULL;
pthread_mutex_t mutex;
_Bool thread_running = _True,
thread_paused = _True; /* Thread control */
bool thread_running = true,
thread_paused = true; /* Thread control */
void* thread_poll(void*);
/* Meet devices */
#ifdef _AUDIO
#ifdef AUDIO
DeviceError init_devices(ToxAv* av_)
#else
DeviceError init_devices()
#endif /* _AUDIO */
#endif /* AUDIO */
{
const char *stringed_device_list;
size[input] = 0;
if ( (stringed_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER)) ) {
ddevice_names[input] = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
@@ -114,8 +113,6 @@ DeviceError init_devices()
}
}
size[output] = 0;
if ( (stringed_device_list = alcGetString(NULL, ALC_DEVICE_SPECIFIER)) ) {
ddevice_names[output] = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
@@ -127,16 +124,16 @@ DeviceError init_devices()
}
// Start poll thread
pthread_mutex_init(&mutex, NULL);
if (pthread_mutex_init(&mutex, NULL) != 0)
return de_InternalError;
pthread_t thread_id;
if ( pthread_create(&thread_id, NULL, thread_poll, NULL) != 0 || pthread_detach(thread_id) != 0)
return de_InternalError;
#ifdef _AUDIO
#ifdef AUDIO
av = av_;
#endif /* _AUDIO */
#endif /* AUDIO */
return (DeviceError) de_None;
}
@@ -147,7 +144,8 @@ DeviceError terminate_devices()
thread_running = false;
usleep(20000);
pthread_mutex_destroy(&mutex);
if (pthread_mutex_destroy(&mutex) != 0)
return (DeviceError) de_InternalError;
return (DeviceError) de_None;
}
@@ -170,7 +168,7 @@ DeviceError device_mute(DeviceType type, uint32_t device_idx)
return de_None;
}
#ifdef _AUDIO
#ifdef AUDIO
DeviceError device_set_VAD_treshold(uint32_t device_idx, float value)
{
if (device_idx >= MAX_DEVICES) return de_InvalidSelection;
@@ -222,6 +220,18 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
if (i == MAX_DEVICES) { unlock; return de_AllDevicesBusy; }
else *device_idx = i;
for (i = 0; i < MAX_DEVICES; i ++) { /* Check if any device has the same selection */
if ( running[type][i] && running[type][i]->selection == selection ) {
// printf("a%d-%d:%p ", selection, i, running[type][i]->dhndl);
running[type][*device_idx] = running[type][i];
running[type][i]->ref_count ++;
unlock;
return de_None;
}
}
Device* device = running[type][*device_idx] = calloc(1, sizeof(Device));
device->selection = selection;
@@ -229,26 +239,17 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
device->frame_duration = frame_duration;
device->sound_mode = channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
for (i = 0; i < *device_idx; i ++) { /* Check if any previous has the same selection */
if ( running[type][i]->selection == selection ) {
device->dhndl = running[type][i]->dhndl;
if (type == output) {
device->ctx = running[type][i]->ctx;
memcpy(device->buffers, running[type][i]->buffers, sizeof(running[type][i]->buffers));
device->source = running[type][i]->source;
}
device->ref_count++;
pthread_mutex_init(device->mutex, NULL);
if (pthread_mutex_init(device->mutex, NULL) != 0) {
free(device);
unlock;
return de_None;
}
return de_InternalError;
}
if (type == input) {
device->dhndl = alcCaptureOpenDevice(devices_names[type][selection],
sample_rate, device->sound_mode, frame_size * 2);
#ifdef _AUDIO
device->VAD_treshold = user_settings_->VAD_treshold;
#ifdef AUDIO
device->VAD_treshold = user_settings->VAD_treshold;
#endif
}
else {
@@ -287,10 +288,9 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
if (type == input) {
alcCaptureStart(device->dhndl);
thread_paused = _False;
thread_paused = false;
}
pthread_mutex_init(device->mutex, NULL);
unlock;
return de_None;
}
@@ -301,17 +301,18 @@ DeviceError close_device(DeviceType type, uint32_t device_idx)
lock;
Device* device = running[type][device_idx];
DeviceError rc = de_None;
if (!device) {
unlock;
return de_DeviceNotActive;
}
if ( !(device->ref_count--) ) {
running[type][device_idx] = NULL;
unlock;
DeviceError rc = de_None;
if ( !device->ref_count ) {
// printf("Closed device ");
if (type == input) {
if ( !alcCaptureCloseDevice(device->dhndl) ) rc = de_AlError;
@@ -328,15 +329,14 @@ DeviceError close_device(DeviceType type, uint32_t device_idx)
}
free(device);
}
else device->ref_count--;
unlock;
return rc;
}
unlock;
return de_None;
}
DeviceError register_device_callback( int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, _Bool enable_VAD)
DeviceError register_device_callback( int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, bool enable_VAD)
{
if (size[input] <= device_idx || !running[input][device_idx] || running[input][device_idx]->dhndl == NULL)
return de_InvalidSelection;
@@ -427,9 +427,9 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
alcCaptureSamples(device->dhndl, frame, f_size);
if ( device->muted
#ifdef _AUDIO
#ifdef AUDIO
|| (device->enable_VAD && !toxav_has_activity(av, device->call_idx, frame, f_size, device->VAD_treshold))
#endif /* _AUDIO */
#endif /* AUDIO */
)
{ unlock; continue; } /* Skip if no voice activity */

View File

@@ -26,16 +26,13 @@
* Read from running input device(s) via select()/callback combo.
*/
#ifndef _device_h
#define _device_h
#ifndef DEVICE_H
#define DEVICE_H
#define MAX_DEVICES 32
#include <inttypes.h>
#include "windows.h"
#define _True 1
#define _False 0
typedef enum DeviceType {
input,
output,
@@ -57,22 +54,22 @@ typedef enum DeviceError {
typedef void (*DataHandleCallback) (const int16_t*, uint32_t size, void* data);
#ifdef _AUDIO
#ifdef AUDIO
DeviceError init_devices(ToxAv* av);
#else
DeviceError init_devices();
#endif /* _AUDIO */
#endif /* AUDIO */
DeviceError terminate_devices();
/* Callback handles ready data from INPUT device */
DeviceError register_device_callback(int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, _Bool enable_VAD);
DeviceError register_device_callback(int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, bool enable_VAD);
void* get_device_callback_data(uint32_t device_idx);
/* toggle device mute */
DeviceError device_mute(DeviceType type, uint32_t device_idx);
#ifdef _AUDIO
#ifdef AUDIO
DeviceError device_set_VAD_treshold(uint32_t device_idx, float value);
#endif
@@ -89,4 +86,4 @@ DeviceError write_out(uint32_t device_idx, int16_t* data, uint32_t lenght, uint8
void print_devices(ToxWindow* self, DeviceType type);
DeviceError selection_valid(DeviceType type, int32_t selection);
#endif /* _device_h */
#endif /* DEVICE_H */

View File

@@ -46,7 +46,7 @@
#define MAX_DNS_REQST_SIZE 255
#define TOX_DNS3_TXT_PREFIX "v=tox3;id="
extern struct _Winthread Winthread;
extern struct Winthread Winthread;
extern struct _dns3_servers dns3_servers;
extern struct arg_opts arg_opts;

View File

@@ -23,10 +23,10 @@
/* Does DNS lookup for addr and puts resulting tox id in id_bin.
Return 0 on success, -1 on failure. */
#ifndef _dns_h
#define _dns_h
#ifndef DNS_H
#define DNS_H
/* creates new thread for dns3 lookup. Only allows one lookup at a time. */
void dns3_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *msg);
#endif /* #define _dns_h */
#endif /* #define DNS_H */

View File

@@ -41,6 +41,7 @@ struct cmd_func {
static struct cmd_func global_commands[] = {
{ "/accept", cmd_accept },
{ "/add", cmd_add },
{ "/avatar", cmd_avatar },
{ "/clear", cmd_clear },
{ "/connect", cmd_connect },
{ "/decline", cmd_decline },
@@ -55,11 +56,11 @@ static struct cmd_func global_commands[] = {
{ "/quit", cmd_quit },
{ "/requests", cmd_requests },
{ "/status", cmd_status },
#ifdef _AUDIO
#ifdef AUDIO
{ "/lsdev", cmd_list_devices },
{ "/sdev", cmd_change_device },
#endif /* _AUDIO */
#endif /* AUDIO */
{ NULL, NULL },
};
static struct cmd_func chat_commands[] = {
@@ -68,8 +69,7 @@ static struct cmd_func chat_commands[] = {
{ "/join", cmd_join_group },
{ "/savefile", cmd_savefile },
{ "/sendfile", cmd_sendfile },
#ifdef _AUDIO
#ifdef AUDIO
{ "/call", cmd_call },
{ "/answer", cmd_answer },
{ "/reject", cmd_reject },
@@ -77,7 +77,8 @@ static struct cmd_func chat_commands[] = {
{ "/sdev", cmd_ccur_device },
{ "/mute", cmd_mute },
{ "/sense", cmd_sense },
#endif /* _AUDIO */
#endif /* AUDIO */
{ NULL, NULL },
};
/* Parses input command and puts args into arg array.
@@ -101,7 +102,7 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
i = char_find(1, cmd, '\"');
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);
free(cmd);
return -1;
@@ -118,7 +119,7 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
char tmp[MAX_STR_SIZE];
snprintf(tmp, sizeof(tmp), "%s", &cmd[i + 1]);
strcpy(cmd, tmp);
strcpy(cmd, tmp); /* tmp will always fit inside cmd */
}
free(cmd);
@@ -126,12 +127,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 */
static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, int num_cmds,
struct cmd_func *commands, char (*args)[MAX_STR_SIZE])
static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct cmd_func *commands,
char (*args)[MAX_STR_SIZE])
{
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) {
(commands[i].func)(w, self, m, num_args - 1, args);
return 0;
@@ -158,7 +159,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 */
switch (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;
break;
@@ -167,7 +168,7 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
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;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid command.");

View File

@@ -20,22 +20,14 @@
*
*/
#ifndef _execute_h
#define _execute_h
#ifndef EXECUTE_H
#define EXECUTE_H
#include "toxic.h"
#include "windows.h"
#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 {
GLOBAL_COMMAND_MODE,
CHAT_COMMAND_MODE,
@@ -44,4 +36,4 @@ enum {
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode);
#endif /* #define _execute_h */
#endif /* #define EXECUTE_H */

View File

@@ -36,7 +36,7 @@
FileSender file_senders[MAX_FILES];
uint8_t max_file_senders_index;
uint8_t num_active_file_senders;
extern _Friends Friends;
extern FriendsList Friends;
/* creates initial progress line that will be updated during file transfer.
Assumes progline is of size MAX_STR_SIZE */
@@ -276,6 +276,7 @@ void do_file_senders(Tox *m)
box_notify2(self, error, NT_NOFOCUS | NT_WNDALERT_2, self->active_box, "%s", msg);
else
box_notify(self, error, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", msg);
continue;
}

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _filesenders_h
#define _filesenders_h
#ifndef FILESENDERS_H
#define FILESENDERS_H
#include "toxic.h"
#include "windows.h"
@@ -72,4 +72,4 @@ void reset_file_sender_queue(void);
void close_all_file_senders(Tox *m);
void do_file_senders(Tox *m);
#endif /* #define _filesenders_h */
#endif /* #define FILESENDERS_H */

View File

@@ -37,8 +37,9 @@
#include "settings.h"
#include "notify.h"
#include "help.h"
#include "log.h"
#ifdef _AUDIO
#ifdef AUDIO
#include "audio_call.h"
#endif
@@ -46,15 +47,15 @@
extern char *DATA_FILE;
extern char *BLOCK_FILE;
extern ToxWindow *prompt;
extern struct _Winthread Winthread;
extern struct user_settings *user_settings_;
extern struct Winthread Winthread;
extern struct user_settings *user_settings;
extern struct arg_opts arg_opts;
static uint8_t blocklist_view = 0; /* 0 if we're in friendlist view, 1 if we're in blocklist view */
_Friends Friends;
FriendsList Friends;
static struct _Blocked {
static struct Blocked {
int num_selected;
int max_idx;
int num_blocked;
@@ -63,7 +64,7 @@ static struct _Blocked {
BlockedFriend *list;
} Blocked;
static struct _pendingDel {
static struct pendingDel {
int num;
bool active;
WINDOW *popup;
@@ -111,6 +112,13 @@ static void realloc_blocklist(int n)
void kill_friendlist(void)
{
int i;
for (i = 0; i < Friends.max_idx; ++i) {
if (Friends.list[i].active && Friends.list[i].group_invite.key != NULL)
free(Friends.list[i].group_invite.key);
}
realloc_blocklist(0);
realloc_friends(0);
}
@@ -130,11 +138,12 @@ static int save_blocklist(char *path)
exit_toxic_err("Failed in save_blocklist", FATALERR_MEMORY);
int i;
int ret = -1;
int count = 0;
for (i = 0; i < Blocked.max_idx; ++i) {
if (count > Blocked.num_blocked)
return -1;
goto on_error;
if (Blocked.list[i].active) {
BlockedFriend tmp;
@@ -155,17 +164,16 @@ static int save_blocklist(char *path)
FILE *fp = fopen(path, "wb");
if (fp == NULL) {
free(data);
return -1;
}
if (fp == NULL)
goto on_error;
int ret = 0;
if (fwrite(data, len, 1, fp) != 1)
ret = -1;
if (fwrite(data, len, 1, fp) == 1)
ret = 0;
fclose(fp);
return ret;
on_error:
free(data);
return ret;
}
@@ -182,9 +190,12 @@ int load_blocklist(char *path)
if (fp == NULL)
return -1;
fseek(fp, 0, SEEK_END);
int len = ftell(fp);
fseek(fp, 0, SEEK_SET);
off_t len = file_size(path);
if (len == -1) {
fclose(fp);
return -1;
}
char *data = malloc(len);
@@ -287,7 +298,7 @@ static void update_friend_last_online(int32_t num, uint64_t timestamp)
Friends.list[num].last_online.tm = *localtime((const time_t*)&timestamp);
/* if the format changes make sure TIME_STR_SIZE is the correct size */
const char *t = user_settings_->time == TIME_12 ? "%I:%M %p" : "%H:%M";
const char *t = user_settings->time == TIME_12 ? "%I:%M %p" : "%H:%M";
strftime(Friends.list[num].last_online.hour_min_str, TIME_STR_SIZE, t,
&Friends.list[num].last_online.tm);
}
@@ -332,12 +343,27 @@ static void friendlist_onNickChange(ToxWindow *self, Tox *m, int32_t num, const
if (len > TOX_MAX_NAME_LENGTH || num >= Friends.max_idx)
return;
/* save old name for log renaming */
char oldname[TOXIC_MAX_NAME_LENGTH];
snprintf(oldname, sizeof(oldname), "%s", Friends.list[num].name);
/* update name */
char tempname[TOX_MAX_NAME_LENGTH];
strcpy(tempname, nick);
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
tempname[len] = '\0';
snprintf(Friends.list[num].name, sizeof(Friends.list[num].name), "%s", tempname);
Friends.list[num].namelength = len;
/* get data for chatlog renaming */
char newnamecpy[TOXIC_MAX_NAME_LENGTH];
char myid[TOX_FRIEND_ADDRESS_SIZE];
strcpy(newnamecpy, tempname);
tox_get_address(m, (uint8_t *) myid);
if (strcmp(oldname, newnamecpy) != 0)
rename_logfile(oldname, newnamecpy, myid, Friends.list[num].pub_key, Friends.list[num].chatwin);
sort_friendlist_index();
}
@@ -379,7 +405,7 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort)
Friends.list[i].chatwin = -1;
Friends.list[i].online = false;
Friends.list[i].status = TOX_USERSTATUS_NONE;
Friends.list[i].logging_on = (bool) user_settings_->autolog == AUTOLOG_ON;
Friends.list[i].logging_on = (bool) user_settings->autolog == AUTOLOG_ON;
tox_get_client_id(m, num, (uint8_t *) Friends.list[i].pub_key);
update_friend_last_online(i, tox_get_last_online(m, i));
@@ -421,7 +447,7 @@ static void friendlist_add_blocked(Tox *m, int32_t fnum, int32_t bnum)
Friends.list[i].active = true;
Friends.list[i].chatwin = -1;
Friends.list[i].status = TOX_USERSTATUS_NONE;
Friends.list[i].logging_on = (bool) user_settings_->autolog == AUTOLOG_ON;
Friends.list[i].logging_on = (bool) user_settings->autolog == AUTOLOG_ON;
Friends.list[i].namelength = Blocked.list[bnum].namelength;
update_friend_last_online(i, Blocked.list[bnum].last_on);
memcpy(Friends.list[i].name, Blocked.list[bnum].name, Friends.list[i].namelength + 1);
@@ -460,7 +486,7 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u
}
}
static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const char *group_pub_key)
static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const char *group_pub_key, uint16_t length)
{
if (num >= Friends.max_idx)
return;
@@ -503,6 +529,9 @@ static void delete_friend(Tox *m, int32_t f_num)
}
}
if (Friends.list[f_num].group_invite.key != NULL)
free(Friends.list[f_num].group_invite.key);
tox_del_friend(m, f_num);
memset(&Friends.list[f_num], 0, sizeof(ToxicFriend));
@@ -996,12 +1025,11 @@ void disable_chatwin(int32_t f_num)
Friends.list[f_num].chatwin = -1;
}
#ifdef _AUDIO
#ifdef AUDIO
static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index)
{
int id = toxav_get_peer_id(av, call_index, 0);
/*id++;*/
if ( id != ErrorInternal && id >= Friends.max_idx)
return;
@@ -1024,7 +1052,7 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index)
}
}
}
#endif /* _AUDIO */
#endif /* AUDIO */
ToxWindow new_friendlist(void)
{
@@ -1046,7 +1074,7 @@ ToxWindow new_friendlist(void)
ret.onFileSendRequest = &friendlist_onFileSendRequest;
ret.onGroupInvite = &friendlist_onGroupInvite;
#ifdef _AUDIO
#ifdef AUDIO
ret.onInvite = &friendlist_onAv;
ret.onRinging = &friendlist_onAv;
ret.onStarting = &friendlist_onAv;
@@ -1061,7 +1089,7 @@ ToxWindow new_friendlist(void)
ret.call_idx = -1;
ret.device_selection[0] = ret.device_selection[1] = -1;
#endif /* _AUDIO */
#endif /* AUDIO */
ret.active_box = -1;

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef FRIENDLIST_H_53I41IM
#define FRIENDLIST_H_53I41IM
#ifndef FRIENDLIST_H
#define FRIENDLIST_H
#include <time.h>
@@ -48,13 +48,17 @@ struct LastOnline {
char hour_min_str[TIME_STR_SIZE]; /* holds 12/24-hour time string e.g. "10:43 PM" */
};
struct GroupChatInvite {
char *key;
uint16_t length;
bool pending;
};
typedef struct {
char name[TOXIC_MAX_NAME_LENGTH];
int namelength;
char statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH];
uint16_t statusmsg_len;
char groupchat_key[TOX_CLIENT_ID_SIZE];
bool groupchat_pending;
char pub_key[TOX_CLIENT_ID_SIZE];
int32_t num;
int chatwin;
@@ -65,6 +69,7 @@ typedef struct {
uint8_t status;
struct LastOnline last_online;
struct FileReceiver file_receiver[MAX_FILES];
struct GroupChatInvite group_invite;
uint8_t active_file_receivers;
} ToxicFriend;
@@ -83,7 +88,7 @@ typedef struct {
int num_friends;
int *index;
ToxicFriend *list;
} _Friends;
} FriendsList;
ToxWindow new_friendlist(void);
void disable_chatwin(int32_t f_num);
@@ -95,4 +100,4 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort);
/* sorts friendlist_index first by connection status then alphabetically */
void sort_friendlist_index(void);
#endif /* end of include guard: FRIENDLIST_H_53I41IM */
#endif /* end of include guard: FRIENDLIST_H */

View File

@@ -37,8 +37,8 @@
extern char *DATA_FILE;
extern ToxWindow *prompt;
extern _Friends Friends;
extern _FriendRequests FriendRequests;
extern FriendsList Friends;
extern FriendRequests FrndRequests;
/* command functions */
void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@@ -55,13 +55,13 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
return;
}
if (!FriendRequests.request[req].active) {
if (!FrndRequests.request[req].active) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
return;
}
const char *msg;
int32_t friendnum = tox_add_friend_norequest(m, FriendRequests.request[req].key);
int32_t friendnum = tox_add_friend_norequest(m, FrndRequests.request[req].key);
if (friendnum == -1)
msg = "Failed to add friend.";
@@ -70,17 +70,17 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
on_friendadded(m, friendnum, true);
}
memset(&FriendRequests.request[req], 0, sizeof(struct _friend_request));
memset(&FrndRequests.request[req], 0, sizeof(struct friend_request));
int i;
for (i = FriendRequests.max_idx; i > 0; --i) {
if (FriendRequests.request[i - 1].active)
for (i = FrndRequests.max_idx; i > 0; --i) {
if (FrndRequests.request[i - 1].active)
break;
}
FriendRequests.max_idx = i;
--FriendRequests.num_requests;
FrndRequests.max_idx = i;
--FrndRequests.num_requests;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", msg);
}
@@ -184,6 +184,81 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
}
}
void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
if (argc < 2) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: No file path supplied.");
return;
}
/* turns the avatar off */
if (strlen(argv[1]) < 3) {
tox_unset_avatar(m);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No avatar set.");
return;
}
if (argv[1][0] != '\"') {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Path must be enclosed in quotes.");
return;
}
/* remove opening and closing quotes */
char path[MAX_STR_SIZE];
snprintf(path, sizeof(path), "%s", &argv[1][1]);
int len = strlen(path) - 1;
path[len] = '\0';
off_t sz = file_size(path);
if (sz <= 8) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Invalid file.");
return;
}
if (sz > TOX_AVATAR_MAX_DATA_LENGTH) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File is too large.");
return;
}
FILE *fp = fopen(path, "rb");
if (fp == NULL) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Could not open file.");
return;
}
char PNG_signature[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
if (check_file_signature(PNG_signature, sizeof(PNG_signature), fp) != 0) {
fclose(fp);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: File type not supported.");
return;
}
char *avatar = malloc(sz);
if (avatar == NULL)
exit_toxic_err("Failed in set_avatar", FATALERR_MEMORY);
if (fread(avatar, sz, 1, fp) != 1) {
fclose(fp);
free(avatar);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Read fail.");
return;
}
if (tox_set_avatar(m, TOX_AVATAR_FORMAT_PNG, (const uint8_t *) avatar, (uint32_t) sz) == -1)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set avatar: Core error.");
char filename[MAX_STR_SIZE];
get_file_name(filename, sizeof(filename), path);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Avatar set to '%s'", filename);
fclose(fp);
free(avatar);
}
void cmd_clear(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
line_info_clear(self->chatwin->hst);
@@ -227,22 +302,22 @@ void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
return;
}
if (!FriendRequests.request[req].active) {
if (!FrndRequests.request[req].active) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
return;
}
memset(&FriendRequests.request[req], 0, sizeof(struct _friend_request));
memset(&FrndRequests.request[req], 0, sizeof(struct friend_request));
int i;
for (i = FriendRequests.max_idx; i > 0; --i) {
if (FriendRequests.request[i - 1].active)
for (i = FrndRequests.max_idx; i > 0; --i) {
if (FrndRequests.request[i - 1].active)
break;
}
FriendRequests.max_idx = i;
--FriendRequests.num_requests;
FrndRequests.max_idx = i;
--FrndRequests.num_requests;
}
void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@@ -286,16 +361,16 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
const char *swch = argv[1];
if (!strcmp(swch, "1") || !strcmp(swch, "on")) {
char myid[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid);
if (self->is_chat) {
Friends.list[self->num].logging_on = true;
log_enable(self->name, Friends.list[self->num].pub_key, log);
log_enable(self->name, myid, Friends.list[self->num].pub_key, log, LOG_CHAT);
} else if (self->is_prompt) {
char myid[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid);
log_enable(self->name, myid, log);
log_enable(self->name, myid, NULL, log, LOG_PROMPT);
} else if (self->is_groupchat) {
log_enable(self->name, NULL, log);
log_enable(self->name, myid, NULL, log, LOG_GROUP);
}
msg = "Logging enabled";
@@ -399,7 +474,7 @@ void cmd_quit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
void cmd_requests(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
if (FriendRequests.num_requests == 0) {
if (FrndRequests.num_requests == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend requests.");
return;
}
@@ -407,22 +482,22 @@ void cmd_requests(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
int i, j;
int count = 0;
for (i = 0; i < FriendRequests.max_idx; ++i) {
if (!FriendRequests.request[i].active)
for (i = 0; i < FrndRequests.max_idx; ++i) {
if (!FrndRequests.request[i].active)
continue;
char id[TOX_CLIENT_ID_SIZE * 2 + 1] = {0};
for (j = 0; j < TOX_CLIENT_ID_SIZE; ++j) {
char d[3];
snprintf(d, sizeof(d), "%02X", FriendRequests.request[i].key[j] & 0xff);
snprintf(d, sizeof(d), "%02X", FrndRequests.request[i].key[j] & 0xff);
strcat(id, d);
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%d : %s", i, id);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", FriendRequests.request[i].msg);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", FrndRequests.request[i].msg);
if (++count < FriendRequests.num_requests)
if (++count < FrndRequests.num_requests)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
}
}

View File

@@ -20,14 +20,15 @@
*
*/
#ifndef _global_commands_h
#define _global_commands_h
#ifndef GLOBAL_COMMANDS_H
#define GLOBAL_COMMANDS_H
#include "windows.h"
#include "toxic.h"
void cmd_accept(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_add(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_clear(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_connect(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
@@ -43,9 +44,9 @@ void cmd_status(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZ
void cmd_add_helper(ToxWindow *self, Tox *m, char *id_bin, char *msg);
#ifdef _AUDIO
#ifdef AUDIO
void cmd_list_devices(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_change_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
#endif /* _AUDIO */
#endif /* AUDIO */
#endif /* #define _global_commands_h */
#endif /* #define GLOBAL_COMMANDS_H */

View File

@@ -50,7 +50,7 @@ extern char *DATA_FILE;
static GroupChat groupchats[MAX_GROUPCHAT_NUM];
static int max_groupchat_index = 0;
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
/* temporary until group chats have unique commands */
extern const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE];
@@ -67,11 +67,16 @@ int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum)
groupchats[i].chatwin = add_window(m, new_group_chat(m, groupnum));
groupchats[i].active = true;
groupchats[i].num_peers = 0;
groupchats[i].peer_names = malloc(sizeof(uint8_t) * TOX_MAX_NAME_LENGTH);
groupchats[i].oldpeer_names = malloc(sizeof(uint8_t) * TOX_MAX_NAME_LENGTH);
groupchats[i].peer_name_lengths = malloc(sizeof(uint16_t));
groupchats[i].oldpeer_name_lengths = malloc(sizeof(uint16_t));
if (groupchats[i].peer_names == NULL || groupchats[i].oldpeer_names == NULL
|| groupchats[i].peer_name_lengths == NULL || groupchats[i].oldpeer_name_lengths == NULL)
exit_toxic_err("failed in init_groupchat_win", FATALERR_MEMORY);
memcpy(&groupchats[i].oldpeer_names[0], UNKNOWN_NAME, sizeof(UNKNOWN_NAME));
groupchats[i].oldpeer_name_lengths[0] = (uint16_t) strlen(UNKNOWN_NAME);
@@ -97,7 +102,6 @@ void kill_groupchat_window(ToxWindow *self)
delwin(ctx->history);
delwin(ctx->sidebar);
free(ctx->log);
free(ctx->hst);
free(ctx);
free(self->help);
del_window(self);
@@ -198,7 +202,7 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p
char timefrmt[TIME_STR_SIZE];
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);
}
@@ -303,7 +307,7 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
case TOX_CHAT_CHANGE_PEER_DEL:
event = "has left the room";
line_info_add(self, timefrmt, (char *) oldpeername, NULL, CONNECTION, 0, 0, event);
line_info_add(self, timefrmt, (char *) oldpeername, NULL, CONNECTION, 0, RED, event);
if (groupchats[self->num].side_pos > 0)
--groupchats[self->num].side_pos;
@@ -368,11 +372,15 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (ctx->len > 0) {
int diff;
if ((ctx->line[0] != '/') || (ctx->line[1] == 'm' && ctx->line[2] == 'e'))
diff = complete_line(self, groupchats[self->num].peer_names,
groupchats[self->num].num_peers, TOX_MAX_NAME_LENGTH);
else
/* TODO: make this not suck */
if (ctx->line[0] != L'/' || wcscmp(ctx->line, L"/me") == 0) {
diff = complete_line(self, groupchats[self->num].peer_names, groupchats[self->num].num_peers,
TOX_MAX_NAME_LENGTH);
} else if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) {
diff = dir_match(self, m, ctx->line, L"/avatar");
} else {
diff = complete_line(self, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
}
if (diff != -1) {
if (x + diff > x2 - 1) {
@@ -385,12 +393,12 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
} else {
sound_notify(self, error, 0, NULL);
}
} else if (key == user_settings_->key_peer_list_down) { /* Scroll peerlist up and down one position */
} else if (key == user_settings->key_peer_list_down) { /* Scroll peerlist up and down one position */
int L = y2 - CHATBOX_HEIGHT - SDBAR_OFST;
if (groupchats[self->num].side_pos < groupchats[self->num].num_peers - L)
++groupchats[self->num].side_pos;
} else if (key == user_settings_->key_peer_list_up) {
} else if (key == user_settings->key_peer_list_up) {
if (groupchats[self->num].side_pos > 0)
--groupchats[self->num].side_pos;
} else if (key == '\n') {
@@ -504,8 +512,11 @@ static void groupchat_onInit(ToxWindow *self, Tox *m)
line_info_init(ctx->hst);
if (user_settings_->autolog == AUTOLOG_ON)
log_enable(self->name, NULL, ctx->log);
if (user_settings->autolog == AUTOLOG_ON) {
char myid[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid);
log_enable(self->name, myid, NULL, ctx->log, LOG_GROUP);
}
execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _groupchat_h
#define _groupchat_h
#ifndef GROUPCHAT_H
#define GROUPCHAT_H
#include "toxic.h"
#include "windows.h"
@@ -45,4 +45,4 @@ void kill_groupchat_window(ToxWindow *self);
int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum);
ToxWindow new_group_chat(Tox *m, int groupnum);
#endif /* #define _groupchat_h */
#endif /* #define GROUPCHAT_H */

View File

@@ -138,6 +138,7 @@ static void help_draw_global(ToxWindow *self)
wprintw(win, " /add <addr> <msg> : Add contact with optional message\n");
wprintw(win, " /accept <id> : Accept friend request\n");
wprintw(win, " /avatar <path> : Set a personal avatar\n");
wprintw(win, " /decline <id> : Decline friend request\n");
wprintw(win, " /requests : List pending friend requests\n");
wprintw(win, " /connect <ip> <port> <key> : Manually connect to a DHT node\n");
@@ -151,14 +152,14 @@ static void help_draw_global(ToxWindow *self)
wprintw(win, " /close : Close the current chat window\n");
wprintw(win, " /quit or /exit : Exit Toxic\n");
#ifdef _AUDIO
#ifdef AUDIO
wattron(win, A_BOLD);
wprintw(win, "\n Audio:\n");
wattroff(win, A_BOLD);
wprintw(win, " /lsdev <type> : List devices where type: in|out\n");
wprintw(win, " /sdev <type> <id> : Set active device\n");
#endif /* _AUDIO */
#endif /* AUDIO */
help_draw_bottom_menu(win);
@@ -182,7 +183,7 @@ static void help_draw_chat(ToxWindow *self)
wprintw(win, " /savefile <id> : Receive a file\n");
wprintw(win, " /cancel <type> <id> : Cancel file transfer where type: in|out\n");
#ifdef _AUDIO
#ifdef AUDIO
wattron(win, A_BOLD);
wprintw(win, "\n Audio:\n");
wattroff(win, A_BOLD);
@@ -194,7 +195,7 @@ static void help_draw_chat(ToxWindow *self)
wprintw(win, " /sdev <type> <id> : Change active device\n");
wprintw(win, " /mute <type> : Mute active device if in call\n");
wprintw(win, " /sense <n> : VAD sensitivity treshold\n");
#endif /* _AUDIO */
#endif /* AUDIO */
help_draw_bottom_menu(win);
@@ -256,7 +257,7 @@ void help_onKey(ToxWindow *self, wint_t key)
break;
case 'c':
#ifdef _AUDIO
#ifdef AUDIO
help_init_window(self, 19, 80);
#else
help_init_window(self, 9, 80);
@@ -265,10 +266,10 @@ void help_onKey(ToxWindow *self, wint_t key)
break;
case 'g':
#ifdef _AUDIO
help_init_window(self, 23, 80);
#ifdef AUDIO
help_init_window(self, 24, 80);
#else
help_init_window(self, 19, 80);
help_init_window(self, 20, 80);
#endif
self->help->type = HELP_GLOBAL;
break;

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _help_h
#define _help_h
#ifndef HELP_H
#define HELP_H
#include "toxic.h"
#include "windows.h"
@@ -39,4 +39,4 @@ void help_onDraw(ToxWindow *self);
void help_init_menu(ToxWindow *self);
void help_onKey(ToxWindow *self, wint_t key);
#endif /* #define _help_h */
#endif /* #define HELP_H */

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _input_h
#define _input_h
#ifndef INPUT_H
#define INPUT_H
/* add a char to input field and buffer for given chatcontext */
void input_new_char(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y);
@@ -30,4 +30,4 @@ void input_new_char(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_
return true if key matches a function, false otherwise */
bool input_handle(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y);
#endif /* #define _input_h */
#endif /* #define INPUT_H */

View File

@@ -31,8 +31,10 @@
#include "groupchat.h"
#include "settings.h"
#include "notify.h"
#include "message_queue.h"
#include "misc_tools.h"
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
void line_info_init(struct history *hst)
{
@@ -46,8 +48,8 @@ void line_info_init(struct history *hst)
hst->queue_sz = 0;
}
/* resets line_start (page end) */
static void line_info_reset_start(ToxWindow *self, struct history *hst)
/* resets line_start (moves to end of chat history) */
void line_info_reset_start(ToxWindow *self, struct history *hst)
{
struct line_info *line = hst->line_end;
@@ -89,6 +91,8 @@ void line_info_cleanup(struct history *hst)
if (hst->queue[i])
free(hst->queue[i]);
}
free(hst);
}
/* moves root forward and frees previous root */
@@ -107,22 +111,13 @@ static void line_info_root_fwd(struct history *hst)
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. Returns NULL if queue is empty. */
static struct line_info *line_info_ret_queue(struct history *hst)
{
if (hst->queue_sz <= 0)
return NULL;
struct line_info *ret = hst->queue[0];
struct line_info *line = hst->queue[0];
int i;
@@ -131,21 +126,24 @@ static struct line_info *line_info_ret_queue(struct history *hst)
--hst->queue_sz;
return ret;
return line;
}
/* 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 *tmstmp, char *name1, char *name2, uint8_t type, uint8_t bold,
/* creates new line_info line and puts it in the queue. */
void line_info_add(ToxWindow *self, char *timestr, char *name1, char *name2, uint8_t type, uint8_t bold,
uint8_t colour, const char *msg, ...)
{
struct history *hst = self->chatwin->hst;
if (hst->queue_sz >= MAX_LINE_INFO_QUEUE)
return;
struct line_info *new_line = calloc(1, sizeof(struct line_info));
if (new_line == NULL)
exit_toxic_err("failed in line_info_add", FATALERR_MEMORY);
char frmt_msg[MAX_STR_SIZE] = {0};
char frmt_msg[MAX_LINE_INFO_MSG_SIZE] = {0};
va_list args;
va_start(args, msg);
@@ -156,14 +154,27 @@ void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint
/* for type-specific formatting in print function */
switch (type) {
case ACTION:
case IN_ACTION:
case OUT_ACTION:
len += 5;
break;
case IN_MSG:
case OUT_MSG:
len += 6;
break;
case CONNECTION:
len += 3;
len += 5;
break;
case SYS_MSG:
break;
case NAME_CHANGE:
len += 4;
break;
case PROMPT:
++len;
break;
@@ -185,9 +196,9 @@ void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint
}
}
if (tmstmp) {
snprintf(new_line->timestamp, sizeof(new_line->timestamp), "%s", tmstmp);
len += strlen(new_line->timestamp);
if (timestr) {
snprintf(new_line->timestr, sizeof(new_line->timestr), "%s", timestr);
len += strlen(new_line->timestr);
}
if (name1) {
@@ -204,8 +215,10 @@ void line_info_add(ToxWindow *self, char *tmstmp, char *name1, char *name2, uint
new_line->type = type;
new_line->bold = bold;
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() */
@@ -217,7 +230,7 @@ static void line_info_check_queue(ToxWindow *self)
if (line == NULL)
return;
if (hst->start_id > user_settings_->history_size)
if (hst->start_id > user_settings->history_size)
line_info_root_fwd(hst);
line->id = hst->line_end->id + 1;
@@ -245,8 +258,14 @@ static void line_info_check_queue(ToxWindow *self)
++hst->start_id;
}
}
/* force move to bottom of history when we print an outgoing message */
if (line->type == OUT_MSG)
line_info_reset_start(self, hst);
}
#define NOREAD_FLAG_TIMEOUT 5 /* seconds before a sent message with no read receipt is flagged as unread */
void line_info_print(ToxWindow *self)
{
ChatContext *ctx = self->chatwin;
@@ -280,9 +299,10 @@ void line_info_print(ToxWindow *self)
switch (type) {
case OUT_MSG:
case OUT_MSG_READ:
case IN_MSG:
wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp);
wprintw(win, "%s", line->timestr);
wattroff(win, COLOR_PAIR(BLUE));
int nameclr = GREEN;
@@ -293,34 +313,60 @@ void line_info_print(ToxWindow *self)
nameclr = CYAN;
wattron(win, COLOR_PAIR(nameclr));
wprintw(win, "%s: ", line->name1);
wprintw(win, "--- %s: ", line->name1);
wattroff(win, COLOR_PAIR(nameclr));
if (line->msg[0] == '>')
wattron(win, COLOR_PAIR(GREEN));
wprintw(win, "%s\n", line->msg);
wprintw(win, "%s", line->msg);
if (line->msg[0] == '>')
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;
case ACTION:
case OUT_ACTION_READ:
case OUT_ACTION:
case IN_ACTION:
wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp);
wprintw(win, "%s", line->timestr);
wattroff(win, COLOR_PAIR(BLUE));
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));
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;
case SYS_MSG:
if (line->timestamp[0]) {
if (line->timestr[0]) {
wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp);
wprintw(win, "%s", line->timestr);
wattroff(win, COLOR_PAIR(BLUE));
}
@@ -353,13 +399,16 @@ void line_info_print(ToxWindow *self)
case CONNECTION:
wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp);
wprintw(win, "%s", line->timestr);
wattroff(win, COLOR_PAIR(BLUE));
wattron(win, COLOR_PAIR(line->colour));
wprintw(win, "%s ", line->colour == RED ? "<--" : "-->");
wattron(win, A_BOLD);
wprintw(win, "* %s ", line->name1);
wprintw(win, "%s ", line->name1);
wattroff(win, A_BOLD);
wprintw(win, "%s\n", line->msg);
wattroff(win, COLOR_PAIR(line->colour));
@@ -367,12 +416,13 @@ void line_info_print(ToxWindow *self)
case NAME_CHANGE:
wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp);
wprintw(win, "%s", line->timestr);
wattroff(win, COLOR_PAIR(BLUE));
wattron(win, COLOR_PAIR(MAGENTA));
wprintw(win, "-!- ");
wattron(win, A_BOLD);
wprintw(win, "* %s", line->name1);
wprintw(win, "%s", line->name1);
wattroff(win, A_BOLD);
wprintw(win, "%s", line->msg);
@@ -393,6 +443,7 @@ void line_info_print(ToxWindow *self)
line_info_print(self);
}
/* puts msg in specified line_info msg buffer */
void line_info_set(ToxWindow *self, uint32_t id, char *msg)
{
struct line_info *line = self->chatwin->hst->line_end;
@@ -455,19 +506,19 @@ bool line_info_onKey(ToxWindow *self, wint_t key)
struct history *hst = self->chatwin->hst;
bool match = true;
if (key == user_settings_->key_half_page_up) {
if (key == user_settings->key_half_page_up) {
line_info_page_up(self, hst);
}
else if (key == user_settings_->key_half_page_down) {
else if (key == user_settings->key_half_page_down) {
line_info_page_down(self, hst);
}
else if (key == user_settings_->key_scroll_line_up) {
else if (key == user_settings->key_scroll_line_up) {
line_info_scroll_up(hst);
}
else if (key == user_settings_->key_scroll_line_down) {
else if (key == user_settings->key_scroll_line_down) {
line_info_scroll_down(hst);
}
else if (key == user_settings_->key_page_bottom) {
else if (key == user_settings->key_page_bottom) {
line_info_reset_start(self, hst);
}
else {

View File

@@ -20,36 +20,42 @@
*
*/
#ifndef _line_info_h
#define _line_info_h
#ifndef LINE_INFO_H
#define LINE_INFO_H
#include "windows.h"
#include "toxic.h"
#define MAX_HISTORY 100000
#define MIN_HISTORY 40
#define MAX_QUEUE 128
#define MAX_LINE_INFO_QUEUE 1024
#define MAX_LINE_INFO_MSG_SIZE MAX_STR_SIZE + TOXIC_MAX_NAME_LENGTH + 32 /* needs extra room for log loading */
enum {
SYS_MSG,
IN_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,
ACTION,
CONNECTION,
NAME_CHANGE,
} LINE_TYPE;
struct line_info {
char timestamp[TIME_STR_SIZE];
char timestr[TIME_STR_SIZE];
char name1[TOXIC_MAX_NAME_LENGTH];
char name2[TOXIC_MAX_NAME_LENGTH];
char msg[TOX_MAX_MESSAGE_LENGTH];
char msg[MAX_LINE_INFO_MSG_SIZE];
uint64_t timestamp;
uint8_t type;
uint8_t bold;
uint8_t colour;
uint8_t noread_flag; /* true if a line should be flagged as unread */
uint32_t id;
uint16_t len; /* combined len of all strings */
uint16_t len; /* combined len of entire line */
uint8_t newlines;
struct line_info *prev;
@@ -63,13 +69,12 @@ struct history {
struct line_info *line_end;
uint32_t start_id; /* keeps track of where line_start should be when at bottom of history */
struct line_info *queue[MAX_QUEUE];
struct line_info *queue[MAX_LINE_INFO_QUEUE];
int queue_sz;
};
/* 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 *tmstmp, char *name1, char *name2, uint8_t type, uint8_t bold,
/* creates new line_info line and puts it in the queue. */
void line_info_add(ToxWindow *self, char *timestr, char *name1, char *name2, uint8_t type, uint8_t bold,
uint8_t colour, const char *msg, ...);
/* Prints a section of history starting at line_start */
@@ -84,7 +89,10 @@ void line_info_clear(struct history *hst);
/* puts msg in specified line_info msg buffer */
void line_info_set(ToxWindow *self, uint32_t id, char *msg);
/* resets line_start (moves to end of chat history) */
void line_info_reset_start(ToxWindow *self, struct history *hst);
void line_info_init(struct history *hst);
bool line_info_onKey(ToxWindow *self, wint_t key); /* returns true if key is a match */
#endif /* #define _line_info_h */
#endif /* #define LINE_INFO_H */

214
src/log.c
View File

@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include "configdir.h"
#include "toxic.h"
@@ -30,61 +31,91 @@
#include "misc_tools.h"
#include "log.h"
#include "settings.h"
#include "line_info.h"
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
/* Creates/fetches log file by appending to the config dir the name and a pseudo-unique identity */
void init_logging_session(char *name, const char *key, struct chatlog *log)
/* There are three types of logs: chat logs, groupchat logs, and prompt logs (see LOG_TYPE in log.h)
A prompt log is in the format: LOGDIR/selfkey-home.log
A chat log is in the format: LOGDIR/selfkey-friendname-otherkey.log
A groupchat log is in the format: LOGDIR/selfkey-groupname-date[time].log
Only the first (KEY_IDENT_DIGITS * 2) numbers of the key are used.
Returns 0 on success, -1 if the path is too long */
static int get_log_path(char *dest, int destsize, char *name, const char *selfkey, const char *otherkey, int logtype)
{
if (!log->log_on)
return;
if (!valid_nick(name))
name = UNKNOWN_NAME;
const char *set_path = user_settings_->chatlogs_path;
const char *namedash = logtype == LOG_PROMPT ? "" : "-";
const char *set_path = user_settings->chatlogs_path;
char *user_config_dir = get_user_config_dir();
int path_len = strlen(set_path) + strlen(name) ? *set_path
: strlen(user_config_dir) + strlen(LOGDIR) + strlen(name);
int path_len = strlen(name) + strlen(".log") + strlen("-") + strlen(namedash);
path_len += strlen(set_path) ? *set_path : strlen(user_config_dir) + strlen(LOGDIR);
/* use first 4 digits of key as log ident. If no key use a timestamp */
char ident[32];
/* first 6 digits of selfkey */
char self_id[32];
path_len += KEY_IDENT_DIGITS * 2;
sprintf(&self_id[0], "%02X", selfkey[0] & 0xff);
sprintf(&self_id[2], "%02X", selfkey[1] & 0xff);
sprintf(&self_id[4], "%02X", selfkey[2] & 0xff);
self_id[KEY_IDENT_DIGITS * 2] = '\0';
if (key != NULL) {
path_len += (KEY_IDENT_DIGITS * 2 + 5);
sprintf(&ident[0], "%02X", key[0] & 0xff);
sprintf(&ident[2], "%02X", key[1] & 0xff);
ident[KEY_IDENT_DIGITS * 2 + 1] = '\0';
} else {
strftime(ident, sizeof(ident), "%Y-%m-%d[%H:%M:%S]", get_time());
path_len += strlen(ident) + 1;
char other_id[32] = {0};
switch (logtype) {
case LOG_CHAT:
path_len += KEY_IDENT_DIGITS * 2;
sprintf(&other_id[0], "%02X", otherkey[0] & 0xff);
sprintf(&other_id[2], "%02X", otherkey[1] & 0xff);
sprintf(&other_id[4], "%02X", otherkey[2] & 0xff);
other_id[KEY_IDENT_DIGITS * 2] = '\0';
break;
case LOG_GROUP:
strftime(other_id, sizeof(other_id), "%Y-%m-%d[%H:%M:%S]", get_time());
path_len += strlen(other_id);
break;
}
if (path_len >= MAX_STR_SIZE) {
log->log_on = false;
if (path_len >= destsize) {
free(user_config_dir);
return;
return -1;
}
if (!string_is_empty(set_path))
snprintf(dest, destsize, "%s%s-%s%s%s.log", set_path, self_id, name, namedash, other_id);
else
snprintf(dest, destsize, "%s%s%s-%s%s%s.log", user_config_dir, LOGDIR, self_id, name, namedash, other_id);
free(user_config_dir);
return 0;
}
/* Opens log file or creates a new one */
static int init_logging_session(char *name, const char *selfkey, const char *otherkey, struct chatlog *log, int logtype)
{
if (selfkey == NULL || (logtype == LOG_CHAT && otherkey == NULL))
return -1;
char log_path[MAX_STR_SIZE];
if (*set_path)
snprintf(log_path, sizeof(log_path), "%s%s-%s.log", set_path, name, ident);
else
snprintf(log_path, sizeof(log_path), "%s%s%s-%s.log", user_config_dir, LOGDIR, name, ident);
if (get_log_path(log_path, sizeof(log_path), name, selfkey, otherkey, logtype) == -1)
return -1;
free(user_config_dir);
log->file = fopen(log_path, "a+");
snprintf(log->path, sizeof(log->path), "%s", log_path);
log->file = fopen(log_path, "a");
if (log->file == NULL)
return -1;
if (log->file == NULL) {
log->log_on = false;
return;
return 0;
}
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)
{
@@ -103,7 +134,7 @@ void write_to_log(const char *msg, const char *name, struct chatlog *log, bool e
else
snprintf(name_frmt, sizeof(name_frmt), "%s:", name);
const char *t = user_settings_->time == TIME_12 ? "%Y/%m/%d [%I:%M:%S %p]" : "%Y/%m/%d [%H:%M:%S]";
const char *t = user_settings->time == TIME_12 ? "%Y/%m/%d [%I:%M:%S %p]" : "%Y/%m/%d [%H:%M:%S]";
char s[MAX_STR_SIZE];
strftime(s, MAX_STR_SIZE, t, get_time());
fprintf(log->file, "%s %s %s\n", s, name_frmt, msg);
@@ -116,20 +147,119 @@ void write_to_log(const char *msg, const char *name, struct chatlog *log, bool e
}
}
void log_enable(char *name, const char *key, struct chatlog *log)
void log_disable(struct chatlog *log)
{
if (log->file != NULL)
fclose(log->file);
memset(log, 0, sizeof(struct chatlog));
}
void log_enable(char *name, const char *selfkey, const char *otherkey, struct chatlog *log, int logtype)
{
log->log_on = true;
if (log->file == NULL)
init_logging_session(name, key, log);
if (log->file != NULL)
return;
if (init_logging_session(name, selfkey, otherkey, log, logtype) == -1)
log_disable(log);
}
void log_disable(struct chatlog *log)
/* Loads previous history from chat log */
void load_chat_history(ToxWindow *self, struct chatlog *log)
{
log->log_on = false;
if (log->file == NULL)
return;
if (log->file != NULL) {
fclose(log->file);
log->file = NULL;
off_t sz = file_size(log->path);
if (sz <= 0)
return;
char *hstbuf = malloc(sz);
if (hstbuf == NULL)
exit_toxic_err("failed in load_chat_history", FATALERR_MEMORY);
if (fseek(log->file, 0L, SEEK_SET) == -1) {
free(hstbuf);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to read log file");
return;
}
if (fread(hstbuf, sz, 1, log->file) != 1) {
free(hstbuf);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to read log file");
return;
}
/* Number of history lines to load: must not be larger than MAX_LINE_INFO_QUEUE - 2 */
int L = MIN(MAX_LINE_INFO_QUEUE - 2, user_settings->history_size);
int start, count = 0;
/* start at end and backtrace L lines or to the beginning of buffer */
for (start = sz - 1; start >= 0 && count < L; --start) {
if (hstbuf[start] == '\n')
++count;
}
const char *line = strtok(&hstbuf[start + 1], "\n");
if (line == NULL) {
free(hstbuf);
return;
}
while (line != NULL && count--) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", line);
line = strtok(NULL, "\n");
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
free(hstbuf);
}
/* renames chatlog file replacing src with dest.
Returns 0 on success or if no log exists, -1 on failure. */
int rename_logfile(char *src, char *dest, const char *selfkey, const char *otherkey, int winnum)
{
ToxWindow *toxwin = get_window_ptr(winnum);
struct chatlog *log = NULL;
bool log_on = false;
/* disable log if necessary and save its state */
if (toxwin != NULL) {
log = toxwin->chatwin->log;
log_on = log->log_on;
}
if (log_on)
log_disable(log);
char newpath[MAX_STR_SIZE];
char oldpath[MAX_STR_SIZE];
if (get_log_path(oldpath, sizeof(oldpath), src, selfkey, otherkey, LOG_CHAT) == -1)
goto on_error;
if (!file_exists(oldpath))
return 0;
if (get_log_path(newpath, sizeof(newpath), dest, selfkey, otherkey, LOG_CHAT) == -1)
goto on_error;
if (rename(oldpath, newpath) != 0)
goto on_error;
if (log_on)
log_enable(dest, selfkey, otherkey, log, LOG_CHAT);
return 0;
on_error:
if (log_on)
log_enable(src, selfkey, otherkey, log, LOG_CHAT);
return -1;
}

View File

@@ -20,28 +20,36 @@
*
*/
#ifndef _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 */
#ifndef LOG_H
#define LOG_H
struct chatlog {
FILE *file;
uint64_t lastwrite;
int pos;
char path[MAX_STR_SIZE];
bool log_on; /* specific to current chat window */
};
/* Creates/fetches log file by appending to the config dir the name and a pseudo-unique identity */
void init_logging_session(char *name, const char *key, struct chatlog *log);
enum {
LOG_GROUP,
LOG_PROMPT,
LOG_CHAT,
} LOG_TYPE;
/* formats/writes line to log file */
void write_to_log(const char *msg, const char *name, struct chatlog *log, bool event);
/* enables logging for specified log and creates/fetches file if necessary */
void log_enable(char *name, const char *key, struct chatlog *log);
void log_enable(char *name, const char *selfkey, const char *otherkey, struct chatlog *log, int logtype);
/* disables logging for specified log and closes file */
void log_disable(struct chatlog *log);
#endif /* #define _log_h */
/* Loads previous history from chat log */
void load_chat_history(ToxWindow *self, struct chatlog *log);
/* renames chatlog file replacing src with dest.
Returns 0 on success or if no log exists, -1 on failure. */
int rename_logfile(char *src, char *dest, const char *selfkey, const char *otherkey, int winnum);
#endif /* #define LOG_H */

156
src/message_queue.c Normal file
View 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;
}
}

51
src/message_queue.h Normal file
View File

@@ -0,0 +1,51 @@
/* 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/>.
*
*/
#ifndef MESSAGE_QUEUE_H
#define MESSAGE_QUEUE_H
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);
#endif /* #define MESSAGE_QUEUE_H */

View File

@@ -35,7 +35,7 @@
#include "file_senders.h"
extern ToxWindow *prompt;
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
static uint64_t current_unix_time;
@@ -82,12 +82,12 @@ struct tm *get_time(void)
/*Puts the current time in buf in the format of [HH:mm:ss] */
void get_time_str(char *buf, int bufsize)
{
if (user_settings_->timestamps == TIMESTAMPS_OFF) {
if (user_settings->timestamps == TIMESTAMPS_OFF) {
buf[0] = '\0';
return;
}
const char *t = user_settings_->time == TIME_12 ? "[%-I:%M:%S] " : "[%H:%M:%S] ";
const char *t = user_settings->time == TIME_12 ? "%I:%M:%S " : "%H:%M:%S ";
strftime(buf, bufsize, t, get_time());
}
@@ -306,8 +306,38 @@ void bytes_convert_str(char *buf, int size, uint64_t bytes)
}
/* checks if a file exists. Returns true or false */
bool file_exists(const char *fp)
bool file_exists(const char *path)
{
struct stat s;
return stat(fp, &s) == 0;
return stat(path, &s) == 0;
}
/* returns file size or -1 on error */
off_t file_size(const char *path)
{
struct stat st;
if (stat(path, &st) == -1)
return -1;
return st.st_size;
}
/* compares the first size bytes of fp to signature.
Returns 0 if they are the same, 1 if they differ, and -1 on error.
On success this function will seek back to the beginning of fp */
int check_file_signature(const char *signature, size_t size, FILE *fp)
{
char buf[size];
if (fread(buf, size, 1, fp) != 1)
return -1;
int ret = memcmp(signature, buf, size);
if (fseek(fp, 0L, SEEK_SET) == -1)
return -1;
return ret == 0 ? 0 : 1;
}

View File

@@ -19,8 +19,10 @@
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _misc_tools_h
#define _misc_tools_h
#ifndef MISC_TOOLS_H
#define MISC_TOOLS_H
#include <sys/stat.h>
#include "windows.h"
#include "toxic.h"
@@ -110,6 +112,15 @@ int char_rfind(const char *s, char ch, int len);
void bytes_convert_str(char *buf, int size, uint64_t bytes);
/* 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 */
/* returns file size or -1 on error */
off_t file_size(const char *path);
/* compares the first size bytes of fp and signature.
Returns 0 if they are the same, 1 if they differ, and -1 on error.
On success this function will seek back to the beginning of fp */
int check_file_signature(const char *signature, size_t size, FILE *fp);
#endif /* #define MISC_TOOLS_H */

View File

@@ -20,21 +20,23 @@
*
*/
#include "notify.h"
#include "device.h"
#include "settings.h"
#include "line_info.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdarg.h>
#include <time.h>
#include <assert.h>
#include <sys/stat.h>
#if defined(_AUDIO) || defined(_SOUND_NOTIFY)
#include "notify.h"
#include "device.h"
#include "settings.h"
#include "line_info.h"
#include "misc_tools.h"
#if defined(AUDIO) || defined(SOUND_NOTIFY)
#ifdef __APPLE__
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
@@ -46,54 +48,55 @@
#include <AL/alext.h>
#endif
#endif
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
#include <AL/alut.h> /* freealut packet */
#endif
#endif /* _AUDIO */
#endif /* AUDIO */
#ifdef _X11
#ifdef X11
#include <X11/Xlib.h>
#endif /* _X11 */
#endif /* X11 */
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
#include <libnotify/notify.h>
#endif
#define MAX_BOX_MSG_LEN 127
#define SOUNDS_SIZE 10
#define ACTIVE_NOTIFS_MAX 50
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
struct _Control {
struct Control {
time_t cooldown;
time_t notif_timeout;
unsigned long this_window;
#ifdef _X11
#ifdef X11
Display *display;
#endif /* _X11 */
unsigned long this_window;
#endif /* X11 */
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
pthread_mutex_t poll_mutex[1];
_Bool poll_active;
bool poll_active;
#endif
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
uint32_t device_idx; /* index of output device */
char* sounds[SOUNDS_SIZE];
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
} Control = {0};
struct _ActiveNotifications {
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
uint32_t source;
uint32_t buffer;
_Bool looping;
bool looping;
#endif
_Bool active;
bool active;
int *id_indicator;
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
NotifyNotification* box;
char messages[128][128];
char messages[MAX_BOX_MSG_LEN + 1][MAX_BOX_MSG_LEN + 1];
char title[24];
size_t size;
time_t n_timeout;
@@ -105,43 +108,92 @@ 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()
{
#ifdef _X11
if (!Control.display) return 0;
Window focus;
int revert;
XGetInputFocus(Control.display, &focus, &revert);
return focus;
}
#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 0;
#endif /* _X11 */
return res;
#endif
}
static void control_lock()
{
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
pthread_mutex_lock(Control.poll_mutex);
#endif
}
static void control_unlock()
{
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
pthread_mutex_unlock(Control.poll_mutex);
#endif
}
#ifdef _SOUND_NOTIFY
_Bool is_playing(int source)
#ifdef SOUND_NOTIFY
bool is_playing(int source)
{
int ready;
alGetSourcei(source, AL_SOURCE_STATE, &ready);
return ready == AL_PLAYING;
}
/* Terminate all sounds but wait them to finish first */
/* TODO maybe find better way to do this */
/* cooldown is in seconds */
#define DEVICE_COOLDOWN 5 /* TODO perhaps load this from config? */
static bool device_opened = false;
time_t last_opened_update = 0;
bool m_open_device()
{
last_opened_update = time(NULL);
if (device_opened) return true;
/* Blah error check */
open_primary_device(output, &Control.device_idx, 48000, 20, 1);
return (device_opened = true);
}
bool m_close_device()
{
if (!device_opened) return true;
close_device(output, Control.device_idx);
return !(device_opened = false);
}
/* Terminate all sounds but wait for them to finish first */
void graceful_clear()
{
int i;
@@ -149,7 +201,7 @@ void graceful_clear()
while (1) {
for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) {
if (actives[i].active) {
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
if (actives[i].box) {
GError* ignore;
notify_notification_close(actives[i].box, &ignore);
@@ -167,10 +219,10 @@ void graceful_clear()
else break;
}
}
}
if (i == ACTIVE_NOTIFS_MAX) {
m_close_device(); /* In case it's opened */
control_unlock();
return;
}
@@ -183,11 +235,19 @@ void* do_playing(void* _p)
{
(void)_p;
int i;
bool has_looping = false;
while(Control.poll_active) {
control_lock();
for (i = 0; i < ACTIVE_NOTIFS_MAX; i ++) {
if (actives[i].looping) has_looping = true;
if (actives[i].active && !actives[i].looping
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
&& !actives[i].box
#endif
) {
@@ -199,7 +259,7 @@ void* do_playing(void* _p)
memset(&actives[i], 0, sizeof(struct _ActiveNotifications));
}
}
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
else if (actives[i].box && time(NULL) >= actives[i].n_timeout)
{
GError* ignore;
@@ -218,13 +278,21 @@ void* do_playing(void* _p)
}
#endif
}
/* device is opened and no activity in under DEVICE_COOLDOWN time, close device*/
if (device_opened && !has_looping &&
(time(NULL) - last_opened_update) > DEVICE_COOLDOWN) {
m_close_device();
}
has_looping = false;
control_unlock();
usleep(10000);
}
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;
for (; i < ACTIVE_NOTIFS_MAX && actives[i].active; i ++);
@@ -242,7 +310,7 @@ int play_source(uint32_t source, uint32_t buffer, _Bool looping)
return i;
}
#elif _BOX_NOTIFY
#elif BOX_NOTIFY
void* do_playing(void* _p)
{
(void)_p;
@@ -297,15 +365,16 @@ void graceful_clear()
/* Opens primary device */
int init_notify(int login_cooldown, int notification_timeout)
{
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
alutInitWithoutContext(NULL, NULL);
if (open_primary_device(output, &Control.device_idx, 48000, 20, 1) != de_None)
return -1;
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
if (pthread_mutex_init(Control.poll_mutex, NULL) != 0)
return -1;
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
pthread_mutex_init(Control.poll_mutex, NULL);
pthread_t thread;
if (pthread_create(&thread, NULL, do_playing, NULL) != 0 || pthread_detach(thread) != 0 ) {
pthread_mutex_destroy(Control.poll_mutex);
return -1;
@@ -314,15 +383,13 @@ int init_notify(int login_cooldown, int notification_timeout)
#endif
Control.cooldown = time(NULL) + login_cooldown;
#ifdef _X11
#ifdef X11
Control.display = XOpenDisplay(NULL);
Control.this_window = get_focused_window_id();
#else
Control.this_window = 1;
#endif /* _X11 */
#endif /* X11 */
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
notify_init("toxic");
#endif
Control.notif_timeout = notification_timeout;
@@ -331,26 +398,25 @@ int init_notify(int login_cooldown, int notification_timeout)
void terminate_notify()
{
#if defined(_SOUND_NOTIFY) || defined(_BOX_NOTIFY)
#if defined(SOUND_NOTIFY) || defined(BOX_NOTIFY)
if ( !Control.poll_active ) return;
Control.poll_active = 0;
graceful_clear();
#endif
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
int i = 0;
for (; i < SOUNDS_SIZE; i ++) free(Control.sounds[i]);
close_device(output, Control.device_idx);
alutExit();
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
notify_uninit();
#endif
}
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
int set_sound(Notification sound, const char* value)
{
if (sound == silent) return 0;
@@ -365,11 +431,13 @@ int set_sound(Notification sound, const char* value)
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 buffer;
m_open_device();
alGenSources(1, &source);
alGenBuffers(1, &buffer);
buffer = alutCreateBufferFromFile(Control.sounds[what]);
@@ -406,7 +474,7 @@ int play_notify_sound(Notification notif, uint64_t flags)
void stop_sound(int id)
{
if (id >= 0 && id < ACTIVE_NOTIFS_MAX && actives[id].looping && actives[id].active ) {
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
if (actives[id].box) {
GError* ignore;
notify_notification_close(actives[id].box, &ignore);
@@ -424,17 +492,17 @@ void stop_sound(int id)
static int m_play_sound(Notification notif, uint64_t flags)
{
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
return play_notify_sound(notif, flags);
#else
if (notif != silent)
beep();
return -1;
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
void m_notify_action(NotifyNotification *box, char *action, void* data)
{
}
@@ -442,27 +510,21 @@ void m_notify_action(NotifyNotification *box, char *action, void* data)
int sound_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indicator)
{
/* Consider colored notify as primary */
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;
}
tab_notify(self, flags);
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
if (notifications_are_disabled(flags))
return -1;
int id = -1;
control_lock();
if (self && (!self->stb || self->stb->status != TOX_USERSTATUS_BUSY) && user_settings_->alerts == ALERTS_ENABLED)
if (self && (!self->stb || self->stb->status != TOX_USERSTATUS_BUSY) && user_settings->alerts == ALERTS_ENABLED)
id = m_play_sound(notif, flags);
else if (flags & NT_ALWAYS)
id = m_play_sound(notif, flags);
#if defined(_BOX_NOTIFY) && !defined(_SOUND_NOTIFY)
#if defined(BOX_NOTIFY) && !defined(SOUND_NOTIFY)
if (id == -1) {
for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].box; id ++);
@@ -486,19 +548,13 @@ 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)
{
/* Consider colored notify as primary */
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;
}
tab_notify(self, flags);
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
if (notifications_are_disabled(flags))
return -1;
if (id < 0 || id >= ACTIVE_NOTIFS_MAX) return -1;
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
control_lock();
if (!actives[id].active || !Control.sounds[notif]) {
@@ -506,6 +562,8 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
return -1;
}
m_open_device();
alSourceStop(actives[id].source);
alDeleteSources(1, &actives[id].source);
alDeleteBuffers(1,&actives[id].buffer);
@@ -527,22 +585,23 @@ int sound_notify2(ToxWindow* self, Notification notif, uint64_t flags, int id)
beep();
return 0;
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
}
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)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
if (notifications_are_disabled(flags)) {
tab_notify(self, flags);
return -1;
}
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
int id = sound_notify(self, notif, flags, id_indicator);
control_lock();
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
if (id == -1) { /* Could not play */
for (id = 0; id < ACTIVE_NOTIFS_MAX && actives[id].active; id ++);
@@ -561,11 +620,11 @@ int box_notify(ToxWindow* self, Notification notif, uint64_t flags, int* id_indi
if (strlen(title) > 23) strcpy(actives[id].title + 20, "...");
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__);
if (strlen(actives[id].messages[0]) > 124)
strcpy(actives[id].messages[0] + 124, "...");
if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3)
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].size ++;
@@ -585,29 +644,29 @@ 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, ...)
{
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
if (notifications_are_disabled(flags)) {
tab_notify(self, flags);
return -1;
}
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
if (sound_notify2(self, notif, flags, id) == -1)
return -1;
control_lock();
if (!actives[id].box || actives[id].size >= 128 ) {
if (!actives[id].box || actives[id].size >= MAX_BOX_MSG_LEN + 1) {
control_unlock();
return -1;
}
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__);
if (strlen(actives[id].messages[actives[id].size]) > 124)
strcpy(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] + MAX_BOX_MSG_LEN - 3, "...");
actives[id].size ++;
actives[id].n_timeout = time(NULL) + Control.notif_timeout / 1000;
@@ -635,18 +694,12 @@ 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, ...)
{
/* Always do colored notify */
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;
}
tab_notify(self, flags);
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
if (notifications_are_disabled(flags))
return -1;
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
control_lock();
@@ -666,11 +719,11 @@ int box_silent_notify(ToxWindow* self, uint64_t flags, int* id_indicator, const
if (strlen(title) > 23) strcpy(actives[id].title + 20, "...");
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__);
if (strlen(actives[id].messages[0]) > 124)
strcpy(actives[id].messages[0] + 124, "...");
if (strlen(actives[id].messages[0]) > MAX_BOX_MSG_LEN - 3)
strcpy(actives[id].messages[0] + MAX_BOX_MSG_LEN - 3, "...");
actives[id].active = 1;
actives[id].box = notify_notification_new(actives[id].title, actives[id].messages[0], NULL);
@@ -691,32 +744,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, ...)
{
/* Always do colored notify */
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;
}
tab_notify(self, flags);
if ((flags & NT_RESTOL && Control.cooldown > time(NULL)) ||
((flags & NT_NOFOCUS && Control.this_window == get_focused_window_id()) ))
if (notifications_are_disabled(flags))
return -1;
#ifdef _BOX_NOTIFY
#ifdef BOX_NOTIFY
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();
return -1;
}
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__);
if (strlen(actives[id].messages[actives[id].size]) > 124)
strcpy(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] + MAX_BOX_MSG_LEN - 3, "...");
actives[id].size ++;
actives[id].n_timeout = time(NULL) + Control.notif_timeout / 1000;

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _notify_h
#define _notify_h
#ifndef NOTIFY_H
#define NOTIFY_H
#include <inttypes.h>
#include "windows.h"
@@ -73,8 +73,8 @@ 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_notify2(ToxWindow* self, uint64_t flags, int id, const char* format, ...);
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
int set_sound(Notification sound, const char* value);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
#endif /* _notify_h */
#endif /* NOTIFY_H */

View File

@@ -43,15 +43,16 @@
#include "autocomplete.h"
extern ToxWindow *prompt;
extern struct user_settings *user_settings_;
extern struct _Winthread Winthread;
extern struct user_settings *user_settings;
extern struct Winthread Winthread;
_FriendRequests FriendRequests;
FriendRequests FrndRequests;
/* Array of global command names used for tab completion. */
const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/accept" },
{ "/add" },
{ "/avatar" },
{ "/clear" },
{ "/close" }, /* rm /close when groupchats gets its own list */
{ "/connect" },
@@ -67,12 +68,12 @@ const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/requests" },
{ "/status" },
#ifdef _AUDIO
#ifdef AUDIO
{ "/lsdev" },
{ "/sdev" },
#endif /* _AUDIO */
#endif /* AUDIO */
};
void kill_prompt_window(ToxWindow *self)
@@ -88,7 +89,6 @@ void kill_prompt_window(ToxWindow *self)
delwin(statusbar->topline);
free(ctx->log);
free(ctx->hst);
free(ctx);
free(self->help);
free(statusbar);
@@ -132,21 +132,21 @@ void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected)
Returns request number on success, -1 if queue is full. */
static int add_friend_request(const char *public_key, const char *data)
{
if (FriendRequests.max_idx >= MAX_FRIEND_REQUESTS)
if (FrndRequests.max_idx >= MAX_FRIEND_REQUESTS)
return -1;
int i;
for (i = 0; i <= FriendRequests.max_idx; ++i) {
if (!FriendRequests.request[i].active) {
FriendRequests.request[i].active = true;
memcpy(FriendRequests.request[i].key, public_key, TOX_CLIENT_ID_SIZE);
snprintf(FriendRequests.request[i].msg, sizeof(FriendRequests.request[i].msg), "%s", data);
for (i = 0; i <= FrndRequests.max_idx; ++i) {
if (!FrndRequests.request[i].active) {
FrndRequests.request[i].active = true;
memcpy(FrndRequests.request[i].key, public_key, TOX_CLIENT_ID_SIZE);
snprintf(FrndRequests.request[i].msg, sizeof(FrndRequests.request[i].msg), "%s", data);
if (i == FriendRequests.max_idx)
++FriendRequests.max_idx;
if (i == FrndRequests.max_idx)
++FrndRequests.max_idx;
++FriendRequests.num_requests;
++FrndRequests.num_requests;
return i;
}
@@ -184,7 +184,12 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (key == '\t') { /* TAB key: auto-completes command */
if (ctx->len > 1 && ctx->line[0] == '/') {
int diff = complete_line(self, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
int diff = -1;
if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0)
diff = dir_match(self, m, ctx->line, L"/avatar");
else
diff = complete_line(self, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
if (diff != -1) {
if (x + diff > x2 - 1) {
@@ -300,7 +305,7 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
}
if (statusbar->statusmsg[0])
wprintw(statusbar->topline, " - %s", statusbar->statusmsg);
wprintw(statusbar->topline, " : %s", statusbar->statusmsg);
mvwhline(self->window, y2 - CHATBOX_HEIGHT, 0, ACS_HLINE, x2);
@@ -456,15 +461,16 @@ static void prompt_onInit(ToxWindow *self, Tox *m)
line_info_init(ctx->hst);
if (user_settings_->autolog == AUTOLOG_ON) {
if (user_settings->autolog == AUTOLOG_ON) {
char myid[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(m, (uint8_t *) myid);
log_enable(self->name, myid, ctx->log);
log_enable(self->name, myid, NULL, ctx->log, LOG_PROMPT);
}
scrollok(ctx->history, 0);
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
if (user_settings->show_welcome_msg == SHOW_WELCOME_MSG_ON)
print_welcome_msg(self);
}

View File

@@ -20,21 +20,21 @@
*
*/
#ifndef PROMPT_H_UZYGWFFL
#define PROMPT_H_UZYGWFFL
#ifndef PROMPT_H
#define PROMPT_H
#include "toxic.h"
#include "windows.h"
#ifdef _AUDIO
#define AC_NUM_GLOB_COMMANDS 18
#ifdef AUDIO
#define AC_NUM_GLOB_COMMANDS 19
#else
#define AC_NUM_GLOB_COMMANDS 16
#endif /* _AUDIO */
#define AC_NUM_GLOB_COMMANDS 17
#endif /* AUDIO */
#define MAX_FRIEND_REQUESTS 32
struct _friend_request {
struct friend_request {
bool active;
char msg[MAX_STR_SIZE];
uint8_t key[TOX_CLIENT_ID_SIZE];
@@ -43,8 +43,8 @@ struct _friend_request {
typedef struct {
int max_idx;
int num_requests;
struct _friend_request request[MAX_FRIEND_REQUESTS];
} _FriendRequests;
struct friend_request request[MAX_FRIEND_REQUESTS];
} FriendRequests;
ToxWindow new_prompt(void);
void prep_prompt_win(void);
@@ -55,4 +55,4 @@ void prompt_update_status(ToxWindow *prompt, uint8_t status);
void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected);
void kill_prompt_window(ToxWindow *self);
#endif /* end of include guard: PROMPT_H_UZYGWFFL */
#endif /* end of include guard: PROMPT_H */

View File

@@ -31,9 +31,9 @@
#include "notify.h"
#include "misc_tools.h"
#ifdef _AUDIO
#ifdef AUDIO
#include "device.h"
#endif /* _AUDIO */
#endif /* AUDIO */
#include "settings.h"
#include "line_info.h"
@@ -44,7 +44,7 @@
#define NO_SOUND "silent"
static struct _ui_strings {
static struct ui_strings {
const char* self;
const char* timestamps;
const char* alerts;
@@ -54,6 +54,7 @@ static struct _ui_strings {
const char* history_size;
const char* show_typing_self;
const char* show_typing_other;
const char* show_welcome_msg;
} ui_strings = {
"ui",
"timestamps",
@@ -64,6 +65,7 @@ static struct _ui_strings {
"history_size",
"show_typing_self",
"show_typing_other",
"show_welcome_msg",
};
static void ui_defaults(struct user_settings* settings)
@@ -76,9 +78,10 @@ static void ui_defaults(struct user_settings* settings)
settings->history_size = 700;
settings->show_typing_self = 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 {
const char* self;
const char* next_tab;
const char* prev_tab;
@@ -116,24 +119,27 @@ static void key_defaults(struct user_settings* settings)
settings->key_peer_list_down = T_KEY_C_RB;
}
static const struct _tox_strings {
static const struct tox_strings {
const char* self;
const char* download_path;
const char* chatlogs_path;
const char* avatar_path;
} tox_strings = {
"tox",
"download_path",
"chatlogs_path",
"avatar_path",
};
static void tox_defaults(struct user_settings* settings)
{
strcpy(settings->download_path, "");
strcpy(settings->chatlogs_path, "");
strcpy(settings->avatar_path, "");
}
#ifdef _AUDIO
static const struct _audio_strings {
#ifdef AUDIO
static const struct audio_strings {
const char* self;
const char* input_device;
const char* output_device;
@@ -153,8 +159,8 @@ static void audio_defaults(struct user_settings* settings)
}
#endif
#ifdef _SOUND_NOTIFY
static const struct _sound_strings {
#ifdef SOUND_NOTIFY
static const struct sound_strings {
const char* self;
const char* error;
const char* self_log_in;
@@ -209,7 +215,7 @@ int settings_load(struct user_settings *s, const char *patharg)
tox_defaults(s);
key_defaults(s);
#ifdef _AUDIO
#ifdef AUDIO
audio_defaults(s);
#endif
@@ -250,6 +256,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_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_welcome_msg, &s->show_welcome_msg);
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 */
}
@@ -276,6 +283,14 @@ int settings_load(struct user_settings *s, const char *patharg)
else if (s->chatlogs_path[len - 1] != '/')
strcat(&s->chatlogs_path[len - 1], "/");
}
if ( config_setting_lookup_string(setting, tox_strings.avatar_path, &str) ) {
snprintf(s->avatar_path, sizeof(s->avatar_path), "%s", str);
int len = strlen(s->avatar_path);
if (len >= sizeof(s->avatar_path))
s->avatar_path[0] = '\0';
}
}
/* keys */
@@ -292,7 +307,7 @@ int settings_load(struct user_settings *s, const char *patharg)
if (config_setting_lookup_string(setting, key_strings.peer_list_down, &tmp)) s->key_peer_list_down = key_parse(&tmp);
}
#ifdef _AUDIO
#ifdef AUDIO
if ((setting = config_lookup(cfg, audio_strings.self)) != NULL) {
config_setting_lookup_int(setting, audio_strings.input_device, &s->audio_in_dev);
s->audio_in_dev = s->audio_in_dev < 0 || s->audio_in_dev > MAX_DEVICES ? 0 : s->audio_in_dev;
@@ -304,7 +319,7 @@ int settings_load(struct user_settings *s, const char *patharg)
}
#endif
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
if ((setting = config_lookup(cfg, sound_strings.self)) != NULL) {
if ( (config_setting_lookup_string(setting, sound_strings.error, &str) != CONFIG_TRUE) ||
!set_sound(error, str) ) {

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _settings_h
#define _settings_h
#ifndef SETTINGS_H
#define SETTINGS_H
#include <limits.h>
@@ -35,12 +35,14 @@ struct user_settings {
int history_size; /* int between MIN_HISTORY and MAX_HISTORY */
int show_typing_self; /* boolean */
int show_typing_other; /* boolean */
int show_welcome_msg; /* boolean */
char download_path[PATH_MAX];
char chatlogs_path[PATH_MAX];
char avatar_path[PATH_MAX];
int key_next_tab; /* character code */
int key_prev_tab; /* character code */
int key_next_tab;
int key_prev_tab;
int key_scroll_line_up;
int key_scroll_line_down;
int key_half_page_up;
@@ -48,7 +50,8 @@ struct user_settings {
int key_page_bottom;
int key_peer_list_up;
int key_peer_list_down;
#ifdef _AUDIO
#ifdef AUDIO
int audio_in_dev;
int audio_out_dev;
double VAD_treshold;
@@ -74,8 +77,11 @@ enum {
SHOW_TYPING_OFF = 0,
SHOW_TYPING_ON = 1,
SHOW_WELCOME_MSG_OFF = 0,
SHOW_WELCOME_MSG_ON = 1,
DFLT_HST_SIZE = 700,
} settings_values;
int settings_load(struct user_settings *s, const char *patharg);
#endif /* #define _settings_h */
#endif /* #define SETTINGS_H */

View File

@@ -38,8 +38,10 @@
#include <sys/socket.h>
#include <unistd.h>
#include <limits.h>
#include <termios.h>
#include <tox/tox.h>
#include <tox/toxencryptsave.h>
#include "configdir.h"
#include "toxic.h"
@@ -53,18 +55,20 @@
#include "log.h"
#include "notify.h"
#include "device.h"
#include "message_queue.h"
#include "execute.h"
#ifdef _AUDIO
#ifdef AUDIO
#include "audio_call.h"
#endif /* _AUDIO */
#endif /* AUDIO */
#ifndef PACKAGE_DATADIR
#define PACKAGE_DATADIR "."
#endif
#ifdef _AUDIO
#ifdef AUDIO
ToxAv *av;
#endif /* _AUDIO */
#endif /* AUDIO */
/* Export for use in Callbacks */
char *DATA_FILE = NULL;
@@ -73,13 +77,23 @@ ToxWindow *prompt = NULL;
#define AUTOSAVE_FREQ 60
struct _Winthread Winthread;
struct Winthread Winthread;
struct cqueue_thread cqueue_thread;
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)
{
Winthread.sig_exit_toxic = true;
Winthread.sig_exit_toxic = 1;
}
static void catch_SIGSEGV(int sig)
@@ -92,7 +106,7 @@ static void catch_SIGSEGV(int sig)
static void flag_window_resize(int sig)
{
Winthread.flag_resize = true;
Winthread.flag_resize = 1;
}
static void init_signal_catchers(void)
@@ -105,20 +119,21 @@ static void init_signal_catchers(void)
void exit_toxic_success(Tox *m)
{
store_data(m, DATA_FILE);
memset(&user_password, 0, sizeof(struct user_password));
close_all_file_senders(m);
kill_all_windows(m);
free(DATA_FILE);
free(BLOCK_FILE);
free(user_settings_);
free(user_settings);
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
// sound_notify(NULL, self_log_out, NT_ALWAYS, NULL);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
terminate_notify();
#ifdef _AUDIO
#ifdef AUDIO
terminate_audio();
#endif /* _AUDIO */
#endif /* AUDIO */
tox_kill(m);
endwin();
exit(EXIT_SUCCESS);
@@ -157,7 +172,7 @@ static void init_term(void)
short bg_color = COLOR_BLACK;
start_color();
if (user_settings_->colour_theme == NATIVE_COLS) {
if (user_settings->colour_theme == NATIVE_COLS) {
if (assume_default_colors(-1, -1) == OK)
bg_color = -1;
}
@@ -182,8 +197,15 @@ static struct _init_messages {
} init_messages;
/* 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;
++init_messages.num;
@@ -197,11 +219,11 @@ static void queue_init_message(const char *msg)
if (new_msgs[i] == NULL)
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;
}
/* called after messages have been printed to console and are no longer needed */
/* called after messages have been printed to prompt and are no longer needed */
static void cleanup_init_messages(void)
{
if (init_messages.num <= 0)
@@ -237,16 +259,16 @@ static Tox *init_tox(void)
char tmp[48];
snprintf(tmp, sizeof(tmp), "Using proxy %s : %d",
arg_opts.proxy_address, arg_opts.proxy_port);
queue_init_message(tmp);
queue_init_message("%s", tmp);
}
if (tox_opts.udp_disabled) {
queue_init_message("UDP disabled");
} else if (tox_opts.proxy_enabled) {
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.";
queue_init_message(msg);
queue_init_message("%s", msg);
}
/* Init core */
@@ -283,6 +305,7 @@ static Tox *init_tox(void)
tox_callback_file_send_request(m, on_file_sendrequest, NULL);
tox_callback_file_control(m, on_file_control, NULL);
tox_callback_file_data(m, on_file_data, NULL);
tox_callback_read_receipt(m, on_read_receipt, NULL);
#ifdef __linux__
tox_set_name(m, (uint8_t *) "Cool dude", strlen("Cool dude"));
@@ -302,7 +325,7 @@ static Tox *init_tox(void)
#define MAXNODES 50
#define NODELEN (MAX_NODE_LINE - TOX_CLIENT_ID_SIZE - 7)
static struct _toxNodes {
static struct toxNodes {
int lines;
char nodes[MAXNODES][NODELEN];
uint16_t ports[MAXNODES];
@@ -456,6 +479,104 @@ static void load_friendlist(Tox *m)
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
* Return 0 stored successfully or ignoring data file
@@ -464,7 +585,7 @@ static void load_friendlist(Tox *m)
* Return -3 opening path 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)
return 0;
@@ -472,12 +593,15 @@ int store_data(Tox *m, char *path)
if (path == NULL)
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);
if (buf == NULL)
return -2;
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");
@@ -506,9 +630,12 @@ static void load_data(Tox *m, char *path)
FILE *fd;
if ((fd = fopen(path, "rb")) != NULL) {
fseek(fd, 0, SEEK_END);
int len = ftell(fd);
fseek(fd, 0, SEEK_SET);
off_t len = file_size(path);
if (len == -1) {
fclose(fd);
exit_toxic_err("failed in load_data", FATALERR_FILEOP);
}
char *buf = malloc(len);
@@ -520,10 +647,54 @@ static void load_data(Tox *m, char *path)
if (fread(buf, len, 1, fd) != 1) {
free(buf);
fclose(fd);
exit_toxic_err("failed in load_data", FATALERR_FREAD);
exit_toxic_err("failed in load_data", FATALERR_FILEOP);
}
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_blocklist(BLOCK_FILE);
@@ -553,6 +724,7 @@ void *thread_winref(void *data)
{
Tox *m = (Tox *) data;
uint8_t draw_count = 0;
init_signal_catchers();
while (true) {
draw_active_window(m);
@@ -560,7 +732,7 @@ void *thread_winref(void *data)
if (Winthread.flag_resize) {
on_window_resize();
Winthread.flag_resize = false;
Winthread.flag_resize = 0;
} else if (draw_count >= INACTIVE_WIN_REFRESH_RATE) {
refresh_inactive_windows();
draw_count = 0;
@@ -573,13 +745,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)
{
fprintf(stderr, "usage: toxic [OPTION] [FILE ...]\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, " -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, " -h, --help Show this message and exit\n");
fprintf(stderr, " -n, --nodes Use specified DHTnodes file\n");
@@ -587,19 +780,15 @@ static void print_usage(void)
fprintf(stderr, " -p, --proxy Use proxy: Requires [IP] [port]\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, " -u, --unencrypt-data Unencrypt an encrypted data file\n");
fprintf(stderr, " -x, --nodata Ignore data file\n");
}
static void set_default_opts(void)
{
arg_opts.use_ipv4 = 0;
arg_opts.ignore_data_file = 0;
arg_opts.debug = 0;
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;
memset(&arg_opts, 0, sizeof(struct arg_opts));
/* set any non-zero defaults here*/
}
static void parse_args(int argc, char *argv[])
@@ -613,16 +802,18 @@ static void parse_args(int argc, char *argv[])
{"debug", no_argument, 0, 'b'},
{"default-locale", no_argument, 0, 'd'},
{"config", required_argument, 0, 'c'},
{"encrypt-data", no_argument, 0, 'e'},
{"nodes", required_argument, 0, 'n'},
{"help", no_argument, 0, 'h'},
{"noconnect", no_argument, 0, 'o'},
{"dnslist", required_argument, 0, 'r'},
{"force-tcp", no_argument, 0, 't'},
{"proxy", required_argument, 0, 'p'},
{"unencrypt-data", no_argument, 0, 'u'},
{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;
while ((opt = getopt_long(argc, argv, opts_str, long_opts, &indexptr)) != -1) {
@@ -649,6 +840,10 @@ static void parse_args(int argc, char *argv[])
queue_init_message("Using default POSIX locale");
break;
case 'e':
arg_opts.encrypt_data = 1;
break;
case 'f':
arg_opts.use_custom_data = 1;
DATA_FILE = strdup(optarg);
@@ -660,9 +855,8 @@ static void parse_args(int argc, char *argv[])
strcpy(BLOCK_FILE, optarg);
strcat(BLOCK_FILE, "-blocklist");
char tmp[PATH_MAX];
snprintf(tmp, sizeof(tmp), "Using '%s' data file", DATA_FILE);
queue_init_message(tmp);
queue_init_message("Using '%s' data file", DATA_FILE);
break;
case 'n':
@@ -700,6 +894,10 @@ static void parse_args(int argc, char *argv[])
arg_opts.force_tcp = 1;
break;
case 'u':
arg_opts.unencrypt_data = 1;
break;
case 'x':
arg_opts.ignore_data_file = 1;
queue_init_message("Ignoring data file");
@@ -715,7 +913,7 @@ static void parse_args(int argc, char *argv[])
#define DATANAME "data"
#define BLOCKNAME "data-blocklist"
static int init_data_files(void)
static int init_default_data_files(void)
{
if (arg_opts.use_custom_data)
return 0;
@@ -723,7 +921,6 @@ static int init_data_files(void)
char *user_config_dir = get_user_config_dir();
int config_err = create_user_config_dirs(user_config_dir);
if (DATA_FILE == NULL ) {
if (config_err) {
DATA_FILE = strdup(DATANAME);
BLOCK_FILE = strdup(BLOCKNAME);
@@ -745,7 +942,6 @@ static int init_data_files(void)
strcat(BLOCK_FILE, CONFIGDIR);
strcat(BLOCK_FILE, BLOCKNAME);
}
}
free(user_config_dir);
return config_err;
@@ -772,35 +968,54 @@ static useconds_t optimal_msleepval(uint64_t *looptimer, uint64_t *loopcount, ui
int main(int argc, char *argv[])
{
init_signal_catchers();
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. */
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 */
user_settings_ = calloc(1, sizeof(struct user_settings));
user_settings = calloc(1, sizeof(struct user_settings));
if (user_settings_ == NULL)
if (user_settings == NULL)
exit_toxic_err("failed in main", FATALERR_MEMORY);
char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
int settings_err = settings_load(user_settings_, p);
const char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
int settings_err = settings_load(user_settings, p);
Tox *m = init_tox();
init_term();
/* enable stderr for debugging */
if (!arg_opts.debug)
freopen("/dev/null", "w", stderr);
if (m == NULL)
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);
}
init_term();
prompt = init_windows(m);
prompt_init_statusbar(prompt, m);
@@ -811,31 +1026,34 @@ int main(int argc, char *argv[])
if (pthread_create(&Winthread.tid, NULL, thread_winref, (void *) m) != 0)
exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);
#ifdef _AUDIO
/* 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
av = init_audio(prompt, m);
set_primary_device(input, user_settings->audio_in_dev);
set_primary_device(output, user_settings->audio_out_dev);
set_primary_device(input, user_settings_->audio_in_dev);
set_primary_device(output, user_settings_->audio_out_dev);
#elif _SOUND_NOTIFY
#elif SOUND_NOTIFY
if ( init_devices() == de_InternalError )
queue_init_message("Failed to init audio devices");
#endif /* _AUDIO */
#endif /* AUDIO */
init_notify(60, 3000);
#ifdef _SOUND_NOTIFY
#ifdef SOUND_NOTIFY
// sound_notify(prompt, self_log_in, 0, NULL);
#endif /* _SOUND_NOTIFY */
#endif /* SOUND_NOTIFY */
const char *msg;
if (config_err) {
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)
@@ -844,6 +1062,11 @@ int main(int argc, char *argv[])
print_init_messages(prompt);
cleanup_init_messages();
/* set user avatar from config file. if no path is supplied tox_unset_avatar is called */
char avatarstr[MAX_STR_SIZE];
snprintf(avatarstr, sizeof(avatarstr), "/avatar \"%s\"", user_settings->avatar_path);
execute(prompt->chatwin->history, prompt, m, avatarstr, GLOBAL_COMMAND_MODE);
uint64_t last_save = (uint64_t) time(NULL);
uint64_t looptimer = last_save;
useconds_t msleepval = 40000;

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _toxic_h
#define _toxic_h
#ifndef TOXIC_H
#define TOXIC_H
#ifndef TOXICVER
#define TOXICVER "NOVER_" /* Use the -D flag to set this */
@@ -45,7 +45,7 @@
#define MAX_STR_SIZE TOX_MAX_MESSAGE_LENGTH
#define MAX_CMDNAME_SIZE 64
#define TOXIC_MAX_NAME_LENGTH 32 /* Must be <= TOX_MAX_NAME_LENGTH */
#define KEY_IDENT_DIGITS 2 /* number of hex digits to display for the pub-key based identifier */
#define KEY_IDENT_DIGITS 3 /* number of hex digits to display for the pub-key based identifier */
#define TIME_STR_SIZE 16
/* ASCII key codes */
@@ -69,9 +69,9 @@
typedef enum _FATAL_ERRS {
FATALERR_MEMORY = -1, /* heap memory allocation failed */
FATALERR_FREAD = -2, /* fread() failed on critical read */
FATALERR_THREAD_CREATE = -3, /* thread creation failed */
FATALERR_MUTEX_INIT = -4, /* mutex init failed */
FATALERR_FILEOP = -2, /* critical file operation failed */
FATALERR_THREAD_CREATE = -3, /* thread creation failed for critical thread */
FATALERR_MUTEX_INIT = -4, /* mutex init for critical thread failed */
FATALERR_THREAD_ATTR = -5, /* thread attr object init failed */
FATALERR_LOCALE_SET = -6, /* system locale not set */
FATALERR_STORE_DATA = -7, /* store_data failed in critical section */
@@ -79,6 +79,7 @@ typedef enum _FATAL_ERRS {
FATALERR_INFLOOP = -9, /* infinite loop detected */
FATALERR_WININIT = -10, /* window init failed */
FATALERR_PROXY = -11, /* Tox network failed to init using a proxy */
FATALERR_ENCRYPT = -12, /* Data file encryption failure */
} FATAL_ERRS;
/* Fixes text color problem on some terminals.
@@ -88,7 +89,7 @@ typedef enum _FATAL_ERRS {
void exit_toxic_success(Tox *m);
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_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata);
@@ -100,7 +101,7 @@ void on_statusmessagechange(Tox *m, int32_t friendnumber, const uint8_t *string,
void on_friendadded(Tox *m, int32_t friendnumber, bool sort);
void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *message, uint16_t length, void *userdata);
void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *action, uint16_t length, void *userdata);
void on_groupinvite(Tox *m, int32_t friendnumber, const uint8_t *group_pub_key, void *userdata);
void on_groupinvite(Tox *m, int32_t friendnumber, const uint8_t *group_pub_key, uint16_t length, void *userdata);
void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t change, void *userdata);
void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *pathname,
uint16_t pathname_length, 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);
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_read_receipt(Tox *m, int32_t, uint32_t, void *userdata);
#endif /* #define _toxic_h */
#endif /* #define TOXIC_H */

View File

@@ -20,8 +20,8 @@
*
*/
#ifndef _toxic_strings_h
#define _toxic_strings_h
#ifndef TOXIC_STRINGS_H
#define TOXIC_STRINGS_H
#include "windows.h"
@@ -61,4 +61,4 @@ void add_line_to_hist(ChatContext *ctx);
resets line if at end of history */
void fetch_hist_item(ChatContext *ctx, int key_dir);
#endif /* #define _toxic_strings_h */
#endif /* #define TOXIC_STRINGS_H */

View File

@@ -35,12 +35,12 @@
#include "settings.h"
extern char *DATA_FILE;
extern struct _Winthread Winthread;
extern struct Winthread Winthread;
static ToxWindow windows[MAX_WINDOWS_NUM];
static ToxWindow *active_window;
extern ToxWindow *prompt;
extern struct user_settings *user_settings_;
extern struct user_settings *user_settings;
static int num_active_windows;
@@ -67,7 +67,7 @@ void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *use
void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata)
{
if (user_settings_->show_typing_other == SHOW_TYPING_OFF)
if (user_settings->show_typing_other == SHOW_TYPING_OFF)
return;
int i;
@@ -164,13 +164,13 @@ void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *acti
}
}
void on_groupinvite(Tox *m, int32_t friendnumber, const uint8_t *group_pub_key, void *userdata)
void on_groupinvite(Tox *m, int32_t friendnumber, const uint8_t *group_pub_key, uint16_t length, void *userdata)
{
int i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupInvite != NULL)
windows[i].onGroupInvite(&windows[i], m, friendnumber, (const char *) group_pub_key);
windows[i].onGroupInvite(&windows[i], m, friendnumber, (const char *) group_pub_key, length);
}
}
@@ -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 */
int add_window(Tox *m, ToxWindow w)
@@ -269,7 +278,7 @@ void set_next_window(int ch)
ToxWindow *inf = active_window;
while (true) {
if (ch == user_settings_->key_next_tab) {
if (ch == user_settings->key_next_tab) {
if (++active_window > end)
active_window = windows;
} else if (--active_window < windows)
@@ -357,12 +366,12 @@ void on_window_resize(void)
w->stb->topline = subwin(w->window, 2, x2, 0, 0);
}
#ifdef _AUDIO
#ifdef AUDIO
if (w->chatwin->infobox.active) {
delwin(w->chatwin->infobox.win);
w->chatwin->infobox.win = newwin(INFOBOX_HEIGHT, INFOBOX_WIDTH + 1, 1, x2 - INFOBOX_WIDTH);
}
#endif /* _AUDIO */
#endif /* AUDIO */
scrollok(w->chatwin->history, 0);
}
@@ -453,7 +462,7 @@ void draw_active_window(Tox *m)
ltr = isprint(ch);
#endif /* HAVE_WIDECHAR */
if (!ltr && (ch == user_settings_->key_next_tab || ch == user_settings_->key_prev_tab)) {
if (!ltr && (ch == user_settings->key_next_tab || ch == user_settings->key_prev_tab)) {
set_next_window((int) ch);
} else {
pthread_mutex_lock(&Winthread.lock);

View File

@@ -20,18 +20,19 @@
*
*/
#ifndef _windows_h
#define _windows_h
#ifndef WINDOWS_H
#define WINDOWS_H
#include <pthread.h>
#include <wctype.h>
#include <wchar.h>
#include <signal.h>
#include <tox/tox.h>
#ifdef _AUDIO
#ifdef AUDIO
#include <tox/toxav.h>
#endif /* _AUDIO */
#endif /* AUDIO */
#include "toxic.h"
@@ -64,11 +65,15 @@ typedef enum {
Uncomment if necessary */
/* #define URXVT_FIX */
struct _Winthread {
struct Winthread {
pthread_t tid;
pthread_mutex_t lock;
bool sig_exit_toxic;
bool flag_resize;
volatile sig_atomic_t sig_exit_toxic;
volatile sig_atomic_t flag_resize;
};
struct cqueue_thread {
pthread_t tid;
};
struct arg_opts {
@@ -79,7 +84,8 @@ struct arg_opts {
int default_locale;
int use_custom_data;
int no_connect;
int encrypt_data;
int unencrypt_data;
char dns_path[MAX_STR_SIZE];
char config_path[MAX_STR_SIZE];
char nodes_path[MAX_STR_SIZE];
@@ -109,14 +115,15 @@ struct ToxWindow {
void(*onAction)(ToxWindow *, Tox *, int32_t, const char *, uint16_t);
void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t);
void(*onGroupAction)(ToxWindow *, Tox *, int, int, const char *, uint16_t);
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, const char *);
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, const char *, uint16_t);
void(*onGroupNamelistChange)(ToxWindow *, Tox *, int, int, uint8_t);
void(*onFileSendRequest)(ToxWindow *, Tox *, int32_t, uint8_t, uint64_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(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t);
void(*onReadReceipt)(ToxWindow *, Tox *, int32_t, uint32_t);
#ifdef _AUDIO
#ifdef AUDIO
void(*onInvite)(ToxWindow *, ToxAv *, int);
void(*onRinging)(ToxWindow *, ToxAv *, int);
@@ -135,7 +142,7 @@ struct ToxWindow {
int device_selection[2]; /* -1 if not set, if set uses these selections instead of primary device */
int ringing_sound;
#endif /* _AUDIO */
#endif /* AUDIO */
int active_box; /* For box notify */
@@ -169,7 +176,7 @@ struct StatusBar {
bool is_online;
};
#ifdef _AUDIO
#ifdef AUDIO
#define INFOBOX_HEIGHT 7
@@ -188,7 +195,7 @@ struct infobox {
WINDOW *win;
};
#endif /* _AUDIO */
#endif /* AUDIO */
#define MAX_LINE_HIST 128
@@ -208,8 +215,9 @@ struct ChatContext {
struct history *hst;
struct chatlog *log;
struct chat_queue *cqueue;
#ifdef _AUDIO
#ifdef AUDIO
struct infobox infobox;
#endif
@@ -240,4 +248,4 @@ ToxWindow *get_window_ptr(int i);
call at least once per second */
void refresh_inactive_windows(void);
#endif /* #define _windows_h */
#endif /* #define WINDOWS_H */