mirror of
				https://github.com/Tha14/toxic.git
				synced 2025-11-04 07:16:52 +01:00 
			
		
		
		
	Synced to master
This commit is contained in:
		
							
								
								
									
										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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user