diff --git a/build/Makefile.am b/build/Makefile.am
index b821b36..5e402ff 100644
--- a/build/Makefile.am
+++ b/build/Makefile.am
@@ -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)"'
@@ -58,7 +61,7 @@ if BUILD_AV
toxic_SOURCES += $(top_srcdir)/src/audio_call.c \
$(top_srcdir)/src/audio_call.h \
$(top_srcdir)/src/device.c \
- $(top_srcdir)/src/device.h
+ $(top_srcdir)/src/device.h
toxic_CFLAGS += $(LIBTOXAV_CFLAGS) \
$(OPENAL_CFLAGS)
diff --git a/configure.ac b/configure.ac
index a2da511..a800b6a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,9 +2,9 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.65])
-AC_INIT([toxic], [0.3.3], [https://tox.im/])
+AC_INIT([toxic], [0.4.2], [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,9 @@ 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
+else
+ export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
fi
AC_ARG_WITH(libtoxcore-headers,
@@ -77,11 +79,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 +389,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
@@ -404,6 +419,8 @@ if test -n "$AV_SEARCH_DIR"; then
CPPFLAGS="$CPPFLAGS -I$AV_SEARCH_DIR/include"
LDFLAGS="$LDFLAGS -L$AV_SEARCH_DIR/lib"
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$AV_SEARCH_DIR/lib/pkgconfig
+else
+ export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig"
fi
# Check if specified enable
@@ -422,29 +439,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 +503,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])
diff --git a/src/audio_call.c b/src/audio_call.c
index fd23838..50cfe57 100644
--- a/src/audio_call.c
+++ b/src/audio_call.c
@@ -1,22 +1,38 @@
-/*
- * 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 .
+ *
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include "toxic_windows.h"
+#include "toxic.h"
+#include "windows.h"
#include "audio_call.h"
#include "device.h"
#include "chat_commands.h"
#include "global_commands.h"
-#include "toxic_windows.h"
#include "line_info.h"
#include
-#include
-#include
#include
#include
#include
@@ -29,16 +45,6 @@
#define frame_size (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000)
-typedef struct _DeviceIx {
-
- ALCdevice *dhndl; /* Handle of device selected/opened */
- ALCcontext *ctx; /* Device context */
- const char *devices[MAX_DEVICES]; /* Container of available devices */
- int size; /* Size of above container */
- int dix; /* Index of default device */
- int index; /* Current index */
-} DeviceIx;
-
typedef struct _Call {
pthread_t ttid; /* Transmission thread id */
_Bool ttas; /* Transmission thread active status (0 - stopped, 1- running) */
@@ -178,7 +184,7 @@ void *transmission(void *arg)
if ( open_primary_device(input, &this_call->in_idx) != de_None ) goto cleanup;
- if ( register_device_callback(this_call->in_idx, read_device_callback, &call_index, _True) != de_None)
+ if ( register_device_callback(call_index, this_call->in_idx, read_device_callback, &call_index, _True) != de_None)
/* Set VAD as true for all; TODO: Make it more dynamic */
goto cleanup;
@@ -582,7 +588,7 @@ on_error:
print_err (self, error_str);
}
-void cmd_set_this_session_device(WINDOW * window, ToxWindow * self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
+void cmd_ccur_device(WINDOW * window, ToxWindow * self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
uint8_t msg[MAX_STR_SIZE];
uint8_t *error_str;
@@ -638,7 +644,7 @@ void cmd_set_this_session_device(WINDOW * window, ToxWindow * self, Tox *m, int
close_device(input, this_call->in_idx);
open_device(input, selection, &this_call->in_idx);
/* Set VAD as true for all; TODO: Make it more dynamic */
- register_device_callback(this_call->in_idx, read_device_callback, &self->call_idx, _True);
+ register_device_callback(self->call_idx, this_call->in_idx, read_device_callback, &self->call_idx, _True);
}
}
}
@@ -646,6 +652,77 @@ void cmd_set_this_session_device(WINDOW * window, ToxWindow * self, Tox *m, int
self->device_selection[type] = selection;
return;
+ on_error:
+ print_err (self, error_str);
+}
+
+void cmd_mute(WINDOW * window, ToxWindow * self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
+{
+ uint8_t msg[MAX_STR_SIZE];
+ uint8_t *error_str;
+
+ if ( argc != 1 ) {
+ if ( argc < 1 ) error_str = "Type must be specified!";
+ else error_str = "Only two arguments allowed!";
+
+ goto on_error;
+ }
+
+ DeviceType type;
+
+ if ( strcmp(argv[1], "in") == 0 ) /* Input devices */
+ type = input;
+
+ else if ( strcmp(argv[1], "out") == 0 ) /* Output devices */
+ type = output;
+
+ else {
+ snprintf(msg, sizeof(msg), "Invalid type: %s", argv[1]);
+ line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
+ return;
+ }
+
+
+ /* If call is active, use this_call values */
+ if ( self->call_idx > -1) {
+ Call* this_call = &ASettins.calls[self->call_idx];
+
+ pthread_mutex_lock(&this_call->mutex);
+ device_mute(type, type == input ? this_call->in_idx : this_call->out_idx);
+ pthread_mutex_unlock(&this_call->mutex);
+ }
+
+ return;
+
+ on_error:
+ print_err (self, error_str);
+}
+
+void cmd_sense(WINDOW * window, ToxWindow * self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
+{
+ uint8_t msg[MAX_STR_SIZE];
+ uint8_t *error_str;
+
+ if ( argc != 1 ) {
+ if ( argc < 1 ) error_str = "Must have value!";
+ else error_str = "Only two arguments allowed!";
+
+ goto on_error;
+ }
+
+ char *end;
+ float value = strtof(argv[1], &end);
+
+ if ( *end ) {
+ error_str = "Invalid input";
+ goto on_error;
+ }
+
+ /* Call must be active */
+ if ( self->call_idx > -1) device_set_VAD_treshold(ASettins.calls[self->call_idx].in_idx, value);
+
+ return;
+
on_error:
print_err (self, error_str);
}
\ No newline at end of file
diff --git a/src/audio_call.h b/src/audio_call.h
index 6b78e38..c33dc42 100644
--- a/src/audio_call.h
+++ b/src/audio_call.h
@@ -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 .
+ *
*/
#ifndef _audio_h
@@ -23,8 +41,6 @@ typedef enum _AudioError {
ToxAv *init_audio(ToxWindow *self, Tox *tox);
void terminate_audio();
-int clear_call_settings_per_se(ToxWindow *self);
-
int start_transmission(ToxWindow *self);
int stop_transmission(int call_index);
int device_set(ToxWindow* self, DeviceType type, long int selection);
diff --git a/src/chat.c b/src/chat.c
index 5b5693a..3b486d0 100644
--- a/src/chat.c
+++ b/src/chat.c
@@ -28,7 +28,8 @@
#include
#include
-#include "toxic_windows.h"
+#include "toxic.h"
+#include "windows.h"
#include "execute.h"
#include "misc_tools.h"
#include "friendlist.h"
@@ -51,7 +52,7 @@ extern struct _Winthread Winthread;
extern struct user_settings *user_settings;
#ifdef _SUPPORT_AUDIO
-#define AC_NUM_CHAT_COMMANDS 24
+#define AC_NUM_CHAT_COMMANDS 26
#else
#define AC_NUM_CHAT_COMMANDS 18
#endif /* _SUPPORT_AUDIO */
@@ -85,6 +86,8 @@ static const uint8_t chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/reject" },
{ "/hangup" },
{ "/sdev" },
+ { "/mute" },
+ { "/sense" },
#endif /* _SUPPORT_AUDIO */
};
@@ -215,8 +218,11 @@ static void chat_onStatusMessageChange(ToxWindow *self, int32_t num, uint8_t *st
return;
StatusBar *statusbar = self->stb;
+
+ status[len] = '\0';
+ snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", status);
+ len = strlen(statusbar->statusmsg);
statusbar->statusmsg_len = len;
- strcpy(statusbar->statusmsg, status);
statusbar->statusmsg[len] = '\0';
}
@@ -226,15 +232,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);
@@ -244,17 +256,42 @@ 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';
char d[9];
sprintf(d, "(%d)", count++);
+ int d_len = strlen(d);
+
+ if (len + d_len >= sizeof(filename)) {
+ len -= d_len;
+ filename[len] = '\0';
+ }
+
strcat(filename, d);
- filename[len + strlen(d)] = '\0';
+ filename[len + d_len] = '\0';
if (count > 999) {
errmsg = "Error saving file to disk.";
@@ -291,21 +328,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);
@@ -315,8 +359,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;
}
@@ -349,7 +396,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);
}
@@ -365,8 +412,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);
@@ -509,44 +557,44 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
int x, y, y2, x2;
getyx(self->window, y, x);
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);
+ if (x2 <= 0)
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);
+ int cur_len = 0; /* widechar size of current char */
+ int x2_is_odd = x2 % 2 != 0;
- if (x == x2 - 1)
- wmove(self->window, y + 1, 0);
- else
+ if (ltr) { /* char is printable */
+ if (ctx->len < MAX_STR_SIZE - 1) {
+ add_char_to_buf(ctx, key);
+
+ if (x >= x2 - 1) {
+ wmove(self->window, y, x2 / 2 + x2_is_odd);
+ ctx->start += x2 / 2;
+ } else {
wmove(self->window, y, x + MAX(1, wcwidth(key)));
+ }
}
if (!ctx->self_is_typing && ctx->line[0] != '/')
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);
+ cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
+ del_char_buf_bck(ctx);
- if (x == 0)
- wmove(self->window, y - 1, x2 - cur_len);
- else
+ if (x == 0) {
+ ctx->start = ctx->start >= x2 ? ctx->start - x2 : 0;
+ int new_x = ctx->start == 0 ? ctx->pos : x2 - cur_len;
+ wmove(self->window, y, new_x);
+ } else {
wmove(self->window, y, x - cur_len);
+ }
} else {
beep();
}
@@ -554,14 +602,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();
@@ -570,7 +618,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();
}
@@ -578,6 +626,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
else if (key == KEY_HOME || key == T_KEY_C_A) { /* HOME/C-a key: Move cursor to start of line */
if (ctx->pos > 0) {
ctx->pos = 0;
+ ctx->start = 0;
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
}
}
@@ -585,7 +634,8 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
else if (key == KEY_END || key == T_KEY_C_E) { /* END/C-e key: move cursor to end of line */
if (ctx->pos != ctx->len) {
ctx->pos = ctx->len;
- mv_curs_end(self->window, MAX(0, wcswidth(ctx->line, (CHATBOX_HEIGHT - 1)*x2)), y2, x2);
+ ctx->start = x2 * (ctx->len / x2);
+ mv_curs_end(self->window, ctx->len, y2, x2);
}
}
@@ -594,10 +644,13 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
--ctx->pos;
cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
- if (x == 0)
- wmove(self->window, y - 1, x2 - cur_len);
- else
+ if (x == 0) {
+ wmove(self->window, y, x2 - cur_len);
+ ctx->start = ctx->start >= x2 ? ctx->start - x2 : 0;
+ ctx->pos = ctx->start + x2 - 1;
+ } else {
wmove(self->window, y, x - cur_len);
+ }
} else {
beep();
}
@@ -605,39 +658,42 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
else if (key == KEY_RIGHT) {
if (ctx->pos < ctx->len) {
- cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
++ctx->pos;
- if (x == x2 - 1)
- wmove(self->window, y + 1, 0);
- else
+ if (x == x2 - 1) {
+ wmove(self->window, y, 0);
+ ctx->start += x2;
+ ctx->pos = ctx->start;
+ } else {
+ cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
wmove(self->window, y, x + cur_len);
+ }
} else {
beep();
}
}
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);
+ ctx->start = x2 * (ctx->len / x2);
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);
+ ctx->start = x2 * (ctx->len / x2);
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) {
- int ofst = (x + diff - 1) - (x2 - 1);
- wmove(self->window, y + 1, ofst);
+ //int ofst = x + diff - x2;
+ wmove(self->window, y, x + diff);
+ ctx->start += x2 / 2;
} else {
wmove(self->window, y, x + diff);
}
@@ -651,6 +707,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)
@@ -660,7 +718,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) {
@@ -692,7 +750,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);
}
}
@@ -710,21 +768,16 @@ 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);
- 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[ctx->start]);
}
}
@@ -845,17 +898,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));
@@ -868,6 +917,7 @@ static void chat_onInit(ToxWindow *self, Tox *m)
execute(ctx->history, self, m, "/help", CHAT_COMMAND_MODE);
execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);
+ scrollok(ctx->history, 0);
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
}
@@ -929,9 +979,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;
diff --git a/src/chat.h b/src/chat.h
index d3aeb3e..e6fc30b 100644
--- a/src/chat.h
+++ b/src/chat.h
@@ -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);
diff --git a/src/chat_commands.c b/src/chat_commands.c
index afbbe27..8fd7ff8 100644
--- a/src/chat_commands.c
+++ b/src/chat_commands.c
@@ -27,7 +27,8 @@
#include
#include
-#include "toxic_windows.h"
+#include "toxic.h"
+#include "windows.h"
#include "misc_tools.h"
#include "friendlist.h"
#include "execute.h"
@@ -57,7 +58,7 @@ void cmd_chat_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
#ifdef _SUPPORT_AUDIO
-#define NUMLINES 13
+#define NUMLINES 16
#else
#define NUMLINES 9
#endif
@@ -70,6 +71,9 @@ void cmd_chat_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
{ " /answer : Answer incomming call" },
{ " /reject : Reject incoming call" },
{ " /hangup : Hangup active call" },
+ { " /sdev : Change active device" },
+ { " /mute : Mute active device if in call" },
+ { " /sense : VAD sensitivity treshold" },
#endif /* _SUPPORT_AUDIO */
{ " /invite : Invite friend to a group chat" },
{ " /join : Join a pending group chat" },
@@ -86,7 +90,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 +189,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 +250,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) {
diff --git a/src/chat_commands.h b/src/chat_commands.h
index 30ca9f1..d1fc34f 100644
--- a/src/chat_commands.h
+++ b/src/chat_commands.h
@@ -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]);
@@ -33,5 +39,9 @@ void cmd_answer(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZ
void cmd_reject(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
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]);
-void cmd_set_this_session_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
+void cmd_ccur_device(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
+void cmd_mute(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
+void cmd_sense(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
#endif /* _SUPPORT_AUDIO */
+
+#endif /* #define _chat_commands_h */
diff --git a/src/configdir.c b/src/configdir.c
index 4bb2411..f569ca9 100644
--- a/src/configdir.c
+++ b/src/configdir.c
@@ -30,14 +30,8 @@
#include
#include
#include
-
-#ifdef _WIN32
-#include
-#include
-#else /* WIN32 */
#include
#include
-#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
}
diff --git a/src/configdir.h b/src/configdir.h
index 6a1a7eb..0a8b01d 100644
--- a/src/configdir.h
+++ b/src/configdir.h
@@ -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 */
diff --git a/src/device.c b/src/device.c
index e3f9212..ad638c1 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1,9 +1,15 @@
-#include "toxic_windows.h"
#include "audio_call.h"
#include "line_info.h"
+
+#ifdef __APPLE__
+#include
+#include
+#else
#include
#include
+#endif
+
#include
#include
#include
@@ -22,11 +28,14 @@ typedef struct _Device {
ALCcontext *ctx; /* Device context */
DataHandleCallback cb; /* Use this to handle data from input device usually */
void* cb_data; /* Data to be passed to callback */
+ int32_t call_idx; /* ToxAv call index */
uint32_t source, buffers[openal_bufs]; /* Playback source/buffers */
size_t ref_count;
int32_t selection;
_Bool enable_VAD;
+ _Bool muted;
+ float VAD_treshold; /* 40 is usually recommended value */
} Device;
const char *ddevice_names[2]; /* Default device */
@@ -100,6 +109,42 @@ DeviceError terminate_devices()
return ae_None;
}
+DeviceError device_mute(DeviceType type, uint32_t device_idx)
+{
+ if (device_idx >= MAX_DEVICES) return de_InvalidSelection;
+ lock;
+
+ Device* device = running[type][device_idx];
+
+ if (!device) {
+ unlock;
+ return de_DeviceNotActive;
+ }
+
+ device->muted = !device->muted;
+
+ unlock;
+ return de_None;
+}
+
+DeviceError device_set_VAD_treshold(uint32_t device_idx, float value)
+{
+ if (device_idx >= MAX_DEVICES) return de_InvalidSelection;
+ lock;
+
+ Device* device = running[input][device_idx];
+
+ if (!device) {
+ unlock;
+ return de_DeviceNotActive;
+ }
+
+ device->VAD_treshold = value;
+
+ unlock;
+ return de_None;
+}
+
DeviceError set_primary_device(DeviceType type, int32_t selection)
{
if (size[type] <= selection || selection < 0) return de_InvalidSelection;
@@ -147,6 +192,7 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
if (type == input) {
device->dhndl = alcCaptureOpenDevice(devices_names[type][selection],
av_DefaultSettings.audio_sample_rate, AL_FORMAT_MONO16, frame_size * 4);
+ device->VAD_treshold = 40.0;
}
else {
device->dhndl = alcOpenDevice(devices_names[type][selection]);
@@ -230,7 +276,7 @@ DeviceError close_device(DeviceType type, uint32_t device_idx)
return de_None;
}
-DeviceError register_device_callback(uint32_t device_idx, DataHandleCallback callback, void* data, _Bool enable_VAD)
+DeviceError register_device_callback( int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, _Bool enable_VAD)
{
if (size[input] <= device_idx || !running[input][device_idx] || running[input][device_idx]->dhndl == NULL)
return de_InvalidSelection;
@@ -239,6 +285,7 @@ DeviceError register_device_callback(uint32_t device_idx, DataHandleCallback cal
running[input][device_idx]->cb = callback;
running[input][device_idx]->cb_data = data;
running[input][device_idx]->enable_VAD = enable_VAD;
+ running[input][device_idx]->call_idx = call_idx;
unlock;
return de_None;
@@ -265,7 +312,7 @@ inline__ DeviceError write_out(uint32_t device_idx, int16_t* data, uint32_t leng
Device* device = running[output][device_idx];
- if (!device) return de_DeviceNotActive;
+ if (!device || device->muted) return de_DeviceNotActive;
alcMakeContextCurrent(device->ctx); /* TODO: Check for error */
@@ -319,27 +366,27 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
{
lock;
if (running[input][i] != NULL)
-// do
{
-
alcGetIntegerv(running[input][i]->dhndl, ALC_CAPTURE_SAMPLES, sizeof(int32_t), &sample);
if (sample < f_size) {
unlock;
continue;
}
+ Device* device = running[input][i];
int16_t frame[4096];
- alcCaptureSamples(running[input][i]->dhndl, frame, f_size);
+ alcCaptureSamples(device->dhndl, frame, f_size);
- if ( running[input][i]->enable_VAD && !toxav_has_activity(frame, f_size, 88.5)) { unlock; continue; } /* Skip if no voice activity */
- if ( running[input][i]->cb ) running[input][i]->cb(frame, f_size, running[input][i]->cb_data);
+ if ( device->muted ||
+ (device->enable_VAD && !toxav_has_activity(av, device->call_idx, frame, f_size, device->VAD_treshold)))
+ { unlock; continue; } /* Skip if no voice activity */
+ if ( device->cb ) device->cb(frame, f_size, device->cb_data);
}
unlock;
-// while (_True);
}
-// usleep(10);
+ usleep(5000);
}
}
diff --git a/src/device.h b/src/device.h
index e71ba75..9715854 100644
--- a/src/device.h
+++ b/src/device.h
@@ -14,7 +14,7 @@
#define MAX_DEVICES 32
#include
-#include "toxic_windows.h"
+#include "windows.h"
#define _True 1
#define _False 0
@@ -43,9 +43,14 @@ DeviceError init_devices(ToxAv* av);
DeviceError terminate_devices();
/* Callback handles ready data from INPUT device */
-DeviceError register_device_callback(uint32_t device_idx, DataHandleCallback callback, void* data, _Bool enable_VAD);
+DeviceError register_device_callback(int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, _Bool enable_VAD);
void* get_device_callback_data(uint32_t device_idx);
+/* toggle device mute */
+DeviceError device_mute(DeviceType type, uint32_t device_idx);
+
+DeviceError device_set_VAD_treshold(uint32_t device_idx, float value);
+
DeviceError set_primary_device(DeviceType type, int32_t selection);
DeviceError open_primary_device(DeviceType type, uint32_t* device_idx);
/* Start device */
diff --git a/src/dns.c b/src/dns.c
new file mode 100644
index 0000000..8217cb2
--- /dev/null
+++ b/src/dns.c
@@ -0,0 +1,305 @@
+/* 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 .
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#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;
+ }
+
+ 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.self = self;
+ 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);
+}
diff --git a/src/dns.h b/src/dns.h
new file mode 100644
index 0000000..edd6579
--- /dev/null
+++ b/src/dns.h
@@ -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 .
+ *
+ */
+
+/* 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 */
diff --git a/src/execute.c b/src/execute.c
index 7dc18cb..62057c5 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -28,7 +28,8 @@
#include
#include
-#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 },
@@ -73,7 +75,9 @@ static struct cmd_func chat_commands[] = {
{ "/answer", cmd_answer },
{ "/reject", cmd_reject },
{ "/hangup", cmd_hangup },
- { "/sdev", cmd_set_this_session_device },
+ { "/sdev", cmd_ccur_device },
+ { "/mute", cmd_mute },
+ { "/sense", cmd_sense },
#endif /* _SUPPORT_AUDIO */
};
diff --git a/src/execute.h b/src/execute.h
index 57b0b26..20c55a3 100644
--- a/src/execute.h
+++ b/src/execute.h
@@ -20,11 +20,17 @@
*
*/
+#ifndef _execute_h
+#define _execute_h
+
+#include "toxic.h"
+#include "windows.h"
+
#define MAX_NUM_ARGS 4 /* Includes command */
#ifdef _SUPPORT_AUDIO
#define GLOBAL_NUM_COMMANDS 16
-#define CHAT_NUM_COMMANDS 11
+#define CHAT_NUM_COMMANDS 13
#else
#define GLOBAL_NUM_COMMANDS 14
#define CHAT_NUM_COMMANDS 5
@@ -37,3 +43,5 @@ enum {
};
void execute(WINDOW *w, ToxWindow *self, Tox *m, char *cmd, int mode);
+
+#endif /* #define _execute_h */
diff --git a/src/file_senders.c b/src/file_senders.c
index b8529d0..4d12a54 100644
--- a/src/file_senders.c
+++ b/src/file_senders.c
@@ -28,7 +28,9 @@
#include
#include
-#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) {
diff --git a/src/file_senders.h b/src/file_senders.h
index 9ec1cdc..59cc640 100644
--- a/src/file_senders.h
+++ b/src/file_senders.h
@@ -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 */
diff --git a/src/friendlist.c b/src/friendlist.c
index 874b01f..a1573de 100644
--- a/src/friendlist.c
+++ b/src/friendlist.c
@@ -31,6 +31,8 @@
#include
+#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;
@@ -162,9 +164,11 @@ static void friendlist_onStatusMessageChange(ToxWindow *self, int32_t num, uint8
if (len > TOX_MAX_STATUSMESSAGE_LENGTH || num >= max_friends_index)
return;
- strcpy(friends[num].statusmsg, str);
- friends[num].statusmsg[len] = '\0';
+ str[len] = '\0';
+ snprintf(friends[num].statusmsg, sizeof(friends[num].statusmsg), "%s", str);
+ len = strlen(friends[num].statusmsg);
friends[num].statusmsg_len = len;
+ friends[num].statusmsg[len] = '\0';
}
void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort)
diff --git a/src/friendlist.h b/src/friendlist.h
index 363cbea..f6cc9fd 100644
--- a/src/friendlist.h
+++ b/src/friendlist.h
@@ -24,10 +24,21 @@
#define FRIENDLIST_H_53I41IM
#include
-#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;
diff --git a/src/global_commands.c b/src/global_commands.c
index b51adca..cb0aa52 100644
--- a/src/global_commands.c
+++ b/src/global_commands.c
@@ -27,11 +27,13 @@
#include
#include
-#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.";
diff --git a/src/global_commands.h b/src/global_commands.h
index f8aec5b..688b6af 100644
--- a/src/global_commands.h
+++ b/src/global_commands.h
@@ -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 */
\ No newline at end of file
+#endif /* _SUPPORT_AUDIO */
+
+#endif /* #define _global_commands_h */
diff --git a/src/groupchat.c b/src/groupchat.c
index 741e122..f81fea8 100644
--- a/src/groupchat.c
+++ b/src/groupchat.c
@@ -28,7 +28,8 @@
#include
#include
-#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_index)
+ 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];
@@ -380,40 +389,42 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
int x, y, y2, x2;
getyx(self->window, y, x);
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);
+ if (x2 <= 0)
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);
+ int cur_len = 0; /* widechar len of current char */
+ int x2_is_odd = x2 % 2 != 0;
- if (x == x2 - 1)
- wmove(self->window, y + 1, 0);
- else
+ if (ltr) { /* char is printable */
+ if (ctx->len < MAX_STR_SIZE - 1) {
+ add_char_to_buf(ctx, key);
+
+ if (x >= x2 - 1) {
+ wmove(self->window, y, x2 / 2 + x2_is_odd);
+ ctx->start += x2 / 2;
+ } else {
wmove(self->window, y, x + MAX(1, wcwidth(key)));
+ }
}
} else { /* if (!ltr) */
- 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);
+ if (line_info_onKey(self, key))
+ return;
- if (x == 0)
- wmove(self->window, y - 1, x2 - cur_len);
- else
+ if (key == 0x107 || key == 0x8 || key == 0x7f) { /* BACKSPACE key */
+ if (ctx->pos > 0) {
+ cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
+ del_char_buf_bck(ctx);
+
+ if (x == 0) {
+ ctx->start = ctx->start >= x2 ? ctx->start - x2 : 0;
+ int new_x = ctx->start == 0 ? ctx->pos : x2 - cur_len;
+ wmove(self->window, y, new_x);
+ } else {
wmove(self->window, y, x - cur_len);
+ }
} else {
beep();
}
@@ -421,14 +432,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 +448,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();
}
@@ -445,6 +456,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
else if (key == KEY_HOME || key == T_KEY_C_A) { /* HOME/C-a key: Move cursor to start of line */
if (ctx->pos > 0) {
ctx->pos = 0;
+ ctx->start = 0;
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
}
}
@@ -452,7 +464,8 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
else if (key == KEY_END || key == T_KEY_C_E) { /* END/C-e key: move cursor to end of line */
if (ctx->pos != ctx->len) {
ctx->pos = ctx->len;
- mv_curs_end(self->window, MAX(0, wcswidth(ctx->line, (CHATBOX_HEIGHT - 1)*x2)), y2, x2);
+ ctx->start = x2 * (ctx->len / x2);
+ mv_curs_end(self->window, ctx->len, y2, x2);
}
}
@@ -461,10 +474,13 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
--ctx->pos;
cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
- if (x == 0)
- wmove(self->window, y - 1, x2 - cur_len);
- else
+ if (x == 0) {
+ wmove(self->window, y, x2 - cur_len);
+ ctx->start = ctx->start >= x2 ? ctx->start - x2 : 0;
+ ctx->pos = ctx->start + x2 - 1;
+ } else {
wmove(self->window, y, x - cur_len);
+ }
} else {
beep();
}
@@ -472,27 +488,30 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
else if (key == KEY_RIGHT) {
if (ctx->pos < ctx->len) {
- cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
++ctx->pos;
- if (x == x2 - 1)
- wmove(self->window, y + 1, 0);
- else
+ if (x == x2 - 1) {
+ wmove(self->window, y, 0);
+ ctx->start += x2;
+ ctx->pos = ctx->start;
+ } else {
+ cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
wmove(self->window, y, x + cur_len);
+ }
} else {
beep();
}
}
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);
+ ctx->start = x2 * (ctx->len / x2);
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);
+ ctx->start = x2 * (ctx->len / x2);
mv_curs_end(self->window, ctx->len, y2, x2);
}
@@ -501,11 +520,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 +541,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_RB) {
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_LB) {
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 +567,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 +591,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 +607,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[ctx->start]);
}
}
@@ -651,11 +667,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 +703,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;
diff --git a/src/groupchat.h b/src/groupchat.h
index afaa311..56f08b8 100644
--- a/src/groupchat.h
+++ b/src/groupchat.h
@@ -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 - 2
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 */
diff --git a/src/line_info.c b/src/line_info.c
index 6fc96bb..42d617f 100644
--- a/src/line_info.c
+++ b/src/line_info.c
@@ -28,56 +28,46 @@
#include
#include
-#include "toxic_windows.h"
+#include "toxic.h"
+#include "windows.h"
#include "line_info.h"
#include "groupchat.h"
+#include "settings.h"
+
+extern struct user_settings *user_settings;
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 ? 2 : 0;
+ int max_y = (y2 - CHATBOX_HEIGHT - top_offst);
+ while (line->prev && lncnt < max_y) {
+ lncnt += (1 + line->newlines) +( line->len / (x2 - side_offst));
line = line->prev;
}
-}
-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)
@@ -107,75 +97,117 @@ 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));
- int len = 1; /* there will always be a newline */
+ int len = 1; /* there will always be a newline */
/* 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;
}
if (msg) {
- strcpy(new_line->msg, msg);
- len += strlen(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) {
- strcpy(new_line->timestamp, tmstmp);
- len += strlen(tmstmp);
+ snprintf(new_line->timestamp, sizeof(new_line->timestamp), "%s", tmstmp);
+ len += strlen(new_line->timestamp);
}
if (name1) {
- strcpy(new_line->name1, name1);
- len += strlen(name1);
+ snprintf(new_line->name1, sizeof(new_line->name1), "%s", name1);
+ len += strlen(new_line->name1);
}
if (name2) {
- strcpy(new_line->name2, name2);
- len += strlen(name2);
+ snprintf(new_line->name2, sizeof(new_line->name2), "%s", name2);
+ len += strlen(new_line->name2);
}
new_line->len = len;
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 > MAX_HISTORY) {
- --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);
@@ -185,20 +217,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;
}
}
}
@@ -206,17 +233,22 @@ void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *na
void line_info_print(ToxWindow *self)
{
ChatContext *ctx = self->chatwin;
+
+ 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);
if (self->is_prompt)
- y2 = MAX_HISTORY; /* temporary fix to make prompt scroll */
+ y2 = user_settings->history_size; /* temporary fix to make prompt scroll */
if (x2 <= SIDEBAR_WIDTH)
return;
@@ -226,7 +258,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;
@@ -342,6 +374,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)
@@ -399,46 +435,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_F:
line_info_page_up(self, hst);
break;
- case KEY_NPAGE:
+ case T_KEY_C_V:
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;
+ break; */
- case KEY_END:
- line_info_reset_start(hst);
+ case T_KEY_C_H:
+ 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)
diff --git a/src/line_info.h b/src/line_info.h
index be0e1e3..b04f7cc 100644
--- a/src/line_info.h
+++ b/src/line_info.h
@@ -20,7 +20,15 @@
*
*/
-#define MAX_HISTORY 700
+#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,
@@ -42,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;
@@ -53,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);
@@ -71,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);
@@ -81,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 */
diff --git a/src/log.c b/src/log.c
index 63f3d40..d965895 100644
--- a/src/log.c
+++ b/src/log.c
@@ -29,7 +29,8 @@
#include
#include "configdir.h"
-#include "toxic_windows.h"
+#include "toxic.h"
+#include "windows.h"
#include "misc_tools.h"
#include "log.h"
#include "settings.h"
diff --git a/src/log.h b/src/log.h
index 9473eeb..0cb1ba2 100644
--- a/src/log.h
+++ b/src/log.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 */
diff --git a/src/misc_tools.c b/src/misc_tools.c
index 928c6b4..15641b1 100644
--- a/src/misc_tools.c
+++ b/src/misc_tools.c
@@ -29,7 +29,8 @@
#include
#include
-#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;
}
@@ -227,30 +226,35 @@ int valid_nick(uint8_t *nick)
/* Moves cursor to the end of the line in given window */
void mv_curs_end(WINDOW *w, size_t len, int max_y, int max_x)
{
- int end_y = (len / max_x) + (max_y - CURS_Y_OFFSET);
- int end_x = len % max_x;
- wmove(w, end_y, end_x);
+ int new_x = len < max_x ? len : len % max_x;
+ wmove(w, max_y - CURS_Y_OFFSET, new_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]);
+}
diff --git a/src/misc_tools.h b/src/misc_tools.h
index b5b2a93..87908f7 100644
--- a/src/misc_tools.h
+++ b/src/misc_tools.h
@@ -19,12 +19,22 @@
* along with Toxic. If not, see .
*
*/
+#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 lowercase */
+void str_to_lower(uint8_t *str);
+
+#endif /* #define _misc_tools_h */
diff --git a/src/prompt.c b/src/prompt.c
index 1a9f6cd..3609574 100644
--- a/src/prompt.c
+++ b/src/prompt.c
@@ -27,7 +27,8 @@
#include
#include
-#include "toxic_windows.h"
+#include "toxic.h"
+#include "windows.h"
#include "prompt.h"
#include "execute.h"
#include "misc_tools.h"
@@ -74,7 +75,7 @@ void prompt_update_nick(ToxWindow *prompt, uint8_t *nick, uint16_t len)
{
StatusBar *statusbar = prompt->stb;
snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick);
- statusbar->nick_len = len;
+ statusbar->nick_len = strlen(statusbar->nick);
}
/* Updates own statusmessage in prompt statusbar */
@@ -82,7 +83,7 @@ void prompt_update_statusmessage(ToxWindow *prompt, uint8_t *statusmsg, uint16_t
{
StatusBar *statusbar = prompt->stb;
snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg);
- statusbar->statusmsg_len = len;
+ statusbar->statusmsg_len = strlen(statusbar->statusmsg);
}
/* Updates own status in prompt statusbar */
@@ -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;
}
diff --git a/src/prompt.h b/src/prompt.h
index b120a65..405a3ec 100644
--- a/src/prompt.h
+++ b/src/prompt.h
@@ -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
diff --git a/src/settings.c b/src/settings.c
index 81d5bc9..8964723 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -20,95 +20,162 @@
*
*/
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
-#include
+
+#include "toxic.h"
+#include "windows.h"
+#include "configdir.h"
#ifdef _SUPPORT_AUDIO
#include "device.h"
#endif /* _SUPPORT_AUDIO */
-#include "toxic_windows.h"
-#include "configdir.h"
#include "settings.h"
+#include "line_info.h"
+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);
-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);
+#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 },
#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;
}
#ifdef _SUPPORT_AUDIO
-static void uset_ain_dev(struct user_settings *s, int val)
+static void uset_ain_dev(struct user_settings *s, const char *val)
{
- if (val < 0 || val > MAX_DEVICES)
- val = 0;
- s->audio_in_dev = 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 = 0;
+ int n = atoi(val);
- s->audio_out_dev = val;
+ if (n < 0 || n > MAX_DEVICES)
+ n = (long int) 0;
+
+ s->audio_out_dev = (long int) n;
}
#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 = (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)
+{
+ /* 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)
{
char *user_config_dir = get_user_config_dir();
FILE *fp = NULL;
char dflt_path[MAX_STR_SIZE];
-
+
if (path) {
fp = fopen(path, "r");
} else {
@@ -118,34 +185,37 @@ int settings_load(struct user_settings *s, char *path)
free(user_config_dir);
+ set_default_settings(s);
+
if (fp == NULL && !path) {
if ((fp = fopen(dflt_path, "w")) == NULL)
return -1;
} else if (fp == NULL && path) {
return -1;
}
-
+
char line[MAX_STR_SIZE];
while (fgets(line, sizeof(line), fp)) {
if (line[0] == '#' || !line[0])
continue;
-
+
const char *key = strtok(line, ":");
const char *val = strtok(NULL, ";");
-
+
if (key == NULL || val == NULL)
continue;
-
+
int i;
+
for (i = 0; i < NUM_SETTINGS; ++i) {
- if (strcmp(user_settings_list[i].name, key) == 0) {
- (user_settings_list[i].func)(s, atoi(val));
+ if (strcmp(user_settings_list[i].key, key) == 0) {
+ (user_settings_list[i].func)(s, val);
break;
}
}
- }
-
+ }
+
fclose(fp);
return 0;
}
diff --git a/src/settings.h b/src/settings.h
index 68a0e18..3400466 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -20,10 +20,15 @@
*
*/
+#ifndef _settings_h
+#define _settings_h
+
+#include "toxic.h"
+
#ifdef _SUPPORT_AUDIO
- #define NUM_SETTINGS 6
+ #define NUM_SETTINGS 8
#else
- #define NUM_SETTINGS 4
+ #define NUM_SETTINGS 6
#endif /* _SUPPORT_AUDIO */
/* holds user setting values */
@@ -32,11 +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
- int audio_in_dev;
- int audio_out_dev;
-#endif /* _SUPPORT_AUDIO */
+ long int audio_in_dev;
+ long int audio_out_dev;
+#endif
};
enum {
@@ -51,6 +58,10 @@ enum {
NATIVE_COLS = 1,
DFLT_COLS = 0,
-};
+
+ DFLT_HST_SIZE = 700,
+} settings_values;
int settings_load(struct user_settings *s, char *path);
+
+#endif /* #define _settings_h */
diff --git a/src/main.c b/src/toxic.c
similarity index 60%
rename from src/main.c
rename to src/toxic.c
index ccd2f14..0eeefe2 100644
--- a/src/main.c
+++ b/src/toxic.c
@@ -39,31 +39,24 @@
#include
#include
#include
-#include
-
-#ifdef _WIN32
-#include
-#include
-#include
-#else
+#include
#include
#include
#include
#include
#include
-#endif
#include
#include "configdir.h"
-#include "toxic_windows.h"
+#include "toxic.h"
+#include "windows.h"
#include "friendlist.h"
#include "prompt.h"
#include "misc_tools.h"
#include "file_senders.h"
#include "line_info.h"
#include "settings.h"
-#include "global_commands.h"
#ifdef _SUPPORT_AUDIO
#include "audio_call.h"
@@ -81,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, please check your locale settings or"
+ "disable wide char support", FATALERR_LOCALE_SET);
#endif
+
initscr();
cbreak();
keypad(stdscr, 1);
@@ -149,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;
@@ -170,11 +200,9 @@ static Tox *init_tox(int ipv4)
tox_callback_file_data(m, on_file_data, NULL);
#ifdef __linux__
- tox_set_name(m, (uint8_t *) "Cool guy", strlen("Cool guy"));
+ tox_set_name(m, (uint8_t *) "Cool dude", strlen("Cool dude"));
#elif defined(__FreeBSD__)
- tox_set_name(m, (uint8_t *) "Very cool guy", strlen("Very cool guy"));
-#elif defined(_WIN32)
- tox_set_name(m, (uint8_t *) "I should buy a Mac", strlen("I should install buy a Mac"));
+ tox_set_name(m, (uint8_t *) "Nerd", strlen("Nerd"));
#elif defined(__APPLE__)
tox_set_name(m, (uint8_t *) "Hipster", strlen("Hipster")); /* This used to users of other Unixes are hipsters */
#else
@@ -189,10 +217,12 @@ static Tox *init_tox(int ipv4)
#define MAXNODES 50
#define NODELEN (MAXLINE - TOX_CLIENT_ID_SIZE - 7)
-static int linecnt = 0;
-static char nodes[MAXNODES][NODELEN];
-static uint16_t ports[MAXNODES];
-static uint8_t keys[MAXNODES][TOX_CLIENT_ID_SIZE];
+static struct _toxNodes {
+ int lines;
+ char nodes[MAXNODES][NODELEN];
+ uint16_t ports[MAXNODES];
+ uint8_t keys[MAXNODES][TOX_CLIENT_ID_SIZE];
+} toxNodes;
static int nodelist_load(char *filename)
{
@@ -206,29 +236,29 @@ static int nodelist_load(char *filename)
char line[MAXLINE];
- while (fgets(line, sizeof(line), fp) && linecnt < MAXNODES) {
+ while (fgets(line, sizeof(line), fp) && toxNodes.lines < 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);
- nodes[linecnt][NODELEN - 1] = 0;
- ports[linecnt] = htons(atoi(port));
+ snprintf(toxNodes.nodes[toxNodes.lines], sizeof(toxNodes.nodes[toxNodes.lines]), "%s", name);
+ toxNodes.nodes[toxNodes.lines][NODELEN - 1] = 0;
+ toxNodes.ports[toxNodes.lines] = htons(atoi(port));
uint8_t *key_binary = hex_string_to_bin(key_ascii);
- memcpy(keys[linecnt], key_binary, TOX_CLIENT_ID_SIZE);
+ memcpy(toxNodes.keys[toxNodes.lines], key_binary, TOX_CLIENT_ID_SIZE);
free(key_binary);
- linecnt++;
+ toxNodes.lines++;
}
}
- if (linecnt < 1) {
+ if (toxNodes.lines < 1) {
fclose(fp);
return 2;
}
@@ -239,8 +269,8 @@ static int nodelist_load(char *filename)
int init_connection_helper(Tox *m, int line)
{
- return tox_bootstrap_from_address(m, nodes[line], TOX_ENABLE_IPV6_DEFAULT,
- ports[line], keys[line]);
+ return tox_bootstrap_from_address(m, toxNodes.nodes[line], TOX_ENABLE_IPV6_DEFAULT,
+ toxNodes.ports[line], toxNodes.keys[line]);
}
/* Connects to a random DHT node listed in the DHTnodes file
@@ -257,8 +287,8 @@ static bool srvlist_loaded = false;
int init_connection(Tox *m)
{
- if (linecnt > 0) /* already loaded nodelist */
- return init_connection_helper(m, rand() % linecnt) ? 0 : 3;
+ if (toxNodes.lines > 0) /* already loaded nodelist */
+ return init_connection_helper(m, rand() % toxNodes.lines) ? 0 : 3;
/* only once:
* - load the nodelist
@@ -266,17 +296,22 @@ int init_connection(Tox *m)
*/
if (!srvlist_loaded) {
srvlist_loaded = true;
- int res = nodelist_load(PACKAGE_DATADIR "/DHTnodes");
+ int res;
- if (linecnt < 1)
+ if (!arg_opts.nodes_path[0])
+ res = nodelist_load(PACKAGE_DATADIR "/DHTnodes");
+ else
+ res = nodelist_load(arg_opts.nodes_path);
+
+ if (toxNodes.lines < 1)
return res;
res = 3;
int i;
- int n = MIN(NUM_INIT_NODES, linecnt);
+ int n = MIN(NUM_INIT_NODES, toxNodes.lines);
for (i = 0; i < n; ++i) {
- if (init_connection_helper(m, rand() % linecnt))
+ if (init_connection_helper(m, rand() % toxNodes.lines))
res = 0;
}
@@ -287,30 +322,37 @@ int init_connection(Tox *m)
return 4;
}
+#define TRY_CONNECT 10
+
static void do_connection(Tox *m, ToxWindow *prompt)
{
uint8_t msg[MAX_STR_SIZE] = {0};
- static int conn_try = 0;
static int conn_err = 0;
- static bool dht_on = false;
-
+ static bool was_connected = false;
+ static uint64_t last_conn_try = 0;
+ uint64_t curtime = get_unix_time();
bool is_connected = tox_isconnected(m);
- if (!dht_on && !is_connected && !(conn_try++ % 100)) {
- if (!conn_err) {
- if ((conn_err = init_connection(m))) {
- snprintf(msg, sizeof(msg), "\nAuto-connect failed with error code %d", conn_err);
- }
- }
- } else if (!dht_on && is_connected) {
- dht_on = true;
- prompt_update_connectionstatus(prompt, dht_on);
+ if (was_connected && is_connected)
+ return;
+
+ if (!was_connected && is_connected) {
+ was_connected = true;
+ prompt_update_connectionstatus(prompt, was_connected);
snprintf(msg, sizeof(msg), "DHT connected.");
- } else if (dht_on && !is_connected) {
- dht_on = false;
- prompt_update_connectionstatus(prompt, dht_on);
- snprintf(msg, sizeof(msg), "\nDHT disconnected. Attempting to reconnect.");
+ } else if (was_connected && !is_connected) {
+ was_connected = false;
+ prompt_update_connectionstatus(prompt, was_connected);
+ snprintf(msg, sizeof(msg), "DHT disconnected. Attempting to reconnect.");
+ } else if (!was_connected && !is_connected && timed_out(last_conn_try, curtime, TRY_CONNECT)) {
+ /* if autoconnect has already failed there's no point in trying again */
+ if (conn_err == 0) {
+ last_conn_try = curtime;
+
+ if ((conn_err = init_connection(m)) != 0)
+ snprintf(msg, sizeof(msg), "Auto-connect failed with error code %d", conn_err);
+ }
}
if (msg[0])
@@ -336,7 +378,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)
@@ -374,7 +416,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;
@@ -390,17 +432,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);
@@ -411,44 +449,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);
}
@@ -457,72 +469,86 @@ void *thread_winref(void *data)
{
Tox *m = (Tox *) data;
- while (true)
+ while (true) {
draw_active_window(m);
+ refresh_inactive_windows();
+ }
}
-int exit_print(char* exe_name, char* invalid_arg, char* error_str)
+static void print_usage(void)
{
- const char* help_str =
- "usage: \n"
- " -f tox protocol data file path \n"
- " -s custom settings path \n"
- " -n don't load from data file (create new profile) \n"
- " -h print this help \n"
- " -4 force ipv4 \n";
-
- if (!error_str && !invalid_arg) {
- printf("%s %s", exe_name, help_str);
- return 0;
- } else if (invalid_arg) {
- fprintf(stderr, "%s invalid arg: %s", exe_name, invalid_arg);
- return 1;
- } else if (error_str) {
- fprintf(stderr, "%s error: %s", exe_name, error_str);
- return 1;
+ 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(), *settings_path = NULL;
+ char *user_config_dir = get_user_config_dir();
int config_err = 0;
- f_loadfromfile = 1;
- 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 = 1; i < argc; ++i) {
- if (argv[i][0] == '-') {
- if (argv[i][1] == 'f') {
- ++i;
- if (i < argc)
- DATA_FILE = strdup(argv[i]);
- else
- return exit_print(argv[0], NULL, "argument 'f' requires value");
-
- } else if (argv[i][1] == 'n') {
- f_loadfromfile = 0;
- } else if (argv[i][1] == 'h') {
- return exit_print(argv[0], NULL, NULL);
- } else if (argv[i][1] == '4') {
- f_use_ipv4 = 1;
- } else if (argv[i][1] == 's') {
- ++i;
- if (i < argc)
- settings_path = argv[i];
- else
- return exit_print(argv[0], NULL, "argument 's' requires value");
- } else {
- return exit_print(argv[0], argv[i]+1, NULL); /* Invalid arg */
- }
- } else {
- return exit_print(argv[0], argv[i], NULL); /* Invalid value/arg */
- }
- }
+ signal(SIGINT, ignore_SIGINT);
config_err = create_user_config_dir(user_config_dir);
@@ -532,15 +558,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");
}
}
@@ -549,41 +572,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, settings_path);
- 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;
@@ -591,18 +605,10 @@ int main(int argc, char *argv[])
av = init_audio(prompt, m);
-// device_set(prompt, input, user_settings->audio_in_dev);
-// device_set(prompt, output, user_settings->audio_out_dev);
set_primary_device(input, user_settings->audio_in_dev);
set_primary_device(output, user_settings->audio_out_dev);
- char* string = malloc(1000);
- sprintf(string, "i:%d o:%d", user_settings->audio_in_dev, user_settings->audio_out_dev);
-
- line_info_add(prompt, NULL, NULL, NULL, string, SYS_MSG, 0, 0);
- cmd_myid(NULL, prompt, m, 0, NULL);
-
#endif /* _SUPPORT_AUDIO */
if (config_err) {
diff --git a/src/toxic.h b/src/toxic.h
new file mode 100644
index 0000000..1a78e64
--- /dev/null
+++ b/src/toxic.h
@@ -0,0 +1,100 @@
+/* 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 .
+ *
+ */
+
+#ifndef _toxic_h
+#define _toxic_h
+
+#ifndef TOXICVER
+#define TOXICVER "NOVER_" /* Use the -D flag to set this */
+#endif
+
+#include
+#include
+
+#include
+
+#define UNKNOWN_NAME "Anonymous"
+
+#define MAX_FRIENDS_NUM 500
+#define MAX_STR_SIZE 1024
+#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_V 0x16 /* ctrl-v */
+#define T_KEY_C_F 0x06 /* ctrl-f */
+#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 */
diff --git a/src/toxic_strings.c b/src/toxic_strings.c
index 994c0fd..d78af0e 100644
--- a/src/toxic_strings.c
+++ b/src/toxic_strings.c
@@ -27,160 +27,181 @@
#include
#include
-#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->start = 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, len and start 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;
+ ctx->start = 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 +209,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 +248,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 +266,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;
}
diff --git a/src/toxic_strings.h b/src/toxic_strings.h
index 84bb3f7..8c7e12a 100644
--- a/src/toxic_strings.h
+++ b/src/toxic_strings.h
@@ -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, len and start 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 */
diff --git a/src/windows.c b/src/windows.c
index 564da15..1295248 100644
--- a/src/windows.c
+++ b/src/windows.c
@@ -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();
@@ -417,7 +421,7 @@ void draw_active_window(Tox *m)
ltr = isprint(ch);
#endif
- if (!ltr && (ch == T_KEY_NEXT || ch == T_KEY_PREV) ) {
+ if (!ltr && (ch == T_KEY_NEXT || ch == T_KEY_PREV)) {
set_next_window((int) ch);
} else {
pthread_mutex_lock(&Winthread.lock);
@@ -426,6 +430,20 @@ void draw_active_window(Tox *m)
}
}
+/* refresh inactive windows to prevent scrolling bugs.
+ call at least once per second */
+void refresh_inactive_windows(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
+ ToxWindow *a = &windows[i];
+
+ if (a->active && a != active_window && (a->is_chat || a->is_groupchat))
+ line_info_print(a);
+ }
+}
+
int get_num_active_windows(void)
{
return num_active_windows;
diff --git a/src/toxic_windows.h b/src/windows.h
similarity index 58%
rename from src/toxic_windows.h
rename to src/windows.h
index 29addf1..169701d 100644
--- a/src/toxic_windows.h
+++ b/src/windows.h
@@ -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
#include
#include
#include
@@ -38,31 +33,11 @@
#include
#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 */
+#define CURS_Y_OFFSET 1 /* y-axis cursor offset for chat contexts */
+#define CHATBOX_HEIGHT 2
/* 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);
@@ -176,6 +151,7 @@ struct ChatContext {
wchar_t line[MAX_STR_SIZE];
size_t pos;
size_t len;
+ size_t start; /* the position to start printing line at */
wchar_t ln_history[MAX_LINE_HIST][MAX_STR_SIZE]; /* history for input lines/commands */
int hst_pos;
@@ -195,67 +171,13 @@ struct ChatContext {
int orig_y; /* y axis point of line origin */
};
-/* Start file transfer code */
-
-#define MAX_FILES 256
-#define FILE_PIECE_SIZE 1024
-#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 */