mirror of
https://github.com/Tha14/toxic.git
synced 2024-11-26 22:33:27 +01:00
Synced to master
This commit is contained in:
commit
d06581fe1d
47
.travis.yml
Normal file
47
.travis.yml
Normal file
@ -0,0 +1,47 @@
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
before_script:
|
||||
# installing libsodium, needed for Core
|
||||
- git clone git://github.com/jedisct1/libsodium.git
|
||||
- cd libsodium
|
||||
- git checkout tags/0.4.2
|
||||
- ./autogen.sh
|
||||
- ./configure && make check -j3
|
||||
- sudo make install
|
||||
- cd ..
|
||||
# installing libconfig, needed for DHT_bootstrap_daemon
|
||||
- wget http://www.hyperrealm.com/libconfig/libconfig-1.4.9.tar.gz
|
||||
- tar -xvzf libconfig-1.4.9.tar.gz
|
||||
- cd libconfig-1.4.9
|
||||
- ./configure && make -j3
|
||||
- sudo make install
|
||||
- cd ..
|
||||
# creating librarys' links and updating cache
|
||||
- sudo ldconfig
|
||||
# installing sphinx, needed for documentation
|
||||
- sudo apt-get install python-sphinx
|
||||
# installing check, needed for unit tests
|
||||
- sudo apt-get install check
|
||||
|
||||
- git clone https://github.com/irungentoo/ProjectTox-Core.git toxcore
|
||||
- cd toxcore
|
||||
- autoreconf -i
|
||||
- ./configure
|
||||
- make -j2
|
||||
- sudo make install
|
||||
- cd ..
|
||||
script:
|
||||
- autoreconf -i
|
||||
- ./configure
|
||||
- make -j2
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
irc:
|
||||
channels:
|
||||
- "chat.freenode.net#tox-dev"
|
||||
on_success: always
|
||||
on_failure: always
|
@ -2,3 +2,4 @@ SUBDIRS = build misc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
AM_CFLAGS = -wall -c89 -werror
|
||||
|
@ -1,6 +1,6 @@
|
||||
## Toxic - console client for [Tox](http://tox.im)
|
||||
|
||||
The client formerly resided in the [Tox core repository](https://github.com/irungentoo/ProjectTox-Core) and is now available as a standalone verion.
|
||||
The client formerly resided in the [Tox core repository](https://github.com/irungentoo/ProjectTox-Core) and is now available as a standalone version.
|
||||
|
||||
To compile, first generate the configure script by running the ```autoreconf -i``` command.
|
||||
|
||||
|
@ -11,9 +11,7 @@ toxic_SOURCES = $(top_srcdir)/src/main.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/dhtstatus.h \
|
||||
$(top_srcdir)/src/dhtstatus.c
|
||||
$(top_srcdir)/src/windows.c
|
||||
|
||||
toxic_CFLAGS = -I$(top_srcdir) \
|
||||
$(NCURSES_CFLAGS) \
|
||||
|
174
configure.ac
174
configure.ac
@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.65])
|
||||
AC_INIT([toxic], [0.1.1], [http://tox.im/])
|
||||
AC_INIT([toxic], [0.2.0], [http://tox.im/])
|
||||
AC_CONFIG_AUX_DIR(configure_aux)
|
||||
AC_CONFIG_SRCDIR([src/main.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
@ -20,6 +20,10 @@ LIBTOXCORE_SEARCH_LIBS=
|
||||
LIBSODIUM_SEARCH_HEADERS=
|
||||
LIBSODIUM_SEARCH_LIBS=
|
||||
|
||||
LIBTOXCORE_FOUND="no"
|
||||
NCURSES_FOUND="no"
|
||||
NCURSES_WIDECHAR_SUPPORT="no"
|
||||
|
||||
AC_ARG_WITH(dependency-search,
|
||||
AC_HELP_STRING([--with-dependency-search=DIR],
|
||||
[search for dependencies in DIR, i.e. look for libraries in
|
||||
@ -38,7 +42,7 @@ fi
|
||||
|
||||
AC_ARG_WITH(libtoxcore-headers,
|
||||
AC_HELP_STRING([--with-libtoxcore-headers=DIR],
|
||||
[search for libtoxcore header files in DIR]),
|
||||
[search for libtoxcore header files in DIR/tox]),
|
||||
[
|
||||
LIBTOXCORE_SEARCH_HEADERS="$withval"
|
||||
AC_MSG_NOTICE([Will search for libtoxcore header files in $withval])
|
||||
@ -78,9 +82,13 @@ case $host_os in
|
||||
*mingw*)
|
||||
WIN32="yes"
|
||||
;;
|
||||
*freebsd*)
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
CFLAGS="$CFLAGS -I/usr/local/include"
|
||||
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
@ -108,17 +116,21 @@ AC_CHECK_FUNCS(
|
||||
# pkg-config based tests
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
NCURSES_WIDECHAR_SUPPORT="yes"
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
if test "$WIN32" != "xyes"; then
|
||||
if test "x$WIN32" != "xyes"; then
|
||||
PKG_CHECK_MODULES([NCURSES], [ncursesw],
|
||||
[],
|
||||
[
|
||||
NCURSES_FOUND="yes"
|
||||
NCURSES_WIDECHAR_SUPPORT="yes"
|
||||
],
|
||||
[
|
||||
NCURSES_WIDECHAR_SUPPORT="no"
|
||||
PKG_CHECK_MODULES([NCURSES], [ncurses],
|
||||
[],
|
||||
[
|
||||
AC_MSG_ERROR([required library ncursesw was not found on your system: $NCURSES_PKG_ERRORS])
|
||||
NCURSES_FOUND="yes"
|
||||
],
|
||||
[
|
||||
AC_MSG_WARN([$NCURSES_PKG_ERRORS])
|
||||
])
|
||||
])
|
||||
fi
|
||||
@ -126,8 +138,80 @@ else
|
||||
AC_MSG_WARN([pkg-config was not found on your sytem])
|
||||
fi
|
||||
|
||||
if (test "x$NCURSES_FOUND" = "xno") && (test "x$WIN32" != "xyes"); then
|
||||
AC_PATH_PROG([CURSES_CONFIG], [ncursesw5-config], [no])
|
||||
if test "x$CURSES_CONFIG" != "xno"; then
|
||||
AC_MSG_CHECKING(ncurses cflags)
|
||||
NCURSES_CFLAGS=`${CURSES_CONFIG} --cflags`
|
||||
AC_MSG_RESULT($NCURSES_CFLAGS)
|
||||
|
||||
if (test -z "$PKG_CONFIG") || (test "x$WIN32" = "xyes"); then
|
||||
AC_MSG_CHECKING(ncurses libraries)
|
||||
NCURSES_LIBS=`${CURSES_CONFIG} --libs`
|
||||
AC_MSG_RESULT($NCURSES_LIBS)
|
||||
|
||||
AC_SUBST(NCURSES_CFLAGS)
|
||||
AC_SUBST(NCURSES_LIBS)
|
||||
NCURSES_FOUND="yes"
|
||||
NCURSES_WIDECHAR_SUPPORT="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
if (test "x$NCURSES_FOUND" = "xno") && (test "x$WIN32" != "xyes"); then
|
||||
unset ac_cv_path_CURSES_CONFIG
|
||||
AC_PATH_PROG([CURSES_CONFIG], [ncursesw5.4-config], [no])
|
||||
if test "x$CURSES_CONFIG" != "xno"; then
|
||||
AC_MSG_CHECKING(ncurses cflags)
|
||||
NCURSES_CFLAGS=`${CURSES_CONFIG} --cflags`
|
||||
AC_MSG_RESULT($NCURSES_CFLAGS)
|
||||
|
||||
AC_MSG_CHECKING(ncurses libraries)
|
||||
NCURSES_LIBS=`${CURSES_CONFIG} --libs`
|
||||
AC_MSG_RESULT($NCURSES_LIBS)
|
||||
|
||||
AC_SUBST(NCURSES_CFLAGS)
|
||||
AC_SUBST(NCURSES_LIBS)
|
||||
NCURSES_FOUND="yes"
|
||||
NCURSES_WIDECHAR_SUPPORT="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
if (test "x$NCURSES_FOUND" = "xno") && (test "x$WIN32" != "xyes"); then
|
||||
unset ac_cv_path_CURSES_CONFIG
|
||||
AC_PATH_PROG([CURSES_CONFIG], [ncurses5-config], [no])
|
||||
if test "x$CURSES_CONFIG" != "xno"; then
|
||||
AC_MSG_CHECKING(ncurses cflags)
|
||||
NCURSES_CFLAGS=`${CURSES_CONFIG} --cflags`
|
||||
AC_MSG_RESULT($NCURSES_CFLAGS)
|
||||
|
||||
AC_MSG_CHECKING(ncurses libraries)
|
||||
NCURSES_LIBS=`${CURSES_CONFIG} --libs`
|
||||
AC_MSG_RESULT($NCURSES_LIBS)
|
||||
|
||||
AC_SUBST(NCURSES_CFLAGS)
|
||||
AC_SUBST(NCURSES_LIBS)
|
||||
NCURSES_FOUND="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
if (test "x$NCURSES_FOUND" = "xno") && (test "x$WIN32" != "xyes"); then
|
||||
unset ac_cv_path_CURSES_CONFIG
|
||||
AC_PATH_PROG([CURSES_CONFIG], [ncurses5.4-config], [no])
|
||||
if test "x$CURSES_CONFIG" != "xno"; then
|
||||
AC_MSG_CHECKING(ncurses cflags)
|
||||
NCURSES_CFLAGS=`${CURSES_CONFIG} --cflags`
|
||||
AC_MSG_RESULT($NCURSES_CFLAGS)
|
||||
|
||||
AC_MSG_CHECKING(ncurses libraries)
|
||||
NCURSES_LIBS=`${CURSES_CONFIG} --libs`
|
||||
AC_MSG_RESULT($NCURSES_LIBS)
|
||||
|
||||
AC_SUBST(NCURSES_CFLAGS)
|
||||
AC_SUBST(NCURSES_LIBS)
|
||||
NCURSES_FOUND="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$NCURSES_FOUND" = "xno"; then
|
||||
AC_CHECK_HEADER([curses.h],
|
||||
[],
|
||||
[
|
||||
@ -154,19 +238,25 @@ if (test -z "$PKG_CONFIG") || (test "x$WIN32" = "xyes"); then
|
||||
AC_MSG_ERROR([required library winsock2 was not found on the system, please check your MinGW installation])
|
||||
]
|
||||
)
|
||||
AC_DEFINE([_WIN32_WINNT], [0x501],
|
||||
[enable getaddrinfo/freeaddrinfo on XP and higher])
|
||||
else
|
||||
AC_CHECK_LIB([ncursesw], [get_wch],
|
||||
[],
|
||||
AC_CHECK_LIB([ncursesw], [wget_wch],
|
||||
[
|
||||
unset ac_cv_lib_ncursesw_get_wch
|
||||
AC_CHECK_LIB([ncursesw], [get_wch],
|
||||
[],
|
||||
NCURSES_WIDECHAR_SUPPORT="yes"
|
||||
],
|
||||
[
|
||||
unset ac_cv_lib_ncursesw_wget_wch
|
||||
AC_CHECK_LIB([ncursesw], [wget_wch],
|
||||
[
|
||||
NCURSES_WIDECHAR_SUPPORT="yes"
|
||||
],
|
||||
[
|
||||
NCURSES_WIDECHAR_SUPPORT="no"
|
||||
AC_CHECK_LIB([ncurses], [clear],
|
||||
[],
|
||||
[
|
||||
unset ac_cv_lib_ncursesw_get_wch
|
||||
unset ac_cv_lib_ncurses_clear
|
||||
AC_CHECK_LIB([ncurses], [clear],
|
||||
[],
|
||||
[
|
||||
@ -188,34 +278,17 @@ if (test -z "$PKG_CONFIG") || (test "x$WIN32" = "xyes"); then
|
||||
fi
|
||||
fi
|
||||
|
||||
# sodium is included by Tox headers so we kind of need to know where it is
|
||||
LIBSODIUM_CFLAGS=
|
||||
CFLAGS_SAVE="$CFLAGS"
|
||||
CPPFLAGS_SAVE="$CPPFLAGS"
|
||||
if test -n "$LIBSODIUM_SEARCH_HEADERS"; then
|
||||
CFLAGS="$CFLAGS -I$LIBSODIUM_SEARCH_HEADERS"
|
||||
CPPFLAGS="$CFLAGS -I$LIBSODIUM_SEARCH_HEADERS"
|
||||
AC_CHECK_HEADER(sodium.h,
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
PKG_CHECK_MODULES(LIBTOXCORE, [libtoxcore],
|
||||
[
|
||||
LIBSODIUM_CFLAGS="-I$LIBSODIUM_SEARCH_HEADERS"
|
||||
LIBTOXCORE_FOUND="yes"
|
||||
],
|
||||
[
|
||||
AC_MSG_ERROR([header files for required library libsodium was not found in requested location $LIBSODIUM_SEARCH_HEADERS])
|
||||
]
|
||||
)
|
||||
else
|
||||
AC_CHECK_HEADER(sodium.h,
|
||||
[],
|
||||
[
|
||||
AC_MSG_ERROR([header files for required library libsodium was not found on your system, please check http://download.libsodium.org/libsodium/releases/])
|
||||
]
|
||||
)
|
||||
AC_MSG_WARN([required library libsodium was not found in requested location $LIBSODIUM_SEARCH_LIBS])
|
||||
])
|
||||
fi
|
||||
CFLAGS="$CFLAGS_SAVE"
|
||||
CPPFLAGS="$CPPFLAGS_SAVE"
|
||||
AC_SUBST(LIBSODIUM_CFLAGS)
|
||||
|
||||
|
||||
if test "x$LIBTOXCORE_FOUND" = "xno"; then
|
||||
LIBSODIUM_LIBS=
|
||||
LIBSODIUM_LDFLAGS=
|
||||
LDFLAGS_SAVE="$LDFLAGS"
|
||||
@ -250,9 +323,9 @@ CFLAGS_SAVE="$CFLAGS"
|
||||
CPPFLAGS_SAVE="$CPPFLAGS"
|
||||
|
||||
if test -n "$LIBTOXCORE_SEARCH_HEADERS"; then
|
||||
CFLAGS="$CFLAGS -I$LIBTOXCORE_SEARCH_HEADERS $LIBSODIUM_CFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS -I$LIBTOXCORE_SEARCH_HEADERS $LIBSODIUM_CFLAGS"
|
||||
AC_CHECK_HEADER([Messenger.h],
|
||||
CFLAGS="$CFLAGS -I$LIBTOXCORE_SEARCH_HEADERS"
|
||||
CPPFLAGS="$CPPFLAGS -I$LIBTOXCORE_SEARCH_HEADERS"
|
||||
AC_CHECK_HEADER([tox/tox.h],
|
||||
[
|
||||
LIBTOXCORE_CFLAGS="-I$LIBTOXCORE_SEARCH_HEADERS"
|
||||
],
|
||||
@ -261,13 +334,11 @@ if test -n "$LIBTOXCORE_SEARCH_HEADERS"; then
|
||||
]
|
||||
)
|
||||
else
|
||||
CFLAGS="$CFLAGS $LIBSODIUM_CFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $LIBSODIUM_CFLAGS"
|
||||
AC_CHECK_HEADER([Messenger.h],
|
||||
AC_CHECK_HEADER([tox/tox.h],
|
||||
[],
|
||||
[
|
||||
AC_MSG_ERROR([headers for the toxcore library were not found on your system])
|
||||
]
|
||||
],
|
||||
)
|
||||
fi
|
||||
CFLAGS="$CFLAGS_SAVE"
|
||||
@ -279,29 +350,34 @@ LIBTOXCORE_LDFLAGS=
|
||||
LDFLAGS_SAVE="$LDFLAGS"
|
||||
if test -n "$LIBTOXCORE_SEARCH_LIBS"; then
|
||||
LDFLAGS="$LDFLAGS $LIBSODIUM_LDFLAGS -L$LIBTOXCORE_SEARCH_LIBS $LIBSODIUM_LIBS"
|
||||
AC_CHECK_LIB([toxcore], [initMessenger],
|
||||
AC_CHECK_LIB([toxcore], [tox_new],
|
||||
[
|
||||
LIBTOXCORE_LDFLAGS="-L$LIBTOXCORE_SEARCH_LIBS"
|
||||
LIBTOXCORE_LIBS="-ltoxcore"
|
||||
],
|
||||
[
|
||||
AC_MSG_ERROR([required library toxcore was not found on your system])
|
||||
],
|
||||
[
|
||||
$WINSOCK2_LIBS
|
||||
]
|
||||
)
|
||||
else
|
||||
LDFLAGS="$LDFLAGS $LIBSODIUM_LDFLAGS $LIBSODIUM_LIBS"
|
||||
AC_CHECK_LIB([toxcore], [initMessenger],
|
||||
AC_CHECK_LIB([toxcore], [tox_new],
|
||||
[],
|
||||
[
|
||||
AC_MSG_ERROR([required library toxcore was not found on your system])
|
||||
],
|
||||
[
|
||||
$WINSOCK2_LIBS
|
||||
]
|
||||
)
|
||||
fi
|
||||
LDFLAGS="$LDFLAGS_SAVE"
|
||||
AC_SUBST(LIBTOXCORE_LIBS)
|
||||
AC_SUBST(LIBTOXCORE_LDFLAGS)
|
||||
|
||||
|
||||
fi
|
||||
|
||||
TOXIC_VERSION="$PACKAGE_VERSION"
|
||||
AC_PATH_PROG([GIT], [git], [no])
|
||||
|
@ -1,9 +1,7 @@
|
||||
192.81.133.111 33445 8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858
|
||||
66.175.223.88 33445 AC4112C975240CAD260BB2FCD134266521FAAF0A5D159C5FD3201196191E4F5D
|
||||
66.175.223.88 33445 B24E2FB924AE66D023FE1E42A2EE3B432010206F751A2FFD3E297383ACF1572E
|
||||
192.184.81.118 33445 5CD7EB176C19A2FD840406CD56177BB8E75587BB366F7BB3004B19E3EDC04143
|
||||
192.210.149.121 33445 F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67
|
||||
81.224.34.47 443 48F0D94C0D54EB1995A2ECEDE7DB6BDD5E05D81704B2F3D1BB9FE43AC97B7269
|
||||
198.46.136.167 33445 728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854
|
||||
95.47.140.214 33445 F4BF7C5A9D0EF4CB684090C38DE937FAE1612021F21FEA4DCBFAC6AAFEF58E68
|
||||
54.215.145.71 33445 6EDDEE2188EF579303C0766B4796DCBA89C93058B6032FEA51593DCD42FB746C
|
||||
66.74.30.125 33445 7155386A691E7BD3C4C0589D70ACDA191D488634772885CCED5DD7B3F7E6310D
|
||||
|
589
src/chat.c
589
src/chat.c
@ -9,30 +9,27 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "Messenger.h"
|
||||
#include "network.h"
|
||||
|
||||
#include "toxic_windows.h"
|
||||
#include "friendlist.h"
|
||||
#include "chat.h"
|
||||
|
||||
#define CURS_Y_OFFSET 3
|
||||
|
||||
extern char *DATA_FILE;
|
||||
extern int store_data(Tox *m, char *path);
|
||||
|
||||
typedef struct {
|
||||
int friendnum;
|
||||
wchar_t line[MAX_STR_SIZE];
|
||||
size_t pos;
|
||||
WINDOW *history;
|
||||
WINDOW *linewin;
|
||||
} ChatContext;
|
||||
|
||||
void print_help(ChatContext *self);
|
||||
void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd);
|
||||
|
||||
struct tm *get_time(void)
|
||||
{
|
||||
struct tm *timeinfo;
|
||||
@ -42,22 +39,21 @@ struct tm *get_time(void)
|
||||
return timeinfo;
|
||||
}
|
||||
|
||||
static void chat_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *msg, uint16_t len)
|
||||
static void chat_onMessage(ToxWindow *self, Tox *m, int num, uint8_t *msg, uint16_t len)
|
||||
{
|
||||
ChatContext *ctx = (ChatContext *) self->x;
|
||||
uint8_t nick[MAX_NAME_LENGTH] = {0};
|
||||
struct tm *timeinfo = get_time();
|
||||
|
||||
if (ctx->friendnum != num)
|
||||
if (self->friendnum != num)
|
||||
return;
|
||||
|
||||
getname(m, num, (uint8_t *) &nick);
|
||||
msg[len - 1] = '\0';
|
||||
nick[MAX_NAME_LENGTH - 1] = '\0';
|
||||
ChatContext *ctx = (ChatContext *) self->x;
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(2));
|
||||
struct tm *timeinfo = get_time();
|
||||
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
|
||||
tox_getname(m, num, nick);
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(CYAN));
|
||||
wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
|
||||
wattroff(ctx->history, COLOR_PAIR(2));
|
||||
wattroff(ctx->history, COLOR_PAIR(CYAN));
|
||||
wattron(ctx->history, COLOR_PAIR(4));
|
||||
wprintw(ctx->history, "%s: ", nick);
|
||||
wattroff(ctx->history, COLOR_PAIR(4));
|
||||
@ -67,23 +63,33 @@ static void chat_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *msg,
|
||||
beep();
|
||||
}
|
||||
|
||||
static void chat_onAction(ToxWindow *self, Messenger *m, int num, uint8_t *action, uint16_t len)
|
||||
void chat_onConnectionChange(ToxWindow *self, Tox *m, int num, uint8_t status)
|
||||
{
|
||||
if (self->friendnum != num)
|
||||
return;
|
||||
|
||||
StatusBar *statusbar = (StatusBar *) self->s;
|
||||
statusbar->is_online = status == 1 ? true : false;
|
||||
}
|
||||
|
||||
static void chat_onAction(ToxWindow *self, Tox *m, int num, uint8_t *action, uint16_t len)
|
||||
{
|
||||
if (self->friendnum != num)
|
||||
return;
|
||||
|
||||
ChatContext *ctx = (ChatContext *) self->x;
|
||||
struct tm *timeinfo = get_time();
|
||||
|
||||
if (ctx->friendnum != num)
|
||||
return;
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
|
||||
tox_getname(m, num, nick);
|
||||
|
||||
action[len - 1] = '\0';
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(2));
|
||||
wattron(ctx->history, COLOR_PAIR(CYAN));
|
||||
wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
|
||||
wattroff(ctx->history, COLOR_PAIR(2));
|
||||
wattroff(ctx->history, COLOR_PAIR(CYAN));
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(5));
|
||||
wprintw(ctx->history, "%s\n", action);
|
||||
wattroff(ctx->history, COLOR_PAIR(5));
|
||||
wattron(ctx->history, COLOR_PAIR(YELLOW));
|
||||
wprintw(ctx->history, "* %s %s\n", nick, action);
|
||||
wattroff(ctx->history, COLOR_PAIR(YELLOW));
|
||||
|
||||
self->blink = true;
|
||||
beep();
|
||||
@ -91,43 +97,29 @@ static void chat_onAction(ToxWindow *self, Messenger *m, int num, uint8_t *actio
|
||||
|
||||
static void chat_onNickChange(ToxWindow *self, int num, uint8_t *nick, uint16_t len)
|
||||
{
|
||||
ChatContext *ctx = (ChatContext *) self->x;
|
||||
struct tm *timeinfo = get_time();
|
||||
|
||||
if (ctx->friendnum != num)
|
||||
if (self->friendnum != num)
|
||||
return;
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(2));
|
||||
wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
|
||||
wattroff(ctx->history, COLOR_PAIR(2));
|
||||
|
||||
nick[len - 1] = '\0';
|
||||
snprintf(self->title, sizeof(self->title), "[%s (%d)]", nick, num);
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(3));
|
||||
wprintw(ctx->history, "* Your partner changed nick to '%s'\n", nick);
|
||||
wattroff(ctx->history, COLOR_PAIR(3));
|
||||
snprintf(self->name, sizeof(self->name), "%s", nick);
|
||||
}
|
||||
|
||||
static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint16_t len)
|
||||
static void chat_onStatusChange(ToxWindow *self, Tox *m, int num, TOX_USERSTATUS status)
|
||||
{
|
||||
ChatContext *ctx = (ChatContext *) self->x;
|
||||
struct tm *timeinfo = get_time();
|
||||
|
||||
if (ctx->friendnum != num)
|
||||
if (self->friendnum != num)
|
||||
return;
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(2));
|
||||
wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
|
||||
wattroff(ctx->history, COLOR_PAIR(2));
|
||||
StatusBar *statusbar = (StatusBar *) self->s;
|
||||
statusbar->status = status;
|
||||
}
|
||||
|
||||
status[len - 1] = '\0';
|
||||
snprintf(self->title, sizeof(self->title), "[%s (%d)]", status, num);
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(3));
|
||||
wprintw(ctx->history, "* Your partner changed status to '%s'\n", status);
|
||||
wattroff(ctx->history, COLOR_PAIR(3));
|
||||
static void chat_onStatusMessageChange(ToxWindow *self, int num, uint8_t *status, uint16_t len)
|
||||
{
|
||||
if (self->friendnum != num)
|
||||
return;
|
||||
|
||||
StatusBar *statusbar = (StatusBar *) self->s;
|
||||
statusbar->statusmsg_len = len;
|
||||
snprintf(statusbar->statusmsg, len, "%s", status);
|
||||
}
|
||||
|
||||
/* check that the string has one non-space character */
|
||||
@ -141,7 +133,7 @@ int string_is_empty(char *string)
|
||||
}
|
||||
|
||||
/* convert wide characters to null terminated string */
|
||||
static char *wcs_to_char(wchar_t *string)
|
||||
static uint8_t *wcs_to_char(wchar_t *string)
|
||||
{
|
||||
size_t len = 0;
|
||||
char *ret = NULL;
|
||||
@ -150,12 +142,22 @@ static char *wcs_to_char(wchar_t *string)
|
||||
if (len != (size_t) -1) {
|
||||
len++;
|
||||
ret = malloc(len);
|
||||
if (ret != NULL)
|
||||
wcstombs(ret, string, len);
|
||||
} else {
|
||||
ret = malloc(2);
|
||||
if (ret != NULL) {
|
||||
ret[0] = ' ';
|
||||
ret[1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -176,9 +178,174 @@ static char *wc_to_char(wchar_t ch)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void chat_onKey(ToxWindow *self, Messenger *m, wint_t key)
|
||||
static void print_help(ChatContext *self)
|
||||
{
|
||||
wattron(self->history, COLOR_PAIR(CYAN) | A_BOLD);
|
||||
wprintw(self->history, "Commands:\n");
|
||||
wattroff(self->history, A_BOLD);
|
||||
|
||||
wprintw(self->history, " /status <type> <message> : Set your status with optional note\n");
|
||||
wprintw(self->history, " /note <message> : Set a personal note\n");
|
||||
wprintw(self->history, " /nick <nickname> : Set your nickname\n");
|
||||
wprintw(self->history, " /me <action> : Do an action\n");
|
||||
wprintw(self->history, " /myid : Print your ID\n");
|
||||
wprintw(self->history, " /clear : Clear the screen\n");
|
||||
wprintw(self->history, " /close : Close the current chat window\n");
|
||||
wprintw(self->history, " /quit or /exit : Exit Toxic\n");
|
||||
wprintw(self->history, " /help : Print this message again\n\n");
|
||||
|
||||
wattroff(self->history, COLOR_PAIR(CYAN));
|
||||
}
|
||||
|
||||
static void execute(ToxWindow *self, ChatContext *ctx, StatusBar *statusbar, Tox *m, char *cmd)
|
||||
{
|
||||
if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) {
|
||||
wclear(self->window);
|
||||
wclear(ctx->history);
|
||||
wprintw(ctx->history, "\n\n");
|
||||
int x, y;
|
||||
getmaxyx(self->window, y, x);
|
||||
(void) x;
|
||||
wmove(self->window, y - CURS_Y_OFFSET, 0);
|
||||
}
|
||||
|
||||
else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h"))
|
||||
print_help(ctx);
|
||||
|
||||
else if (!strcmp(cmd, "/quit") || !strcmp(cmd, "/exit") || !strcmp(cmd, "/q")) {
|
||||
exit_toxic(m);
|
||||
}
|
||||
|
||||
else if (!strncmp(cmd, "/me ", strlen("/me "))) {
|
||||
struct tm *timeinfo = get_time();
|
||||
uint8_t *action = strchr(cmd, ' ');
|
||||
|
||||
if (action == NULL) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
action++;
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(CYAN));
|
||||
wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
|
||||
wattroff(ctx->history, COLOR_PAIR(CYAN));
|
||||
|
||||
uint8_t selfname[TOX_MAX_NAME_LENGTH];
|
||||
tox_getselfname(m, selfname, TOX_MAX_NAME_LENGTH);
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(YELLOW));
|
||||
wprintw(ctx->history, "* %s %s\n", selfname, action);
|
||||
wattroff(ctx->history, COLOR_PAIR(YELLOW));
|
||||
|
||||
if (!statusbar->is_online
|
||||
|| tox_sendaction(m, self->friendnum, action, strlen(action) + 1) == 0) {
|
||||
wattron(ctx->history, COLOR_PAIR(RED));
|
||||
wprintw(ctx->history, " * Failed to send action\n");
|
||||
wattroff(ctx->history, COLOR_PAIR(RED));
|
||||
}
|
||||
}
|
||||
|
||||
else if (!strncmp(cmd, "/status ", strlen("/status "))) {
|
||||
char *status = strchr(cmd, ' ');
|
||||
|
||||
if (status == NULL) {
|
||||
wprintw(ctx->history, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status++;
|
||||
TOX_USERSTATUS status_kind;
|
||||
|
||||
if (!strncmp(status, "online", strlen("online"))) {
|
||||
status_kind = TOX_USERSTATUS_NONE;
|
||||
wprintw(ctx->history, "Status set to: ");
|
||||
wattron(ctx->history, COLOR_PAIR(GREEN) | A_BOLD);
|
||||
wprintw(ctx->history, "[Online]\n");
|
||||
wattroff(ctx->history, COLOR_PAIR(GREEN) | A_BOLD);
|
||||
}
|
||||
|
||||
else if (!strncmp(status, "away", strlen("away"))) {
|
||||
status_kind = TOX_USERSTATUS_AWAY;
|
||||
wprintw(ctx->history, "Status set to: ");
|
||||
wattron(ctx->history, COLOR_PAIR(YELLOW) | A_BOLD);
|
||||
wprintw(ctx->history, "[Away]\n");
|
||||
wattroff(ctx->history, COLOR_PAIR(YELLOW) | A_BOLD);
|
||||
}
|
||||
|
||||
else if (!strncmp(status, "busy", strlen("busy"))) {
|
||||
status_kind = TOX_USERSTATUS_BUSY;
|
||||
wprintw(ctx->history, "Status set to: ");
|
||||
wattron(ctx->history, COLOR_PAIR(RED) | A_BOLD);
|
||||
wprintw(ctx->history, "[Busy]\n");
|
||||
wattroff(ctx->history, COLOR_PAIR(RED) | A_BOLD);
|
||||
}
|
||||
|
||||
else {
|
||||
wprintw(ctx->history, "Invalid status.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tox_set_userstatus(m, status_kind);
|
||||
prompt_update_status(self->prompt, status_kind);
|
||||
|
||||
uint8_t *msg = strchr(status, ' ');
|
||||
if (msg != NULL) {
|
||||
msg++;
|
||||
uint16_t len = strlen(msg) + 1;
|
||||
tox_set_statusmessage(m, msg, len);
|
||||
prompt_update_statusmessage(self->prompt, msg, len);
|
||||
wprintw(ctx->history, "Personal note set to: %s\n", msg);
|
||||
}
|
||||
}
|
||||
|
||||
else if (!strncmp(cmd, "/note ", strlen("/note "))) {
|
||||
uint8_t *msg = strchr(cmd, ' ');
|
||||
msg++;
|
||||
uint16_t len = strlen(msg) + 1;
|
||||
tox_set_statusmessage(m, msg, len);
|
||||
prompt_update_statusmessage(self->prompt, msg, len);
|
||||
wprintw(ctx->history, "Personal note set to: %s\n", msg);
|
||||
}
|
||||
|
||||
else if (!strncmp(cmd, "/nick ", strlen("/nick "))) {
|
||||
uint8_t *nick = strchr(cmd, ' ');
|
||||
|
||||
if (nick == NULL) {
|
||||
wprintw(ctx->history, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
nick++;
|
||||
tox_setname(m, nick, strlen(nick) + 1);
|
||||
prompt_update_nick(self->prompt, nick);
|
||||
wprintw(ctx->history, "Nickname set to: %s\n", nick);
|
||||
}
|
||||
|
||||
else if (!strcmp(cmd, "/myid")) {
|
||||
char id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1] = {'\0'};
|
||||
int i;
|
||||
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
|
||||
tox_getaddress(m, address);
|
||||
|
||||
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) {
|
||||
char xx[3];
|
||||
snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff);
|
||||
strcat(id, xx);
|
||||
}
|
||||
|
||||
wprintw(ctx->history, "%s\n", id);
|
||||
}
|
||||
|
||||
else
|
||||
wprintw(ctx->history, "Invalid command.\n");
|
||||
}
|
||||
|
||||
static void chat_onKey(ToxWindow *self, Tox *m, wint_t key)
|
||||
{
|
||||
ChatContext *ctx = (ChatContext *) self->x;
|
||||
StatusBar *statusbar = (StatusBar *) self->s;
|
||||
|
||||
struct tm *timeinfo = get_time();
|
||||
|
||||
int x, y, y2, x2;
|
||||
@ -191,7 +358,7 @@ static void chat_onKey(ToxWindow *self, Messenger *m, wint_t key)
|
||||
#else
|
||||
if (isprint(key)) {
|
||||
#endif
|
||||
if (ctx->pos != sizeof(ctx->line) - 1) {
|
||||
if (ctx->pos < (MAX_STR_SIZE-1)) {
|
||||
mvwaddstr(self->window, y, x, wc_to_char(key));
|
||||
ctx->line[ctx->pos++] = key;
|
||||
ctx->line[ctx->pos] = L'\0';
|
||||
@ -212,219 +379,150 @@ static void chat_onKey(ToxWindow *self, Messenger *m, wint_t key)
|
||||
|
||||
/* RETURN key: Execute command or print line */
|
||||
else if (key == '\n') {
|
||||
char *line = wcs_to_char(ctx->line);
|
||||
uint8_t *line = wcs_to_char(ctx->line);
|
||||
wclear(ctx->linewin);
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
wclrtobot(self->window);
|
||||
bool close_win = false;
|
||||
|
||||
if (line[0] == '/')
|
||||
execute(self, ctx, m, line);
|
||||
else {
|
||||
if (line[0] == '/') {
|
||||
if (close_win = !strncmp(line, "/close", strlen("/close"))) {
|
||||
int f_num = self->friendnum;
|
||||
delwin(ctx->linewin);
|
||||
delwin(statusbar->topline);
|
||||
del_window(self);
|
||||
disable_chatwin(f_num);
|
||||
} else
|
||||
execute(self, ctx, statusbar, m, line);
|
||||
} else {
|
||||
/* make sure the string has at least non-space character */
|
||||
if (!string_is_empty(line)) {
|
||||
uint8_t selfname[MAX_NAME_LENGTH];
|
||||
getself_name(m, selfname, sizeof(selfname));
|
||||
uint8_t selfname[TOX_MAX_NAME_LENGTH];
|
||||
tox_getselfname(m, selfname, TOX_MAX_NAME_LENGTH);
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(2));
|
||||
wattron(ctx->history, COLOR_PAIR(CYAN));
|
||||
wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
|
||||
wattroff(ctx->history, COLOR_PAIR(2));
|
||||
wattron(ctx->history, COLOR_PAIR(1));
|
||||
wattroff(ctx->history, COLOR_PAIR(CYAN));
|
||||
wattron(ctx->history, COLOR_PAIR(GREEN));
|
||||
wprintw(ctx->history, "%s: ", selfname);
|
||||
wattroff(ctx->history, COLOR_PAIR(1));
|
||||
wattroff(ctx->history, COLOR_PAIR(GREEN));
|
||||
wprintw(ctx->history, "%s\n", line);
|
||||
|
||||
if (m_sendmessage(m, ctx->friendnum, (uint8_t *) line, strlen(line) + 1) == 0) {
|
||||
wattron(ctx->history, COLOR_PAIR(3));
|
||||
if (!statusbar->is_online
|
||||
|| tox_sendmessage(m, self->friendnum, line, strlen(line) + 1) == 0) {
|
||||
wattron(ctx->history, COLOR_PAIR(RED));
|
||||
wprintw(ctx->history, " * Failed to send message.\n");
|
||||
wattroff(ctx->history, COLOR_PAIR(3));
|
||||
wattroff(ctx->history, COLOR_PAIR(RED));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (close_win) {
|
||||
free(ctx);
|
||||
free(statusbar);
|
||||
} else {
|
||||
ctx->line[0] = L'\0';
|
||||
ctx->pos = 0;
|
||||
}
|
||||
|
||||
free(line);
|
||||
}
|
||||
}
|
||||
|
||||
void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd)
|
||||
{
|
||||
if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) {
|
||||
wclear(self->window);
|
||||
wclear(ctx->history);
|
||||
int x, y;
|
||||
getmaxyx(self->window, y, x);
|
||||
(void) x;
|
||||
wmove(self->window, y - CURS_Y_OFFSET, 0);
|
||||
}
|
||||
|
||||
else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h"))
|
||||
print_help(ctx);
|
||||
|
||||
else if (!strcmp(cmd, "/quit") || !strcmp(cmd, "/exit") || !strcmp(cmd, "/q")) {
|
||||
endwin();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
else if (!strncmp(cmd, "/me ", strlen("/me "))) {
|
||||
struct tm *timeinfo = get_time();
|
||||
char *action = strchr(cmd, ' ');
|
||||
|
||||
if (action == NULL) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
action++;
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(2));
|
||||
wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
|
||||
wattroff(ctx->history, COLOR_PAIR(2));
|
||||
|
||||
uint8_t selfname[MAX_NAME_LENGTH];
|
||||
int len = getself_name(m, selfname, sizeof(selfname));
|
||||
char msg[MAX_STR_SIZE - len - 4];
|
||||
snprintf(msg, sizeof(msg), "* %s %s\n", (uint8_t *) selfname, action);
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(5));
|
||||
wprintw(ctx->history, msg);
|
||||
wattroff(ctx->history, COLOR_PAIR(5));
|
||||
|
||||
if (m_sendaction(m, ctx->friendnum, (uint8_t *) msg, strlen(msg) + 1) < 0) {
|
||||
wattron(ctx->history, COLOR_PAIR(3));
|
||||
wprintw(ctx->history, " * Failed to send action\n");
|
||||
wattroff(ctx->history, COLOR_PAIR(3));
|
||||
}
|
||||
}
|
||||
|
||||
else if (!strncmp(cmd, "/status ", strlen("/status "))) {
|
||||
char *status = strchr(cmd, ' ');
|
||||
char *msg;
|
||||
char *status_text;
|
||||
|
||||
if (status == NULL) {
|
||||
wprintw(ctx->history, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status++;
|
||||
USERSTATUS status_kind;
|
||||
|
||||
if (!strncmp(status, "online", strlen("online"))) {
|
||||
status_kind = USERSTATUS_NONE;
|
||||
status_text = "ONLINE";
|
||||
}
|
||||
|
||||
else if (!strncmp(status, "away", strlen("away"))) {
|
||||
status_kind = USERSTATUS_AWAY;
|
||||
status_text = "AWAY";
|
||||
}
|
||||
|
||||
else if (!strncmp(status, "busy", strlen("busy"))) {
|
||||
status_kind = USERSTATUS_BUSY;
|
||||
status_text = "BUSY";
|
||||
}
|
||||
|
||||
else {
|
||||
wprintw(ctx->history, "Invalid status.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
msg = strchr(status, ' ');
|
||||
|
||||
if (msg == NULL) {
|
||||
m_set_userstatus(m, status_kind);
|
||||
wprintw(ctx->history, "Status set to: %s\n", status_text);
|
||||
} else {
|
||||
msg++;
|
||||
m_set_userstatus(m, status_kind);
|
||||
m_set_statusmessage(m, ( uint8_t *) msg, strlen(msg) + 1);
|
||||
wprintw(ctx->history, "Status set to: %s, %s\n", status_text, msg);
|
||||
}
|
||||
}
|
||||
|
||||
else if (!strncmp(cmd, "/nick ", strlen("/nick "))) {
|
||||
char *nick;
|
||||
nick = strchr(cmd, ' ');
|
||||
|
||||
if (nick == NULL) {
|
||||
wprintw(ctx->history, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
nick++;
|
||||
setname(m, (uint8_t *) nick, strlen(nick) + 1);
|
||||
wprintw(ctx->history, "Nickname set to: %s\n", nick);
|
||||
}
|
||||
|
||||
else if (!strcmp(cmd, "/myid")) {
|
||||
char id[FRIEND_ADDRESS_SIZE * 2 + 1] = {0};
|
||||
uint8_t address[FRIEND_ADDRESS_SIZE];
|
||||
size_t i;
|
||||
getaddress(m, address);
|
||||
|
||||
for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) {
|
||||
char xx[3];
|
||||
snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff);
|
||||
strcat(id, xx);
|
||||
}
|
||||
|
||||
wprintw(ctx->history, "%s\n", id);
|
||||
}
|
||||
|
||||
else if (strcmp(cmd, "/close") == 0) {
|
||||
int f_num = ctx->friendnum;
|
||||
delwin(ctx->linewin);
|
||||
del_window(self);
|
||||
disable_chatwin(f_num);
|
||||
}
|
||||
|
||||
else
|
||||
wprintw(ctx->history, "Invalid command.\n");
|
||||
}
|
||||
|
||||
static void chat_onDraw(ToxWindow *self, Messenger *m)
|
||||
static void chat_onDraw(ToxWindow *self, Tox *m)
|
||||
{
|
||||
curs_set(1);
|
||||
|
||||
int x, y;
|
||||
getmaxyx(self->window, y, x);
|
||||
(void) y;
|
||||
|
||||
ChatContext *ctx = (ChatContext *) self->x;
|
||||
|
||||
/* Draw status bar */
|
||||
StatusBar *statusbar = (StatusBar *) self->s;
|
||||
mvwhline(statusbar->topline, 1, 0, '-', x);
|
||||
wmove(statusbar->topline, 0, 0);
|
||||
|
||||
/* Draw name, status and note in statusbar */
|
||||
if (statusbar->is_online) {
|
||||
char *status_text = "Unknown";
|
||||
int colour = WHITE;
|
||||
|
||||
TOX_USERSTATUS status = statusbar->status;
|
||||
|
||||
switch(status) {
|
||||
case TOX_USERSTATUS_NONE:
|
||||
status_text = "Online";
|
||||
colour = GREEN;
|
||||
break;
|
||||
case TOX_USERSTATUS_AWAY:
|
||||
status_text = "Away";
|
||||
colour = YELLOW;
|
||||
break;
|
||||
case TOX_USERSTATUS_BUSY:
|
||||
status_text = "Busy";
|
||||
colour = RED;
|
||||
break;
|
||||
}
|
||||
|
||||
wattron(statusbar->topline, A_BOLD);
|
||||
wprintw(statusbar->topline, " %s ", self->name);
|
||||
wattroff(statusbar->topline, A_BOLD);
|
||||
wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
|
||||
wprintw(statusbar->topline, "[%s]", status_text);
|
||||
wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
|
||||
|
||||
} else {
|
||||
wattron(statusbar->topline, A_BOLD);
|
||||
wprintw(statusbar->topline, " %s ", self->name);
|
||||
wattroff(statusbar->topline, A_BOLD);
|
||||
wprintw(statusbar->topline, "[Offline]");
|
||||
}
|
||||
|
||||
/* Truncate note if it doesn't fit in statusbar */
|
||||
uint16_t maxlen = x - getcurx(statusbar->topline) - 5;
|
||||
if (statusbar->statusmsg_len > maxlen) {
|
||||
statusbar->statusmsg[maxlen] = '\0';
|
||||
statusbar->statusmsg_len = maxlen;
|
||||
}
|
||||
|
||||
wattron(statusbar->topline, A_BOLD);
|
||||
wprintw(statusbar->topline, " | %s |", statusbar->statusmsg);
|
||||
wattroff(statusbar->topline, A_BOLD);
|
||||
|
||||
wprintw(statusbar->topline, "\n");
|
||||
|
||||
mvwhline(ctx->linewin, 0, 0, '_', x);
|
||||
wrefresh(self->window);
|
||||
}
|
||||
|
||||
static void chat_onInit(ToxWindow *self, Messenger *m)
|
||||
static void chat_onInit(ToxWindow *self, Tox *m)
|
||||
{
|
||||
int x, y;
|
||||
ChatContext *ctx = (ChatContext *) self->x;
|
||||
getmaxyx(self->window, y, x);
|
||||
ctx->history = subwin(self->window, y - 4, x, 0, 0);
|
||||
|
||||
/* Init statusbar info */
|
||||
StatusBar *statusbar = (StatusBar *) self->s;
|
||||
statusbar->status = tox_get_userstatus(m, self->friendnum);
|
||||
statusbar->is_online = tox_get_friend_connectionstatus(m, self->friendnum) == 1;
|
||||
|
||||
uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'};
|
||||
tox_copy_statusmessage(m, self->friendnum, statusmsg, TOX_MAX_STATUSMESSAGE_LENGTH);
|
||||
snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg);
|
||||
statusbar->statusmsg_len = tox_get_statusmessage_size(m, self->friendnum);
|
||||
|
||||
/* Init subwindows */
|
||||
ChatContext *ctx = (ChatContext *) self->x;
|
||||
statusbar->topline = subwin(self->window, 2, x, 0, 0);
|
||||
ctx->history = subwin(self->window, y-3, x, 0, 0);
|
||||
scrollok(ctx->history, 1);
|
||||
ctx->linewin = subwin(self->window, 2, x, y - 4, 0);
|
||||
ctx->linewin = subwin(self->window, 0, x, y-4, 0);
|
||||
wprintw(ctx->history, "\n\n");
|
||||
print_help(ctx);
|
||||
wmove(self->window, y - CURS_Y_OFFSET, 0);
|
||||
}
|
||||
|
||||
void print_help(ChatContext *self)
|
||||
{
|
||||
wattron(self->history, COLOR_PAIR(2) | A_BOLD);
|
||||
wprintw(self->history, "Commands:\n");
|
||||
wattroff(self->history, A_BOLD);
|
||||
|
||||
wprintw(self->history, " /status <type> <message> : Set your status\n");
|
||||
wprintw(self->history, " /nick <nickname> : Set your nickname\n");
|
||||
wprintw(self->history, " /me <action> : Do an action\n");
|
||||
wprintw(self->history, " /myid : Print your ID\n");
|
||||
wprintw(self->history, " /clear : Clear the screen\n");
|
||||
wprintw(self->history, " /close : Close the current chat window\n");
|
||||
wprintw(self->history, " /quit or /exit : Exit program\n");
|
||||
wprintw(self->history, " /help : Print this message again\n\n");
|
||||
|
||||
wattroff(self->history, COLOR_PAIR(2));
|
||||
}
|
||||
|
||||
ToxWindow new_chat(Messenger *m, int friendnum)
|
||||
ToxWindow new_chat(Tox *m, ToxWindow *prompt, int friendnum)
|
||||
{
|
||||
ToxWindow ret;
|
||||
memset(&ret, 0, sizeof(ret));
|
||||
@ -433,17 +531,30 @@ ToxWindow new_chat(Messenger *m, int friendnum)
|
||||
ret.onDraw = &chat_onDraw;
|
||||
ret.onInit = &chat_onInit;
|
||||
ret.onMessage = &chat_onMessage;
|
||||
ret.onConnectionChange = &chat_onConnectionChange;
|
||||
ret.onNickChange = &chat_onNickChange;
|
||||
ret.onStatusChange = &chat_onStatusChange;
|
||||
ret.onStatusMessageChange = &chat_onStatusMessageChange;
|
||||
ret.onAction = &chat_onAction;
|
||||
|
||||
uint8_t nick[MAX_NAME_LENGTH] = {0};
|
||||
getname(m, friendnum, (uint8_t *) &nick);
|
||||
|
||||
snprintf(ret.title, sizeof(ret.title), "[%s (%d)]", nick, friendnum);
|
||||
uint8_t name[TOX_MAX_NAME_LENGTH] = {'\0'};
|
||||
tox_getname(m, friendnum, name);
|
||||
snprintf(ret.name, sizeof(ret.name), "%s", name);
|
||||
|
||||
ChatContext *x = calloc(1, sizeof(ChatContext));
|
||||
x->friendnum = friendnum;
|
||||
ret.x = (void *) x;
|
||||
StatusBar *s = calloc(1, sizeof(StatusBar));
|
||||
|
||||
if (s != NULL && x != NULL) {
|
||||
ret.x = x;
|
||||
ret.s = s;
|
||||
} else {
|
||||
endwin();
|
||||
fprintf(stderr, "calloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret.prompt = prompt;
|
||||
ret.friendnum = friendnum;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifndef CHAT_H_6489PZ13
|
||||
#define CHAT_H_6489PZ13
|
||||
|
||||
ToxWindow new_chat(Messenger *m, int friendnum);
|
||||
ToxWindow new_chat(Tox *m, ToxWindow *prompt, int friendnum);
|
||||
|
||||
#endif /* end of include guard: CHAT_H_6489PZ13 */
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
#include <shlobj.h>
|
||||
#include <direct.h>
|
||||
#else /* WIN32 */
|
||||
@ -49,7 +49,10 @@
|
||||
char *get_user_config_dir(void)
|
||||
{
|
||||
char *user_config_dir;
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
#warning Please fix configdir for Win32
|
||||
return NULL;
|
||||
#if 0
|
||||
char appdata[MAX_PATH];
|
||||
BOOL ok;
|
||||
|
||||
@ -62,6 +65,7 @@ char *get_user_config_dir(void)
|
||||
user_config_dir = strdup(appdata);
|
||||
|
||||
return user_config_dir;
|
||||
#endif
|
||||
|
||||
#else /* WIN32 */
|
||||
|
||||
@ -103,7 +107,8 @@ char *get_user_config_dir(void)
|
||||
snprintf(user_config_dir, len, "%s/Library/Application Support", home);
|
||||
# else /* __APPLE__ */
|
||||
|
||||
if (!(user_config_dir = getenv("XDG_CONFIG_HOME"))) {
|
||||
const char *tmp;
|
||||
if (!(tmp = getenv("XDG_CONFIG_HOME"))) {
|
||||
len = strlen(home) + strlen("/.config") + 1;
|
||||
user_config_dir = malloc(len);
|
||||
|
||||
@ -112,6 +117,8 @@ char *get_user_config_dir(void)
|
||||
}
|
||||
|
||||
snprintf(user_config_dir, len, "%s/.config", home);
|
||||
} else {
|
||||
user_config_dir = strdup(tmp);
|
||||
}
|
||||
|
||||
# endif /* __APPLE__ */
|
||||
@ -126,11 +133,10 @@ char *get_user_config_dir(void)
|
||||
*/
|
||||
int create_user_config_dir(char *path)
|
||||
{
|
||||
|
||||
int mkdir_err;
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#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);
|
||||
@ -143,7 +149,11 @@ int create_user_config_dir(char *path)
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(fullpath);
|
||||
#endif
|
||||
|
||||
#else
|
||||
int mkdir_err;
|
||||
|
||||
mkdir_err = mkdir(path, 0700);
|
||||
struct stat buf;
|
||||
@ -163,7 +173,7 @@ int create_user_config_dir(char *path)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
free(fullpath);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
103
src/dhtstatus.c
103
src/dhtstatus.c
@ -1,103 +0,0 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "dhtstatus.h"
|
||||
#include "string.h"
|
||||
#include "network.h"
|
||||
#include "DHT.h"
|
||||
|
||||
typedef uint8_t ipbuf[3 * 4 + 3 + 1];
|
||||
static int num_selected = 0;
|
||||
|
||||
static void printip(ipbuf buf, IP ip)
|
||||
{
|
||||
sprintf((char *)buf, "%u.%u.%u.%u", ip.c[0], ip.c[1], ip.c[2], ip.c[3]);
|
||||
}
|
||||
|
||||
static void dhtstatus_onKey(ToxWindow *self, Messenger *m, wint_t key)
|
||||
{
|
||||
switch (key) {
|
||||
case KEY_UP:
|
||||
case 'k':
|
||||
if (--num_selected < 0)
|
||||
num_selected = CLIENT_ID_SIZE - 1;
|
||||
|
||||
break;
|
||||
|
||||
case KEY_DOWN:
|
||||
case 'j':
|
||||
num_selected = (num_selected + 1) % CLIENT_ID_SIZE;
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dhtstatus_onDraw(ToxWindow *self, Messenger *m)
|
||||
{
|
||||
Client_data *close_clientlist = DHT_get_close_list(m->dht);
|
||||
curs_set(0);
|
||||
werase(self->window);
|
||||
|
||||
uint64_t now = unix_time();
|
||||
uint32_t i, j;
|
||||
ipbuf ipbuf;
|
||||
wprintw(self->window,
|
||||
"\n%llu ______________________ CLOSE LIST ________________________ ___ IP ADDR ___ _PRT_ LST PNG ____ SELF ____ _PRT_ LST\n\n",
|
||||
now);
|
||||
|
||||
for (i = 0; i < 32; i++) { /*Number of nodes in closelist*/
|
||||
Client_data *client = close_clientlist + i;
|
||||
|
||||
if (i == num_selected) wattron(self->window, COLOR_PAIR(3));
|
||||
|
||||
wprintw(self->window, "[%02i] ", i);
|
||||
uint16_t port = ntohs(client->ip_port.port);
|
||||
|
||||
if (port) {
|
||||
for (j = 0; j < CLIENT_ID_SIZE; j++)
|
||||
wprintw(self->window, "%02hhx", client->client_id[j]);
|
||||
|
||||
printip(ipbuf, client->ip_port.ip);
|
||||
wprintw(self->window, " %15s %5u ", ipbuf, port);
|
||||
wprintw(self->window, " %3llu ", now - client->timestamp);
|
||||
wprintw(self->window, " %3llu ", now - client->last_pinged);
|
||||
|
||||
port = ntohs(client->ret_ip_port.port);
|
||||
|
||||
if (port) {
|
||||
printip(ipbuf, client->ret_ip_port.ip);
|
||||
wprintw(self->window, " %15s %5u %3llu", ipbuf, port, now - close_clientlist[i].ret_timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
wprintw(self->window, "\n");
|
||||
|
||||
if (i == num_selected) wattroff(self->window, COLOR_PAIR(3));
|
||||
}
|
||||
|
||||
wrefresh(self->window);
|
||||
}
|
||||
|
||||
static void dhtstatus_onInit(ToxWindow *self, Messenger *m)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ToxWindow new_dhtstatus()
|
||||
{
|
||||
ToxWindow ret;
|
||||
memset(&ret, 0, sizeof(ret));
|
||||
|
||||
ret.onKey = &dhtstatus_onKey;
|
||||
ret.onDraw = &dhtstatus_onDraw;
|
||||
ret.onInit = &dhtstatus_onInit;
|
||||
|
||||
strcpy(ret.title, "[dht status]");
|
||||
return ret;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#ifndef _dhtstatus_h
|
||||
#define _dhtstatus_h
|
||||
|
||||
#include "toxic_windows.h"
|
||||
|
||||
ToxWindow new_dhtstatus();
|
||||
|
||||
#endif
|
205
src/friendlist.c
205
src/friendlist.c
@ -9,18 +9,25 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Messenger.h"
|
||||
#include "network.h"
|
||||
#include <tox/tox.h>
|
||||
|
||||
#include "friendlist.h"
|
||||
|
||||
extern char *DATA_FILE;
|
||||
extern ToxWindow *prompt;
|
||||
|
||||
typedef struct {
|
||||
uint8_t name[MAX_NAME_LENGTH];
|
||||
uint8_t status[MAX_STATUSMESSAGE_LENGTH];
|
||||
uint8_t name[TOX_MAX_NAME_LENGTH];
|
||||
uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH];
|
||||
uint16_t statusmsg_len;
|
||||
int num;
|
||||
int chatwin;
|
||||
bool active;
|
||||
bool online;
|
||||
TOX_USERSTATUS status;
|
||||
} friend_t;
|
||||
|
||||
static friend_t friends[MAX_FRIENDS_NUM];
|
||||
@ -28,66 +35,146 @@ static int num_friends = 0;
|
||||
static int num_selected = 0;
|
||||
|
||||
|
||||
void friendlist_onMessage(ToxWindow *self, Messenger *m, int num, uint8_t *str, uint16_t len)
|
||||
void friendlist_onMessage(ToxWindow *self, Tox *m, int num, uint8_t *str, uint16_t len)
|
||||
{
|
||||
if (num >= num_friends)
|
||||
if (num < 0 || num >= num_friends)
|
||||
return;
|
||||
|
||||
if (friends[num].chatwin == -1) {
|
||||
friends[num].chatwin = add_window(m, new_chat(m, num));
|
||||
if (friends[num].chatwin == -1)
|
||||
friends[num].chatwin = add_window(m, new_chat(m, prompt, friends[num].num));
|
||||
}
|
||||
|
||||
void friendlist_onConnectionChange(ToxWindow *self, Tox *m, int num, uint8_t status)
|
||||
{
|
||||
if (num < 0 || num >= num_friends)
|
||||
return;
|
||||
|
||||
if (status == 1)
|
||||
friends[num].online = true;
|
||||
else
|
||||
friends[num].online = false;
|
||||
}
|
||||
|
||||
void friendlist_onNickChange(ToxWindow *self, int num, uint8_t *str, uint16_t len)
|
||||
{
|
||||
if (len >= MAX_NAME_LENGTH || num >= num_friends)
|
||||
if (len >= TOX_MAX_NAME_LENGTH || num < 0 || num >= num_friends)
|
||||
return;
|
||||
|
||||
memcpy((char *) &friends[num].name, (char *) str, len);
|
||||
friends[num].name[len] = 0;
|
||||
}
|
||||
|
||||
void friendlist_onStatusChange(ToxWindow *self, int num, uint8_t *str, uint16_t len)
|
||||
void friendlist_onStatusChange(ToxWindow *self, Tox *m, int num, TOX_USERSTATUS status)
|
||||
{
|
||||
if (len >= MAX_STATUSMESSAGE_LENGTH || num >= num_friends)
|
||||
if (num < 0 || num >= num_friends)
|
||||
return;
|
||||
|
||||
memcpy((char *) &friends[num].status, (char *) str, len);
|
||||
friends[num].status[len] = 0;
|
||||
friends[num].status = status;
|
||||
}
|
||||
|
||||
int friendlist_onFriendAdded(Messenger *m, int num)
|
||||
void friendlist_onStatusMessageChange(ToxWindow *self, int num, uint8_t *str, uint16_t len)
|
||||
{
|
||||
if (num_friends == MAX_FRIENDS_NUM)
|
||||
if (len >= TOX_MAX_STATUSMESSAGE_LENGTH || num < 0 || num >= num_friends)
|
||||
return;
|
||||
|
||||
friends[num].statusmsg_len = len;
|
||||
memcpy((char *) &friends[num].statusmsg, (char *) str, len);
|
||||
}
|
||||
|
||||
int friendlist_onFriendAdded(Tox *m, int num)
|
||||
{
|
||||
if (num_friends < 0 || num_friends >= MAX_FRIENDS_NUM)
|
||||
return -1;
|
||||
|
||||
friends[num_friends].num = num;
|
||||
getname(m, num, friends[num_friends].name);
|
||||
strcpy((char *) friends[num_friends].name, "unknown");
|
||||
strcpy((char *) friends[num_friends].status, "unknown");
|
||||
friends[num_friends++].chatwin = -1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= num_friends; ++i) {
|
||||
if (!friends[i].active) {
|
||||
friends[i].num = num;
|
||||
friends[i].active = true;
|
||||
friends[i].chatwin = -1;
|
||||
friends[i].online = false;
|
||||
friends[i].status = TOX_USERSTATUS_NONE;
|
||||
|
||||
if (tox_getname(m, num, friends[i].name) == -1 || friends[i].name[0] == '\0')
|
||||
strcpy((char *) friends[i].name, UNKNOWN_NAME);
|
||||
|
||||
if (i == num_friends)
|
||||
++num_friends;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void friendlist_onKey(ToxWindow *self, Messenger *m, wint_t key)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void select_friend(Tox *m, wint_t key)
|
||||
{
|
||||
if (num_friends < 1)
|
||||
return;
|
||||
|
||||
int n = num_selected;
|
||||
|
||||
if (key == KEY_UP) {
|
||||
if (--num_selected < 0)
|
||||
num_selected = num_friends - 1;
|
||||
while (--n != num_selected) {
|
||||
if (n < 0) n = num_friends - 1;
|
||||
if (friends[n].active) {
|
||||
num_selected = n;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (key == KEY_DOWN) {
|
||||
if (num_friends != 0)
|
||||
num_selected = (num_selected + 1) % num_friends;
|
||||
while (++n != num_selected) {
|
||||
n = n % num_friends;
|
||||
if (friends[n].active) {
|
||||
num_selected = n;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else return; /* Bad key input */
|
||||
|
||||
/* If we reach this something is wrong */
|
||||
endwin();
|
||||
tox_kill(m);
|
||||
fprintf(stderr, "select_friend() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void delete_friend(Tox *m, ToxWindow *self, int f_num, wint_t key)
|
||||
{
|
||||
tox_delfriend(m, f_num);
|
||||
memset(&(friends[f_num]), 0, sizeof(friend_t));
|
||||
|
||||
int i;
|
||||
|
||||
for (i = num_friends; i > 0; --i) {
|
||||
if (friends[i-1].active)
|
||||
break;
|
||||
}
|
||||
|
||||
num_friends = i;
|
||||
|
||||
store_data(m, DATA_FILE);
|
||||
select_friend(m, KEY_DOWN);
|
||||
}
|
||||
|
||||
static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key)
|
||||
{
|
||||
if (key == KEY_UP || key == KEY_DOWN) {
|
||||
select_friend(m, key);
|
||||
} else if (key == '\n') {
|
||||
/* Jump to chat window if already open */
|
||||
if (friends[num_selected].chatwin != -1) {
|
||||
set_active_window(friends[num_selected].chatwin);
|
||||
} else {
|
||||
friends[num_selected].chatwin = add_window(m, new_chat(m, num_selected));
|
||||
}
|
||||
friends[num_selected].chatwin = add_window(m, new_chat(m, prompt, friends[num_selected].num));
|
||||
set_active_window(friends[num_selected].chatwin);
|
||||
}
|
||||
} else if (key == 0x107 || key == 0x8 || key == 0x7f)
|
||||
delete_friend(m, self, num_selected, key);
|
||||
}
|
||||
|
||||
static void friendlist_onDraw(ToxWindow *self, Messenger *m)
|
||||
static void friendlist_onDraw(ToxWindow *self, Tox *m)
|
||||
{
|
||||
curs_set(0);
|
||||
werase(self->window);
|
||||
@ -95,26 +182,58 @@ static void friendlist_onDraw(ToxWindow *self, Messenger *m)
|
||||
if (num_friends == 0) {
|
||||
wprintw(self->window, "Empty. Add some friends! :-)\n");
|
||||
} else {
|
||||
wattron(self->window, COLOR_PAIR(2) | A_BOLD);
|
||||
wprintw(self->window, "Open chat with.. (up/down keys, enter)\n");
|
||||
wattroff(self->window, COLOR_PAIR(2) | A_BOLD);
|
||||
wattron(self->window, COLOR_PAIR(CYAN) | A_BOLD);
|
||||
wprintw(self->window, " Open chat with up/down keys and enter.\n");
|
||||
wprintw(self->window, " Delete friends with the backspace key.\n\n");
|
||||
wattroff(self->window, COLOR_PAIR(CYAN) | A_BOLD);
|
||||
}
|
||||
|
||||
wprintw(self->window, "\n");
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_friends; ++i) {
|
||||
if (i == num_selected) wattron(self->window, COLOR_PAIR(3));
|
||||
if (friends[i].active) {
|
||||
if (i == num_selected)
|
||||
wprintw(self->window, " > ");
|
||||
else
|
||||
wprintw(self->window, " ");
|
||||
|
||||
wprintw(self->window, " [#%d] ", friends[i].num);
|
||||
if (friends[i].online) {
|
||||
TOX_USERSTATUS status = friends[i].status;
|
||||
int colour = WHITE;
|
||||
|
||||
if (i == num_selected) wattroff(self->window, COLOR_PAIR(3));
|
||||
switch(status) {
|
||||
case TOX_USERSTATUS_NONE:
|
||||
colour = GREEN;
|
||||
break;
|
||||
case TOX_USERSTATUS_AWAY:
|
||||
colour = YELLOW;
|
||||
break;
|
||||
case TOX_USERSTATUS_BUSY:
|
||||
colour = RED;
|
||||
break;
|
||||
}
|
||||
|
||||
attron(A_BOLD);
|
||||
wprintw(self->window, "%s ", friends[i].name);
|
||||
attroff(A_BOLD);
|
||||
wprintw(self->window, "[");
|
||||
wattron(self->window, COLOR_PAIR(colour) | A_BOLD);
|
||||
wprintw(self->window, "O");
|
||||
wattroff(self->window, COLOR_PAIR(colour) | A_BOLD);
|
||||
wprintw(self->window, "]%s (", friends[i].name);
|
||||
|
||||
wprintw(self->window, "(%s)\n", friends[i].status);
|
||||
/* Truncate note if it doesn't fit on one line */
|
||||
int x, y;
|
||||
getmaxyx(self->window, y, x);
|
||||
uint16_t maxlen = x - getcurx(self->window) - 2;
|
||||
|
||||
if (friends[i].statusmsg_len > maxlen) {
|
||||
friends[i].statusmsg[maxlen] = '\0';
|
||||
friends[i].statusmsg_len = maxlen;
|
||||
}
|
||||
|
||||
wprintw(self->window, "%s)\n", friends[i].statusmsg);
|
||||
} else {
|
||||
wprintw(self->window, "[O]%s\n", friends[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wrefresh(self->window);
|
||||
@ -125,7 +244,7 @@ void disable_chatwin(int f_num)
|
||||
friends[f_num].chatwin = -1;
|
||||
}
|
||||
|
||||
static void friendlist_onInit(ToxWindow *self, Messenger *m)
|
||||
static void friendlist_onInit(ToxWindow *self, Tox *m)
|
||||
{
|
||||
|
||||
}
|
||||
@ -139,10 +258,12 @@ ToxWindow new_friendlist()
|
||||
ret.onDraw = &friendlist_onDraw;
|
||||
ret.onInit = &friendlist_onInit;
|
||||
ret.onMessage = &friendlist_onMessage;
|
||||
ret.onConnectionChange = &friendlist_onConnectionChange;
|
||||
ret.onAction = &friendlist_onMessage; // Action has identical behaviour to message
|
||||
ret.onNickChange = &friendlist_onNickChange;
|
||||
ret.onStatusChange = &friendlist_onStatusChange;
|
||||
ret.onStatusMessageChange = &friendlist_onStatusMessageChange;
|
||||
|
||||
strcpy(ret.title, "[friends]");
|
||||
strcpy(ret.name, "friends");
|
||||
return ret;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "chat.h"
|
||||
|
||||
ToxWindow new_friendlist();
|
||||
int friendlist_onFriendAdded(Messenger *m, int num);
|
||||
int friendlist_onFriendAdded(Tox *m, int num);
|
||||
void disable_chatwin(int f_num);
|
||||
|
||||
#endif /* end of include guard: FRIENDLIST_H_53I41IM */
|
||||
|
235
src/main.c
235
src/main.c
@ -6,6 +6,10 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef SIGWINCH
|
||||
#define SIGWINCH 28
|
||||
#endif
|
||||
|
||||
#include <curses.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
@ -14,25 +18,34 @@
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _win32
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include "Messenger.h"
|
||||
#include "network.h"
|
||||
#include <tox/tox.h>
|
||||
|
||||
#include "configdir.h"
|
||||
#include "toxic_windows.h"
|
||||
#include "prompt.h"
|
||||
#include "friendlist.h"
|
||||
|
||||
#ifndef PACKAGE_DATADIR
|
||||
#define PACKAGE_DATADIR "."
|
||||
#endif
|
||||
|
||||
/* Export for use in Callbacks */
|
||||
char *DATA_FILE = NULL;
|
||||
char *SRVLIST_FILE = NULL;
|
||||
ToxWindow *prompt = NULL;
|
||||
|
||||
void on_window_resize(int sig)
|
||||
{
|
||||
@ -45,7 +58,13 @@ static void init_term()
|
||||
{
|
||||
/* Setup terminal */
|
||||
signal(SIGWINCH, on_window_resize);
|
||||
setlocale(LC_ALL, "");
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
initscr();
|
||||
cbreak();
|
||||
keypad(stdscr, 1);
|
||||
@ -54,6 +73,7 @@ static void init_term()
|
||||
|
||||
if (has_colors()) {
|
||||
start_color();
|
||||
init_pair(0, COLOR_WHITE, COLOR_BLACK);
|
||||
init_pair(1, COLOR_GREEN, COLOR_BLACK);
|
||||
init_pair(2, COLOR_CYAN, COLOR_BLACK);
|
||||
init_pair(3, COLOR_RED, COLOR_BLACK);
|
||||
@ -62,50 +82,109 @@ static void init_term()
|
||||
init_pair(6, COLOR_MAGENTA, COLOR_BLACK);
|
||||
init_pair(7, COLOR_BLACK, COLOR_BLACK);
|
||||
init_pair(8, COLOR_BLACK, COLOR_WHITE);
|
||||
|
||||
}
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
static Messenger *init_tox()
|
||||
static Tox *init_tox()
|
||||
{
|
||||
/* Init core */
|
||||
Messenger *m = initMessenger();
|
||||
Tox *m = tox_new();
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Callbacks */
|
||||
m_callback_friendrequest(m, on_request, NULL);
|
||||
m_callback_friendmessage(m, on_message, NULL);
|
||||
m_callback_namechange(m, on_nickchange, NULL);
|
||||
m_callback_statusmessage(m, on_statuschange, NULL);
|
||||
m_callback_action(m, on_action, NULL);
|
||||
tox_callback_connectionstatus(m, on_connectionchange, NULL);
|
||||
tox_callback_friendrequest(m, on_request, NULL);
|
||||
tox_callback_friendmessage(m, on_message, NULL);
|
||||
tox_callback_namechange(m, on_nickchange, NULL);
|
||||
tox_callback_userstatus(m, on_statuschange, NULL);
|
||||
tox_callback_statusmessage(m, on_statusmessagechange, NULL);
|
||||
tox_callback_action(m, on_action, NULL);
|
||||
#ifdef __linux__
|
||||
setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy"));
|
||||
#elif defined(WIN32)
|
||||
setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux"));
|
||||
tox_setname(m, (uint8_t *) "Cool guy", sizeof("Cool guy"));
|
||||
#elif defined(_WIN32)
|
||||
tox_setname(m, (uint8_t *) "I should install GNU/Linux", sizeof("I should install GNU/Linux"));
|
||||
#elif defined(__APPLE__)
|
||||
setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); //This used to users of other Unixes are hipsters
|
||||
tox_setname(m, (uint8_t *) "Hipster", sizeof("Hipster")); //This used to users of other Unixes are hipsters
|
||||
#else
|
||||
setname(m, (uint8_t *) "Registered Minix user #4", sizeof("Registered Minix user #4"));
|
||||
tox_setname(m, (uint8_t *) "Registered Minix user #4", sizeof("Registered Minix user #4"));
|
||||
#endif
|
||||
return m;
|
||||
}
|
||||
|
||||
/*
|
||||
resolve_addr():
|
||||
address should represent IPv4 or a hostname with A record
|
||||
|
||||
returns a data in network byte order that can be used to set IP.i or IP_Port.ip.i
|
||||
returns 0 on failure
|
||||
|
||||
TODO: Fix ipv6 support
|
||||
*/
|
||||
uint32_t resolve_addr(const char *address)
|
||||
{
|
||||
struct addrinfo *server = NULL;
|
||||
struct addrinfo hints;
|
||||
int rc;
|
||||
uint32_t addr;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET; // IPv4 only right now.
|
||||
hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
|
||||
|
||||
#ifdef _WIN32
|
||||
int res;
|
||||
WSADATA wsa_data;
|
||||
|
||||
res = WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||
if (res != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
rc = getaddrinfo(address, "echo", &hints, &server);
|
||||
|
||||
// Lookup failed.
|
||||
if (rc != 0) {
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// IPv4 records only..
|
||||
if (server->ai_family != AF_INET) {
|
||||
freeaddrinfo(server);
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
addr = ((struct sockaddr_in *)server->ai_addr)->sin_addr.s_addr;
|
||||
|
||||
freeaddrinfo(server);
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
return addr;
|
||||
}
|
||||
|
||||
#define MAXLINE 90 /* Approx max number of chars in a sever line (IP + port + key) */
|
||||
#define MINLINE 70
|
||||
#define MAXSERVERS 50
|
||||
|
||||
/* Connects to a random DHT server listed in the DHTservers file */
|
||||
int init_connection(Messenger *m)
|
||||
int init_connection(Tox *m)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
|
||||
if (DHT_isconnected(m->dht))
|
||||
return 0;
|
||||
|
||||
fp = fopen(SRVLIST_FILE, "r");
|
||||
|
||||
if (!fp)
|
||||
if (fp == NULL)
|
||||
return 1;
|
||||
|
||||
char servers[MAXSERVERS][MAXLINE];
|
||||
@ -129,10 +208,10 @@ int init_connection(Messenger *m)
|
||||
char *port = strtok(NULL, " ");
|
||||
char *key = strtok(NULL, " ");
|
||||
|
||||
if (!ip || !port || !key)
|
||||
if (ip == NULL || port == NULL || key == NULL)
|
||||
return 3;
|
||||
|
||||
IP_Port dht;
|
||||
tox_IP_Port dht;
|
||||
dht.port = htons(atoi(port));
|
||||
uint32_t resolved_address = resolve_addr(ip);
|
||||
|
||||
@ -140,19 +219,19 @@ int init_connection(Messenger *m)
|
||||
return 0;
|
||||
|
||||
dht.ip.i = resolved_address;
|
||||
unsigned char *binary_string = hex_string_to_bin(key);
|
||||
DHT_bootstrap(m->dht, dht, binary_string);
|
||||
uint8_t *binary_string = hex_string_to_bin(key);
|
||||
tox_bootstrap(m, dht, binary_string);
|
||||
free(binary_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void do_tox(Messenger *m, ToxWindow *prompt)
|
||||
static void do_tox(Tox *m, ToxWindow *prompt)
|
||||
{
|
||||
static int conn_try = 0;
|
||||
static int conn_err = 0;
|
||||
static bool dht_on = false;
|
||||
|
||||
if (!dht_on && !DHT_isconnected(m->dht) && !(conn_try++ % 100)) {
|
||||
if (!dht_on && !tox_isconnected(m) && !(conn_try++ % 100)) {
|
||||
if (!conn_err) {
|
||||
conn_err = init_connection(m);
|
||||
wprintw(prompt->window, "\nEstablishing connection...\n");
|
||||
@ -160,15 +239,17 @@ static void do_tox(Messenger *m, ToxWindow *prompt)
|
||||
if (conn_err)
|
||||
wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err);
|
||||
}
|
||||
} else if (!dht_on && DHT_isconnected(m->dht)) {
|
||||
} else if (!dht_on && tox_isconnected(m)) {
|
||||
dht_on = true;
|
||||
prompt_update_connectionstatus(prompt, dht_on);
|
||||
wprintw(prompt->window, "\nDHT connected.\n");
|
||||
} else if (dht_on && !DHT_isconnected(m->dht)) {
|
||||
} else if (dht_on && !tox_isconnected(m)) {
|
||||
dht_on = false;
|
||||
prompt_update_connectionstatus(prompt, dht_on);
|
||||
wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n");
|
||||
}
|
||||
|
||||
doMessenger(m);
|
||||
tox_do(m);
|
||||
}
|
||||
|
||||
int f_loadfromfile;
|
||||
@ -176,39 +257,42 @@ int f_loadfromfile;
|
||||
/*
|
||||
* Store Messenger to given location
|
||||
* Return 0 stored successfully
|
||||
* Return 1 malloc failed
|
||||
* Return 2 opening path failed
|
||||
* Return 3 fwrite failed
|
||||
* Return 1 file path is NULL
|
||||
* Return 2 malloc failed
|
||||
* Return 3 opening path failed
|
||||
* Return 4 fwrite failed
|
||||
*/
|
||||
int store_data(Messenger *m, char *path)
|
||||
int store_data(Tox *m, char *path)
|
||||
{
|
||||
if (f_loadfromfile == 0) /*If file loading/saving is disabled*/
|
||||
return 0;
|
||||
|
||||
if (path == NULL)
|
||||
return 1;
|
||||
|
||||
FILE *fd;
|
||||
size_t len;
|
||||
uint8_t *buf;
|
||||
|
||||
len = Messenger_size(m);
|
||||
len = tox_size(m);
|
||||
buf = malloc(len);
|
||||
|
||||
if (buf == NULL) {
|
||||
return 1;
|
||||
}
|
||||
if (buf == NULL)
|
||||
return 2;
|
||||
|
||||
Messenger_save(m, buf);
|
||||
tox_save(m, buf);
|
||||
|
||||
fd = fopen(path, "w");
|
||||
|
||||
if (fd == NULL) {
|
||||
free(buf);
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (fwrite(buf, len, 1, fd) != 1) {
|
||||
free(buf);
|
||||
fclose(fd);
|
||||
return 3;
|
||||
return 4;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
@ -216,7 +300,7 @@ int store_data(Messenger *m, char *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void load_data(Messenger *m, char *path)
|
||||
static void load_data(Tox *m, char *path)
|
||||
{
|
||||
if (f_loadfromfile == 0) /*If file loading/saving is disabled*/
|
||||
return;
|
||||
@ -233,26 +317,28 @@ static void load_data(Messenger *m, char *path)
|
||||
buf = malloc(len);
|
||||
|
||||
if (buf == NULL) {
|
||||
fprintf(stderr, "malloc() failed.\n");
|
||||
fclose(fd);
|
||||
endwin();
|
||||
exit(1);
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fread(buf, len, 1, fd) != 1) {
|
||||
fprintf(stderr, "fread() failed.\n");
|
||||
free(buf);
|
||||
fclose(fd);
|
||||
endwin();
|
||||
exit(1);
|
||||
fprintf(stderr, "fread() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
Messenger_load(m, buf, len);
|
||||
tox_load(m, buf, len);
|
||||
|
||||
uint32_t i;
|
||||
uint32_t i = 0;
|
||||
|
||||
for (i = 0; i < m->numfriends; i++) {
|
||||
uint8_t name[TOX_MAX_NAME_LENGTH];
|
||||
while (tox_getname(m, i, name) != -1) {
|
||||
on_friendadded(m, i);
|
||||
i++;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
@ -261,13 +347,24 @@ static void load_data(Messenger *m, char *path)
|
||||
int st;
|
||||
|
||||
if ((st = store_data(m, path)) != 0) {
|
||||
fprintf(stderr, "Store messenger failed with return code: %d\n", st);
|
||||
endwin();
|
||||
exit(1);
|
||||
fprintf(stderr, "Store messenger failed with return code: %d\n", st);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void exit_toxic(Tox *m)
|
||||
{
|
||||
store_data(m, DATA_FILE);
|
||||
free(DATA_FILE);
|
||||
free(SRVLIST_FILE);
|
||||
free(prompt->s);
|
||||
tox_kill(m);
|
||||
endwin();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *user_config_dir = get_user_config_dir();
|
||||
@ -300,40 +397,56 @@ int main(int argc, char *argv[])
|
||||
SRVLIST_FILE = strdup(PACKAGE_DATADIR "/DHTservers");
|
||||
} else {
|
||||
DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1);
|
||||
SRVLIST_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("DHTservers") + 1);
|
||||
|
||||
if (DATA_FILE != NULL && SRVLIST_FILE != NULL) {
|
||||
strcpy(DATA_FILE, user_config_dir);
|
||||
strcat(DATA_FILE, CONFIGDIR);
|
||||
strcat(DATA_FILE, "data");
|
||||
|
||||
SRVLIST_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("DHTservers") + 1);
|
||||
strcpy(SRVLIST_FILE, user_config_dir);
|
||||
strcat(SRVLIST_FILE, CONFIGDIR);
|
||||
strcat(SRVLIST_FILE, "DHTservers");
|
||||
} else {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(user_config_dir);
|
||||
|
||||
init_term();
|
||||
Messenger *m = init_tox();
|
||||
ToxWindow *prompt = init_windows(m);
|
||||
Tox *m = init_tox();
|
||||
|
||||
if (m == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "Failed to initialize network. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
prompt = init_windows(m);
|
||||
|
||||
if (f_loadfromfile)
|
||||
load_data(m, DATA_FILE);
|
||||
|
||||
if (f_flag == -1) {
|
||||
attron(COLOR_PAIR(3) | A_BOLD);
|
||||
attron(COLOR_PAIR(RED) | A_BOLD);
|
||||
wprintw(prompt->window, "You passed '-f' without giving an argument.\n"
|
||||
"defaulting to 'data' for a keyfile...\n");
|
||||
attroff(COLOR_PAIR(3) | A_BOLD);
|
||||
attroff(COLOR_PAIR(RED) | A_BOLD);
|
||||
}
|
||||
|
||||
if (config_err) {
|
||||
attron(COLOR_PAIR(3) | A_BOLD);
|
||||
attron(COLOR_PAIR(RED) | A_BOLD);
|
||||
wprintw(prompt->window, "Unable to determine configuration directory.\n"
|
||||
"defaulting to 'data' for a keyfile...\n");
|
||||
attroff(COLOR_PAIR(3) | A_BOLD);
|
||||
attroff(COLOR_PAIR(RED) | A_BOLD);
|
||||
}
|
||||
|
||||
prompt_init_statusbar(prompt, m);
|
||||
|
||||
while (true) {
|
||||
/* Update tox */
|
||||
do_tox(m, prompt);
|
||||
@ -342,8 +455,6 @@ int main(int argc, char *argv[])
|
||||
draw_active_window(m);
|
||||
}
|
||||
|
||||
cleanupMessenger(m);
|
||||
free(DATA_FILE);
|
||||
free(SRVLIST_FILE);
|
||||
exit_toxic(m);
|
||||
return 0;
|
||||
}
|
||||
|
606
src/prompt.c
606
src/prompt.c
@ -10,61 +10,100 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "Messenger.h"
|
||||
#include "network.h"
|
||||
|
||||
#include "prompt.h"
|
||||
|
||||
extern char *DATA_FILE;
|
||||
extern int store_data(Messenger *m, char *path);
|
||||
|
||||
uint8_t pending_requests[MAX_STR_SIZE][CLIENT_ID_SIZE]; // XXX
|
||||
uint8_t pending_requests[MAX_STR_SIZE][TOX_CLIENT_ID_SIZE]; // XXX
|
||||
uint8_t num_requests = 0; // XXX
|
||||
|
||||
static char prompt_buf[MAX_STR_SIZE] = {0};
|
||||
static char prompt_buf[MAX_STR_SIZE] = {'\0'};
|
||||
static int prompt_buf_pos = 0;
|
||||
|
||||
/* commands */
|
||||
void cmd_accept(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_add(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_clear(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_connect(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_help(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_msg(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_myid(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_nick(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_mynick(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_quit(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_status(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_statusmsg(ToxWindow *, Messenger *m, char **);
|
||||
void cmd_accept(ToxWindow *, Tox *m, int, char **);
|
||||
void cmd_add(ToxWindow *, Tox *m, int, char **);
|
||||
void cmd_clear(ToxWindow *, Tox *m, int, char **);
|
||||
void cmd_connect(ToxWindow *, Tox *m, int, char **);
|
||||
void cmd_help(ToxWindow *, Tox *m, int, char **);
|
||||
void cmd_msg(ToxWindow *, Tox *m, int, char **);
|
||||
void cmd_myid(ToxWindow *, Tox *m, int, char **);
|
||||
void cmd_nick(ToxWindow *, Tox *m, int, char **);
|
||||
void cmd_quit(ToxWindow *, Tox *m, int, char **);
|
||||
void cmd_status(ToxWindow *, Tox *m, int, char **);
|
||||
void cmd_note(ToxWindow *, Tox *m, int, char **);
|
||||
|
||||
#define NUM_COMMANDS 14
|
||||
#define NUM_COMMANDS 13
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
int numargs;
|
||||
void (*func)(ToxWindow *, Messenger *m, char **);
|
||||
void (*func)(ToxWindow *, Tox *m, int, char **);
|
||||
} commands[] = {
|
||||
{ "accept", 1, cmd_accept },
|
||||
{ "add", 1, cmd_add },
|
||||
{ "clear", 0, cmd_clear },
|
||||
{ "connect", 3, cmd_connect },
|
||||
{ "exit", 0, cmd_quit },
|
||||
{ "help", 0, cmd_help },
|
||||
{ "msg", 2, cmd_msg },
|
||||
{ "myid", 0, cmd_myid },
|
||||
{ "nick", 1, cmd_nick },
|
||||
{ "mynick", 0, cmd_mynick },
|
||||
{ "q", 0, cmd_quit },
|
||||
{ "quit", 0, cmd_quit },
|
||||
{ "status", 2, cmd_status },
|
||||
{ "statusmsg", 1, cmd_statusmsg },
|
||||
{ "accept", cmd_accept },
|
||||
{ "add", cmd_add },
|
||||
{ "clear", cmd_clear },
|
||||
{ "connect", cmd_connect },
|
||||
{ "exit", cmd_quit },
|
||||
{ "help", cmd_help },
|
||||
{ "msg", cmd_msg },
|
||||
{ "myid", cmd_myid },
|
||||
{ "nick", cmd_nick },
|
||||
{ "q", cmd_quit },
|
||||
{ "quit", cmd_quit },
|
||||
{ "status", cmd_status },
|
||||
{ "note", cmd_note },
|
||||
};
|
||||
|
||||
/* Updates own nick in prompt statusbar */
|
||||
void prompt_update_nick(ToxWindow *prompt, uint8_t *nick)
|
||||
{
|
||||
StatusBar *statusbar = (StatusBar *) prompt->s;
|
||||
snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick);
|
||||
}
|
||||
|
||||
/* Updates own statusmessage in prompt statusbar */
|
||||
void prompt_update_statusmessage(ToxWindow *prompt, uint8_t *statusmsg)
|
||||
{
|
||||
StatusBar *statusbar = (StatusBar *) prompt->s;
|
||||
snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg);
|
||||
}
|
||||
|
||||
/* Updates own status in prompt statusbar */
|
||||
void prompt_update_status(ToxWindow *prompt, TOX_USERSTATUS status)
|
||||
{
|
||||
StatusBar *statusbar = (StatusBar *) prompt->s;
|
||||
statusbar->status = status;
|
||||
}
|
||||
|
||||
/* Updates own connection status in prompt statusbar */
|
||||
void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected)
|
||||
{
|
||||
StatusBar *statusbar = (StatusBar *) prompt->s;
|
||||
statusbar->is_online = is_connected;
|
||||
}
|
||||
|
||||
void prompt_onFriendRequest(ToxWindow *prompt, uint8_t *key, uint8_t *data, uint16_t length)
|
||||
{
|
||||
int n = add_req(key);
|
||||
wprintw(prompt->window, "\nFriend request from:\n");
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < KEY_SIZE_BYTES; ++i) {
|
||||
wprintw(prompt->window, "%02x", key[i] & 0xff);
|
||||
}
|
||||
|
||||
wprintw(prompt->window, "\n\nWith the message: %s\n\n", data);
|
||||
wprintw(prompt->window, "Type \"accept %d\" to accept it.\n", n);
|
||||
|
||||
prompt->blink = true;
|
||||
beep();
|
||||
}
|
||||
|
||||
// XXX:
|
||||
int add_req(uint8_t *public_key)
|
||||
{
|
||||
memcpy(pending_requests[num_requests], public_key, CLIENT_ID_SIZE);
|
||||
memcpy(pending_requests[num_requests], public_key, TOX_CLIENT_ID_SIZE);
|
||||
++num_requests;
|
||||
return num_requests - 1;
|
||||
}
|
||||
@ -74,8 +113,15 @@ unsigned char *hex_string_to_bin(char hex_string[])
|
||||
{
|
||||
size_t len = strlen(hex_string);
|
||||
unsigned char *val = malloc(len);
|
||||
|
||||
if (val == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char *pos = hex_string;
|
||||
size_t i;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; ++i, pos += 2)
|
||||
sscanf(pos, "%2hhx", &val[i]);
|
||||
@ -83,16 +129,25 @@ unsigned char *hex_string_to_bin(char hex_string[])
|
||||
return val;
|
||||
}
|
||||
|
||||
void cmd_accept(ToxWindow *self, Messenger *m, char **args)
|
||||
/* command functions */
|
||||
void cmd_accept(ToxWindow *self, Tox *m, int argc, char **argv)
|
||||
{
|
||||
int num = atoi(args[1]);
|
||||
int num;
|
||||
|
||||
if (num >= num_requests) {
|
||||
/* check arguments */
|
||||
if (argc != 1) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
num = m_addfriend_norequest(m, pending_requests[num]);
|
||||
num = atoi(argv[1]);
|
||||
|
||||
if (num < 0 || num >= num_requests) {
|
||||
wprintw(self->window, "No pending request with that number.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
num = tox_addfriend_norequest(m, pending_requests[num]);
|
||||
|
||||
if (num == -1)
|
||||
wprintw(self->window, "Failed to add friend.\n");
|
||||
@ -102,30 +157,50 @@ void cmd_accept(ToxWindow *self, Messenger *m, char **args)
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_add(ToxWindow *self, Messenger *m, char **args)
|
||||
void cmd_add(ToxWindow *self, Tox *m, int argc, char **argv)
|
||||
{
|
||||
uint8_t id_bin[FRIEND_ADDRESS_SIZE];
|
||||
char xx[3];
|
||||
uint32_t x;
|
||||
char *id = args[1];
|
||||
char *msg = args[2];
|
||||
|
||||
if (!id) {
|
||||
wprintw(self->window, "Invalid command: add expected at least one argument.\n");
|
||||
if (argc < 1 || argc > 2) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!msg)
|
||||
msg = "";
|
||||
uint8_t id_bin[TOX_FRIEND_ADDRESS_SIZE];
|
||||
char xx[3];
|
||||
uint32_t x;
|
||||
uint8_t *msg;
|
||||
int i, num;
|
||||
|
||||
if (strlen(id) != 2 * FRIEND_ADDRESS_SIZE) {
|
||||
char *id = argv[1];
|
||||
|
||||
if (id == NULL) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
msg = argv[2];
|
||||
|
||||
if (msg == NULL) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg[0] != '\"') {
|
||||
wprintw(self->window, "Messages must be enclosed in quotes.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
msg[strlen(++msg)-1] = L'\0';
|
||||
|
||||
} else
|
||||
msg = "Let's tox.";
|
||||
|
||||
if (strlen(id) != 2 * TOX_FRIEND_ADDRESS_SIZE) {
|
||||
wprintw(self->window, "Invalid ID length.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < FRIEND_ADDRESS_SIZE; ++i) {
|
||||
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) {
|
||||
xx[0] = id[2 * i];
|
||||
xx[1] = id[2 * i + 1];
|
||||
xx[2] = '\0';
|
||||
@ -138,38 +213,38 @@ void cmd_add(ToxWindow *self, Messenger *m, char **args)
|
||||
id_bin[i] = x;
|
||||
}
|
||||
|
||||
for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) {
|
||||
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) {
|
||||
id[i] = toupper(id[i]);
|
||||
}
|
||||
|
||||
int num = m_addfriend(m, id_bin, (uint8_t *) msg, strlen(msg) + 1);
|
||||
num = tox_addfriend(m, id_bin, msg, strlen(msg) + 1);
|
||||
|
||||
switch (num) {
|
||||
case FAERR_TOOLONG:
|
||||
case TOX_FAERR_TOOLONG:
|
||||
wprintw(self->window, "Message is too long.\n");
|
||||
break;
|
||||
|
||||
case FAERR_NOMESSAGE:
|
||||
case TOX_FAERR_NOMESSAGE:
|
||||
wprintw(self->window, "Please add a message to your request.\n");
|
||||
break;
|
||||
|
||||
case FAERR_OWNKEY:
|
||||
case TOX_FAERR_OWNKEY:
|
||||
wprintw(self->window, "That appears to be your own ID.\n");
|
||||
break;
|
||||
|
||||
case FAERR_ALREADYSENT:
|
||||
case TOX_FAERR_ALREADYSENT:
|
||||
wprintw(self->window, "Friend request already sent.\n");
|
||||
break;
|
||||
|
||||
case FAERR_UNKNOWN:
|
||||
case TOX_FAERR_UNKNOWN:
|
||||
wprintw(self->window, "Undefined error when adding friend.\n");
|
||||
break;
|
||||
|
||||
case FAERR_BADCHECKSUM:
|
||||
case TOX_FAERR_BADCHECKSUM:
|
||||
wprintw(self->window, "Bad checksum in address.\n");
|
||||
break;
|
||||
|
||||
case FAERR_SETNEWNOSPAM:
|
||||
case TOX_FAERR_SETNEWNOSPAM:
|
||||
wprintw(self->window, "Nospam was different.\n");
|
||||
break;
|
||||
|
||||
@ -180,17 +255,29 @@ void cmd_add(ToxWindow *self, Messenger *m, char **args)
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_clear(ToxWindow *self, Messenger *m, char **args)
|
||||
void cmd_clear(ToxWindow *self, Tox *m, int argc, char **argv)
|
||||
{
|
||||
wclear(self->window);
|
||||
wprintw(self->window, "\n\n");
|
||||
}
|
||||
|
||||
void cmd_connect(ToxWindow *self, Messenger *m, char **args)
|
||||
void cmd_connect(ToxWindow *self, Tox *m, int argc, char **argv)
|
||||
{
|
||||
IP_Port dht;
|
||||
char *ip = args[1];
|
||||
char *port = args[2];
|
||||
char *key = args[3];
|
||||
/* check arguments */
|
||||
if (argc != 3) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tox_IP_Port dht;
|
||||
char *ip = argv[1];
|
||||
char *port = argv[2];
|
||||
char *key = argv[3];
|
||||
|
||||
if (!ip || !port || !key) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (atoi(port) == 0) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
@ -205,62 +292,75 @@ void cmd_connect(ToxWindow *self, Messenger *m, char **args)
|
||||
}
|
||||
|
||||
dht.ip.i = resolved_address;
|
||||
unsigned char *binary_string = hex_string_to_bin(key);
|
||||
DHT_bootstrap(m->dht, dht, binary_string);
|
||||
uint8_t *binary_string = hex_string_to_bin(key);
|
||||
tox_bootstrap(m, dht, binary_string);
|
||||
free(binary_string);
|
||||
}
|
||||
|
||||
void cmd_quit(ToxWindow *self, Messenger *m, char **args)
|
||||
void cmd_quit(ToxWindow *self, Tox *m, int argc, char **argv)
|
||||
{
|
||||
endwin();
|
||||
exit(0);
|
||||
exit_toxic(m);
|
||||
}
|
||||
|
||||
void cmd_help(ToxWindow *self, Messenger *m, char **args)
|
||||
void cmd_help(ToxWindow *self, Tox *m, int argc, char **argv)
|
||||
{
|
||||
wclear(self->window);
|
||||
wattron(self->window, COLOR_PAIR(2) | A_BOLD);
|
||||
wprintw(self->window, "Commands:\n");
|
||||
wattron(self->window, COLOR_PAIR(CYAN) | A_BOLD);
|
||||
wprintw(self->window, "\n\nCommands:\n");
|
||||
wattroff(self->window, A_BOLD);
|
||||
|
||||
wprintw(self->window, " connect <ip> <port> <key> : Connect to DHT server\n");
|
||||
wprintw(self->window, " add <id> <message> : Add friend\n");
|
||||
wprintw(self->window, " status <type> <message> : Set your status\n");
|
||||
wprintw(self->window, " statusmsg <message> : Set your status\n");
|
||||
wprintw(self->window, " add <id> <message> : Add friend with optional message\n");
|
||||
wprintw(self->window, " status <type> <message> : Set your status with optional note\n");
|
||||
wprintw(self->window, " note <message> : Set a personal note\n");
|
||||
wprintw(self->window, " nick <nickname> : Set your nickname\n");
|
||||
wprintw(self->window, " mynick : Print your current nickname\n");
|
||||
wprintw(self->window, " accept <number> : Accept friend request\n");
|
||||
wprintw(self->window, " myid : Print your ID\n");
|
||||
wprintw(self->window, " quit/exit : Exit program\n");
|
||||
wprintw(self->window, " quit/exit : Exit Toxic\n");
|
||||
wprintw(self->window, " help : Print this message again\n");
|
||||
wprintw(self->window, " clear : Clear this window\n");
|
||||
|
||||
wattron(self->window, A_BOLD);
|
||||
wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n");
|
||||
wprintw(self->window, " * Messages must be enclosed in quotation marks.\n");
|
||||
wprintw(self->window, " * Use the TAB key to navigate through the tabs.\n\n");
|
||||
wattroff(self->window, A_BOLD);
|
||||
|
||||
wattroff(self->window, COLOR_PAIR(2));
|
||||
wattroff(self->window, COLOR_PAIR(CYAN));
|
||||
}
|
||||
|
||||
void cmd_msg(ToxWindow *self, Messenger *m, char **args)
|
||||
void cmd_msg(ToxWindow *self, Tox *m, int argc, char **argv)
|
||||
{
|
||||
char *id = args[1];
|
||||
char *msg = args[2];
|
||||
/* check arguments */
|
||||
if (argc != 2) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_sendmessage(m, atoi(id), (uint8_t *) msg, strlen(msg) + 1) == 0)
|
||||
wprintw(self->window, "Error occurred while sending message.\n");
|
||||
char *id = argv[1];
|
||||
uint8_t *msg = argv[2];
|
||||
|
||||
if (id == NULL || msg == NULL) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
msg[strlen(++msg)-1] = L'\0';
|
||||
|
||||
if (tox_sendmessage(m, atoi(id), msg, strlen(msg) + 1) == 0)
|
||||
wprintw(self->window, "Failed to send message.\n");
|
||||
else
|
||||
wprintw(self->window, "Message successfully sent.\n");
|
||||
}
|
||||
|
||||
void cmd_myid(ToxWindow *self, Messenger *m, char **args)
|
||||
void cmd_myid(ToxWindow *self, Tox *m, int argc, char **argv)
|
||||
{
|
||||
char id[FRIEND_ADDRESS_SIZE * 2 + 1] = {0};
|
||||
size_t i;
|
||||
uint8_t address[FRIEND_ADDRESS_SIZE];
|
||||
getaddress(m, address);
|
||||
char id[TOX_FRIEND_ADDRESS_SIZE * 2 + 1] = {0};
|
||||
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
|
||||
tox_getaddress(m, address);
|
||||
|
||||
for (i = 0; i < FRIEND_ADDRESS_SIZE; ++i) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; ++i) {
|
||||
char xx[3];
|
||||
snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff);
|
||||
strcat(id, xx);
|
||||
@ -269,70 +369,115 @@ void cmd_myid(ToxWindow *self, Messenger *m, char **args)
|
||||
wprintw(self->window, "%s\n", id);
|
||||
}
|
||||
|
||||
void cmd_nick(ToxWindow *self, Messenger *m, char **args)
|
||||
void cmd_nick(ToxWindow *self, Tox *m, int argc, char **argv)
|
||||
{
|
||||
char *nick = args[1];
|
||||
setname(m, (uint8_t *) nick, strlen(nick) + 1);
|
||||
wprintw(self->window, "Nickname set to: %s\n", nick);
|
||||
|
||||
if (store_data(m, DATA_FILE)) {
|
||||
wprintw(self->window, "\nCould not store Messenger data\n");
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_mynick(ToxWindow *self, Messenger *m, char **args)
|
||||
{
|
||||
uint8_t *nick = malloc(m->name_length);
|
||||
getself_name(m, nick, m->name_length);
|
||||
wprintw(self->window, "Current nickname: %s\n", nick);
|
||||
free(nick);
|
||||
}
|
||||
|
||||
void cmd_status(ToxWindow *self, Messenger *m, char **args)
|
||||
{
|
||||
char *status = args[1];
|
||||
char *status_text;
|
||||
|
||||
USERSTATUS status_kind;
|
||||
|
||||
if (!strncmp(status, "online", strlen("online"))) {
|
||||
status_kind = USERSTATUS_NONE;
|
||||
status_text = "ONLINE";
|
||||
} else if (!strncmp(status, "away", strlen("away"))) {
|
||||
status_kind = USERSTATUS_AWAY;
|
||||
status_text = "AWAY";
|
||||
} else if (!strncmp(status, "busy", strlen("busy"))) {
|
||||
status_kind = USERSTATUS_BUSY;
|
||||
status_text = "BUSY";
|
||||
} else {
|
||||
wprintw(self->window, "Invalid status.\n");
|
||||
/* check arguments */
|
||||
if (argc != 1) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char *msg = args[2];
|
||||
uint8_t *nick = argv[1];
|
||||
|
||||
if (nick == NULL) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nick[0] == '\"')
|
||||
nick[strlen(++nick)-1] = L'\0';
|
||||
|
||||
tox_setname(m, nick, strlen(nick) + 1);
|
||||
prompt_update_nick(self, nick);
|
||||
|
||||
store_data(m, DATA_FILE);
|
||||
}
|
||||
|
||||
void cmd_status(ToxWindow *self, Tox *m, int argc, char **argv)
|
||||
{
|
||||
if (argc < 1 || argc > 2) {
|
||||
wprintw(self->window, "Wrong number of arguments.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *msg = NULL;
|
||||
|
||||
if (argc == 2) {
|
||||
|
||||
msg = argv[2];
|
||||
|
||||
if (msg == NULL) {
|
||||
m_set_userstatus(m, status_kind);
|
||||
wprintw(self->window, "Status set to: %s\n", status_text);
|
||||
} else {
|
||||
m_set_userstatus(m, status_kind);
|
||||
m_set_statusmessage(m, (uint8_t *) msg, strlen(msg) + 1);
|
||||
wprintw(self->window, "Status set to: %s, %s\n", status_text, msg);
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg[0] != '\"') {
|
||||
wprintw(self->window, "Messages must be enclosed in quotes.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_statusmsg(ToxWindow *self, Messenger *m, char **args)
|
||||
char *status = argv[1];
|
||||
|
||||
if (status == NULL) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
TOX_USERSTATUS status_kind;
|
||||
|
||||
if (!strncmp(status, "online", strlen("online")))
|
||||
status_kind = TOX_USERSTATUS_NONE;
|
||||
|
||||
else if (!strncmp(status, "away", strlen("away")))
|
||||
status_kind = TOX_USERSTATUS_AWAY;
|
||||
|
||||
else if (!strncmp(status, "busy", strlen("busy")))
|
||||
status_kind = TOX_USERSTATUS_BUSY;
|
||||
|
||||
else
|
||||
wprintw(self->window, "Invalid status.\n");
|
||||
|
||||
tox_set_userstatus(m, status_kind);
|
||||
prompt_update_status(self, status_kind);
|
||||
|
||||
if (msg != NULL) {
|
||||
msg[strlen(++msg)-1] = L'\0'; /* remove opening and closing quotes */
|
||||
tox_set_statusmessage(m, msg, strlen(msg) + 1);
|
||||
prompt_update_statusmessage(self, msg);
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_note(ToxWindow *self, Tox *m, int argc, char **argv)
|
||||
{
|
||||
char *msg = args[1];
|
||||
m_set_statusmessage(m, (uint8_t *) msg, strlen(msg) + 1);
|
||||
wprintw(self->window, "Status set to: %s\n", msg);
|
||||
if (argc != 1) {
|
||||
wprintw(self->window, "Wrong number of arguments.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static void execute(ToxWindow *self, Messenger *m, char *u_cmd)
|
||||
uint8_t *msg = argv[1];
|
||||
|
||||
if (msg == NULL) {
|
||||
wprintw(self->window, "Invalid syntax.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg[0] != '\"') {
|
||||
wprintw(self->window, "Messages must be enclosed in quotes.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
msg[strlen(++msg)-1] = L'\0';
|
||||
|
||||
tox_set_statusmessage(m, msg, strlen(msg) + 1);
|
||||
prompt_update_statusmessage(self, msg);
|
||||
}
|
||||
|
||||
static void execute(ToxWindow *self, Tox *m, char *u_cmd)
|
||||
{
|
||||
int newlines = 0;
|
||||
char cmd[MAX_STR_SIZE] = {0};
|
||||
size_t i;
|
||||
char cmd[MAX_STR_SIZE] = {'\0'};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < strlen(prompt_buf); ++i) {
|
||||
if (u_cmd[i] == '\n')
|
||||
@ -358,85 +503,60 @@ static void execute(ToxWindow *self, Messenger *m, char *u_cmd)
|
||||
|
||||
/* insert \0 at argument boundaries */
|
||||
int numargs = 0;
|
||||
|
||||
for (i = 0; i < MAX_STR_SIZE; i++) {
|
||||
char quote_chr;
|
||||
if (cmd[i] == '\"' || cmd[i] == '\'') {
|
||||
quote_chr = cmd[i];
|
||||
while (cmd[++i] != quote_chr && i < MAX_STR_SIZE); /* skip over strings */
|
||||
/* Check if got qoute character */
|
||||
if (cmd[i] != quote_chr) {
|
||||
wprintw(self->window, "Missing terminating %c character\n", quote_chr);
|
||||
if (cmd[i] == ' ') {
|
||||
cmd[i] = '\0';
|
||||
numargs++;
|
||||
}
|
||||
/* skip over strings */
|
||||
else if (cmd[i] == '\"') {
|
||||
while (cmd[++i] != '\"') {
|
||||
if (cmd[i] == '\0') {
|
||||
wprintw(self->window, "Invalid command: did you forget an opening or closing \"?\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd[i] == ' ') {
|
||||
cmd[i] = '\0';
|
||||
|
||||
int j = i;
|
||||
|
||||
while (++j < MAX_STR_SIZE && isspace(cmd[j]));
|
||||
|
||||
i = j - 1;
|
||||
|
||||
numargs++;
|
||||
}
|
||||
}
|
||||
|
||||
/* excessive arguments */
|
||||
if (numargs > 3) {
|
||||
/* read arguments into array */
|
||||
char **cmdargs = malloc((numargs + 1) * sizeof(char *));
|
||||
if (!cmdargs) {
|
||||
wprintw(self->window, "Invalid command: too many arguments.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* read arguments into array */
|
||||
char *cmdargs[5];
|
||||
int pos = 0;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
for (i = 0; i < numargs + 1; i++) {
|
||||
cmdargs[i] = cmd + pos;
|
||||
pos += strlen(cmdargs[i]) + 1;
|
||||
|
||||
while (isspace(cmd[pos]) && pos < MAX_STR_SIZE)
|
||||
++pos;
|
||||
/* replace empty strings with NULL for easier error checking */
|
||||
if (strlen(cmdargs[i]) == 0)
|
||||
cmdargs[i] = NULL;
|
||||
}
|
||||
|
||||
/* no input */
|
||||
if (strlen(cmdargs[0]) == 0)
|
||||
if (!cmdargs[0]) {
|
||||
free(cmdargs);
|
||||
return;
|
||||
}
|
||||
|
||||
/* match input to command list */
|
||||
for (i = 0; i < NUM_COMMANDS; i++) {
|
||||
if (!strcmp(cmdargs[0], commands[i].name)) {
|
||||
/* check for missing arguments */
|
||||
int j;
|
||||
|
||||
for (j = 0; j <= commands[i].numargs; j++) {
|
||||
if (strlen(cmdargs[j]) == 0) {
|
||||
wprintw(self->window, "Invalid command: %s expected %d arguments, got %d.\n",
|
||||
commands[i].name, commands[i].numargs, j - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for excess arguments */
|
||||
if (strcmp(cmdargs[0], "add") && strlen(cmdargs[j]) != 0) {
|
||||
wprintw(self->window, "Invalid command: too many arguments to %s.\n", commands[i].name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* pass arguments to command function */
|
||||
(commands[i].func)(self, m, cmdargs);
|
||||
(commands[i].func)(self, m, numargs, cmdargs);
|
||||
free(cmdargs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* no match */
|
||||
free(cmdargs);
|
||||
wprintw(self->window, "Invalid command.\n");
|
||||
}
|
||||
|
||||
static void prompt_onKey(ToxWindow *self, Messenger *m, wint_t key)
|
||||
static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key)
|
||||
{
|
||||
/* Add printable characters to line */
|
||||
if (isprint(key)) {
|
||||
@ -466,40 +586,104 @@ static void prompt_onKey(ToxWindow *self, Messenger *m, wint_t key)
|
||||
|
||||
/* BACKSPACE key: Remove one character from line */
|
||||
else if (key == 0x107 || key == 0x8 || key == 0x7f) {
|
||||
if (prompt_buf_pos != 0) {
|
||||
if (prompt_buf_pos != 0)
|
||||
prompt_buf[--prompt_buf_pos] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void prompt_onDraw(ToxWindow *self, Messenger *m)
|
||||
static void prompt_onDraw(ToxWindow *self, Tox *m)
|
||||
{
|
||||
curs_set(1);
|
||||
int x, y;
|
||||
int i;
|
||||
getyx(self->window, y, x);
|
||||
(void) x;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < (strlen(prompt_buf)); ++i) {
|
||||
if ((prompt_buf[i] == '\n') && (y != 0))
|
||||
--y;
|
||||
}
|
||||
|
||||
wattron(self->window, COLOR_PAIR(1));
|
||||
StatusBar *statusbar = (StatusBar *) self->s;
|
||||
|
||||
werase(statusbar->topline);
|
||||
|
||||
if (statusbar->is_online) {
|
||||
int colour = WHITE;
|
||||
char *status_text = "Unknown";
|
||||
|
||||
switch(statusbar->status) {
|
||||
case TOX_USERSTATUS_NONE:
|
||||
status_text = "Online";
|
||||
colour = GREEN;
|
||||
break;
|
||||
case TOX_USERSTATUS_AWAY:
|
||||
status_text = "Away";
|
||||
colour = YELLOW;
|
||||
break;
|
||||
case TOX_USERSTATUS_BUSY:
|
||||
status_text = "Busy";
|
||||
colour = RED;
|
||||
break;
|
||||
}
|
||||
|
||||
wattron(statusbar->topline, A_BOLD);
|
||||
wprintw(statusbar->topline, " %s ", statusbar->nick);
|
||||
wattron(statusbar->topline, A_BOLD);
|
||||
wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
|
||||
wprintw(statusbar->topline, "[%s]", status_text);
|
||||
wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
|
||||
} else {
|
||||
wattron(statusbar->topline, A_BOLD);
|
||||
wprintw(statusbar->topline, "%s ", statusbar->nick);
|
||||
wattroff(statusbar->topline, A_BOLD);
|
||||
wprintw(statusbar->topline, "[Offline]");
|
||||
}
|
||||
|
||||
wattron(statusbar->topline, A_BOLD);
|
||||
wprintw(statusbar->topline, " | %s |", statusbar->statusmsg);
|
||||
wattroff(statusbar->topline, A_BOLD);
|
||||
|
||||
wprintw(statusbar->topline, "\n");
|
||||
|
||||
wattron(self->window, COLOR_PAIR(GREEN));
|
||||
mvwprintw(self->window, y, 0, "# ");
|
||||
wattroff(self->window, COLOR_PAIR(1));
|
||||
wattroff(self->window, COLOR_PAIR(GREEN));
|
||||
mvwprintw(self->window, y, 2, "%s", prompt_buf);
|
||||
wclrtoeol(self->window);
|
||||
|
||||
wrefresh(self->window);
|
||||
}
|
||||
|
||||
static void prompt_onInit(ToxWindow *self, Messenger *m)
|
||||
static void prompt_onInit(ToxWindow *self, Tox *m)
|
||||
{
|
||||
scrollok(self->window, 1);
|
||||
cmd_help(self, m, NULL);
|
||||
cmd_help(self, m, 0, NULL);
|
||||
wclrtoeol(self->window);
|
||||
}
|
||||
|
||||
void prompt_init_statusbar(ToxWindow *self, Tox *m)
|
||||
{
|
||||
int x, y;
|
||||
getmaxyx(self->window, y, x);
|
||||
|
||||
/* Init statusbar info */
|
||||
StatusBar *statusbar = (StatusBar *) self->s;
|
||||
statusbar->status = TOX_USERSTATUS_NONE;
|
||||
statusbar->is_online = false;
|
||||
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
|
||||
tox_getselfname(m, nick, TOX_MAX_NAME_LENGTH);
|
||||
snprintf(statusbar->nick, sizeof(statusbar->nick), "%s", nick);
|
||||
|
||||
/* temporary until statusmessage saving works */
|
||||
uint8_t *statusmsg = "Toxing on Toxic v0.2.0";
|
||||
m_set_statusmessage(m, statusmsg, strlen(statusmsg) + 1);
|
||||
snprintf(statusbar->statusmsg, sizeof(statusbar->statusmsg), "%s", statusmsg);
|
||||
|
||||
/* Init statusbar subwindow */
|
||||
statusbar->topline = subwin(self->window, 2, x, 0, 0);
|
||||
}
|
||||
|
||||
ToxWindow new_prompt()
|
||||
{
|
||||
ToxWindow ret;
|
||||
@ -507,6 +691,18 @@ ToxWindow new_prompt()
|
||||
ret.onKey = &prompt_onKey;
|
||||
ret.onDraw = &prompt_onDraw;
|
||||
ret.onInit = &prompt_onInit;
|
||||
strcpy(ret.title, "[prompt]");
|
||||
ret.onFriendRequest = &prompt_onFriendRequest;
|
||||
strcpy(ret.name, "prompt");
|
||||
|
||||
StatusBar *s = calloc(1, sizeof(StatusBar));
|
||||
|
||||
if (s != NULL)
|
||||
ret.s = s;
|
||||
else {
|
||||
endwin();
|
||||
fprintf(stderr, "calloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
ToxWindow new_prompt();
|
||||
int add_req(uint8_t *public_key);
|
||||
unsigned char *hex_string_to_bin(char hex_string[]);
|
||||
void prompt_init_statusbar(ToxWindow *self, Tox *m);
|
||||
|
||||
#endif /* end of include guard: PROMPT_H_UZYGWFFL */
|
||||
|
||||
|
||||
|
@ -9,7 +9,9 @@
|
||||
#include <stdbool.h>
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
#include "Messenger.h"
|
||||
|
||||
#include <tox/tox.h>
|
||||
|
||||
#define MAX_WINDOWS_NUM 32
|
||||
#define MAX_FRIENDS_NUM 100
|
||||
#define MAX_STR_SIZE 256
|
||||
@ -18,39 +20,71 @@
|
||||
/* number of permanent default windows */
|
||||
#define N_DEFAULT_WINS 3
|
||||
|
||||
#define UNKNOWN_NAME "Unknown"
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_FAILURE 1
|
||||
|
||||
#ifndef TOXICVER
|
||||
#define TOXICVER "NOVER" //Use the -D flag to set this
|
||||
#endif
|
||||
|
||||
/* Curses foreground colours (background is black) */
|
||||
#define WHITE 0
|
||||
#define GREEN 1
|
||||
#define CYAN 2
|
||||
#define RED 3
|
||||
#define BLUE 4
|
||||
#define YELLOW 5
|
||||
#define MAGENTA 6
|
||||
#define BLACK 7
|
||||
|
||||
typedef struct ToxWindow_ ToxWindow;
|
||||
|
||||
struct ToxWindow_ {
|
||||
void(*onKey)(ToxWindow *, Messenger *, wint_t);
|
||||
void(*onDraw)(ToxWindow *, Messenger *);
|
||||
void(*onInit)(ToxWindow *, Messenger *);
|
||||
void(*onKey)(ToxWindow *, Tox *, wint_t);
|
||||
void(*onDraw)(ToxWindow *, Tox *);
|
||||
void(*onInit)(ToxWindow *, Tox *);
|
||||
void(*onFriendRequest)(ToxWindow *, uint8_t *, uint8_t *, uint16_t);
|
||||
void(*onMessage)(ToxWindow *, Messenger *, int, uint8_t *, uint16_t);
|
||||
void(*onConnectionChange)(ToxWindow *, Tox *, int, uint8_t);
|
||||
void(*onMessage)(ToxWindow *, Tox *, int, uint8_t *, uint16_t);
|
||||
void(*onNickChange)(ToxWindow *, int, uint8_t *, uint16_t);
|
||||
void(*onStatusChange)(ToxWindow *, int, uint8_t *, uint16_t);
|
||||
void(*onAction)(ToxWindow *, Messenger *, int, uint8_t *, uint16_t);
|
||||
char title[256];
|
||||
void(*onStatusChange)(ToxWindow *, Tox *, int, TOX_USERSTATUS);
|
||||
void(*onStatusMessageChange)(ToxWindow *, int, uint8_t *, uint16_t);
|
||||
void(*onAction)(ToxWindow *, Tox *, int, uint8_t *, uint16_t);
|
||||
|
||||
char name[TOX_MAX_NAME_LENGTH];
|
||||
int friendnum;
|
||||
|
||||
void *x;
|
||||
void *s;
|
||||
void *prompt;
|
||||
|
||||
bool blink;
|
||||
|
||||
WINDOW *window;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
WINDOW *topline;
|
||||
uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH];
|
||||
uint16_t statusmsg_len;
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH];
|
||||
TOX_USERSTATUS status;
|
||||
bool is_online;
|
||||
} StatusBar;
|
||||
|
||||
void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata);
|
||||
void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_friendadded(Messenger *m, int friendnumber);
|
||||
void on_connectionchange(Tox *m, int friendnumber, uint8_t status, void *userdata);
|
||||
void on_message(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_action(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_nickchange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_statuschange(Tox *m, int friendnumber, TOX_USERSTATUS status, void *userdata);
|
||||
void on_statusmessagechange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata);
|
||||
void on_friendadded(Tox *m, int friendnumber);
|
||||
ToxWindow *init_windows();
|
||||
void draw_active_window(Messenger *m);
|
||||
int add_window(Messenger *m, ToxWindow w);
|
||||
void draw_active_window(Tox *m);
|
||||
int add_window(Tox *m, ToxWindow w);
|
||||
void del_window(ToxWindow *w);
|
||||
void set_active_window(int ch);
|
||||
#endif
|
||||
|
||||
|
122
src/windows.c
122
src/windows.c
@ -2,41 +2,64 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "friendlist.h"
|
||||
#include "prompt.h"
|
||||
#include "dhtstatus.h"
|
||||
#include "toxic_windows.h"
|
||||
|
||||
extern char *DATA_FILE;
|
||||
extern int store_data(Messenger *m, char *path);
|
||||
|
||||
static ToxWindow windows[MAX_WINDOWS_NUM];
|
||||
static ToxWindow *active_window;
|
||||
static ToxWindow *prompt;
|
||||
static Messenger *m;
|
||||
static Tox *m;
|
||||
|
||||
/* CALLBACKS START */
|
||||
void on_request(uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata)
|
||||
{
|
||||
int n = add_req(public_key);
|
||||
wprintw(prompt->window, "\nFriend request from:\n");
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < KEY_SIZE_BYTES; ++i) {
|
||||
wprintw(prompt->window, "%02x", public_key[i] & 0xff);
|
||||
}
|
||||
|
||||
wprintw(prompt->window, "\nWith the message: %s\n", data);
|
||||
wprintw(prompt->window, "\nUse \"accept %d\" to accept it.\n", n);
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].onFriendRequest != NULL)
|
||||
windows[i].onFriendRequest(&windows[i], public_key, data, length);
|
||||
}
|
||||
}
|
||||
|
||||
void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
|
||||
void on_connectionchange(Tox *m, int friendnumber, uint8_t status, void *userdata)
|
||||
{
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
|
||||
tox_getname(m, friendnumber, nick);
|
||||
|
||||
if (!nick[0])
|
||||
snprintf(nick, sizeof(nick), "%s", UNKNOWN_NAME);
|
||||
|
||||
if (status == 1) {
|
||||
wattron(prompt->window, COLOR_PAIR(GREEN));
|
||||
wattron(prompt->window, A_BOLD);
|
||||
wprintw(prompt->window, "\n%s ", nick);
|
||||
wattroff(prompt->window, A_BOLD);
|
||||
wprintw(prompt->window, "has come online\n");
|
||||
wattroff(prompt->window, COLOR_PAIR(GREEN));
|
||||
} else {
|
||||
wattron(prompt->window, COLOR_PAIR(RED));
|
||||
wattron(prompt->window, A_BOLD);
|
||||
wprintw(prompt->window, "\n%s ", nick);
|
||||
wattroff(prompt->window, A_BOLD);
|
||||
wprintw(prompt->window, "has gone offline\n");
|
||||
wattroff(prompt->window, COLOR_PAIR(RED));
|
||||
}
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].onConnectionChange != NULL)
|
||||
windows[i].onConnectionChange(&windows[i], m, friendnumber, status);
|
||||
}
|
||||
}
|
||||
|
||||
void on_message(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -46,7 +69,7 @@ void on_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t length
|
||||
}
|
||||
}
|
||||
|
||||
void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
|
||||
void on_action(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -56,39 +79,49 @@ void on_action(Messenger *m, int friendnumber, uint8_t *string, uint16_t length,
|
||||
}
|
||||
}
|
||||
|
||||
void on_nickchange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
|
||||
void on_nickchange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
|
||||
{
|
||||
wprintw(prompt->window, "\n(nickchange) %d: %s\n", friendnumber, string);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].onNickChange != NULL)
|
||||
windows[i].onNickChange(&windows[i], friendnumber, string, length);
|
||||
}
|
||||
|
||||
if (store_data(m, DATA_FILE))
|
||||
wprintw(prompt->window, "\nCould not store Tox data\n");
|
||||
}
|
||||
|
||||
void on_statuschange(Messenger *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
|
||||
void on_statusmessagechange(Tox *m, int friendnumber, uint8_t *string, uint16_t length, void *userdata)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].onStatusMessageChange != NULL)
|
||||
windows[i].onStatusMessageChange(&windows[i], friendnumber, string, length);
|
||||
}
|
||||
}
|
||||
|
||||
void on_statuschange(Tox *m, int friendnumber, TOX_USERSTATUS status, void *userdata)
|
||||
{
|
||||
wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].onStatusChange != NULL)
|
||||
windows[i].onStatusChange(&windows[i], friendnumber, string, length);
|
||||
windows[i].onStatusChange(&windows[i], m, friendnumber, status);
|
||||
}
|
||||
}
|
||||
|
||||
void on_friendadded(Messenger *m, int friendnumber)
|
||||
void on_friendadded(Tox *m, int friendnumber)
|
||||
{
|
||||
friendlist_onFriendAdded(m, friendnumber);
|
||||
|
||||
if (store_data(m, DATA_FILE)) {
|
||||
wprintw(prompt->window, "\nCould not store Messenger data\n");
|
||||
}
|
||||
if (store_data(m, DATA_FILE))
|
||||
wprintw(prompt->window, "\nCould not store Tox data\n");
|
||||
}
|
||||
/* CALLBACKS END */
|
||||
|
||||
int add_window(Messenger *m, ToxWindow w)
|
||||
int add_window(Tox *m, ToxWindow w)
|
||||
{
|
||||
if (LINES < 2)
|
||||
return -1;
|
||||
@ -107,7 +140,6 @@ int add_window(Messenger *m, ToxWindow w)
|
||||
windows[i] = w;
|
||||
w.onInit(&w, m);
|
||||
|
||||
active_window = windows + i;
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -118,13 +150,10 @@ int add_window(Messenger *m, ToxWindow w)
|
||||
void del_window(ToxWindow *w)
|
||||
{
|
||||
active_window = windows; // Go to prompt screen
|
||||
|
||||
delwin(w->window);
|
||||
|
||||
if (w->x)
|
||||
free(w->x);
|
||||
|
||||
w->window = NULL;
|
||||
memset(w, 0, sizeof(ToxWindow));
|
||||
|
||||
clear();
|
||||
refresh();
|
||||
}
|
||||
@ -147,7 +176,8 @@ void set_next_window(int ch)
|
||||
|
||||
if (active_window == inf) { // infinite loop check
|
||||
endwin();
|
||||
exit(2);
|
||||
fprintf(stderr, "set_next_window() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -164,12 +194,10 @@ ToxWindow *init_windows()
|
||||
{
|
||||
int n_prompt = add_window(m, new_prompt());
|
||||
|
||||
if (n_prompt == -1
|
||||
|| add_window(m, new_friendlist()) == -1
|
||||
|| add_window(m, new_dhtstatus()) == -1) {
|
||||
fprintf(stderr, "add_window() failed.\n");
|
||||
if (n_prompt == -1 || add_window(m, new_friendlist()) == -1) {
|
||||
endwin();
|
||||
exit(1);
|
||||
fprintf(stderr, "add_window() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
prompt = &windows[n_prompt];
|
||||
@ -183,19 +211,19 @@ static void draw_bar()
|
||||
static int odd = 0;
|
||||
int blinkrate = 30;
|
||||
|
||||
attron(COLOR_PAIR(4));
|
||||
attron(COLOR_PAIR(BLUE));
|
||||
mvhline(LINES - 2, 0, '_', COLS);
|
||||
attroff(COLOR_PAIR(4));
|
||||
attroff(COLOR_PAIR(BLUE));
|
||||
|
||||
move(LINES - 1, 0);
|
||||
|
||||
attron(COLOR_PAIR(4) | A_BOLD);
|
||||
attron(COLOR_PAIR(BLUE) | A_BOLD);
|
||||
printw(" TOXIC " TOXICVER " |");
|
||||
attroff(COLOR_PAIR(4) | A_BOLD);
|
||||
attroff(COLOR_PAIR(BLUE) | A_BOLD);
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (MAX_WINDOWS_NUM); ++i) {
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].window) {
|
||||
if (windows + i == active_window)
|
||||
attron(A_BOLD);
|
||||
@ -203,13 +231,13 @@ static void draw_bar()
|
||||
odd = (odd + 1) % blinkrate;
|
||||
|
||||
if (windows[i].blink && (odd < (blinkrate / 2)))
|
||||
attron(COLOR_PAIR(3));
|
||||
attron(COLOR_PAIR(RED));
|
||||
|
||||
clrtoeol();
|
||||
printw(" %s", windows[i].title);
|
||||
printw(" [%s]", windows[i].name);
|
||||
|
||||
if (windows[i].blink && (odd < (blinkrate / 2)))
|
||||
attroff(COLOR_PAIR(3));
|
||||
attroff(COLOR_PAIR(RED));
|
||||
|
||||
if (windows + i == active_window) {
|
||||
attroff(A_BOLD);
|
||||
@ -226,7 +254,7 @@ void prepare_window(WINDOW *w)
|
||||
wresize(w, LINES - 2, COLS);
|
||||
}
|
||||
|
||||
void draw_active_window(Messenger *m)
|
||||
void draw_active_window(Tox *m)
|
||||
{
|
||||
|
||||
ToxWindow *a = active_window;
|
||||
@ -239,7 +267,7 @@ void draw_active_window(Messenger *m)
|
||||
|
||||
/* Handle input */
|
||||
#ifdef HAVE_WIDECHAR
|
||||
get_wch(&ch);
|
||||
wget_wch(stdscr, &ch);
|
||||
#else
|
||||
ch = getch();
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user