mirror of
https://github.com/Tha14/toxic.git
synced 2025-06-29 11:56:44 +02:00
Compare commits
47 Commits
Author | SHA1 | Date | |
---|---|---|---|
eb7d910683 | |||
85af9f55ba | |||
ca98b49813 | |||
0cff881d69 | |||
7eb82a0fe5 | |||
58a131426a | |||
72e9e7d9c4 | |||
fc148be3e2 | |||
bc51714148 | |||
b24325d879 | |||
b480e22a27 | |||
afa4bc86e8 | |||
6cd2411ec0 | |||
6f9ab56493 | |||
485191d185 | |||
1456cef991 | |||
53cb4b0248 | |||
2c4f0d593d | |||
499c66f411 | |||
1b5da956e5 | |||
c76b541cb8 | |||
ce2d371c4b | |||
eefd981572 | |||
9240295724 | |||
a516724760 | |||
a0ef4d752f | |||
65ad64bf42 | |||
b36680d767 | |||
24a85df15f | |||
f10ce94f38 | |||
612c6c95eb | |||
31a2e648c5 | |||
31acdcada3 | |||
12e33a1760 | |||
328e7f8d57 | |||
33000598fc | |||
6a2ef5cc6c | |||
2a63e62aba | |||
935d8f8770 | |||
8c5ac1f77d | |||
bfa266c604 | |||
901ffbc7c0 | |||
97dedd32fb | |||
789c491c1e | |||
4b8dd3ad72 | |||
c2dce960b8 | |||
f9e15cd60b |
@ -3,7 +3,8 @@
|
||||
bin_PROGRAMS = toxic
|
||||
|
||||
|
||||
toxic_SOURCES = $(top_srcdir)/src/main.c \
|
||||
toxic_SOURCES = $(top_srcdir)/src/toxic.c \
|
||||
$(top_srcdir)/src/toxic.h \
|
||||
$(top_srcdir)/src/chat.h \
|
||||
$(top_srcdir)/src/chat.c \
|
||||
$(top_srcdir)/src/configdir.h \
|
||||
@ -12,8 +13,8 @@ toxic_SOURCES = $(top_srcdir)/src/main.c \
|
||||
$(top_srcdir)/src/prompt.c \
|
||||
$(top_srcdir)/src/friendlist.h \
|
||||
$(top_srcdir)/src/friendlist.c \
|
||||
$(top_srcdir)/src/toxic_windows.h \
|
||||
$(top_srcdir)/src/windows.c \
|
||||
$(top_srcdir)/src/windows.h \
|
||||
$(top_srcdir)/src/groupchat.c \
|
||||
$(top_srcdir)/src/groupchat.h \
|
||||
$(top_srcdir)/src/global_commands.c \
|
||||
@ -33,13 +34,15 @@ toxic_SOURCES = $(top_srcdir)/src/main.c \
|
||||
$(top_srcdir)/src/line_info.c \
|
||||
$(top_srcdir)/src/line_info.h \
|
||||
$(top_srcdir)/src/settings.c \
|
||||
$(top_srcdir)/src/settings.h
|
||||
$(top_srcdir)/src/settings.h \
|
||||
$(top_srcdir)/src/dns.c \
|
||||
$(top_srcdir)/src/dns.h
|
||||
|
||||
toxic_CFLAGS = -I$(top_srcdir) \
|
||||
$(NCURSES_CFLAGS) \
|
||||
$(LIBSODIUM_CFLAGS) \
|
||||
$(LIBTOXCORE_CFLAGS) \
|
||||
$(PTHREAD_CFLAGS)
|
||||
toxic_CFLAGS = -I$(top_srcdir) \
|
||||
$(NCURSES_CFLAGS) \
|
||||
$(LIBSODIUM_CFLAGS) \
|
||||
$(LIBTOXCORE_CFLAGS) \
|
||||
$(PTHREAD_CFLAGS)
|
||||
|
||||
toxic_CPPFLAGS = '-DTOXICVER="$(TOXIC_VERSION)"'
|
||||
|
||||
|
78
configure.ac
78
configure.ac
@ -2,9 +2,9 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.65])
|
||||
AC_INIT([toxic], [0.4.0], [https://tox.im/])
|
||||
AC_INIT([toxic], [0.4.1], [https://tox.im/])
|
||||
AC_CONFIG_AUX_DIR(configure_aux)
|
||||
AC_CONFIG_SRCDIR([src/main.c])
|
||||
AC_CONFIG_SRCDIR([src/toxic.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_INIT_AUTOMAKE([1.10 -Wall])
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
@ -37,7 +37,7 @@ if test -n "$DEPSEARCH"; then
|
||||
CFLAGS="$CFLAGS -I$DEPSEARCH/include"
|
||||
CPPFLAGS="$CPPFLAGS -I$DEPSEARCH/include"
|
||||
LDFLAGS="$LDFLAGS -L$DEPSEARCH/lib"
|
||||
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$DEPSEARCH/lib/pkgconfig
|
||||
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$DEPSEARCH/lib/pkgconfig:/usr/local/lib/pkgconfig
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(libtoxcore-headers,
|
||||
@ -77,11 +77,15 @@ AC_ARG_WITH(libsodium-libs,
|
||||
)
|
||||
|
||||
WIN32=no
|
||||
MACH=no
|
||||
AC_CANONICAL_HOST
|
||||
case $host_os in
|
||||
*mingw*)
|
||||
WIN32="yes"
|
||||
;;
|
||||
darwin*)
|
||||
MACH=yes
|
||||
;;
|
||||
*freebsd*)
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
CFLAGS="$CFLAGS -I/usr/local/include"
|
||||
@ -383,6 +387,15 @@ if test "x$LIBTOXCORE_FOUND" = "xno"; then
|
||||
AC_SUBST(LIBTOXCORE_LDFLAGS)
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADER([resolv.h], [],
|
||||
[
|
||||
AC_MSG_ERROR([resolv.h header was not found on your system])
|
||||
])
|
||||
|
||||
AC_CHECK_LIB(resolv, __res_init, [],
|
||||
[
|
||||
AC_MSG_ERROR([libresolv library was not found on your system])
|
||||
])
|
||||
|
||||
####
|
||||
#### A/V Stuff
|
||||
@ -422,29 +435,46 @@ AC_ARG_ENABLE([av],
|
||||
|
||||
if test "x$BUILD_AV" = "xyes"; then
|
||||
PKG_CHECK_MODULES([OPENAL], [openal],
|
||||
[
|
||||
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
|
||||
|
||||
PKG_CHECK_MODULES([LIBTOXAV], [libtoxav],
|
||||
[
|
||||
AC_CHECK_HEADER([tox/toxav.h],
|
||||
[
|
||||
# Place define for audio support
|
||||
AC_DEFINE([_SUPPORT_AUDIO], [], [Is audio supported])
|
||||
AC_MSG_NOTICE([Building with audio support])
|
||||
],
|
||||
[
|
||||
AC_MSG_NOTICE([No A/V headers; disabling A/V support])
|
||||
BUILD_AV="no"
|
||||
],)
|
||||
],
|
||||
[
|
||||
AC_MSG_NOTICE([No A/V library; disabling A/V support])
|
||||
[],
|
||||
[
|
||||
if test "x$MACH" = "xyes"; then
|
||||
CFLAGS="$CFLAGS -framework OpenAL"
|
||||
AC_CHECK_HEADER([OpenAL/al.h],
|
||||
[
|
||||
OPENAL_CFLAGS="-framework OpenAL"
|
||||
OPENAL_LIBS="-framework OpenAL"
|
||||
AC_SUBST(OPENAL_CFLAGS)
|
||||
AC_SUBST(OPENAL_LIBS)
|
||||
],
|
||||
[
|
||||
AC_MSG_NOTICE([No openal framework; disabling A/V support])
|
||||
BUILD_AV="no"
|
||||
]
|
||||
)
|
||||
CFLAGS="$CFLAGS_SAVE"
|
||||
else
|
||||
AC_MSG_NOTICE([No openal library; disabling A/V support])
|
||||
BUILD_AV="no"
|
||||
])
|
||||
fi
|
||||
])
|
||||
fi
|
||||
|
||||
if test "x$BUILD_AV" = "xyes"; then
|
||||
PKG_CHECK_MODULES([LIBTOXAV], [libtoxav],
|
||||
[
|
||||
AC_CHECK_HEADER([tox/toxav.h],
|
||||
[
|
||||
# Place define for audio support
|
||||
AC_DEFINE([_SUPPORT_AUDIO], [], [Is audio supported])
|
||||
AC_MSG_NOTICE([Building with audio support])
|
||||
],
|
||||
[
|
||||
AC_MSG_NOTICE([No A/V headers; disabling A/V support])
|
||||
BUILD_AV="no"
|
||||
],)
|
||||
],
|
||||
[
|
||||
AC_MSG_NOTICE([No openal library; disabling A/V support])
|
||||
AC_MSG_NOTICE([No A/V library; disabling A/V support])
|
||||
BUILD_AV="no"
|
||||
])
|
||||
fi
|
||||
@ -469,7 +499,7 @@ if test "x$NCURSES_WIDECHAR_SUPPORT" = "xyes"; then
|
||||
AC_DEFINE([_XOPEN_SOURCE_EXTENDED], [1],
|
||||
[enable X/Open Portability Guide functionality])
|
||||
fi
|
||||
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
misc/Makefile
|
||||
build/Makefile])
|
||||
|
@ -1,8 +1,8 @@
|
||||
192.254.75.98 33445 951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F
|
||||
2607:5600:284::2 33445 951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F
|
||||
23.226.230.47 33445 A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074
|
||||
173.255.223.85 33445 92E0CE88651FC89D54D6A3110FD08854ECD487613E69BFB1002380D35FD4F947
|
||||
37.187.46.132 33445 A9D98212B3F972BD11DA52BEB0658C326FCCC1BFD49F347F9C2D3D8B61E1B927
|
||||
144.76.60.215 33445 04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F
|
||||
109.169.46.133 33445 4086B340BF2C2C3CC5412BCF673080EF10CF5E75A06AC960497BD85B9DEA2E64
|
||||
54.199.139.199 33445 7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029
|
||||
66.175.223.88 33445 B24E2FB924AE66D023FE1E42A2EE3B432010206F751A2FFD3E297383ACF1572E
|
||||
23.226.230.47 33445 A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074
|
||||
37.187.20.216 33445 4FD54CFD426A338399767E56FD0F44F5E35FA8C38C8E87C8DC3FEAC0160F8E17
|
||||
54.199.139.199 33445 7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029
|
||||
109.169.46.133 33445 7F31BFC93B8E4016A902144D0B110C3EA97CB7D43F1C4D21BCAE998A7C838821
|
||||
192.210.149.121 33445 F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67
|
||||
|
@ -18,3 +18,6 @@ audio_in_dev:0;
|
||||
|
||||
# preferred audio output device; numbers correspond to /lsdev out
|
||||
audio_out_dev:0;
|
||||
|
||||
# preferred path for downloads
|
||||
download_path:/home/USERNAME/Downloads/;
|
@ -1,27 +1,51 @@
|
||||
/*
|
||||
* Toxic -- Tox Curses Client
|
||||
/* audio_call.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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "audio_call.h"
|
||||
#include "chat_commands.h"
|
||||
#include "global_commands.h"
|
||||
#include "toxic_windows.h"
|
||||
#include "line_info.h"
|
||||
|
||||
#include <curses.h>
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <OpenAL/al.h>
|
||||
#include <OpenAL/alc.h>
|
||||
#else
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#endif
|
||||
|
||||
#define _cbend pthread_exit(NULL)
|
||||
|
||||
#define AUDIO_FRAME_SIZE (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000)
|
||||
|
@ -1,5 +1,23 @@
|
||||
/*
|
||||
* Toxic -- Tox Curses Client
|
||||
/* audio_call.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 _audio_h
|
||||
@ -7,6 +25,9 @@
|
||||
|
||||
#include <tox/toxav.h>
|
||||
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
|
||||
#define MAX_DEVICES 32
|
||||
|
||||
typedef enum _AudioError {
|
||||
|
154
src/chat.c
154
src/chat.c
@ -28,7 +28,8 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "execute.h"
|
||||
#include "misc_tools.h"
|
||||
#include "friendlist.h"
|
||||
@ -228,15 +229,21 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
|
||||
if (self->num != num)
|
||||
return;
|
||||
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
uint8_t msg[MAX_STR_SIZE * 2];
|
||||
uint8_t *errmsg;
|
||||
|
||||
pathname[path_len] = '\0';
|
||||
|
||||
uint8_t filename[MAX_STR_SIZE];
|
||||
get_file_name(pathname, filename);
|
||||
|
||||
snprintf(msg, sizeof(msg), "File transfer request for '%s' (%llu bytes).", filename,
|
||||
/* holds the filename appended to the user specified path */
|
||||
uint8_t filename_path[MAX_STR_SIZE] = {0};
|
||||
|
||||
/* holds the lone filename */
|
||||
uint8_t filename_nopath[MAX_STR_SIZE];
|
||||
get_file_name(filename_nopath, pathname);
|
||||
int len = strlen(filename_nopath);
|
||||
|
||||
snprintf(msg, sizeof(msg), "File transfer request for '%s' (%llu bytes).", filename_nopath,
|
||||
(long long unsigned int)filesize);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
|
||||
@ -246,10 +253,28 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
|
||||
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 (len >= sizeof(friends[num].file_receiver.filenames[filenum])) {
|
||||
errmsg = "File name too long; discarding.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t filename[MAX_STR_SIZE];
|
||||
|
||||
if (filename_path[0])
|
||||
strcpy(filename, filename_path);
|
||||
else
|
||||
strcpy(filename, filename_nopath);
|
||||
|
||||
/* Append a number to duplicate file names */
|
||||
FILE *filecheck = NULL;
|
||||
int count = 1;
|
||||
int len = strlen(filename);
|
||||
|
||||
while ((filecheck = fopen(filename, "r"))) {
|
||||
filename[len] = '\0';
|
||||
@ -300,21 +325,28 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
|
||||
|
||||
const uint8_t *filename;
|
||||
uint8_t msg[MAX_STR_SIZE] = {0};
|
||||
int i; /* file_sender index */
|
||||
|
||||
if (receive_send == 0)
|
||||
if (receive_send == 0) {
|
||||
filename = friends[num].file_receiver.filenames[filenum];
|
||||
else
|
||||
filename = file_senders[filenum].pathname;
|
||||
} else {
|
||||
for (i = 0; i < MAX_FILES; ++i) {
|
||||
if (file_senders[i].filenum == filenum)
|
||||
break;
|
||||
}
|
||||
|
||||
filename = file_senders[i].pathname;
|
||||
}
|
||||
|
||||
switch (control_type) {
|
||||
case TOX_FILECONTROL_ACCEPT:
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' accepted (%.1f%%)", filename, 0.0);
|
||||
file_senders[filenum].line_id = self->chatwin->hst->line_end->id + 1;
|
||||
if (receive_send == 1) {
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' accepted (%.1f%%)", filename, 0.0);
|
||||
file_senders[i].line_id = self->chatwin->hst->line_end->id + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/*case TOX_FILECONTROL_PAUSE:
|
||||
wprintw(ctx->history, "File transfer for '%s' paused.\n", filename);
|
||||
break; */
|
||||
case TOX_FILECONTROL_KILL:
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", filename);
|
||||
|
||||
@ -324,8 +356,11 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
|
||||
break;
|
||||
|
||||
case TOX_FILECONTROL_FINISHED:
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename);
|
||||
chat_close_file_receiver(num, filenum);
|
||||
if (receive_send == 0) {
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename);
|
||||
chat_close_file_receiver(num, filenum);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -358,7 +393,7 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu
|
||||
|
||||
const uint8_t *name = friends[num].file_receiver.filenames[filenum];
|
||||
snprintf(msg, sizeof(msg), "Saving file as: '%s' (%.1Lf%%)", name, pct_remain);
|
||||
line_info_set(self, friends[num].file_receiver.line_id, msg);
|
||||
line_info_set(self, friends[num].file_receiver.line_id[filenum], msg);
|
||||
|
||||
}
|
||||
|
||||
@ -374,8 +409,9 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, ui
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
name[n_len] = '\0';
|
||||
|
||||
snprintf(msg, sizeof(msg), "%s has invited you to a group chat.\n"
|
||||
"Type \"/join\" to join the chat.", name);
|
||||
snprintf(msg, sizeof(msg), "%s has invited you to a group chat.", name);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
snprintf(msg, sizeof(msg), "Type \"/join\" to join the chat.", name);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
|
||||
memcpy(friends[friendnumber].pending_groupchat, group_pub_key, TOX_CLIENT_ID_SIZE);
|
||||
@ -394,7 +430,7 @@ void chat_onInvite (ToxWindow *self, ToxAv *av, int call_index)
|
||||
|
||||
self->call_index = call_index;
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, "Incoming audio call!\nType: \"/answer\" or \"/reject\"", SYS_MSG, 0, 0);
|
||||
line_info_add(self, NULL, NULL, NULL, "Incoming audio call! Type: \"/answer\" or \"/reject\"", SYS_MSG, 0, 0);
|
||||
|
||||
alert_window(self, WINDOW_ALERT_0, true);
|
||||
}
|
||||
@ -404,7 +440,7 @@ void chat_onRinging (ToxWindow *self, ToxAv *av, int call_index)
|
||||
if ( self->call_index != call_index || self->num != toxav_get_peer_id(av, call_index, 0))
|
||||
return;
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, "Ringing...\n\"cancel\" ?", SYS_MSG, 0, 0);
|
||||
line_info_add(self, NULL, NULL, NULL, "Ringing...\"cancel\" ?", SYS_MSG, 0, 0);
|
||||
}
|
||||
|
||||
void chat_onStarting (ToxWindow *self, ToxAv *av, int call_index)
|
||||
@ -412,7 +448,7 @@ void chat_onStarting (ToxWindow *self, ToxAv *av, int call_index)
|
||||
if ( self->call_index != call_index || self->num != toxav_get_peer_id(av, call_index, 0))
|
||||
return;
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, "Call started!\nType: \"/hangup\" to end it.", SYS_MSG, 0, 0);
|
||||
line_info_add(self, NULL, NULL, NULL, "Call started! Type: \"/hangup\" to end it.", SYS_MSG, 0, 0);
|
||||
}
|
||||
|
||||
void chat_onEnding (ToxWindow *self, ToxAv *av, int call_index)
|
||||
@ -436,7 +472,7 @@ void chat_onStart (ToxWindow *self, ToxAv *av, int call_index)
|
||||
if ( self->call_index != call_index || self->num != toxav_get_peer_id(av, call_index, 0))
|
||||
return;
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, "Call started!\nType: \"/hangup\" to end it.", SYS_MSG, 0, 0);
|
||||
line_info_add(self, NULL, NULL, NULL, "Call started! Type: \"/hangup\" to end it.", SYS_MSG, 0, 0);
|
||||
}
|
||||
|
||||
void chat_onCancel (ToxWindow *self, ToxAv *av, int call_index)
|
||||
@ -513,21 +549,10 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
getmaxyx(self->window, y2, x2);
|
||||
int cur_len = 0;
|
||||
|
||||
if (!ltr && (key == T_KEY_ESC)) { /* ESC key: Toggle history scroll mode */
|
||||
bool scroll = ctx->hst->scroll_mode ? false : true;
|
||||
line_info_toggle_scroll(self, scroll);
|
||||
}
|
||||
|
||||
/* If we're in scroll mode ignore rest of function */
|
||||
if (ctx->hst->scroll_mode) {
|
||||
line_info_onKey(self, key);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ltr) {
|
||||
/* prevents buffer overflows and strange behaviour when cursor goes past the window */
|
||||
if ( (ctx->len < MAX_STR_SIZE - 1) && (ctx->len < (x2 * (CHATBOX_HEIGHT - 1) - 1)) ) {
|
||||
add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key);
|
||||
add_char_to_buf(ctx, key);
|
||||
|
||||
if (x == x2 - 1)
|
||||
wmove(self->window, y + 1, 0);
|
||||
@ -539,11 +564,13 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
set_typingstatus(self, m, 1);
|
||||
|
||||
} else { /* if (!ltr) */
|
||||
if (line_info_onKey(self, key))
|
||||
return;
|
||||
|
||||
if (key == 0x107 || key == 0x8 || key == 0x7f) { /* BACKSPACE key */
|
||||
if (ctx->pos > 0) {
|
||||
cur_len = MAX(1, wcwidth(ctx->line[ctx->pos - 1]));
|
||||
del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
|
||||
del_char_buf_bck(ctx);
|
||||
|
||||
if (x == 0)
|
||||
wmove(self->window, y - 1, x2 - cur_len);
|
||||
@ -556,14 +583,14 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
else if (key == KEY_DC) { /* DEL key: Remove character at pos */
|
||||
if (ctx->pos != ctx->len)
|
||||
del_char_buf_frnt(ctx->line, &ctx->pos, &ctx->len);
|
||||
del_char_buf_frnt(ctx);
|
||||
else
|
||||
beep();
|
||||
}
|
||||
|
||||
else if (key == T_KEY_DISCARD) { /* CTRL-U: Delete entire line behind pos */
|
||||
if (ctx->pos > 0) {
|
||||
discard_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
discard_buf(ctx);
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
} else {
|
||||
beep();
|
||||
@ -572,7 +599,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
else if (key == T_KEY_KILL) { /* CTRL-K: Delete entire line in front of pos */
|
||||
if (ctx->pos != ctx->len)
|
||||
kill_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
kill_buf(ctx);
|
||||
else
|
||||
beep();
|
||||
}
|
||||
@ -620,21 +647,18 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
}
|
||||
|
||||
else if (key == KEY_UP) { /* fetches previous item in history */
|
||||
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
||||
&ctx->hst_pos, MOVE_UP);
|
||||
fetch_hist_item(ctx, MOVE_UP);
|
||||
mv_curs_end(self->window, ctx->len, y2, x2);
|
||||
}
|
||||
|
||||
else if (key == KEY_DOWN) { /* fetches next item in history */
|
||||
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
||||
&ctx->hst_pos, MOVE_DOWN);
|
||||
fetch_hist_item(ctx, MOVE_DOWN);
|
||||
mv_curs_end(self->window, ctx->len, y2, x2);
|
||||
}
|
||||
|
||||
else if (key == '\t') { /* TAB key: completes command */
|
||||
if (ctx->len > 1 && ctx->line[0] == '/') {
|
||||
int diff = complete_line(ctx->line, &ctx->pos, &ctx->len, chat_cmd_list, AC_NUM_CHAT_COMMANDS,
|
||||
MAX_CMDNAME_SIZE);
|
||||
int diff = complete_line(ctx, chat_cmd_list, AC_NUM_CHAT_COMMANDS, MAX_CMDNAME_SIZE);
|
||||
|
||||
if (diff != -1) {
|
||||
if (x + diff > x2 - 1) {
|
||||
@ -653,6 +677,8 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
/* RETURN key: Execute command or print line */
|
||||
else if (key == '\n') {
|
||||
rm_trailing_spaces_buf(ctx);
|
||||
|
||||
uint8_t line[MAX_STR_SIZE];
|
||||
|
||||
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
|
||||
@ -662,7 +688,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
|
||||
if (!string_is_empty(line))
|
||||
add_line_to_hist(ctx->line, ctx->len, ctx->ln_history, &ctx->hst_tot, &ctx->hst_pos);
|
||||
add_line_to_hist(ctx);
|
||||
|
||||
if (line[0] == '/') {
|
||||
if (strcmp(line, "/close") == 0) {
|
||||
@ -694,7 +720,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
}
|
||||
}
|
||||
|
||||
reset_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
reset_buf(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -712,21 +738,17 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
|
||||
line_info_print(self);
|
||||
wclear(ctx->linewin);
|
||||
|
||||
if (ctx->hst->scroll_mode) {
|
||||
line_info_onDraw(self);
|
||||
} else {
|
||||
curs_set(1);
|
||||
scrollok(ctx->history, 1);
|
||||
curs_set(1);
|
||||
scrollok(ctx->history, 0);
|
||||
|
||||
if (ctx->len > 0 && !ctx->hst->scroll_mode) {
|
||||
uint8_t line[MAX_STR_SIZE];
|
||||
if (ctx->len> 0) {
|
||||
uint8_t line[MAX_STR_SIZE];
|
||||
|
||||
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) {
|
||||
reset_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
} else {
|
||||
mvwprintw(ctx->linewin, 1, 0, "%s", line);
|
||||
}
|
||||
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) {
|
||||
reset_buf(ctx);
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
} else {
|
||||
mvwprintw(ctx->linewin, 1, 0, "%s", line);
|
||||
}
|
||||
}
|
||||
|
||||
@ -847,17 +869,13 @@ static void chat_onInit(ToxWindow *self, Tox *m)
|
||||
|
||||
statusbar->topline = subwin(self->window, 2, x2, 0, 0);
|
||||
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, x2, 0, 0);
|
||||
scrollok(ctx->history, 1);
|
||||
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2 - CHATBOX_HEIGHT, 0);
|
||||
|
||||
ctx->hst = malloc(sizeof(struct history));
|
||||
ctx->log = malloc(sizeof(struct chatlog));
|
||||
|
||||
if (ctx->log == NULL || ctx->hst == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (ctx->log == NULL || ctx->hst == NULL)
|
||||
exit_toxic_err("failed in chat_onInit", FATALERR_MEMORY);
|
||||
|
||||
memset(ctx->hst, 0, sizeof(struct history));
|
||||
memset(ctx->log, 0, sizeof(struct chatlog));
|
||||
@ -930,9 +948,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
|
||||
ret.chatwin = chatwin;
|
||||
ret.stb = stb;
|
||||
} else {
|
||||
endwin();
|
||||
fprintf(stderr, "calloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
exit_toxic_err("failed in new_chat", FATALERR_MEMORY);
|
||||
}
|
||||
|
||||
ret.num = friendnum;
|
||||
|
@ -23,7 +23,8 @@
|
||||
#ifndef CHAT_H_6489PZ13
|
||||
#define CHAT_H_6489PZ13
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "windows.h"
|
||||
#include "toxic.h"
|
||||
|
||||
void kill_chat_window(ToxWindow *self);
|
||||
ToxWindow new_chat(Tox *m, int32_t friendnum);
|
||||
|
@ -27,7 +27,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "misc_tools.h"
|
||||
#include "friendlist.h"
|
||||
#include "execute.h"
|
||||
@ -86,7 +87,7 @@ void cmd_chat_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
|
||||
for (i = 0; i < NUMLINES; ++i)
|
||||
line_info_add(self, NULL, NULL, NULL, lines[i], SYS_MSG, 0, 0);
|
||||
|
||||
msg = " * Use ESC key to toggle history scroll mode\n";
|
||||
msg = " * Use Page Up/Page Down to scroll chat history\n";
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
|
||||
|
||||
hst->line_start = start;
|
||||
@ -185,7 +186,7 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
snprintf(msg, sizeof(msg), "Saving file as: '%s' (%.1f%%)", filename, 0.0);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
friends[self->num].file_receiver.line_id = self->chatwin->hst->line_end->id;
|
||||
friends[self->num].file_receiver.line_id[filenum] = self->chatwin->hst->line_end->id + 1;
|
||||
|
||||
if ((friends[self->num].file_receiver.files[filenum] = fopen(filename, "a")) == NULL) {
|
||||
errmsg = "* Error writing to file.";
|
||||
@ -246,7 +247,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
fseek(file_to_send, 0, SEEK_SET);
|
||||
|
||||
uint8_t filename[MAX_STR_SIZE];
|
||||
get_file_name(path, filename);
|
||||
get_file_name(filename, path);
|
||||
int filenum = tox_new_file_sender(m, self->num, filesize, filename, strlen(filename));
|
||||
|
||||
if (filenum == -1) {
|
||||
|
@ -20,6 +20,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _chat_commands_h
|
||||
#define _chat_commands_h
|
||||
|
||||
#include "windows.h"
|
||||
#include "toxic.h"
|
||||
|
||||
void cmd_chat_help(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_groupinvite(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_join_group(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
@ -34,3 +40,5 @@ void cmd_reject(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZ
|
||||
void cmd_hangup(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_cancel(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
#endif /* #define _chat_commands_h */
|
||||
|
@ -30,14 +30,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <shlobj.h>
|
||||
#include <direct.h>
|
||||
#else /* WIN32 */
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#endif /* WIN32 */
|
||||
|
||||
#include "configdir.h"
|
||||
|
||||
@ -51,25 +45,6 @@
|
||||
char *get_user_config_dir(void)
|
||||
{
|
||||
char *user_config_dir;
|
||||
#ifdef _WIN32
|
||||
#warning Please fix configdir for Win32
|
||||
return NULL;
|
||||
#if 0
|
||||
char appdata[MAX_PATH];
|
||||
BOOL ok;
|
||||
|
||||
ok = SHGetSpecialFolderPathA(NULL, appdata, CSIDL_PROFILE, TRUE);
|
||||
|
||||
if (!ok) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
user_config_dir = strdup(appdata);
|
||||
|
||||
return user_config_dir;
|
||||
#endif
|
||||
|
||||
#else /* WIN32 */
|
||||
|
||||
#ifndef NSS_BUFLEN_PASSWD
|
||||
#define NSS_BUFLEN_PASSWD 4096
|
||||
@ -128,7 +103,6 @@ char *get_user_config_dir(void)
|
||||
|
||||
return user_config_dir;
|
||||
#undef NSS_BUFLEN_PASSWD
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -136,26 +110,6 @@ char *get_user_config_dir(void)
|
||||
*/
|
||||
int create_user_config_dir(char *path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#warning Please fix configdir for Win32
|
||||
return -1;
|
||||
#if 0
|
||||
char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1);
|
||||
strcpy(fullpath, path);
|
||||
strcat(fullpath, CONFIGDIR);
|
||||
|
||||
mkdir_err = _mkdir(fullpath);
|
||||
struct __stat64 buf;
|
||||
|
||||
if (mkdir_err && (errno != EEXIST || _wstat64(fullpath, &buf) || !S_ISDIR(buf.st_mode))) {
|
||||
free(fullpath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(fullpath);
|
||||
#endif
|
||||
|
||||
#else
|
||||
int mkdir_err;
|
||||
|
||||
mkdir_err = mkdir(path, 0700);
|
||||
@ -178,5 +132,4 @@ int create_user_config_dir(char *path)
|
||||
|
||||
free(fullpath);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
@ -20,11 +20,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef _win32
|
||||
#define CONFIGDIR "\\tox\\"
|
||||
#else
|
||||
#ifndef _configdir_h
|
||||
#define _configdir_h
|
||||
|
||||
#define CONFIGDIR "/tox/"
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
@ -33,3 +32,5 @@
|
||||
char *get_user_config_dir(void);
|
||||
|
||||
int create_user_config_dir(char *path);
|
||||
|
||||
#endif /* #define _configdir_h */
|
||||
|
304
src/dns.c
Normal file
304
src/dns.c
Normal file
@ -0,0 +1,304 @@
|
||||
/* dns.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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
|
||||
#include <tox/toxdns.h>
|
||||
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "line_info.h"
|
||||
#include "dns.h"
|
||||
#include "global_commands.h"
|
||||
#include "misc_tools.h"
|
||||
|
||||
#define MAX_DNS_REQST_SIZE 256
|
||||
#define NUM_DNS3_SERVERS 2 /* must correspond to number of items in dns3_servers array */
|
||||
#define TOX_DNS3_TXT_PREFIX "v=tox3;id="
|
||||
#define DNS3_KEY_SZ 32
|
||||
|
||||
/* TODO: process keys from key file instead of hard-coding like a noob */
|
||||
static struct dns3_server {
|
||||
uint8_t *name;
|
||||
uint8_t key[DNS3_KEY_SZ];
|
||||
} dns3_servers[] = {
|
||||
{
|
||||
"utox.org",
|
||||
{
|
||||
0xD3, 0x15, 0x4F, 0x65, 0xD2, 0x8A, 0x5B, 0x41, 0xA0, 0x5D, 0x4A, 0xC7, 0xE4, 0xB3, 0x9C, 0x6B,
|
||||
0x1C, 0x23, 0x3C, 0xC8, 0x57, 0xFB, 0x36, 0x5C, 0x56, 0xE8, 0x39, 0x27, 0x37, 0x46, 0x2A, 0x12
|
||||
}
|
||||
},
|
||||
{
|
||||
"toxme.se",
|
||||
{
|
||||
0x5D, 0x72, 0xC5, 0x17, 0xDF, 0x6A, 0xEC, 0x54, 0xF1, 0xE9, 0x77, 0xA6, 0xB6, 0xF2, 0x59, 0x14,
|
||||
0xEA, 0x4C, 0xF7, 0x27, 0x7A, 0x85, 0x02, 0x7C, 0xD9, 0xF5, 0x19, 0x6D, 0xF1, 0x7E, 0x0B, 0x13
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static struct _thread_data {
|
||||
ToxWindow *self;
|
||||
uint8_t id_bin[TOX_FRIEND_ADDRESS_SIZE];
|
||||
uint8_t addr[MAX_STR_SIZE];
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
uint8_t busy;
|
||||
Tox *m;
|
||||
} t_data;
|
||||
|
||||
static struct _dns_thread {
|
||||
pthread_t tid;
|
||||
pthread_mutex_t lock;
|
||||
} dns_thread;
|
||||
|
||||
static int dns_error(ToxWindow *self, uint8_t *errmsg)
|
||||
{
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
snprintf(msg, sizeof(msg), "DNS lookup failed: %s", errmsg);
|
||||
|
||||
pthread_mutex_lock(&dns_thread.lock);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
pthread_mutex_unlock(&dns_thread.lock);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void kill_dns_thread(void *dns_obj)
|
||||
{
|
||||
if (dns_obj)
|
||||
tox_dns3_kill(dns_obj);
|
||||
|
||||
memset(&t_data, 0, sizeof(struct _thread_data));
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
/* puts TXT from dns response in buf. Returns length of TXT on success, -1 on fail.*/
|
||||
static int parse_dns_response(ToxWindow *self, u_char *answer, int ans_len, uint8_t *buf)
|
||||
{
|
||||
uint8_t *ans_pt = answer + sizeof(HEADER);
|
||||
uint8_t *ans_end = answer + ans_len;
|
||||
uint8_t exp_ans[PACKETSZ];
|
||||
|
||||
int len = dn_expand(answer, ans_end, ans_pt, exp_ans, sizeof(exp_ans));
|
||||
|
||||
if (len == -1)
|
||||
return dns_error(self, "dn_expand failed.");
|
||||
|
||||
ans_pt += len;
|
||||
|
||||
if (ans_pt > ans_end - 4)
|
||||
return dns_error(self, "Reply was too short.");
|
||||
|
||||
int type;
|
||||
GETSHORT(type, ans_pt);
|
||||
|
||||
if (type != T_TXT)
|
||||
return dns_error(self, "Broken reply.");
|
||||
|
||||
|
||||
ans_pt += INT16SZ; /* class */
|
||||
uint32_t size = 0;
|
||||
|
||||
/* recurse through CNAME rr's */
|
||||
do {
|
||||
ans_pt += size;
|
||||
len = dn_expand(answer, ans_end, ans_pt, exp_ans, sizeof(exp_ans));
|
||||
|
||||
if (len == -1)
|
||||
return dns_error(self, "Second dn_expand failed.");
|
||||
|
||||
ans_pt += len;
|
||||
|
||||
if (ans_pt > ans_end - 10)
|
||||
return dns_error(self, "Reply was too short.");
|
||||
|
||||
GETSHORT(type, ans_pt);
|
||||
ans_pt += INT16SZ;
|
||||
ans_pt += 4;
|
||||
GETSHORT(size, ans_pt);
|
||||
|
||||
if (ans_pt + size < answer || ans_pt + size > ans_end)
|
||||
return dns_error(self, "RR overflow.");
|
||||
|
||||
} while (type == T_CNAME);
|
||||
|
||||
if (type != T_TXT)
|
||||
return dns_error(self, "Not a TXT record.");
|
||||
|
||||
uint32_t txt_len = *ans_pt;
|
||||
|
||||
if (!size || txt_len >= size || !txt_len)
|
||||
return dns_error(self, "No record found.");
|
||||
|
||||
ans_pt++;
|
||||
ans_pt[txt_len] = '\0';
|
||||
memcpy(buf, ans_pt, txt_len + 1);
|
||||
|
||||
return txt_len;
|
||||
}
|
||||
|
||||
/* Takes address addr in the form "username@domain", puts the username in namebuf,
|
||||
and the domain in dombuf.
|
||||
|
||||
return length of username on success, -1 on failure */
|
||||
static int parse_addr(uint8_t *addr, uint8_t *namebuf, uint8_t *dombuf)
|
||||
{
|
||||
uint8_t tmpaddr[MAX_STR_SIZE];
|
||||
uint8_t *tmpname, *tmpdom;
|
||||
|
||||
strcpy(tmpaddr, addr);
|
||||
tmpname = strtok(tmpaddr, "@");
|
||||
tmpdom = strtok(NULL, "");
|
||||
|
||||
if (tmpname == NULL || tmpdom == NULL)
|
||||
return -1;
|
||||
|
||||
str_to_lower(tmpdom);
|
||||
strcpy(namebuf, tmpname);
|
||||
strcpy(dombuf, tmpdom);
|
||||
|
||||
return strlen(namebuf);
|
||||
}
|
||||
|
||||
/* Does DNS lookup for addr and puts resulting tox id in id_bin. */
|
||||
void *dns3_lookup_thread(void *data)
|
||||
{
|
||||
ToxWindow *self = t_data.self;
|
||||
|
||||
uint8_t domain[MAX_STR_SIZE];
|
||||
uint8_t name[MAX_STR_SIZE];
|
||||
|
||||
int namelen = parse_addr(t_data.addr, name, domain);
|
||||
|
||||
if (namelen == -1) {
|
||||
dns_error(self, "Must be a Tox ID or an address in the form username@domain");
|
||||
kill_dns_thread(NULL);
|
||||
}
|
||||
|
||||
/* get domain name/pub key */
|
||||
uint8_t *DNS_pubkey, *domname = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_DNS3_SERVERS; ++i) {
|
||||
if (strcmp(dns3_servers[i].name, domain) == 0) {
|
||||
DNS_pubkey = dns3_servers[i].key;
|
||||
domname = dns3_servers[i].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (domname == NULL) {
|
||||
dns_error(self, "Domain not found.");
|
||||
kill_dns_thread(NULL);
|
||||
}
|
||||
|
||||
void *dns_obj = tox_dns3_new(DNS_pubkey);
|
||||
|
||||
if (dns_obj == NULL) {
|
||||
dns_error(self, "Core failed to create DNS object.");
|
||||
kill_dns_thread(NULL);
|
||||
}
|
||||
|
||||
uint8_t string[MAX_DNS_REQST_SIZE];
|
||||
uint32_t request_id;
|
||||
|
||||
int str_len = tox_generate_dns3_string(dns_obj, string, sizeof(string), &request_id, name, namelen);
|
||||
|
||||
if (str_len == -1) {
|
||||
dns_error(self, "Core failed to generate dns3 string.");
|
||||
kill_dns_thread(dns_obj);
|
||||
}
|
||||
|
||||
string[str_len] = '\0';
|
||||
|
||||
u_char answer[PACKETSZ];
|
||||
uint8_t d_string[MAX_DNS_REQST_SIZE];
|
||||
|
||||
/* format string and create dns query */
|
||||
snprintf(d_string, sizeof(d_string), "_%s._tox.%s", string, domname);
|
||||
int ans_len = res_query(d_string, C_IN, T_TXT, answer, sizeof(answer));
|
||||
|
||||
if (ans_len <= 0) {
|
||||
dns_error(self, "Query failed.");
|
||||
kill_dns_thread(dns_obj);
|
||||
}
|
||||
|
||||
uint8_t ans_id[MAX_DNS_REQST_SIZE];
|
||||
|
||||
/* extract TXT from DNS response */
|
||||
if (parse_dns_response(self, answer, ans_len, ans_id) == -1)
|
||||
kill_dns_thread(dns_obj);
|
||||
|
||||
uint8_t encrypted_id[MAX_DNS_REQST_SIZE];
|
||||
int prfx_len = strlen(TOX_DNS3_TXT_PREFIX);
|
||||
|
||||
/* extract the encrypted ID from TXT response */
|
||||
if (strncmp(ans_id, TOX_DNS3_TXT_PREFIX, prfx_len) != 0) {
|
||||
dns_error(self, "Bad dns3 TXT response.");
|
||||
kill_dns_thread(dns_obj);
|
||||
}
|
||||
|
||||
memcpy(encrypted_id, ans_id + prfx_len, ans_len - prfx_len);
|
||||
|
||||
if (tox_decrypt_dns3_TXT(dns_obj, t_data.id_bin, encrypted_id, strlen(encrypted_id), request_id) == -1) {
|
||||
dns_error(self, "Core failed to decrypt response.");
|
||||
kill_dns_thread(dns_obj);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&dns_thread.lock);
|
||||
cmd_add_helper(self, t_data.m, t_data.id_bin, t_data.msg);
|
||||
pthread_mutex_unlock(&dns_thread.lock);
|
||||
|
||||
kill_dns_thread(dns_obj);
|
||||
}
|
||||
|
||||
/* creates new thread for dns3 lookup. Only allows one lookup at a time. */
|
||||
void dns3_lookup(ToxWindow *self, Tox *m, uint8_t *id_bin, uint8_t *addr, uint8_t *msg)
|
||||
{
|
||||
if (t_data.busy) {
|
||||
uint8_t *err = "Please wait for previous user lookup to finish.";
|
||||
line_info_add(self, NULL, NULL, NULL, err, SYS_MSG, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
t_data.self = self;
|
||||
snprintf(t_data.id_bin, sizeof(t_data.id_bin), "%s", id_bin);
|
||||
snprintf(t_data.addr, sizeof(t_data.addr), "%s", addr);
|
||||
snprintf(t_data.msg, sizeof(t_data.msg), "%s", msg);
|
||||
t_data.m = m;
|
||||
t_data.busy = 1;
|
||||
|
||||
if (pthread_create(&dns_thread.tid, NULL, dns3_lookup_thread, NULL) != 0)
|
||||
exit_toxic_err("failed in dns3_lookup", FATALERR_THREAD_CREATE);
|
||||
|
||||
if (pthread_mutex_init(&dns_thread.lock, NULL) != 0)
|
||||
exit_toxic_err("failed in dns3_lookup", FATALERR_MUTEX_INIT);
|
||||
}
|
32
src/dns.h
Normal file
32
src/dns.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* dns.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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* 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
|
||||
|
||||
/* creates new thread for dns3 lookup. Only allows one lookup at a time. */
|
||||
void dns3_lookup(ToxWindow *self, Tox *m, uint8_t *id_bin, uint8_t *addr, uint8_t *msg);
|
||||
|
||||
#endif /* #define _dns_h */
|
@ -28,7 +28,8 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "execute.h"
|
||||
#include "chat_commands.h"
|
||||
#include "global_commands.h"
|
||||
@ -54,6 +55,7 @@ static struct cmd_func global_commands[] = {
|
||||
{ "/q", cmd_quit },
|
||||
{ "/quit", cmd_quit },
|
||||
{ "/status", cmd_status },
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
{ "/lsdev", cmd_list_devices },
|
||||
{ "/sdev", cmd_change_device },
|
||||
|
@ -20,6 +20,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _execute_h
|
||||
#define _execute_h
|
||||
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
|
||||
#define MAX_NUM_ARGS 4 /* Includes command */
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
@ -37,3 +43,5 @@ enum {
|
||||
};
|
||||
|
||||
void execute(WINDOW *w, ToxWindow *self, Tox *m, char *cmd, int mode);
|
||||
|
||||
#endif /* #define _execute_h */
|
||||
|
@ -28,7 +28,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "file_senders.h"
|
||||
#include "line_info.h"
|
||||
|
||||
FileSender file_senders[MAX_FILES];
|
||||
@ -107,9 +109,9 @@ void do_file_senders(Tox *m)
|
||||
if (remain)
|
||||
pct_remain = (1 - (remain / size)) * 100;
|
||||
|
||||
const uint8_t *name = file_senders[filenum].pathname;
|
||||
const uint8_t *name = file_senders[i].pathname;
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' accepted (%.1Lf%%)", name, pct_remain);
|
||||
line_info_set(self, file_senders[filenum].line_id, msg);
|
||||
line_info_set(self, file_senders[i].line_id, msg);
|
||||
}
|
||||
|
||||
if (file_senders[i].piecelen == 0) {
|
||||
|
@ -20,7 +20,33 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _filesenders_h
|
||||
#define _filesenders_h
|
||||
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
|
||||
#define FILE_PIECE_SIZE 2048 /* must be >= (MAX_CRYPTO_DATA_SIZE - 2) in toxcore/net_crypto.h */
|
||||
#define MAX_FILES 256
|
||||
#define TIMEOUT_FILESENDER 300
|
||||
|
||||
typedef struct {
|
||||
FILE *file;
|
||||
ToxWindow *toxwin;
|
||||
int32_t friendnum;
|
||||
bool active;
|
||||
int filenum;
|
||||
uint8_t nextpiece[FILE_PIECE_SIZE];
|
||||
uint16_t piecelen;
|
||||
uint8_t pathname[MAX_STR_SIZE];
|
||||
uint64_t timestamp;
|
||||
uint64_t size;
|
||||
uint32_t line_id;
|
||||
} FileSender;
|
||||
|
||||
/* Should only be called on exit */
|
||||
void close_all_file_senders(void);
|
||||
|
||||
void do_file_senders(Tox *m);
|
||||
|
||||
#endif /* #define _filesenders_h */
|
||||
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include <tox/tox.h>
|
||||
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "chat.h"
|
||||
#include "friendlist.h"
|
||||
#include "misc_tools.h"
|
||||
@ -54,7 +56,7 @@ extern struct user_settings *user_settings;
|
||||
ToxicFriend friends[MAX_FRIENDS_NUM];
|
||||
static int friendlist_index[MAX_FRIENDS_NUM] = {0};
|
||||
|
||||
struct _pendingDel {
|
||||
static struct _pendingDel {
|
||||
int num;
|
||||
bool active;
|
||||
} pendingdelete;
|
||||
|
@ -24,10 +24,21 @@
|
||||
#define FRIENDLIST_H_53I41IM
|
||||
|
||||
#include <time.h>
|
||||
#include "toxic_windows.h"
|
||||
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "file_senders.h"
|
||||
|
||||
#define TIME_STR_SIZE 16
|
||||
|
||||
struct FileReceiver {
|
||||
uint8_t filenames[MAX_FILES][MAX_STR_SIZE];
|
||||
FILE *files[MAX_FILES];
|
||||
bool pending[MAX_FILES];
|
||||
uint64_t size[MAX_FILES];
|
||||
uint32_t line_id[MAX_FILES];
|
||||
};
|
||||
|
||||
struct LastOnline {
|
||||
uint64_t last_on;
|
||||
struct tm tm;
|
||||
|
@ -27,11 +27,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "misc_tools.h"
|
||||
#include "friendlist.h"
|
||||
#include "log.h"
|
||||
#include "line_info.h"
|
||||
#include "dns.h"
|
||||
|
||||
extern char *DATA_FILE;
|
||||
extern ToxWindow *prompt;
|
||||
@ -88,6 +90,49 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
}
|
||||
|
||||
void cmd_add_helper(ToxWindow *self, Tox *m, uint8_t *id_bin, uint8_t *msg)
|
||||
{
|
||||
uint8_t *errmsg;
|
||||
int32_t f_num = tox_add_friend(m, id_bin, msg, strlen(msg));
|
||||
|
||||
switch (f_num) {
|
||||
case TOX_FAERR_TOOLONG:
|
||||
errmsg = "Message is too long.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_NOMESSAGE:
|
||||
errmsg = "Please add a message to your request.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_OWNKEY:
|
||||
errmsg = "That appears to be your own ID.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_ALREADYSENT:
|
||||
errmsg = "Friend request has already been sent.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_UNKNOWN:
|
||||
errmsg = "Undefined error when adding friend.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_BADCHECKSUM:
|
||||
errmsg = "Bad checksum in address.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_SETNEWNOSPAM:
|
||||
errmsg = "Nospam was different.";
|
||||
break;
|
||||
|
||||
default:
|
||||
errmsg = "Friend request sent.";
|
||||
on_friendadded(m, f_num, true);
|
||||
break;
|
||||
}
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
}
|
||||
|
||||
void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
uint8_t *errmsg;
|
||||
@ -119,73 +164,33 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
|
||||
snprintf(msg, sizeof(msg), "Hello, my name is %s. Care to Tox?", selfname);
|
||||
}
|
||||
|
||||
if (strlen(id) != 2 * TOX_FRIEND_ADDRESS_SIZE) {
|
||||
errmsg = "Invalid ID length.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
}
|
||||
uint8_t id_bin[TOX_FRIEND_ADDRESS_SIZE] = {0};
|
||||
uint16_t id_len = strlen(id);
|
||||
|
||||
size_t i;
|
||||
char xx[3];
|
||||
uint32_t x;
|
||||
uint8_t id_bin[TOX_FRIEND_ADDRESS_SIZE];
|
||||
/* try to add tox ID */
|
||||
if (id_len == 2 * TOX_FRIEND_ADDRESS_SIZE) {
|
||||
size_t i;
|
||||
char xx[3];
|
||||
uint32_t x;
|
||||
|
||||
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) {
|
||||
xx[0] = id[2 * i];
|
||||
xx[1] = id[2 * i + 1];
|
||||
xx[2] = '\0';
|
||||
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) {
|
||||
xx[0] = id[2 * i];
|
||||
xx[1] = id[2 * i + 1];
|
||||
xx[2] = '\0';
|
||||
|
||||
if (sscanf(xx, "%02x", &x) != 1) {
|
||||
errmsg = "Invalid ID.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
if (sscanf(xx, "%02x", &x) != 1) {
|
||||
errmsg = "Invalid ID.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
id_bin[i] = x;
|
||||
}
|
||||
|
||||
id_bin[i] = x;
|
||||
cmd_add_helper(self, m, id_bin, msg);
|
||||
} else { /* assume id is a username@domain address and do DNS lookup */
|
||||
dns3_lookup(self, m, id_bin, id, msg);
|
||||
}
|
||||
|
||||
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) {
|
||||
id[i] = toupper(id[i]);
|
||||
}
|
||||
|
||||
int32_t f_num = tox_add_friend(m, id_bin, msg, strlen(msg));
|
||||
|
||||
switch (f_num) {
|
||||
case TOX_FAERR_TOOLONG:
|
||||
errmsg = "Message is too long.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_NOMESSAGE:
|
||||
errmsg = "Please add a message to your request.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_OWNKEY:
|
||||
errmsg = "That appears to be your own ID.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_ALREADYSENT:
|
||||
errmsg = "Friend request has already been sent.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_UNKNOWN:
|
||||
errmsg = "Undefined error when adding friend.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_BADCHECKSUM:
|
||||
errmsg = "Bad checksum in address.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_SETNEWNOSPAM:
|
||||
errmsg = "Nospam was different (is this contact already added?";
|
||||
break;
|
||||
|
||||
default:
|
||||
errmsg = "Friend request sent.";
|
||||
on_friendadded(m, f_num, true);
|
||||
break;
|
||||
}
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
}
|
||||
|
||||
void cmd_clear(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
@ -422,16 +427,18 @@ void cmd_prompt_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
|
||||
for (i = 0; i < NUMLINES; ++i)
|
||||
line_info_add(self, NULL, NULL, NULL, lines[i], SYS_MSG, 0, 0);
|
||||
|
||||
msg = " * Argument messages must be enclosed in quotation marks.\n"
|
||||
" * Use ctrl-o and ctrl-p to navigate through the tabs.\n";
|
||||
msg = " * Argument messages must be enclosed in quotation marks.";
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
|
||||
msg = " * Use ctrl-o and ctrl-p to navigate through the tabs.";
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
|
||||
line_info_add(self, NULL, NULL, NULL, "", SYS_MSG, 0, 0);
|
||||
|
||||
hst->line_start = start;
|
||||
}
|
||||
|
||||
void cmd_quit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
exit_toxic(m);
|
||||
exit_toxic_success(m);
|
||||
}
|
||||
|
||||
void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
@ -454,20 +461,16 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
}
|
||||
|
||||
char *status = argv[1];
|
||||
str_to_lower(status);
|
||||
int len = strlen(status);
|
||||
char l_status[len + 1];
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= len; ++i)
|
||||
l_status[i] = tolower(status[i]);
|
||||
|
||||
TOX_USERSTATUS status_kind;
|
||||
|
||||
if (!strcmp(l_status, "online"))
|
||||
if (!strcmp(status, "online"))
|
||||
status_kind = TOX_USERSTATUS_NONE;
|
||||
else if (!strcmp(l_status, "away"))
|
||||
else if (!strcmp(status, "away"))
|
||||
status_kind = TOX_USERSTATUS_AWAY;
|
||||
else if (!strcmp(l_status, "busy"))
|
||||
else if (!strcmp(status, "busy"))
|
||||
status_kind = TOX_USERSTATUS_BUSY;
|
||||
else {
|
||||
errmsg = "Invalid status. Valid statuses are: online, busy and away.";
|
||||
|
@ -20,6 +20,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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_clear(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
@ -33,7 +39,11 @@ void cmd_prompt_help(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_ST
|
||||
void cmd_quit(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_status(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
|
||||
void cmd_add_helper(ToxWindow *self, Tox *m, uint8_t *id_bin, uint8_t *msg);
|
||||
|
||||
#ifdef _SUPPORT_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 /* _SUPPORT_AUDIO */
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
#endif /* #define _global_commands_h */
|
||||
|
117
src/groupchat.c
117
src/groupchat.c
@ -28,7 +28,8 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "windows.h"
|
||||
#include "toxic.h"
|
||||
#include "execute.h"
|
||||
#include "misc_tools.h"
|
||||
#include "groupchat.h"
|
||||
@ -41,7 +42,7 @@
|
||||
extern char *DATA_FILE;
|
||||
extern int store_data(Tox *m, char *path);
|
||||
|
||||
static GroupChat groupchats[MAX_WINDOWS_NUM];
|
||||
static GroupChat groupchats[MAX_GROUPCHAT_NUM];
|
||||
static int max_groupchat_index = 0;
|
||||
|
||||
extern struct user_settings *user_settings;
|
||||
@ -51,6 +52,9 @@ extern const uint8_t glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE];
|
||||
|
||||
int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum)
|
||||
{
|
||||
if (groupnum > MAX_GROUPCHAT_NUM)
|
||||
return -1;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= max_groupchat_index; ++i) {
|
||||
@ -146,12 +150,13 @@ static void print_groupchat_help(ToxWindow *self)
|
||||
for (i = 0; i < NUMLINES; ++i)
|
||||
line_info_add(self, NULL, NULL, NULL, lines[i], SYS_MSG, 0, 0);
|
||||
|
||||
msg = " * Use ESC key to toggle history scroll mode";
|
||||
msg = " * Use Page Up/Page Down keys to scroll chat history";
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
|
||||
msg = " * Scroll peer list with the Page Up/Page Down keys.\n";
|
||||
msg = " * Scroll peer list with the ctrl-] and ctrl-[ keys.";
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
|
||||
msg = " * Notice, some friends will be missing names while finding peers\n";
|
||||
msg = " * Notice, some friends will be missing names while finding peers";
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, 0);
|
||||
line_info_add(self, NULL, NULL, NULL, "", SYS_MSG, 0, 0);
|
||||
|
||||
hst->line_start = start;
|
||||
}
|
||||
@ -255,16 +260,14 @@ static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], ui
|
||||
groupchats[gnum].peer_name_lengths = malloc(sizeof(uint16_t) * npeers);
|
||||
groupchats[gnum].oldpeer_name_lengths = malloc(sizeof(uint16_t) * npeers);
|
||||
|
||||
if (groupchats[gnum].peer_names == NULL || groupchats[gnum].oldpeer_names == NULL
|
||||
|| groupchats[gnum].peer_name_lengths == NULL || groupchats[gnum].oldpeer_name_lengths == NULL) {
|
||||
exit_toxic_err("failed in copy_peernames", FATALERR_MEMORY);
|
||||
}
|
||||
|
||||
memset(groupchats[gnum].peer_names, 0, sizeof(uint8_t) * npeers * N);
|
||||
memset(groupchats[gnum].peer_name_lengths, 0, sizeof(uint16_t) * npeers);
|
||||
|
||||
if (groupchats[gnum].peer_names == NULL || groupchats[gnum].oldpeer_names == NULL
|
||||
|| groupchats[gnum].peer_name_lengths == NULL || groupchats[gnum].oldpeer_name_lengths == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
uint16_t unknown_len = strlen(UNKNOWN_NAME);
|
||||
int i;
|
||||
|
||||
@ -294,9 +297,15 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
|
||||
if (self->num != groupnum)
|
||||
return;
|
||||
|
||||
if (groupnum > MAX_GROUPCHAT_NUM)
|
||||
return;
|
||||
|
||||
groupchats[groupnum].num_peers = tox_group_number_peers(m, groupnum);
|
||||
int num_peers = groupchats[groupnum].num_peers;
|
||||
|
||||
if (peernum >= num_peers)
|
||||
return;
|
||||
|
||||
/* get old peer name before updating name list */
|
||||
uint8_t oldpeername[TOX_MAX_NAME_LENGTH];
|
||||
|
||||
@ -382,20 +391,9 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
getmaxyx(self->window, y2, x2);
|
||||
int cur_len = 0;
|
||||
|
||||
if (!ltr && (key == T_KEY_ESC) ) { /* ESC key: Toggle history scroll mode */
|
||||
bool scroll = ctx->hst->scroll_mode ? false : true;
|
||||
line_info_toggle_scroll(self, scroll);
|
||||
}
|
||||
|
||||
/* If we're in scroll mode ignore rest of function */
|
||||
if (ctx->hst->scroll_mode) {
|
||||
line_info_onKey(self, key);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ltr) {
|
||||
if ( (ctx->len < MAX_STR_SIZE - 1) && (ctx->len < (x2 * (CHATBOX_HEIGHT - 1) - 1)) ) {
|
||||
add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key);
|
||||
add_char_to_buf(ctx, key);
|
||||
|
||||
if (x == x2 - 1)
|
||||
wmove(self->window, y + 1, 0);
|
||||
@ -405,10 +403,13 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
} else { /* if (!ltr) */
|
||||
|
||||
if (line_info_onKey(self, key))
|
||||
return;
|
||||
|
||||
if (key == 0x107 || key == 0x8 || key == 0x7f) { /* BACKSPACE key: Remove character behind pos */
|
||||
if (ctx->pos > 0) {
|
||||
cur_len = MAX(1, wcwidth(ctx->line[ctx->pos - 1]));
|
||||
del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
|
||||
del_char_buf_bck(ctx);
|
||||
|
||||
if (x == 0)
|
||||
wmove(self->window, y - 1, x2 - cur_len);
|
||||
@ -421,14 +422,14 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
else if (key == KEY_DC) { /* DEL key: Remove character at pos */
|
||||
if (ctx->pos != ctx->len)
|
||||
del_char_buf_frnt(ctx->line, &ctx->pos, &ctx->len);
|
||||
del_char_buf_frnt(ctx);
|
||||
else
|
||||
beep();
|
||||
}
|
||||
|
||||
else if (key == T_KEY_DISCARD) { /* CTRL-U: Delete entire line behind pos */
|
||||
if (ctx->pos > 0) {
|
||||
discard_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
discard_buf(ctx);
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
} else {
|
||||
beep();
|
||||
@ -437,7 +438,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
else if (key == T_KEY_KILL) { /* CTRL-K: Delete entire line in front of pos */
|
||||
if (ctx->pos != ctx->len)
|
||||
kill_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
kill_buf(ctx);
|
||||
else
|
||||
beep();
|
||||
}
|
||||
@ -485,14 +486,12 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
}
|
||||
|
||||
else if (key == KEY_UP) { /* fetches previous item in history */
|
||||
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
||||
&ctx->hst_pos, MOVE_UP);
|
||||
fetch_hist_item(ctx, MOVE_UP);
|
||||
mv_curs_end(self->window, ctx->len, y2, x2);
|
||||
}
|
||||
|
||||
else if (key == KEY_DOWN) { /* fetches next item in history */
|
||||
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
||||
&ctx->hst_pos, MOVE_DOWN);
|
||||
fetch_hist_item(ctx, MOVE_DOWN);
|
||||
mv_curs_end(self->window, ctx->len, y2, x2);
|
||||
}
|
||||
|
||||
@ -501,11 +500,10 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
int diff;
|
||||
|
||||
if ((ctx->line[0] != '/') || (ctx->line[1] == 'm' && ctx->line[2] == 'e'))
|
||||
diff = complete_line(ctx->line, &ctx->pos, &ctx->len, groupchats[self->num].peer_names,
|
||||
diff = complete_line(ctx, groupchats[self->num].peer_names,
|
||||
groupchats[self->num].num_peers, TOX_MAX_NAME_LENGTH);
|
||||
else
|
||||
diff = complete_line(ctx->line, &ctx->pos, &ctx->len, glob_cmd_list, AC_NUM_GLOB_COMMANDS,
|
||||
MAX_CMDNAME_SIZE);
|
||||
diff = complete_line(ctx, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE);
|
||||
|
||||
if (diff != -1) {
|
||||
if (x + diff > x2 - 1) {
|
||||
@ -523,20 +521,22 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
}
|
||||
|
||||
/* Scroll peerlist up and down one position if list overflows window */
|
||||
else if (key == KEY_NPAGE) {
|
||||
else if (key == T_KEY_C_LB) {
|
||||
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 == KEY_PPAGE) {
|
||||
else if (key == T_KEY_C_RB) {
|
||||
if (groupchats[self->num].side_pos > 0)
|
||||
--groupchats[self->num].side_pos;
|
||||
}
|
||||
|
||||
/* RETURN key: Execute command or print line */
|
||||
else if (key == '\n') {
|
||||
rm_trailing_spaces_buf(ctx);
|
||||
|
||||
uint8_t line[MAX_STR_SIZE];
|
||||
|
||||
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
|
||||
@ -547,7 +547,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
|
||||
if (!string_is_empty(line))
|
||||
add_line_to_hist(ctx->line, ctx->len, ctx->ln_history, &ctx->hst_tot, &ctx->hst_pos);
|
||||
add_line_to_hist(ctx);
|
||||
|
||||
if (line[0] == '/') {
|
||||
if (strcmp(line, "/close") == 0) {
|
||||
@ -571,7 +571,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
}
|
||||
}
|
||||
|
||||
reset_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
reset_buf(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -587,21 +587,17 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
line_info_print(self);
|
||||
wclear(ctx->linewin);
|
||||
|
||||
if (ctx->hst->scroll_mode) {
|
||||
line_info_onDraw(self);
|
||||
} else {
|
||||
scrollok(ctx->history, 1);
|
||||
curs_set(1);
|
||||
scrollok(ctx->history, 0);
|
||||
curs_set(1);
|
||||
|
||||
if (ctx->len > 0) {
|
||||
uint8_t line[MAX_STR_SIZE];
|
||||
if (ctx->len > 0) {
|
||||
uint8_t line[MAX_STR_SIZE];
|
||||
|
||||
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) {
|
||||
reset_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
} else {
|
||||
mvwprintw(ctx->linewin, 1, 0, "%s", line);
|
||||
}
|
||||
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) {
|
||||
reset_buf(ctx);
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
} else {
|
||||
mvwprintw(ctx->linewin, 1, 0, "%s", line);
|
||||
}
|
||||
}
|
||||
|
||||
@ -651,11 +647,8 @@ static void groupchat_onInit(ToxWindow *self, Tox *m)
|
||||
ctx->hst = malloc(sizeof(struct history));
|
||||
ctx->log = malloc(sizeof(struct chatlog));
|
||||
|
||||
if (ctx->log == NULL || ctx->hst == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (ctx->log == NULL || ctx->hst == NULL)
|
||||
exit_toxic_err("failed in groupchat_onInit", FATALERR_MEMORY);
|
||||
|
||||
memset(ctx->hst, 0, sizeof(struct history));
|
||||
memset(ctx->log, 0, sizeof(struct chatlog));
|
||||
@ -690,14 +683,10 @@ ToxWindow new_group_chat(Tox *m, int groupnum)
|
||||
|
||||
ChatContext *chatwin = calloc(1, sizeof(ChatContext));
|
||||
|
||||
if (chatwin != NULL)
|
||||
ret.chatwin = chatwin;
|
||||
else {
|
||||
endwin();
|
||||
fprintf(stderr, "calloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (chatwin == NULL)
|
||||
exit_toxic_err("failed in new_group_chat", FATALERR_MEMORY);
|
||||
|
||||
ret.chatwin = chatwin;
|
||||
ret.num = groupnum;
|
||||
|
||||
return ret;
|
||||
|
@ -20,8 +20,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _groupchat_h
|
||||
#define _groupchat_h
|
||||
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
|
||||
#define SIDEBAR_WIDTH 16
|
||||
#define SDBAR_OFST 2 /* Offset for the peer number box at the top of the statusbar */
|
||||
#define MAX_GROUPCHAT_NUM MAX_WINDOWS_NUM
|
||||
|
||||
typedef struct {
|
||||
int chatwin;
|
||||
@ -37,3 +44,5 @@ typedef struct {
|
||||
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 */
|
||||
|
193
src/line_info.c
193
src/line_info.c
@ -28,7 +28,8 @@
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "line_info.h"
|
||||
#include "groupchat.h"
|
||||
#include "settings.h"
|
||||
@ -39,48 +40,33 @@ void line_info_init(struct history *hst)
|
||||
{
|
||||
hst->line_root = malloc(sizeof(struct line_info));
|
||||
|
||||
if (hst->line_root == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (hst->line_root == NULL)
|
||||
exit_toxic_err("failed in line_info_init", FATALERR_MEMORY);
|
||||
|
||||
memset(hst->line_root, 0, sizeof(struct line_info));
|
||||
hst->line_start = hst->line_root;
|
||||
hst->line_end = hst->line_start;
|
||||
hst->queue_sz = 0;
|
||||
}
|
||||
|
||||
/* resets line_start when scroll mode is disabled */
|
||||
static void line_info_reset_start(struct history *hst)
|
||||
/* resets line_start */
|
||||
static void line_info_reset_start(ToxWindow *self, struct history *hst)
|
||||
{
|
||||
int y2, x2;
|
||||
getmaxyx(self->window, y2, x2);
|
||||
|
||||
struct line_info *line = hst->line_end;
|
||||
uint32_t start_id = hst->start_id;
|
||||
|
||||
while (line) {
|
||||
if (line->id == start_id) {
|
||||
hst->line_start = line;
|
||||
break;
|
||||
}
|
||||
uint16_t lncnt = 0;
|
||||
int side_offst = self->is_groupchat ? SIDEBAR_WIDTH : 0;
|
||||
int top_offst = self->is_chat ? 3 : 0;
|
||||
int max_y = (y2 - CHATBOX_HEIGHT - top_offst);
|
||||
|
||||
while (line->prev && lncnt < max_y) {
|
||||
line = line->prev;
|
||||
lncnt += (1 + line->len / (x2 - side_offst));
|
||||
}
|
||||
}
|
||||
|
||||
void line_info_toggle_scroll(ToxWindow *self, bool scroll)
|
||||
{
|
||||
WINDOW *win = self->chatwin->history;
|
||||
struct history *hst = self->chatwin->hst;
|
||||
|
||||
if (scroll) {
|
||||
hst->scroll_mode = true;
|
||||
scrollok(win, 0);
|
||||
curs_set(0);
|
||||
} else {
|
||||
hst->scroll_mode = false;
|
||||
scrollok(win, 1);
|
||||
curs_set(1);
|
||||
line_info_reset_start(hst);
|
||||
}
|
||||
hst->line_start = line;
|
||||
}
|
||||
|
||||
void line_info_cleanup(struct history *hst)
|
||||
@ -110,17 +96,42 @@ 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 */
|
||||
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];
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hst->queue_sz; ++i)
|
||||
hst->queue[i] = hst->queue[i + 1];
|
||||
|
||||
--hst->queue_sz;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* creates new line_info line and puts it in the queue */
|
||||
void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *name2, uint8_t *msg,
|
||||
uint8_t type, uint8_t bold, uint8_t colour)
|
||||
{
|
||||
struct history *hst = self->chatwin->hst;
|
||||
struct line_info *new_line = malloc(sizeof(struct line_info));
|
||||
|
||||
if (new_line == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (new_line == NULL)
|
||||
exit_toxic_err("failed in line_info_add", FATALERR_MEMORY);
|
||||
|
||||
memset(new_line, 0, sizeof(struct line_info));
|
||||
|
||||
@ -129,9 +140,17 @@ void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *na
|
||||
/* for type-specific formatting in print function */
|
||||
switch (type) {
|
||||
case ACTION:
|
||||
case CONNECTION:
|
||||
len += 3;
|
||||
break;
|
||||
|
||||
case SYS_MSG:
|
||||
break;
|
||||
|
||||
case PROMPT:
|
||||
++len;
|
||||
break;
|
||||
|
||||
default:
|
||||
len += 2;
|
||||
break;
|
||||
@ -140,6 +159,13 @@ void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *na
|
||||
if (msg) {
|
||||
snprintf(new_line->msg, sizeof(new_line->msg), "%s", msg);
|
||||
len += strlen(new_line->msg);
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; msg[i]; ++i) {
|
||||
if (msg[i] == '\n')
|
||||
++new_line->newlines;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmstmp) {
|
||||
@ -161,24 +187,26 @@ void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *na
|
||||
new_line->type = type;
|
||||
new_line->bold = bold;
|
||||
new_line->colour = colour;
|
||||
new_line->id = hst->line_end->id + 1;
|
||||
|
||||
new_line->prev = hst->line_end;
|
||||
hst->line_end->next = new_line;
|
||||
hst->line_end = new_line;
|
||||
line_info_add_queue(hst, new_line);
|
||||
}
|
||||
|
||||
if (++hst->line_items > user_settings->history_size) {
|
||||
--hst->line_items;
|
||||
/* adds a single queue item to hst if possible. only called once per call to line_info_print() */
|
||||
static void line_info_check_queue(ToxWindow *self)
|
||||
{
|
||||
struct history *hst = self->chatwin->hst;
|
||||
struct line_info *line = line_info_ret_queue(hst);
|
||||
|
||||
if (line == NULL)
|
||||
return;
|
||||
|
||||
if (hst->start_id > user_settings->history_size)
|
||||
line_info_root_fwd(hst);
|
||||
}
|
||||
|
||||
int newlines = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; msg[i]; ++i) {
|
||||
if (msg[i] == '\n')
|
||||
++newlines;
|
||||
}
|
||||
line->id = hst->line_end->id + 1;
|
||||
line->prev = hst->line_end;
|
||||
hst->line_end->next = line;
|
||||
hst->line_end = line;
|
||||
|
||||
int y, y2, x, x2;
|
||||
getmaxyx(self->window, y2, x2);
|
||||
@ -188,20 +216,15 @@ void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *na
|
||||
return;
|
||||
|
||||
int offst = self->is_groupchat ? SIDEBAR_WIDTH : 0; /* offset width of groupchat sidebar */
|
||||
int lines = (1 + newlines + (len / (x2 - offst)));
|
||||
hst->queue_lns += lines;
|
||||
++hst->queue;
|
||||
|
||||
int lines = 1 + line->newlines + (line->len / (x2 - offst));
|
||||
int max_y = self->is_prompt ? y2 : y2 - CHATBOX_HEIGHT;
|
||||
|
||||
/* move line_start forward proportionate to the number of new lines */
|
||||
if (y + hst->queue_lns - hst->queue >= max_y) {
|
||||
while (lines > 0) {
|
||||
if (y + lines - 1 >= max_y) {
|
||||
while (lines > 0 && hst->line_start->next) {
|
||||
lines -= 1 + hst->line_start->next->newlines + (hst->line_start->next->len / (x2 - offst));
|
||||
hst->line_start = hst->line_start->next;
|
||||
++hst->start_id;
|
||||
lines -= (1 + hst->line_start->len / (x2 - offst));
|
||||
|
||||
if (!hst->scroll_mode && hst->line_start->next)
|
||||
hst->line_start = hst->line_start->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -213,11 +236,12 @@ void line_info_print(ToxWindow *self)
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
|
||||
struct history *hst = ctx->hst;
|
||||
|
||||
/* Only allow one new item to be added to chat window per call to this function */
|
||||
line_info_check_queue(self);
|
||||
|
||||
WINDOW *win = ctx->history;
|
||||
|
||||
ctx->hst->queue = 0;
|
||||
ctx->hst->queue_lns = 0;
|
||||
|
||||
wclear(win);
|
||||
int y2, x2;
|
||||
getmaxyx(self->window, y2, x2);
|
||||
@ -233,7 +257,7 @@ void line_info_print(ToxWindow *self)
|
||||
else
|
||||
wmove(win, 2, 0);
|
||||
|
||||
struct line_info *line = ctx->hst->line_start->next;
|
||||
struct line_info *line = hst->line_start->next;
|
||||
int offst = self->is_groupchat ? SIDEBAR_WIDTH : 0;
|
||||
int numlines = 0;
|
||||
|
||||
@ -349,6 +373,10 @@ void line_info_print(ToxWindow *self)
|
||||
|
||||
line = line->next;
|
||||
}
|
||||
|
||||
/* keep calling until queue is empty */
|
||||
if (hst->queue_sz > 0)
|
||||
line_info_print(self);
|
||||
}
|
||||
|
||||
void line_info_set(ToxWindow *self, uint32_t id, uint8_t *msg)
|
||||
@ -406,46 +434,43 @@ static void line_info_page_down(ToxWindow *self, struct history *hst)
|
||||
hst->line_start = hst->line_start->next;
|
||||
}
|
||||
|
||||
void line_info_onKey(ToxWindow *self, wint_t key)
|
||||
bool line_info_onKey(ToxWindow *self, wint_t key)
|
||||
{
|
||||
struct history *hst = self->chatwin->hst;
|
||||
bool match = true;
|
||||
|
||||
switch (key) {
|
||||
case KEY_PPAGE:
|
||||
/* TODO: Find good key bindings for all this stuff */
|
||||
case T_KEY_C_H:
|
||||
line_info_page_up(self, hst);
|
||||
break;
|
||||
|
||||
case KEY_NPAGE:
|
||||
case T_KEY_C_B:
|
||||
line_info_page_down(self, hst);
|
||||
break;
|
||||
break;
|
||||
|
||||
case KEY_UP:
|
||||
case KEY_PPAGE:
|
||||
line_info_scroll_up(hst);
|
||||
break;
|
||||
|
||||
case KEY_DOWN:
|
||||
case KEY_NPAGE:
|
||||
line_info_scroll_down(hst);
|
||||
break;
|
||||
|
||||
case KEY_HOME:
|
||||
/* case ?:
|
||||
line_info_goto_root(hst);
|
||||
break;
|
||||
|
||||
case KEY_END:
|
||||
line_info_reset_start(hst);
|
||||
case ?:
|
||||
line_info_reset_start(self, hst);
|
||||
break; */
|
||||
|
||||
default:
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void line_info_onDraw(ToxWindow *self)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
wattron(ctx->linewin, A_BOLD | COLOR_PAIR(BLUE));
|
||||
mvwprintw(ctx->linewin, 1, 0, "Scroll mode:\n");
|
||||
wattroff(ctx->linewin, A_BOLD | COLOR_PAIR(BLUE));
|
||||
mvwprintw(ctx->linewin, 1, 13, "Use up/down arrows, page up/page down, and home/end to navigate.\n"
|
||||
" ESC to exit.\n");
|
||||
return match;
|
||||
}
|
||||
|
||||
void line_info_clear(struct history *hst)
|
||||
|
@ -20,8 +20,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _line_info_h
|
||||
#define _line_info_h
|
||||
|
||||
#include "windows.h"
|
||||
#include "toxic.h"
|
||||
|
||||
#define MAX_HISTORY 10000
|
||||
#define MIN_HISTORY 20
|
||||
#define MAX_QUEUE 32
|
||||
|
||||
enum {
|
||||
SYS_MSG,
|
||||
@ -43,6 +50,7 @@ struct line_info {
|
||||
uint8_t colour;
|
||||
uint32_t id;
|
||||
uint16_t len; /* combined len of all strings */
|
||||
uint8_t newlines;
|
||||
|
||||
struct line_info *prev;
|
||||
struct line_info *next;
|
||||
@ -54,15 +62,12 @@ struct history {
|
||||
struct line_info *line_start; /* the first line we want to start printing at */
|
||||
struct line_info *line_end;
|
||||
uint32_t start_id; /* keeps track of where line_start should be when at bottom of history */
|
||||
uint32_t line_items;
|
||||
bool scroll_mode;
|
||||
|
||||
/* keeps track of lines added between window refreshes */
|
||||
uint32_t queue;
|
||||
uint32_t queue_lns;
|
||||
struct line_info *queue[MAX_QUEUE];
|
||||
int queue_sz;
|
||||
};
|
||||
|
||||
/* adds a line to history (also moves line_start and/or line_root forward if necessary) */
|
||||
/* creates new line_info line and puts it in the queue */
|
||||
void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *name2, uint8_t *msg,
|
||||
uint8_t type, uint8_t bold, uint8_t colour);
|
||||
|
||||
@ -72,9 +77,6 @@ void line_info_print(ToxWindow *self);
|
||||
/* frees all history lines */
|
||||
void line_info_cleanup(struct history *hst);
|
||||
|
||||
/* Toggles scroll mode for current window */
|
||||
void line_info_toggle_scroll(ToxWindow *self, bool scroll);
|
||||
|
||||
/* clears the screen (does not delete anything) */
|
||||
void line_info_clear(struct history *hst);
|
||||
|
||||
@ -82,5 +84,6 @@ void line_info_clear(struct history *hst);
|
||||
void line_info_set(ToxWindow *self, uint32_t id, uint8_t *msg);
|
||||
|
||||
void line_info_init(struct history *hst);
|
||||
void line_info_onKey(ToxWindow *self, wint_t key);
|
||||
void line_info_onDraw(ToxWindow *self);
|
||||
bool line_info_onKey(ToxWindow *self, wint_t key); /* returns true if key is a match */
|
||||
|
||||
#endif /* #define _line_info_h */
|
||||
|
@ -29,7 +29,8 @@
|
||||
#include <time.h>
|
||||
|
||||
#include "configdir.h"
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "misc_tools.h"
|
||||
#include "log.h"
|
||||
#include "settings.h"
|
||||
|
@ -20,6 +20,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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 */
|
||||
|
||||
struct chatlog {
|
||||
@ -40,3 +43,5 @@ void log_enable(uint8_t *name, uint8_t *key, struct chatlog *log);
|
||||
|
||||
/* disables logging for specified log and closes file */
|
||||
void log_disable(struct chatlog *log);
|
||||
|
||||
#endif /* #define _log_h */
|
||||
|
@ -29,7 +29,8 @@
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "misc_tools.h"
|
||||
#include "settings.h"
|
||||
|
||||
@ -63,11 +64,10 @@ void get_time_str(uint8_t *buf)
|
||||
strftime(buf, TIME_STR_SIZE, t, get_time());
|
||||
}
|
||||
|
||||
/* XXX: FIX */
|
||||
unsigned char *hex_string_to_bin(char hex_string[])
|
||||
char *hex_string_to_bin(const char *hex_string)
|
||||
{
|
||||
size_t len = strlen(hex_string);
|
||||
unsigned char *val = malloc(len);
|
||||
char *val = malloc(len);
|
||||
|
||||
if (val == NULL) {
|
||||
endwin();
|
||||
@ -75,11 +75,10 @@ unsigned char *hex_string_to_bin(char hex_string[])
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char *pos = hex_string;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i, pos += 2)
|
||||
sscanf(pos, "%2hhx", &val[i]);
|
||||
for (i = 0; i < len; ++i, hex_string += 2)
|
||||
sscanf(hex_string, "%2hhx", &val[i]);
|
||||
|
||||
return val;
|
||||
}
|
||||
@ -233,24 +232,30 @@ void mv_curs_end(WINDOW *w, size_t len, int max_y, int max_x)
|
||||
}
|
||||
|
||||
/* gets base file name from path or original file name if no path is supplied */
|
||||
void get_file_name(uint8_t *pathname, uint8_t *namebuf)
|
||||
void get_file_name(uint8_t *namebuf, uint8_t *pathname)
|
||||
{
|
||||
int idx = strlen(pathname) - 1;
|
||||
|
||||
while (idx >= 0 && pathname[idx] == '/')
|
||||
pathname[idx--] = '\0';
|
||||
|
||||
uint8_t *filename = strrchr(pathname, '/'); /* Try unix style paths */
|
||||
uint8_t *filename = strrchr(pathname, '/');
|
||||
|
||||
if (filename != NULL) {
|
||||
if (!strlen(++filename))
|
||||
filename = pathname;
|
||||
} else {
|
||||
filename = strrchr(pathname, '\\'); /* Try windows style paths */
|
||||
|
||||
if (filename == NULL)
|
||||
filename = pathname;
|
||||
filename = pathname;
|
||||
}
|
||||
|
||||
snprintf(namebuf, MAX_STR_SIZE, "%s", filename);
|
||||
}
|
||||
|
||||
/* converts str to all lowercase */
|
||||
void str_to_lower(uint8_t *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; str[i]; ++i)
|
||||
str[i] = tolower(str[i]);
|
||||
}
|
||||
|
@ -19,12 +19,22 @@
|
||||
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef _misc_tools_h
|
||||
#define _misc_tools_h
|
||||
|
||||
#include "windows.h"
|
||||
#include "toxic.h"
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
/* convert a hex string to binary */
|
||||
unsigned char *hex_string_to_bin(char hex_string[]);
|
||||
char *hex_string_to_bin(const char *hex_string);
|
||||
|
||||
/* get the current unix time */
|
||||
uint64_t get_unix_time(void);
|
||||
@ -63,9 +73,10 @@ void alert_window(ToxWindow *self, int type, bool is_beep);
|
||||
/* case-insensitive string compare function for use with qsort */
|
||||
int qsort_strcasecmp_hlpr(const void *nick1, const void *nick2);
|
||||
|
||||
/* Returns true if nick is valid. A valid toxic nick:
|
||||
/* Returns 1 if nick is valid, 0 if not. A valid toxic nick:
|
||||
- cannot be empty
|
||||
- cannot start with a space
|
||||
- must not contain a forward slash (for logfile naming purposes)
|
||||
- must not contain contiguous spaces */
|
||||
int valid_nick(uint8_t *nick);
|
||||
|
||||
@ -73,4 +84,9 @@ int valid_nick(uint8_t *nick);
|
||||
void mv_curs_end(WINDOW *w, size_t len, int max_y, int max_x);
|
||||
|
||||
/* gets base file name from path or original file name if no path is supplied */
|
||||
void get_file_name(uint8_t *pathname, uint8_t *namebuf);
|
||||
void get_file_name(uint8_t *namebuf, uint8_t *pathname);
|
||||
|
||||
/* converts str to all uppercase */
|
||||
void str_to_lower(uint8_t *str);
|
||||
|
||||
#endif /* #define _misc_tools_h */
|
||||
|
78
src/prompt.c
78
src/prompt.c
@ -27,7 +27,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "prompt.h"
|
||||
#include "execute.h"
|
||||
#include "misc_tools.h"
|
||||
@ -101,7 +102,7 @@ void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected)
|
||||
|
||||
/* Adds friend request to pending friend requests.
|
||||
Returns request number on success, -1 if queue is full or other error. */
|
||||
static int add_friend_request(uint8_t *public_key)
|
||||
static int add_friend_request(const uint8_t *public_key)
|
||||
{
|
||||
if (num_frnd_requests >= MAX_FRIENDS_NUM)
|
||||
return -1;
|
||||
@ -130,31 +131,16 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
getyx(ctx->history, y, x);
|
||||
getmaxyx(ctx->history, y2, x2);
|
||||
|
||||
/* TODO this is buggy */
|
||||
/* ESC key: Toggle history scroll mode */
|
||||
/*
|
||||
if (key == T_KEY_ESC) {
|
||||
bool scroll = ctx->hst->scroll_mode ? false : true;
|
||||
line_info_toggle_scroll(self, scroll);
|
||||
}
|
||||
*/
|
||||
|
||||
/* If we're in scroll mode ignore rest of function */
|
||||
if (ctx->hst->scroll_mode) {
|
||||
line_info_onKey(self, key);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ltr) {
|
||||
if (ctx->len < (MAX_STR_SIZE - 1)) {
|
||||
add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key);
|
||||
add_char_to_buf(ctx, key);
|
||||
}
|
||||
} else { /* if (!ltr) */
|
||||
|
||||
/* BACKSPACE key: Remove one character from line */
|
||||
if (key == 0x107 || key == 0x8 || key == 0x7f) {
|
||||
if (ctx->pos > 0) {
|
||||
del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
|
||||
del_char_buf_bck(ctx);
|
||||
wmove(ctx->history, y, x - 1); /* not necessary but fixes a display glitch */
|
||||
} else {
|
||||
beep();
|
||||
@ -163,7 +149,7 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
else if (key == KEY_DC) { /* DEL key: Remove character at pos */
|
||||
if (ctx->pos != ctx->len) {
|
||||
del_char_buf_frnt(ctx->line, &ctx->pos, &ctx->len);
|
||||
del_char_buf_frnt(ctx);
|
||||
} else {
|
||||
beep();
|
||||
}
|
||||
@ -173,7 +159,7 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
if (ctx->pos > 0) {
|
||||
wmove(ctx->history, ctx->orig_y, X_OFST);
|
||||
wclrtobot(ctx->history);
|
||||
discard_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
discard_buf(ctx);
|
||||
} else {
|
||||
beep();
|
||||
}
|
||||
@ -181,7 +167,7 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
else if (key == T_KEY_KILL) { /* CTRL-K: Delete entire line in front of pos */
|
||||
if (ctx->len != ctx->pos)
|
||||
kill_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
kill_buf(ctx);
|
||||
else
|
||||
beep();
|
||||
}
|
||||
@ -212,8 +198,7 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
else if (key == KEY_UP) { /* fetches previous item in history */
|
||||
wmove(ctx->history, ctx->orig_y, X_OFST);
|
||||
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
||||
&ctx->hst_pos, MOVE_UP);
|
||||
fetch_hist_item(ctx, MOVE_UP);
|
||||
|
||||
/* adjust line y origin appropriately when window scrolls down */
|
||||
if (ctx->at_bottom && ctx->len >= x2 - X_OFST) {
|
||||
@ -233,14 +218,12 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
else if (key == KEY_DOWN) { /* fetches next item in history */
|
||||
wmove(ctx->history, ctx->orig_y, X_OFST);
|
||||
fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
|
||||
&ctx->hst_pos, MOVE_DOWN);
|
||||
fetch_hist_item(ctx, MOVE_DOWN);
|
||||
}
|
||||
|
||||
else if (key == '\t') { /* TAB key: completes command */
|
||||
if (ctx->len > 1 && ctx->line[0] == '/') {
|
||||
if (complete_line(ctx->line, &ctx->pos, &ctx->len, glob_cmd_list, AC_NUM_GLOB_COMMANDS,
|
||||
MAX_CMDNAME_SIZE) == -1)
|
||||
if (complete_line(ctx, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE) == -1)
|
||||
beep();
|
||||
} else {
|
||||
beep();
|
||||
@ -249,6 +232,8 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
/* RETURN key: execute command */
|
||||
else if (key == '\n') {
|
||||
rm_trailing_spaces_buf(ctx);
|
||||
|
||||
wprintw(ctx->history, "\n");
|
||||
uint8_t line[MAX_STR_SIZE] = {0};
|
||||
|
||||
@ -256,11 +241,11 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
memset(&line, 0, sizeof(line));
|
||||
|
||||
if (!string_is_empty(line))
|
||||
add_line_to_hist(ctx->line, ctx->len, ctx->ln_history, &ctx->hst_tot, &ctx->hst_pos);
|
||||
add_line_to_hist(ctx);
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, line, PROMPT, 0, 0);
|
||||
execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE);
|
||||
reset_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
reset_buf(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -273,10 +258,8 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
|
||||
getyx(ctx->history, y, x);
|
||||
getmaxyx(ctx->history, y2, x2);
|
||||
|
||||
if (!ctx->hst->scroll_mode) {
|
||||
curs_set(1);
|
||||
scrollok(ctx->history, 1);
|
||||
}
|
||||
curs_set(1);
|
||||
scrollok(ctx->history, 1);
|
||||
|
||||
line_info_print(self);
|
||||
|
||||
@ -293,7 +276,7 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
|
||||
uint8_t line[MAX_STR_SIZE];
|
||||
|
||||
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
|
||||
reset_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
reset_buf(ctx);
|
||||
else
|
||||
mvwprintw(ctx->history, ctx->orig_y, X_OFST, line);
|
||||
|
||||
@ -403,10 +386,9 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum
|
||||
}
|
||||
}
|
||||
|
||||
static void prompt_onFriendRequest(ToxWindow *self, Tox *m, uint8_t *key, uint8_t *data, uint16_t length)
|
||||
static void prompt_onFriendRequest(ToxWindow *self, Tox *m, const uint8_t *key, const uint8_t *data,
|
||||
uint16_t length)
|
||||
{
|
||||
data[length] = '\0';
|
||||
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
uint8_t timefrmt[TIME_STR_SIZE];
|
||||
@ -486,11 +468,8 @@ static void prompt_onInit(ToxWindow *self, Tox *m)
|
||||
ctx->log = malloc(sizeof(struct chatlog));
|
||||
ctx->hst = malloc(sizeof(struct history));
|
||||
|
||||
if (ctx->log == NULL || ctx->hst == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (ctx->log == NULL || ctx->hst == NULL)
|
||||
exit_toxic_err("failed in prompt_onInit", FATALERR_MEMORY);
|
||||
|
||||
memset(ctx->log, 0, sizeof(struct chatlog));
|
||||
memset(ctx->hst, 0, sizeof(struct history));
|
||||
@ -526,14 +505,11 @@ ToxWindow new_prompt(void)
|
||||
ChatContext *chatwin = calloc(1, sizeof(ChatContext));
|
||||
StatusBar *stb = calloc(1, sizeof(StatusBar));
|
||||
|
||||
if (stb != NULL && chatwin != NULL) {
|
||||
ret.chatwin = chatwin;
|
||||
ret.stb = stb;
|
||||
} else {
|
||||
endwin();
|
||||
fprintf(stderr, "calloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (stb == NULL || chatwin == NULL)
|
||||
exit_toxic_err("failed in new_prompt", FATALERR_MEMORY);
|
||||
|
||||
ret.chatwin = chatwin;
|
||||
ret.stb = stb;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -23,8 +23,10 @@
|
||||
#ifndef PROMPT_H_UZYGWFFL
|
||||
#define PROMPT_H_UZYGWFFL
|
||||
|
||||
#define X_OFST 2 /* offset to account for prompt char */
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
|
||||
#define X_OFST 2 /* offset to account for prompt char */
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#define AC_NUM_GLOB_COMMANDS 17
|
||||
|
146
src/settings.c
146
src/settings.c
@ -20,91 +20,154 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "configdir.h"
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#include "audio_call.h"
|
||||
#endif
|
||||
|
||||
#include "settings.h"
|
||||
#include "line_info.h"
|
||||
|
||||
static void uset_autolog(struct user_settings *s, int val);
|
||||
static void uset_time(struct user_settings *s, int val);
|
||||
static void uset_alerts(struct user_settings *s, int val);
|
||||
static void uset_colours(struct user_settings *s, int val);
|
||||
static void uset_ain_dev(struct user_settings *s, int val);
|
||||
static void uset_aout_dev(struct user_settings *s, int val);
|
||||
static void uset_hst_size(struct user_settings *s, int val);
|
||||
static void uset_autolog(struct user_settings *s, const char *val);
|
||||
static void uset_time(struct user_settings *s, const char *val);
|
||||
static void uset_alerts(struct user_settings *s, const char *val);
|
||||
static void uset_colours(struct user_settings *s, const char *val);
|
||||
static void uset_hst_size(struct user_settings *s, const char *val);
|
||||
static void uset_dwnld_path(struct user_settings *s, const char *val);
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
static void uset_ain_dev(struct user_settings *s, const char *val);
|
||||
static void uset_aout_dev(struct user_settings *s, const char *val);
|
||||
#endif
|
||||
|
||||
struct {
|
||||
const char *name;
|
||||
void (*func)(struct user_settings *s, int val);
|
||||
const char *key;
|
||||
void (*func)(struct user_settings *s, const char *val);
|
||||
} user_settings_list[] = {
|
||||
{ "autolog", uset_autolog },
|
||||
{ "time", uset_time },
|
||||
{ "disable_alerts", uset_alerts },
|
||||
{ "colour_theme", uset_colours },
|
||||
{ "history_size", uset_hst_size },
|
||||
{ "download_path", uset_dwnld_path },
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
{ "audio_in_dev", uset_ain_dev },
|
||||
{ "audio_out_dev", uset_aout_dev },
|
||||
{ "history_size", uset_hst_size },
|
||||
#endif
|
||||
};
|
||||
|
||||
static void uset_autolog(struct user_settings *s, int val)
|
||||
static void uset_autolog(struct user_settings *s, const char *val)
|
||||
{
|
||||
int n = atoi(val);
|
||||
|
||||
/* default off if invalid value */
|
||||
s->autolog = val == AUTOLOG_ON ? AUTOLOG_ON : AUTOLOG_OFF;
|
||||
s->autolog = n == AUTOLOG_ON ? AUTOLOG_ON : AUTOLOG_OFF;
|
||||
}
|
||||
|
||||
static void uset_time(struct user_settings *s, int val)
|
||||
static void uset_time(struct user_settings *s, const char *val)
|
||||
{
|
||||
int n = atoi(val);
|
||||
|
||||
/* default to 24 hour time if invalid value */
|
||||
s->time = val == TIME_12 ? TIME_12 : TIME_24;
|
||||
s->time = n == TIME_12 ? TIME_12 : TIME_24;
|
||||
}
|
||||
|
||||
static void uset_alerts(struct user_settings *s, int val)
|
||||
static void uset_alerts(struct user_settings *s, const char *val)
|
||||
{
|
||||
int n = atoi(val);
|
||||
|
||||
/* alerts default on if invalid value */
|
||||
s->alerts = val == ALERTS_DISABLED ? ALERTS_DISABLED : ALERTS_ENABLED;
|
||||
s->alerts = n == ALERTS_DISABLED ? ALERTS_DISABLED : ALERTS_ENABLED;
|
||||
}
|
||||
|
||||
static void uset_colours(struct user_settings *s, int val)
|
||||
static void uset_colours(struct user_settings *s, const char *val)
|
||||
{
|
||||
int n = atoi(val);
|
||||
|
||||
/* use default toxic colours if invalid value */
|
||||
s->colour_theme = val == NATIVE_COLS ? NATIVE_COLS : DFLT_COLS;
|
||||
s->colour_theme = n == NATIVE_COLS ? NATIVE_COLS : DFLT_COLS;
|
||||
}
|
||||
|
||||
static void uset_ain_dev(struct user_settings *s, int val)
|
||||
{
|
||||
if (val < 0 || val > MAX_DEVICES)
|
||||
val = (long int) 0;
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
|
||||
s->audio_in_dev = (long int) val;
|
||||
static void uset_ain_dev(struct user_settings *s, const char *val)
|
||||
{
|
||||
int n = atoi(val);
|
||||
|
||||
if (n < 0 || n > MAX_DEVICES)
|
||||
n = (long int) 0;
|
||||
|
||||
s->audio_in_dev = (long int) n;
|
||||
}
|
||||
|
||||
static void uset_aout_dev(struct user_settings *s, int val)
|
||||
static void uset_aout_dev(struct user_settings *s, const char *val)
|
||||
{
|
||||
if (val < 0 || val > MAX_DEVICES)
|
||||
val = (long int) 0;
|
||||
int n = atoi(val);
|
||||
|
||||
s->audio_out_dev = (long int) val;
|
||||
if (n < 0 || n > MAX_DEVICES)
|
||||
n = (long int) 0;
|
||||
|
||||
s->audio_out_dev = (long int) n;
|
||||
}
|
||||
|
||||
static void uset_hst_size(struct user_settings *s, int val)
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
static void uset_hst_size(struct user_settings *s, const char *val)
|
||||
{
|
||||
int n = atoi(val);
|
||||
|
||||
/* if val is out of range use default history size */
|
||||
s->history_size = (val > MAX_HISTORY || val < MIN_HISTORY) ? DFLT_HST_SIZE : val;
|
||||
s->history_size = (n > MAX_HISTORY || n < MIN_HISTORY) ? DFLT_HST_SIZE : n;
|
||||
}
|
||||
|
||||
static void uset_dwnld_path(struct user_settings *s, const char *val)
|
||||
{
|
||||
memset(s->download_path, 0, sizeof(s->download_path));
|
||||
|
||||
if (val == NULL)
|
||||
return;
|
||||
|
||||
int len = strlen(val);
|
||||
|
||||
if (len >= sizeof(s->download_path) - 2) /* leave room for null and '/' */
|
||||
return;
|
||||
|
||||
FILE *fp = fopen(val, "r");
|
||||
|
||||
if (fp == NULL)
|
||||
return;
|
||||
|
||||
strcpy(s->download_path, val);
|
||||
|
||||
if (val[len - 1] != '/')
|
||||
strcat(s->download_path, "/");
|
||||
}
|
||||
|
||||
static void set_default_settings(struct user_settings *s)
|
||||
{
|
||||
uset_autolog(s, AUTOLOG_OFF);
|
||||
uset_time(s, TIME_24);
|
||||
uset_alerts(s, ALERTS_ENABLED);
|
||||
uset_colours(s, DFLT_COLS);
|
||||
uset_ain_dev(s, 0);
|
||||
uset_aout_dev(s, 0);
|
||||
uset_hst_size(s, DFLT_HST_SIZE);
|
||||
/* see settings_values enum in settings.h for defaults */
|
||||
uset_autolog(s, "0");
|
||||
uset_time(s, "24");
|
||||
uset_alerts(s, "0");
|
||||
uset_colours(s, "0");
|
||||
uset_hst_size(s, "700");
|
||||
uset_dwnld_path(s, NULL);
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
uset_ain_dev(s, "0");
|
||||
uset_aout_dev(s, "0");
|
||||
#endif
|
||||
}
|
||||
|
||||
int settings_load(struct user_settings *s, char *path)
|
||||
@ -137,17 +200,16 @@ int settings_load(struct user_settings *s, char *path)
|
||||
if (line[0] == '#' || !line[0])
|
||||
continue;
|
||||
|
||||
char *name = strtok(line, ":");
|
||||
char *val_s = strtok(NULL, ";");
|
||||
const char *key = strtok(line, ":");
|
||||
const char *val = strtok(NULL, ";");
|
||||
|
||||
if (name == NULL || val_s == NULL)
|
||||
if (key == NULL || val == NULL)
|
||||
continue;
|
||||
|
||||
int val = atoi(val_s);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_SETTINGS; ++i) {
|
||||
if (!strcmp(user_settings_list[i].name, name)) {
|
||||
if (!strcmp(user_settings_list[i].key, key)) {
|
||||
(user_settings_list[i].func)(s, val);
|
||||
break;
|
||||
}
|
||||
|
@ -20,7 +20,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define NUM_SETTINGS 7
|
||||
#ifndef _settings_h
|
||||
#define _settings_h
|
||||
|
||||
#include "toxic.h"
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#define NUM_SETTINGS 8
|
||||
#else
|
||||
#define NUM_SETTINGS 6
|
||||
#endif
|
||||
|
||||
/* holds user setting values */
|
||||
struct user_settings {
|
||||
@ -28,9 +37,13 @@ struct user_settings {
|
||||
int alerts; /* boolean */
|
||||
int time; /* 12 or 24 */
|
||||
int colour_theme; /* boolean (0 for default toxic colours) */
|
||||
int history_size; /* int between MIN_HISTORY and MAX_HISTORY */
|
||||
char download_path[MAX_STR_SIZE];
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
long int audio_in_dev;
|
||||
long int audio_out_dev;
|
||||
int history_size; /* int between MIN_HISTORY and MAX_HISTORY */
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -47,6 +60,8 @@ enum {
|
||||
DFLT_COLS = 0,
|
||||
|
||||
DFLT_HST_SIZE = 700,
|
||||
};
|
||||
} settings_values;
|
||||
|
||||
int settings_load(struct user_settings *s, char *path);
|
||||
|
||||
#endif /* #define _settings_h */
|
||||
|
@ -39,23 +39,18 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <getopt.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <tox/tox.h>
|
||||
|
||||
#include "configdir.h"
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "friendlist.h"
|
||||
#include "prompt.h"
|
||||
#include "misc_tools.h"
|
||||
@ -79,30 +74,64 @@ ToxAv *av;
|
||||
char *DATA_FILE = NULL;
|
||||
ToxWindow *prompt = NULL;
|
||||
|
||||
static int f_loadfromfile; /* 1 if we want to load from/save the data file, 0 otherwise */
|
||||
struct arg_opts {
|
||||
int ignore_data_file;
|
||||
int use_ipv4;
|
||||
char config_path[MAX_STR_SIZE];
|
||||
char nodes_path[MAX_STR_SIZE];
|
||||
} arg_opts;
|
||||
|
||||
struct _Winthread Winthread;
|
||||
struct user_settings *user_settings = NULL;
|
||||
|
||||
void on_window_resize(int sig)
|
||||
static void ignore_SIGINT(int sig)
|
||||
{
|
||||
refresh();
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void exit_toxic_success(Tox *m)
|
||||
{
|
||||
store_data(m, DATA_FILE);
|
||||
close_all_file_senders();
|
||||
kill_all_windows();
|
||||
log_disable(prompt->chatwin->log);
|
||||
line_info_cleanup(prompt->chatwin->hst);
|
||||
free(DATA_FILE);
|
||||
free(prompt->stb);
|
||||
free(prompt->chatwin->log);
|
||||
free(prompt->chatwin->hst);
|
||||
free(prompt->chatwin);
|
||||
free(user_settings);
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
terminate_audio();
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
tox_kill(m);
|
||||
endwin();
|
||||
fprintf(stderr, "Toxic session ended gracefully.\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
void exit_toxic_err(const char *errmsg, int errcode)
|
||||
{
|
||||
if (errmsg == NULL)
|
||||
errmsg = "No error message";
|
||||
|
||||
endwin();
|
||||
fprintf(stderr, "Toxic session aborted with error code %d (%s)\n", errcode, errmsg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void init_term(void)
|
||||
{
|
||||
/* Setup terminal */
|
||||
signal(SIGWINCH, on_window_resize);
|
||||
|
||||
#if HAVE_WIDECHAR
|
||||
|
||||
if (setlocale(LC_ALL, "") == NULL) {
|
||||
fprintf(stderr, "Could not set your locale, plese check your locale settings or"
|
||||
"disable wide char support\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (setlocale(LC_ALL, "") == NULL)
|
||||
exit_toxic_err("Could not set your locale, plese check your locale settings or"
|
||||
"disable wide char support", FATALERR_LOCALE_SET);
|
||||
#endif
|
||||
|
||||
initscr();
|
||||
cbreak();
|
||||
keypad(stdscr, 1);
|
||||
@ -147,6 +176,9 @@ static Tox *init_tox(int ipv4)
|
||||
m = tox_new(0);
|
||||
}
|
||||
|
||||
if (ipv4)
|
||||
fprintf(stderr, "Forcing IPv4 connection\n");
|
||||
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -204,15 +236,15 @@ static int nodelist_load(char *filename)
|
||||
|
||||
while (fgets(line, sizeof(line), fp) && linecnt < MAXNODES) {
|
||||
if (strlen(line) > MINLINE) {
|
||||
char *name = strtok(line, " ");
|
||||
char *port = strtok(NULL, " ");
|
||||
char *key_ascii = strtok(NULL, " ");
|
||||
const char *name = strtok(line, " ");
|
||||
const char *port = strtok(NULL, " ");
|
||||
const char *key_ascii = strtok(NULL, " ");
|
||||
|
||||
/* invalid line */
|
||||
if (name == NULL || port == NULL || key_ascii == NULL)
|
||||
continue;
|
||||
|
||||
strncpy(nodes[linecnt], name, NODELEN);
|
||||
snprintf(nodes[linecnt], sizeof(nodes[linecnt]), "%s", name);
|
||||
nodes[linecnt][NODELEN - 1] = 0;
|
||||
ports[linecnt] = htons(atoi(port));
|
||||
|
||||
@ -262,7 +294,12 @@ int init_connection(Tox *m)
|
||||
*/
|
||||
if (!srvlist_loaded) {
|
||||
srvlist_loaded = true;
|
||||
int res = nodelist_load(PACKAGE_DATADIR "/DHTnodes");
|
||||
int res;
|
||||
|
||||
if (!arg_opts.nodes_path[0])
|
||||
res = nodelist_load(PACKAGE_DATADIR "/DHTnodes");
|
||||
else
|
||||
res = nodelist_load(arg_opts.nodes_path);
|
||||
|
||||
if (linecnt < 1)
|
||||
return res;
|
||||
@ -332,7 +369,7 @@ static void load_friendlist(Tox *m)
|
||||
*/
|
||||
int store_data(Tox *m, char *path)
|
||||
{
|
||||
if (f_loadfromfile == 0) /*If file loading/saving is disabled*/
|
||||
if (arg_opts.ignore_data_file)
|
||||
return 0;
|
||||
|
||||
if (path == NULL)
|
||||
@ -370,7 +407,7 @@ int store_data(Tox *m, char *path)
|
||||
|
||||
static void load_data(Tox *m, char *path)
|
||||
{
|
||||
if (f_loadfromfile == 0) /*If file loading/saving is disabled*/
|
||||
if (arg_opts.ignore_data_file)
|
||||
return;
|
||||
|
||||
FILE *fd;
|
||||
@ -386,17 +423,13 @@ static void load_data(Tox *m, char *path)
|
||||
|
||||
if (buf == NULL) {
|
||||
fclose(fd);
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
exit_toxic_err("failed in load_data", FATALERR_MEMORY);
|
||||
}
|
||||
|
||||
if (fread(buf, len, 1, fd) != 1) {
|
||||
free(buf);
|
||||
fclose(fd);
|
||||
endwin();
|
||||
fprintf(stderr, "fread() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
exit_toxic_err("failed in load_data", FATALERR_FREAD);
|
||||
}
|
||||
|
||||
tox_load(m, buf, len);
|
||||
@ -407,44 +440,18 @@ static void load_data(Tox *m, char *path)
|
||||
} else {
|
||||
int st;
|
||||
|
||||
if ((st = store_data(m, path)) != 0) {
|
||||
endwin();
|
||||
fprintf(stderr, "Store messenger failed with return code: %d\n", st);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if ((st = store_data(m, path)) != 0)
|
||||
exit_toxic_err("failed in load_data", FATALERR_STORE_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
void exit_toxic(Tox *m)
|
||||
{
|
||||
store_data(m, DATA_FILE);
|
||||
close_all_file_senders();
|
||||
kill_all_windows();
|
||||
log_disable(prompt->chatwin->log);
|
||||
line_info_cleanup(prompt->chatwin->hst);
|
||||
free(DATA_FILE);
|
||||
free(prompt->stb);
|
||||
free(prompt->chatwin->log);
|
||||
free(prompt->chatwin->hst);
|
||||
free(prompt->chatwin);
|
||||
free(user_settings);
|
||||
tox_kill(m);
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
terminate_audio();
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
endwin();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void do_toxic(Tox *m, ToxWindow *prompt)
|
||||
{
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
|
||||
do_connection(m, prompt);
|
||||
do_file_senders(m);
|
||||
|
||||
/* main tox-core loop */
|
||||
tox_do(m);
|
||||
tox_do(m); /* main tox-core loop */
|
||||
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
}
|
||||
@ -459,35 +466,80 @@ void *thread_winref(void *data)
|
||||
}
|
||||
}
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: toxic [OPTION] [FILE ...]\n");
|
||||
fprintf(stderr, " -f, --file Use specified data file\n");
|
||||
fprintf(stderr, " -x, --nodata Ignore data file\n");
|
||||
fprintf(stderr, " -4, --ipv4 Force IPv4 connection\n");
|
||||
fprintf(stderr, " -c, --config Use specified config file\n");
|
||||
fprintf(stderr, " -n, --nodes Use specified DHTnodes file\n");
|
||||
fprintf(stderr, " -h, --help Show this message and exit\n");
|
||||
}
|
||||
|
||||
static void set_default_opts(void)
|
||||
{
|
||||
arg_opts.use_ipv4 = 0;
|
||||
arg_opts.ignore_data_file = 0;
|
||||
}
|
||||
|
||||
static void parse_args(int argc, char *argv[])
|
||||
{
|
||||
set_default_opts();
|
||||
|
||||
static struct option long_opts[] = {
|
||||
{"file", required_argument, 0, 'f'},
|
||||
{"nodata", no_argument, 0, 'x'},
|
||||
{"ipv4", no_argument, 0, '4'},
|
||||
{"config", required_argument, 0, 'c'},
|
||||
{"nodes", required_argument, 0, 'n'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
};
|
||||
|
||||
const char *opts_str = "4xf:c:n:h";
|
||||
int opt, indexptr;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, opts_str, long_opts, &indexptr)) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
DATA_FILE = strdup(optarg);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
arg_opts.ignore_data_file = 1;
|
||||
break;
|
||||
|
||||
case '4':
|
||||
arg_opts.use_ipv4 = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
snprintf(arg_opts.config_path, sizeof(arg_opts.config_path), "%s", optarg);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
snprintf(arg_opts.nodes_path, sizeof(arg_opts.nodes_path), "%s", optarg);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
default:
|
||||
print_usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *user_config_dir = get_user_config_dir();
|
||||
int config_err = 0;
|
||||
|
||||
f_loadfromfile = 1;
|
||||
int f_flag = 0;
|
||||
int i = 0;
|
||||
int f_use_ipv4 = 0;
|
||||
parse_args(argc, argv);
|
||||
|
||||
/* Make sure all written files are read/writeable only by the current user. */
|
||||
umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
|
||||
for (i = 0; i < argc; ++i) {
|
||||
if (argv[i] == NULL)
|
||||
break;
|
||||
else if (argv[i][0] == '-') {
|
||||
if (argv[i][1] == 'f') {
|
||||
if (argv[i + 1] != NULL)
|
||||
DATA_FILE = strdup(argv[i + 1]);
|
||||
else
|
||||
f_flag = -1;
|
||||
} else if (argv[i][1] == 'n') {
|
||||
f_loadfromfile = 0;
|
||||
} else if (argv[i][1] == '4') {
|
||||
f_use_ipv4 = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
signal(SIGINT, ignore_SIGINT);
|
||||
|
||||
config_err = create_user_config_dir(user_config_dir);
|
||||
|
||||
@ -497,15 +549,12 @@ int main(int argc, char *argv[])
|
||||
} else {
|
||||
DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1);
|
||||
|
||||
if (DATA_FILE != NULL) {
|
||||
strcpy(DATA_FILE, user_config_dir);
|
||||
strcat(DATA_FILE, CONFIGDIR);
|
||||
strcat(DATA_FILE, "data");
|
||||
} else {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (DATA_FILE == NULL)
|
||||
exit_toxic_err("failed in main", FATALERR_MEMORY);
|
||||
|
||||
strcpy(DATA_FILE, user_config_dir);
|
||||
strcat(DATA_FILE, CONFIGDIR);
|
||||
strcat(DATA_FILE, "data");
|
||||
}
|
||||
}
|
||||
|
||||
@ -514,41 +563,32 @@ int main(int argc, char *argv[])
|
||||
/* init user_settings struct and load settings from conf file */
|
||||
user_settings = malloc(sizeof(struct user_settings));
|
||||
|
||||
if (user_settings == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (user_settings == NULL)
|
||||
exit_toxic_err("failed in main", FATALERR_MEMORY);
|
||||
|
||||
memset(user_settings, 0, sizeof(struct user_settings));
|
||||
int settings_err = settings_load(user_settings, NULL);
|
||||
|
||||
Tox *m = init_tox(f_use_ipv4);
|
||||
char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL;
|
||||
int settings_err = settings_load(user_settings, p);
|
||||
|
||||
Tox *m = init_tox(arg_opts.use_ipv4);
|
||||
init_term();
|
||||
|
||||
if (m == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "Failed to initialize network. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (m == NULL)
|
||||
exit_toxic_err("failed in main", FATALERR_NETWORKINIT);
|
||||
|
||||
if (f_loadfromfile)
|
||||
if (!arg_opts.ignore_data_file)
|
||||
load_data(m, DATA_FILE);
|
||||
|
||||
prompt = init_windows(m);
|
||||
|
||||
/* create new thread for ncurses stuff */
|
||||
if (pthread_mutex_init(&Winthread.lock, NULL) != 0) {
|
||||
endwin();
|
||||
fprintf(stderr, "Mutex init failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (pthread_mutex_init(&Winthread.lock, NULL) != 0)
|
||||
exit_toxic_err("failed in main", FATALERR_MUTEX_INIT);
|
||||
|
||||
if (pthread_create(&Winthread.tid, NULL, thread_winref, (void *) m) != 0) {
|
||||
endwin();
|
||||
fprintf(stderr, "Thread creation failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (pthread_create(&Winthread.tid, NULL, thread_winref, (void *) m) != 0)
|
||||
exit_toxic_err("failed in main", FATALERR_THREAD_CREATE);
|
||||
|
||||
|
||||
uint8_t *msg;
|
||||
|
||||
@ -568,11 +608,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
if (f_flag == -1) {
|
||||
msg = "You passed '-f' without giving an argument. Defaulting to 'data' for a keyfile...";
|
||||
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
}
|
||||
|
||||
if (config_err) {
|
||||
msg = "Unable to determine configuration directory. Defaulting to 'data' for a keyfile...";
|
||||
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
99
src/toxic.h
Normal file
99
src/toxic.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* toxic.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 _toxic_h
|
||||
#define _toxic_h
|
||||
|
||||
#ifndef TOXICVER
|
||||
#define TOXICVER "NOVER_" /* Use the -D flag to set this */
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <curses.h>
|
||||
|
||||
#include <tox/tox.h>
|
||||
|
||||
#define UNKNOWN_NAME "Anonymous"
|
||||
|
||||
#define MAX_FRIENDS_NUM 500
|
||||
#define MAX_STR_SIZE 256
|
||||
#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 TIME_STR_SIZE 16
|
||||
|
||||
/* ASCII key codes */
|
||||
#define T_KEY_KILL 0x0B /* ctrl-k */
|
||||
#define T_KEY_DISCARD 0x15 /* ctrl-u */
|
||||
#define T_KEY_NEXT 0x10 /* ctrl-p */
|
||||
#define T_KEY_PREV 0x0F /* ctrl-o */
|
||||
#define T_KEY_C_E 0x05 /* ctrl-e */
|
||||
#define T_KEY_C_A 0x01 /* ctrl-a */
|
||||
#define T_KEY_C_RB 0x1D /* ctrl-] */
|
||||
#define T_KEY_C_LB 0x1B /* ctrl-[ */
|
||||
#define T_KEY_C_B 0x02 /* ctrl-b */
|
||||
#define T_KEY_C_H 0x08 /* ctrl-h */
|
||||
|
||||
enum {
|
||||
MOVE_UP,
|
||||
MOVE_DOWN,
|
||||
} KEY_DIRS;
|
||||
|
||||
typedef enum _FATAL_ERRS {
|
||||
FATALERR_MEMORY = -1, /* malloc() or calloc() failed */
|
||||
FATALERR_FREAD = -2, /* fread() failed on critical read */
|
||||
FATALERR_THREAD_CREATE = -3,
|
||||
FATALERR_MUTEX_INIT = -4,
|
||||
FATALERR_LOCALE_SET = -5,
|
||||
FATALERR_STORE_DATA = -6,
|
||||
FATALERR_NETWORKINIT = -7, /* Tox network failed to init */
|
||||
FATALERR_INFLOOP = -8, /* infinite loop detected */
|
||||
FATALERR_WININIT = -9, /* window init failed */
|
||||
} FATAL_ERRS;
|
||||
|
||||
/* Fixes text color problem on some terminals.
|
||||
Uncomment if necessary */
|
||||
/* #define URXVT_FIX */
|
||||
|
||||
void exit_toxic_success(Tox *m);
|
||||
void exit_toxic_err(const char *errmsg, int errcode);
|
||||
|
||||
void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata);
|
||||
void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata);
|
||||
void on_message(Tox *m, int32_t friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_action(Tox *m, int32_t friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_nickchange(Tox *m, int32_t friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_statuschange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata);
|
||||
void on_statusmessagechange(Tox *m, int32_t friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_friendadded(Tox *m, int32_t friendnumber, bool sort);
|
||||
void on_groupmessage(Tox *m, int groupnumber, int peernumber, uint8_t *message, uint16_t length, void *userdata);
|
||||
void on_groupaction(Tox *m, int groupnumber, int peernumber, uint8_t *action, uint16_t length, void *userdata);
|
||||
void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t *group_pub_key, 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, uint8_t *pathname,
|
||||
uint16_t pathname_length, void *userdata);
|
||||
void on_file_control(Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type,
|
||||
uint8_t *data, uint16_t length, void *userdata);
|
||||
void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata);
|
||||
void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata);
|
||||
|
||||
#endif /* #define _toxic_h */
|
@ -27,160 +27,179 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "misc_tools.h"
|
||||
#include "toxic_strings.h"
|
||||
|
||||
/* Adds char to buffer at pos */
|
||||
void add_char_to_buf(wchar_t *buf, size_t *pos, size_t *len, wint_t ch)
|
||||
/* Adds char to line at pos */
|
||||
void add_char_to_buf(ChatContext *ctx, wint_t ch)
|
||||
{
|
||||
if (*pos < 0 || *len >= MAX_STR_SIZE)
|
||||
if (ctx->pos < 0 || ctx->len >= MAX_STR_SIZE)
|
||||
return;
|
||||
|
||||
/* move all chars including null in front of pos one space forward and insert char in pos */
|
||||
int i;
|
||||
|
||||
for (i = *len; i >= *pos && i >= 0; --i)
|
||||
buf[i + 1] = buf[i];
|
||||
for (i = ctx->len; i >= ctx->pos && i >= 0; --i)
|
||||
ctx->line[i + 1] = ctx->line[i];
|
||||
|
||||
buf[(*pos)++] = ch;
|
||||
++(*len);
|
||||
ctx->line[ctx->pos++] = ch;
|
||||
++ctx->len;
|
||||
}
|
||||
|
||||
/* Deletes the character before pos */
|
||||
void del_char_buf_bck(wchar_t *buf, size_t *pos, size_t *len)
|
||||
void del_char_buf_bck(ChatContext *ctx)
|
||||
{
|
||||
if (*pos <= 0)
|
||||
if (ctx->pos <= 0)
|
||||
return;
|
||||
|
||||
int i;
|
||||
|
||||
/* similar to add_char_to_buf but deletes a char */
|
||||
for (i = *pos - 1; i <= *len; ++i)
|
||||
buf[i] = buf[i + 1];
|
||||
for (i = ctx->pos - 1; i <= ctx->len; ++i)
|
||||
ctx->line[i] = ctx->line[i + 1];
|
||||
|
||||
--(*pos);
|
||||
--(*len);
|
||||
--ctx->pos;
|
||||
--ctx->len;
|
||||
}
|
||||
|
||||
/* Deletes the character at pos */
|
||||
void del_char_buf_frnt(wchar_t *buf, size_t *pos, size_t *len)
|
||||
void del_char_buf_frnt(ChatContext *ctx)
|
||||
{
|
||||
if (*pos < 0 || *pos >= *len)
|
||||
if (ctx->pos < 0 || ctx->pos >= ctx->len)
|
||||
return;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = *pos; i < *len; ++i)
|
||||
buf[i] = buf[i + 1];
|
||||
for (i = ctx->pos; i < ctx->len; ++i)
|
||||
ctx->line[i] = ctx->line[i + 1];
|
||||
|
||||
--(*len);
|
||||
--ctx->len;
|
||||
}
|
||||
|
||||
/* Deletes the line from beginning to pos */
|
||||
void discard_buf(wchar_t *buf, size_t *pos, size_t *len)
|
||||
void discard_buf(ChatContext *ctx)
|
||||
{
|
||||
if (*pos <= 0)
|
||||
if (ctx->pos <= 0)
|
||||
return;
|
||||
|
||||
int i;
|
||||
int c = 0;
|
||||
|
||||
for (i = *pos; i <= *len; ++i)
|
||||
buf[c++] = buf[i];
|
||||
for (i = ctx->pos; i <= ctx->len; ++i)
|
||||
ctx->line[c++] = ctx->line[i];
|
||||
|
||||
*pos = 0;
|
||||
*len = c - 1;
|
||||
ctx->pos = 0;
|
||||
ctx->len = c - 1;
|
||||
}
|
||||
|
||||
/* Deletes the line from pos to len */
|
||||
void kill_buf(wchar_t *buf, size_t *pos, size_t *len)
|
||||
void kill_buf(ChatContext *ctx)
|
||||
{
|
||||
if (*len == *pos)
|
||||
if (ctx->len == ctx->pos)
|
||||
return;
|
||||
|
||||
buf[*pos] = L'\0';
|
||||
*len = *pos;
|
||||
ctx->line[ctx->pos] = L'\0';
|
||||
ctx->len = ctx->pos;
|
||||
}
|
||||
|
||||
/* nulls buf and sets pos and len to 0 */
|
||||
void reset_buf(wchar_t *buf, size_t *pos, size_t *len)
|
||||
/* nulls line and sets pos and len to 0 */
|
||||
void reset_buf(ChatContext *ctx)
|
||||
{
|
||||
buf[0] = L'\0';
|
||||
*pos = 0;
|
||||
*len = 0;
|
||||
ctx->line[0] = L'\0';
|
||||
ctx->pos = 0;
|
||||
ctx->len = 0;
|
||||
}
|
||||
|
||||
/* Removes trailing spaces from line. */
|
||||
void rm_trailing_spaces_buf(ChatContext *ctx)
|
||||
{
|
||||
if (ctx->len <= 0)
|
||||
return;
|
||||
|
||||
if (ctx->line[ctx->len - 1] != ' ')
|
||||
return;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = ctx->len - 1; i >= 0; --i) {
|
||||
if (ctx->line[i] != ' ')
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->len = i + 1;
|
||||
ctx->pos = MIN(ctx->pos, ctx->len);
|
||||
ctx->line[ctx->len] = L'\0';
|
||||
}
|
||||
|
||||
#define HIST_PURGE MAX_LINE_HIST / 4
|
||||
|
||||
/* shifts hist items back and makes room for HIST_PURGE new entries */
|
||||
static void shift_hist_back(wchar_t (*hst)[MAX_STR_SIZE], int *hst_tot)
|
||||
static void shift_hist_back(ChatContext *ctx)
|
||||
{
|
||||
int i;
|
||||
int n = MAX_LINE_HIST - HIST_PURGE;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
wmemcpy(hst[i], hst[i + HIST_PURGE], MAX_STR_SIZE);
|
||||
wmemcpy(ctx->ln_history[i], ctx->ln_history[i + HIST_PURGE], MAX_STR_SIZE);
|
||||
|
||||
*hst_tot = n;
|
||||
ctx->hst_tot = n;
|
||||
}
|
||||
|
||||
/* adds a line to the ln_history buffer at hst_pos and sets hst_pos to end of history. */
|
||||
void add_line_to_hist(const wchar_t *buf, size_t len, wchar_t (*hst)[MAX_STR_SIZE], int *hst_tot,
|
||||
int *hst_pos)
|
||||
void add_line_to_hist(ChatContext *ctx)
|
||||
{
|
||||
if (len > MAX_STR_SIZE)
|
||||
if (ctx->len > MAX_STR_SIZE)
|
||||
return;
|
||||
|
||||
if (*hst_tot >= MAX_LINE_HIST)
|
||||
shift_hist_back(hst, hst_tot);
|
||||
if (ctx->hst_tot >= MAX_LINE_HIST)
|
||||
shift_hist_back(ctx);
|
||||
|
||||
++(*hst_tot);
|
||||
*hst_pos = *hst_tot;
|
||||
++ctx->hst_tot;
|
||||
ctx->hst_pos = ctx->hst_tot;
|
||||
|
||||
wmemcpy(hst[*hst_tot - 1], buf, len + 1);
|
||||
wmemcpy(ctx->ln_history[ctx->hst_tot - 1], ctx->line, ctx->len + 1);
|
||||
}
|
||||
|
||||
/* copies history item at hst_pos to buf. Sets pos and len to the len of the history item.
|
||||
/* copies history item at hst_pos to line. Sets pos and len to the len of the history item.
|
||||
hst_pos is decremented or incremented depending on key_dir.
|
||||
|
||||
resets buffer if at end of history */
|
||||
void fetch_hist_item(wchar_t *buf, size_t *pos, size_t *len, wchar_t (*hst)[MAX_STR_SIZE],
|
||||
int hst_tot, int *hst_pos, int key_dir)
|
||||
resets line if at end of history */
|
||||
void fetch_hist_item(ChatContext *ctx, int key_dir)
|
||||
{
|
||||
if (key_dir == MOVE_UP) {
|
||||
if (--(*hst_pos) < 0) {
|
||||
*hst_pos = 0;
|
||||
if (--ctx->hst_pos < 0) {
|
||||
ctx->hst_pos = 0;
|
||||
beep();
|
||||
}
|
||||
} else {
|
||||
if (++(*hst_pos) >= hst_tot) {
|
||||
*hst_pos = hst_tot;
|
||||
reset_buf(buf, pos, len);
|
||||
if (++ctx->hst_pos >= ctx->hst_tot) {
|
||||
ctx->hst_pos = ctx->hst_tot;
|
||||
reset_buf(ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t *hst_line = hst[*hst_pos];
|
||||
const wchar_t *hst_line = ctx->ln_history[ctx->hst_pos];
|
||||
size_t h_len = wcslen(hst_line);
|
||||
|
||||
wmemcpy(buf, hst_line, h_len + 1);
|
||||
|
||||
*pos = h_len;
|
||||
*len = h_len;
|
||||
wmemcpy(ctx->line, hst_line, h_len + 1);
|
||||
ctx->pos = h_len;
|
||||
ctx->len = h_len;
|
||||
}
|
||||
|
||||
/* looks for the first instance in list that begins with the last entered word in buf according to pos,
|
||||
then fills buf with the complete word. e.g. "Hello jo" would complete the buffer
|
||||
/* looks for the first instance in list that begins 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
|
||||
with "Hello john".
|
||||
|
||||
list is a pointer to the list of strings being compared, n_items is the number of items
|
||||
in the list, and size is the size of each item in the list.
|
||||
|
||||
Returns the difference between the old len and new len of buf on success, -1 if error */
|
||||
int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int n_items, int size)
|
||||
Returns the difference between the old len and new len of line on success, -1 if error */
|
||||
int complete_line(ChatContext *ctx, const void *list, int n_items, int size)
|
||||
{
|
||||
if (*pos <= 0 || *len <= 0 || *len >= MAX_STR_SIZE)
|
||||
if (ctx->pos <= 0 || ctx->len <= 0 || ctx->len >= MAX_STR_SIZE)
|
||||
return -1;
|
||||
|
||||
const uint8_t *L = (uint8_t *) list;
|
||||
@ -188,13 +207,13 @@ int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int
|
||||
uint8_t ubuf[MAX_STR_SIZE];
|
||||
|
||||
/* work with multibyte string copy of buf for simplicity */
|
||||
if (wcs_to_mbs_buf(ubuf, buf, MAX_STR_SIZE) == -1)
|
||||
if (wcs_to_mbs_buf(ubuf, ctx->line, MAX_STR_SIZE) == -1)
|
||||
return -1;
|
||||
|
||||
/* isolate substring from space behind pos to pos */
|
||||
uint8_t tmp[MAX_STR_SIZE];
|
||||
snprintf(tmp, sizeof(tmp), "%s", ubuf);
|
||||
tmp[*pos] = '\0';
|
||||
tmp[ctx->pos] = '\0';
|
||||
uint8_t *sub = strrchr(tmp, ' ');
|
||||
int n_endchrs = 1; /* 1 = append space to end of match, 2 = append ": " */
|
||||
|
||||
@ -227,14 +246,14 @@ int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int
|
||||
/* put match in correct spot in buf and append endchars (space or ": ") */
|
||||
const uint8_t *endchrs = n_endchrs == 1 ? " " : ": ";
|
||||
int m_len = strlen(match);
|
||||
int strt = (int) * pos - s_len;
|
||||
int strt = ctx->pos - s_len;
|
||||
int diff = m_len - s_len + n_endchrs;
|
||||
|
||||
if (*len + diff > MAX_STR_SIZE)
|
||||
if (ctx->len + diff > MAX_STR_SIZE)
|
||||
return -1;
|
||||
|
||||
uint8_t tmpend[MAX_STR_SIZE];
|
||||
strcpy(tmpend, &ubuf[*pos]);
|
||||
strcpy(tmpend, &ubuf[ctx->pos]);
|
||||
strcpy(&ubuf[strt], match);
|
||||
strcpy(&ubuf[strt + m_len], endchrs);
|
||||
strcpy(&ubuf[strt + m_len + n_endchrs], tmpend);
|
||||
@ -245,10 +264,10 @@ int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int
|
||||
if (mbs_to_wcs_buf(newbuf, ubuf, MAX_STR_SIZE) == -1)
|
||||
return -1;
|
||||
|
||||
wcscpy(buf, newbuf);
|
||||
wcscpy(ctx->line, newbuf);
|
||||
|
||||
*len += (size_t) diff;
|
||||
*pos += (size_t) diff;
|
||||
ctx->len += (size_t) diff;
|
||||
ctx->pos += (size_t) diff;
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
@ -20,39 +20,49 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* Adds char to buffer at pos */
|
||||
void add_char_to_buf(wchar_t *buf, size_t *pos, size_t *len, wint_t ch);
|
||||
#ifndef _toxic_strings_h
|
||||
#define _toxic_strings_h
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
/* Adds char to line at pos */
|
||||
void add_char_to_buf(ChatContext *ctx, wint_t ch);
|
||||
|
||||
/* Deletes the character before pos */
|
||||
void del_char_buf_bck(wchar_t *buf, size_t *pos, size_t *len);
|
||||
void del_char_buf_bck(ChatContext *ctx);
|
||||
|
||||
/* Deletes the character at pos */
|
||||
void del_char_buf_frnt(wchar_t *buf, size_t *pos, size_t *len);
|
||||
void del_char_buf_frnt(ChatContext *ctx);
|
||||
|
||||
/* Deletes the line from beginning to pos */
|
||||
void discard_buf(wchar_t *buf, size_t *pos, size_t *len);
|
||||
void discard_buf(ChatContext *ctx);
|
||||
|
||||
/* Deletes the line from pos to len */
|
||||
void kill_buf(wchar_t *buf, size_t *pos, size_t *len);
|
||||
void kill_buf(ChatContext *ctx);
|
||||
|
||||
/* nulls buf and sets pos and len to 0 */
|
||||
void reset_buf(wchar_t *buf, size_t *pos, size_t *len);
|
||||
/* nulls line and sets pos and len to 0 */
|
||||
void reset_buf(ChatContext *ctx);
|
||||
|
||||
/* looks for the first instance in list that begins with the last entered word in buf according to pos,
|
||||
then fills buf with the complete word. e.g. "Hello jo" would complete the buffer
|
||||
/* Removes trailing spaces from line. */
|
||||
void rm_trailing_spaces_buf(ChatContext *ctx);
|
||||
|
||||
/* looks for the first instance in list that begins 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
|
||||
with "Hello john".
|
||||
|
||||
list is a pointer to the list of strings being compared, n_items is the number of items
|
||||
in the list, and size is the size of each item in the list.
|
||||
|
||||
Returns the difference between the old len and new len of buf on success, -1 if error */
|
||||
int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int n_items, int size);
|
||||
Returns the difference between the old len and new len of line on success, -1 if error */
|
||||
int complete_line(ChatContext *ctx, const void *list, int n_items, int size);
|
||||
|
||||
/* adds a line to the ln_history buffer at hst_pos and sets hst_pos to last history item. */
|
||||
void add_line_to_hist(const wchar_t *buf, size_t len, wchar_t (*hst)[MAX_STR_SIZE], int *hst_tot,
|
||||
int *hst_pos);
|
||||
void add_line_to_hist(ChatContext *ctx);
|
||||
|
||||
/* copies history item at hst_pos to buf. Sets pos and len to the len of the history item.
|
||||
hst_pos is decremented or incremented depending on key_dir. */
|
||||
void fetch_hist_item(wchar_t *buf, size_t *pos, size_t *len, wchar_t (*hst)[MAX_STR_SIZE],
|
||||
int hst_tot, int *hst_pos, int key_dir);
|
||||
/* copies history item at hst_pos to line. Sets pos and len to the len of the history item.
|
||||
hst_pos is decremented or incremented depending on key_dir.
|
||||
|
||||
resets line if at end of history */
|
||||
void fetch_hist_item(ChatContext *ctx, int key_dir);
|
||||
|
||||
#endif /* #define _toxic_strings_h */
|
||||
|
@ -30,7 +30,8 @@
|
||||
|
||||
#include "friendlist.h"
|
||||
#include "prompt.h"
|
||||
#include "toxic_windows.h"
|
||||
#include "toxic.h"
|
||||
#include "windows.h"
|
||||
#include "groupchat.h"
|
||||
|
||||
extern char *DATA_FILE;
|
||||
@ -43,7 +44,7 @@ extern ToxWindow *prompt;
|
||||
static int num_active_windows;
|
||||
|
||||
/* CALLBACKS START */
|
||||
void on_request(Tox *m, uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata)
|
||||
void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -283,11 +284,8 @@ void set_next_window(int ch)
|
||||
if (active_window->window)
|
||||
return;
|
||||
|
||||
if (active_window == inf) { /* infinite loop check */
|
||||
endwin();
|
||||
fprintf(stderr, "set_next_window() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (active_window == inf) /* infinite loop check */
|
||||
exit_toxic_err("failed in set_next_window", FATALERR_INFLOOP);
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,11 +301,8 @@ ToxWindow *init_windows(Tox *m)
|
||||
{
|
||||
int n_prompt = add_window(m, new_prompt());
|
||||
|
||||
if (n_prompt == -1 || add_window(m, new_friendlist()) == -1) {
|
||||
endwin();
|
||||
fprintf(stderr, "add_window() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (n_prompt == -1 || add_window(m, new_friendlist()) == -1)
|
||||
exit_toxic_err("failed in init_windows", FATALERR_WININIT);
|
||||
|
||||
prompt = &windows[n_prompt];
|
||||
active_window = prompt;
|
||||
@ -315,6 +310,12 @@ ToxWindow *init_windows(Tox *m)
|
||||
return prompt;
|
||||
}
|
||||
|
||||
void on_window_resize(int sig)
|
||||
{
|
||||
refresh();
|
||||
clear();
|
||||
}
|
||||
|
||||
static void draw_window_tab(ToxWindow toxwin)
|
||||
{
|
||||
/* alert0 takes priority */
|
||||
@ -351,25 +352,28 @@ static void draw_bar(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].active) {
|
||||
if (windows + i == active_window) {
|
||||
#ifdef URXVT_FIX
|
||||
attron(A_BOLD | COLOR_PAIR(GREEN));
|
||||
} else {
|
||||
#endif
|
||||
attron(A_BOLD);
|
||||
}
|
||||
if (!windows[i].active)
|
||||
continue;
|
||||
|
||||
draw_window_tab(windows[i]);
|
||||
if (windows + i == active_window)
|
||||
|
||||
if (windows + i == active_window) {
|
||||
#ifdef URXVT_FIX
|
||||
attroff(A_BOLD | COLOR_PAIR(GREEN));
|
||||
} else {
|
||||
attron(A_BOLD | COLOR_PAIR(GREEN));
|
||||
else
|
||||
#endif
|
||||
attroff(A_BOLD);
|
||||
}
|
||||
}
|
||||
|
||||
attron(A_BOLD);
|
||||
|
||||
draw_window_tab(windows[i]);
|
||||
|
||||
if (windows + i == active_window)
|
||||
|
||||
#ifdef URXVT_FIX
|
||||
attroff(A_BOLD | COLOR_PAIR(GREEN));
|
||||
else
|
||||
#endif
|
||||
|
||||
attroff(A_BOLD);
|
||||
}
|
||||
|
||||
refresh();
|
||||
@ -435,7 +439,7 @@ void refresh_inactive_windows(void)
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
ToxWindow *a = &windows[i];
|
||||
|
||||
if (a->active && a != active_window && !a->is_prompt) /* if prompt doesn't have scroll mode */
|
||||
if (a->active && a != active_window && (a->is_chat || a->is_groupchat))
|
||||
line_info_print(a);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* toxic_windows.h
|
||||
/* windows.h
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2014 Toxic All Rights Reserved.
|
||||
@ -23,11 +23,6 @@
|
||||
#ifndef _windows_h
|
||||
#define _windows_h
|
||||
|
||||
#ifndef TOXICVER
|
||||
#define TOXICVER "NOVER_" /* Use the -D flag to set this */
|
||||
#endif
|
||||
|
||||
#include <curses.h>
|
||||
#include <pthread.h>
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
@ -38,31 +33,11 @@
|
||||
#include <tox/toxav.h>
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
#define UNKNOWN_NAME "Anonymous"
|
||||
#include "toxic.h"
|
||||
|
||||
#define MAX_WINDOWS_NUM 32
|
||||
#define MAX_FRIENDS_NUM 100
|
||||
#define MAX_STR_SIZE 256
|
||||
#define MAX_CMDNAME_SIZE 64
|
||||
#define KEY_SIZE_BYTES 32
|
||||
#define TOXIC_MAX_NAME_LENGTH 32 /* Must be <= TOX_MAX_NAME_LENGTH */
|
||||
#define N_DEFAULT_WINS 2 /* number of permanent default windows */
|
||||
#define CURS_Y_OFFSET 3 /* y-axis cursor offset for chat contexts */
|
||||
#define CHATBOX_HEIGHT 4
|
||||
#define KEY_IDENT_DIGITS 2 /* number of hex digits to display for the pub-key based identifier */
|
||||
#define TIME_STR_SIZE 16
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_FAILURE 1
|
||||
|
||||
/* ASCII key codes */
|
||||
#define T_KEY_KILL 0xB /* ctrl-k */
|
||||
#define T_KEY_DISCARD 0x15 /* ctrl-u */
|
||||
#define T_KEY_NEXT 0x10 /* ctrl-p */
|
||||
#define T_KEY_PREV 0x0F /* ctrl-o */
|
||||
#define T_KEY_C_E 0x05 /* ctrl-e */
|
||||
#define T_KEY_C_A 0x01 /* ctrl-a */
|
||||
#define T_KEY_ESC 0x1B /* ESC key */
|
||||
|
||||
/* Curses foreground colours (background is black) */
|
||||
enum {
|
||||
@ -74,24 +49,24 @@ enum {
|
||||
YELLOW,
|
||||
MAGENTA,
|
||||
BLACK,
|
||||
};
|
||||
} C_COLOURS;
|
||||
|
||||
/* tab alert types: lower types take priority */
|
||||
enum {
|
||||
WINDOW_ALERT_0,
|
||||
WINDOW_ALERT_1,
|
||||
WINDOW_ALERT_2,
|
||||
};
|
||||
|
||||
enum {
|
||||
MOVE_UP,
|
||||
MOVE_DOWN,
|
||||
};
|
||||
} WINDOW_ALERTS;
|
||||
|
||||
/* Fixes text color problem on some terminals.
|
||||
Uncomment if necessary */
|
||||
/* #define URXVT_FIX */
|
||||
|
||||
struct _Winthread {
|
||||
pthread_t tid;
|
||||
pthread_mutex_t lock;
|
||||
};
|
||||
|
||||
typedef struct ToxWindow ToxWindow;
|
||||
typedef struct StatusBar StatusBar;
|
||||
typedef struct PromptBuf PromptBuf;
|
||||
@ -101,7 +76,7 @@ struct ToxWindow {
|
||||
void(*onKey)(ToxWindow *, Tox *, wint_t, bool);
|
||||
void(*onDraw)(ToxWindow *, Tox *);
|
||||
void(*onInit)(ToxWindow *, Tox *);
|
||||
void(*onFriendRequest)(ToxWindow *, Tox *, uint8_t *, uint8_t *, uint16_t);
|
||||
void(*onFriendRequest)(ToxWindow *, Tox *, const uint8_t *, const uint8_t *, uint16_t);
|
||||
void(*onFriendAdded)(ToxWindow *, Tox *, int32_t, bool);
|
||||
void(*onConnectionChange)(ToxWindow *, Tox *, int32_t, uint8_t);
|
||||
void(*onMessage)(ToxWindow *, Tox *, int32_t, uint8_t *, uint16_t);
|
||||
@ -194,67 +169,13 @@ struct ChatContext {
|
||||
int orig_y; /* y axis point of line origin */
|
||||
};
|
||||
|
||||
/* Start file transfer code */
|
||||
|
||||
#define FILE_PIECE_SIZE 2048 /* must be >= (MAX_CRYPTO_DATA_SIZE - 2) in toxcore/net_crypto.h */
|
||||
#define MAX_FILES 256
|
||||
#define TIMEOUT_FILESENDER 300
|
||||
|
||||
typedef struct {
|
||||
FILE *file;
|
||||
ToxWindow *toxwin;
|
||||
int32_t friendnum;
|
||||
bool active;
|
||||
int filenum;
|
||||
uint8_t nextpiece[FILE_PIECE_SIZE];
|
||||
uint16_t piecelen;
|
||||
uint8_t pathname[MAX_STR_SIZE];
|
||||
uint64_t timestamp;
|
||||
uint64_t size;
|
||||
uint32_t line_id;
|
||||
} FileSender;
|
||||
|
||||
struct FileReceiver {
|
||||
uint8_t filenames[MAX_FILES][MAX_STR_SIZE];
|
||||
FILE *files[MAX_FILES];
|
||||
bool pending[MAX_FILES];
|
||||
uint64_t size[MAX_FILES];
|
||||
uint32_t line_id;
|
||||
};
|
||||
|
||||
/* End file transfer code */
|
||||
|
||||
struct _Winthread {
|
||||
pthread_t tid;
|
||||
pthread_mutex_t lock;
|
||||
};
|
||||
|
||||
void on_request(Tox *m, uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata);
|
||||
void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata);
|
||||
void on_message(Tox *m, int32_t friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_action(Tox *m, int32_t friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_nickchange(Tox *m, int32_t friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_statuschange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata);
|
||||
void on_statusmessagechange(Tox *m, int32_t friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_friendadded(Tox *m, int32_t friendnumber, bool sort);
|
||||
void on_groupmessage(Tox *m, int groupnumber, int peernumber, uint8_t *message, uint16_t length, void *userdata);
|
||||
void on_groupaction(Tox *m, int groupnumber, int peernumber, uint8_t *action, uint16_t length, void *userdata);
|
||||
void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t *group_pub_key, 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, uint8_t *pathname,
|
||||
uint16_t pathname_length, void *userdata);
|
||||
void on_file_control(Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type,
|
||||
uint8_t *data, uint16_t length, void *userdata);
|
||||
void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata);
|
||||
void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata);
|
||||
|
||||
ToxWindow *init_windows(Tox *m);
|
||||
void draw_active_window(Tox *m);
|
||||
int add_window(Tox *m, ToxWindow w);
|
||||
void del_window(ToxWindow *w);
|
||||
void set_active_window(int ch);
|
||||
int get_num_active_windows(void);
|
||||
void kill_all_windows(void); /* should only be called on shutdown */
|
||||
void on_window_resize(int sig);
|
||||
|
||||
/* cleans up all chat and groupchat windows (should only be called on shutdown) */
|
||||
void kill_all_windows(void);
|
||||
#endif
|
||||
#endif /* #define _windows_h */
|
Reference in New Issue
Block a user