mirror of
https://github.com/Tha14/toxic.git
synced 2025-06-26 22:46:44 +02:00
Compare commits
43 Commits
Author | SHA1 | Date | |
---|---|---|---|
22d60232fb | |||
e428879beb | |||
3015138a5a | |||
9c06ad608b | |||
015dbd9a96 | |||
a7466c3142 | |||
f012007cc4 | |||
dcf3baf60f | |||
4bda799a4b | |||
bdeae33d48 | |||
47591d5298 | |||
b5ace27a3e | |||
b334622d36 | |||
4bfb344caa | |||
16d96d6faf | |||
0ab2bad226 | |||
68db926f9f | |||
b270c1e8b7 | |||
e7142e49fd | |||
610906d07f | |||
6f72a191ba | |||
dd5fa236ae | |||
51e1ab94b3 | |||
ddc8c53abf | |||
46513017e3 | |||
98cb7f58c0 | |||
206bf407fd | |||
0a8ac4de3b | |||
87d54acad0 | |||
45ff6d8bac | |||
437dd8baeb | |||
b080236ee5 | |||
116bff8cef | |||
ddeca171a0 | |||
127f9462e0 | |||
4b5a9abbd4 | |||
bb2257973e | |||
12b9cd2386 | |||
2cbe8fa880 | |||
2e39bee05a | |||
05eda76643 | |||
f7b73af9a7 | |||
73aaa44d12 |
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1 @@
|
||||
/.github/ @TokTok/admins
|
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
---
|
||||
github: [JFreegman]
|
17
.github/settings.yml
vendored
Normal file
17
.github/settings.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
_extends: .github
|
||||
|
||||
repository:
|
||||
name: toxic
|
||||
description: An ncurses-based Tox client
|
||||
topics: tox, console, chat
|
||||
|
||||
branches:
|
||||
- name: "master"
|
||||
protection:
|
||||
required_status_checks:
|
||||
contexts:
|
||||
- Codacy/PR Quality Review
|
||||
- CodeFactor
|
||||
- Travis CI - Pull Request
|
||||
- code-review/reviewable
|
4
.restyled.yaml
Normal file
4
.restyled.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
restylers:
|
||||
- astyle:
|
||||
arguments: ["--options=astylerc"]
|
83
.travis.yml
83
.travis.yml
@ -1,37 +1,60 @@
|
||||
---
|
||||
language: python
|
||||
python: nightly
|
||||
dist: xenial
|
||||
os: linux
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- astyle
|
||||
- libalut-dev
|
||||
- libconfig-dev
|
||||
- libnotify-dev
|
||||
- libopenal-dev
|
||||
- libopus-dev
|
||||
- libqrencode-dev
|
||||
- libvpx-dev
|
||||
jobs:
|
||||
include:
|
||||
- env: JOB=linux
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/cache
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libalut-dev
|
||||
- libconfig-dev
|
||||
- libnotify-dev
|
||||
- libopenal-dev
|
||||
- libopus-dev
|
||||
- libqrencode-dev
|
||||
- libvpx-dev
|
||||
|
||||
install:
|
||||
# Where to find libraries.
|
||||
- export LD_LIBRARY_PATH=$HOME/cache/usr/lib
|
||||
- export PKG_CONFIG_PATH=$HOME/cache/usr/lib/pkgconfig
|
||||
# c-sodium
|
||||
- git clone --depth=1 --branch=stable https://github.com/jedisct1/libsodium ../libsodium
|
||||
- test -f $HOME/cache/usr/lib/libsodium.so || (cd ../libsodium && ./configure --prefix=$HOME/cache/usr && make install -j$(nproc))
|
||||
# c-toxcore
|
||||
- git clone --depth=1 https://github.com/TokTok/c-toxcore ../c-toxcore
|
||||
- test -f $HOME/cache/usr/lib/libtoxcore.so || (cd ../c-toxcore && cmake -B_build -H. -DCMAKE_INSTALL_PREFIX:PATH=$HOME/cache/usr && make -C_build install -j$(nproc))
|
||||
# astyle
|
||||
- wget -O ../astyle.tar.gz https://deb.debian.org/debian/pool/main/a/astyle/astyle_2.06.orig.tar.gz
|
||||
- test -f $HOME/cache/astyle/build/gcc/bin/astyle || (tar -xf ../astyle.tar.gz -C "$HOME/cache" && make -C "$HOME/cache/astyle/build/gcc" -j2)
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/cache
|
||||
|
||||
script:
|
||||
- $HOME/cache/astyle/build/gcc/bin/astyle --options=astylerc $(find . -name "*.[ch]")
|
||||
- make ENABLE_PYTHON=1 -j2
|
||||
install:
|
||||
# Where to find libraries.
|
||||
- export LD_LIBRARY_PATH=$HOME/cache/usr/lib
|
||||
- export PKG_CONFIG_PATH=$HOME/cache/usr/lib/pkgconfig
|
||||
# c-sodium
|
||||
- git clone --depth=1 --branch=stable https://github.com/jedisct1/libsodium ../libsodium
|
||||
- test -f $HOME/cache/usr/lib/libsodium.so || (cd ../libsodium && ./configure --prefix=$HOME/cache/usr && make install -j$(nproc))
|
||||
# c-toxcore
|
||||
- git clone --depth=1 https://github.com/TokTok/c-toxcore ../c-toxcore
|
||||
- test -f $HOME/cache/usr/lib/libtoxcore.so || (cd ../c-toxcore && cmake -B_build -H. -DCMAKE_INSTALL_PREFIX:PATH=$HOME/cache/usr && make -C_build install -j$(nproc))
|
||||
|
||||
script:
|
||||
- make ENABLE_PYTHON=1 -j$(nproc)
|
||||
|
||||
- env: JOB=macos
|
||||
os: macos
|
||||
language: c
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/cache
|
||||
|
||||
install:
|
||||
- brew install
|
||||
freealut
|
||||
libconfig
|
||||
libqrencode
|
||||
libsodium
|
||||
openal-soft
|
||||
- export LDFLAGS="-L/usr/local/Cellar/openal-soft/1.20.1/lib"
|
||||
- git clone --depth=1 https://github.com/TokTok/c-toxcore ../c-toxcore
|
||||
- test -f /usr/local/lib/libtoxcore.dylib || (cd ../c-toxcore && cmake -B_build -H. && make -C_build install -j$(nproc))
|
||||
|
||||
script:
|
||||
- make ENABLE_PYTHON=1 DISABLE_DESKTOP_NOTIFY=1 DISABLE_X11=1 DISABLE_AV=1 DISABLE_SOUND_NOTIFY=1 -j$(nproc)
|
||||
|
29
BUILD.bazel
29
BUILD.bazel
@ -1,21 +1,30 @@
|
||||
load("@rules_cc//cc:defs.bzl", "cc_binary")
|
||||
load("//tools/project:build_defs.bzl", "project")
|
||||
|
||||
project()
|
||||
|
||||
cc_binary(
|
||||
name = "toxic",
|
||||
srcs = glob([
|
||||
"src/*.c",
|
||||
"src/*.h",
|
||||
]),
|
||||
srcs = glob(
|
||||
[
|
||||
"src/*.c",
|
||||
"src/*.h",
|
||||
],
|
||||
exclude = ["src/video*"],
|
||||
) + select({
|
||||
"//tools/config:linux": glob(["src/video*"]),
|
||||
"//tools/config:osx": [],
|
||||
}),
|
||||
copts = [
|
||||
"-std=gnu99",
|
||||
"-DAUDIO",
|
||||
"-DPACKAGE_DATADIR='\"data\"'",
|
||||
"-DPYTHON",
|
||||
"-DQRCODE",
|
||||
"-DVIDEO",
|
||||
"-Wno-error=unused-result",
|
||||
],
|
||||
] + select({
|
||||
"//tools/config:linux": ["-DVIDEO"],
|
||||
"//tools/config:osx": [],
|
||||
}),
|
||||
deps = [
|
||||
"//c-toxcore",
|
||||
"@curl",
|
||||
@ -25,6 +34,8 @@ cc_binary(
|
||||
"@ncurses",
|
||||
"@openal",
|
||||
"@python3//:python",
|
||||
"@x11",
|
||||
],
|
||||
] + select({
|
||||
"//tools/config:linux": ["@x11"],
|
||||
"//tools/config:osx": [],
|
||||
}),
|
||||
)
|
||||
|
@ -55,6 +55,8 @@ Run `make doc` in the build directory after editing the asciidoc files to regene
|
||||
* `DISABLE_X11=1` → Disable X11 support (needed for focus tracking)
|
||||
* `DISABLE_AV=1` → Disable audio call support
|
||||
* `DISABLE_SOUND_NOTIFY=1` → Disable sound notifications support
|
||||
* `DISABLE_QRCODE` → Disable QR exporting support
|
||||
* `DISABLE_QRPNG` → Disable support for exporting QR as PNG
|
||||
* `DISABLE_DESKTOP_NOTIFY=1` → Disable desktop notifications support
|
||||
* `ENABLE_PYTHON=1` → Build toxic with Python scripting support
|
||||
|
||||
|
2
Makefile
2
Makefile
@ -6,7 +6,7 @@ CFG_DIR = $(BASE_DIR)/cfg
|
||||
LIBS = toxcore ncursesw libconfig libcurl
|
||||
|
||||
CFLAGS ?= -g
|
||||
CFLAGS += -std=gnu99 -pthread -Wall -fstack-protector-all
|
||||
CFLAGS += -std=gnu99 -pthread -Wall -Wpedantic -Wunused -fstack-protector-all
|
||||
CFLAGS += '-DTOXICVER="$(VERSION)"' -DHAVE_WIDECHAR -D_XOPEN_SOURCE_EXTENDED -D_FILE_OFFSET_BITS=64
|
||||
CFLAGS += '-DPACKAGE_DATADIR="$(abspath $(DATADIR))"'
|
||||
CFLAGS += ${USER_CFLAGS}
|
||||
|
@ -3,7 +3,7 @@
|
||||
src="https://scan.coverity.com/projects/4975/badge.svg"/>
|
||||
</a>
|
||||
|
||||
Toxic is a [Tox](https://tox.chat)-based instant messenging and video chat client.
|
||||
Toxic is a [Tox](https://tox.chat)-based instant messaging and video chat client.
|
||||
|
||||
[](https://i.imgur.com/san99Z2.png)
|
||||
|
||||
|
@ -55,9 +55,9 @@ author = 'Jakob Kreuze'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.8.3'
|
||||
version = '0.8.4'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.8.3'
|
||||
release = '0.8.4'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -8,13 +8,13 @@ else
|
||||
endif
|
||||
|
||||
# Check if we can build audio support
|
||||
CHECK_AUDIO_LIBS = $(shell $(PKG_CONFIG) --exists $(AUDIO_LIBS) || echo -n "error")
|
||||
CHECK_AUDIO_LIBS := $(shell $(PKG_CONFIG) --exists $(AUDIO_LIBS) || echo -n "error")
|
||||
ifneq ($(CHECK_AUDIO_LIBS), error)
|
||||
LIBS += $(AUDIO_LIBS)
|
||||
CFLAGS += $(AUDIO_CFLAGS)
|
||||
OBJ += $(AUDIO_OBJ)
|
||||
else ifneq ($(MAKECMDGOALS), clean)
|
||||
MISSING_AUDIO_LIBS = $(shell for lib in $(AUDIO_LIBS) ; do if ! $(PKG_CONFIG) --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
MISSING_AUDIO_LIBS := $(shell for lib in $(AUDIO_LIBS) ; do if ! $(PKG_CONFIG) --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
$(warning WARNING -- Toxic will be compiled without audio support)
|
||||
$(warning WARNING -- You need these libraries for audio support)
|
||||
$(warning WARNING -- $(MISSING_AUDIO_LIBS))
|
||||
|
@ -1,19 +1,19 @@
|
||||
CHECKS_DIR = $(CFG_DIR)/checks
|
||||
|
||||
# Check if we want build X11 support
|
||||
X11 = $(shell if [ -z "$(DISABLE_X11)" ] || [ "$(DISABLE_X11)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
X11 := $(shell if [ -z "$(DISABLE_X11)" ] || [ "$(DISABLE_X11)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
ifneq ($(X11), disabled)
|
||||
-include $(CHECKS_DIR)/x11.mk
|
||||
endif
|
||||
|
||||
# Check if we want build audio support
|
||||
AUDIO = $(shell if [ -z "$(DISABLE_AV)" ] || [ "$(DISABLE_AV)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
AUDIO := $(shell if [ -z "$(DISABLE_AV)" ] || [ "$(DISABLE_AV)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
ifneq ($(AUDIO), disabled)
|
||||
-include $(CHECKS_DIR)/audio.mk
|
||||
endif
|
||||
|
||||
# Check if we want build video support
|
||||
VIDEO = $(shell if [ -z "$(DISABLE_VI)" ] || [ "$(DISABLE_VI)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
VIDEO := $(shell if [ -z "$(DISABLE_VI)" ] || [ "$(DISABLE_VI)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
ifneq ($(X11), disabled)
|
||||
ifneq ($(AUDIO), disabled)
|
||||
ifneq ($(VIDEO), disabled)
|
||||
@ -23,42 +23,42 @@ endif
|
||||
endif
|
||||
|
||||
# Check if we want build sound notifications support
|
||||
SND_NOTIFY = $(shell if [ -z "$(DISABLE_SOUND_NOTIFY)" ] || [ "$(DISABLE_SOUND_NOTIFY)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
SND_NOTIFY := $(shell if [ -z "$(DISABLE_SOUND_NOTIFY)" ] || [ "$(DISABLE_SOUND_NOTIFY)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
ifneq ($(SND_NOTIFY), disabled)
|
||||
-include $(CHECKS_DIR)/sound_notifications.mk
|
||||
endif
|
||||
|
||||
# Check if we want build desktop notifications support
|
||||
DESK_NOTIFY = $(shell if [ -z "$(DISABLE_DESKTOP_NOTIFY)" ] || [ "$(DISABLE_DESKTOP_NOTIFY)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
DESK_NOTIFY := $(shell if [ -z "$(DISABLE_DESKTOP_NOTIFY)" ] || [ "$(DISABLE_DESKTOP_NOTIFY)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
ifneq ($(DESK_NOTIFY), disabled)
|
||||
-include $(CHECKS_DIR)/desktop_notifications.mk
|
||||
endif
|
||||
|
||||
# Check if we want build QR export support
|
||||
QR_CODE = $(shell if [ -z "$(DISABLE_QRCODE)" ] || [ "$(DISABLE_QRCODE)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
QR_CODE := $(shell if [ -z "$(DISABLE_QRCODE)" ] || [ "$(DISABLE_QRCODE)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
ifneq ($(QR_CODE), disabled)
|
||||
-include $(CHECKS_DIR)/qr.mk
|
||||
endif
|
||||
|
||||
# Check if we want build QR exported as PNG support
|
||||
QR_PNG = $(shell if [ -z "$(DISABLE_QRPNG)" ] || [ "$(DISABLE_QRPNG)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
QR_PNG := $(shell if [ -z "$(DISABLE_QRPNG)" ] || [ "$(DISABLE_QRPNG)" = "0" ] ; then echo enabled ; else echo disabled ; fi)
|
||||
ifneq ($(QR_PNG), disabled)
|
||||
-include $(CHECKS_DIR)/qr_png.mk
|
||||
endif
|
||||
|
||||
# Check if we want build Python scripting support
|
||||
PYTHON = $(shell if [ -z "$(ENABLE_PYTHON)" ] || [ "$(ENABLE_PYTHON)" = "0" ] ; then echo disabled ; else echo enabled ; fi)
|
||||
PYTHON := $(shell if [ -z "$(ENABLE_PYTHON)" ] || [ "$(ENABLE_PYTHON)" = "0" ] ; then echo disabled ; else echo enabled ; fi)
|
||||
ifneq ($(PYTHON), disabled)
|
||||
-include $(CHECKS_DIR)/python.mk
|
||||
endif
|
||||
|
||||
# Check if we can build Toxic
|
||||
CHECK_LIBS = $(shell $(PKG_CONFIG) --exists $(LIBS) || echo -n "error")
|
||||
CHECK_LIBS := $(shell $(PKG_CONFIG) --exists $(LIBS) || echo -n "error")
|
||||
ifneq ($(CHECK_LIBS), error)
|
||||
CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBS))
|
||||
LDFLAGS += $(shell $(PKG_CONFIG) --libs $(LIBS))
|
||||
else ifneq ($(MAKECMDGOALS), clean)
|
||||
MISSING_LIBS = $(shell for lib in $(LIBS) ; do if ! $(PKG_CONFIG) --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
MISSING_LIBS := $(shell for lib in $(LIBS) ; do if ! $(PKG_CONFIG) --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
$(warning ERROR -- Cannot compile Toxic)
|
||||
$(warning ERROR -- You need these libraries)
|
||||
$(warning ERROR -- $(MISSING_LIBS))
|
||||
|
@ -3,12 +3,12 @@ DESK_NOTIFY_LIBS = libnotify
|
||||
DESK_NOTIFY_CFLAGS = -DBOX_NOTIFY
|
||||
|
||||
# Check if we can build desktop notifications support
|
||||
CHECK_DESK_NOTIFY_LIBS = $(shell $(PKG_CONFIG) --exists $(DESK_NOTIFY_LIBS) || echo -n "error")
|
||||
CHECK_DESK_NOTIFY_LIBS := $(shell $(PKG_CONFIG) --exists $(DESK_NOTIFY_LIBS) || echo -n "error")
|
||||
ifneq ($(CHECK_DESK_NOTIFY_LIBS), error)
|
||||
LIBS += $(DESK_NOTIFY_LIBS)
|
||||
CFLAGS += $(DESK_NOTIFY_CFLAGS)
|
||||
else ifneq ($(MAKECMDGOALS), clean)
|
||||
MISSING_DESK_NOTIFY_LIBS = $(shell for lib in $(DESK_NOTIFY_LIBS) ; do if ! $(PKG_CONFIG) --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
MISSING_DESK_NOTIFY_LIBS := $(shell for lib in $(DESK_NOTIFY_LIBS) ; do if ! $(PKG_CONFIG) --exists $$lib ; then echo $$lib ; fi ; done)
|
||||
$(warning WARNING -- Toxic will be compiled without desktop notifications support)
|
||||
$(warning WARNING -- You need these libraries for desktop notifications support)
|
||||
$(warning WARNING -- $(MISSING_DESK_NOTIFY_LIBS))
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Variables for video call support
|
||||
VIDEO_LIBS = vpx x11
|
||||
VIDEO_LIBS = openal vpx x11
|
||||
VIDEO_CFLAGS = -DVIDEO
|
||||
ifneq (, $(findstring video_device.o, $(OBJ)))
|
||||
VIDEO_OBJ = video_call.o
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Version
|
||||
TOXIC_VERSION = 0.8.3
|
||||
TOXIC_VERSION = 0.8.4
|
||||
REV = $(shell git rev-list HEAD --count 2>/dev/null || echo -n "error")
|
||||
ifneq (, $(findstring error, $(REV)))
|
||||
VERSION = $(TOXIC_VERSION)
|
||||
|
@ -1,10 +1,10 @@
|
||||
# Doc target
|
||||
doc: $(MANFILES:%=$(DOC_DIR)/%)
|
||||
|
||||
|
||||
$(DOC_DIR)/%: $(DOC_DIR)/%.asc
|
||||
@echo " MAN $(@F)"
|
||||
@a2x -f manpage -a revdate=$(shell git log -1 --date=short --format="%ad" $<) \
|
||||
-a manmanual="Toxic Manual" -a mansource=toxic \
|
||||
-a manversion=__VERSION__ -a datadir=__DATADIR__ $<
|
||||
|
||||
|
||||
.PHONY: doc
|
||||
|
@ -78,6 +78,11 @@ instead of
|
||||
Show help message
|
||||
.RE
|
||||
.PP
|
||||
\-l, \-\-logging
|
||||
.RS 4
|
||||
Enable toxcore logging to stderr
|
||||
.RE
|
||||
.PP
|
||||
\-n, \-\-nodes nodes\-file
|
||||
.RS 4
|
||||
Use specified
|
||||
|
@ -40,6 +40,9 @@ OPTIONS
|
||||
-h, --help::
|
||||
Show help message
|
||||
|
||||
-l, --logging::
|
||||
Enable toxcore logging to stderr
|
||||
|
||||
-n, --nodes nodes-file::
|
||||
Use specified 'nodes-file' for DHT bootstrap nodes instead of '~/.config/tox/DHTnodes.json'
|
||||
|
||||
|
@ -2,12 +2,12 @@
|
||||
.\" Title: toxic.conf
|
||||
.\" Author: [see the "AUTHORS" section]
|
||||
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
|
||||
.\" Date: 2016-09-20
|
||||
.\" Date: 2018-10-27
|
||||
.\" Manual: Toxic Manual
|
||||
.\" Source: toxic __VERSION__
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "TOXIC\&.CONF" "5" "2016\-09\-20" "toxic __VERSION__" "Toxic Manual"
|
||||
.TH "TOXIC\&.CONF" "5" "2018\-10\-27" "toxic __VERSION__" "Toxic Manual"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * Define some portability stuff
|
||||
.\" -----------------------------------------------------------------
|
||||
@ -120,7 +120,12 @@ Enable friend connection change notifications\&. true or false
|
||||
.PP
|
||||
\fBnodelist_update_freq\fR
|
||||
.RS 4
|
||||
How often in days to update the DHT nodes list\&. (0 to disable updates)
|
||||
How often in days to update the DHT nodes list\&. (integer; 0 to disable)
|
||||
.RE
|
||||
.PP
|
||||
\fBautosave_freq\fR
|
||||
.RS 4
|
||||
How often in seconds to auto\-save the Tox data file\&. (integer; 0 to disable)
|
||||
.RE
|
||||
.PP
|
||||
\fBhistory_size\fR
|
||||
@ -128,6 +133,11 @@ How often in days to update the DHT nodes list\&. (0 to disable updates)
|
||||
Maximum lines for chat window history\&. Integer value\&. (for example: 700)
|
||||
.RE
|
||||
.PP
|
||||
\fBnotification_timeout\fR
|
||||
.RS 4
|
||||
Time in milliseconds to display a notification\&. (for example: 3000)
|
||||
.RE
|
||||
.PP
|
||||
\fBline_join\fR
|
||||
.RS 4
|
||||
Indicator for when someone connects or joins a group\&. Three characters max for line_ settings\&.
|
||||
@ -341,16 +351,6 @@ Key combination to scroll half page down\&.
|
||||
Key combination to scroll to page bottom\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBpeer_list_up\fR
|
||||
.RS 4
|
||||
Key combination to scroll contacts list up\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBpeer_list_down\fR
|
||||
.RS 4
|
||||
Key combination to scroll contacts list down\&.
|
||||
.RE
|
||||
.PP
|
||||
\fBtoggle_peerlist\fR
|
||||
.RS 4
|
||||
Toggle the peer list on and off\&.
|
||||
|
@ -76,11 +76,17 @@ OPTIONS
|
||||
Enable friend connection change notifications. true or false
|
||||
|
||||
*nodelist_update_freq*;;
|
||||
How often in days to update the DHT nodes list. (0 to disable updates)
|
||||
How often in days to update the DHT nodes list. (integer; 0 to disable)
|
||||
|
||||
*autosave_freq*;;
|
||||
How often in seconds to auto-save the Tox data file. (integer; 0 to disable)
|
||||
|
||||
*history_size*;;
|
||||
Maximum lines for chat window history. Integer value. (for example: 700)
|
||||
|
||||
*notification_timeout*;;
|
||||
Time in milliseconds to display a notification. Integer value. (for example: 3000)
|
||||
|
||||
*line_join*;;
|
||||
Indicator for when someone connects or joins a group.
|
||||
Three characters max for line_ settings.
|
||||
@ -215,12 +221,6 @@ OPTIONS
|
||||
*page_bottom*;;
|
||||
Key combination to scroll to page bottom.
|
||||
|
||||
*peer_list_up*;;
|
||||
Key combination to scroll contacts list up.
|
||||
|
||||
*peer_list_down*;;
|
||||
Key combination to scroll contacts list down.
|
||||
|
||||
*toggle_peerlist*;;
|
||||
Toggle the peer list on and off.
|
||||
|
||||
|
@ -47,9 +47,15 @@ ui = {
|
||||
// How often in days to update the DHT nodes list. (0 to disable updates)
|
||||
nodeslist_update_freq=7;
|
||||
|
||||
// How often in seconds to auto-save the Tox data file. (0 to disable periodic auto-saves)
|
||||
autosave_freq=600;
|
||||
|
||||
// maximum lines for chat window history
|
||||
history_size=700;
|
||||
|
||||
// time in milliseconds to display a notification
|
||||
notification_timeout=3000;
|
||||
|
||||
// Indicator for display when someone connects or joins a group.
|
||||
line_join="-->";
|
||||
|
||||
@ -116,8 +122,6 @@ keys = {
|
||||
half_page_up="Ctrl+F";
|
||||
half_page_down="Ctrl+V";
|
||||
page_bottom="Ctrl+H";
|
||||
peer_list_up="Ctrl+[";
|
||||
peer_list_down="Ctrl+]";
|
||||
toggle_peerlist="Ctrl+b";
|
||||
toggle_paste_mode="Ctrl+T";
|
||||
};
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "notify.h"
|
||||
#include "friendlist.h"
|
||||
#include "chat.h"
|
||||
#include "misc_tools.h"
|
||||
|
||||
#ifdef AUDIO
|
||||
|
||||
@ -174,6 +175,8 @@ void terminate_audio(void)
|
||||
|
||||
void read_device_callback(const int16_t *captured, uint32_t size, void *data)
|
||||
{
|
||||
UNUSED_VAR(size);
|
||||
|
||||
Toxav_Err_Send_Frame error;
|
||||
uint32_t friend_number = *((uint32_t *)data); /* TODO: Or pass an array of call_idx's */
|
||||
int64_t sample_count = ((int64_t) CallControl.audio_sample_rate) * \
|
||||
@ -280,6 +283,10 @@ int stop_transmission(Call *call, uint32_t friend_number)
|
||||
*/
|
||||
void on_call(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(audio_enabled);
|
||||
UNUSED_VAR(video_enabled);
|
||||
|
||||
Tox *m = (Tox *) user_data;
|
||||
CallControl.pending_call = true;
|
||||
callback_recv_invite(m, friend_number);
|
||||
@ -287,6 +294,9 @@ void on_call(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_e
|
||||
|
||||
void on_call_state(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(user_data);
|
||||
|
||||
CallControl.call_state = state;
|
||||
|
||||
switch (state) {
|
||||
@ -350,6 +360,9 @@ void on_audio_receive_frame(ToxAV *av, uint32_t friend_number,
|
||||
int16_t const *pcm, size_t sample_count,
|
||||
uint8_t channels, uint32_t sampling_rate, void *user_data)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(user_data);
|
||||
|
||||
write_device_callback(friend_number, pcm, sample_count, channels, sampling_rate);
|
||||
}
|
||||
|
||||
@ -457,6 +470,10 @@ void callback_call_ended(uint32_t friend_number)
|
||||
*/
|
||||
void cmd_call(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
UNUSED_VAR(argv);
|
||||
|
||||
Toxav_Err_Call error;
|
||||
const char *error_str;
|
||||
|
||||
@ -508,6 +525,10 @@ on_error:
|
||||
|
||||
void cmd_answer(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
UNUSED_VAR(argv);
|
||||
|
||||
Toxav_Err_Answer error;
|
||||
const char *error_str;
|
||||
|
||||
@ -555,6 +576,10 @@ on_error:
|
||||
|
||||
void cmd_reject(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
UNUSED_VAR(argv);
|
||||
|
||||
const char *error_str;
|
||||
|
||||
if (argc != 0) {
|
||||
@ -586,6 +611,10 @@ on_error:
|
||||
|
||||
void cmd_hangup(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
UNUSED_VAR(argv);
|
||||
|
||||
const char *error_str = NULL;
|
||||
|
||||
if (!CallControl.av) {
|
||||
@ -615,6 +644,9 @@ on_error:
|
||||
|
||||
void cmd_list_devices(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
const char *error_str;
|
||||
|
||||
if (argc != 1) {
|
||||
@ -655,6 +687,9 @@ on_error:
|
||||
/* This changes primary device only */
|
||||
void cmd_change_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
const char *error_str;
|
||||
|
||||
if (argc != 2) {
|
||||
@ -705,6 +740,9 @@ on_error:
|
||||
|
||||
void cmd_ccur_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
const char *error_str;
|
||||
|
||||
if (argc != 2) {
|
||||
@ -782,6 +820,9 @@ on_error:
|
||||
|
||||
void cmd_mute(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
const char *error_str;
|
||||
|
||||
if (argc != 1) {
|
||||
@ -835,6 +876,9 @@ on_error:
|
||||
|
||||
void cmd_sense(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
const char *error_str;
|
||||
|
||||
if (argc != 1) {
|
||||
@ -869,6 +913,9 @@ on_error:
|
||||
|
||||
void cmd_bitrate(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
char *error_str;
|
||||
|
||||
if (argc != 1) {
|
||||
@ -919,8 +966,9 @@ on_error:
|
||||
|
||||
void stop_current_call(ToxWindow *self)
|
||||
{
|
||||
toxav_call_control(CallControl.av, self->num, TOXAV_CALL_CONTROL_CANCEL, NULL);
|
||||
|
||||
if (CallControl.pending_call) {
|
||||
toxav_call_control(CallControl.av, self->num, TOXAV_CALL_CONTROL_CANCEL, NULL);
|
||||
callback_call_canceled(self->num);
|
||||
} else {
|
||||
stop_transmission(&CallControl.calls[self->num], self->num);
|
||||
|
@ -28,18 +28,14 @@
|
||||
|
||||
#include "line_info.h"
|
||||
#include "settings.h"
|
||||
#include "misc_tools.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <OpenAL/al.h>
|
||||
#include <OpenAL/alc.h>
|
||||
#else
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
/* compatibility with older versions of OpenAL */
|
||||
#ifndef ALC_ALL_DEVICES_SPECIFIER
|
||||
#include <AL/alext.h>
|
||||
#endif /* ALC_ALL_DEVICES_SPECIFIER */
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
@ -461,7 +457,7 @@ void *thread_poll(void *arg) // TODO: maybe use thread for every input source
|
||||
/*
|
||||
* NOTE: We only need to poll input devices for data.
|
||||
*/
|
||||
(void)arg;
|
||||
UNUSED_VAR(arg);
|
||||
uint32_t i;
|
||||
int32_t sample = 0;
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
#define OPENAL_BUFS 5
|
||||
#define MAX_DEVICES 32
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
typedef enum DeviceType {
|
||||
|
@ -61,6 +61,8 @@ static void print_matches(ToxWindow *self, Tox *m, const void *list, size_t n_it
|
||||
*/
|
||||
static size_t get_str_match(ToxWindow *self, char *match, size_t match_sz, char (*matches)[MAX_STR_SIZE], int n)
|
||||
{
|
||||
UNUSED_VAR(self);
|
||||
|
||||
if (n == 1) {
|
||||
return snprintf(match, match_sz, "%s", matches[0]);
|
||||
}
|
||||
@ -126,7 +128,7 @@ static int complete_line_helper(ToxWindow *self, const void *list, size_t n_item
|
||||
snprintf(tmp, sizeof(tmp), "%s", ubuf);
|
||||
tmp[ctx->pos] = '\0';
|
||||
|
||||
const char *s = strrchr(tmp, ' ');
|
||||
const char *s = dir_search ? strchr(tmp, ' ') : strrchr(tmp, ' ');
|
||||
char *sub = calloc(1, strlen(ubuf) + 1);
|
||||
|
||||
if (sub == NULL) {
|
||||
@ -219,12 +221,22 @@ static int complete_line_helper(ToxWindow *self, const void *list, size_t n_item
|
||||
|
||||
/* If path points to a file with no extension don't append a forward slash */
|
||||
if (dir_search && *endchrs == '/') {
|
||||
const char *path_start = strchr(ubuf+1, '/');
|
||||
const char *path_start = strchr(ubuf + 1, '/');
|
||||
|
||||
if (!path_start) { // should never happen
|
||||
if (!path_start) {
|
||||
path_start = strchr(ubuf + 1, ' ');
|
||||
|
||||
if (!path_start) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(path_start) < 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
++path_start;
|
||||
|
||||
if (file_type(path_start) == FILE_TYPE_REGULAR) {
|
||||
endchrs = "";
|
||||
diff -= n_endchrs;
|
||||
@ -269,7 +281,7 @@ static void complete_home_dir(ToxWindow *self, char *path, int pathsize, const c
|
||||
|
||||
char newline[MAX_STR_SIZE];
|
||||
snprintf(newline, sizeof(newline), "%s %s%s", cmd, homedir, path + 1);
|
||||
snprintf(path, pathsize, "%s", &newline[cmdlen-1]);
|
||||
snprintf(path, pathsize, "%s", &newline[cmdlen - 1]);
|
||||
|
||||
wchar_t wline[MAX_STR_SIZE];
|
||||
|
||||
|
@ -112,7 +112,7 @@ int avatar_set(Tox *m, const char *path, size_t path_len)
|
||||
return -1;
|
||||
}
|
||||
|
||||
char PNG_signature[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
|
||||
unsigned char PNG_signature[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
|
||||
|
||||
if (check_file_signature(PNG_signature, sizeof(PNG_signature), fp) != 0) {
|
||||
fclose(fp);
|
||||
|
@ -430,6 +430,8 @@ static int extract_node(const char *line, struct Node *node)
|
||||
/* Loads the DHT nodeslist to memory from json encoded nodes file. */
|
||||
void *load_nodeslist_thread(void *data)
|
||||
{
|
||||
UNUSED_VAR(data);
|
||||
|
||||
char nodes_path[PATH_MAX];
|
||||
get_nodeslist_path(nodes_path, sizeof(nodes_path));
|
||||
|
||||
|
94
src/chat.c
94
src/chat.c
@ -172,8 +172,7 @@ void kill_chat_window(ToxWindow *self, Tox *m)
|
||||
del_window(self);
|
||||
}
|
||||
|
||||
static void recv_message_helper(ToxWindow *self, Tox *m, uint32_t num, const char *msg, size_t len,
|
||||
const char *nick, const char *timefrmt)
|
||||
static void recv_message_helper(ToxWindow *self, const char *msg, const char *nick, const char *timefrmt)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
@ -189,8 +188,7 @@ static void recv_message_helper(ToxWindow *self, Tox *m, uint32_t num, const cha
|
||||
}
|
||||
}
|
||||
|
||||
static void recv_action_helper(ToxWindow *self, Tox *m, uint32_t num, const char *action, size_t len,
|
||||
const char *nick, const char *timefrmt)
|
||||
static void recv_action_helper(ToxWindow *self, const char *action, const char *nick, const char *timefrmt)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
@ -208,6 +206,8 @@ static void recv_action_helper(ToxWindow *self, Tox *m, uint32_t num, const char
|
||||
|
||||
static void chat_onMessage(ToxWindow *self, Tox *m, uint32_t num, Tox_Message_Type type, const char *msg, size_t len)
|
||||
{
|
||||
UNUSED_VAR(len);
|
||||
|
||||
if (self->num != num) {
|
||||
return;
|
||||
}
|
||||
@ -219,17 +219,17 @@ static void chat_onMessage(ToxWindow *self, Tox *m, uint32_t num, Tox_Message_Ty
|
||||
get_time_str(timefrmt, sizeof(timefrmt));
|
||||
|
||||
if (type == TOX_MESSAGE_TYPE_NORMAL) {
|
||||
recv_message_helper(self, m, num, msg, len, nick, timefrmt);
|
||||
recv_message_helper(self, msg, nick, timefrmt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == TOX_MESSAGE_TYPE_ACTION) {
|
||||
recv_action_helper(self, m, num, msg, len, nick, timefrmt);
|
||||
recv_action_helper(self, msg, nick, timefrmt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void chat_pause_file_transfers(Tox *m, uint32_t friendnum);
|
||||
static void chat_pause_file_transfers(uint32_t friendnum);
|
||||
static void chat_resume_file_senders(ToxWindow *self, Tox *m, uint32_t fnum);
|
||||
|
||||
static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, Tox_Connection connection_status)
|
||||
@ -268,7 +268,7 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, Tox_C
|
||||
set_self_typingstatus(self, m, 0);
|
||||
}
|
||||
|
||||
chat_pause_file_transfers(m, num);
|
||||
chat_pause_file_transfers(num);
|
||||
|
||||
msg = "has gone offline";
|
||||
line_info_add(self, timefrmt, nick, NULL, DISCONNECTION, 0, RED, msg);
|
||||
@ -278,6 +278,8 @@ static void chat_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, Tox_C
|
||||
|
||||
static void chat_onTypingChange(ToxWindow *self, Tox *m, uint32_t num, bool is_typing)
|
||||
{
|
||||
UNUSED_VAR(m);
|
||||
|
||||
if (self->num != num) {
|
||||
return;
|
||||
}
|
||||
@ -287,6 +289,8 @@ static void chat_onTypingChange(ToxWindow *self, Tox *m, uint32_t num, bool is_t
|
||||
|
||||
static void chat_onNickChange(ToxWindow *self, Tox *m, uint32_t num, const char *nick, size_t length)
|
||||
{
|
||||
UNUSED_VAR(m);
|
||||
|
||||
if (self->num != num) {
|
||||
return;
|
||||
}
|
||||
@ -302,6 +306,8 @@ static void chat_onNickChange(ToxWindow *self, Tox *m, uint32_t num, const char
|
||||
|
||||
static void chat_onStatusChange(ToxWindow *self, Tox *m, uint32_t num, Tox_User_Status status)
|
||||
{
|
||||
UNUSED_VAR(m);
|
||||
|
||||
if (self->num != num) {
|
||||
return;
|
||||
}
|
||||
@ -312,6 +318,8 @@ static void chat_onStatusChange(ToxWindow *self, Tox *m, uint32_t num, Tox_User_
|
||||
|
||||
static void chat_onStatusMessageChange(ToxWindow *self, uint32_t num, const char *status, size_t length)
|
||||
{
|
||||
UNUSED_VAR(length);
|
||||
|
||||
if (self->num != num) {
|
||||
return;
|
||||
}
|
||||
@ -324,11 +332,13 @@ static void chat_onStatusMessageChange(ToxWindow *self, uint32_t num, const char
|
||||
|
||||
static void chat_onReadReceipt(ToxWindow *self, Tox *m, uint32_t num, uint32_t receipt)
|
||||
{
|
||||
UNUSED_VAR(num);
|
||||
|
||||
cqueue_remove(self, m, receipt);
|
||||
}
|
||||
|
||||
/* Stops active file transfers for this friend. Called when a friend goes offline */
|
||||
static void chat_pause_file_transfers(Tox *m, uint32_t friendnum)
|
||||
static void chat_pause_file_transfers(uint32_t friendnum)
|
||||
{
|
||||
ToxicFriend *friend = &Friends.list[friendnum];
|
||||
|
||||
@ -436,6 +446,8 @@ static void chat_onFileChunkRequest(ToxWindow *self, Tox *m, uint32_t friendnum,
|
||||
static void chat_onFileRecvChunk(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_t filenum, uint64_t position,
|
||||
const char *data, size_t length)
|
||||
{
|
||||
UNUSED_VAR(position);
|
||||
|
||||
if (friendnum != self->num) {
|
||||
return;
|
||||
}
|
||||
@ -704,6 +716,9 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, ui
|
||||
|
||||
void chat_onInvite(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(state);
|
||||
|
||||
if (!self || self->num != friend_number) {
|
||||
return;
|
||||
}
|
||||
@ -726,6 +741,9 @@ void chat_onInvite(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state
|
||||
|
||||
void chat_onRinging(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(state);
|
||||
|
||||
if (!self || self->num != friend_number) {
|
||||
return;
|
||||
}
|
||||
@ -743,6 +761,9 @@ void chat_onRinging(ToxWindow *self, ToxAV *av, uint32_t friend_number, int stat
|
||||
|
||||
void chat_onStarting(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(state);
|
||||
|
||||
if (!self || self->num != friend_number) {
|
||||
return;
|
||||
}
|
||||
@ -761,6 +782,9 @@ void chat_onStarting(ToxWindow *self, ToxAV *av, uint32_t friend_number, int sta
|
||||
|
||||
void chat_onEnding(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(state);
|
||||
|
||||
if (!self || self->num != friend_number) {
|
||||
return;
|
||||
}
|
||||
@ -777,6 +801,9 @@ void chat_onEnding(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state
|
||||
|
||||
void chat_onError(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(state);
|
||||
|
||||
if (!self || self->num != friend_number) {
|
||||
return;
|
||||
}
|
||||
@ -791,6 +818,9 @@ void chat_onError(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
|
||||
void chat_onStart(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(state);
|
||||
|
||||
if (!self || self->num != friend_number) {
|
||||
return;
|
||||
}
|
||||
@ -809,6 +839,9 @@ void chat_onStart(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
|
||||
void chat_onCancel(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(state);
|
||||
|
||||
if (!self || self->num != friend_number) {
|
||||
return;
|
||||
}
|
||||
@ -824,6 +857,9 @@ void chat_onCancel(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state
|
||||
|
||||
void chat_onReject(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(state);
|
||||
|
||||
if (!self || self->num != friend_number) {
|
||||
return;
|
||||
}
|
||||
@ -838,6 +874,9 @@ void chat_onReject(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state
|
||||
|
||||
void chat_onEnd(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(state);
|
||||
|
||||
if (!self || self->num != friend_number) {
|
||||
return;
|
||||
}
|
||||
@ -862,7 +901,7 @@ static void init_infobox(ToxWindow *self)
|
||||
return;
|
||||
}
|
||||
|
||||
(void) y2;
|
||||
UNUSED_VAR(y2);
|
||||
|
||||
memset(&ctx->infobox, 0, sizeof(struct infobox));
|
||||
|
||||
@ -963,7 +1002,10 @@ static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *action)
|
||||
cqueue_add(ctx->cqueue, action, strlen(action), OUT_ACTION, id);
|
||||
}
|
||||
|
||||
static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
/*
|
||||
* Return true if input is recognized by handler
|
||||
*/
|
||||
bool chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
StatusBar *statusbar = self->stb;
|
||||
@ -972,8 +1014,10 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
getyx(self->window, y, x);
|
||||
getmaxyx(self->window, y2, x2);
|
||||
|
||||
UNUSED_VAR(y);
|
||||
|
||||
if (y2 <= 0 || x2 <= 0) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx->pastemode && key == '\r') {
|
||||
@ -982,26 +1026,31 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
if (self->help->active) {
|
||||
help_onKey(self, key);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ltr || key == '\n') { /* char is printable */
|
||||
input_new_char(self, key, x, y, x2, y2);
|
||||
input_new_char(self, key, x, x2);
|
||||
|
||||
if (ctx->line[0] != '/' && !ctx->self_is_typing && statusbar->connection != TOX_CONNECTION_NONE) {
|
||||
set_self_typingstatus(self, m, 1);
|
||||
}
|
||||
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (line_info_onKey(self, key)) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
input_handle(self, key, x, y, x2, y2);
|
||||
if (input_handle(self, key, x, x2)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int input_ret = false;
|
||||
|
||||
if (key == '\t' && ctx->len > 1 && ctx->line[0] == '/') { /* TAB key: auto-complete */
|
||||
input_ret = true;
|
||||
int diff = -1;
|
||||
|
||||
/* TODO: make this not suck */
|
||||
@ -1039,6 +1088,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
}
|
||||
|
||||
} else if (key == '\r') {
|
||||
input_ret = true;
|
||||
rm_trailing_spaces_buf(ctx);
|
||||
|
||||
if (!wstring_is_empty(ctx->line)) {
|
||||
@ -1055,7 +1105,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
if (line[0] == '/') {
|
||||
if (strcmp(line, "/close") == 0) {
|
||||
kill_chat_window(self, m);
|
||||
return;
|
||||
return input_ret;
|
||||
} else if (strncmp(line, "/me ", strlen("/me ")) == 0) {
|
||||
send_action(self, ctx, m, line + strlen("/me "));
|
||||
} else {
|
||||
@ -1084,6 +1134,8 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
if (ctx->len <= 0 && ctx->self_is_typing) {
|
||||
set_self_typingstatus(self, m, 0);
|
||||
}
|
||||
|
||||
return input_ret;
|
||||
}
|
||||
|
||||
static void chat_onDraw(ToxWindow *self, Tox *m)
|
||||
@ -1200,7 +1252,9 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
|
||||
|
||||
int y, x;
|
||||
getyx(self->window, y, x);
|
||||
(void) 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);
|
||||
|
||||
@ -1219,7 +1273,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
refresh_file_transfer_progress(self, m, self->num);
|
||||
refresh_file_transfer_progress(self, self->num);
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,8 @@ extern FriendsList Friends;
|
||||
|
||||
void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
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.");
|
||||
return;
|
||||
@ -80,6 +82,8 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
|
||||
|
||||
void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
if (argc < 1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group number required.");
|
||||
return;
|
||||
@ -104,6 +108,10 @@ void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
|
||||
|
||||
void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(argc);
|
||||
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.");
|
||||
return;
|
||||
@ -132,7 +140,7 @@ void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
|
||||
return;
|
||||
}
|
||||
|
||||
if (init_groupchat_win(prompt, m, groupnum, type) == -1) {
|
||||
if (init_groupchat_win(m, groupnum, type, NULL, 0) == -1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
|
||||
tox_conference_delete(m, groupnum, NULL);
|
||||
return;
|
||||
@ -142,6 +150,8 @@ void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
|
||||
|
||||
void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
if (argc < 1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File ID required.");
|
||||
return;
|
||||
@ -218,6 +228,8 @@ on_recv_error:
|
||||
|
||||
void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
const char *errmsg = NULL;
|
||||
|
||||
if (argc < 1) {
|
||||
|
@ -122,8 +122,8 @@ static const char special_commands[SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = {
|
||||
#ifdef PYTHON
|
||||
"/run",
|
||||
#endif /* PYTHON */
|
||||
"/title",
|
||||
"/sendfile",
|
||||
"/title",
|
||||
};
|
||||
|
||||
/* Returns true if input command is in the special_commands array. */
|
||||
@ -145,7 +145,7 @@ static bool is_special_command(const char *input)
|
||||
*
|
||||
* Returns the number of arguments.
|
||||
*/
|
||||
static int parse_special_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
|
||||
static int parse_special_command(const char *input, char (*args)[MAX_STR_SIZE])
|
||||
{
|
||||
int len = strlen(input);
|
||||
int s = char_find(0, input, ' ');
|
||||
@ -167,10 +167,10 @@ static int parse_special_command(WINDOW *w, ToxWindow *self, const char *input,
|
||||
*
|
||||
* Returns the number of arguments.
|
||||
*/
|
||||
static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
|
||||
static int parse_command(const char *input, char (*args)[MAX_STR_SIZE])
|
||||
{
|
||||
if (is_special_command(input)) {
|
||||
return parse_special_command(w, self, input, args);
|
||||
return parse_special_command(input, args);
|
||||
}
|
||||
|
||||
char *cmd = strdup(input);
|
||||
@ -227,7 +227,7 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
|
||||
}
|
||||
|
||||
char args[MAX_NUM_ARGS][MAX_STR_SIZE];
|
||||
int num_args = parse_command(w, self, input, args);
|
||||
int num_args = parse_command(input, args);
|
||||
|
||||
if (num_args <= 0) {
|
||||
return;
|
||||
|
@ -87,7 +87,7 @@ void print_progress_bar(ToxWindow *self, double bps, double pct_done, uint32_t l
|
||||
line_info_set(self, line_id, full_line);
|
||||
}
|
||||
|
||||
static void refresh_progress_helper(ToxWindow *self, Tox *m, struct FileTransfer *ft)
|
||||
static void refresh_progress_helper(ToxWindow *self, struct FileTransfer *ft)
|
||||
{
|
||||
if (ft->state == FILE_TRANSFER_INACTIVE) {
|
||||
return;
|
||||
@ -107,13 +107,13 @@ static void refresh_progress_helper(ToxWindow *self, Tox *m, struct FileTransfer
|
||||
}
|
||||
|
||||
/* refreshes active file transfer status bars. */
|
||||
void refresh_file_transfer_progress(ToxWindow *self, Tox *m, uint32_t friendnum)
|
||||
void refresh_file_transfer_progress(ToxWindow *self, uint32_t friendnum)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < MAX_FILES; ++i) {
|
||||
refresh_progress_helper(self, m, &Friends.list[friendnum].file_receiver[i]);
|
||||
refresh_progress_helper(self, m, &Friends.list[friendnum].file_sender[i]);
|
||||
refresh_progress_helper(self, &Friends.list[friendnum].file_receiver[i]);
|
||||
refresh_progress_helper(self, &Friends.list[friendnum].file_sender[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ void init_progress_bar(char *progline);
|
||||
void print_progress_bar(ToxWindow *self, double pct_done, double bps, uint32_t line_id);
|
||||
|
||||
/* refreshes active file transfer status bars. */
|
||||
void refresh_file_transfer_progress(ToxWindow *self, Tox *m, uint32_t friendnum);
|
||||
void refresh_file_transfer_progress(ToxWindow *self, uint32_t friendnum);
|
||||
|
||||
/* Returns a pointer to friendnum's FileTransfer struct associated with filenum.
|
||||
* Returns NULL if filenum is invalid.
|
||||
|
@ -308,7 +308,9 @@ void sort_friendlist_index(void)
|
||||
}
|
||||
}
|
||||
|
||||
qsort(Friends.index, Friends.num_friends, sizeof(uint32_t), index_name_cmp);
|
||||
if (Friends.num_friends > 0) {
|
||||
qsort(Friends.index, Friends.num_friends, sizeof(uint32_t), index_name_cmp);
|
||||
}
|
||||
}
|
||||
|
||||
static int index_name_cmp_block(const void *n1, const void *n2)
|
||||
@ -344,6 +346,10 @@ static void update_friend_last_online(uint32_t num, time_t timestamp)
|
||||
static void friendlist_onMessage(ToxWindow *self, Tox *m, uint32_t num, Tox_Message_Type type, const char *str,
|
||||
size_t length)
|
||||
{
|
||||
UNUSED_VAR(self);
|
||||
UNUSED_VAR(type);
|
||||
UNUSED_VAR(length);
|
||||
|
||||
if (num >= Friends.max_idx) {
|
||||
return;
|
||||
}
|
||||
@ -370,6 +376,8 @@ static void friendlist_onMessage(ToxWindow *self, Tox *m, uint32_t num, Tox_Mess
|
||||
|
||||
static void friendlist_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num, Tox_Connection connection_status)
|
||||
{
|
||||
UNUSED_VAR(self);
|
||||
|
||||
if (num >= Friends.max_idx) {
|
||||
return;
|
||||
}
|
||||
@ -392,6 +400,9 @@ static void friendlist_onConnectionChange(ToxWindow *self, Tox *m, uint32_t num,
|
||||
|
||||
static void friendlist_onNickChange(ToxWindow *self, Tox *m, uint32_t num, const char *nick, size_t length)
|
||||
{
|
||||
UNUSED_VAR(self);
|
||||
UNUSED_VAR(length);
|
||||
|
||||
if (num >= Friends.max_idx) {
|
||||
return;
|
||||
}
|
||||
@ -419,6 +430,9 @@ static void friendlist_onNickChange(ToxWindow *self, Tox *m, uint32_t num, const
|
||||
|
||||
static void friendlist_onStatusChange(ToxWindow *self, Tox *m, uint32_t num, Tox_User_Status status)
|
||||
{
|
||||
UNUSED_VAR(self);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
if (num >= Friends.max_idx) {
|
||||
return;
|
||||
}
|
||||
@ -428,6 +442,8 @@ static void friendlist_onStatusChange(ToxWindow *self, Tox *m, uint32_t num, Tox
|
||||
|
||||
static void friendlist_onStatusMessageChange(ToxWindow *self, uint32_t num, const char *note, size_t length)
|
||||
{
|
||||
UNUSED_VAR(self);
|
||||
|
||||
if (length > TOX_MAX_STATUS_MESSAGE_LENGTH || num >= Friends.max_idx) {
|
||||
return;
|
||||
}
|
||||
@ -438,6 +454,8 @@ static void friendlist_onStatusMessageChange(ToxWindow *self, uint32_t num, cons
|
||||
|
||||
void friendlist_onFriendAdded(ToxWindow *self, Tox *m, uint32_t num, bool sort)
|
||||
{
|
||||
UNUSED_VAR(self);
|
||||
|
||||
realloc_friends(Friends.max_idx + 1);
|
||||
memset(&Friends.list[Friends.max_idx], 0, sizeof(ToxicFriend));
|
||||
|
||||
@ -495,7 +513,7 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, uint32_t num, bool sort)
|
||||
}
|
||||
|
||||
/* Puts blocked friend back in friendlist. fnum is new friend number, bnum is blocked number. */
|
||||
static void friendlist_add_blocked(Tox *m, uint32_t fnum, uint32_t bnum)
|
||||
static void friendlist_add_blocked(uint32_t fnum, uint32_t bnum)
|
||||
{
|
||||
realloc_friends(Friends.max_idx + 1);
|
||||
memset(&Friends.list[Friends.max_idx], 0, sizeof(ToxicFriend));
|
||||
@ -536,6 +554,11 @@ static void friendlist_add_blocked(Tox *m, uint32_t fnum, uint32_t bnum)
|
||||
static void friendlist_onFileRecv(ToxWindow *self, Tox *m, uint32_t num, uint32_t filenum,
|
||||
uint64_t file_size, const char *filename, size_t name_length)
|
||||
{
|
||||
UNUSED_VAR(self);
|
||||
UNUSED_VAR(file_size);
|
||||
UNUSED_VAR(filename);
|
||||
UNUSED_VAR(name_length);
|
||||
|
||||
if (num >= Friends.max_idx) {
|
||||
return;
|
||||
}
|
||||
@ -563,6 +586,11 @@ static void friendlist_onFileRecv(ToxWindow *self, Tox *m, uint32_t num, uint32_
|
||||
static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, uint8_t type, const char *group_pub_key,
|
||||
uint16_t length)
|
||||
{
|
||||
UNUSED_VAR(self);
|
||||
UNUSED_VAR(type);
|
||||
UNUSED_VAR(group_pub_key);
|
||||
UNUSED_VAR(length);
|
||||
|
||||
if (num >= Friends.max_idx) {
|
||||
return;
|
||||
}
|
||||
@ -586,7 +614,7 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, uint8
|
||||
}
|
||||
|
||||
/* move friendlist/blocklist cursor up and down */
|
||||
static void select_friend(ToxWindow *self, wint_t key, int *selected, int num)
|
||||
static void select_friend(wint_t key, int *selected, int num)
|
||||
{
|
||||
if (num <= 0) {
|
||||
return;
|
||||
@ -656,7 +684,7 @@ static void delete_friend(Tox *m, uint32_t f_num)
|
||||
}
|
||||
|
||||
/* activates delete friend popup */
|
||||
static void del_friend_activate(ToxWindow *self, Tox *m, uint32_t f_num)
|
||||
static void del_friend_activate(uint32_t f_num)
|
||||
{
|
||||
PendingDelete.popup = newwin(3, 22 + TOXIC_MAX_NAME_LENGTH, 8, 8);
|
||||
PendingDelete.active = true;
|
||||
@ -666,7 +694,7 @@ static void del_friend_activate(ToxWindow *self, Tox *m, uint32_t f_num)
|
||||
static void delete_blocked_friend(uint32_t bnum);
|
||||
|
||||
/* deactivates delete friend popup and deletes friend if instructed */
|
||||
static void del_friend_deactivate(ToxWindow *self, Tox *m, wint_t key)
|
||||
static void del_friend_deactivate(Tox *m, wint_t key)
|
||||
{
|
||||
if (key == 'y') {
|
||||
if (blocklist_view == 0) {
|
||||
@ -791,31 +819,34 @@ static void unblock_friend(Tox *m, uint32_t bnum)
|
||||
return;
|
||||
}
|
||||
|
||||
friendlist_add_blocked(m, friendnum, bnum);
|
||||
friendlist_add_blocked(friendnum, bnum);
|
||||
delete_blocked_friend(bnum);
|
||||
sort_blocklist_index();
|
||||
sort_friendlist_index();
|
||||
}
|
||||
|
||||
static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
/*
|
||||
* Return true if input is recognized by handler
|
||||
*/
|
||||
static bool friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
{
|
||||
|
||||
if (self->help->active) {
|
||||
help_onKey(self, key);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key == 'h') {
|
||||
help_init_menu(self);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!blocklist_view && !Friends.num_friends && (key != KEY_RIGHT && key != KEY_LEFT)) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (blocklist_view && !Blocked.num_blocked && (key != KEY_RIGHT && key != KEY_LEFT)) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
int f = 0;
|
||||
@ -829,14 +860,14 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
/* lock screen and force decision on deletion popup */
|
||||
if (PendingDelete.active) {
|
||||
if (key == 'y' || key == 'n') {
|
||||
del_friend_deactivate(self, m, key);
|
||||
del_friend_deactivate(m, key);
|
||||
}
|
||||
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key == ltr) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
@ -860,7 +891,7 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
break;
|
||||
|
||||
case KEY_DC:
|
||||
del_friend_activate(self, m, f);
|
||||
del_friend_activate(f);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
@ -879,19 +910,23 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
default:
|
||||
if (blocklist_view == 0) {
|
||||
select_friend(self, key, &Friends.num_selected, Friends.num_friends);
|
||||
select_friend(key, &Friends.num_selected, Friends.num_friends);
|
||||
} else {
|
||||
select_friend(self, key, &Blocked.num_selected, Blocked.num_blocked);
|
||||
select_friend(key, &Blocked.num_selected, Blocked.num_blocked);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define FLIST_OFST 6 /* Accounts for space at top and bottom */
|
||||
|
||||
static void blocklist_onDraw(ToxWindow *self, Tox *m, int y2, int x2)
|
||||
{
|
||||
UNUSED_VAR(m);
|
||||
|
||||
wattron(self->window, A_BOLD);
|
||||
wprintw(self->window, " Blocked: ");
|
||||
wattroff(self->window, A_BOLD);
|
||||
@ -1199,13 +1234,12 @@ void disable_chatwin(uint32_t f_num)
|
||||
#ifdef AUDIO
|
||||
static void friendlist_onAV(ToxWindow *self, ToxAV *av, uint32_t friend_number, int state)
|
||||
{
|
||||
assert(0);
|
||||
UNUSED_VAR(self);
|
||||
|
||||
if (friend_number >= Friends.max_idx) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
Tox *m = toxav_get_tox(av);
|
||||
|
||||
if (Friends.list[friend_number].chatwin == -1) {
|
||||
@ -1240,6 +1274,26 @@ Tox_Connection get_friend_connection_status(uint32_t friendnumber)
|
||||
return Friends.list[friendnumber].connection_status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if friend associated with `public_key` is in the block list.
|
||||
*
|
||||
* `public_key` must be at least TOX_PUBLIC_KEY_SIZE bytes.
|
||||
*/
|
||||
bool friend_is_blocked(const char *public_key)
|
||||
{
|
||||
for (size_t i = 0; i < Blocked.max_idx; ++i) {
|
||||
if (!Blocked.list[i].active) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (memcmp(public_key, Blocked.list[i].pub_key, TOX_PUBLIC_KEY_SIZE) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ToxWindow *new_friendlist(void)
|
||||
{
|
||||
ToxWindow *ret = calloc(1, sizeof(ToxWindow));
|
||||
|
@ -93,4 +93,11 @@ Tox_Connection get_friend_connection_status(uint32_t friendnumber);
|
||||
/* sorts friendlist_index first by connection status then alphabetically */
|
||||
void sort_friendlist_index(void);
|
||||
|
||||
/*
|
||||
* Returns true if friend associated with `public_key` is in the block list.
|
||||
*
|
||||
* `public_key` must be at least TOX_PUBLIC_KEY_SIZE bytes.
|
||||
*/
|
||||
bool friend_is_blocked(const char *public_key);
|
||||
|
||||
#endif /* end of include guard: FRIENDLIST_H */
|
||||
|
@ -45,6 +45,8 @@ extern FriendsList Friends;
|
||||
/* command functions */
|
||||
void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
if (argc < 1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Request ID required.");
|
||||
return;
|
||||
@ -133,7 +135,7 @@ void cmd_add_helper(ToxWindow *self, Tox *m, const char *id_bin, const char *msg
|
||||
|
||||
/* fallthrough */
|
||||
default:
|
||||
errmsg = "Faile to add friend: Unknown error.";
|
||||
errmsg = "Failed to add friend: Unknown error.";
|
||||
break;
|
||||
}
|
||||
|
||||
@ -142,6 +144,8 @@ void cmd_add_helper(ToxWindow *self, Tox *m, const char *id_bin, const char *msg
|
||||
|
||||
void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
if (argc < 1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Tox ID or address required.");
|
||||
return;
|
||||
@ -193,6 +197,11 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
|
||||
id_bin[i] = x;
|
||||
}
|
||||
|
||||
if (friend_is_blocked(id_bin)) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Friend is in your block list.");
|
||||
return;
|
||||
}
|
||||
|
||||
cmd_add_helper(self, m, id_bin, msg);
|
||||
} else { /* assume id is a username@domain address and do http name server lookup */
|
||||
name_lookup(self, m, id_bin, id, msg);
|
||||
@ -201,6 +210,8 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
|
||||
|
||||
void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
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.");
|
||||
@ -232,12 +243,18 @@ void cmd_avatar(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
|
||||
void cmd_clear(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(m);
|
||||
UNUSED_VAR(argc);
|
||||
UNUSED_VAR(argv);
|
||||
|
||||
line_info_clear(self->chatwin->hst);
|
||||
force_refresh(window);
|
||||
}
|
||||
|
||||
void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
if (argc != 3) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Require: <ip> <port> <key>");
|
||||
return;
|
||||
@ -285,6 +302,9 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
|
||||
|
||||
void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
if (argc < 1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Request ID required.");
|
||||
return;
|
||||
@ -318,6 +338,8 @@ void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
|
||||
|
||||
void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
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.");
|
||||
return;
|
||||
@ -353,7 +375,7 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
|
||||
return;
|
||||
}
|
||||
|
||||
if (init_groupchat_win(prompt, m, groupnum, type) == -1) {
|
||||
if (init_groupchat_win(m, groupnum, type, NULL, 0) == -1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
|
||||
tox_conference_delete(m, groupnum, NULL);
|
||||
return;
|
||||
@ -364,6 +386,8 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
|
||||
|
||||
void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
const char *msg;
|
||||
struct chatlog *log = self->chatwin->log;
|
||||
|
||||
@ -416,6 +440,10 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
|
||||
|
||||
void cmd_myid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(argc);
|
||||
UNUSED_VAR(argv);
|
||||
|
||||
char id_string[TOX_ADDRESS_SIZE * 2 + 1];
|
||||
char bin_id[TOX_ADDRESS_SIZE];
|
||||
tox_self_get_address(m, (uint8_t *) bin_id);
|
||||
@ -431,6 +459,8 @@ void cmd_myid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
#ifdef QRCODE
|
||||
void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
char id_string[TOX_ADDRESS_SIZE * 2 + 1];
|
||||
char bin_id[TOX_ADDRESS_SIZE];
|
||||
tox_self_get_address(m, (uint8_t *) bin_id);
|
||||
@ -490,6 +520,8 @@ void cmd_myqr(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
|
||||
void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
if (argc < 1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Input required.");
|
||||
return;
|
||||
@ -515,6 +547,8 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
|
||||
void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
if (argc < 1) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Input required.");
|
||||
return;
|
||||
@ -550,16 +584,31 @@ void cmd_nospam(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
|
||||
void cmd_prompt_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
UNUSED_VAR(argc);
|
||||
UNUSED_VAR(argv);
|
||||
|
||||
help_init_menu(self);
|
||||
}
|
||||
|
||||
void cmd_quit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(argc);
|
||||
UNUSED_VAR(argv);
|
||||
UNUSED_VAR(self);
|
||||
|
||||
exit_toxic_success(m);
|
||||
}
|
||||
|
||||
void cmd_requests(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
UNUSED_VAR(argc);
|
||||
UNUSED_VAR(argv);
|
||||
|
||||
if (FrndRequests.num_requests == 0) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending friend requests.");
|
||||
return;
|
||||
@ -592,6 +641,8 @@ void cmd_requests(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
|
||||
void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
const char *errmsg;
|
||||
|
||||
lock_status();
|
||||
|
@ -30,13 +30,15 @@
|
||||
|
||||
void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
Tox_Err_Conference_Title err;
|
||||
char title[MAX_STR_SIZE];
|
||||
|
||||
if (argc < 1) {
|
||||
size_t tlen = tox_conference_get_title_size(m, self->num, &err);
|
||||
|
||||
if (err != TOX_ERR_CONFERENCE_TITLE_OK) {
|
||||
if (err != TOX_ERR_CONFERENCE_TITLE_OK || tlen >= sizeof(title)) {
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is not set");
|
||||
return;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <time.h>
|
||||
#include <wchar.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef AUDIO
|
||||
#ifdef __APPLE__
|
||||
@ -113,6 +114,8 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = {
|
||||
#endif /* PYTHON */
|
||||
};
|
||||
|
||||
static ToxWindow *new_group_chat(uint32_t groupnum);
|
||||
|
||||
static void kill_groupchat_window(ToxWindow *self)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
@ -128,13 +131,14 @@ static void kill_groupchat_window(ToxWindow *self)
|
||||
del_window(self);
|
||||
}
|
||||
|
||||
int init_groupchat_win(ToxWindow *prompt, Tox *m, uint32_t groupnum, uint8_t type)
|
||||
int init_groupchat_win(Tox *m, uint32_t groupnum, uint8_t type, const char *title,
|
||||
size_t title_length)
|
||||
{
|
||||
if (groupnum > MAX_GROUPCHAT_NUM) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ToxWindow *self = new_group_chat(m, groupnum);
|
||||
ToxWindow *self = new_group_chat(groupnum);
|
||||
|
||||
for (int i = 0; i <= max_groupchat_index; ++i) {
|
||||
if (!groupchats[i].active) {
|
||||
@ -145,6 +149,7 @@ int init_groupchat_win(ToxWindow *prompt, Tox *m, uint32_t groupnum, uint8_t typ
|
||||
groupchats[i].start_time = get_unix_time();
|
||||
|
||||
set_active_window_index(groupchats[i].chatwin);
|
||||
set_window_title(self, title, title_length);
|
||||
|
||||
if (i == max_groupchat_index) {
|
||||
++max_groupchat_index;
|
||||
@ -159,7 +164,7 @@ int init_groupchat_win(ToxWindow *prompt, Tox *m, uint32_t groupnum, uint8_t typ
|
||||
return -1;
|
||||
}
|
||||
|
||||
void free_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum)
|
||||
void free_groupchat(ToxWindow *self, uint32_t groupnum)
|
||||
{
|
||||
free(groupchats[groupnum].name_list);
|
||||
free(groupchats[groupnum].peer_list);
|
||||
@ -180,7 +185,7 @@ void free_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum)
|
||||
static void delete_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum)
|
||||
{
|
||||
tox_conference_delete(m, groupnum, NULL);
|
||||
free_groupchat(self, m, groupnum);
|
||||
free_groupchat(self, groupnum);
|
||||
}
|
||||
|
||||
/* destroys and re-creates groupchat window with or without the peerlist */
|
||||
@ -226,6 +231,8 @@ void redraw_groupchat_win(ToxWindow *self)
|
||||
static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, uint32_t groupnum, uint32_t peernum,
|
||||
Tox_Message_Type type, const char *msg, size_t len)
|
||||
{
|
||||
UNUSED_VAR(len);
|
||||
|
||||
if (self->num != groupnum) {
|
||||
return;
|
||||
}
|
||||
@ -298,7 +305,7 @@ static void group_update_name_list(uint32_t groupnum)
|
||||
{
|
||||
GroupChat *chat = &groupchats[groupnum];
|
||||
|
||||
if (!chat) {
|
||||
if (!chat->active) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -356,7 +363,7 @@ static void update_peer_list(Tox *m, uint32_t groupnum, uint32_t num_peers)
|
||||
{
|
||||
GroupChat *chat = &groupchats[groupnum];
|
||||
|
||||
if (!chat) {
|
||||
if (!chat->active) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -400,6 +407,11 @@ static void groupchat_onGroupNameListChange(ToxWindow *self, Tox *m, uint32_t gr
|
||||
}
|
||||
|
||||
GroupChat *chat = &groupchats[groupnum];
|
||||
|
||||
if (!chat->active) {
|
||||
return;
|
||||
}
|
||||
|
||||
Tox_Err_Conference_Peer_Query err;
|
||||
|
||||
uint32_t num_peers = tox_conference_peer_count(m, groupnum, &err);
|
||||
@ -418,17 +430,19 @@ static void groupchat_onGroupNameListChange(ToxWindow *self, Tox *m, uint32_t gr
|
||||
static void groupchat_onGroupPeerNameChange(ToxWindow *self, Tox *m, uint32_t groupnum, uint32_t peernum,
|
||||
const char *name, size_t length)
|
||||
{
|
||||
UNUSED_VAR(length);
|
||||
|
||||
if (self->num != groupnum) {
|
||||
return;
|
||||
}
|
||||
|
||||
GroupChat *chat = &groupchats[groupnum];
|
||||
|
||||
if (!chat) {
|
||||
if (!chat->active) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < chat->max_idx; ++i) {
|
||||
GroupPeer *peer = &chat->peer_list[i];
|
||||
@ -466,7 +480,10 @@ static void send_group_action(ToxWindow *self, ChatContext *ctx, Tox *m, char *a
|
||||
}
|
||||
}
|
||||
|
||||
static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
/*
|
||||
* Return true if input is recognized by handler
|
||||
*/
|
||||
static bool groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
@ -474,13 +491,15 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
getyx(self->window, y, x);
|
||||
getmaxyx(self->window, y2, x2);
|
||||
|
||||
UNUSED_VAR(y);
|
||||
|
||||
if (x2 <= 0 || y2 <= 0) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (self->help->active) {
|
||||
help_onKey(self, key);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ctx->pastemode && key == '\r') {
|
||||
@ -488,19 +507,23 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
}
|
||||
|
||||
if (ltr || key == '\n') { /* char is printable */
|
||||
input_new_char(self, key, x, y, x2, y2);
|
||||
return;
|
||||
input_new_char(self, key, x, x2);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (line_info_onKey(self, key)) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (input_handle(self, key, x, y, x2, y2)) {
|
||||
return;
|
||||
if (input_handle(self, key, x, x2)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool input_ret = false;
|
||||
|
||||
if (key == '\t') { /* TAB key: auto-completes peer name or command */
|
||||
input_ret = true;
|
||||
|
||||
if (ctx->len > 0) {
|
||||
int diff;
|
||||
|
||||
@ -518,7 +541,6 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
else {
|
||||
diff = complete_line(self, group_cmd_list, AC_NUM_GROUP_COMMANDS, MAX_CMDNAME_SIZE);
|
||||
}
|
||||
@ -534,17 +556,21 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
} else {
|
||||
sound_notify(self, notif_error, 0, NULL);
|
||||
}
|
||||
} else if (key == user_settings->key_peer_list_down) { /* Scroll peerlist up and down one position */
|
||||
int L = y2 - CHATBOX_HEIGHT - SDBAR_OFST;
|
||||
} else if (key == T_KEY_C_DOWN) { /* Scroll peerlist up and down one position */
|
||||
input_ret = true;
|
||||
const int L = y2 - CHATBOX_HEIGHT - SDBAR_OFST;
|
||||
|
||||
if (groupchats[self->num].side_pos < groupchats[self->num].num_peers - L) {
|
||||
if (groupchats[self->num].side_pos < (int64_t) groupchats[self->num].num_peers - L) {
|
||||
++groupchats[self->num].side_pos;
|
||||
}
|
||||
} else if (key == user_settings->key_peer_list_up) {
|
||||
} else if (key == T_KEY_C_UP) {
|
||||
input_ret = true;
|
||||
|
||||
if (groupchats[self->num].side_pos > 0) {
|
||||
--groupchats[self->num].side_pos;
|
||||
}
|
||||
} else if (key == '\r') {
|
||||
input_ret = true;
|
||||
rm_trailing_spaces_buf(ctx);
|
||||
|
||||
if (!wstring_is_empty(ctx->line)) {
|
||||
@ -561,7 +587,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
if (line[0] == '/') {
|
||||
if (strcmp(line, "/close") == 0) {
|
||||
delete_groupchat(self, m, self->num);
|
||||
return;
|
||||
return true;
|
||||
} else if (strncmp(line, "/me ", strlen("/me ")) == 0) {
|
||||
send_group_action(self, ctx, m, line + strlen("/me "));
|
||||
} else {
|
||||
@ -580,10 +606,14 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
reset_buf(ctx);
|
||||
}
|
||||
|
||||
return input_ret;
|
||||
}
|
||||
|
||||
static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
{
|
||||
UNUSED_VAR(m);
|
||||
|
||||
int x2, y2;
|
||||
getmaxyx(self->window, y2, x2);
|
||||
|
||||
@ -613,19 +643,19 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
mvwaddch(ctx->sidebar, y2 - CHATBOX_HEIGHT, 0, ACS_BTEE);
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
int num_peers = groupchats[self->num].num_peers;
|
||||
uint32_t num_peers = groupchats[self->num].num_peers;
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
wmove(ctx->sidebar, 0, 1);
|
||||
wattron(ctx->sidebar, A_BOLD);
|
||||
wprintw(ctx->sidebar, "Peers: %d\n", num_peers);
|
||||
wprintw(ctx->sidebar, "Peers: %"PRIu32"\n", num_peers);
|
||||
wattroff(ctx->sidebar, A_BOLD);
|
||||
|
||||
mvwaddch(ctx->sidebar, 1, 0, ACS_LTEE);
|
||||
mvwhline(ctx->sidebar, 1, 1, ACS_HLINE, SIDEBAR_WIDTH - 1);
|
||||
|
||||
int maxlines = y2 - SDBAR_OFST - CHATBOX_HEIGHT;
|
||||
int i;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < num_peers && i < maxlines; ++i) {
|
||||
wmove(ctx->sidebar, i + 2, 1);
|
||||
@ -650,7 +680,9 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
|
||||
int y, x;
|
||||
getyx(self->window, y, x);
|
||||
(void) 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);
|
||||
|
||||
@ -700,7 +732,7 @@ static void groupchat_onInit(ToxWindow *self, Tox *m)
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
}
|
||||
|
||||
ToxWindow *new_group_chat(Tox *m, uint32_t groupnum)
|
||||
static ToxWindow *new_group_chat(uint32_t groupnum)
|
||||
{
|
||||
ToxWindow *ret = calloc(1, sizeof(ToxWindow));
|
||||
|
||||
|
@ -46,21 +46,19 @@ typedef struct {
|
||||
time_t start_time;
|
||||
|
||||
GroupPeer *peer_list;
|
||||
size_t max_idx;
|
||||
uint32_t max_idx;
|
||||
|
||||
char *name_list;
|
||||
size_t num_peers;
|
||||
uint32_t num_peers;
|
||||
|
||||
} GroupChat;
|
||||
|
||||
/* Frees all Toxic associated data structures for a groupchat (does not call tox_conference_delete() ) */
|
||||
void free_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum);
|
||||
void free_groupchat(ToxWindow *self, uint32_t groupnum);
|
||||
|
||||
int init_groupchat_win(ToxWindow *prompt, Tox *m, uint32_t groupnum, uint8_t type);
|
||||
int init_groupchat_win(Tox *m, uint32_t groupnum, uint8_t type, const char *title, size_t title_length);
|
||||
|
||||
/* destroys and re-creates groupchat window with or without the peerlist */
|
||||
void redraw_groupchat_win(ToxWindow *self);
|
||||
|
||||
ToxWindow *new_group_chat(Tox *m, uint32_t groupnum);
|
||||
|
||||
#endif /* GROUPCHAT_H */
|
||||
|
@ -138,7 +138,8 @@ static void help_draw_bottom_menu(WINDOW *win)
|
||||
{
|
||||
int y2, x2;
|
||||
getmaxyx(win, y2, x2);
|
||||
(void) x2;
|
||||
|
||||
UNUSED_VAR(x2);
|
||||
|
||||
wmove(win, y2 - 2, 1);
|
||||
|
||||
@ -278,7 +279,7 @@ static void help_draw_keys(ToxWindow *self)
|
||||
wprintw(win, " Page Up and Page Down : Scroll window history one line\n");
|
||||
wprintw(win, " Ctrl+F and Ctrl+V : Scroll window history half a page\n");
|
||||
wprintw(win, " Ctrl+H : Move to the bottom of window history\n");
|
||||
wprintw(win, " Ctrl+[ and Ctrl+] : Scroll peer list in groupchats\n");
|
||||
wprintw(win, " Ctrl+up and Ctrl+down : Scroll peer list in groupchats\n");
|
||||
wprintw(win, " Ctrl+B : Toggle the groupchat peerlist\n");
|
||||
wprintw(win, " Ctrl+J : Insert new line\n");
|
||||
wprintw(win, " Ctrl+T : Toggle paste mode\n\n");
|
||||
|
74
src/input.c
74
src/input.c
@ -38,7 +38,7 @@
|
||||
extern struct user_settings *user_settings;
|
||||
|
||||
/* add a char to input field and buffer */
|
||||
void input_new_char(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y)
|
||||
void input_new_char(ToxWindow *self, wint_t key, int x, int mx_x)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
@ -94,13 +94,12 @@ static void input_delete(ToxWindow *self)
|
||||
}
|
||||
|
||||
/* delete last typed word */
|
||||
static void input_del_word(ToxWindow *self, int x, int mx_x)
|
||||
static void input_del_word(ToxWindow *self)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
if (del_word_buf(ctx) == -1) {
|
||||
sound_notify(self, notif_error, 0, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,7 +138,7 @@ static void input_yank(ToxWindow *self, int x, int mx_x)
|
||||
}
|
||||
|
||||
/* moves cursor/line position to end of line in input field and buffer */
|
||||
static void input_mv_end(ToxWindow *self, int y, int mx_x)
|
||||
static void input_mv_end(ToxWindow *self, int mx_x)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
@ -172,17 +171,41 @@ static void input_mv_left(ToxWindow *self, int x, int mx_x)
|
||||
}
|
||||
|
||||
int cur_len = ctx->pos > 0 ? wcwidth(ctx->line[ctx->pos - 1]) : 0;
|
||||
int s_len = ctx->start > 0 ? wcwidth(ctx->line[ctx->start - 1]) : 0;
|
||||
|
||||
--ctx->pos;
|
||||
|
||||
if (ctx->start && (x >= mx_x - cur_len)) {
|
||||
if (ctx->start > 0 && (x >= mx_x - cur_len)) {
|
||||
int s_len = wcwidth(ctx->line[ctx->start - 1]);
|
||||
ctx->start = MAX(0, ctx->start - 1 + (s_len - cur_len));
|
||||
} else if (ctx->start) {
|
||||
} else if (ctx->start > 0) {
|
||||
ctx->start = MAX(0, ctx->start - cur_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* moves the cursor to the beginning of the previous word in input field and buffer */
|
||||
static void input_skip_left(ToxWindow *self, int x, int mx_x)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
if (ctx->pos <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
do {
|
||||
--ctx->pos;
|
||||
count += wcwidth(ctx->line[ctx->pos]);
|
||||
} while (ctx->pos > 0 && (ctx->line[ctx->pos - 1] != L' ' || ctx->line[ctx->pos] == L' '));
|
||||
|
||||
if (ctx->start > 0 && (x >= mx_x - count)) {
|
||||
int s_len = wcwidth(ctx->line[ctx->start - 1]);
|
||||
ctx->start = MAX(0, ctx->start - 1 + (s_len - count));
|
||||
} else if (ctx->start > 0) {
|
||||
ctx->start = MAX(0, ctx->start - count);
|
||||
}
|
||||
}
|
||||
|
||||
/* moves cursor/line position right in input field and buffer */
|
||||
static void input_mv_right(ToxWindow *self, int x, int mx_x)
|
||||
{
|
||||
@ -202,6 +225,29 @@ static void input_mv_right(ToxWindow *self, int x, int mx_x)
|
||||
}
|
||||
}
|
||||
|
||||
/* moves the cursor to the end of the next word in input field and buffer */
|
||||
static void input_skip_right(ToxWindow *self, int x, int mx_x)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
if (ctx->pos >= ctx->len) {
|
||||
return;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
do {
|
||||
count += wcwidth(ctx->line[ctx->pos]);
|
||||
++ctx->pos;
|
||||
} while (ctx->pos < ctx->len && !(ctx->line[ctx->pos] == L' ' && ctx->line[ctx->pos - 1] != L' '));
|
||||
|
||||
int newpos = x + count;
|
||||
|
||||
if (newpos >= mx_x) {
|
||||
ctx->start += (1 + (newpos - mx_x));
|
||||
}
|
||||
}
|
||||
|
||||
/* puts a line history item in input field and buffer */
|
||||
static void input_history(ToxWindow *self, wint_t key, int mx_x)
|
||||
{
|
||||
@ -214,7 +260,7 @@ static void input_history(ToxWindow *self, wint_t key, int mx_x)
|
||||
|
||||
/* Handles non-printable input keys that behave the same for all types of chat windows.
|
||||
return true if key matches a function, false otherwise */
|
||||
bool input_handle(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y)
|
||||
bool input_handle(ToxWindow *self, wint_t key, int x, int mx_x)
|
||||
{
|
||||
bool match = true;
|
||||
|
||||
@ -241,7 +287,7 @@ bool input_handle(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y)
|
||||
break;
|
||||
|
||||
case T_KEY_C_W:
|
||||
input_del_word(self, x, mx_x);
|
||||
input_del_word(self);
|
||||
break;
|
||||
|
||||
case KEY_HOME:
|
||||
@ -251,7 +297,7 @@ bool input_handle(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y)
|
||||
|
||||
case KEY_END:
|
||||
case T_KEY_C_E:
|
||||
input_mv_end(self, y, mx_x);
|
||||
input_mv_end(self, mx_x);
|
||||
break;
|
||||
|
||||
case KEY_LEFT:
|
||||
@ -271,6 +317,14 @@ bool input_handle(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y)
|
||||
force_refresh(self->chatwin->history);
|
||||
break;
|
||||
|
||||
case T_KEY_C_LEFT:
|
||||
input_skip_left(self, x, mx_x);
|
||||
break;
|
||||
|
||||
case T_KEY_C_RIGHT:
|
||||
input_skip_right(self, x, mx_x);
|
||||
break;
|
||||
|
||||
default:
|
||||
match = false;
|
||||
break;
|
||||
|
@ -24,10 +24,10 @@
|
||||
#define INPUT_H
|
||||
|
||||
/* add a char to input field and buffer for given chatcontext */
|
||||
void input_new_char(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y);
|
||||
void input_new_char(ToxWindow *self, wint_t key, int x, int mx_x);
|
||||
|
||||
/* Handles non-printable input keys that behave the same for all types of chat windows.
|
||||
return true if key matches a function, false otherwise */
|
||||
bool input_handle(ToxWindow *self, wint_t key, int x, int y, int mx_x, int mx_y);
|
||||
bool input_handle(ToxWindow *self, wint_t key, int x, int mx_x);
|
||||
|
||||
#endif /* INPUT_H */
|
||||
|
@ -270,7 +270,8 @@ static void line_info_check_queue(ToxWindow *self)
|
||||
int y, y2, x, x2;
|
||||
getmaxyx(self->window, y2, x2);
|
||||
getyx(self->chatwin->history, y, x);
|
||||
(void) x;
|
||||
|
||||
UNUSED_VAR(x);
|
||||
|
||||
if (x2 <= SIDEBAR_WIDTH) {
|
||||
return;
|
||||
@ -381,7 +382,7 @@ void line_info_print(ToxWindow *self)
|
||||
|
||||
if (type == OUT_MSG && timed_out(line->timestamp, NOREAD_FLAG_TIMEOUT)) {
|
||||
wattron(win, COLOR_PAIR(RED));
|
||||
wprintw(win, " x", line->msg);
|
||||
wprintw(win, " x");
|
||||
wattroff(win, COLOR_PAIR(RED));
|
||||
|
||||
if (line->noread_flag == false) {
|
||||
@ -567,7 +568,9 @@ static void line_info_page_up(ToxWindow *self, struct history *hst)
|
||||
{
|
||||
int x2, y2;
|
||||
getmaxyx(self->window, y2, x2);
|
||||
(void) x2;
|
||||
|
||||
UNUSED_VAR(x2);
|
||||
|
||||
int jump_dist = y2 / 2;
|
||||
int i;
|
||||
|
||||
@ -580,7 +583,9 @@ static void line_info_page_down(ToxWindow *self, struct history *hst)
|
||||
{
|
||||
int x2, y2;
|
||||
getmaxyx(self->window, y2, x2);
|
||||
(void) x2;
|
||||
|
||||
UNUSED_VAR(x2);
|
||||
|
||||
int jump_dist = y2 / 2;
|
||||
int i;
|
||||
|
||||
|
@ -40,6 +40,13 @@
|
||||
extern ToxWindow *prompt;
|
||||
extern struct user_settings *user_settings;
|
||||
|
||||
void clear_screen(void)
|
||||
{
|
||||
if (system("clear") != 0) {
|
||||
fprintf(stderr, "Warning: system() failed to clear screen\n");
|
||||
}
|
||||
}
|
||||
|
||||
void hst_to_net(uint8_t *num, uint16_t numbytes)
|
||||
{
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
@ -491,16 +498,21 @@ bool file_exists(const char *path)
|
||||
File_Type file_type(const char *path)
|
||||
{
|
||||
struct stat s;
|
||||
stat(path, &s);
|
||||
|
||||
if (stat(path, &s) == -1) {
|
||||
return FILE_TYPE_OTHER;
|
||||
}
|
||||
|
||||
switch (s.st_mode & S_IFMT) {
|
||||
case S_IFDIR:
|
||||
return FILE_TYPE_DIRECTORY;
|
||||
|
||||
case S_IFREG:
|
||||
return FILE_TYPE_REGULAR;
|
||||
|
||||
default:
|
||||
return FILE_TYPE_OTHER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* returns file size. If file doesn't exist returns 0. */
|
||||
@ -519,7 +531,7 @@ off_t file_size(const char *path)
|
||||
Returns 0 if they are the same, 1 if they differ, and -1 on error.
|
||||
|
||||
On success this function will seek back to the beginning of fp */
|
||||
int check_file_signature(const char *signature, size_t size, FILE *fp)
|
||||
int check_file_signature(const unsigned char *signature, size_t size, FILE *fp)
|
||||
{
|
||||
char buf[size];
|
||||
|
||||
@ -539,6 +551,10 @@ int check_file_signature(const char *signature, size_t size, FILE *fp)
|
||||
/* sets window title in tab bar. */
|
||||
void set_window_title(ToxWindow *self, const char *title, int len)
|
||||
{
|
||||
if (len <= 0 || !title) {
|
||||
return;
|
||||
}
|
||||
|
||||
char cpy[TOXIC_MAX_NAME_LENGTH + 1];
|
||||
|
||||
if (self->is_groupchat) { /* keep groupnumber in title */
|
||||
|
@ -39,14 +39,17 @@
|
||||
#define net_to_host(x, y) hst_to_net(x, y)
|
||||
#endif
|
||||
|
||||
typedef enum File_Type
|
||||
{
|
||||
FILE_TYPE_REGULAR,
|
||||
FILE_TYPE_DIRECTORY,
|
||||
FILE_TYPE_OTHER,
|
||||
#define UNUSED_VAR(x) ((void) x)
|
||||
|
||||
typedef enum File_Type {
|
||||
FILE_TYPE_REGULAR,
|
||||
FILE_TYPE_DIRECTORY,
|
||||
FILE_TYPE_OTHER,
|
||||
} File_Type;
|
||||
|
||||
|
||||
void clear_screen(void);
|
||||
|
||||
void hst_to_net(uint8_t *num, uint16_t numbytes);
|
||||
|
||||
/*
|
||||
@ -170,7 +173,7 @@ off_t file_size(const char *path);
|
||||
Returns 0 if they are the same, 1 if they differ, and -1 on error.
|
||||
|
||||
On success this function will seek back to the beginning of fp */
|
||||
int check_file_signature(const char *signature, size_t size, FILE *fp);
|
||||
int check_file_signature(const unsigned char *signature, size_t size, FILE *fp);
|
||||
|
||||
/* sets window title in tab bar. */
|
||||
void set_window_title(ToxWindow *self, const char *title, int len);
|
||||
|
@ -233,6 +233,8 @@ static int process_response(struct Recv_Curl_Data *recv_data)
|
||||
|
||||
void *lookup_thread_func(void *data)
|
||||
{
|
||||
UNUSED_VAR(data);
|
||||
|
||||
ToxWindow *self = t_data.self;
|
||||
|
||||
char input_domain[MAX_STR_SIZE];
|
||||
@ -292,7 +294,7 @@ void *lookup_thread_func(void *data)
|
||||
int proxy_ret = set_curl_proxy(c_handle, arg_opts.proxy_address, arg_opts.proxy_port, arg_opts.proxy_type);
|
||||
|
||||
if (proxy_ret != 0) {
|
||||
lookup_error(self, "Failed to set proxy (error %d)\n");
|
||||
lookup_error(self, "Failed to set proxy (error %d)\n", proxy_ret);
|
||||
goto on_exit;
|
||||
}
|
||||
|
||||
|
@ -235,7 +235,7 @@ void graceful_clear(void)
|
||||
|
||||
void *do_playing(void *_p)
|
||||
{
|
||||
(void)_p;
|
||||
UNUSED_VAR(_p);
|
||||
|
||||
while (true) {
|
||||
control_lock();
|
||||
@ -334,7 +334,7 @@ int play_source(uint32_t source, uint32_t buffer, bool looping)
|
||||
#elif BOX_NOTIFY
|
||||
void *do_playing(void *_p)
|
||||
{
|
||||
(void)_p;
|
||||
UNUSED_VAR(_p);
|
||||
|
||||
while (true) {
|
||||
control_lock();
|
||||
|
@ -23,7 +23,7 @@
|
||||
#ifndef NOTIFY_H
|
||||
#define NOTIFY_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include "windows.h"
|
||||
|
||||
typedef enum _Notification {
|
||||
|
@ -343,4 +343,4 @@ int osx_video_read_device(uint8_t *y, uint8_t *u, uint8_t *v, uint16_t *width, u
|
||||
* End of C-interface for OSXVideo
|
||||
*/
|
||||
|
||||
#endif /* __OBJC__ */
|
||||
#endif /* __OBJC__ */
|
||||
|
41
src/prompt.c
41
src/prompt.c
@ -139,6 +139,8 @@ void kill_prompt_window(ToxWindow *self)
|
||||
/* callback: Updates own connection status in prompt statusbar */
|
||||
void on_self_connection_status(Tox *m, Tox_Connection connection_status, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(m);
|
||||
UNUSED_VAR(userdata);
|
||||
StatusBar *statusbar = prompt->stb;
|
||||
statusbar->connection = connection_status;
|
||||
}
|
||||
@ -210,7 +212,10 @@ static int add_friend_request(const char *public_key, const char *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
/*
|
||||
* Return true if input is recognized by handler
|
||||
*/
|
||||
static bool prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
{
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
@ -218,8 +223,10 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
getyx(self->window, y, x);
|
||||
getmaxyx(self->window, y2, x2);
|
||||
|
||||
UNUSED_VAR(y);
|
||||
|
||||
if (x2 <= 0 || y2 <= 0) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx->pastemode && key == '\r') {
|
||||
@ -229,21 +236,27 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
/* ignore non-menu related input if active */
|
||||
if (self->help->active) {
|
||||
help_onKey(self, key);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ltr || key == '\n') { /* char is printable */
|
||||
input_new_char(self, key, x, y, x2, y2);
|
||||
return;
|
||||
input_new_char(self, key, x, x2);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (line_info_onKey(self, key)) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
input_handle(self, key, x, y, x2, y2);
|
||||
if (input_handle(self, key, x, x2)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int input_ret = false;
|
||||
|
||||
if (key == '\t') { /* TAB key: auto-completes command */
|
||||
input_ret = true;
|
||||
|
||||
if (ctx->len > 1 && ctx->line[0] == '/') {
|
||||
int diff = -1;
|
||||
|
||||
@ -281,6 +294,8 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
sound_notify(self, notif_error, 0, NULL);
|
||||
}
|
||||
} else if (key == '\r') {
|
||||
input_ret = true;
|
||||
|
||||
rm_trailing_spaces_buf(ctx);
|
||||
|
||||
if (!wstring_is_empty(ctx->line)) {
|
||||
@ -301,6 +316,8 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
reset_buf(ctx);
|
||||
}
|
||||
|
||||
return input_ret;
|
||||
}
|
||||
|
||||
static void prompt_onDraw(ToxWindow *self, Tox *m)
|
||||
@ -414,7 +431,8 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
|
||||
|
||||
int y, x;
|
||||
getyx(self->window, y, x);
|
||||
(void) 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);
|
||||
@ -474,6 +492,9 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, uint32_t friendnu
|
||||
|
||||
static void prompt_onFriendRequest(ToxWindow *self, Tox *m, const char *key, const char *data, size_t length)
|
||||
{
|
||||
UNUSED_VAR(m);
|
||||
UNUSED_VAR(length);
|
||||
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
char timefrmt[TIME_STR_SIZE];
|
||||
@ -503,7 +524,7 @@ void prompt_init_statusbar(ToxWindow *self, Tox *m, bool first_time_run)
|
||||
exit_toxic_err("failed in prompt_init_statusbar", FATALERR_CURSES);
|
||||
}
|
||||
|
||||
(void) y2;
|
||||
UNUSED_VAR(y2);
|
||||
|
||||
/* Init statusbar info */
|
||||
StatusBar *statusbar = self->stb;
|
||||
@ -547,7 +568,7 @@ static void print_welcome_msg(ToxWindow *self)
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, " |_| \\___/_/\\_\\___\\____| v." TOXICVER);
|
||||
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "");
|
||||
|
||||
const char *msg = "Welcome to Toxic, a free, open source Tox-based instant messenging client.";
|
||||
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);
|
||||
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);
|
||||
|
@ -58,11 +58,13 @@ static struct ui_strings {
|
||||
const char *native_colors;
|
||||
const char *autolog;
|
||||
const char *history_size;
|
||||
const char *notification_timeout;
|
||||
const char *show_typing_self;
|
||||
const char *show_typing_other;
|
||||
const char *show_welcome_msg;
|
||||
const char *show_connection_msg;
|
||||
const char *nodeslist_update_freq;
|
||||
const char *autosave_freq;
|
||||
|
||||
const char *line_join;
|
||||
const char *line_quit;
|
||||
@ -85,11 +87,13 @@ static struct ui_strings {
|
||||
"native_colors",
|
||||
"autolog",
|
||||
"history_size",
|
||||
"notification_timeout",
|
||||
"show_typing_self",
|
||||
"show_typing_other",
|
||||
"show_welcome_msg",
|
||||
"show_connection_msg",
|
||||
"nodeslist_update_freq",
|
||||
"autosave_freq",
|
||||
"line_join",
|
||||
"line_quit",
|
||||
"line_alert",
|
||||
@ -112,11 +116,13 @@ 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->show_typing_self = SHOW_TYPING_ON;
|
||||
settings->show_typing_other = SHOW_TYPING_ON;
|
||||
settings->show_welcome_msg = SHOW_WELCOME_MSG_ON;
|
||||
settings->show_connection_msg = SHOW_CONNECTION_MSG_ON;
|
||||
settings->nodeslist_update_freq = 7;
|
||||
settings->autosave_freq = 600;
|
||||
|
||||
snprintf(settings->line_join, LINE_HINT_MAX + 1, "%s", LINE_JOIN);
|
||||
snprintf(settings->line_quit, LINE_HINT_MAX + 1, "%s", LINE_QUIT);
|
||||
@ -139,8 +145,6 @@ static const struct keys_strings {
|
||||
const char *half_page_up;
|
||||
const char *half_page_down;
|
||||
const char *page_bottom;
|
||||
const char *peer_list_up;
|
||||
const char *peer_list_down;
|
||||
const char *toggle_peerlist;
|
||||
const char *toggle_pastemode;
|
||||
} key_strings = {
|
||||
@ -152,8 +156,6 @@ static const struct keys_strings {
|
||||
"half_page_up",
|
||||
"half_page_down",
|
||||
"page_bottom",
|
||||
"peer_list_up",
|
||||
"peer_list_down",
|
||||
"toggle_peerlist",
|
||||
"toggle_paste_mode",
|
||||
};
|
||||
@ -168,8 +170,6 @@ static void key_defaults(struct user_settings *settings)
|
||||
settings->key_half_page_up = T_KEY_C_F;
|
||||
settings->key_half_page_down = T_KEY_C_V;
|
||||
settings->key_page_bottom = T_KEY_C_H;
|
||||
settings->key_peer_list_up = T_KEY_C_LB;
|
||||
settings->key_peer_list_down = T_KEY_C_RB;
|
||||
settings->key_toggle_peerlist = T_KEY_C_B;
|
||||
settings->key_toggle_pastemode = T_KEY_C_T;
|
||||
}
|
||||
@ -369,7 +369,9 @@ int settings_load(struct user_settings *s, const char *patharg)
|
||||
config_setting_lookup_bool(setting, ui_strings.show_connection_msg, &s->show_connection_msg);
|
||||
|
||||
config_setting_lookup_int(setting, ui_strings.history_size, &s->history_size);
|
||||
config_setting_lookup_int(setting, ui_strings.notification_timeout, &s->notification_timeout);
|
||||
config_setting_lookup_int(setting, ui_strings.nodeslist_update_freq, &s->nodeslist_update_freq);
|
||||
config_setting_lookup_int(setting, ui_strings.autosave_freq, &s->autosave_freq);
|
||||
|
||||
if (config_setting_lookup_string(setting, ui_strings.line_join, &str)) {
|
||||
snprintf(s->line_join, sizeof(s->line_join), "%s", str);
|
||||
@ -485,14 +487,6 @@ int settings_load(struct user_settings *s, const char *patharg)
|
||||
set_key_binding(&s->key_page_bottom, &tmp);
|
||||
}
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.peer_list_up, &tmp)) {
|
||||
set_key_binding(&s->key_peer_list_up, &tmp);
|
||||
}
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.peer_list_down, &tmp)) {
|
||||
set_key_binding(&s->key_peer_list_down, &tmp);
|
||||
}
|
||||
|
||||
if (config_setting_lookup_string(setting, key_strings.toggle_peerlist, &tmp)) {
|
||||
set_key_binding(&s->key_toggle_peerlist, &tmp);
|
||||
}
|
||||
|
@ -49,11 +49,13 @@ struct user_settings {
|
||||
|
||||
int colour_theme; /* boolean (0 for default toxic colours) */
|
||||
int history_size; /* int between MIN_HISTORY and MAX_HISTORY */
|
||||
int notification_timeout;
|
||||
int show_typing_self; /* boolean */
|
||||
int show_typing_other; /* boolean */
|
||||
int show_welcome_msg; /* boolean */
|
||||
int show_connection_msg; /* boolean */
|
||||
int nodeslist_update_freq; /* int (<= 0 to disable updates) */
|
||||
int autosave_freq; /* int (<= 0 to disable autosave) */
|
||||
|
||||
char line_join[LINE_HINT_MAX + 1];
|
||||
char line_quit[LINE_HINT_MAX + 1];
|
||||
@ -73,8 +75,6 @@ struct user_settings {
|
||||
int key_half_page_up;
|
||||
int key_half_page_down;
|
||||
int key_page_bottom;
|
||||
int key_peer_list_up;
|
||||
int key_peer_list_down;
|
||||
int key_toggle_peerlist;
|
||||
int key_toggle_pastemode;
|
||||
|
||||
|
@ -393,7 +393,7 @@ static void mplex_timer_handler(Tox *m)
|
||||
char status_str[MAX_STR_SIZE];
|
||||
char note_str[MAX_STR_SIZE];
|
||||
const char *status = new_status == TOX_USER_STATUS_AWAY ? "away" :
|
||||
new_status == TOX_USER_STATUS_BUSY ? "busy" : "online";
|
||||
new_status == TOX_USER_STATUS_BUSY ? "busy" : "online";
|
||||
snprintf(status_str, sizeof(status_str), "/status %s", status);
|
||||
snprintf(note_str, sizeof(status_str), "/note %s", new_note);
|
||||
|
||||
|
150
src/toxic.c
150
src/toxic.c
@ -94,7 +94,6 @@ ToxWindow *prompt = NULL;
|
||||
#define DATANAME "toxic_profile.tox"
|
||||
#define BLOCKNAME "toxic_blocklist"
|
||||
|
||||
#define AUTOSAVE_FREQ 600
|
||||
#define MIN_PASSWORD_LEN 6
|
||||
#define MAX_PASSWORD_LEN 64
|
||||
|
||||
@ -115,6 +114,8 @@ static time_t last_signal_time;
|
||||
|
||||
static void catch_SIGINT(int sig)
|
||||
{
|
||||
UNUSED_VAR(sig);
|
||||
|
||||
time_t cur_time = get_unix_time();
|
||||
|
||||
if (difftime(cur_time, last_signal_time) <= 1) {
|
||||
@ -126,7 +127,12 @@ static void catch_SIGINT(int sig)
|
||||
|
||||
static void catch_SIGSEGV(int sig)
|
||||
{
|
||||
freopen("/dev/tty", "w", stderr); // make sure stderr is enabled since we may have disabled it
|
||||
UNUSED_VAR(sig);
|
||||
|
||||
if (!freopen("/dev/tty", "w", stderr)) { // make sure stderr is enabled since we may have disabled it
|
||||
fprintf(stderr, "Warning: Failed to enable stderr\n");
|
||||
}
|
||||
|
||||
endwin();
|
||||
fprintf(stderr, "Caught SIGSEGV: Aborting toxic session.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
@ -134,6 +140,8 @@ static void catch_SIGSEGV(int sig)
|
||||
|
||||
static void flag_window_resize(int sig)
|
||||
{
|
||||
UNUSED_VAR(sig);
|
||||
|
||||
Winthread.flag_resize = 1;
|
||||
}
|
||||
|
||||
@ -166,9 +174,11 @@ void exit_toxic_success(Tox *m)
|
||||
{
|
||||
store_data(m, DATA_FILE);
|
||||
memset(&user_password, 0, sizeof(struct user_password));
|
||||
|
||||
terminate_notify();
|
||||
|
||||
kill_all_file_transfers(m);
|
||||
kill_all_windows(m);
|
||||
terminate_notify();
|
||||
|
||||
#ifdef AUDIO
|
||||
#ifdef VIDEO
|
||||
@ -183,6 +193,12 @@ void exit_toxic_success(Tox *m)
|
||||
|
||||
free_global_data();
|
||||
tox_kill(m);
|
||||
|
||||
if (arg_opts.log_fp != NULL) {
|
||||
fclose(arg_opts.log_fp);
|
||||
arg_opts.log_fp = NULL;
|
||||
}
|
||||
|
||||
endwin();
|
||||
curl_global_cleanup();
|
||||
|
||||
@ -199,12 +215,32 @@ void exit_toxic_success(Tox *m)
|
||||
void exit_toxic_err(const char *errmsg, int errcode)
|
||||
{
|
||||
free_global_data();
|
||||
freopen("/dev/tty", "w", stderr);
|
||||
|
||||
if (!freopen("/dev/tty", "w", stderr)) {
|
||||
fprintf(stderr, "Warning: Failed to open stderr\n");
|
||||
}
|
||||
|
||||
endwin();
|
||||
fprintf(stderr, "Toxic session aborted with error code %d (%s)\n", errcode, errmsg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void cb_toxcore_logger(Tox *m, TOX_LOG_LEVEL level, const char *file, uint32_t line, const char *func,
|
||||
const char *message, void *user_data)
|
||||
{
|
||||
UNUSED_VAR(user_data);
|
||||
UNUSED_VAR(file);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
if (user_data) {
|
||||
FILE *fp = (FILE *)user_data;
|
||||
fprintf(fp, "[%d] %u:%s() - %s\n", level, line, func, message);
|
||||
fflush(fp);
|
||||
} else {
|
||||
fprintf(stderr, "[%d] %u:%s() - %s\n", level, line, func, message);
|
||||
}
|
||||
}
|
||||
|
||||
static void init_term(void)
|
||||
{
|
||||
#if HAVE_WIDECHAR
|
||||
@ -319,17 +355,18 @@ static void load_friendlist(Tox *m)
|
||||
sort_friendlist_index();
|
||||
}
|
||||
|
||||
static void load_groups(ToxWindow *prompt, Tox *m)
|
||||
static void load_conferences(Tox *m)
|
||||
{
|
||||
size_t i;
|
||||
size_t num_chats = tox_conference_get_chatlist_size(m);
|
||||
uint32_t chatlist[num_chats];
|
||||
|
||||
if (num_chats) {
|
||||
tox_conference_get_chatlist(m, chatlist);
|
||||
if (num_chats == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_chats; ++i) {
|
||||
uint32_t chatlist[num_chats];
|
||||
tox_conference_get_chatlist(m, chatlist);
|
||||
|
||||
for (size_t i = 0; i < num_chats; ++i) {
|
||||
uint32_t groupnum = chatlist[i];
|
||||
|
||||
if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
|
||||
@ -345,7 +382,23 @@ static void load_groups(ToxWindow *prompt, Tox *m)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (init_groupchat_win(prompt, m, groupnum, type) == -1) {
|
||||
Tox_Err_Conference_Title t_err;
|
||||
size_t length = tox_conference_get_title_size(m, groupnum, &t_err);
|
||||
uint8_t title[MAX_STR_SIZE];
|
||||
|
||||
if (t_err != TOX_ERR_CONFERENCE_TITLE_OK || length >= sizeof(title)) {
|
||||
length = 0;
|
||||
} else {
|
||||
tox_conference_get_title(m, groupnum, title, &t_err);
|
||||
|
||||
if (t_err != TOX_ERR_CONFERENCE_TITLE_OK) {
|
||||
length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
title[length] = 0;
|
||||
|
||||
if (init_groupchat_win(m, groupnum, type, (const char *) title, length) == -1) {
|
||||
tox_conference_delete(m, groupnum, NULL);
|
||||
continue;
|
||||
}
|
||||
@ -441,7 +494,7 @@ static void first_time_encrypt(const char *msg)
|
||||
char ch[256] = {0};
|
||||
|
||||
do {
|
||||
system("clear");
|
||||
clear_screen();
|
||||
printf("%s ", msg);
|
||||
fflush(stdout);
|
||||
|
||||
@ -500,7 +553,7 @@ static void first_time_encrypt(const char *msg)
|
||||
user_password.data_is_encrypted = true;
|
||||
}
|
||||
|
||||
system("clear");
|
||||
clear_screen();
|
||||
}
|
||||
|
||||
/* Store Tox profile data to path.
|
||||
@ -544,7 +597,7 @@ int store_data(Tox *m, const char *path)
|
||||
return -1;
|
||||
}
|
||||
|
||||
TOX_ERR_ENCRYPTION err;
|
||||
Tox_Err_Encryption err;
|
||||
tox_pass_encrypt((uint8_t *) data, data_len, (uint8_t *) user_password.pass, user_password.len,
|
||||
(uint8_t *) enc_data, &err);
|
||||
|
||||
@ -614,6 +667,15 @@ static void init_tox_options(struct Tox_Options *tox_opts)
|
||||
tox_options_set_udp_enabled(tox_opts, !arg_opts.force_tcp);
|
||||
tox_options_set_proxy_type(tox_opts, arg_opts.proxy_type);
|
||||
tox_options_set_tcp_port(tox_opts, arg_opts.tcp_port);
|
||||
tox_options_set_local_discovery_enabled(tox_opts, !arg_opts.disable_local_discovery);
|
||||
|
||||
if (arg_opts.logging) {
|
||||
tox_options_set_log_callback(tox_opts, cb_toxcore_logger);
|
||||
|
||||
if (arg_opts.log_fp != NULL) {
|
||||
tox_options_set_log_user_data(tox_opts, arg_opts.log_fp);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tox_options_get_ipv6_enabled(tox_opts)) {
|
||||
queue_init_message("Forcing IPv4 connection");
|
||||
@ -690,7 +752,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
|
||||
int pweval = user_settings->password_eval[0];
|
||||
|
||||
if (!pweval) {
|
||||
system("clear"); // TODO: is this portable?
|
||||
clear_screen();
|
||||
printf("Enter password (q to quit) ");
|
||||
}
|
||||
|
||||
@ -714,14 +776,14 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
|
||||
}
|
||||
|
||||
if (pwlen < MIN_PASSWORD_LEN) {
|
||||
system("clear");
|
||||
clear_screen();
|
||||
sleep(1);
|
||||
printf("Invalid password. Try again. ");
|
||||
pweval = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
TOX_ERR_DECRYPTION pwerr;
|
||||
Tox_Err_Decryption pwerr;
|
||||
tox_pass_decrypt((uint8_t *) data, len, (uint8_t *) user_password.pass, pwlen,
|
||||
(uint8_t *) plain, &pwerr);
|
||||
|
||||
@ -738,7 +800,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, Tox_Err_New
|
||||
|
||||
break;
|
||||
} else if (pwerr == TOX_ERR_DECRYPTION_FAILED) {
|
||||
system("clear");
|
||||
clear_screen();
|
||||
sleep(1);
|
||||
printf("Invalid password. Try again. ");
|
||||
pweval = 0;
|
||||
@ -912,6 +974,8 @@ static void print_usage(void)
|
||||
fprintf(stderr, " -e, --encrypt-data Encrypt an unencrypted data file\n");
|
||||
fprintf(stderr, " -f, --file Use specified data file\n");
|
||||
fprintf(stderr, " -h, --help Show this message and exit\n");
|
||||
fprintf(stderr, " -l, --logging Enable toxcore logging: Requires [log_path | stderr]\n");
|
||||
fprintf(stderr, " -L, --no-lan Disable local discovery\n");
|
||||
fprintf(stderr, " -n, --nodes Use specified DHTnodes file\n");
|
||||
fprintf(stderr, " -o, --noconnect Do not connect to the DHT network\n");
|
||||
fprintf(stderr, " -p, --SOCKS5-proxy Use SOCKS5 proxy: Requires [IP] [port]\n");
|
||||
@ -942,12 +1006,14 @@ static void parse_args(int argc, char *argv[])
|
||||
set_default_opts();
|
||||
|
||||
static struct option long_opts[] = {
|
||||
{"file", required_argument, 0, 'f'},
|
||||
{"ipv4", no_argument, 0, '4'},
|
||||
{"debug", no_argument, 0, 'b'},
|
||||
{"default-locale", no_argument, 0, 'd'},
|
||||
{"config", required_argument, 0, 'c'},
|
||||
{"encrypt-data", no_argument, 0, 'e'},
|
||||
{"file", required_argument, 0, 'f'},
|
||||
{"logging", required_argument, 0, 'l'},
|
||||
{"no-lan", no_argument, 0, 'L'},
|
||||
{"nodes", required_argument, 0, 'n'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"noconnect", no_argument, 0, 'o'},
|
||||
@ -961,7 +1027,7 @@ static void parse_args(int argc, char *argv[])
|
||||
{NULL, no_argument, NULL, 0},
|
||||
};
|
||||
|
||||
const char *opts_str = "4bdehotuxvc:f:n:r:p:P:T:";
|
||||
const char *opts_str = "4bdehLotuxvc:f:l:n:r:p:P:T:";
|
||||
int opt, indexptr;
|
||||
long int port = 0;
|
||||
|
||||
@ -1025,6 +1091,32 @@ static void parse_args(int argc, char *argv[])
|
||||
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
if (optarg) {
|
||||
arg_opts.logging = true;
|
||||
|
||||
if (strcmp(optarg, "stderr") != 0) {
|
||||
arg_opts.log_fp = fopen(optarg, "w");
|
||||
|
||||
if (arg_opts.log_fp != NULL) {
|
||||
queue_init_message("Toxcore logging enabled to %s", optarg);
|
||||
} else {
|
||||
arg_opts.debug = true;
|
||||
queue_init_message("Failed to open log file %s. Falling back to stderr.", optarg);
|
||||
}
|
||||
} else {
|
||||
arg_opts.debug = true;
|
||||
queue_init_message("Toxcore logging enabled to stderr");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
arg_opts.disable_local_discovery = 1;
|
||||
queue_init_message("Local discovery disabled");
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
snprintf(arg_opts.nodes_path, sizeof(arg_opts.nodes_path), "%s", optarg);
|
||||
break;
|
||||
@ -1205,6 +1297,8 @@ static void init_default_data_files(void)
|
||||
#ifdef X11
|
||||
void DnD_callback(const char *asdv, DropType dt)
|
||||
{
|
||||
UNUSED_VAR(asdv);
|
||||
UNUSED_VAR(dt);
|
||||
// if (dt != DT_plain)
|
||||
// return;
|
||||
|
||||
@ -1216,11 +1310,16 @@ void DnD_callback(const char *asdv, DropType dt)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* Make sure all written files are read/writeable only by the current user. */
|
||||
umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
|
||||
parse_args(argc, argv);
|
||||
|
||||
/* Use the -b flag to enable stderr */
|
||||
if (!arg_opts.debug) {
|
||||
freopen("/dev/null", "w", stderr);
|
||||
if (!freopen("/dev/null", "w", stderr)) {
|
||||
fprintf(stderr, "Warning: failed to enable stderr\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_opts.encrypt_data && arg_opts.unencrypt_data) {
|
||||
@ -1229,9 +1328,6 @@ int main(int argc, char **argv)
|
||||
queue_init_message("Warning: Using --unencrypt-data and --encrypt-data simultaneously has no effect");
|
||||
}
|
||||
|
||||
/* Make sure all written files are read/writeable only by the current user. */
|
||||
umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
|
||||
init_default_data_files();
|
||||
|
||||
bool datafile_exists = file_exists(DATA_FILE);
|
||||
@ -1285,7 +1381,7 @@ int main(int argc, char **argv)
|
||||
|
||||
prompt = init_windows(m);
|
||||
prompt_init_statusbar(prompt, m, !datafile_exists);
|
||||
load_groups(prompt, m);
|
||||
load_conferences(m);
|
||||
|
||||
/* thread for ncurses stuff */
|
||||
if (pthread_mutex_init(&Winthread.lock, NULL) != 0) {
|
||||
@ -1333,7 +1429,7 @@ int main(int argc, char **argv)
|
||||
|
||||
#endif /* PYTHON */
|
||||
|
||||
init_notify(60, 3000);
|
||||
init_notify(60, user_settings->notification_timeout);
|
||||
|
||||
/* screen/tmux auto-away timer */
|
||||
if (init_mplex_away_timer(m) == -1) {
|
||||
@ -1364,7 +1460,7 @@ int main(int argc, char **argv)
|
||||
|
||||
time_t cur_time = get_unix_time();
|
||||
|
||||
if (timed_out(last_save, AUTOSAVE_FREQ)) {
|
||||
if (user_settings->autosave_freq > 0 && timed_out(last_save, user_settings->autosave_freq)) {
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
|
||||
if (store_data(m, DATA_FILE) != 0) {
|
||||
|
@ -61,8 +61,6 @@
|
||||
#define T_KEY_PREV 0x0F /* ctrl-o */
|
||||
#define T_KEY_C_E 0x05 /* ctrl-e */
|
||||
#define T_KEY_C_A 0x01 /* ctrl-a */
|
||||
#define T_KEY_C_RB 0x1D /* ctrl-] */
|
||||
#define T_KEY_C_LB 0x1B /* ctrl-[ */
|
||||
#define T_KEY_C_V 0x16 /* ctrl-v */
|
||||
#define T_KEY_C_F 0x06 /* ctrl-f */
|
||||
#define T_KEY_C_H 0x08 /* ctrl-h */
|
||||
@ -71,6 +69,10 @@
|
||||
#define T_KEY_C_W 0x17 /* ctrl-w */
|
||||
#define T_KEY_C_B 0x02 /* ctrl-b */
|
||||
#define T_KEY_C_T 0x14 /* ctrl-t */
|
||||
#define T_KEY_C_LEFT 0x221 /* ctrl-left arrow */
|
||||
#define T_KEY_C_RIGHT 0x230 /* ctrl-right arrow */
|
||||
#define T_KEY_C_UP 0x236 /* ctrl-up arrow */
|
||||
#define T_KEY_C_DOWN 0x20D /* ctrl-down arrow */
|
||||
#define T_KEY_TAB 0x09 /* TAB key */
|
||||
|
||||
#define ONLINE_CHAR "*"
|
||||
|
@ -236,6 +236,12 @@ void add_line_to_hist(ChatContext *ctx)
|
||||
resets line if at end of history */
|
||||
void fetch_hist_item(ChatContext *ctx, int key_dir)
|
||||
{
|
||||
if (wcscmp(ctx->line, L"\0") != 0
|
||||
&& ctx->hst_pos == ctx->hst_tot) {
|
||||
add_line_to_hist(ctx);
|
||||
ctx->hst_pos--;
|
||||
}
|
||||
|
||||
if (key_dir == KEY_UP) {
|
||||
if (--ctx->hst_pos < 0) {
|
||||
ctx->hst_pos = 0;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "global_commands.h"
|
||||
#include "line_info.h"
|
||||
#include "notify.h"
|
||||
#include "misc_tools.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <curses.h>
|
||||
@ -56,6 +57,8 @@ static void print_err(ToxWindow *self, const char *error_str)
|
||||
|
||||
ToxAV *init_video(ToxWindow *self, Tox *tox)
|
||||
{
|
||||
UNUSED_VAR(tox);
|
||||
|
||||
CallControl.video_errors = ve_None;
|
||||
|
||||
CallControl.video_enabled = true;
|
||||
@ -126,6 +129,8 @@ void write_video_device_callback(uint32_t friend_number, uint16_t width, uint16_
|
||||
int32_t ystride, int32_t ustride, int32_t vstride,
|
||||
void *user_data)
|
||||
{
|
||||
UNUSED_VAR(friend_number);
|
||||
|
||||
write_video_out(width, height, y, u, v, ystride, ustride, vstride, user_data);
|
||||
}
|
||||
|
||||
@ -185,11 +190,16 @@ void on_video_receive_frame(ToxAV *av, uint32_t friend_number,
|
||||
int32_t ystride, int32_t ustride, int32_t vstride,
|
||||
void *user_data)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
|
||||
write_video_device_callback(friend_number, width, height, y, u, v, ystride, ustride, vstride, user_data);
|
||||
}
|
||||
|
||||
void on_video_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_bit_rate, void *user_data)
|
||||
{
|
||||
UNUSED_VAR(av);
|
||||
UNUSED_VAR(user_data);
|
||||
|
||||
CallControl.video_bit_rate = video_bit_rate;
|
||||
toxav_video_set_bit_rate(CallControl.av, friend_number, CallControl.video_bit_rate, NULL);
|
||||
}
|
||||
@ -213,7 +223,6 @@ void callback_recv_video_end(uint32_t friend_number)
|
||||
}
|
||||
void callback_video_starting(uint32_t friend_number)
|
||||
{
|
||||
ToxWindow *windows = CallControl.prompt;
|
||||
Call *this_call = &CallControl.calls[friend_number];
|
||||
|
||||
Toxav_Err_Call_Control error = TOXAV_ERR_CALL_CONTROL_OK;
|
||||
@ -223,13 +232,15 @@ void callback_video_starting(uint32_t friend_number)
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i].is_call && windows[i].num == friend_number) {
|
||||
if (0 != start_video_transmission(&windows[i], CallControl.av, this_call)) {
|
||||
line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0, "Error starting transmission!");
|
||||
ToxWindow *window = get_window_ptr(i);
|
||||
|
||||
if (window != NULL && window->is_call && window->num == friend_number) {
|
||||
if (0 != start_video_transmission(window, CallControl.av, this_call)) {
|
||||
line_info_add(window, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error starting transmission!");
|
||||
return;
|
||||
}
|
||||
|
||||
line_info_add(&windows[i], NULL, NULL, NULL, SYS_MSG, 0, 0, "Video capture starting.");
|
||||
line_info_add(window, NULL, NULL, NULL, SYS_MSG, 0, 0, "Video capture starting.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -249,6 +260,10 @@ void callback_video_end(uint32_t friend_number)
|
||||
*/
|
||||
void cmd_video(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
UNUSED_VAR(argv);
|
||||
|
||||
const char *error_str;
|
||||
Call *this_call = &CallControl.calls[self->num];
|
||||
|
||||
@ -285,6 +300,9 @@ on_error:
|
||||
|
||||
void cmd_list_video_devices(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
const char *error_str;
|
||||
|
||||
if (argc != 1) {
|
||||
@ -322,6 +340,9 @@ on_error:
|
||||
/* This changes primary video device only */
|
||||
void cmd_change_video_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
const char *error_str;
|
||||
|
||||
if (argc != 2) {
|
||||
@ -372,6 +393,9 @@ on_error:
|
||||
|
||||
void cmd_ccur_video_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
const char *error_str;
|
||||
|
||||
if (argc != 2) {
|
||||
|
@ -24,15 +24,15 @@
|
||||
#include "video_call.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xos.h>
|
||||
|
||||
#include <vpx/vpx_image.h>
|
||||
|
||||
#if defined(__OSX__)
|
||||
#if defined(__OSX__) || defined(__APPLE__)
|
||||
#import "osx_video.h"
|
||||
#else
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xos.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
@ -42,10 +42,11 @@
|
||||
#else
|
||||
#include <linux/videodev2.h>
|
||||
#endif /* defined(__OpenBSD__) || defined(__NetBSD__) */
|
||||
#endif /* __OSX__ */
|
||||
#endif /* __OSX__ || __APPLE__ */
|
||||
|
||||
#include "line_info.h"
|
||||
#include "settings.h"
|
||||
#include "misc_tools.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
@ -71,7 +72,7 @@ typedef struct VideoDevice {
|
||||
void *cb_data; /* Data to be passed to callback */
|
||||
int32_t friend_number; /* ToxAV friend number */
|
||||
|
||||
#if !defined(__OSX__)
|
||||
#if !(defined(__OSX__) || defined(__APPLE__))
|
||||
int fd; /* File descriptor of video device selected/opened */
|
||||
struct v4l2_format fmt;
|
||||
struct VideoBuffer *buffers;
|
||||
@ -101,8 +102,8 @@ uint32_t primary_video_device[2]; /* Primary device */
|
||||
static ToxAV *av = NULL;
|
||||
|
||||
/* q_mutex */
|
||||
#define lock pthread_mutex_lock(&video_mutex);
|
||||
#define unlock pthread_mutex_unlock(&video_mutex);
|
||||
#define lock pthread_mutex_lock(&video_mutex)
|
||||
#define unlock pthread_mutex_unlock(&video_mutex)
|
||||
pthread_mutex_t video_mutex;
|
||||
|
||||
bool video_thread_running = true,
|
||||
@ -136,7 +137,7 @@ static void yuv420tobgr(uint16_t width, uint16_t height, const uint8_t *y,
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(__OSX__)
|
||||
#if !(defined(__OSX__) || defined(__APPLE__))
|
||||
static void yuv422to420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v,
|
||||
uint8_t *input, uint16_t width, uint16_t height)
|
||||
{
|
||||
@ -185,13 +186,13 @@ VideoDeviceError init_video_devices()
|
||||
{
|
||||
size[vdt_input] = 0;
|
||||
|
||||
#if defined(__OSX__)
|
||||
#if defined(__OSX__) || defined(__APPLE__)
|
||||
|
||||
if (osx_video_init((char **)video_devices_names[vdt_input], &size[vdt_input]) != 0) {
|
||||
return vde_InternalError;
|
||||
}
|
||||
|
||||
#else /* not __OSX__*/
|
||||
#else /* not __OSX__ || __APPLE__ */
|
||||
|
||||
for (; size[vdt_input] <= MAX_DEVICES; ++size[vdt_input]) {
|
||||
int fd;
|
||||
@ -269,9 +270,9 @@ VideoDeviceError terminate_video_devices(void)
|
||||
return (VideoDeviceError) vde_InternalError;
|
||||
}
|
||||
|
||||
#ifdef __OSX__
|
||||
#if defined(__OSX__) || defined(__APPLE__)
|
||||
osx_video_release();
|
||||
#endif /* __OSX__ */
|
||||
#endif /* __OSX__ || __APPLE__ */
|
||||
|
||||
return (VideoDeviceError) vde_None;
|
||||
}
|
||||
@ -279,13 +280,13 @@ VideoDeviceError terminate_video_devices(void)
|
||||
VideoDeviceError register_video_device_callback(int32_t friend_number, uint32_t device_idx,
|
||||
VideoDataHandleCallback callback, void *data)
|
||||
{
|
||||
#if defined(__OSX__)
|
||||
#if defined(__OSX__) || defined(__APPLE__)
|
||||
|
||||
if (size[vdt_input] <= device_idx || !video_devices_running[vdt_input][device_idx]) {
|
||||
return vde_InvalidSelection;
|
||||
}
|
||||
|
||||
#else /* not __OSX__ */
|
||||
#else /* not __OSX__ || __APPLE__ */
|
||||
|
||||
if (size[vdt_input] <= device_idx || !video_devices_running[vdt_input][device_idx]
|
||||
|| !video_devices_running[vdt_input][device_idx]->fd) {
|
||||
@ -369,7 +370,7 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
if (type == vdt_input) {
|
||||
video_thread_paused = true;
|
||||
|
||||
#if defined(__OSX__)
|
||||
#if defined(__OSX__) || defined(__APPLE__)
|
||||
|
||||
if (osx_video_open_device(selection, &device->video_width, &device->video_height) != 0) {
|
||||
free(device);
|
||||
@ -377,7 +378,7 @@ VideoDeviceError open_video_device(VideoDeviceType type, int32_t selection, uint
|
||||
return vde_FailedStart;
|
||||
}
|
||||
|
||||
#else /* not __OSX__*/
|
||||
#else /* not __OSX__ || __APPLE__ */
|
||||
/* Open selected device */
|
||||
char device_address[] = "/dev/videoXX";
|
||||
snprintf(device_address + 10, sizeof(device_address) - 10, "%i", selection);
|
||||
@ -596,6 +597,8 @@ VideoDeviceError write_video_out(uint16_t width, uint16_t height,
|
||||
int32_t ystride, int32_t ustride, int32_t vstride,
|
||||
void *user_data)
|
||||
{
|
||||
UNUSED_VAR(user_data);
|
||||
|
||||
VideoDevice *device = video_devices_running[vdt_output][0];
|
||||
|
||||
if (!device) {
|
||||
@ -659,7 +662,7 @@ void *video_thread_poll(void *arg) // TODO: maybe use thread for every input so
|
||||
/*
|
||||
* NOTE: We only need to poll input devices for data.
|
||||
*/
|
||||
(void)arg;
|
||||
UNUSED_VAR(arg);
|
||||
uint32_t i;
|
||||
|
||||
while (1) {
|
||||
@ -687,14 +690,14 @@ void *video_thread_poll(void *arg) // TODO: maybe use thread for every input so
|
||||
uint8_t *u = device->input.planes[1];
|
||||
uint8_t *v = device->input.planes[2];
|
||||
|
||||
#if defined(__OSX__)
|
||||
#if defined(__OSX__) || defined(__APPLE__)
|
||||
|
||||
if (osx_video_read_device(y, u, v, &video_width, &video_height) != 0) {
|
||||
unlock;
|
||||
continue;
|
||||
}
|
||||
|
||||
#else /* not __OSX__*/
|
||||
#else /* not __OSX__ || __APPLE__ */
|
||||
struct v4l2_buffer buf;
|
||||
memset(&(buf), 0, sizeof(buf));
|
||||
|
||||
@ -748,7 +751,7 @@ void *video_thread_poll(void *arg) // TODO: maybe use thread for every input so
|
||||
XFlush(device->x_display);
|
||||
free(img_data);
|
||||
|
||||
#if !defined(__OSX__)
|
||||
#if !(defined(__OSX__) || defined(__APPLE__))
|
||||
|
||||
if (-1 == xioctl(device->fd, VIDIOC_QBUF, &buf)) {
|
||||
unlock;
|
||||
@ -789,10 +792,10 @@ VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx)
|
||||
if (!device->ref_count) {
|
||||
|
||||
if (type == vdt_input) {
|
||||
#if defined(__OSX__)
|
||||
#if defined(__OSX__) || defined(__APPLE__)
|
||||
|
||||
osx_video_close_device(device_idx);
|
||||
#else /* not __OSX__ */
|
||||
#else /* not __OSX__ || __APPLE__ */
|
||||
enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
if (-1 == xioctl(device->fd, VIDIOC_STREAMOFF, &buf_type)) {}
|
||||
@ -813,9 +816,9 @@ VideoDeviceError close_video_device(VideoDeviceType type, uint32_t device_idx)
|
||||
XCloseDisplay(device->x_display);
|
||||
pthread_mutex_destroy(device->mutex);
|
||||
|
||||
#if !defined(__OSX__)
|
||||
#if !(defined(__OSX__) || defined(__APPLE__))
|
||||
free(device->buffers);
|
||||
#endif /* not __OSX__ */
|
||||
#endif /* not __OSX__ || __APPLE__ */
|
||||
|
||||
free(device);
|
||||
} else {
|
||||
|
180
src/windows.c
180
src/windows.c
@ -50,6 +50,8 @@ extern struct user_settings *user_settings;
|
||||
/* CALLBACKS START */
|
||||
void on_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
char msg[MAX_STR_SIZE + 1];
|
||||
length = copy_tox_str(msg, sizeof(msg), (const char *) data, length);
|
||||
|
||||
@ -62,6 +64,8 @@ void on_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, s
|
||||
|
||||
void on_friend_connection_status(Tox *m, uint32_t friendnumber, Tox_Connection connection_status, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
for (uint8_t i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i] != NULL && windows[i]->onConnectionChange != NULL) {
|
||||
windows[i]->onConnectionChange(windows[i], m, friendnumber, connection_status);
|
||||
@ -71,6 +75,8 @@ void on_friend_connection_status(Tox *m, uint32_t friendnumber, Tox_Connection c
|
||||
|
||||
void on_friend_typing(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
if (user_settings->show_typing_other == SHOW_TYPING_OFF) {
|
||||
return;
|
||||
}
|
||||
@ -85,6 +91,8 @@ void on_friend_typing(Tox *m, uint32_t friendnumber, bool is_typing, void *userd
|
||||
void on_friend_message(Tox *m, uint32_t friendnumber, Tox_Message_Type type, const uint8_t *string, size_t length,
|
||||
void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
char msg[MAX_STR_SIZE + 1];
|
||||
length = copy_tox_str(msg, sizeof(msg), (const char *) string, length);
|
||||
|
||||
@ -97,6 +105,8 @@ void on_friend_message(Tox *m, uint32_t friendnumber, Tox_Message_Type type, con
|
||||
|
||||
void on_friend_name(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
char nick[TOXIC_MAX_NAME_LENGTH + 1];
|
||||
length = copy_tox_str(nick, sizeof(nick), (const char *) string, length);
|
||||
filter_str(nick, length);
|
||||
@ -112,6 +122,9 @@ void on_friend_name(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t
|
||||
|
||||
void on_friend_status_message(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
UNUSED_VAR(m);
|
||||
|
||||
char msg[TOX_MAX_STATUS_MESSAGE_LENGTH + 1];
|
||||
length = copy_tox_str(msg, sizeof(msg), (const char *) string, length);
|
||||
filter_str(msg, length);
|
||||
@ -125,6 +138,8 @@ void on_friend_status_message(Tox *m, uint32_t friendnumber, const uint8_t *stri
|
||||
|
||||
void on_friend_status(Tox *m, uint32_t friendnumber, Tox_User_Status status, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
for (uint8_t i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i] != NULL && windows[i]->onStatusChange != NULL) {
|
||||
windows[i]->onStatusChange(windows[i], m, friendnumber, status);
|
||||
@ -146,6 +161,8 @@ void on_friend_added(Tox *m, uint32_t friendnumber, bool sort)
|
||||
void on_conference_message(Tox *m, uint32_t groupnumber, uint32_t peernumber, Tox_Message_Type type,
|
||||
const uint8_t *message, size_t length, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
char msg[MAX_STR_SIZE + 1];
|
||||
length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
|
||||
|
||||
@ -159,6 +176,8 @@ void on_conference_message(Tox *m, uint32_t groupnumber, uint32_t peernumber, To
|
||||
void on_conference_invite(Tox *m, uint32_t friendnumber, Tox_Conference_Type type, const uint8_t *group_pub_key,
|
||||
size_t length, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
for (uint8_t i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i] != NULL && windows[i]->onGroupInvite != NULL) {
|
||||
windows[i]->onGroupInvite(windows[i], m, friendnumber, type, (char *) group_pub_key, length);
|
||||
@ -168,6 +187,8 @@ void on_conference_invite(Tox *m, uint32_t friendnumber, Tox_Conference_Type typ
|
||||
|
||||
void on_conference_peer_list_changed(Tox *m, uint32_t groupnumber, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
for (uint8_t i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i] != NULL && windows[i]->onGroupNameListChange != NULL) {
|
||||
windows[i]->onGroupNameListChange(windows[i], m, groupnumber);
|
||||
@ -178,6 +199,8 @@ void on_conference_peer_list_changed(Tox *m, uint32_t groupnumber, void *userdat
|
||||
void on_conference_peer_name(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *name,
|
||||
size_t length, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
char nick[TOXIC_MAX_NAME_LENGTH + 1];
|
||||
length = copy_tox_str(nick, sizeof(nick), (const char *) name, length);
|
||||
filter_str(nick, length);
|
||||
@ -192,6 +215,8 @@ void on_conference_peer_name(Tox *m, uint32_t groupnumber, uint32_t peernumber,
|
||||
void on_conference_title(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *title, size_t length,
|
||||
void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
char data[MAX_STR_SIZE + 1];
|
||||
length = copy_tox_str(data, sizeof(data), (const char *) title, length);
|
||||
|
||||
@ -205,6 +230,8 @@ void on_conference_title(Tox *m, uint32_t groupnumber, uint32_t peernumber, cons
|
||||
void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position,
|
||||
size_t length, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
struct FileTransfer *ft = get_file_transfer_struct(friendnumber, filenumber);
|
||||
|
||||
if (!ft) {
|
||||
@ -224,8 +251,10 @@ void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, u
|
||||
}
|
||||
|
||||
void on_file_recv_chunk(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position,
|
||||
const uint8_t *data, size_t length, void *user_data)
|
||||
const uint8_t *data, size_t length, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
struct FileTransfer *ft = get_file_transfer_struct(friendnumber, filenumber);
|
||||
|
||||
if (!ft) {
|
||||
@ -242,6 +271,8 @@ void on_file_recv_chunk(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint
|
||||
void on_file_recv_control(Tox *m, uint32_t friendnumber, uint32_t filenumber, Tox_File_Control control,
|
||||
void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
struct FileTransfer *ft = get_file_transfer_struct(friendnumber, filenumber);
|
||||
|
||||
if (!ft) {
|
||||
@ -263,6 +294,8 @@ void on_file_recv_control(Tox *m, uint32_t friendnumber, uint32_t filenumber, To
|
||||
void on_file_recv(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint32_t kind, uint64_t file_size,
|
||||
const uint8_t *filename, size_t filename_length, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
/* We don't care about receiving avatars */
|
||||
if (kind != TOX_FILE_KIND_DATA) {
|
||||
tox_file_control(m, friendnumber, filenumber, TOX_FILE_CONTROL_CANCEL, NULL);
|
||||
@ -279,6 +312,8 @@ void on_file_recv(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint32_t k
|
||||
|
||||
void on_friend_read_receipt(Tox *m, uint32_t friendnumber, uint32_t receipt, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(userdata);
|
||||
|
||||
for (uint8_t i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
if (windows[i] != NULL && windows[i]->onReadReceipt != NULL) {
|
||||
windows[i]->onReadReceipt(windows[i], m, friendnumber, receipt);
|
||||
@ -532,6 +567,93 @@ static void draw_bar(void)
|
||||
refresh();
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets current char from stdscr and puts it in ch.
|
||||
*
|
||||
* Return 1 if char is printable.
|
||||
* Return 0 if char is not printable.
|
||||
* Return -1 on error.
|
||||
*/
|
||||
static int get_current_char(wint_t *ch)
|
||||
{
|
||||
wint_t tmpchar = 0;
|
||||
bool is_printable = false;
|
||||
|
||||
#ifdef HAVE_WIDECHAR
|
||||
int status = wget_wch(stdscr, &tmpchar);
|
||||
|
||||
if (status == ERR) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (status == OK) {
|
||||
is_printable = iswprint(tmpchar);
|
||||
}
|
||||
|
||||
#else
|
||||
tmpchar = getch();
|
||||
|
||||
if (tmpchar == ERR) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
is_printable = isprint(tmpchar);
|
||||
#endif /* HAVE_WIDECHAR */
|
||||
|
||||
*ch = tmpchar;
|
||||
|
||||
return (int) is_printable;
|
||||
}
|
||||
|
||||
static struct key_sequence_codes {
|
||||
wchar_t *code;
|
||||
wint_t key;
|
||||
} Keys[] = {
|
||||
{ L"[1;5A", T_KEY_C_UP },
|
||||
{ L"[1;5B", T_KEY_C_DOWN },
|
||||
{ L"[1;5C", T_KEY_C_RIGHT },
|
||||
{ L"[1;5D", T_KEY_C_LEFT },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Return key code corresponding to character sequence queued in stdscr.
|
||||
* Return -1 if sequence is unknown.
|
||||
*/
|
||||
#define MAX_SEQUENCE_SIZE 5
|
||||
static wint_t get_input_sequence_code(void)
|
||||
{
|
||||
wchar_t code[MAX_SEQUENCE_SIZE + 1];
|
||||
|
||||
size_t length = 0;
|
||||
wint_t ch = 0;
|
||||
|
||||
for (size_t i = 0; i < MAX_SEQUENCE_SIZE; ++i) {
|
||||
int res = get_current_char(&ch);
|
||||
|
||||
if (res < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
++length;
|
||||
code[i] = (wchar_t) ch;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
code[length] = L'\0';
|
||||
|
||||
for (size_t i = 0; Keys[i].key != 0; ++i) {
|
||||
if (wcscmp(code, Keys[i].code) == 0) {
|
||||
return Keys[i].key;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void draw_active_window(Tox *m)
|
||||
{
|
||||
ToxWindow *a = windows[active_window_index];
|
||||
@ -544,51 +666,47 @@ void draw_active_window(Tox *m)
|
||||
a->alert = WINDOW_ALERT_NONE;
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
wint_t ch = 0;
|
||||
|
||||
draw_bar();
|
||||
|
||||
touchwin(a->window);
|
||||
a->onDraw(a, m);
|
||||
wrefresh(a->window);
|
||||
|
||||
/* Handle input */
|
||||
bool ltr;
|
||||
#ifdef HAVE_WIDECHAR
|
||||
int status = wget_wch(stdscr, &ch);
|
||||
wint_t ch = 0;
|
||||
int printable = get_current_char(&ch);
|
||||
|
||||
if (status == ERR) {
|
||||
if (printable < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == OK) {
|
||||
ltr = iswprint(ch);
|
||||
} else { /* if (status == KEY_CODE_YES) */
|
||||
ltr = false;
|
||||
}
|
||||
|
||||
#else
|
||||
ch = getch();
|
||||
|
||||
if (ch == ERR) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO verify if this works */
|
||||
ltr = isprint(ch);
|
||||
#endif /* HAVE_WIDECHAR */
|
||||
|
||||
if (!ltr && (ch == user_settings->key_next_tab || ch == user_settings->key_prev_tab)) {
|
||||
if (printable == 0 && (ch == user_settings->key_next_tab || ch == user_settings->key_prev_tab)) {
|
||||
set_next_window((int) ch);
|
||||
} else {
|
||||
return;
|
||||
} else if (printable == 0 && !a->is_friendlist) {
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
a->onKey(a, m, ch, ltr);
|
||||
bool input_ret = a->onKey(a, m, ch, (bool) printable);
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
if (input_ret) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if an unprintable key code is unrecognized by input handler we attempt to manually decode char sequence
|
||||
wint_t tmp = get_input_sequence_code();
|
||||
|
||||
if (tmp != (wint_t) -1) {
|
||||
ch = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
a->onKey(a, m, ch, (bool) printable);
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
}
|
||||
|
||||
/* refresh inactive windows to prevent scrolling bugs.
|
||||
call at least once per second */
|
||||
/* Refresh inactive windows to prevent scrolling bugs.
|
||||
* Call at least once per second.
|
||||
*/
|
||||
void refresh_inactive_windows(void)
|
||||
{
|
||||
for (uint8_t i = 0; i < MAX_WINDOWS_NUM; ++i) {
|
||||
@ -647,7 +765,7 @@ void kill_all_windows(Tox *m)
|
||||
if (windows[i]->is_chat) {
|
||||
kill_chat_window(windows[i], m);
|
||||
} else if (windows[i]->is_groupchat) {
|
||||
free_groupchat(windows[i], m, windows[i]->num);
|
||||
free_groupchat(windows[i], windows[i]->num);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,7 @@ struct av_thread {
|
||||
struct arg_opts {
|
||||
bool use_ipv4;
|
||||
bool force_tcp;
|
||||
bool disable_local_discovery;
|
||||
bool debug;
|
||||
bool default_locale;
|
||||
bool use_custom_data;
|
||||
@ -94,6 +95,9 @@ struct arg_opts {
|
||||
char config_path[MAX_STR_SIZE];
|
||||
char nodes_path[MAX_STR_SIZE];
|
||||
|
||||
bool logging;
|
||||
FILE *log_fp;
|
||||
|
||||
char proxy_address[256];
|
||||
uint8_t proxy_type;
|
||||
uint16_t proxy_port;
|
||||
@ -109,7 +113,7 @@ typedef struct Help Help;
|
||||
|
||||
struct ToxWindow {
|
||||
/* ncurses */
|
||||
void(*onKey)(ToxWindow *, Tox *, wint_t, bool);
|
||||
bool(*onKey)(ToxWindow *, Tox *, wint_t, bool);
|
||||
void(*onDraw)(ToxWindow *, Tox *);
|
||||
void(*onInit)(ToxWindow *, Tox *);
|
||||
|
||||
|
11
src/xtra.c
11
src/xtra.c
@ -21,6 +21,9 @@
|
||||
*/
|
||||
|
||||
#include "xtra.h"
|
||||
#include "misc_tools.h"
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
@ -179,6 +182,8 @@ static void handle_xdnd_drop(XClientMessageEvent *e)
|
||||
|
||||
static void handle_xdnd_selection(XSelectionEvent *e)
|
||||
{
|
||||
UNUSED_VAR(e);
|
||||
|
||||
/* DnD succesfully finished, send finished and call callback */
|
||||
XEvent ev = {
|
||||
.xclient = {
|
||||
@ -227,7 +232,7 @@ void *event_loop(void *p)
|
||||
{
|
||||
/* Handle events like a real nigga */
|
||||
|
||||
(void) p; /* DINDUNOTHIN */
|
||||
UNUSED_VAR(p); /* DINDUNOTHIN */
|
||||
|
||||
XEvent event;
|
||||
int pending;
|
||||
@ -297,7 +302,7 @@ static long unsigned int focused_window_id(void)
|
||||
|
||||
int is_focused(void)
|
||||
{
|
||||
return Xtra.proxy_window == focused_window_id() || Xtra.terminal_window == focused_window_id();
|
||||
return Xtra.display && (Xtra.proxy_window == focused_window_id() || Xtra.terminal_window == focused_window_id());
|
||||
}
|
||||
|
||||
int init_xtra(drop_callback d)
|
||||
@ -416,3 +421,5 @@ void terminate_xtra(void)
|
||||
|
||||
while (Xtra.display); /* Wait for termination */
|
||||
}
|
||||
|
||||
#endif /* !__APPLE__ */
|
||||
|
Reference in New Issue
Block a user