1
0
mirror of https://github.com/Tha14/toxic.git synced 2025-06-28 21:26:46 +02:00

Compare commits

..

15 Commits

Author SHA1 Message Date
a5246bcbc6 Bump to version 0.10.1 2021-01-20 16:18:43 -05:00
b37e28c2d0 Add a script for building minimal static toxic
The intention is that JFreegman would run it locally on his machine for
every Toxic release and publish the build artifacts on GitHub for
download, similarly to how the qTox team makes release builds. This
should mitigate the loss of the Jenkins build server to some extent,
which used to provide Toxic builds before.
2021-01-19 21:48:51 -05:00
973e60ef11 Fix Makefile assignment bug
When a user provides variable=value as an argument to make, all
assignments to that variable are ignored within the Makefile because the
user has explicitly overrode variable to be "value". This made the
ENABLE_ASAN assignment to be ignored, resulting in Toxic always enabling
ASAN unless you run `make ENABLE_ASAN=disabled`, which is not
documented and not how it's intended to work. This can be fixed by
prefixing the assignment with "override", but to be in line with other
argument assignments we just change the variable name.

See more at:
https://www.gnu.org/software/make/manual/html_node/Overriding.html
2021-01-19 20:18:24 -05:00
ae94bc593b Rename some build options for naming consistency 2021-01-19 15:21:31 -05:00
81eb58532e Fix bug sometimes causing join message spam on conference join 2021-01-17 17:10:10 -05:00
8464ea9a7a Fix minor display bug with the audio call info box 2021-01-12 19:18:22 -05:00
b77bff35a1 Add config man entries for colour scheme options 2020-12-06 11:52:46 -05:00
eb964b64c2 Fix off by one error and comment magic numbers 2020-12-05 20:53:09 -05:00
2ff9d29491 Custom colors proof of concept
Fix formatting

Fix repeated variable in example config
2020-12-05 17:46:13 -06:00
2640919318 Don't announce when ghost peers leave the group
This appears to be a toxcore bug, but nonetheless it looks ugly. Also changed
group -> conference for join/part messages
2020-12-03 11:49:48 -05:00
2fcbc4fa1c Remove lots of duplicate code related to printing timestamps 2020-11-30 17:55:57 -05:00
4330bf5867 Show peer join/part messages in conferences
Also a couple trivial fixes
2020-11-30 12:06:13 -05:00
3f1b7cdd26 Update config example and some default settings to reflect recent changes 2020-11-30 00:58:43 -05:00
1e985c1456 Interface improvements and bump to v0.10.0
- Give window tab and statusbar a make over
- Place window tab above input field
- Reduce input field to one square in height
- Refactor window tab so that it's now a subwin of its parent ToxWindow
- Fix bug causing notification counter to sometimes increment by 2
- No longer scroll on output when output is not at bottom of screen
- Show a small indicator on far left of window tab when output is
  not at bottom of screen
- Reduce ncurses/UI thread sleep time by half
- Handle nanosleep errors better
2020-11-29 23:26:51 -05:00
61740bda85 Fix a couple minor issues
Print a warning if remove() fails, and check if the win pointer is null
before using it (this is unnecessary but it's correct and shuts coverity up)
2020-11-26 18:25:37 -05:00
38 changed files with 1306 additions and 584 deletions

View File

@ -18,7 +18,7 @@ OBJ += line_info.o log.o message_queue.o misc_tools.o name_lookup.o notify.o pro
OBJ += term_mplex.o toxic.o toxic_strings.o windows.o
# Check if debug build is enabled
RELEASE := $(shell if [ -z "$(RELEASE_ENABLED)" ] || [ "$(RELEASE_ENABLED)" = "0" ] ; then echo disabled ; else echo enabled ; fi)
RELEASE := $(shell if [ -z "$(ENABLE_RELEASE)" ] || [ "$(ENABLE_RELEASE)" = "0" ] ; then echo disabled ; else echo enabled ; fi)
ifneq ($(RELEASE), enabled)
CFLAGS += -O0 -g -DDEBUG
LDFLAGS += -O0
@ -28,9 +28,9 @@ else
endif
# Check if LLVM Address Sanitizer is enabled
ASAN_ENABLED := $(shell if [ -z "$(ENABLE_ASAN)" ] || [ "$(ENABLE_ASAN)" = "0" ] ; then echo disabled ; else echo enabled ; fi)
ifneq ($(ASAN_ENABLED), disabled)
CFLAGS += -fsanitize=address -fno-omit-frame-pointer -mllvm -asan-use-private-alias=1 -Wno-unused-command-line-argument
ASAN := $(shell if [ -z "$(ENABLE_ASAN)" ] || [ "$(ENABLE_ASAN)" = "0" ] ; then echo disabled ; else echo enabled ; fi)
ifneq ($(ASAN), disabled)
CFLAGS += -fsanitize=address -fno-omit-frame-pointer
endif
# Check on wich system we are running

View File

@ -5,7 +5,7 @@
Toxic is a [Tox](https://tox.chat)-based instant messaging and video chat client.
[![Toxic Screenshot](https://i.imgur.com/5S577z6.png "Toxic Audio Conference")](https://i.imgur.com/5S577z6.png)
[![Toxic Screenshot](https://i.imgur.com/TwYA8L0.png "Toxic Home Screen")](https://i.imgur.com/TwYA8L0.png)
## Installation
[See the install instructions](/INSTALL.md)

View File

@ -55,9 +55,9 @@ author = 'Jakob Kreuze'
# built documents.
#
# The short X.Y version.
version = '0.9.1'
version = '0.10.1'
# The full version, including alpha/beta/rc tags.
release = '0.9.1'
release = '0.10.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@ -1,5 +1,5 @@
# Version
TOXIC_VERSION = 0.9.1
TOXIC_VERSION = 0.10.1
REV = $(shell git rev-list HEAD --count 2>/dev/null || echo -n "error")
ifneq (, $(findstring error, $(REV)))
VERSION = $(TOXIC_VERSION)

View File

@ -17,8 +17,8 @@ help:
@echo " DISABLE_QRCODE: Set to \"1\" to force building without QR export support"
@echo " DISABLE_QRPNG: Set to \"1\" to force building without QR exported as PNG support"
@echo " ENABLE_PYTHON: Set to \"1\" to enable building with Python scripting support"
@echo " RELEASE_ENABLED: Set to \"1\" to build without debug symbols and with full compiler optimizations"
@echo " ASAN_ENABLED: Set to \"1\" to build with LLVM address sanitizer enabled.
@echo " ENABLE_RELEASE: Set to \"1\" to build without debug symbols and with full compiler optimizations"
@echo " ENABLE_ASAN: Set to \"1\" to build with LLVM address sanitizer enabled.
@echo " USER_CFLAGS: Add custom flags to default CFLAGS"
@echo " USER_LDFLAGS: Add custom flags to default LDFLAGS"
@echo " PREFIX: Specify a prefix directory for binaries, data files,... (default is \"$(abspath $(PREFIX))\")"

View File

@ -2,12 +2,12 @@
.\" Title: toxic.conf
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 2020-05-07
.\" Date: 2020-11-18
.\" Manual: Toxic Manual
.\" Source: toxic __VERSION__
.\" Language: English
.\"
.TH "TOXIC\&.CONF" "5" "2020\-05\-07" "toxic __VERSION__" "Toxic Manual"
.TH "TOXIC\&.CONF" "5" "2020\-11\-18" "toxic __VERSION__" "Toxic Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@ -93,6 +93,26 @@ Enable or disable acoustic alerts on events\&. true or false
Select between native terminal colors and toxic color theme\&. true or false
.RE
.PP
\fBcolor_bar_bg\fR
.RS 4
set background color of chat status bars\&. (black, white, red, green, blue, cyan, yellow, magenta)
.RE
.PP
\fBcolor_bar_fg\fR
.RS 4
set foreground (text) color of chat status bars\&. (black, white, red, green, blue, cyan, yellow, magenta)
.RE
.PP
\fBcolor_bar_accent\fR
.RS 4
set foreground accent color of chat status bars\&. (black, white, red, green, blue, cyan, yellow, magenta)
.RE
.PP
\fBcolor_bar_notify\fR
.RS 4
set foreground notify (and typing) color in chat status bar\&. (black, white, red, green, blue, cyan, yellow, magenta)
.RE
.PP
\fBautolog\fR
.RS 4
Enable or disable autologging\&. true or false
@ -222,11 +242,6 @@ Audio output device\&. Integer value\&. Number corresponds to
Voice Activity Detection threshold\&. Float value\&. Recommended values are 1\&.0\-40\&.0
.RE
.PP
\fBpush_to_talk\fR
.RS 4
Enable/Disable Push\-To\-Talk for conference audio chats (active key is F2)\&. true or false
.RE
.PP
\fBconference_audio_channels\fR
.RS 4
Number of channels for conference audio broadcast\&. Integer value\&. 1 (mono) or 2 (stereo)
@ -236,6 +251,11 @@ Number of channels for conference audio broadcast\&. Integer value\&. 1 (mono) o
.RS 4
Number of channels for 1\-on\-1 audio broadcast\&. Integer value\&. 1 (mono) or 2 (stereo)
.RE
.PP
\fBpush_to_talk\fR
.RS 4
Enable/Disable Push\-To\-Talk for conference audio chats (active key is F2)\&. true or false
.RE
.RE
.PP
\fBtox\fR

View File

@ -60,6 +60,18 @@ OPTIONS
*native_colors*;;
Select between native terminal colors and toxic color theme. true or false
*color_bar_bg*;;
set background color of chat status bars. (black, white, red, green, blue, cyan, yellow, magenta)
*color_bar_fg*;;
set foreground (text) color of chat status bars. (black, white, red, green, blue, cyan, yellow, magenta)
*color_bar_accent*;;
set foreground accent color of chat status bars. (black, white, red, green, blue, cyan, yellow, magenta)
*color_bar_notify*;;
set foreground notify (and typing) color in chat status bar. (black, white, red, green, blue, cyan, yellow, magenta)
*autolog*;;
Enable or disable autologging. true or false

View File

@ -9,20 +9,32 @@ ui = {
alerts=true;
// Output a bell when receiving a message (see manpage)
bell_on_message=true
bell_on_message=true;
// Output a bell when receiving a filetransfer (see manpage)
bell_on_filetrans=true
bell_on_filetrans=true;
// Don't output a bell when a filetransfer was accepted (see manpage)
bell_on_filetrans_accept=false
bell_on_filetrans_accept=false;
// Output a bell when receiving a group/call invite (see manpage)
bell_on_invite=true
bell_on_invite=true;
// true to use native terminal colours, false to use toxic default colour theme
native_colors=false;
// set background color of chat status bars (black, white, red, green, blue, cyan, yellow, magenta)
color_bar_bg="blue";
// set foreground (text) color of chat status bars (black, white, red, green, blue, cyan, yellow, magenta)
color_bar_fg="white";
// set foreground accent color of chat status bars (black, white, red, green, blue, cyan, yellow, magenta)
color_bar_accent="cyan";
// set foreground notify (and typing) color in chat status bar (black, white, red, green, blue, cyan, yellow, magenta)
color_bar_notify="yellow";
// true to enable autologging, false to disable
autolog=false;
@ -30,7 +42,7 @@ ui = {
time_format=24;
// Timestamp format string according to date/strftime format. Overrides time_format setting
timestamp_format="%H:%M:%S";
timestamp_format="%H:%M";
// true to show you when others are typing a message in 1-on-1 chats
show_typing_other=true;
@ -54,19 +66,19 @@ ui = {
history_size=700;
// time in milliseconds to display a notification
notification_timeout=3000;
notification_timeout=6000;
// Indicator for display when someone connects or joins a group.
// Indicator for display when someone connects or joins a group
line_join="-->";
// Indicator for display when someone disconnects or leaves a group.
// Indicator for display when someone disconnects or leaves a group
line_quit="<--";
// Indicator for alert messages.
line_alert="-!-";
// Indicator for normal messages.
line_normal="---";
line_normal="-";
// true to change status based on screen/tmux attach/detach, false to disable
mplex_away=true;
@ -131,6 +143,6 @@ keys = {
half_page_up="Ctrl+F";
half_page_down="Ctrl+V";
page_bottom="Ctrl+H";
toggle_peerlist="Ctrl+b";
toggle_peerlist="Ctrl+B";
toggle_paste_mode="Ctrl+T";
};

View File

@ -0,0 +1,297 @@
#!/usr/bin/env sh
# MIT License
#
# Copyright (c) 2021 Maxim Biro <nurupo.contributions@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Script for building a minimal statically compiled Toxic. While it doesn't
# support X11 integration, video/audio calls, desktop & sound notifications, QR
# codes and Python scripting, it is rather portable.
#
# Run as:
#
# sudo docker run -it --rm \
# -v /tmp/artifact:/artifact \
# -v /home/jfreegman/git/toxic:/toxic \
# amd64/alpine:latest \
# /bin/sh /toxic/script/build-minimal-static-toxic.sh
#
# that would use Toxic code from /home/jfreegman/git/toxic and place the build
# artifact at /tmp/artifact.
# You can change between amd64/alpine:latest and i386/alpine:latest, for 64-bit
# and 32-bit builds.
#
# To debug, run:
#
# sudo docker run -it --rm \
# -v /tmp/artifact:/artifact \
# -v /home/jfreegman/git/toxic:/toxic \
# amd64/alpine:latest \
# /bin/sh
# # sh /toxic/script/build-minimal-static-toxic.sh
set -eu
ARTIFACT_DIR="/artifact"
TOXIC_SRC_DIR="/toxic"
# Make sure we run in the expected environment
if ! grep -q 'docker' /proc/1/cgroup
then
echo "Error: This script should be run inside a disposable Docker container as it might modify system files in ways that would break a real system."
exit 1
fi
if [ ! -f /etc/os-release ] || ! grep -qi 'Alpine Linux' /etc/os-release
then
echo "Error: This script expects to be run on Alpine Linux."
exit 1
fi
if [ ! -d "$ARTIFACT_DIR" ] || [ ! -d "$TOXIC_SRC_DIR" ]
then
echo "Error: At least one of $ARTIFACT_DIR or $TOXIC_SRC_DIR directories inside the container is missing."
exit 1
fi
if [ "$(id -u)" != "0" ]
then
echo "Error: This script expects to be run as root."
exit 1
fi
set -x
# Use all cores for building
MAKEFLAGS=j$(nproc)
export MAKEFLAGS
check_sha256()
{
if ! ( echo "$1 $2" | sha256sum -cs - )
then
echo "Error: sha256 of $2 doesn't match the known one."
echo "Expected: $1 $2"
echo "Got: $(sha256sum "$2")"
exit 1
else
echo "sha256 matches the expected one: $1"
fi
}
apk update
apk upgrade
apk add \
brotli-dev \
brotli-static \
build-base \
cmake \
git \
libconfig-dev \
libconfig-static \
libsodium-dev \
libsodium-static \
linux-headers \
ncurses-dev \
ncurses-static \
ncurses-terminfo \
ncurses-terminfo-base \
nghttp2-dev \
nghttp2-static \
openssl-dev \
openssl-libs-static \
pkgconf \
wget \
xz \
zlib-dev \
zlib-static
BUILD_DIR="/tmp/build"
mkdir -p "$BUILD_DIR"
# Build Toxcore
cd "$BUILD_DIR"
TOXCORE_VERSION="0.2.12"
TOXCORE_HASH="30ae3263c9b68d3bef06f799ba9d7a67e3fad447030625f0ffa4bb22684228b0"
TOXCORE_FILENAME="c-toxcore-$TOXCORE_VERSION.tar.gz"
wget --timeout=10 -O "$TOXCORE_FILENAME" "https://github.com/TokTok/c-toxcore/archive/v$TOXCORE_VERSION.tar.gz"
check_sha256 "$TOXCORE_HASH" "$TOXCORE_FILENAME"
tar -o -xf "$TOXCORE_FILENAME"
rm "$TOXCORE_FILENAME"
cd c-toxcore*
cmake -B_build -H. \
-DENABLE_STATIC=ON \
-DENABLE_SHARED=OFF \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_TOXAV=OFF \
-DBOOTSTRAP_DAEMON=OFF \
-DDHT_BOOTSTRAP=OFF \
-DCMAKE_INSTALL_PREFIX="$BUILD_DIR/prefix-toxcore"
cmake --build _build --target install
# Build cURL
# While Alpine does provide a static cURL build, it's not built with
# --with-ca-fallback, which is needed for better cross-distro portability.
# Basically, some distros put their ca-certificates in different places, and
# with --with-ca-fallback we or the user can provide the cert bundle file
# location with SSL_CERT_FILE env variable.
cd "$BUILD_DIR"
CURL_VERSION="7.74.0"
CURL_HASH="e56b3921eeb7a2951959c02db0912b5fcd5fdba5aca071da819e1accf338bbd7"
CURL_FILENAME="curl-$CURL_VERSION.tar.gz"
wget --timeout=10 -O "$CURL_FILENAME" "https://curl.haxx.se/download/$CURL_FILENAME"
check_sha256 "$CURL_HASH" "$CURL_FILENAME"
tar -xf curl*.tar.gz
rm curl*.tar.gz
cd curl*
./configure \
--prefix="$BUILD_DIR/prefix-curl" \
--disable-shared \
--enable-static \
--without-ca-bundle \
--without-ca-path \
--with-ca-fallback \
--with-nghttp2 \
--with-brotli
make
make install
sed -i 's|-lbrotlidec |-lbrotlidec-static -lbrotlicommon-static |g' $BUILD_DIR/prefix-curl/lib/pkgconfig/libcurl.pc
# Build Toxic
cd "$BUILD_DIR"
cp -a "$TOXIC_SRC_DIR" toxic
cd toxic
if [ -z "$(git describe --tags --exact-match HEAD)" ]
then
set +x
echo "Didn't find a git tag on the HEAD commit. You seem to be building an in-development release of Toxic rather than a release version." | fold -sw 80
printf "Do you wish to proceed? (y/N): "
read -r answer
if echo "$answer" | grep -v -iq "^y" ; then
echo "Exiting."
exit 1
fi
set -x
fi
sed -i 's|pkg-config|pkg-config --static|' cfg/global_vars.mk
sed -i 's|<limits.h|<linux/limits.h|' src/*
CFLAGS="-static" PKG_CONFIG_PATH="$BUILD_DIR/prefix-toxcore/lib64/pkgconfig:$BUILD_DIR/prefix-toxcore/lib/pkgconfig:$BUILD_DIR/prefix-curl/lib/pkgconfig" PREFIX="$BUILD_DIR/prefix-toxic" make \
DISABLE_X11=1 \
DISABLE_AV=1 \
DISABLE_SOUND_NOTIFY=1 \
DISABLE_QRCODE=1 \
DISABLE_QRPNG=1 \
DISABLE_DESKTOP_NOTIFY=1 \
ENABLE_PYTHON=0 \
ENABLE_RELEASE=1 \
ENABLE_ASAN=0 \
install
# Prepare the build artifact
PREPARE_ARTIFACT_DIR="$BUILD_DIR/artifact"
cp -a "$BUILD_DIR/prefix-toxic/bin" "$PREPARE_ARTIFACT_DIR"
strip "$PREPARE_ARTIFACT_DIR"/*
cp -a "$BUILD_DIR/toxic/misc"/* "$PREPARE_ARTIFACT_DIR"
mv "$PREPARE_ARTIFACT_DIR/toxic.conf.example" "$PREPARE_ARTIFACT_DIR/toxic.conf"
cp -aL /usr/share/terminfo "$PREPARE_ARTIFACT_DIR"
echo "A minimal statically compiled Toxic.
Doesn't support X11 integration, video/audio calls, desktop & sound
notifications, QR codes and Python scripting.
However, it is rather portable.
Toxic $(git -C "$BUILD_DIR/toxic" describe --tags --exact-match HEAD) ($(git -C "$BUILD_DIR/toxic" rev-parse HEAD))
Build date time: $(TZ=UTC date +"%Y-%m-%dT%H:%M:%S%z")
OS:
$(cat /etc/os-release)
List of self-built software statically compiled into Toxic:
libcurl $CURL_VERSION
libtoxcore $TOXCORE_VERSION
List of OS-packaged software statically compiled into Toxic:
$(apk list -I | grep 'static' | sort -i)
List of all packages installed during the build:
$(apk list -I | sort -i)" > "$PREPARE_ARTIFACT_DIR/build_info"
echo '#!/usr/bin/env sh
DEBIAN_SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
RHEL_SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt
OPENSUSE_CERT_FILE=/etc/ssl/ca-bundle.pem
if [ ! -f "$SSL_CERT_FILE" ] ; then
if [ -f "$DEBIAN_SSL_CERT_FILE" ] ; then
SSL_CERT_FILE="$DEBIAN_SSL_CERT_FILE"
elif [ -f "$RHEL_SSL_CERT_FILE" ] ; then
SSL_CERT_FILE="$RHEL_SSL_CERT_FILE"
elif [ -f "$OPENSUSE_CERT_FILE" ] ; then
SSL_CERT_FILE="$OPENSUSE_CERT_FILE"
fi
fi
if [ -z "$SSL_CERT_FILE" ] ; then
echo "Warning: Couldn'\''t find the SSL CA certificate store file." | fold -sw 80
echo
echo "Toxic uses HTTPS to download a list of DHT bootstrap nodes in order to connect to the Tox DHT. This functionality is optional, you should be able to use Toxic without it. If you choose to use Toxic without it, you might need to manually enter DHT bootstrap node information using the '\''/connect'\'' command in order to come online." | fold -sw 80
echo
echo "To fix this issue, install SSL CAs as provided by your Linux distribution, e.g. '\''ca-certificates'\'' package on Debian/Ubuntu. If it'\''s already installed and you still see this message, run this script with SSL_CERT_FILE variable set to point to the SSL CA certificate store file location. The file is usually named '\''ca-certificates.crt'\'' or '\''ca-bundle.pem'\''." | fold -sw 80
echo
printf "Do you wish to run Toxic without SSL CA certificate store file found? (y/N): "
read -r answer
if echo "$answer" | grep -v -iq "^y" ; then
echo "Exiting."
exit
fi
fi
cd "$(dirname -- $0)"
SSL_CERT_FILE="$SSL_CERT_FILE" TERMINFO=./terminfo ./toxic -c toxic.conf' > "$PREPARE_ARTIFACT_DIR/run_toxic.sh"
chmod a+x "$PREPARE_ARTIFACT_DIR/run_toxic.sh"
# Tar it
cd "$PREPARE_ARTIFACT_DIR"
cd ..
ARCH="$(tr '_' '-' < /etc/apk/arch)"
ARTIFACT_NAME="toxic-minimal-static-musl_linux_$ARCH"
mv "$PREPARE_ARTIFACT_DIR" "$PREPARE_ARTIFACT_DIR/../$ARTIFACT_NAME"
tar -cJf "$ARTIFACT_NAME.tar.xz" "$ARTIFACT_NAME"
mv "$ARTIFACT_NAME.tar.xz" "$ARTIFACT_DIR"
chmod 777 -R "$ARTIFACT_DIR"

View File

@ -99,18 +99,16 @@ void api_send(const char *msg)
}
char *name = api_get_nick();
char timefrmt[TIME_STR_SIZE];
if (name == NULL) {
return;
}
self_window = get_active_window();
get_time_str(timefrmt, sizeof(timefrmt));
strncpy((char *) self_window->chatwin->line, msg, sizeof(self_window->chatwin->line));
add_line_to_hist(self_window->chatwin);
int id = line_info_add(self_window, timefrmt, name, NULL, OUT_MSG, 0, 0, "%s", msg);
int id = line_info_add(self_window, true, name, NULL, OUT_MSG, 0, 0, "%s", msg);
cqueue_add(self_window->chatwin->cqueue, msg, strlen(msg), OUT_MSG, id);
free(name);
}
@ -156,7 +154,7 @@ void cmd_run(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
error_str = "Only one argument allowed.";
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, error_str);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, error_str);
return;
}
@ -165,7 +163,7 @@ void cmd_run(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
if (fp == NULL) {
error_str = "Path does not exist.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, error_str);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, error_str);
return;
}

View File

@ -90,7 +90,7 @@ void audio_bit_rate_callback(ToxAV *av, uint32_t friend_number, uint32_t audio_b
static void print_err(ToxWindow *self, const char *error_str)
{
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", error_str);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s", error_str);
}
ToxAV *init_audio(ToxWindow *self, Tox *tox)
@ -113,13 +113,13 @@ ToxAV *init_audio(ToxWindow *self, Tox *tox)
if (!CallControl.av) {
CallControl.audio_errors |= ae_StartingCoreAudio;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to init ToxAV");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to init ToxAV");
return NULL;
}
if (init_devices() == de_InternalError) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to init devices");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to init devices");
toxav_kill(CallControl.av);
return CallControl.av = NULL;
@ -200,7 +200,7 @@ static bool cancel_call(Call *call)
static int start_transmission(ToxWindow *self, Call *call)
{
if (!self || !CallControl.av) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to prepare audio transmission");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to prepare audio transmission");
return -1;
}
@ -209,17 +209,17 @@ static int start_transmission(ToxWindow *self, Call *call)
if (error != de_None) {
if (error == de_FailedStart) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to start audio input device");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to start audio input device");
}
if (error == de_InternalError) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Internal error with opening audio input device");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Internal error with opening audio input device");
}
}
if (open_output_device(&call->out_idx,
CallControl.audio_sample_rate, CallControl.audio_frame_duration, CallControl.audio_channels) != de_None) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open audio output device!");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to open audio output device!");
}
return 0;
@ -342,7 +342,7 @@ void on_call_state(ToxAV *av, uint32_t friend_number, uint32_t state, void *user
case TOXAV_FRIEND_CALL_STATE_ERROR:
case TOXAV_FRIEND_CALL_STATE_FINISHED:
if (state == TOXAV_FRIEND_CALL_STATE_ERROR) {
line_info_add(CallControl.prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "ToxAV callstate error!");
line_info_add(CallControl.prompt, false, NULL, NULL, SYS_MSG, 0, 0, "ToxAV callstate error!");
}
if (call->status == cs_Pending) {
@ -669,7 +669,7 @@ void cmd_list_devices(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*
}
else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
return;
}
@ -708,7 +708,7 @@ void cmd_change_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (
}
else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
return;
}
@ -748,7 +748,7 @@ void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
}
else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
return;
}
@ -816,7 +816,7 @@ void cmd_bitrate(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
}
if (argc == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0,
"Current audio encoding bitrate: %u", call->audio_bit_rate);
return;
}

View File

@ -775,7 +775,7 @@ float get_input_volume(void)
void print_al_devices(ToxWindow *self, DeviceType type)
{
for (int i = 0; i < audio_state->num_al_devices[type]; ++i) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG,
line_info_add(self, false, NULL, NULL, SYS_MSG,
audio_state->current_al_device_name[type]
&& strcmp(audio_state->current_al_device_name[type], audio_state->al_device_names[type][i]) == 0 ? 1 : 0,
0, "%d: %s", i, audio_state->al_device_names[type][i]);

View File

@ -45,10 +45,10 @@ static void print_ac_matches(ToxWindow *self, Tox *m, char **list, size_t n_matc
}
for (size_t i = 0; i < n_matches; ++i) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", list[i]);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s", list[i]);
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "");
}
/* puts match in match buffer. if more than one match, add first n chars that are identical.

View File

@ -167,11 +167,11 @@ void kill_chat_window(ToxWindow *self, Tox *m)
del_window(self);
}
static void recv_message_helper(ToxWindow *self, const char *msg, const char *nick, const char *timefrmt)
static void recv_message_helper(ToxWindow *self, const char *msg, const char *nick)
{
ChatContext *ctx = self->chatwin;
line_info_add(self, timefrmt, nick, NULL, IN_MSG, 0, 0, "%s", msg);
line_info_add(self, true, nick, NULL, IN_MSG, 0, 0, "%s", msg);
write_to_log(msg, nick, ctx->log, false);
if (self->active_box != -1) {
@ -183,11 +183,11 @@ static void recv_message_helper(ToxWindow *self, const char *msg, const char *ni
}
}
static void recv_action_helper(ToxWindow *self, const char *action, const char *nick, const char *timefrmt)
static void recv_action_helper(ToxWindow *self, const char *action, const char *nick)
{
ChatContext *ctx = self->chatwin;
line_info_add(self, timefrmt, nick, NULL, IN_ACTION, 0, 0, "%s", action);
line_info_add(self, true, nick, NULL, IN_ACTION, 0, 0, "%s", action);
write_to_log(action, nick, ctx->log, true);
if (self->active_box != -1) {
@ -210,16 +210,13 @@ static void chat_onMessage(ToxWindow *self, Tox *m, uint32_t num, Tox_Message_Ty
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
if (type == TOX_MESSAGE_TYPE_NORMAL) {
recv_message_helper(self, msg, nick, timefrmt);
recv_message_helper(self, msg, nick);
return;
}
if (type == TOX_MESSAGE_TYPE_ACTION) {
recv_action_helper(self, msg, nick, timefrmt);
recv_action_helper(self, msg, nick);
return;
}
}
@ -237,9 +234,6 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, Tox_C
ChatContext *ctx = self->chatwin;
const char *msg;
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
@ -254,7 +248,7 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, Tox_C
chat_resume_file_senders(self, m, num);
msg = "has come online";
line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, GREEN, msg);
line_info_add(self, true, nick, NULL, CONNECTION, 0, GREEN, msg);
write_to_log(msg, nick, ctx->log, true);
} else if (connection_status == TOX_CONNECTION_NONE) {
Friends.list[num].is_typing = false;
@ -266,7 +260,7 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, Tox_C
chat_pause_file_transfers(num);
msg = "has gone offline";
line_info_add(self, timefrmt, nick, NULL, DISCONNECTION, 0, RED, msg);
line_info_add(self, true, nick, NULL, DISCONNECTION, 0, RED, msg);
write_to_log(msg, nick, ctx->log, true);
}
}
@ -509,11 +503,11 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, uint32_t friendnum, uint
/* transfer is accepted */
if (ft->state == FILE_TRANSFER_PENDING) {
ft->state = FILE_TRANSFER_STARTED;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer [%zu] for '%s' accepted.",
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "File transfer [%zu] for '%s' accepted.",
ft->index, ft->file_name);
char progline[MAX_STR_SIZE];
init_progress_bar(progline);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s", progline);
sound_notify(self, silent, NT_NOFOCUS | user_settings->bell_on_filetrans_accept | NT_WNDALERT_2, NULL);
ft->line_id = self->chatwin->hst->line_end->id + 2;
} else if (ft->state == FILE_TRANSFER_PAUSED) { /* transfer is resumed */
@ -637,14 +631,14 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
if (!ft) {
tox_file_control(m, friendnum, filenumber, TOX_FILE_CONTROL_CANCEL, NULL);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0,
"File transfer request failed: Too many concurrent file transfers.");
return;
}
char sizestr[32];
bytes_convert_str(sizestr, sizeof(sizestr), file_size);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer request for '%s' (%s)", filename, sizestr);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "File transfer request for '%s' (%s)", filename, sizestr);
if (!valid_file_name(filename, name_length)) {
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, "File transfer failed: Invalid file name.", notif_error);
@ -703,7 +697,7 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
}
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type '/savefile %zu' to accept the file transfer.", ft->index);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Type '/savefile %zu' to accept the file transfer.", ft->index);
ft->file_size = file_size;
snprintf(ft->file_path, sizeof(ft->file_path), "%s", file_path);
@ -745,21 +739,21 @@ static void chat_onConferenceInvite(ToxWindow *self, Tox *m, int32_t friendnumbe
Friends.list[friendnumber].conference_invite.length = length;
Friends.list[friendnumber].conference_invite.type = type;
sound_notify(self, generic_message, NT_WNDALERT_2 | user_settings->bell_on_invite, NULL);
char name[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, name, friendnumber);
const char *description = type == TOX_CONFERENCE_TYPE_AV ? "an audio conference" : "a conference";
if (self->active_box != -1) {
box_silent_notify2(self, NT_WNDALERT_2 | NT_NOFOCUS, self->active_box, "invites you to join %s", description);
box_notify2(self, generic_message, NT_WNDALERT_2 | user_settings->bell_on_invite, self->active_box,
"invites you to join %s", description);
} else {
box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join %s", description);
box_notify(self, generic_message, NT_WNDALERT_2 | user_settings->bell_on_invite, &self->active_box, name,
"invites you to join %s", description);
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to %s.", name, description);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to %s.", name, description);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat.");
}
/* AV Stuff */
@ -777,7 +771,7 @@ void chat_onInvite(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state
/* call is flagged active here */
self->is_call = true;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Incoming audio call! Type: \"/answer\" or \"/reject\"");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Incoming audio call! Type: \"/answer\" or \"/reject\"");
if (self->ringing_sound == -1) {
sound_notify(self, call_incoming, NT_LOOP | user_settings->bell_on_invite, &self->ringing_sound);
@ -799,7 +793,7 @@ void chat_onRinging(ToxWindow *self, ToxAV *av, uint32_t friend_number, int stat
return;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ringing...type \"/hangup\" to cancel it.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Ringing...type \"/hangup\" to cancel it.");
#ifdef SOUND_NOTIFY
@ -821,7 +815,7 @@ void chat_onStarting(ToxWindow *self, ToxAV *av, uint32_t friend_number, int sta
init_infobox(self);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call started! Type: \"/hangup\" to end it.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Call started! Type: \"/hangup\" to end it.");
/* call is flagged active here */
self->is_call = true;
@ -841,7 +835,7 @@ void chat_onEnding(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state
}
kill_infobox(self);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call ended!");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Call ended!");
self->is_call = false;
@ -860,7 +854,7 @@ void chat_onError(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
}
self->is_call = false;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error!");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Error!");
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
@ -881,7 +875,7 @@ void chat_onStart(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
init_infobox(self);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call started! Type: \"/hangup\" to end it.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Call started! Type: \"/hangup\" to end it.");
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
@ -899,7 +893,7 @@ void chat_onCancel(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state
self->is_call = false;
kill_infobox(self);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call canceled!");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Call canceled!");
#ifdef SOUND_NOTIFY
stop_sound(self->ringing_sound);
@ -915,7 +909,7 @@ void chat_onReject(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state
return;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Rejected!");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Rejected!");
self->is_call = false;
#ifdef SOUND_NOTIFY
@ -933,7 +927,7 @@ void chat_onEnd(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
}
kill_infobox(self);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Call ended!");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Call ended!");
self->is_call = false;
#ifdef SOUND_NOTIFY
@ -1033,7 +1027,7 @@ static void draw_infobox(ToxWindow *self)
wattroff(infobox->win, A_BOLD);
wprintw(infobox->win, "%.2f\n", (double) infobox->vad_lvl);
wborder(infobox->win, ACS_VLINE, ' ', ACS_HLINE, ACS_HLINE, ACS_TTEE, ' ', ACS_LLCORNER, ' ');
wborder(infobox->win, ACS_VLINE, ' ', ACS_HLINE, ACS_HLINE, ACS_ULCORNER, ' ', ACS_LLCORNER, ' ');
wnoutrefresh(infobox->win);
}
@ -1051,10 +1045,7 @@ static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
size_t len = tox_self_get_name_size(m);
selfname[len] = '\0';
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
int id = line_info_add(self, timefrmt, selfname, NULL, OUT_ACTION, 0, 0, "%s", action);
int id = line_info_add(self, true, selfname, NULL, OUT_ACTION, 0, 0, "%s", action);
cqueue_add(ctx->cqueue, action, strlen(action), OUT_ACTION, id);
}
@ -1170,18 +1161,15 @@ bool chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
size_t len = tox_self_get_name_size(m);
selfname[len] = '\0';
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
int id = line_info_add(self, timefrmt, selfname, NULL, OUT_MSG, 0, 0, "%s", line);
int id = line_info_add(self, true, selfname, NULL, OUT_MSG, 0, 0, "%s", line);
cqueue_add(ctx->cqueue, line, strlen(line), OUT_MSG, id);
} else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to parse message.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * Failed to parse message.");
}
}
wclear(ctx->linewin);
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
wmove(self->window, y2, 0);
reset_buf(ctx);
}
@ -1194,7 +1182,8 @@ bool chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
static void chat_onDraw(ToxWindow *self, Tox *m)
{
int x2, y2;
int x2;
int y2;
getmaxyx(self->window, y2, x2);
if (y2 <= 0 || x2 <= 0) {
@ -1209,15 +1198,14 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
wclear(ctx->linewin);
curs_set(1);
if (ctx->len > 0) {
mvwprintw(ctx->linewin, 1, 0, "%ls", &ctx->line[ctx->start]);
mvwprintw(ctx->linewin, 0, 0, "%ls", &ctx->line[ctx->start]);
}
curs_set(1);
/* Draw status bar */
StatusBar *statusbar = self->stb;
mvwhline(statusbar->topline, 1, 0, ACS_HLINE, x2);
wmove(statusbar->topline, 0, 0);
/* Draw name, status and note in statusbar */
@ -1227,38 +1215,63 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
switch (status) {
case TOX_USER_STATUS_NONE:
colour = GREEN;
colour = STATUS_ONLINE;
break;
case TOX_USER_STATUS_AWAY:
colour = YELLOW;
colour = STATUS_AWAY;
break;
case TOX_USER_STATUS_BUSY:
colour = RED;
colour = STATUS_ONLINE;
break;
}
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, " [");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
wprintw(statusbar->topline, " %s", ONLINE_CHAR);
wprintw(statusbar->topline, "%s", ONLINE_CHAR);
wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
if (Friends.list[self->num].is_typing) {
wattron(statusbar->topline, COLOR_PAIR(YELLOW));
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, "] ");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
pthread_mutex_lock(&Winthread.lock);
const bool is_typing = Friends.list[self->num].is_typing;
pthread_mutex_unlock(&Winthread.lock);
if (is_typing) {
wattron(statusbar->topline, A_BOLD | COLOR_PAIR(BAR_NOTIFY));
} else {
wattron(statusbar->topline, COLOR_PAIR(BAR_TEXT));
}
wattron(statusbar->topline, A_BOLD);
wprintw(statusbar->topline, " %s ", statusbar->nick);
wattroff(statusbar->topline, A_BOLD);
wprintw(statusbar->topline, "%s", statusbar->nick);
if (Friends.list[self->num].is_typing) {
wattroff(statusbar->topline, COLOR_PAIR(YELLOW));
if (is_typing) {
wattroff(statusbar->topline, A_BOLD | COLOR_PAIR(BAR_NOTIFY));
} else {
wattroff(statusbar->topline, A_BOLD | COLOR_PAIR(BAR_TEXT));
}
} else {
wprintw(statusbar->topline, " %s", OFFLINE_CHAR);
wattron(statusbar->topline, A_BOLD);
wprintw(statusbar->topline, " %s ", statusbar->nick);
wattroff(statusbar->topline, A_BOLD);
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, " [");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wattron(statusbar->topline, COLOR_PAIR(BAR_TEXT));
wprintw(statusbar->topline, "%s", OFFLINE_CHAR);
wattroff(statusbar->topline, COLOR_PAIR(BAR_TEXT));
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, "] ");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wattron(statusbar->topline, COLOR_PAIR(BAR_TEXT));
wprintw(statusbar->topline, "%s", statusbar->nick);
wattroff(statusbar->topline, COLOR_PAIR(BAR_TEXT));
}
/* Reset statusbar->statusmsg on window resize */
@ -1287,30 +1300,51 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
}
if (statusbar->statusmsg[0]) {
wprintw(statusbar->topline, ": %s ", statusbar->statusmsg);
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, " | ");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wattron(statusbar->topline, COLOR_PAIR(BAR_TEXT));
wprintw(statusbar->topline, "%s ", statusbar->statusmsg);
} else {
wattron(statusbar->topline, COLOR_PAIR(BAR_TEXT));
}
wclrtoeol(statusbar->topline);
int s_y;
int s_x;
getyx(statusbar->topline, s_y, s_x);
mvwhline(statusbar->topline, s_y, s_x, ' ', x2 - s_x - (KEY_IDENT_DIGITS * 2) - 3);
wattroff(statusbar->topline, COLOR_PAIR(BAR_TEXT));
wmove(statusbar->topline, 0, x2 - (KEY_IDENT_DIGITS * 2) - 3);
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, "{");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
size_t i;
wattron(statusbar->topline, COLOR_PAIR(BAR_TEXT));
for (i = 0; i < KEY_IDENT_DIGITS; ++i) {
for (size_t i = 0; i < KEY_IDENT_DIGITS; ++i) {
wprintw(statusbar->topline, "%02X", Friends.list[self->num].pub_key[i] & 0xff);
}
wprintw(statusbar->topline, "}\n");
wattroff(statusbar->topline, COLOR_PAIR(BAR_TEXT));
mvwhline(self->window, y2 - CHATBOX_HEIGHT, 0, ACS_HLINE, x2);
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, "} ");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
int y, x;
int y;
int x;
getyx(self->window, y, x);
UNUSED_VAR(x);
int new_x = ctx->start ? x2 - 1 : MAX(0, wcswidth(ctx->line, ctx->pos));
wmove(self->window, y + 1, new_x);
wmove(self->window, y, new_x);
draw_window_bar(self);
wnoutrefresh(self->window);
@ -1339,17 +1373,17 @@ static void chat_init_log(ToxWindow *self, Tox *m, const char *self_nick)
tox_self_get_address(m, (uint8_t *) myid);
if (log_init(ctx->log, self_nick, myid, Friends.list[self->num].pub_key, LOG_TYPE_CHAT) != 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to initialize chat log.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to initialize chat log.");
return;
}
if (load_chat_history(self, ctx->log) != 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to load chat history.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to load chat history.");
}
if (Friends.list[self->num].logging_on) {
if (log_enable(ctx->log) != 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to enable chat log.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to enable chat log.");
}
}
}
@ -1357,7 +1391,9 @@ static void chat_init_log(ToxWindow *self, Tox *m, const char *self_nick)
static void chat_onInit(ToxWindow *self, Tox *m)
{
curs_set(1);
int x2, y2;
int x2;
int y2;
getmaxyx(self->window, y2, x2);
if (y2 <= 0 || x2 <= 0) {
@ -1390,9 +1426,10 @@ static void chat_onInit(ToxWindow *self, Tox *m)
/* Init subwindows */
ChatContext *ctx = self->chatwin;
statusbar->topline = subwin(self->window, 2, x2, 0, 0);
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, x2, 0, 0);
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2 - CHATBOX_HEIGHT, 0);
statusbar->topline = subwin(self->window, TOP_BAR_HEIGHT, x2, 0, 0);
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT, x2, 0, 0);
self->window_bar = subwin(self->window, WINDOW_BAR_HEIGHT, x2, y2 - (CHATBOX_HEIGHT + WINDOW_BAR_HEIGHT), 0);
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2 - WINDOW_BAR_HEIGHT, 0);
ctx->hst = calloc(1, sizeof(struct history));
ctx->log = calloc(1, sizeof(struct chatlog));

View File

@ -41,7 +41,7 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
UNUSED_VAR(window);
if (argc < 2) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Requires type in|out and the file ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Requires type in|out and the file ID.");
return;
}
@ -50,7 +50,7 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
long int idx = strtol(argv[2], NULL, 10);
if ((idx == 0 && strcmp(argv[2], "0")) || idx >= MAX_FILES || idx < 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID.");
return;
}
@ -62,17 +62,17 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
} else if (strcasecmp(inoutstr, "out") == 0) {
ft = get_file_transfer_struct_index(self->num, idx, FILE_TRANSFER_SEND);
} else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type must be 'in' or 'out'.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Type must be 'in' or 'out'.");
return;
}
if (!ft) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID.");
return;
}
if (ft->state == FILE_TRANSFER_INACTIVE) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid file ID.");
return;
}
@ -85,25 +85,25 @@ void cmd_conference_invite(WINDOW *window, ToxWindow *self, Tox *m, int argc, ch
UNUSED_VAR(window);
if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Conference number required.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Conference number required.");
return;
}
long int conferencenum = strtol(argv[1], NULL, 10);
if ((conferencenum == 0 && strcmp(argv[1], "0")) || conferencenum < 0 || conferencenum == LONG_MAX) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid conference number.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid conference number.");
return;
}
Tox_Err_Conference_Invite err;
if (!tox_conference_invite(m, self->num, conferencenum, &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to conference (error %d)", err);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to conference (error %d)", err);
return;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invited contact to Conference %ld.", conferencenum);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invited contact to Conference %ld.", conferencenum);
}
void cmd_conference_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -113,7 +113,7 @@ void cmd_conference_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char
UNUSED_VAR(argv);
if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
return;
}
@ -122,7 +122,7 @@ void cmd_conference_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char
uint8_t type = Friends.list[self->num].conference_invite.type;
if (!Friends.list[self->num].conference_invite.pending) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending conference invite.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "No pending conference invite.");
return;
}
@ -133,7 +133,7 @@ void cmd_conference_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char
conferencenum = tox_conference_join(m, self->num, (const uint8_t *) conferencekey, length, &err);
if (err != TOX_ERR_CONFERENCE_JOIN_OK) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Conference instance failed to initialize (error %d)", err);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Conference instance failed to initialize (error %d)", err);
return;
}
} else if (type == TOX_CONFERENCE_TYPE_AV) {
@ -142,21 +142,21 @@ void cmd_conference_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char
audio_conference_callback, NULL);
if (conferencenum == (uint32_t) -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Audio conference instance failed to initialize");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Audio conference instance failed to initialize");
return;
}
#else
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Audio support disabled by compile-time option.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Audio support disabled by compile-time option.");
return;
#endif
} else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Unknown conference type %d", type);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Unknown conference type %d", type);
return;
}
if (init_conference_win(m, conferencenum, type, NULL, 0) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Conference window failed to initialize.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Conference window failed to initialize.");
tox_conference_delete(m, conferencenum, NULL);
return;
}
@ -165,7 +165,7 @@ void cmd_conference_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char
if (type == TOX_CONFERENCE_TYPE_AV) {
if (!init_conference_audio_input(m, conferencenum)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Audio capture failed; use \"/audio on\" to try again.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Audio capture failed; use \"/audio on\" to try again.");
}
}
@ -177,26 +177,26 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
UNUSED_VAR(window);
if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File ID required.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "File ID required.");
return;
}
long int idx = strtol(argv[1], NULL, 10);
if ((idx == 0 && strcmp(argv[1], "0")) || idx < 0 || idx >= MAX_FILES) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID.");
return;
}
struct FileTransfer *ft = get_file_transfer_struct_index(self->num, idx, FILE_TRANSFER_RECV);
if (!ft) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID.");
return;
}
if (ft->state != FILE_TRANSFER_PENDING) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "No pending file transfers with that ID.");
return;
}
@ -213,12 +213,12 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
goto on_recv_error;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Saving file [%ld] as: '%s'", idx, ft->file_path);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Saving file [%ld] as: '%s'", idx, ft->file_path);
/* prep progress bar line */
char progline[MAX_STR_SIZE];
init_progress_bar(progline);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", progline);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s", progline);
ft->line_id = self->chatwin->hst->line_end->id + 2;
ft->state = FILE_TRANSFER_STARTED;
@ -229,23 +229,23 @@ on_recv_error:
switch (err) {
case TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Friend not found.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Friend not found.");
return;
case TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Friend is not online.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Friend is not online.");
return;
case TOX_ERR_FILE_CONTROL_NOT_FOUND:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Invalid filenumber.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Invalid filenumber.");
return;
case TOX_ERR_FILE_CONTROL_SENDQ:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Connection error.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed: Connection error.");
return;
default:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed (error %d)\n", err);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "File transfer failed (error %d)\n", err);
return;
}
}
@ -257,7 +257,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
const char *errmsg = NULL;
if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File path required.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "File path required.");
return;
}
@ -266,21 +266,21 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
int path_len = strlen(path);
if (path_len >= MAX_STR_SIZE) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File path exceeds character limit.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "File path exceeds character limit.");
return;
}
FILE *file_to_send = fopen(path, "r");
if (file_to_send == NULL) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File not found.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "File not found.");
return;
}
off_t filesize = file_size(path);
if (filesize == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid file.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid file.");
fclose(file_to_send);
return;
}
@ -310,7 +310,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
char sizestr[32];
bytes_convert_str(sizestr, sizeof(sizestr), filesize);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Sending file [%d]: '%s' (%s)", filenum, file_name, sizestr);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Sending file [%d]: '%s' (%s)", filenum, file_name, sizestr);
return;
@ -338,7 +338,7 @@ on_send_error:
break;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", errmsg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s", errmsg);
tox_file_control(m, self->num, filenum, TOX_FILE_CONTROL_CANCEL, NULL);
fclose(file_to_send);
}

View File

@ -65,6 +65,9 @@
extern char *DATA_FILE;
#define MAX_CONFERENCE_NUM (MAX_WINDOWS_NUM - 2)
#define CONFERENCE_EVENT_WAIT 30
static ConferenceChat conferences[MAX_CONFERENCE_NUM];
static int max_conference_index = 0;
@ -161,17 +164,17 @@ static void init_conference_logging(ToxWindow *self, Tox *m, uint32_t conference
tox_conference_get_id(m, conferencenum, (uint8_t *) conference_id);
if (log_init(ctx->log, conferences[self->num].title, my_id, conference_id, LOG_TYPE_CHAT) != 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Warning: Log failed to initialize.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Warning: Log failed to initialize.");
return;
}
if (load_chat_history(self, ctx->log) != 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to load chat history.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to load chat history.");
}
if (user_settings->autolog == AUTOLOG_ON) {
if (log_enable(ctx->log) != 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to enable chat log.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to enable chat log.");
}
}
@ -307,9 +310,9 @@ void redraw_conference_win(ToxWindow *self)
refresh();
clear();
int x2, y2;
getmaxyx(stdscr, y2, x2);
y2 -= 2;
int x2;
int y2;
getmaxyx(self->window, y2, x2);
if (y2 <= 0 || x2 <= 0) {
return;
@ -322,20 +325,22 @@ void redraw_conference_win(ToxWindow *self)
delwin(ctx->linewin);
delwin(ctx->history);
delwin(self->window_bar);
delwin(self->window);
self->window = newwin(y2, x2, 0, 0);
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2 - CHATBOX_HEIGHT, 0);
self->window_bar = subwin(self->window, WINDOW_BAR_HEIGHT, x2, y2 - (CHATBOX_HEIGHT + WINDOW_BAR_HEIGHT), 0);
if (self->show_peerlist) {
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, x2 - SIDEBAR_WIDTH - 1, 0, 0);
ctx->sidebar = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, SIDEBAR_WIDTH, 0, x2 - SIDEBAR_WIDTH);
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT, x2 - SIDEBAR_WIDTH - 1, 0, 0);
ctx->sidebar = subwin(self->window, y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT, SIDEBAR_WIDTH, 0, x2 - SIDEBAR_WIDTH);
} else {
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, x2, 0, 0);
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT, x2, 0, 0);
}
scrollok(ctx->history, 0);
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
}
static void conference_onConferenceMessage(ToxWindow *self, Tox *m, uint32_t conferencenum, uint32_t peernum,
@ -362,12 +367,12 @@ static void conference_onConferenceMessage(ToxWindow *self, Tox *m, uint32_t con
/* Only play sound if mentioned by someone else */
if (strcasestr(msg, selfnick) && strcmp(selfnick, nick)) {
sound_notify(self, generic_message, NT_WNDALERT_0 | user_settings->bell_on_message, NULL);
if (self->active_box != -1) {
box_silent_notify2(self, NT_NOFOCUS, self->active_box, "%s %s", nick, msg);
box_notify2(self, generic_message, NT_WNDALERT_0 | NT_NOFOCUS | user_settings->bell_on_message,
self->active_box, "%s %s", nick, msg);
} else {
box_silent_notify(self, NT_NOFOCUS, &self->active_box, self->name, "%s %s", nick, msg);
box_notify(self, generic_message, NT_WNDALERT_0 | NT_NOFOCUS | user_settings->bell_on_message,
&self->active_box, self->name, "%s %s", nick, msg);
}
nick_clr = RED;
@ -375,10 +380,7 @@ static void conference_onConferenceMessage(ToxWindow *self, Tox *m, uint32_t con
sound_notify(self, silent, NT_WNDALERT_1, NULL);
}
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, nick, NULL, type == TOX_MESSAGE_TYPE_NORMAL ? IN_MSG : IN_ACTION, 0, nick_clr, "%s", msg);
line_info_add(self, true, nick, NULL, type == TOX_MESSAGE_TYPE_NORMAL ? IN_MSG : IN_ACTION, 0, nick_clr, "%s", msg);
write_to_log(msg, nick, ctx->log, false);
}
@ -402,9 +404,6 @@ static void conference_onConferenceTitleChange(ToxWindow *self, Tox *m, uint32_t
conference_set_title(self, conferencenum, title, length);
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
/* don't announce title when we join the room */
if (!timed_out(conferences[conferencenum].start_time, CONFERENCE_EVENT_WAIT)) {
return;
@ -412,7 +411,7 @@ static void conference_onConferenceTitleChange(ToxWindow *self, Tox *m, uint32_t
char nick[TOX_MAX_NAME_LENGTH];
get_conference_nick_truncate(m, nick, peernum, conferencenum);
line_info_add(self, timefrmt, nick, NULL, NAME_CHANGE, 0, 0, " set the conference title to: %s", title);
line_info_add(self, true, nick, NULL, NAME_CHANGE, 0, 0, " set the conference title to: %s", title);
char tmp_event[MAX_STR_SIZE];
snprintf(tmp_event, sizeof(tmp_event), "set title to %s", title);
@ -629,7 +628,10 @@ static bool find_peer_by_pubkey(const ConferencePeer *list, uint32_t num_peers,
const ConferencePeer *peer = &list[i];
if (peer->active && memcmp(peer->pubkey, pubkey, TOX_PUBLIC_KEY_SIZE) == 0) {
*idx = i;
if (idx) {
*idx = i;
}
return true;
}
}
@ -637,7 +639,8 @@ static bool find_peer_by_pubkey(const ConferencePeer *list, uint32_t num_peers,
return false;
}
static void update_peer_list(Tox *m, uint32_t conferencenum, uint32_t num_peers, uint32_t old_num_peers)
static void update_peer_list(ToxWindow *self, Tox *m, uint32_t conferencenum, uint32_t num_peers,
uint32_t old_num_peers)
{
ConferenceChat *chat = &conferences[conferencenum];
@ -645,6 +648,8 @@ static void update_peer_list(Tox *m, uint32_t conferencenum, uint32_t num_peers,
return;
}
ChatContext *ctx = self->chatwin;
ConferencePeer *old_peer_list = malloc(old_num_peers * sizeof(ConferencePeer));
if (!old_peer_list) {
@ -676,12 +681,14 @@ static void update_peer_list(Tox *m, uint32_t conferencenum, uint32_t num_peers,
continue;
}
bool new_peer = true;
uint32_t j;
if (find_peer_by_pubkey(old_peer_list, old_num_peers, peer->pubkey, &j)) {
ConferencePeer *old_peer = &old_peer_list[j];
memcpy(peer, old_peer, sizeof(ConferencePeer));
old_peer->active = false;
new_peer = false;
}
size_t length = tox_conference_peer_get_name_size(m, conferencenum, i, &err);
@ -702,22 +709,34 @@ static void update_peer_list(Tox *m, uint32_t conferencenum, uint32_t num_peers,
peer->name_length = length;
peer->peernum = i;
if (new_peer && peer->name_length > 0 && timed_out(chat->start_time, CONFERENCE_EVENT_WAIT)) {
const char *msg = "has joined the conference";
line_info_add(self, true, peer->name, NULL, CONNECTION, 0, GREEN, msg);
write_to_log(msg, peer->name, ctx->log, true);
}
#ifdef AUDIO
set_peer_audio_position(m, conferencenum, i);
#endif
}
conference_update_name_list(conferencenum);
for (uint32_t i = 0; i < old_num_peers; ++i) {
ConferencePeer *old_peer = &old_peer_list[i];
if (old_peer->active) {
if (old_peer->name_length > 0 && !find_peer_by_pubkey(chat->peer_list, chat->num_peers, old_peer->pubkey, NULL)) {
const char *msg = "has left the conference";
line_info_add(self, true, old_peer->name, NULL, DISCONNECTION, 0, RED, msg);
write_to_log(msg, old_peer->name, ctx->log, true);
}
free_peer(old_peer);
}
}
free(old_peer_list);
conference_update_name_list(conferencenum);
}
static void conference_onConferenceNameListChange(ToxWindow *self, Tox *m, uint32_t conferencenum)
@ -749,7 +768,7 @@ static void conference_onConferenceNameListChange(ToxWindow *self, Tox *m, uint3
chat->num_peers = num_peers;
chat->max_idx = num_peers;
update_peer_list(m, conferencenum, num_peers, old_num);
update_peer_list(self, m, conferencenum, num_peers, old_num);
}
static void conference_onConferencePeerNameChange(ToxWindow *self, Tox *m, uint32_t conferencenum, uint32_t peernum,
@ -763,17 +782,22 @@ static void conference_onConferencePeerNameChange(ToxWindow *self, Tox *m, uint3
const ConferencePeer *peer = peer_in_conference(conferencenum, peernum);
if (peer != NULL && peer->name_length > 0) {
if (peer != NULL) {
ChatContext *ctx = self->chatwin;
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
char tmp_event[TOXIC_MAX_NAME_LENGTH * 2 + 32];
snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", (const char *) name);
if (peer->name_length > 0) {
char log_event[TOXIC_MAX_NAME_LENGTH * 2 + 32];
line_info_add(self, true, peer->name, (const char *) name, NAME_CHANGE, 0, 0, " is now known as ");
write_to_log(tmp_event, peer->name, ctx->log, true);
line_info_add(self, timefrmt, peer->name, (const char *) name, NAME_CHANGE, 0, 0, " is now known as ");
snprintf(log_event, sizeof(log_event), "is now known as %s", (const char *) name);
write_to_log(log_event, peer->name, ctx->log, true);
// this is kind of a hack; peers always join a group with no name set and then set it after
} else if (timed_out(conferences[conferencenum].start_time, CONFERENCE_EVENT_WAIT)) {
const char *msg = "has joined the conference";
line_info_add(self, true, name, NULL, CONNECTION, 0, GREEN, msg);
write_to_log(msg, name, ctx->log, true);
}
}
conference_onConferenceNameListChange(self, m, conferencenum);
@ -789,7 +813,7 @@ static void send_conference_action(ToxWindow *self, ChatContext *ctx, Tox *m, ch
Tox_Err_Conference_Send_Message err;
if (!tox_conference_send_message(m, self->num, TOX_MESSAGE_TYPE_ACTION, (uint8_t *) action, strlen(action), &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send action (error %d)", err);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send action (error %d)", err);
}
}
@ -955,15 +979,15 @@ static bool conference_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
Tox_Err_Conference_Send_Message err;
if (!tox_conference_send_message(m, self->num, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) line, strlen(line), &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send message (error %d)", err);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send message (error %d)", err);
}
} else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to parse message.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * Failed to parse message.");
}
}
wclear(ctx->linewin);
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
wmove(self->window, y2, 0);
reset_buf(ctx);
}
@ -1049,15 +1073,16 @@ static void conference_onDraw(ToxWindow *self, Tox *m)
curs_set(1);
if (ctx->len > 0) {
mvwprintw(ctx->linewin, 1, 0, "%ls", &ctx->line[ctx->start]);
mvwprintw(ctx->linewin, 0, 0, "%ls", &ctx->line[ctx->start]);
}
wclear(ctx->sidebar);
mvwhline(self->window, y2 - CHATBOX_HEIGHT, 0, ACS_HLINE, x2);
if (self->show_peerlist) {
wattron(ctx->sidebar, COLOR_PAIR(BLUE));
mvwvline(ctx->sidebar, 0, 0, ACS_VLINE, y2 - CHATBOX_HEIGHT);
mvwaddch(ctx->sidebar, y2 - CHATBOX_HEIGHT, 0, ACS_BTEE);
wattroff(ctx->sidebar, COLOR_PAIR(BLUE));
pthread_mutex_lock(&Winthread.lock);
const uint32_t num_peers = chat->num_peers;
@ -1117,8 +1142,10 @@ static void conference_onDraw(ToxWindow *self, Tox *m)
wattroff(ctx->sidebar, A_BOLD);
++line;
wattron(ctx->sidebar, COLOR_PAIR(BLUE));
mvwaddch(ctx->sidebar, line, 0, ACS_LTEE);
mvwhline(ctx->sidebar, line, 1, ACS_HLINE, SIDEBAR_WIDTH - 1);
wattroff(ctx->sidebar, COLOR_PAIR(BLUE));
++line;
for (uint32_t i = 0;
@ -1135,7 +1162,9 @@ static void conference_onDraw(ToxWindow *self, Tox *m)
UNUSED_VAR(x);
int new_x = ctx->start ? x2 - 1 : MAX(0, wcswidth(ctx->line, ctx->pos));
wmove(self->window, y + 1, new_x);
wmove(self->window, y, new_x);
draw_window_bar(self);
wnoutrefresh(self->window);
@ -1155,9 +1184,10 @@ static void conference_onInit(ToxWindow *self, Tox *m)
ChatContext *ctx = self->chatwin;
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, x2 - SIDEBAR_WIDTH - 1, 0, 0);
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT, x2 - SIDEBAR_WIDTH - 1, 0, 0);
self->window_bar = subwin(self->window, WINDOW_BAR_HEIGHT, x2, y2 - (CHATBOX_HEIGHT + WINDOW_BAR_HEIGHT), 0);
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2 - CHATBOX_HEIGHT, 0);
ctx->sidebar = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, SIDEBAR_WIDTH, 0, x2 - SIDEBAR_WIDTH);
ctx->sidebar = subwin(self->window, y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT, SIDEBAR_WIDTH, 0, x2 - SIDEBAR_WIDTH);
ctx->hst = calloc(1, sizeof(struct history));
ctx->log = calloc(1, sizeof(struct chatlog));

View File

@ -26,10 +26,8 @@
#include "toxic.h"
#include "windows.h"
#define SIDEBAR_WIDTH 16
#define MAX_CONFERENCE_NUM (MAX_WINDOWS_NUM - 2)
#define CONFERENCE_EVENT_WAIT 3
#define CONFERENCE_MAX_TITLE_LENGTH TOX_MAX_NAME_LENGTH
#define SIDEBAR_WIDTH 16
typedef struct ConferencePeer {
bool active;

View File

@ -32,7 +32,7 @@
static void print_err(ToxWindow *self, const char *error_str)
{
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", error_str);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s", error_str);
}
void cmd_conference_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -56,7 +56,7 @@ void cmd_conference_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc,
}
title[tlen] = '\0';
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is set to: %s", title);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Title is set to: %s", title);
return;
}
@ -64,14 +64,14 @@ void cmd_conference_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc,
size_t len = strlen(argv[1]);
if (len >= sizeof(title)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set title: max length exceeded.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to set title: max length exceeded.");
return;
}
snprintf(title, sizeof(title), "%s", argv[1]);
if (!tox_conference_set_title(m, self->num, (uint8_t *) title, len, &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set title (error %d)", err);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to set title (error %d)", err);
return;
}
@ -79,16 +79,13 @@ void cmd_conference_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc,
conference_set_title(self, self->num, title, len);
char timefrmt[TIME_STR_SIZE];
char selfnick[TOX_MAX_NAME_LENGTH];
get_time_str(timefrmt, sizeof(timefrmt));
tox_self_get_name(m, (uint8_t *) selfnick);
size_t sn_len = tox_self_get_name_size(m);
selfnick[sn_len] = '\0';
line_info_add(self, timefrmt, selfnick, NULL, NAME_CHANGE, 0, 0, " set the conference title to: %s", title);
line_info_add(self, true, selfnick, NULL, NAME_CHANGE, 0, 0, " set the conference title to: %s", title);
char tmp_event[MAX_STR_SIZE + 20];
snprintf(tmp_event, sizeof(tmp_event), "set title to %s", title);
@ -142,14 +139,14 @@ void cmd_conference_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char
print_err(self, "Multiple matching peers (use /mute [public key] to disambiguate):");
for (uint32_t i = 0; i < n; ++i) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s: %s", entries[i]->pubkey_str, entries[i]->name);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s: %s", entries[i]->pubkey_str, entries[i]->name);
}
return;
}
if (conference_mute_peer(m, self->num, entries[0]->peernum)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Toggled audio mute status of %s", entries[0]->name);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Toggled audio mute status of %s", entries[0]->name);
} else {
print_err(self, "Peer is not on the call");
}
@ -162,7 +159,7 @@ void cmd_conference_sense(WINDOW *window, ToxWindow *self, Tox *m, int argc, cha
UNUSED_VAR(m);
if (argc == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Current VAD threshold: %.1f",
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Current VAD threshold: %.1f",
(double) conference_get_VAD_threshold(self->num));
return;
}
@ -181,7 +178,7 @@ void cmd_conference_sense(WINDOW *window, ToxWindow *self, Tox *m, int argc, cha
}
if (conference_set_VAD_threshold(self->num, value)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Set VAD threshold to %.1f", (double) value);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Set VAD threshold to %.1f", (double) value);
} else {
print_err(self, "Failed to set conference audio input sensitivity.");
}

View File

@ -271,5 +271,5 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
#endif
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid command.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid command.");
}

View File

@ -274,7 +274,7 @@ void close_file_transfer(ToxWindow *self, Tox *m, struct FileTransfer *ft, int C
box_notify(self, sound_type, NT_NOFOCUS | NT_WNDALERT_2, &self->active_box, self->name, "%s", message);
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", message);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s", message);
}
clear_file_transfer(ft);

View File

@ -397,11 +397,8 @@ static void friendlist_onMessage(ToxWindow *self, Tox *m, uint32_t num, Tox_Mess
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(prompt, timefrmt, nick, NULL, IN_MSG, 0, 0, "%s", str);
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, "* Warning: Too many windows are open.");
line_info_add(prompt, true, nick, NULL, IN_MSG, 0, 0, "%s", str);
line_info_add(prompt, false, NULL, NULL, SYS_MSG, 0, RED, "* Warning: Too many windows are open.");
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
}
@ -611,7 +608,7 @@ static void friendlist_onFileRecv(ToxWindow *self, Tox *m, uint32_t num, uint32_
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED,
line_info_add(prompt, false, NULL, NULL, SYS_MSG, 0, RED,
"* File transfer from %s failed: too many windows are open.", nick);
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
@ -642,7 +639,7 @@ static void friendlist_onConferenceInvite(ToxWindow *self, Tox *m, int32_t num,
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, num);
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED,
line_info_add(prompt, false, NULL, NULL, SYS_MSG, 0, RED,
"* Conference chat invite from %s failed: too many windows are open.", nick);
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
@ -854,7 +851,7 @@ static void unblock_friend(Tox *m, uint32_t bnum)
uint32_t friendnum = tox_friend_add_norequest(m, (uint8_t *) Blocked.list[bnum].pub_key, &err);
if (err != TOX_ERR_FRIEND_ADD_OK) {
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unblock friend (error %d)", err);
line_info_add(prompt, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to unblock friend (error %d)", err);
return;
}
@ -923,7 +920,7 @@ static bool friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
set_active_window_index(Friends.list[f].chatwin);
} else {
const char *msg = "* Warning: Too many windows are open.";
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, msg);
line_info_add(prompt, false, NULL, NULL, SYS_MSG, 0, RED, msg);
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
}
@ -1022,7 +1019,7 @@ static void blocklist_onDraw(ToxWindow *self, Tox *m, int y2, int x2)
wmove(self->window, y2 - 1, 1);
wattron(self->window, A_BOLD);
wprintw(self->window, "Key: ");
wprintw(self->window, "Public key: ");
wattroff(self->window, A_BOLD);
int i;
@ -1057,6 +1054,8 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
wprintw(self->window, "key for help\n\n");
wattroff(self->window, COLOR_PAIR(CYAN));
draw_window_bar(self);
if (blocklist_view == 1) {
blocklist_onDraw(self, m, y2, x2);
return;
@ -1098,9 +1097,9 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
int num_selected = Friends.num_selected;
pthread_mutex_unlock(&Winthread.lock);
bool f_selected = false;
if (is_active) {
bool f_selected = false;
if (i == num_selected) {
wattron(self->window, A_BOLD);
wprintw(self->window, " > ");
@ -1247,7 +1246,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
wmove(self->window, y2 - 1, 1);
wattron(self->window, A_BOLD);
wprintw(self->window, "Key: ");
wprintw(self->window, "Public key: ");
wattroff(self->window, A_BOLD);
int i;
@ -1265,6 +1264,21 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
}
}
void friendlist_onInit(ToxWindow *self, Tox *m)
{
UNUSED_VAR(m);
int x2;
int y2;
getmaxyx(self->window, y2, x2);
if (y2 <= 0 || x2 <= 0) {
exit_toxic_err("failed in friendlist_onInit", FATALERR_CURSES);
}
self->window_bar = subwin(self->window, WINDOW_BAR_HEIGHT, x2, y2 - 2, 0);
}
void disable_chatwin(uint32_t f_num)
{
Friends.list[f_num].chatwin = -1;
@ -1290,10 +1304,10 @@ static void friendlist_onAV(ToxWindow *self, ToxAV *av, uint32_t friend_number,
} else {
char nick[TOX_MAX_NAME_LENGTH];
get_nick_truncate(m, nick, Friends.list[friend_number].num);
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Audio action from: %s!", nick);
line_info_add(prompt, false, NULL, NULL, SYS_MSG, 0, 0, "Audio action from: %s!", nick);
const char *errmsg = "* Warning: Too many windows are open.";
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, errmsg);
line_info_add(prompt, false, NULL, NULL, SYS_MSG, 0, RED, errmsg);
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
}
@ -1343,6 +1357,7 @@ ToxWindow *new_friendlist(void)
ret->type = WINDOW_TYPE_FRIEND_LIST;
ret->onInit = &friendlist_onInit;
ret->onKey = &friendlist_onKey;
ret->onDraw = &friendlist_onDraw;
ret->onFriendAdded = &friendlist_onFriendAdded;

View File

@ -82,6 +82,7 @@ typedef struct {
} FriendsList;
ToxWindow *new_friendlist(void);
void friendlist_onInit(ToxWindow *self, Tox *m);
void disable_chatwin(uint32_t f_num);
int get_friendnum(uint8_t *name);
int load_blocklist(char *data);

View File

@ -49,19 +49,19 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
UNUSED_VAR(window);
if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Request ID required.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Request ID required.");
return;
}
long int req = strtol(argv[1], NULL, 10);
if ((req == 0 && strcmp(argv[1], "0")) || req < 0 || req >= MAX_FRIEND_REQUESTS) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
return;
}
if (!FrndRequests.request[req].active) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
return;
}
@ -69,10 +69,10 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
uint32_t friendnum = tox_friend_add_norequest(m, FrndRequests.request[req].key, &err);
if (err != TOX_ERR_FRIEND_ADD_OK) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to add friend (error %d\n)", err);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to add friend (error %d\n)", err);
return;
} else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Friend request accepted.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Friend request accepted.");
on_friend_added(m, friendnum, true);
}
@ -141,7 +141,7 @@ void cmd_add_helper(ToxWindow *self, Tox *m, const char *id_bin, const char *msg
break;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, errmsg);
}
void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -149,7 +149,7 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
UNUSED_VAR(window);
if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Tox ID or address required.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Tox ID or address required.");
return;
}
@ -158,7 +158,7 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
if (argc > 1) {
if (argv[2][0] != '\"') {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Message must be enclosed in quotes.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Message must be enclosed in quotes.");
return;
}
@ -192,7 +192,7 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
xx[2] = '\0';
if (sscanf(xx, "%02x", &x) != 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid Tox ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid Tox ID.");
return;
}
@ -200,7 +200,7 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
}
if (friend_is_blocked(id_bin)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Friend is in your block list.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Friend is in your block list.");
return;
}
@ -216,7 +216,7 @@ void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
if (argc != 1 || strlen(argv[1]) < 3) {
avatar_unset(m);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Avatar has been unset.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Avatar has been unset.");
return;
}
@ -225,7 +225,7 @@ void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
int len = strlen(path);
if (len <= 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid path.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid path.");
return;
}
@ -234,13 +234,13 @@ void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
get_file_name(filename, sizeof(filename), path);
if (avatar_set(m, path, len) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0,
"Failed to set avatar. Avatars must be in PNG format and may not exceed %d bytes.",
MAX_AVATAR_FILE_SIZE);
return;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Avatar set to '%s'", filename);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Avatar set to '%s'", filename);
}
void cmd_clear(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -258,7 +258,7 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
UNUSED_VAR(window);
if (argc != 3) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Require: <ip> <port> <key>");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Require: <ip> <port> <key>");
return;
}
@ -269,14 +269,14 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
long int port = strtol(port_str, NULL, 10);
if (port <= 0 || port > MAX_PORT_RANGE) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid port.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid port.");
return;
}
char key_binary[TOX_PUBLIC_KEY_SIZE * 2 + 1];
if (hex_string_to_bin(ascii_key, strlen(ascii_key), key_binary, TOX_PUBLIC_KEY_SIZE) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid key.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid key.");
return;
}
@ -286,15 +286,15 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
switch (err) {
case TOX_ERR_BOOTSTRAP_BAD_HOST:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed: Invalid IP.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed: Invalid IP.");
break;
case TOX_ERR_BOOTSTRAP_BAD_PORT:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed: Invalid port.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed: Invalid port.");
break;
case TOX_ERR_BOOTSTRAP_NULL:
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Bootstrap failed.");
break;
default:
@ -308,19 +308,19 @@ void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
UNUSED_VAR(m);
if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Request ID required.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Request ID required.");
return;
}
long int req = strtol(argv[1], NULL, 10);
if ((req == 0 && strcmp(argv[1], "0")) || req < 0 || req >= MAX_FRIEND_REQUESTS) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
return;
}
if (!FrndRequests.request[req].active) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "No pending friend request with that ID.");
return;
}
@ -345,12 +345,12 @@ void cmd_conference(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
UNUSED_VAR(window);
if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
return;
}
if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Please specify conference type: text | audio");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Please specify conference type: text | audio");
return;
}
@ -361,7 +361,7 @@ void cmd_conference(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
} else if (!strcasecmp(argv[1], "text")) {
type = TOX_CONFERENCE_TYPE_TEXT;
} else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Valid conference types are: text | audio");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Valid conference types are: text | audio");
return;
}
@ -373,7 +373,7 @@ void cmd_conference(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
conferencenum = tox_conference_new(m, &err);
if (err != TOX_ERR_CONFERENCE_NEW_OK) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Conference instance failed to initialize (error %d)", err);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Conference instance failed to initialize (error %d)", err);
return;
}
} else if (type == TOX_CONFERENCE_TYPE_AV) {
@ -381,18 +381,18 @@ void cmd_conference(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
conferencenum = toxav_add_av_groupchat(m, audio_conference_callback, NULL);
if (conferencenum == (uint32_t) -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Audio conference instance failed to initialize");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Audio conference instance failed to initialize");
return;
}
#else
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Audio support disabled by compile-time option.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Audio support disabled by compile-time option.");
return;
#endif
}
if (init_conference_win(m, conferencenum, type, NULL, 0) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Conference window failed to initialize.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Conference window failed to initialize.");
tox_conference_delete(m, conferencenum, NULL);
return;
}
@ -401,13 +401,13 @@ void cmd_conference(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
if (type == TOX_CONFERENCE_TYPE_AV) {
if (!init_conference_audio_input(m, conferencenum)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Audio capture failed; use \"/audio on\" to try again.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Audio capture failed; use \"/audio on\" to try again.");
}
}
#endif
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Conference [%d] created.", conferencenum);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Conference [%d] created.", conferencenum);
}
void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -424,7 +424,7 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
msg = "Logging for this window is OFF; type \"/log on\" to enable.";
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, msg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, msg);
return;
}
@ -432,7 +432,7 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
if (!strcmp(swch, "1") || !strcmp(swch, "on")) {
msg = log_enable(log) == 0 ? "Logging enabled." : "Warning: Failed to enable log.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, msg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, msg);
return;
} else if (!strcmp(swch, "0") || !strcmp(swch, "off")) {
if (self->type == WINDOW_TYPE_CHAT) {
@ -442,12 +442,12 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
log_disable(log);
msg = "Logging disabled.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, msg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, msg);
return;
}
msg = "Invalid option. Use \"/log on\" and \"/log off\" to toggle logging.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, msg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, msg);
}
void cmd_myid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -461,11 +461,11 @@ void cmd_myid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
tox_self_get_address(m, (uint8_t *) bin_id);
if (bin_id_to_string(bin_id, sizeof(bin_id), id_string, sizeof(id_string)) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to print ID.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to print ID.");
return;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", id_string);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s", id_string);
}
#ifdef QRCODE
@ -478,7 +478,7 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
tox_self_get_address(m, (uint8_t *) bin_id);
if (bin_id_to_string(bin_id, sizeof(bin_id), id_string, sizeof(id_string)) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code.");
return;
}
@ -491,7 +491,7 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
char *dir = malloc(data_file_len + 1);
if (dir == NULL) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code: Out of memory.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code: Out of memory.");
return;
}
@ -500,7 +500,7 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
#ifdef QRPNG
if (argc == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Required 'txt' or 'png'");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Required 'txt' or 'png'");
free(dir);
return;
} else if (!strcmp(argv[1], "txt")) {
@ -510,7 +510,7 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
char *qr_path = malloc(qr_path_buf_size);
if (qr_path == NULL) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code: Out of memory");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code: Out of memory");
free(dir);
return;
}
@ -518,13 +518,13 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
snprintf(qr_path, qr_path_buf_size, "%s%s%s", dir, nick, QRCODE_FILENAME_EXT);
if (ID_to_QRcode_txt(id_string, qr_path) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code.");
free(dir);
free(qr_path);
return;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "QR code has been printed to the file '%s'", qr_path);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "QR code has been printed to the file '%s'", qr_path);
free(qr_path);
@ -534,7 +534,7 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
char *qr_path = malloc(qr_path_buf_size);
if (qr_path == NULL) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code: Out of memory");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code: Out of memory");
free(dir);
return;
}
@ -542,18 +542,18 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
snprintf(qr_path, qr_path_buf_size, "%s%s%s", dir, nick, QRCODE_FILENAME_EXT_PNG);
if (ID_to_QRcode_png(id_string, qr_path) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to create QR code.");
free(dir);
free(qr_path);
return;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "QR code has been printed to the file '%s'", qr_path);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "QR code has been printed to the file '%s'", qr_path);
free(qr_path);
} else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Unknown option '%s' -- Required 'txt' or 'png'", argv[1]);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Unknown option '%s' -- Required 'txt' or 'png'", argv[1]);
free(dir);
return;
}
@ -569,7 +569,7 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
UNUSED_VAR(window);
if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Input required.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Input required.");
return;
}
@ -578,7 +578,7 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
size_t len = strlen(nick);
if (!valid_nick(nick)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid name.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid name.");
return;
}
@ -596,7 +596,7 @@ void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
UNUSED_VAR(window);
if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Input required.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Input required.");
return;
}
@ -611,7 +611,7 @@ void cmd_nospam(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
nospam = strtol(argv[1], NULL, 16);
if ((nospam == 0 && strcmp(argv[1], "0")) || nospam < 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid nospam value.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid nospam value.");
return;
}
}
@ -619,12 +619,12 @@ void cmd_nospam(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
uint32_t old_nospam = tox_self_get_nospam(m);
tox_self_set_nospam(m, (uint32_t) nospam);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Your new Tox ID is:");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Your new Tox ID is:");
cmd_myid(window, self, m, 0, NULL);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0,
"Any services that relied on your old ID will need to be updated manually.");
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "If you ever want your old Tox ID back, type '/nospam %X'",
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "If you ever want your old Tox ID back, type '/nospam %X'",
old_nospam);
}
@ -656,7 +656,7 @@ void cmd_requests(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
UNUSED_VAR(argv);
if (FrndRequests.num_requests == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend requests.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "No pending friend requests.");
return;
}
@ -676,11 +676,11 @@ void cmd_requests(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
strcat(id, d);
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%d : %s", i, id);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", FrndRequests.request[i].msg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%d : %s", i, id);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s", FrndRequests.request[i].msg);
if (++count < FrndRequests.num_requests) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "");
}
}
}
@ -695,7 +695,7 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
if (argc < 1) {
errmsg = "Require a status. Statuses are: online, busy and away.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, errmsg);
goto finish;
}
@ -710,13 +710,13 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
status = TOX_USER_STATUS_BUSY;
} else {
errmsg = "Invalid status. Valid statuses are: online, busy and away.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, errmsg);
goto finish;
}
tox_self_set_status(m, status);
prompt_update_status(prompt, status);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Your status has been changed to %s.", status_str);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Your status has been changed to %s.", status_str);
finish:

View File

@ -54,7 +54,7 @@ void line_info_reset_start(ToxWindow *self, struct history *hst)
{
struct line_info *line = hst->line_end;
if (line->prev == NULL) {
if (line == NULL || line->prev == NULL) {
return;
}
@ -63,10 +63,10 @@ void line_info_reset_start(ToxWindow *self, struct history *hst)
getmaxyx(self->window, y2, x2);
UNUSED_VAR(x2);
int top_offst = (self->type == WINDOW_TYPE_CHAT) || (self->type == WINDOW_TYPE_PROMPT) ? 2 : 0;
int max_y = y2 - CHATBOX_HEIGHT - top_offst;
int top_offst = (self->type == WINDOW_TYPE_CHAT) || (self->type == WINDOW_TYPE_PROMPT) ? TOP_BAR_HEIGHT : 0;
int max_y = y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT - top_offst;
int curlines = 0;
uint16_t curlines = 0;
do {
curlines += line->format_lines;
@ -74,6 +74,8 @@ void line_info_reset_start(ToxWindow *self, struct history *hst)
} while (line->prev && curlines + line->format_lines <= max_y);
hst->line_start = line;
self->scroll_pause = false;
}
void line_info_cleanup(struct history *hst)
@ -131,20 +133,32 @@ static struct line_info *line_info_ret_queue(struct history *hst)
/* Prints a maximum of `n` chars from `s` to `win`.
*
* Return true if the string contains a newline or tab byte.
* Return 1 if the string contains a newline byte.
* Return 0 if string does not contain a newline byte.
* Return -1 if printing was aborted.
*/
static bool print_n_chars(WINDOW *win, const char *s, size_t n)
static int print_n_chars(WINDOW *win, const char *s, size_t n, int max_y)
{
bool newline = false;
char ch;
for (size_t i = 0; i < n && (ch = s[i]); ++i) {
if (win) {
wprintw(win, "%c", ch);
}
if (ch == '\n') {
newline = true;
int x;
int y;
UNUSED_VAR(x);
getyx(win, y, x);
// make sure cursor will wrap correctly after newline to prevent display bugs
if (y + 1 >= max_y) {
return -1;
}
}
if (win) {
wprintw(win, "%c", ch);
}
}
@ -201,24 +215,42 @@ static unsigned int newline_count(const char *s)
*
* If `win` is null nothing will be printed to the window. This is useful to set the
* `format_lines` field on initialization.
*
* Return 0 on success.
* Return -1 if not all characters in line's message were printed to screen.
*/
static void print_wrap(WINDOW *win, struct line_info *line, int max_x)
static int print_wrap(WINDOW *win, struct line_info *line, int max_x, int max_y)
{
int x;
int y;
UNUSED_VAR(y);
const char *msg = line->msg;
uint16_t length = line->msg_len;
uint16_t lines = 0;
const int x_start = line->len - line->msg_len - 1; // manually keep track of x position because ncurses sucks
int x_limit = max_x - x_start;
if (x_limit <= 0) {
if (x_limit <= 1) {
fprintf(stderr, "Warning: x_limit <= 0 in print_wrap(): %d\n", x_limit);
return;
return -1;
}
while (msg) {
getyx(win, y, x);
// next line would print past window limit so we abort; we don't want to update format_lines
if (x > x_start) {
return -1;
}
if (length < x_limit) {
if (print_n_chars(win, msg, length)) {
int p_ret = print_n_chars(win, msg, length, max_y);
if (p_ret == 1) {
lines += newline_count(msg);
} else if (p_ret == -1) {
return -1;
}
++lines;
@ -228,8 +260,11 @@ static void print_wrap(WINDOW *win, struct line_info *line, int max_x)
int newline_idx = newline_index(msg, x_limit - 1);
if (newline_idx >= 0) {
print_n_chars(win, msg, newline_idx + 1);
msg += newline_idx + 1;
if (print_n_chars(win, msg, newline_idx + 1, max_y) == -1) {
return -1;
}
msg += (newline_idx + 1);
length -= (newline_idx + 1);
x_limit = max_x; // if we find a newline we stop adding column padding for rest of message
++lines;
@ -239,12 +274,21 @@ static void print_wrap(WINDOW *win, struct line_info *line, int max_x)
int space_idx = rspace_index(msg, x_limit - 1);
if (space_idx >= 1) {
print_n_chars(win, msg, space_idx);
if (print_n_chars(win, msg, space_idx, max_y) == -1) {
return -1;
}
msg += space_idx + 1;
length -= (space_idx + 1);
waddch(win, '\n');
if (win) {
waddch(win, '\n');
}
} else {
print_n_chars(win, msg, x_limit);
if (print_n_chars(win, msg, x_limit, max_y) == -1) {
return -1;
}
msg += x_limit;
length -= x_limit;
}
@ -260,10 +304,6 @@ static void print_wrap(WINDOW *win, struct line_info *line, int max_x)
}
if (win && line->noread_flag) {
int x;
int y;
UNUSED_VAR(y);
getyx(win, y, x);
if (x >= max_x - 1 || x == x_start) {
@ -276,17 +316,22 @@ static void print_wrap(WINDOW *win, struct line_info *line, int max_x)
}
line->format_lines = lines;
return 0;
}
static void line_info_init_line(WINDOW *win, struct line_info *line)
static void line_info_init_line(ToxWindow *self, struct line_info *line)
{
int max_y;
int max_x;
UNUSED_VAR(max_y);
int y2;
int x2;
UNUSED_VAR(y2);
getmaxyx(win, max_y, max_x);
getmaxyx(self->window, y2, x2);
print_wrap(NULL, line, max_x);
const int max_y = y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT;
const int max_x = self->show_peerlist ? x2 - 1 - SIDEBAR_WIDTH : x2;
print_wrap(NULL, line, max_x, max_y);
}
/* creates new line_info line and puts it in the queue.
@ -294,7 +339,7 @@ static void line_info_init_line(WINDOW *win, struct line_info *line)
* Returns the id of the new line.
* Returns -1 on failure.
*/
int line_info_add(ToxWindow *self, const char *timestr, const char *name1, const char *name2, uint8_t type,
int line_info_add(ToxWindow *self, bool show_timestamp, const char *name1, const char *name2, LINE_TYPE type,
uint8_t bold, uint8_t colour, const char *msg, ...)
{
if (!self) {
@ -329,33 +374,33 @@ int line_info_add(ToxWindow *self, const char *timestr, const char *name1, const
/* fallthrough */
case OUT_ACTION:
len += strlen(user_settings->line_normal) + 2;
len += strlen(user_settings->line_normal) + 2; // two spaces
break;
case IN_MSG:
/* fallthrough */
case OUT_MSG:
len += strlen(user_settings->line_normal) + 3;
len += strlen(user_settings->line_normal) + 3; // two spaces and a ':' char
break;
case CONNECTION:
len += strlen(user_settings->line_join) + 2;
len += strlen(user_settings->line_join) + 2; // two spaces
break;
case DISCONNECTION:
len += strlen(user_settings->line_quit) + 2;
len += strlen(user_settings->line_quit) + 2; // two spaces
break;
case SYS_MSG:
break;
case NAME_CHANGE:
len += strlen(user_settings->line_alert) + 1;
len += strlen(user_settings->line_alert) + 2; // two spaces
break;
case PROMPT:
++len;
len += 2; // '$' char and a space
break;
default:
@ -371,8 +416,8 @@ int line_info_add(ToxWindow *self, const char *timestr, const char *name1, const
len += msg_len;
}
if (timestr) {
snprintf(new_line->timestr, sizeof(new_line->timestr), "%s", timestr);
if (show_timestamp) {
get_time_str(new_line->timestr, sizeof(new_line->timestr));
len += strlen(new_line->timestr) + 1;
}
@ -395,7 +440,7 @@ int line_info_add(ToxWindow *self, const char *timestr, const char *name1, const
new_line->noread_flag = false;
new_line->timestamp = get_unix_time();
line_info_init_line(self->chatwin->history, new_line);
line_info_init_line(self, new_line);
hst->queue[hst->queue_size++] = new_line;
@ -421,29 +466,8 @@ static void line_info_check_queue(ToxWindow *self)
hst->line_end = line;
hst->line_end->id = line->id;
int y;
int y2;
int x;
int x2;
getmaxyx(self->window, y2, x2);
getyx(self->chatwin->history, y, x);
UNUSED_VAR(x);
if (x2 <= SIDEBAR_WIDTH) {
return;
}
int lines = line->format_lines;
int max_y = y2 - CHATBOX_HEIGHT;
/* move line_start forward proportionate to the number of new lines */
if (y + lines > max_y) {
while (lines > 0 && hst->line_start->next) {
lines -= hst->line_start->next->format_lines;
hst->line_start = hst->line_start->next;
++hst->start_id;
}
if (!self->scroll_pause) {
line_info_reset_start(self, hst);
}
}
@ -479,16 +503,31 @@ void line_info_print(ToxWindow *self)
if (self->type == WINDOW_TYPE_CONFERENCE) {
wmove(win, 0, 0);
} else {
wmove(win, 2, 0);
wmove(win, TOP_BAR_HEIGHT, 0);
}
struct line_info *line = hst->line_start->next;
if (!line) {
return;
}
const int max_y = y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT;
const int max_x = self->show_peerlist ? x2 - 1 - SIDEBAR_WIDTH : x2;
uint16_t numlines = line->format_lines;
int print_ret = 0;
int numlines = 0;
while (line && numlines++ <= max_y && print_ret == 0) {
int y;
int x;
UNUSED_VAR(y);
getyx(win, y, x);
if (x > 0) { // Prevents us from printing off the screen
break;
}
while (line && numlines++ <= y2) {
uint8_t type = line->type;
switch (type) {
@ -526,7 +565,7 @@ void line_info_print(ToxWindow *self)
wattron(win, COLOR_PAIR(RED));
}
print_wrap(win, line, max_x);
print_ret = print_wrap(win, line, max_x, max_y);
if (line->msg[0] == '>') {
wattroff(win, COLOR_PAIR(GREEN));
@ -556,7 +595,7 @@ void line_info_print(ToxWindow *self)
wattron(win, COLOR_PAIR(YELLOW));
wprintw(win, "%s %s ", user_settings->line_normal, line->name1);
print_wrap(win, line, max_x);
print_ret = print_wrap(win, line, max_x, max_y);
wattroff(win, COLOR_PAIR(YELLOW));
if (type == OUT_ACTION && !line->read_flag) {
@ -583,7 +622,7 @@ void line_info_print(ToxWindow *self)
wattron(win, COLOR_PAIR(line->colour));
}
print_wrap(win, line, max_x);
print_ret = print_wrap(win, line, max_x, max_y);
waddch(win, '\n');
if (line->bold) {
@ -602,7 +641,7 @@ void line_info_print(ToxWindow *self)
wattroff(win, COLOR_PAIR(GREEN));
if (line->msg[0]) {
print_wrap(win, line, max_x);
print_ret = print_wrap(win, line, max_x, max_y);
}
waddch(win, '\n');
@ -620,7 +659,7 @@ void line_info_print(ToxWindow *self)
wprintw(win, "%s ", line->name1);
wattroff(win, A_BOLD);
print_wrap(win, line, max_x);
print_ret = print_wrap(win, line, max_x, max_y);
waddch(win, '\n');
wattroff(win, COLOR_PAIR(line->colour));
@ -639,7 +678,7 @@ void line_info_print(ToxWindow *self)
wprintw(win, "%s ", line->name1);
wattroff(win, A_BOLD);
print_wrap(win, line, max_x);
print_ret = print_wrap(win, line, max_x, max_y);
waddch(win, '\n');
wattroff(win, COLOR_PAIR(line->colour));
@ -657,7 +696,7 @@ void line_info_print(ToxWindow *self)
wprintw(win, "%s", line->name1);
wattroff(win, A_BOLD);
print_wrap(win, line, max_x);
print_ret = print_wrap(win, line, max_x, max_y);
wattron(win, A_BOLD);
wprintw(win, "%s\n", line->name2);
@ -676,6 +715,38 @@ void line_info_print(ToxWindow *self)
}
}
/*
* Return true if all lines starting from `line` can fit on the screen.
*/
static bool line_info_screen_fit(ToxWindow *self, struct line_info *line)
{
if (!line) {
return true;
}
int x2;
int y2;
getmaxyx(self->chatwin->history, y2, x2);
UNUSED_VAR(x2);
const int top_offset = (self->type == WINDOW_TYPE_CHAT) || (self->type == WINDOW_TYPE_PROMPT) ? TOP_BAR_HEIGHT : 0;
const int max_y = y2 - top_offset;
uint16_t lines = line->format_lines;
while (line) {
if (lines > max_y) {
return false;
}
lines += line->format_lines;
line = line->next;
}
return true;
}
/* puts msg in specified line_info msg buffer */
void line_info_set(ToxWindow *self, uint32_t id, char *msg)
{
@ -694,49 +765,74 @@ void line_info_set(ToxWindow *self, uint32_t id, char *msg)
}
}
static void line_info_scroll_up(struct history *hst)
static void line_info_scroll_up(ToxWindow *self, struct history *hst)
{
if (hst->line_start->prev) {
hst->line_start = hst->line_start->prev;
} else {
sound_notify(NULL, notif_error, NT_ALWAYS, NULL);
self->scroll_pause = true;
}
}
static void line_info_scroll_down(struct history *hst)
static void line_info_scroll_down(ToxWindow *self, struct history *hst)
{
if (hst->line_start->next) {
hst->line_start = hst->line_start->next;
struct line_info *next = hst->line_start->next;
if (next && self->scroll_pause) {
if (line_info_screen_fit(self, next->next)) {
line_info_reset_start(self, hst);
} else {
hst->line_start = next;
}
} else {
sound_notify(NULL, notif_error, NT_ALWAYS, NULL);
line_info_reset_start(self, hst);
}
}
static void line_info_page_up(ToxWindow *self, struct history *hst)
{
int x2, y2;
int x2;
int y2;
getmaxyx(self->window, y2, x2);
UNUSED_VAR(x2);
size_t jump_dist = y2 / 2;
const int top_offset = (self->type == WINDOW_TYPE_CHAT) || (self->type == WINDOW_TYPE_PROMPT) ? TOP_BAR_HEIGHT : 0;
const int max_y = y2 - top_offset;
size_t jump_dist = max_y / 2;
for (size_t i = 0; i < jump_dist && hst->line_start->prev; ++i) {
hst->line_start = hst->line_start->prev;
}
self->scroll_pause = true;
}
static void line_info_page_down(ToxWindow *self, struct history *hst)
{
int x2, y2;
getmaxyx(self->window, y2, x2);
if (!self->scroll_pause) {
return;
}
int x2;
int y2;
getmaxyx(self->chatwin->history, y2, x2);
UNUSED_VAR(x2);
size_t jump_dist = y2 / 2;
const int top_offset = (self->type == WINDOW_TYPE_CHAT) || (self->type == WINDOW_TYPE_PROMPT) ? TOP_BAR_HEIGHT : 0;
const int max_y = y2 - top_offset;
size_t jump_dist = max_y / 2;
for (size_t i = 0; i < jump_dist && hst->line_start->next; ++i) {
hst->line_start = hst->line_start->next;
struct line_info *next = hst->line_start->next;
for (size_t i = 0; i < jump_dist && next; ++i) {
if (line_info_screen_fit(self, next->next)) {
line_info_reset_start(self, hst);
break;
}
hst->line_start = next;
next = hst->line_start->next;
}
}
@ -750,9 +846,9 @@ bool line_info_onKey(ToxWindow *self, wint_t key)
} else if (key == user_settings->key_half_page_down) {
line_info_page_down(self, hst);
} else if (key == user_settings->key_scroll_line_up) {
line_info_scroll_up(hst);
line_info_scroll_up(self, hst);
} else if (key == user_settings->key_scroll_line_down) {
line_info_scroll_down(hst);
line_info_scroll_down(self, hst);
} else if (key == user_settings->key_page_bottom) {
line_info_reset_start(self, hst);
} else {

View File

@ -31,7 +31,7 @@
#define MAX_LINE_INFO_QUEUE 1024
#define MAX_LINE_INFO_MSG_SIZE (MAX_STR_SIZE + TOXIC_MAX_NAME_LENGTH + 32) /* needs extra room for log loading */
typedef enum {
typedef enum LINE_TYPE {
SYS_MSG,
IN_MSG,
OUT_MSG,
@ -81,7 +81,7 @@ struct history {
* Returns the id of the new line.
* Returns -1 on failure.
*/
int line_info_add(ToxWindow *self, const char *timestr, const char *name1, const char *name2, uint8_t type,
int line_info_add(ToxWindow *self, bool show_timestamp, const char *name1, const char *name2, LINE_TYPE type,
uint8_t bold, uint8_t colour, const char *msg, ...);
/* Prints a section of history starting at line_start */

View File

@ -302,11 +302,11 @@ int load_chat_history(ToxWindow *self, struct chatlog *log)
}
while (line != NULL && count--) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", line);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s", line);
line = strtok_r(NULL, "\n", &tmp);
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, YELLOW, "---");
free(buf);
@ -358,7 +358,9 @@ int rename_logfile(const char *src, const char *dest, const char *selfkey, const
}
if (file_exists(newpath)) {
remove(oldpath);
if (remove(oldpath) != 0) {
fprintf(stderr, "Warning: remove() failed to remove log path `%s`\n", oldpath);
}
} else if (rename(oldpath, newpath) != 0) {
goto on_error;
}

View File

@ -71,16 +71,19 @@ int timed_out(time_t timestamp, time_t timeout)
return timestamp + timeout <= get_unix_time();
}
/* Sleeps the caller's thread for `usec` microseconds */
/* Attempts to sleep the caller's thread for `usec` microseconds */
void sleep_thread(long int usec)
{
struct timespec req;
struct timespec rem;
req.tv_sec = 0;
req.tv_nsec = usec * 1000L;
if (nanosleep(&req, NULL) == -1) {
fprintf(stderr, "nanosleep() returned -1\n");
if (nanosleep(&req, &rem) == -1) {
if (nanosleep(&rem, NULL) == -1) {
fprintf(stderr, "nanosleep() returned -1\n");
}
}
}
@ -93,11 +96,16 @@ struct tm *get_time(void)
return timeinfo;
}
/*Puts the current time in buf in the format of [HH:mm:ss] */
void get_time_str(char *buf, int bufsize)
/* Puts the current time in buf in the format of specified by the config */
void get_time_str(char *buf, size_t bufsize)
{
if (buf == NULL || bufsize == 0) {
return;
}
*buf = 0;
if (user_settings->timestamps == TIMESTAMPS_OFF) {
buf[0] = '\0';
return;
}

View File

@ -81,8 +81,8 @@ int bin_pubkey_to_string(const uint8_t *bin_pubkey, size_t bin_pubkey_size, char
/* get the current unix time (not thread safe) */
time_t get_unix_time(void);
/* Puts the current time in buf in the format of [HH:mm:ss] (not thread safe) */
void get_time_str(char *buf, int bufsize);
/* Puts the current time in buf in the format of specified by the config */
void get_time_str(char *buf, size_t bufsize);
/* Converts seconds to string in format HH:mm:ss; truncates hours and minutes when necessary */
void get_elapsed_time_str(char *buf, int bufsize, time_t secs);
@ -108,7 +108,7 @@ int mbs_to_wcs_buf(wchar_t *buf, const char *string, size_t n);
/* Returns 1 if connection has timed out, 0 otherwise */
int timed_out(time_t timestamp, time_t timeout);
/* Sleeps the caller's thread for `usec` microseconds */
/* Attempts to sleep the caller's thread for `usec` microseconds */
void sleep_thread(long int usec);
/* Colours the window tab according to type. Beeps if is_beep is true */

View File

@ -80,7 +80,7 @@ static int lookup_error(ToxWindow *self, const char *errmsg, ...)
va_end(args);
pthread_mutex_lock(&Winthread.lock);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "name lookup failed: %s", frmt_msg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "name lookup failed: %s", frmt_msg);
pthread_mutex_unlock(&Winthread.lock);
return -1;
@ -365,12 +365,12 @@ on_exit:
void name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *message)
{
if (t_data.disabled) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "name lookups are disabled.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "name lookups are disabled.");
return;
}
if (t_data.busy) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Please wait for previous name lookup to finish.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Please wait for previous name lookup to finish.");
return;
}
@ -382,20 +382,20 @@ void name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr,
t_data.busy = true;
if (pthread_attr_init(&lookup_thread.attr) != 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread attr failed to init");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread attr failed to init");
clear_thread_data();
return;
}
if (pthread_attr_setdetachstate(&lookup_thread.attr, PTHREAD_CREATE_DETACHED) != 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread attr failed to set");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread attr failed to set");
pthread_attr_destroy(&lookup_thread.attr);
clear_thread_data();
return;
}
if (pthread_create(&lookup_thread.tid, &lookup_thread.attr, lookup_thread_func, NULL) != 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread failed to init");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread failed to init");
pthread_attr_destroy(&lookup_thread.attr);
clear_thread_data();
return;

View File

@ -144,7 +144,7 @@ void prompt_update_statusmessage(ToxWindow *prompt, Tox *m, const char *statusms
tox_self_set_status_message(m, (const uint8_t *) statusmsg, len, &err);
if (err != TOX_ERR_SET_INFO_OK) {
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set note (error %d)\n", err);
line_info_add(prompt, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to set note (error %d)\n", err);
}
}
@ -284,15 +284,15 @@ static bool prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
char line[MAX_STR_SIZE];
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Failed to parse message.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * Failed to parse message.");
} else {
line_info_add(self, NULL, NULL, NULL, PROMPT, 0, 0, "%s", line);
line_info_add(self, false, NULL, NULL, PROMPT, 0, 0, "%s", line);
execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE);
}
}
wclear(ctx->linewin);
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
wmove(self->window, y2, 0);
reset_buf(ctx);
}
@ -301,7 +301,8 @@ static bool prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
static void prompt_onDraw(ToxWindow *self, Tox *m)
{
int x2, y2;
int x2;
int y2;
getmaxyx(self->window, y2, x2);
if (y2 <= 0 || x2 <= 0) {
@ -316,64 +317,88 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
wclear(ctx->linewin);
curs_set(1);
if (ctx->len > 0) {
mvwprintw(ctx->linewin, 1, 0, "%ls", &ctx->line[ctx->start]);
mvwprintw(ctx->linewin, 0, 0, "%ls", &ctx->line[ctx->start]);
}
mvwhline(ctx->linewin, 0, ctx->len, ' ', x2 - ctx->len);
curs_set(1);
StatusBar *statusbar = self->stb;
mvwhline(statusbar->topline, 1, 0, ACS_HLINE, x2);
wmove(statusbar->topline, 0, 0);
pthread_mutex_lock(&Winthread.lock);
Tox_Connection connection = statusbar->connection;
Tox_User_Status status = statusbar->status;
pthread_mutex_unlock(&Winthread.lock);
if (connection != TOX_CONNECTION_NONE) {
int colour = MAGENTA;
const char *status_text = "ERROR";
pthread_mutex_lock(&Winthread.lock);
Tox_User_Status status = statusbar->status;
pthread_mutex_unlock(&Winthread.lock);
switch (status) {
case TOX_USER_STATUS_NONE:
status_text = "Online";
colour = GREEN;
colour = STATUS_ONLINE;
break;
case TOX_USER_STATUS_AWAY:
status_text = "Away";
colour = YELLOW;
colour = STATUS_AWAY;
break;
case TOX_USER_STATUS_BUSY:
status_text = "Busy";
colour = RED;
colour = STATUS_BUSY;
break;
}
wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
wprintw(statusbar->topline, " [%s]", status_text);
wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, " [");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wattron(statusbar->topline, A_BOLD | COLOR_PAIR(colour));
wprintw(statusbar->topline, "%s", status_text);
wattroff(statusbar->topline, A_BOLD | COLOR_PAIR(colour));
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, "]");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wattron(statusbar->topline, COLOR_PAIR(BAR_TEXT));
wattron(statusbar->topline, A_BOLD);
pthread_mutex_lock(&Winthread.lock);
wprintw(statusbar->topline, " %s", statusbar->nick);
pthread_mutex_unlock(&Winthread.lock);
wattroff(statusbar->topline, A_BOLD);
} else {
wprintw(statusbar->topline, " [Offline]");
wattron(statusbar->topline, A_BOLD);
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, " [");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wattron(statusbar->topline, COLOR_PAIR(BAR_TEXT));
wprintw(statusbar->topline, "Offline");
wattroff(statusbar->topline, COLOR_PAIR(BAR_TEXT));
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, "]");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wattron(statusbar->topline, COLOR_PAIR(BAR_TEXT));
pthread_mutex_lock(&Winthread.lock);
wprintw(statusbar->topline, " %s", statusbar->nick);
pthread_mutex_unlock(&Winthread.lock);
wattroff(statusbar->topline, A_BOLD);
}
int s_y;
int s_x;
getyx(statusbar->topline, s_y, s_x);
mvwhline(statusbar->topline, s_y, s_x, ' ', x2 - s_x);
wattroff(statusbar->topline, COLOR_PAIR(BAR_TEXT));
/* Reset statusbar->statusmsg on window resize */
if (x2 != self->x) {
char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH];
@ -401,20 +426,27 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
}
if (statusbar->statusmsg[0]) {
wprintw(statusbar->topline, " : %s", statusbar->statusmsg);
wattron(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wprintw(statusbar->topline, " | ");
wattroff(statusbar->topline, COLOR_PAIR(BAR_ACCENT));
wattron(statusbar->topline, COLOR_PAIR(BAR_TEXT));
wprintw(statusbar->topline, "%s", statusbar->statusmsg);
wattroff(statusbar->topline, COLOR_PAIR(BAR_TEXT));
}
pthread_mutex_unlock(&Winthread.lock);
mvwhline(self->window, y2 - CHATBOX_HEIGHT, 0, ACS_HLINE, x2);
int y, x;
int y;
int x;
getyx(self->window, y, x);
UNUSED_VAR(x);
int new_x = ctx->start ? x2 - 1 : MAX(0, wcswidth(ctx->line, ctx->pos));
wmove(self->window, y + 1, new_x);
wmove(self->window, y, new_x);
draw_window_bar(self);
wnoutrefresh(self->window);
@ -434,8 +466,6 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, uint32_t friendnu
snprintf(nick, sizeof(nick), "%s", UNKNOWN_NAME);
}
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
const char *msg;
if (user_settings->show_connection_msg == SHOW_WELCOME_MSG_OFF) {
@ -444,7 +474,7 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, uint32_t friendnu
if (connection_status != TOX_CONNECTION_NONE && Friends.list[friendnum].connection_status == TOX_CONNECTION_NONE) {
msg = "has come online";
line_info_add(self, timefrmt, nick, NULL, CONNECTION, 0, GREEN, msg);
line_info_add(self, true, nick, NULL, CONNECTION, 0, GREEN, msg);
write_to_log(msg, nick, ctx->log, true);
if (self->active_box != -1) {
@ -456,7 +486,7 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, uint32_t friendnu
}
} else if (connection_status == TOX_CONNECTION_NONE) {
msg = "has gone offline";
line_info_add(self, timefrmt, nick, NULL, DISCONNECTION, 0, RED, msg);
line_info_add(self, true, nick, NULL, DISCONNECTION, 0, RED, msg);
write_to_log(msg, nick, ctx->log, true);
if (self->active_box != -1) {
@ -476,21 +506,18 @@ static void prompt_onFriendRequest(ToxWindow *self, Tox *m, const char *key, con
ChatContext *ctx = self->chatwin;
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 0, 0, "Friend request with the message '%s'", data);
line_info_add(self, true, NULL, NULL, SYS_MSG, 0, 0, "Friend request with the message '%s'", data);
write_to_log("Friend request with the message '%s'", "", ctx->log, true);
int n = add_friend_request(key, data);
if (n == -1) {
const char *errmsg = "Friend request queue is full. Discarding request.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, errmsg);
return;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/accept %d\" or \"/decline %d\"", n, n);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Type \"/accept %d\" or \"/decline %d\"", n, n);
sound_notify(self, generic_message, NT_WNDALERT_1 | NT_NOTIFWND, NULL);
}
@ -535,23 +562,23 @@ void prompt_init_statusbar(ToxWindow *self, Tox *m, bool first_time_run)
prompt_update_nick(prompt, nick);
/* Init statusbar subwindow */
statusbar->topline = subwin(self->window, 2, x2, 0, 0);
statusbar->topline = subwin(self->window, TOP_BAR_HEIGHT, x2, 0, 0);
}
static void print_welcome_msg(ToxWindow *self)
{
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, " _____ _____ _____ ____ ");
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, " |_ _/ _ \\ \\/ /_ _/ ___|");
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, " | || | | \\ / | | | ");
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, " | || |_| / \\ | | |___ ");
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, " |_| \\___/_/\\_\\___\\____| v." TOXICVER);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
line_info_add(self, false, NULL, NULL, SYS_MSG, 1, BLUE, " _____ _____ _____ ____ ");
line_info_add(self, false, NULL, NULL, SYS_MSG, 1, BLUE, " |_ _/ _ \\ \\/ /_ _/ ___|");
line_info_add(self, false, NULL, NULL, SYS_MSG, 1, BLUE, " | || | | \\ / | | | ");
line_info_add(self, false, NULL, NULL, SYS_MSG, 1, BLUE, " | || |_| / \\ | | |___ ");
line_info_add(self, false, NULL, NULL, SYS_MSG, 1, BLUE, " |_| \\___/_/\\_\\___\\____| v." TOXICVER);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "");
const char *msg = "Welcome to Toxic, a free, open source Tox-based instant messaging client.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, CYAN, msg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 1, CYAN, msg);
msg = "Type \"/help\" for assistance. Further help may be found via the man page.";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, CYAN, msg);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
line_info_add(self, false, NULL, NULL, SYS_MSG, 1, CYAN, msg);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "");
}
static void prompt_init_log(ToxWindow *self, Tox *m, const char *self_name)
@ -562,13 +589,13 @@ static void prompt_init_log(ToxWindow *self, Tox *m, const char *self_name)
tox_self_get_address(m, (uint8_t *) myid);
if (log_init(ctx->log, self->name, myid, NULL, LOG_TYPE_PROMPT) != 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Warning: Log failed to initialize.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Warning: Log failed to initialize.");
return;
}
if (user_settings->autolog == AUTOLOG_ON) {
if (log_enable(ctx->log) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Warning: Failed to enable log.");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Warning: Failed to enable log.");
}
}
}
@ -576,7 +603,9 @@ static void prompt_init_log(ToxWindow *self, Tox *m, const char *self_name)
static void prompt_onInit(ToxWindow *self, Tox *m)
{
curs_set(1);
int y2, x2;
int y2;
int x2;
getmaxyx(self->window, y2, x2);
if (y2 <= 0 || x2 <= 0) {
@ -584,8 +613,10 @@ static void prompt_onInit(ToxWindow *self, Tox *m)
}
ChatContext *ctx = self->chatwin;
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, x2, 0, 0);
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2 - CHATBOX_HEIGHT, 0);
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT, x2, 0, 0);
self->window_bar = subwin(self->window, WINDOW_BAR_HEIGHT, x2, y2 - (CHATBOX_HEIGHT + WINDOW_BAR_HEIGHT), 0);
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2 - WINDOW_BAR_HEIGHT, 0);
ctx->log = calloc(1, sizeof(struct chatlog));
ctx->hst = calloc(1, sizeof(struct history));

View File

@ -73,6 +73,11 @@ static struct ui_strings {
const char *mplex_away;
const char *mplex_away_note;
const char *color_bar_bg;
const char *color_bar_fg;
const char *color_bar_accent;
const char *color_bar_notify;
} ui_strings = {
"ui",
"timestamps",
@ -100,6 +105,10 @@ static struct ui_strings {
"line_normal",
"mplex_away",
"mplex_away_note",
"color_bar_bg",
"color_bar_fg",
"color_bar_accent",
"color_bar_notify",
};
static void ui_defaults(struct user_settings *settings)
@ -116,7 +125,7 @@ static void ui_defaults(struct user_settings *settings)
settings->bell_on_invite = 0;
settings->colour_theme = DFLT_COLS;
settings->history_size = 700;
settings->notification_timeout = 3000;
settings->notification_timeout = 6000;
settings->show_typing_self = SHOW_TYPING_ON;
settings->show_typing_other = SHOW_TYPING_ON;
settings->show_welcome_msg = SHOW_WELCOME_MSG_ON;
@ -130,10 +139,7 @@ static void ui_defaults(struct user_settings *settings)
snprintf(settings->line_normal, LINE_HINT_MAX + 1, "%s", LINE_NORMAL);
settings->mplex_away = MPLEX_ON;
snprintf(settings->mplex_away_note,
sizeof(settings->mplex_away_note),
"%s",
MPLEX_AWAY_NOTE);
snprintf(settings->mplex_away_note, sizeof(settings->mplex_away_note), "%s", MPLEX_AWAY_NOTE);
}
static const struct keys_strings {
@ -339,7 +345,7 @@ int settings_load(struct user_settings *s, const char *patharg)
if (config_setting_lookup_int(setting, ui_strings.time_format, &time)) {
if (time == 12) {
snprintf(s->timestamp_format, sizeof(s->timestamp_format), "%s", "%I:%M:%S %p");
snprintf(s->timestamp_format, sizeof(s->timestamp_format), "%s", "%I:%M %p");
snprintf(s->log_timestamp_format, sizeof(s->log_timestamp_format), "%s", "%Y/%m/%d [%I:%M:%S %p]");
}
}
@ -348,6 +354,22 @@ int settings_load(struct user_settings *s, const char *patharg)
snprintf(s->timestamp_format, sizeof(s->timestamp_format), "%s", str);
}
if (config_setting_lookup_string(setting, ui_strings.color_bar_bg, &str)) {
snprintf(s->color_bar_bg, sizeof(s->color_bar_bg), "%s", str);
}
if (config_setting_lookup_string(setting, ui_strings.color_bar_fg, &str)) {
snprintf(s->color_bar_fg, sizeof(s->color_bar_fg), "%s", str);
}
if (config_setting_lookup_string(setting, ui_strings.color_bar_accent, &str)) {
snprintf(s->color_bar_accent, sizeof(s->color_bar_accent), "%s", str);
}
if (config_setting_lookup_string(setting, ui_strings.color_bar_notify, &str)) {
snprintf(s->color_bar_notify, sizeof(s->color_bar_notify), "%s", str);
}
if (config_setting_lookup_string(setting, ui_strings.log_timestamp_format, &str)) {
snprintf(s->log_timestamp_format, sizeof(s->log_timestamp_format), "%s", str);
}

View File

@ -68,6 +68,11 @@ struct user_settings {
char autorun_path[PATH_MAX];
char password_eval[PASSWORD_EVAL_MAX];
char color_bar_bg[COLOR_STR_SIZE];
char color_bar_fg[COLOR_STR_SIZE];
char color_bar_accent[COLOR_STR_SIZE];
char color_bar_notify[COLOR_STR_SIZE];
int key_next_tab;
int key_prev_tab;
int key_scroll_line_up;
@ -125,7 +130,7 @@ enum settings_values {
#define LINE_NORMAL "-"
#define TIMESTAMP_DEFAULT "%H:%M"
#define LOG_TIMESTAMP_DEFAULT "%Y/%m/%d [%H:%M:%S]"
#define MPLEX_AWAY_NOTE "Detached from screen"
#define MPLEX_AWAY_NOTE "Away from keyboard, be back soon!"
int settings_load(struct user_settings *s, const char *patharg);

View File

@ -256,10 +256,14 @@ static void init_term(void)
keypad(stdscr, 1);
noecho();
nonl();
timeout(100);
timeout(50);
if (has_colors()) {
short bg_color = COLOR_BLACK;
short bar_bg_color = COLOR_BLUE;
short bar_fg_color = COLOR_WHITE;
short bar_accent_color = COLOR_CYAN;
short bar_notify_color = COLOR_YELLOW;
start_color();
if (user_settings->colour_theme == NATIVE_COLS) {
@ -268,15 +272,120 @@ static void init_term(void)
}
}
init_pair(0, COLOR_WHITE, COLOR_BLACK);
init_pair(1, COLOR_GREEN, bg_color);
init_pair(2, COLOR_CYAN, bg_color);
init_pair(3, COLOR_RED, bg_color);
init_pair(4, COLOR_BLUE, bg_color);
init_pair(5, COLOR_YELLOW, bg_color);
init_pair(6, COLOR_MAGENTA, bg_color);
init_pair(7, COLOR_BLACK, COLOR_BLACK);
init_pair(8, COLOR_BLACK, COLOR_WHITE);
if (!string_is_empty(user_settings->color_bar_bg)) {
if (strcmp(user_settings->color_bar_bg, "black") == 0) {
bar_bg_color = COLOR_BLACK;
} else if (strcmp(user_settings->color_bar_bg, "red") == 0) {
bar_bg_color = COLOR_RED;
} else if (strcmp(user_settings->color_bar_bg, "blue") == 0) {
bar_bg_color = COLOR_BLUE;
} else if (strcmp(user_settings->color_bar_bg, "cyan") == 0) {
bar_bg_color = COLOR_CYAN;
} else if (strcmp(user_settings->color_bar_bg, "green") == 0) {
bar_bg_color = COLOR_GREEN;
} else if (strcmp(user_settings->color_bar_bg, "yellow") == 0) {
bar_bg_color = COLOR_YELLOW;
} else if (strcmp(user_settings->color_bar_bg, "magenta") == 0) {
bar_bg_color = COLOR_MAGENTA;
} else if (strcmp(user_settings->color_bar_bg, "white") == 0) {
bar_bg_color = COLOR_WHITE;
} else {
bar_bg_color = COLOR_BLUE;
}
} else {
bar_bg_color = COLOR_BLUE;
}
if (!string_is_empty(user_settings->color_bar_fg)) {
if (strcmp(user_settings->color_bar_fg, "black") == 0) {
bar_fg_color = COLOR_BLACK;
} else if (strcmp(user_settings->color_bar_fg, "red") == 0) {
bar_fg_color = COLOR_RED;
} else if (strcmp(user_settings->color_bar_fg, "blue") == 0) {
bar_fg_color = COLOR_BLUE;
} else if (strcmp(user_settings->color_bar_fg, "cyan") == 0) {
bar_fg_color = COLOR_CYAN;
} else if (strcmp(user_settings->color_bar_fg, "green") == 0) {
bar_fg_color = COLOR_GREEN;
} else if (strcmp(user_settings->color_bar_fg, "yellow") == 0) {
bar_fg_color = COLOR_YELLOW;
} else if (strcmp(user_settings->color_bar_fg, "magenta") == 0) {
bar_fg_color = COLOR_MAGENTA;
} else if (strcmp(user_settings->color_bar_fg, "white") == 0) {
bar_fg_color = COLOR_WHITE;
} else {
bar_fg_color = COLOR_WHITE;
}
} else {
bar_fg_color = COLOR_WHITE;
}
if (!string_is_empty(user_settings->color_bar_accent)) {
if (strcmp(user_settings->color_bar_accent, "black") == 0) {
bar_accent_color = COLOR_BLACK;
} else if (strcmp(user_settings->color_bar_accent, "red") == 0) {
bar_accent_color = COLOR_RED;
} else if (strcmp(user_settings->color_bar_accent, "blue") == 0) {
bar_accent_color = COLOR_BLUE;
} else if (strcmp(user_settings->color_bar_accent, "cyan") == 0) {
bar_accent_color = COLOR_CYAN;
} else if (strcmp(user_settings->color_bar_accent, "green") == 0) {
bar_accent_color = COLOR_GREEN;
} else if (strcmp(user_settings->color_bar_accent, "yellow") == 0) {
bar_accent_color = COLOR_YELLOW;
} else if (strcmp(user_settings->color_bar_accent, "magenta") == 0) {
bar_accent_color = COLOR_MAGENTA;
} else if (strcmp(user_settings->color_bar_accent, "white") == 0) {
bar_accent_color = COLOR_WHITE;
} else {
bar_accent_color = COLOR_CYAN;
}
} else {
bar_accent_color = COLOR_CYAN;
}
if (!string_is_empty(user_settings->color_bar_notify)) {
if (strcmp(user_settings->color_bar_notify, "black") == 0) {
bar_notify_color = COLOR_BLACK;
} else if (strcmp(user_settings->color_bar_notify, "red") == 0) {
bar_notify_color = COLOR_RED;
} else if (strcmp(user_settings->color_bar_notify, "blue") == 0) {
bar_notify_color = COLOR_BLUE;
} else if (strcmp(user_settings->color_bar_notify, "cyan") == 0) {
bar_notify_color = COLOR_CYAN;
} else if (strcmp(user_settings->color_bar_notify, "green") == 0) {
bar_notify_color = COLOR_GREEN;
} else if (strcmp(user_settings->color_bar_notify, "yellow") == 0) {
bar_notify_color = COLOR_YELLOW;
} else if (strcmp(user_settings->color_bar_notify, "magenta") == 0) {
bar_notify_color = COLOR_MAGENTA;
} else if (strcmp(user_settings->color_bar_notify, "white") == 0) {
bar_notify_color = COLOR_WHITE;
} else {
bar_notify_color = COLOR_YELLOW;
}
} else {
bar_notify_color = COLOR_YELLOW;
}
init_pair(WHITE, COLOR_WHITE, COLOR_BLACK);
init_pair(GREEN, COLOR_GREEN, bg_color);
init_pair(CYAN, COLOR_CYAN, bg_color);
init_pair(RED, COLOR_RED, bg_color);
init_pair(BLUE, COLOR_BLUE, bg_color);
init_pair(YELLOW, COLOR_YELLOW, bg_color);
init_pair(MAGENTA, COLOR_MAGENTA, bg_color);
init_pair(BLACK, COLOR_BLACK, COLOR_BLACK);
init_pair(BLUE_BLACK, COLOR_BLUE, COLOR_BLACK);
init_pair(BLACK_WHITE, COLOR_BLACK, COLOR_WHITE);
init_pair(BLACK_BG, COLOR_BLACK, bar_bg_color);
init_pair(PURPLE_BG, COLOR_MAGENTA, bar_bg_color);
init_pair(BAR_TEXT, bar_fg_color, bar_bg_color);
init_pair(BAR_ACCENT, bar_accent_color, bar_bg_color);
init_pair(BAR_NOTIFY, bar_notify_color, bar_bg_color);
init_pair(STATUS_ONLINE, COLOR_GREEN, bar_bg_color);
init_pair(STATUS_AWAY, COLOR_YELLOW, bar_bg_color);
init_pair(STATUS_BUSY, COLOR_RED, bar_bg_color);
}
refresh();
@ -1421,6 +1530,7 @@ int main(int argc, char **argv)
prompt = init_windows(m);
prompt_init_statusbar(prompt, m, !datafile_exists);
load_conferences(m);
set_active_window_index(0);
if (pthread_mutex_init(&Winthread.lock, NULL) != 0) {
exit_toxic_err("failed in main", FATALERR_MUTEX_INIT);
@ -1483,7 +1593,6 @@ int main(int argc, char **argv)
pthread_mutex_lock(&Winthread.lock);
print_init_messages(prompt);
set_active_window_index(0);
pthread_mutex_unlock(&Winthread.lock);
cleanup_init_messages();
@ -1504,7 +1613,7 @@ int main(int argc, char **argv)
pthread_mutex_lock(&Winthread.lock);
if (store_data(m, DATA_FILE) != 0) {
line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, "WARNING: Failed to save to data file");
line_info_add(prompt, false, NULL, NULL, SYS_MSG, 0, RED, "WARNING: Failed to save to data file");
}
pthread_mutex_unlock(&Winthread.lock);

View File

@ -48,6 +48,7 @@
#define TOXIC_MAX_NAME_LENGTH 32 /* Must be <= TOX_MAX_NAME_LENGTH */
#define KEY_IDENT_DIGITS 3 /* number of hex digits to display for the pub-key based identifier */
#define TIME_STR_SIZE 32
#define COLOR_STR_SIZE 10 /* should fit every color option */
#ifndef MAX_PORT_RANGE
#define MAX_PORT_RANGE 65535
@ -75,7 +76,7 @@
#define T_KEY_C_DOWN 0x20D /* ctrl-down arrow */
#define T_KEY_TAB 0x09 /* TAB key */
#define ONLINE_CHAR "*"
#define ONLINE_CHAR "o"
#define OFFLINE_CHAR "o"
typedef enum _FATAL_ERRS {

View File

@ -52,7 +52,7 @@ void on_video_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_bit_rat
static void print_err(ToxWindow *self, const char *error_str)
{
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", error_str);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%s", error_str);
}
ToxAV *init_video(ToxWindow *self, Tox *tox)
@ -66,13 +66,13 @@ ToxAV *init_video(ToxWindow *self, Tox *tox)
CallControl.video_frame_duration = 10;
if (!CallControl.av) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Video failed to init with ToxAV instance");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Video failed to init with ToxAV instance");
return NULL;
}
if (init_video_devices(CallControl.av) == vde_InternalError) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to init video devices");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to init video devices");
return NULL;
}
@ -110,17 +110,17 @@ void read_video_device_callback(int16_t width, int16_t height, const uint8_t *y,
/* Drop frame if video sending is disabled */
if (this_call->video_bit_rate == 0 || this_call->status != cs_Active || this_call->vin_idx == -1) {
line_info_add(CallControl.prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Video frame dropped.");
line_info_add(CallControl.prompt, false, NULL, NULL, SYS_MSG, 0, 0, "Video frame dropped.");
return;
}
if (toxav_video_send_frame(CallControl.av, friend_number, width, height, y, u, v, &error) == false) {
line_info_add(CallControl.prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to send video frame");
line_info_add(CallControl.prompt, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to send video frame");
if (error == TOXAV_ERR_SEND_FRAME_NULL) {
line_info_add(CallControl.prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to capture video frame");
line_info_add(CallControl.prompt, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to capture video frame");
} else if (error == TOXAV_ERR_SEND_FRAME_INVALID) {
line_info_add(CallControl.prompt, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to prepare video frame");
line_info_add(CallControl.prompt, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to prepare video frame");
}
}
}
@ -138,22 +138,22 @@ void write_video_device_callback(uint32_t friend_number, uint16_t width, uint16_
int start_video_transmission(ToxWindow *self, ToxAV *av, Call *call)
{
if (!self || !av) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to prepare video transmission");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to prepare video transmission");
return -1;
}
if (open_primary_video_device(vdt_input, &call->vin_idx, &call->video_width, &call->video_height) != vde_None) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to open input video device!");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to open input video device!");
return -1;
}
if (register_video_device_callback(self->num, call->vin_idx, read_video_device_callback, &self->num) != vde_None) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to register input video handler!");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to register input video handler!");
return -1;
}
if (!toxav_video_set_bit_rate(CallControl.av, self->num, call->video_bit_rate, NULL)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set video bit rate");
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to set video bit rate");
return -1;
}
@ -347,11 +347,11 @@ void cmd_res(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
if (argc == 0) {
if (call->status == cs_Active && call->vin_idx != -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0,
"Resolution of current call: %u x %u",
call->video_width, call->video_height);
} else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0,
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0,
"Initial resolution for video calls: %u x %u",
CallControl.default_video_width, CallControl.default_video_height);
}
@ -411,7 +411,7 @@ void cmd_list_video_devices(WINDOW *window, ToxWindow *self, Tox *m, int argc, c
}
else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
return;
}
@ -447,7 +447,7 @@ void cmd_change_video_device(WINDOW *window, ToxWindow *self, Tox *m, int argc,
}
else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid type: %s", argv[1]);
return;
}

View File

@ -852,7 +852,7 @@ void print_video_devices(ToxWindow *self, VideoDeviceType type)
int i;
for (i = 0; i < size[type]; ++i) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%d: %s", i, video_devices_names[type][i]);
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "%d: %s", i, video_devices_names[type][i]);
}
return;

View File

@ -336,7 +336,7 @@ int add_window(Tox *m, ToxWindow *w)
}
w->index = i;
w->window = newwin(LINES - 2, COLS, 0, 0);
w->window = newwin(LINES, COLS, 0, 0);
if (w->window == NULL) {
return -1;
@ -397,8 +397,9 @@ void del_window(ToxWindow *w)
set_active_window_index(0);
uint8_t idx = w->index;
delwin(w->window_bar);
delwin(w->window);
free(windows[idx]);
free(w);
windows[idx] = NULL;
clear();
@ -408,7 +409,12 @@ void del_window(ToxWindow *w)
ToxWindow *init_windows(Tox *m)
{
if (COLS <= CHATBOX_HEIGHT + WINDOW_BAR_HEIGHT) {
exit_toxic_err("add_window() for prompt failed in init_windows", FATALERR_WININIT);
}
prompt = new_prompt();
int n_prompt = add_window(m, prompt);
if (n_prompt < 0) {
@ -430,25 +436,18 @@ void on_window_resize(void)
refresh();
clear();
/* equivalent to LINES and COLS */
int x2, y2;
getmaxyx(stdscr, y2, x2);
y2 -= 2;
if (y2 <= 0 || x2 <= 0) {
return;
}
for (uint8_t i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i] == NULL) {
ToxWindow *w = windows[i];
if (w == NULL) {
continue;
}
ToxWindow *w = windows[i];
if (windows[i]->type == WINDOW_TYPE_FRIEND_LIST) {
if (w->type == WINDOW_TYPE_FRIEND_LIST) {
delwin(w->window_bar);
delwin(w->window);
w->window = newwin(y2, x2, 0, 0);
w->window = newwin(LINES, COLS, 0, 0);
w->window_bar = subwin(w->window, WINDOW_BAR_HEIGHT, COLS, LINES - 2, 0);
continue;
}
@ -465,22 +464,35 @@ void on_window_resize(void)
delwin(w->chatwin->linewin);
delwin(w->chatwin->history);
delwin(w->window_bar);
delwin(w->window);
w->window = newwin(y2, x2, 0, 0);
w->chatwin->linewin = subwin(w->window, CHATBOX_HEIGHT, x2, y2 - CHATBOX_HEIGHT, 0);
w->window = newwin(LINES, COLS, 0, 0);
int x2;
int y2;
getmaxyx(w->window, y2, x2);
if (y2 <= 0 || x2 <= 0) {
fprintf(stderr, "Failed to resize window: max_x: %d, max_y: %d\n", x2, y2);
delwin(w->window);
return;
}
if (w->show_peerlist) {
w->chatwin->history = subwin(w->window, y2 - CHATBOX_HEIGHT + 1, x2 - SIDEBAR_WIDTH - 1, 0, 0);
w->chatwin->sidebar = subwin(w->window, y2 - CHATBOX_HEIGHT + 1, SIDEBAR_WIDTH, 0, x2 - SIDEBAR_WIDTH);
w->chatwin->history = subwin(w->window, y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT, x2 - SIDEBAR_WIDTH - 1, 0, 0);
w->chatwin->sidebar = subwin(w->window, y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT, SIDEBAR_WIDTH, 0, x2 - SIDEBAR_WIDTH);
} else {
w->chatwin->history = subwin(w->window, y2 - CHATBOX_HEIGHT + 1, x2, 0, 0);
w->chatwin->history = subwin(w->window, y2 - CHATBOX_HEIGHT - WINDOW_BAR_HEIGHT, x2, 0, 0);
if (w->type != WINDOW_TYPE_CONFERENCE) {
w->stb->topline = subwin(w->window, 2, x2, 0, 0);
w->stb->topline = subwin(w->window, TOP_BAR_HEIGHT, x2, 0, 0);
}
}
w->window_bar = subwin(w->window, WINDOW_BAR_HEIGHT, x2, y2 - (CHATBOX_HEIGHT + WINDOW_BAR_HEIGHT), 0);
w->chatwin->linewin = subwin(w->window, CHATBOX_HEIGHT, x2, y2 - WINDOW_BAR_HEIGHT, 0);
#ifdef AUDIO
if (w->chatwin->infobox.active) {
@ -491,97 +503,103 @@ void on_window_resize(void)
#endif /* AUDIO */
scrollok(w->chatwin->history, 0);
wmove(w->window, y2 - CURS_Y_OFFSET, 0);
}
}
static void draw_window_tab(ToxWindow *toxwin, bool active_window)
static void draw_window_tab(WINDOW *win, ToxWindow *toxwin, bool active_window)
{
pthread_mutex_lock(&Winthread.lock);
if (toxwin->alert != WINDOW_ALERT_NONE) {
attron(COLOR_PAIR(toxwin->alert));
}
bool has_alert = toxwin->alert != WINDOW_ALERT_NONE;
unsigned int pending_messages = toxwin->pending_messages;
pthread_mutex_unlock(&Winthread.lock);
clrtoeol();
WINDOW_TYPE type = toxwin->type;
if (active_window || (type == WINDOW_TYPE_PROMPT || type == WINDOW_TYPE_FRIEND_LIST)) {
printw(" [%s]", toxwin->name);
if (active_window) {
wattron(win, A_BOLD | COLOR_PAIR(BAR_ACCENT));
wprintw(win, " [");
wattroff(win, COLOR_PAIR(BAR_ACCENT));
wattron(win, COLOR_PAIR(BAR_TEXT));
} else {
if (pending_messages > 0) {
printw(" [%u]", pending_messages);
if (has_alert) {
wattron(win, COLOR_PAIR(BAR_ACCENT));
wprintw(win, " [");
wattroff(win, COLOR_PAIR(BAR_ACCENT));
wattron(win, A_BOLD | COLOR_PAIR(toxwin->alert));
} else {
printw(" [*]");
wattron(win, COLOR_PAIR(BAR_ACCENT));
wprintw(win, " [");
wattroff(win, COLOR_PAIR(BAR_ACCENT));
wattron(win, COLOR_PAIR(BAR_TEXT));
}
}
pthread_mutex_lock(&Winthread.lock);
if (toxwin->alert != WINDOW_ALERT_NONE) {
attroff(COLOR_PAIR(toxwin->alert));
if (active_window || (type == WINDOW_TYPE_PROMPT || type == WINDOW_TYPE_FRIEND_LIST)) {
wprintw(win, "%s", toxwin->name);
} else {
if (pending_messages > 0) {
wprintw(win, "%u", pending_messages);
} else {
wprintw(win, "-");
}
}
pthread_mutex_unlock(&Winthread.lock);
if (active_window) {
wattroff(win, COLOR_PAIR(BAR_TEXT));
wattron(win, COLOR_PAIR(BAR_ACCENT));
wprintw(win, "]");
wattroff(win, A_BOLD | COLOR_PAIR(BAR_ACCENT));
} else {
if (has_alert) {
wattroff(win, A_BOLD | COLOR_PAIR(toxwin->alert));
wattron(win, COLOR_PAIR(BAR_ACCENT));
wprintw(win, "]");
wattroff(win, COLOR_PAIR(BAR_ACCENT));
} else {
wattroff(win, COLOR_PAIR(BAR_TEXT));
wattron(win, COLOR_PAIR(BAR_ACCENT));
wprintw(win, "]");
wattroff(win, COLOR_PAIR(BAR_ACCENT));
}
}
}
static void draw_bar(void)
void draw_window_bar(ToxWindow *self)
{
int y, x;
WINDOW *win = self->window_bar;
wclear(win);
ToxWindow *w = windows[active_window_index];
if (w == NULL) {
return;
if (self->scroll_pause) {
wattron(win, A_BLINK | A_BOLD | COLOR_PAIR(BAR_NOTIFY));
wprintw(win, "^");
wattroff(win, A_BLINK | A_BOLD | COLOR_PAIR(BAR_NOTIFY));
} else {
wattron(win, COLOR_PAIR(BAR_TEXT));
wprintw(win, " ");
wattroff(win, COLOR_PAIR(BAR_TEXT));
}
// save current cursor position
getyx(w->window, y, x);
attron(COLOR_PAIR(BLUE));
mvhline(LINES - 2, 0, '_', COLS);
attroff(COLOR_PAIR(BLUE));
move(LINES - 1, 0);
for (uint8_t i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i] == NULL) {
continue;
}
bool active_window = i == active_window_index;
if (active_window) {
#ifdef URXVT_FIX
attron(A_BOLD | COLOR_PAIR(GREEN));
} else {
#endif
attron(A_BOLD);
}
draw_window_tab(windows[i], active_window);
if (active_window) {
#ifdef URXVT_FIX
attroff(A_BOLD | COLOR_PAIR(GREEN));
} else {
#endif
attroff(A_BOLD);
}
draw_window_tab(win, windows[i], active_window);
}
// restore cursor position after drawing
move(y, x);
int cur_x;
int cur_y;
UNUSED_VAR(cur_y);
refresh();
getyx(win, cur_y, cur_x);
wattron(win, COLOR_PAIR(BAR_TEXT));
mvwhline(win, 0, cur_x, ' ', COLS - cur_x);
wattroff(win, COLOR_PAIR(BAR_TEXT));
}
/*
@ -684,8 +702,6 @@ void draw_active_window(Tox *m)
a->pending_messages = 0;
pthread_mutex_unlock(&Winthread.lock);
draw_bar();
touchwin(a->window);
a->onDraw(a, m);
wrefresh(a->window);

View File

@ -39,9 +39,11 @@
#define MAX_WINDOWS_NUM 20
#define MAX_WINDOW_NAME_LENGTH 22
#define CURS_Y_OFFSET 1 /* y-axis cursor offset for chat contexts */
#define CHATBOX_HEIGHT 2
#define CHATBOX_HEIGHT 1
#define TOP_BAR_HEIGHT 1
#define WINDOW_BAR_HEIGHT 1
/* Curses foreground colours (background is black) */
/* ncurses colour pairs as FOREGROUND_BACKGROUND. No background defaults to black. */
typedef enum {
WHITE,
GREEN,
@ -51,14 +53,24 @@ typedef enum {
YELLOW,
MAGENTA,
BLACK,
BLUE_BLACK,
BLACK_WHITE,
BAR_TEXT,
STATUS_ONLINE,
BAR_ACCENT,
PURPLE_BG,
BLACK_BG,
STATUS_BUSY,
STATUS_AWAY,
BAR_NOTIFY,
} C_COLOURS;
/* tab alert types: lower types take priority (this relies on the order of C_COLOURS) */
typedef enum {
WINDOW_ALERT_NONE = 0,
WINDOW_ALERT_0 = GREEN,
WINDOW_ALERT_1 = RED,
WINDOW_ALERT_2 = MAGENTA,
WINDOW_ALERT_0 = STATUS_ONLINE,
WINDOW_ALERT_1 = BAR_ACCENT,
WINDOW_ALERT_2 = PURPLE_BG,
} WINDOW_ALERTS;
typedef enum {
@ -167,6 +179,7 @@ struct ToxWindow {
char name[TOXIC_MAX_NAME_LENGTH + 1];
uint32_t num; /* corresponds to friendnumber in chat windows */
uint8_t index; /* This window's index in the windows array */
bool scroll_pause; /* true if this window is not scrolled to the bottom */
unsigned int pending_messages; /* # of new messages in this window since the last time it was focused */
int x;
@ -181,6 +194,7 @@ struct ToxWindow {
Help *help;
WINDOW *window;
WINDOW *window_bar;
};
/* statusbar info holder */
@ -264,6 +278,7 @@ void on_window_resize(void);
void force_refresh(WINDOW *w);
ToxWindow *get_window_ptr(size_t i);
ToxWindow *get_active_window(void);
void draw_window_bar(ToxWindow *self);
/* refresh inactive windows to prevent scrolling bugs.
call at least once per second */