mirror of
https://github.com/Tha14/toxic.git
synced 2024-12-27 19:13:25 +01:00
Merge branch 'master' of https://github.com/Tox/toxic
This commit is contained in:
commit
3a9056745f
461
src/audio_call.c
461
src/audio_call.c
@ -26,23 +26,23 @@
|
||||
#define AUDIO_FRAME_SIZE (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000)
|
||||
|
||||
typedef struct _DeviceIx {
|
||||
|
||||
ALCdevice* dhndl; /* Handle of device selected/opened */
|
||||
ALCcontext* ctx; /* Device context */
|
||||
const char* devices[MAX_DEVICES]; /* Container of available devices */
|
||||
|
||||
ALCdevice *dhndl; /* Handle of device selected/opened */
|
||||
ALCcontext *ctx; /* Device context */
|
||||
const char *devices[MAX_DEVICES]; /* Container of available devices */
|
||||
int size; /* Size of above container */
|
||||
int dix; /* Index of default device */
|
||||
int index; /* Current index */
|
||||
} DeviceIx;
|
||||
|
||||
struct _ASettings {
|
||||
|
||||
|
||||
DeviceIx device[2];
|
||||
|
||||
|
||||
AudioError errors;
|
||||
|
||||
ToxAv* av;
|
||||
|
||||
|
||||
ToxAv *av;
|
||||
|
||||
pthread_t ttid; /* Transmission thread id */
|
||||
int ttas; /* Transmission thread active status (0 - stopped, 1- running) */
|
||||
} ASettins;
|
||||
@ -57,7 +57,7 @@ void callback_call_canceled ( void *arg );
|
||||
void callback_call_rejected ( void *arg );
|
||||
void callback_call_ended ( void *arg );
|
||||
void callback_requ_timeout ( void *arg );
|
||||
void callback_peer_timeout ( void* arg );
|
||||
void callback_peer_timeout ( void *arg );
|
||||
|
||||
|
||||
static void print_err (ToxWindow *self, uint8_t *error_str)
|
||||
@ -88,85 +88,79 @@ int device_open (ToxWindow *self, _Devices type)
|
||||
|
||||
/* Do not error if no device */
|
||||
if ( !ASettins.device[type].size ) return 0;
|
||||
|
||||
ALCdevice* prev_device = ASettins.device[type].dhndl;
|
||||
|
||||
|
||||
ALCdevice *prev_device = ASettins.device[type].dhndl;
|
||||
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
uint8_t* error = NULL;
|
||||
|
||||
uint8_t *error = NULL;
|
||||
|
||||
if ( type == input ) {
|
||||
ASettins.device[type].dhndl = alcCaptureOpenDevice(
|
||||
ASettins.device[type].devices[ASettins.device[type].index],
|
||||
av_DefaultSettings.audio_sample_rate,
|
||||
AL_FORMAT_MONO16,
|
||||
AUDIO_FRAME_SIZE * 4);
|
||||
|
||||
ASettins.device[type].devices[ASettins.device[type].index],
|
||||
av_DefaultSettings.audio_sample_rate,
|
||||
AL_FORMAT_MONO16,
|
||||
AUDIO_FRAME_SIZE * 4);
|
||||
|
||||
if (alcGetError(ASettins.device[type].dhndl) != AL_NO_ERROR) {
|
||||
|
||||
|
||||
/* Now check if we have previous device and act acording to it */
|
||||
if ( !prev_device ) {
|
||||
error = "Error starting input device!";
|
||||
|
||||
|
||||
ASettins.errors |= ErrorStartingCaptureDevice;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
error = "Could not start input device, falling back to previous";
|
||||
|
||||
|
||||
/* NOTE: What if device is opened? */
|
||||
ASettins.device[type].dhndl = prev_device;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* Close previous */
|
||||
if ( prev_device )
|
||||
alcCaptureCloseDevice(prev_device);
|
||||
|
||||
|
||||
if ( window ) {
|
||||
snprintf(msg, sizeof(msg), "Input device: %s", ASettins.device[type].devices[ASettins.device[type].index]);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ASettins.device[type].ctx = NULL;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ASettins.device[type].dhndl = alcOpenDevice(ASettins.device[type].devices[ASettins.device[type].index]);
|
||||
|
||||
|
||||
if (alcGetError(ASettins.device[type].dhndl) != AL_NO_ERROR) {
|
||||
|
||||
|
||||
/* Now check if we have previous device and act acording to it */
|
||||
if ( !prev_device ) {
|
||||
error = "Error starting output device!";
|
||||
|
||||
|
||||
ASettins.errors |= ErrorStartingOutputDevice;
|
||||
ASettins.device[type].ctx = NULL;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
error = "Could not start output device, falling back to previous";
|
||||
|
||||
|
||||
/* NOTE: What if device is opened? */
|
||||
ASettins.device[type].dhndl = prev_device;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
|
||||
/* Close previous */
|
||||
if ( prev_device ) {
|
||||
alcCaptureCloseDevice(prev_device);
|
||||
alcCaptureCloseDevice(prev_device);
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(ASettins.device[type].ctx);
|
||||
}
|
||||
|
||||
|
||||
ASettins.device[type].ctx = alcCreateContext(ASettins.device[type].dhndl, NULL);
|
||||
|
||||
|
||||
if ( window ) {
|
||||
snprintf(msg, sizeof(msg), "Output device: %s", ASettins.device[type].devices[ASettins.device[type].index]);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( error ) {
|
||||
if ( window ) {
|
||||
snprintf(msg, sizeof(msg), "Error: %s", error);
|
||||
@ -174,32 +168,30 @@ int device_open (ToxWindow *self, _Devices type)
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
else return 0;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
int device_close (ToxWindow *self, _Devices type)
|
||||
{
|
||||
uint8_t* device = NULL;
|
||||
|
||||
uint8_t *device = NULL;
|
||||
|
||||
if ( ASettins.device[type].dhndl ) {
|
||||
if (type == input) {
|
||||
alcCaptureCloseDevice(ASettins.device[type].dhndl);
|
||||
device = "input";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
alcCloseDevice(ASettins.device[type].dhndl);
|
||||
alcMakeContextCurrent(NULL);
|
||||
|
||||
|
||||
if ( ASettins.device[type].ctx )
|
||||
alcDestroyContext(ASettins.device[type].ctx);
|
||||
|
||||
|
||||
device = "output";
|
||||
}
|
||||
|
||||
|
||||
ASettins.device[type].index = ASettins.device[type].dix;
|
||||
}
|
||||
|
||||
|
||||
if ( self && device ) {
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
snprintf(msg, sizeof(msg), "Closed %s device", device);
|
||||
@ -207,86 +199,85 @@ int device_close (ToxWindow *self, _Devices type)
|
||||
}
|
||||
}
|
||||
|
||||
ToxAv* init_audio(ToxWindow* self, Tox* tox)
|
||||
ToxAv *init_audio(ToxWindow *self, Tox *tox)
|
||||
{
|
||||
ASettins.errors = NoError;
|
||||
ASettins.ttas = 0; /* Not running */
|
||||
|
||||
|
||||
/* Capture devices */
|
||||
const char* stringed_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||
const char *stringed_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||
ASettins.device[input].size = 0;
|
||||
|
||||
|
||||
if ( stringed_device_list ) {
|
||||
const char* default_device = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
|
||||
|
||||
const char *default_device = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
|
||||
|
||||
for ( ; *stringed_device_list; ++ASettins.device[input].size ) {
|
||||
ASettins.device[input].devices[ASettins.device[input].size] = stringed_device_list;
|
||||
|
||||
|
||||
if ( strcmp( default_device , ASettins.device[input].devices[ASettins.device[input].size] ) == 0 )
|
||||
ASettins.device[input].index = ASettins.device[input].dix = ASettins.device[input].size;
|
||||
|
||||
|
||||
stringed_device_list += strlen( stringed_device_list ) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Output devices */
|
||||
stringed_device_list = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||
ASettins.device[output].size = 0;
|
||||
|
||||
|
||||
if ( stringed_device_list ) {
|
||||
const char* default_device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||
|
||||
const char *default_device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||
|
||||
for ( ; *stringed_device_list; ++ASettins.device[output].size ) {
|
||||
ASettins.device[output].devices[ASettins.device[output].size] = stringed_device_list;
|
||||
|
||||
ASettins.device[output].devices[ASettins.device[output].size] = stringed_device_list;
|
||||
|
||||
if ( strcmp( default_device , ASettins.device[output].devices[ASettins.device[output].size] ) == 0 )
|
||||
ASettins.device[output].index = ASettins.device[output].dix = ASettins.device[output].size;
|
||||
|
||||
|
||||
stringed_device_list += strlen( stringed_device_list ) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!ASettins.device[input].size && !ASettins.device[output].size) {
|
||||
uint8_t *msg = "No devices: disabling audio!";
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
ASettins.av = NULL;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* Streaming stuff from core */
|
||||
|
||||
|
||||
ToxAvCodecSettings cs = av_DefaultSettings;
|
||||
cs.video_height = cs.video_width = 0;
|
||||
|
||||
|
||||
ASettins.av = toxav_new(tox, &cs);
|
||||
|
||||
|
||||
if ( !ASettins.av ) {
|
||||
ASettins.errors |= ErrorStartingCoreAudio;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
toxav_register_callstate_callback(callback_call_started, av_OnStart, self);
|
||||
toxav_register_callstate_callback(callback_call_canceled, av_OnCancel, self);
|
||||
toxav_register_callstate_callback(callback_call_rejected, av_OnReject, self);
|
||||
toxav_register_callstate_callback(callback_call_ended, av_OnEnd, self);
|
||||
toxav_register_callstate_callback(callback_recv_invite, av_OnInvite, self);
|
||||
|
||||
|
||||
toxav_register_callstate_callback(callback_recv_ringing, av_OnRinging, self);
|
||||
toxav_register_callstate_callback(callback_recv_starting, av_OnStarting, self);
|
||||
toxav_register_callstate_callback(callback_recv_ending, av_OnEnding, self);
|
||||
|
||||
|
||||
toxav_register_callstate_callback(callback_recv_error, av_OnError, self);
|
||||
toxav_register_callstate_callback(callback_requ_timeout, av_OnRequestTimeout, self);
|
||||
toxav_register_callstate_callback(callback_peer_timeout, av_OnPeerTimeout, self);
|
||||
}
|
||||
|
||||
|
||||
return ASettins.av;
|
||||
}
|
||||
|
||||
void terminate_audio()
|
||||
{
|
||||
stop_transmission();
|
||||
|
||||
|
||||
if ( ASettins.av )
|
||||
toxav_kill(ASettins.av);
|
||||
}
|
||||
@ -302,133 +293,135 @@ int errors()
|
||||
* Transmission
|
||||
*/
|
||||
|
||||
void* transmission(void* arg)
|
||||
void *transmission(void *arg)
|
||||
{
|
||||
(void)arg; /* Avoid warning */
|
||||
|
||||
|
||||
/* Missing audio support */
|
||||
if ( !ASettins.av ) _cbend;
|
||||
|
||||
|
||||
ASettins.ttas = 1;
|
||||
|
||||
|
||||
/* Prepare devices */
|
||||
alcCaptureStart(ASettins.device[input].dhndl);
|
||||
alcCaptureStart(ASettins.device[input].dhndl);
|
||||
alcMakeContextCurrent(ASettins.device[output].ctx);
|
||||
|
||||
|
||||
int32_t dec_frame_len;
|
||||
int16_t frame[4096];
|
||||
int32_t sample = 0;
|
||||
int32_t sample = 0;
|
||||
uint32_t buffer;
|
||||
int32_t ready;
|
||||
int32_t openal_buffers = 5;
|
||||
uint32_t source, *buffers;
|
||||
|
||||
|
||||
/* Prepare buffers */
|
||||
buffers = calloc(sizeof(uint32_t), openal_buffers);
|
||||
alGenBuffers(openal_buffers, buffers);
|
||||
alGenSources((uint32_t)1, &source);
|
||||
alSourcei(source, AL_LOOPING, AL_FALSE);
|
||||
|
||||
|
||||
|
||||
|
||||
uint16_t zeros[AUDIO_FRAME_SIZE];
|
||||
memset(zeros, 0, AUDIO_FRAME_SIZE);
|
||||
int16_t PCM[AUDIO_FRAME_SIZE];
|
||||
|
||||
|
||||
int32_t i = 0;
|
||||
|
||||
for (; i < openal_buffers; ++i) {
|
||||
alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, AUDIO_FRAME_SIZE, 48000);
|
||||
}
|
||||
|
||||
|
||||
alSourceQueueBuffers(source, openal_buffers, buffers);
|
||||
alSourcePlay(source);
|
||||
|
||||
|
||||
if (alGetError() != AL_NO_ERROR) {
|
||||
/* Print something? */
|
||||
/*fprintf(stderr, "Error starting audio\n");*/
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
/* Start transmission */
|
||||
while (ASettins.ttas) {
|
||||
|
||||
|
||||
alcGetIntegerv(ASettins.device[input].dhndl, ALC_CAPTURE_SAMPLES, (int32_t) sizeof(int32_t), &sample);
|
||||
|
||||
|
||||
/* RECORD AND SEND */
|
||||
if (sample >= AUDIO_FRAME_SIZE) {
|
||||
alcCaptureSamples(ASettins.device[input].dhndl, frame, AUDIO_FRAME_SIZE);
|
||||
|
||||
if (toxav_send_audio(ASettins.av, frame, AUDIO_FRAME_SIZE) < 0)
|
||||
|
||||
if (toxav_send_audio(ASettins.av, frame, AUDIO_FRAME_SIZE) < 0)
|
||||
/*fprintf(stderr, "Could not encode or send audio packet\n")*/;
|
||||
|
||||
} else usleep(1000);
|
||||
|
||||
|
||||
|
||||
|
||||
} else usleep(1000);
|
||||
|
||||
|
||||
|
||||
/* PLAYBACK */
|
||||
|
||||
|
||||
alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready);
|
||||
|
||||
|
||||
if (ready <= 0)
|
||||
continue;
|
||||
|
||||
|
||||
dec_frame_len = toxav_recv_audio(ASettins.av, AUDIO_FRAME_SIZE, PCM);
|
||||
|
||||
|
||||
/* Play the packet */
|
||||
if (dec_frame_len > 0) {
|
||||
alSourceUnqueueBuffers(source, 1, &buffer);
|
||||
alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000);
|
||||
int32_t error = alGetError();
|
||||
|
||||
|
||||
if (error != AL_NO_ERROR) {
|
||||
/*fprintf(stderr, "Error setting buffer %d\n", error);*/
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
alSourceQueueBuffers(source, 1, &buffer);
|
||||
|
||||
|
||||
if (alGetError() != AL_NO_ERROR) {
|
||||
/*fprintf(stderr, "Error: could not buffer audio\n");*/
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
alGetSourcei(source, AL_SOURCE_STATE, &ready);
|
||||
|
||||
|
||||
if (ready != AL_PLAYING) alSourcePlay(source);
|
||||
}
|
||||
|
||||
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
|
||||
cleanup:
|
||||
|
||||
|
||||
alDeleteSources(1, &source);
|
||||
alDeleteBuffers(openal_buffers, buffers);
|
||||
|
||||
|
||||
device_close(NULL, input);
|
||||
device_close(NULL, output);
|
||||
|
||||
|
||||
_cbend;
|
||||
}
|
||||
|
||||
int start_transmission(ToxWindow *self)
|
||||
{
|
||||
if ( !ASettins.av ) return -1;
|
||||
|
||||
|
||||
if ( !toxav_capability_supported(ASettins.av, AudioDecoding) ||
|
||||
!toxav_capability_supported(ASettins.av, AudioEncoding) )
|
||||
!toxav_capability_supported(ASettins.av, AudioEncoding) )
|
||||
return -1;
|
||||
|
||||
|
||||
/* Now open our devices */
|
||||
if ( -1 == device_open(self, input) )
|
||||
return -1;
|
||||
|
||||
if ( -1 == device_open(self, output))
|
||||
return -1;
|
||||
|
||||
|
||||
/* Don't provide support for video */
|
||||
toxav_prepare_transmission(ASettins.av, 0);
|
||||
|
||||
if ( 0 != pthread_create(&ASettins.ttid, NULL, transmission, NULL ) &&
|
||||
0 != pthread_detach(ASettins.ttid) ) {
|
||||
|
||||
if ( 0 != pthread_create(&ASettins.ttid, NULL, transmission, NULL ) &&
|
||||
0 != pthread_detach(ASettins.ttid) ) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -452,53 +445,53 @@ int stop_transmission()
|
||||
#define CB_BODY(Arg, onFunc) do { ToxWindow* windows = (Arg); int i;\
|
||||
for (i = 0; i < MAX_WINDOWS_NUM; ++i) if (windows[i].onFunc != NULL) windows[i].onFunc(&windows[i], ASettins.av); } while (0)
|
||||
|
||||
void callback_recv_invite ( void* arg )
|
||||
{
|
||||
void callback_recv_invite ( void *arg )
|
||||
{
|
||||
CB_BODY(arg, onInvite);
|
||||
}
|
||||
void callback_recv_ringing ( void* arg )
|
||||
void callback_recv_ringing ( void *arg )
|
||||
{
|
||||
CB_BODY(arg, onRinging);
|
||||
}
|
||||
void callback_recv_starting ( void* arg )
|
||||
void callback_recv_starting ( void *arg )
|
||||
{
|
||||
CB_BODY(arg, onStarting);
|
||||
}
|
||||
void callback_recv_ending ( void* arg )
|
||||
{
|
||||
void callback_recv_ending ( void *arg )
|
||||
{
|
||||
CB_BODY(arg, onEnding);
|
||||
stop_transmission();
|
||||
}
|
||||
void callback_recv_error ( void* arg )
|
||||
void callback_recv_error ( void *arg )
|
||||
{
|
||||
CB_BODY(arg, onError);
|
||||
}
|
||||
void callback_call_started ( void* arg )
|
||||
void callback_call_started ( void *arg )
|
||||
{
|
||||
CB_BODY(arg, onStart);
|
||||
}
|
||||
void callback_call_canceled ( void* arg )
|
||||
void callback_call_canceled ( void *arg )
|
||||
{
|
||||
CB_BODY(arg, onCancel);
|
||||
|
||||
|
||||
/* In case call is active */
|
||||
stop_transmission();
|
||||
}
|
||||
void callback_call_rejected ( void* arg )
|
||||
void callback_call_rejected ( void *arg )
|
||||
{
|
||||
CB_BODY(arg, onReject);
|
||||
}
|
||||
void callback_call_ended ( void* arg )
|
||||
{
|
||||
void callback_call_ended ( void *arg )
|
||||
{
|
||||
CB_BODY(arg, onEnd);
|
||||
stop_transmission();
|
||||
}
|
||||
|
||||
void callback_requ_timeout ( void* arg )
|
||||
void callback_requ_timeout ( void *arg )
|
||||
{
|
||||
CB_BODY(arg, onRequestTimeout);
|
||||
}
|
||||
void callback_peer_timeout ( void* arg )
|
||||
void callback_peer_timeout ( void *arg )
|
||||
{
|
||||
CB_BODY(arg, onPeerTimeout);
|
||||
stop_transmission();
|
||||
@ -507,8 +500,8 @@ void callback_peer_timeout ( void* arg )
|
||||
*/
|
||||
toxav_stop_call(ASettins.av);
|
||||
}
|
||||
/*
|
||||
* End of Callbacks
|
||||
/*
|
||||
* End of Callbacks
|
||||
*/
|
||||
|
||||
|
||||
@ -518,18 +511,24 @@ void callback_peer_timeout ( void* arg )
|
||||
void cmd_call(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
uint8_t* error_str;
|
||||
|
||||
if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; }
|
||||
|
||||
if ( !ASettins.av ) { error_str = "Audio not supported!"; goto on_error; }
|
||||
|
||||
uint8_t *error_str;
|
||||
|
||||
if (argc != 0) {
|
||||
error_str = "Invalid syntax!";
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if ( !ASettins.av ) {
|
||||
error_str = "Audio not supported!";
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
ToxAvError error = toxav_call(ASettins.av, self->num, TypeAudio, 30);
|
||||
|
||||
|
||||
if ( error != ErrorNone ) {
|
||||
if ( error == ErrorAlreadyInCall ) error_str = "Already in a call!";
|
||||
else error_str = "Internal error!";
|
||||
|
||||
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
@ -544,98 +543,123 @@ on_error:
|
||||
|
||||
void cmd_answer(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
uint8_t* error_str;
|
||||
|
||||
if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; }
|
||||
|
||||
if ( !ASettins.av ) { error_str = "Audio not supported!"; goto on_error; }
|
||||
|
||||
uint8_t *error_str;
|
||||
|
||||
if (argc != 0) {
|
||||
error_str = "Invalid syntax!";
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if ( !ASettins.av ) {
|
||||
error_str = "Audio not supported!";
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
ToxAvError error = toxav_answer(ASettins.av, TypeAudio);
|
||||
|
||||
|
||||
if ( error != ErrorNone ) {
|
||||
if ( error == ErrorInvalidState ) error_str = "Cannot answer in invalid state!";
|
||||
else if ( error == ErrorNoCall ) error_str = "No incomming call!";
|
||||
else error_str = "Internal error!";
|
||||
|
||||
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
|
||||
/* Callback will print status... */
|
||||
|
||||
|
||||
return;
|
||||
on_error:
|
||||
on_error:
|
||||
print_err (self, error_str);
|
||||
}
|
||||
|
||||
void cmd_reject(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
uint8_t* error_str;
|
||||
|
||||
if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; }
|
||||
|
||||
if ( !ASettins.av ) { error_str = "Audio not supported!"; goto on_error; }
|
||||
|
||||
uint8_t *error_str;
|
||||
|
||||
if (argc != 0) {
|
||||
error_str = "Invalid syntax!";
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if ( !ASettins.av ) {
|
||||
error_str = "Audio not supported!";
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
ToxAvError error = toxav_reject(ASettins.av, "Why not?");
|
||||
|
||||
|
||||
if ( error != ErrorNone ) {
|
||||
if ( error == ErrorInvalidState ) error_str = "Cannot reject in invalid state!";
|
||||
else if ( error == ErrorNoCall ) error_str = "No incomming call!";
|
||||
else error_str = "Internal error!";
|
||||
|
||||
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
|
||||
/* Callback will print status... */
|
||||
|
||||
|
||||
return;
|
||||
on_error:
|
||||
on_error:
|
||||
print_err (self, error_str);
|
||||
}
|
||||
|
||||
void cmd_hangup(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
uint8_t* error_str;
|
||||
|
||||
if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; }
|
||||
|
||||
if ( !ASettins.av ) { error_str = "Audio not supported!"; goto on_error; }
|
||||
|
||||
uint8_t *error_str;
|
||||
|
||||
if (argc != 0) {
|
||||
error_str = "Invalid syntax!";
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if ( !ASettins.av ) {
|
||||
error_str = "Audio not supported!";
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
ToxAvError error = toxav_hangup(ASettins.av);
|
||||
|
||||
|
||||
if ( error != ErrorNone ) {
|
||||
if ( error == ErrorInvalidState ) error_str = "Cannot hangup in invalid state!";
|
||||
else if ( error == ErrorNoCall ) error_str = "No call!";
|
||||
else error_str = "Internal error!";
|
||||
|
||||
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
on_error:
|
||||
on_error:
|
||||
print_err (self, error_str);
|
||||
}
|
||||
|
||||
void cmd_cancel(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
uint8_t* error_str;
|
||||
|
||||
if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; }
|
||||
|
||||
if ( !ASettins.av ) { error_str = "Audio not supported!"; goto on_error; }
|
||||
|
||||
ToxAvError error = toxav_cancel(ASettins.av, self->num, "Only those who appreciate small things know the beauty of life");
|
||||
|
||||
uint8_t *error_str;
|
||||
|
||||
if (argc != 0) {
|
||||
error_str = "Invalid syntax!";
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if ( !ASettins.av ) {
|
||||
error_str = "Audio not supported!";
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
ToxAvError error = toxav_cancel(ASettins.av, self->num,
|
||||
"Only those who appreciate small things know the beauty of life");
|
||||
|
||||
if ( error != ErrorNone ) {
|
||||
if ( error == ErrorNoCall ) error_str = "No call!";
|
||||
else error_str = "Internal error!";
|
||||
|
||||
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
|
||||
/* Callback will print status... */
|
||||
|
||||
|
||||
return;
|
||||
on_error:
|
||||
on_error:
|
||||
print_err (self, error_str);
|
||||
}
|
||||
|
||||
@ -643,76 +667,77 @@ on_error:
|
||||
void cmd_list_devices(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
uint8_t* error_str;
|
||||
|
||||
uint8_t *error_str;
|
||||
|
||||
if ( argc != 1 ) {
|
||||
if ( argc < 1 ) error_str = "Type must be specified!";
|
||||
if ( argc < 1 ) error_str = "Type must be specified!";
|
||||
else error_str = "Only one argument allowed!";
|
||||
|
||||
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
|
||||
_Devices type;
|
||||
|
||||
|
||||
if ( strcmp(argv[1], "in") == 0 ) /* Input devices */
|
||||
type = input;
|
||||
|
||||
|
||||
else if ( strcmp(argv[1], "out") == 0 ) /* Output devices */
|
||||
type = output;
|
||||
|
||||
|
||||
else {
|
||||
snprintf(msg, sizeof(msg), "Invalid type: %s", argv[1]);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int i = 0;
|
||||
|
||||
for ( ; i < ASettins.device[type].size; i ++) {
|
||||
snprintf(msg, sizeof(msg), "%d: %s", i, ASettins.device[type].devices[i]);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
on_error:
|
||||
on_error:
|
||||
print_err (self, error_str);
|
||||
}
|
||||
|
||||
void cmd_change_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
uint8_t* error_str;
|
||||
|
||||
uint8_t *error_str;
|
||||
|
||||
if ( argc != 2 ) {
|
||||
if ( argc < 1 ) error_str = "Type must be specified!";
|
||||
else if ( argc < 2 ) error_str = "Must have id!";
|
||||
else error_str = "Only two arguments allowed!";
|
||||
|
||||
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
|
||||
if ( ASettins.ttas ) { /* Transmission is active */
|
||||
error_str = "Cannot change device while active transmission";
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
|
||||
_Devices type;
|
||||
|
||||
|
||||
if ( strcmp(argv[1], "in") == 0 ) /* Input devices */
|
||||
type = input;
|
||||
|
||||
|
||||
else if ( strcmp(argv[1], "out") == 0 ) /* Output devices */
|
||||
type = output;
|
||||
|
||||
|
||||
else {
|
||||
snprintf(msg, sizeof(msg), "Invalid type: %s", argv[1]);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
char *end;
|
||||
long int selection = strtol(argv[2], &end, 10);
|
||||
|
||||
|
||||
if ( *end ) {
|
||||
error_str = "Invalid input";
|
||||
goto on_error;
|
||||
@ -724,6 +749,6 @@ void cmd_change_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (
|
||||
}
|
||||
|
||||
return;
|
||||
on_error:
|
||||
on_error:
|
||||
print_err (self, error_str);
|
||||
}
|
||||
|
@ -9,24 +9,22 @@
|
||||
|
||||
#define MAX_DEVICES 32
|
||||
|
||||
typedef enum _AudioError
|
||||
{
|
||||
typedef enum _AudioError {
|
||||
NoError = 0,
|
||||
ErrorStartingCaptureDevice = 1 << 0,
|
||||
ErrorStartingOutputDevice = 1 << 1,
|
||||
ErrorStartingCoreAudio = 1 << 2
|
||||
} AudioError;
|
||||
|
||||
typedef enum _Devices
|
||||
{
|
||||
typedef enum _Devices {
|
||||
input,
|
||||
output,
|
||||
} _Devices;
|
||||
|
||||
/* You will have to pass pointer to first member of 'windows'
|
||||
* declared in windows.c otherwise undefined behaviour will
|
||||
/* You will have to pass pointer to first member of 'windows'
|
||||
* declared in windows.c otherwise undefined behaviour will
|
||||
*/
|
||||
ToxAv* init_audio(ToxWindow* self, Tox* tox);
|
||||
ToxAv *init_audio(ToxWindow *self, Tox *tox);
|
||||
void terminate_audio();
|
||||
|
||||
int errors();
|
||||
|
139
src/chat.c
139
src/chat.c
@ -38,7 +38,7 @@
|
||||
#include "settings.h"
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#include "audio_call.h"
|
||||
#include "audio_call.h"
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
extern char *DATA_FILE;
|
||||
@ -51,9 +51,9 @@ extern struct _Winthread Winthread;
|
||||
extern struct user_settings *user_settings;
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#define AC_NUM_CHAT_COMMANDS 23
|
||||
#define AC_NUM_CHAT_COMMANDS 23
|
||||
#else
|
||||
#define AC_NUM_CHAT_COMMANDS 18
|
||||
#define AC_NUM_CHAT_COMMANDS 18
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
/* Array of chat command names used for tab completion. */
|
||||
@ -76,15 +76,15 @@ static const uint8_t chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
|
||||
{ "/savefile" },
|
||||
{ "/sendfile" },
|
||||
{ "/status" },
|
||||
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
|
||||
|
||||
{ "/call" },
|
||||
{ "/cancel" },
|
||||
{ "/answer" },
|
||||
{ "/reject" },
|
||||
{ "/hangup" },
|
||||
|
||||
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
};
|
||||
|
||||
@ -129,7 +129,7 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int32_t num, uint8_t *msg, u
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH];
|
||||
int n_len = tox_get_name(m, num, nick);
|
||||
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
nick[n_len] = '\0';
|
||||
|
||||
uint8_t timefrmt[TIME_STR_SIZE];
|
||||
@ -178,7 +178,7 @@ static void chat_onAction(ToxWindow *self, Tox *m, int32_t num, uint8_t *action,
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH];
|
||||
int n_len = tox_get_name(m, num, nick);
|
||||
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH-1);;
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);;
|
||||
nick[n_len] = '\0';
|
||||
|
||||
uint8_t timefrmt[TIME_STR_SIZE];
|
||||
@ -194,7 +194,7 @@ static void chat_onNickChange(ToxWindow *self, Tox *m, int32_t num, uint8_t *nic
|
||||
if (self->num != num)
|
||||
return;
|
||||
|
||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
nick[len] = '\0';
|
||||
strcpy(self->name, nick);
|
||||
}
|
||||
@ -219,7 +219,7 @@ static void chat_onStatusMessageChange(ToxWindow *self, int32_t num, uint8_t *st
|
||||
statusbar->statusmsg[len] = '\0';
|
||||
}
|
||||
|
||||
static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum,
|
||||
static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum,
|
||||
uint64_t filesize, uint8_t *pathname, uint16_t path_len)
|
||||
{
|
||||
if (self->num != num)
|
||||
@ -231,8 +231,8 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
|
||||
uint8_t filename[MAX_STR_SIZE];
|
||||
get_file_name(pathname, filename);
|
||||
|
||||
snprintf(msg, sizeof(msg), "File transfer request for '%s' (%llu bytes).", filename,
|
||||
(long long unsigned int)filesize);
|
||||
snprintf(msg, sizeof(msg), "File transfer request for '%s' (%llu bytes).", filename,
|
||||
(long long unsigned int)filesize);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
|
||||
if (filenum >= MAX_FILES) {
|
||||
@ -249,7 +249,7 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
|
||||
while ((filecheck = fopen(filename, "r"))) {
|
||||
filename[len] = '\0';
|
||||
char d[9];
|
||||
sprintf(d,"(%d)", count++);
|
||||
sprintf(d, "(%d)", count++);
|
||||
strcat(filename, d);
|
||||
filename[len + strlen(d)] = '\0';
|
||||
|
||||
@ -280,7 +280,7 @@ static void chat_close_file_receiver(int num, uint8_t filenum)
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t receive_send,
|
||||
static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t receive_send,
|
||||
uint8_t filenum, uint8_t control_type, uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (self->num != num)
|
||||
@ -295,22 +295,26 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
|
||||
filename = file_senders[filenum].pathname;
|
||||
|
||||
switch (control_type) {
|
||||
case TOX_FILECONTROL_ACCEPT:
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' accepted (%.1f%%)", filename, 0.0);
|
||||
file_senders[filenum].line_id = self->chatwin->hst->line_end->id + 1;
|
||||
break;
|
||||
/*case TOX_FILECONTROL_PAUSE:
|
||||
wprintw(ctx->history, "File transfer for '%s' paused.\n", filename);
|
||||
break; */
|
||||
case TOX_FILECONTROL_KILL:
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", filename);
|
||||
if (receive_send == 0)
|
||||
case TOX_FILECONTROL_ACCEPT:
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' accepted (%.1f%%)", filename, 0.0);
|
||||
file_senders[filenum].line_id = self->chatwin->hst->line_end->id + 1;
|
||||
break;
|
||||
|
||||
/*case TOX_FILECONTROL_PAUSE:
|
||||
wprintw(ctx->history, "File transfer for '%s' paused.\n", filename);
|
||||
break; */
|
||||
case TOX_FILECONTROL_KILL:
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", filename);
|
||||
|
||||
if (receive_send == 0)
|
||||
chat_close_file_receiver(num, filenum);
|
||||
|
||||
break;
|
||||
|
||||
case TOX_FILECONTROL_FINISHED:
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename);
|
||||
chat_close_file_receiver(num, filenum);
|
||||
break;
|
||||
case TOX_FILECONTROL_FINISHED:
|
||||
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename);
|
||||
chat_close_file_receiver(num, filenum);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
@ -355,11 +359,11 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, ui
|
||||
uint8_t msg[MAX_STR_SIZE + TOX_MAX_NAME_LENGTH];
|
||||
int n_len = tox_get_name(m, friendnumber, name);
|
||||
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
name[n_len] = '\0';
|
||||
|
||||
snprintf(msg, sizeof(msg), "%s has invited you to a group chat.\n"
|
||||
"Type \"/join\" to join the chat.", name);
|
||||
"Type \"/join\" to join the chat.", name);
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
|
||||
memcpy(friends[friendnumber].pending_groupchat, group_pub_key, TOX_CLIENT_ID_SIZE);
|
||||
@ -376,7 +380,7 @@ void chat_onInvite (ToxWindow *self, ToxAv *av)
|
||||
|
||||
uint8_t *msg = "Incoming audio call!\nType: \"/answer\" or \"/reject\"";
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
|
||||
|
||||
alert_window(self, WINDOW_ALERT_0, true);
|
||||
}
|
||||
|
||||
@ -427,7 +431,7 @@ void chat_onError (ToxWindow *self, ToxAv *av)
|
||||
}
|
||||
|
||||
void chat_onStart (ToxWindow *self, ToxAv *av)
|
||||
{
|
||||
{
|
||||
if (self->num != toxav_get_peer_id(av, 0))
|
||||
return;
|
||||
|
||||
@ -492,7 +496,8 @@ void chat_onPeerTimeout (ToxWindow *self, ToxAv *av)
|
||||
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, uint8_t *action) {
|
||||
static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, uint8_t *action)
|
||||
{
|
||||
if (action == NULL)
|
||||
return;
|
||||
|
||||
@ -536,11 +541,11 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
|
||||
if (ltr) {
|
||||
/* prevents buffer overflows and strange behaviour when cursor goes past the window */
|
||||
if ( (ctx->len < MAX_STR_SIZE-1) && (ctx->len < (x2 * (CHATBOX_HEIGHT - 1)-1)) ) {
|
||||
if ( (ctx->len < MAX_STR_SIZE - 1) && (ctx->len < (x2 * (CHATBOX_HEIGHT - 1) - 1)) ) {
|
||||
add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key);
|
||||
|
||||
if (x == x2-1)
|
||||
wmove(self->window, y+1, 0);
|
||||
if (x == x2 - 1)
|
||||
wmove(self->window, y + 1, 0);
|
||||
else
|
||||
wmove(self->window, y, x + MAX(1, wcwidth(key)));
|
||||
}
|
||||
@ -556,7 +561,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
|
||||
|
||||
if (x == 0)
|
||||
wmove(self->window, y-1, x2 - cur_len);
|
||||
wmove(self->window, y - 1, x2 - cur_len);
|
||||
else
|
||||
wmove(self->window, y, x - cur_len);
|
||||
} else {
|
||||
@ -597,7 +602,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
else if (key == KEY_END || key == T_KEY_C_E) { /* END/C-e key: move cursor to end of line */
|
||||
if (ctx->pos != ctx->len) {
|
||||
ctx->pos = ctx->len;
|
||||
mv_curs_end(self->window, MAX(0, wcswidth(ctx->line, (CHATBOX_HEIGHT-1)*x2)), y2, x2);
|
||||
mv_curs_end(self->window, MAX(0, wcswidth(ctx->line, (CHATBOX_HEIGHT - 1)*x2)), y2, x2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -607,7 +612,7 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
|
||||
|
||||
if (x == 0)
|
||||
wmove(self->window, y-1, x2 - cur_len);
|
||||
wmove(self->window, y - 1, x2 - cur_len);
|
||||
else
|
||||
wmove(self->window, y, x - cur_len);
|
||||
} else {
|
||||
@ -620,8 +625,8 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
|
||||
++ctx->pos;
|
||||
|
||||
if (x == x2-1)
|
||||
wmove(self->window, y+1, 0);
|
||||
if (x == x2 - 1)
|
||||
wmove(self->window, y + 1, 0);
|
||||
else
|
||||
wmove(self->window, y, x + cur_len);
|
||||
} else {
|
||||
@ -649,9 +654,9 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
if (diff != -1) {
|
||||
if (x + diff > x2 - 1) {
|
||||
int ofst = (x + diff - 1) - (x2 - 1);
|
||||
wmove(self->window, y+1, ofst);
|
||||
wmove(self->window, y + 1, ofst);
|
||||
} else {
|
||||
wmove(self->window, y, x+diff);
|
||||
wmove(self->window, y, x + diff);
|
||||
}
|
||||
} else {
|
||||
beep();
|
||||
@ -730,7 +735,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
|
||||
|
||||
if (ctx->len > 0 && !ctx->hst->scroll_mode) {
|
||||
uint8_t line[MAX_STR_SIZE];
|
||||
|
||||
|
||||
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) {
|
||||
reset_buf(ctx->line, &ctx->pos, &ctx->len);
|
||||
wmove(self->window, y2 - CURS_Y_OFFSET, 0);
|
||||
@ -753,22 +758,25 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
|
||||
uint8_t status = statusbar->status;
|
||||
|
||||
switch (status) {
|
||||
case TOX_USERSTATUS_NONE:
|
||||
status_text = "Online";
|
||||
colour = GREEN;
|
||||
break;
|
||||
case TOX_USERSTATUS_AWAY:
|
||||
status_text = "Away";
|
||||
colour = YELLOW;
|
||||
break;
|
||||
case TOX_USERSTATUS_BUSY:
|
||||
status_text = "Busy";
|
||||
colour = RED;
|
||||
break;
|
||||
case TOX_USERSTATUS_INVALID:
|
||||
status_text = "ERROR";
|
||||
colour = MAGENTA;
|
||||
break;
|
||||
case TOX_USERSTATUS_NONE:
|
||||
status_text = "Online";
|
||||
colour = GREEN;
|
||||
break;
|
||||
|
||||
case TOX_USERSTATUS_AWAY:
|
||||
status_text = "Away";
|
||||
colour = YELLOW;
|
||||
break;
|
||||
|
||||
case TOX_USERSTATUS_BUSY:
|
||||
status_text = "Busy";
|
||||
colour = RED;
|
||||
break;
|
||||
|
||||
case TOX_USERSTATUS_INVALID:
|
||||
status_text = "ERROR";
|
||||
colour = MAGENTA;
|
||||
break;
|
||||
}
|
||||
|
||||
wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
|
||||
@ -808,6 +816,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
|
||||
|
||||
/* Truncate note if it doesn't fit in statusbar */
|
||||
uint16_t maxlen = x2 - getcurx(statusbar->topline) - (KEY_IDENT_DIGITS * 2) - 7;
|
||||
|
||||
if (statusbar->statusmsg_len > maxlen) {
|
||||
statusbar->statusmsg[maxlen] = '\0';
|
||||
statusbar->statusmsg_len = maxlen;
|
||||
@ -852,9 +861,9 @@ static void chat_onInit(ToxWindow *self, Tox *m)
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
statusbar->topline = subwin(self->window, 2, x2, 0, 0);
|
||||
ctx->history = subwin(self->window, y2-CHATBOX_HEIGHT+1, x2, 0, 0);
|
||||
ctx->history = subwin(self->window, y2 - CHATBOX_HEIGHT + 1, x2, 0, 0);
|
||||
scrollok(ctx->history, 1);
|
||||
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2-CHATBOX_HEIGHT, 0);
|
||||
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2 - CHATBOX_HEIGHT, 0);
|
||||
|
||||
ctx->hst = malloc(sizeof(struct history));
|
||||
ctx->log = malloc(sizeof(struct chatlog));
|
||||
@ -901,7 +910,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
|
||||
ret.onFileSendRequest = &chat_onFileSendRequest;
|
||||
ret.onFileControl = &chat_onFileControl;
|
||||
ret.onFileData = &chat_onFileData;
|
||||
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
ret.onInvite = &chat_onInvite;
|
||||
ret.onRinging = &chat_onRinging;
|
||||
@ -919,7 +928,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
|
||||
uint8_t name[TOX_MAX_NAME_LENGTH] = {'\0'};
|
||||
int len = tox_get_name(m, friendnum, name);
|
||||
|
||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
|
||||
name[len] = '\0';
|
||||
strcpy(ret.name, name);
|
||||
|
@ -57,29 +57,29 @@ void cmd_chat_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#define NUMLINES 13
|
||||
#define NUMLINES 13
|
||||
#else
|
||||
#define NUMLINES 9
|
||||
#define NUMLINES 9
|
||||
#endif
|
||||
|
||||
uint8_t lines[NUMLINES][MAX_STR_SIZE] = {
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
{ " /call : Audio call" },
|
||||
{ " /cancel : Cancel call" },
|
||||
{ " /answer : Answer incomming call" },
|
||||
{ " /reject : Reject incoming call" },
|
||||
{ " /hangup : Hangup active call" },
|
||||
{ " /call : Audio call" },
|
||||
{ " /cancel : Cancel call" },
|
||||
{ " /answer : Answer incomming call" },
|
||||
{ " /reject : Reject incoming call" },
|
||||
{ " /hangup : Hangup active call" },
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
{ " /invite <n> : Invite friend to a group chat" },
|
||||
{ " /join : Join a pending group chat" },
|
||||
{ " /log <on> or <off> : Enable/disable logging" },
|
||||
{ " /sendfile <filepath> : Send a file" },
|
||||
{ " /savefile <n> : Receive a file" },
|
||||
{ " /close : Close the current chat window" },
|
||||
{ " /help : Print this message again" },
|
||||
{ " /help global : Show a list of global commands" },
|
||||
};
|
||||
{ " /invite <n> : Invite friend to a group chat" },
|
||||
{ " /join : Join a pending group chat" },
|
||||
{ " /log <on> or <off> : Enable/disable logging" },
|
||||
{ " /sendfile <filepath> : Send a file" },
|
||||
{ " /savefile <n> : Receive a file" },
|
||||
{ " /close : Close the current chat window" },
|
||||
{ " /help : Print this message again" },
|
||||
{ " /help global : Show a list of global commands" },
|
||||
};
|
||||
|
||||
int i;
|
||||
|
||||
@ -160,9 +160,9 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
uint8_t *errmsg;
|
||||
|
||||
if (argc != 1) {
|
||||
errmsg = "Invalid syntax.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
errmsg = "Invalid syntax.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t filenum = atoi(argv[1]);
|
||||
@ -204,16 +204,16 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
{
|
||||
uint8_t *errmsg;
|
||||
|
||||
if (max_file_senders_index >= (MAX_FILES-1)) {
|
||||
if (max_file_senders_index >= (MAX_FILES - 1)) {
|
||||
errmsg = "Please wait for some of your outgoing file transfers to complete.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (argc < 1) {
|
||||
errmsg = "Invalid syntax.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
errmsg = "Invalid syntax.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *path = argv[1];
|
||||
@ -224,7 +224,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
return;
|
||||
}
|
||||
|
||||
path[strlen(++path)-1] = L'\0';
|
||||
path[strlen(++path) - 1] = L'\0';
|
||||
int path_len = strlen(path);
|
||||
|
||||
if (path_len > MAX_STR_SIZE) {
|
||||
@ -279,5 +279,5 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,6 +110,7 @@ char *get_user_config_dir(void)
|
||||
# else /* __APPLE__ */
|
||||
|
||||
const char *tmp;
|
||||
|
||||
if (!(tmp = getenv("XDG_CONFIG_HOME"))) {
|
||||
len = strlen(home) + strlen("/.config") + 1;
|
||||
user_config_dir = malloc(len);
|
||||
|
@ -66,7 +66,7 @@ static struct cmd_func chat_commands[] = {
|
||||
{ "/join", cmd_join_group },
|
||||
{ "/savefile", cmd_savefile },
|
||||
{ "/sendfile", cmd_sendfile },
|
||||
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
{ "/call", cmd_call },
|
||||
{ "/cancel", cmd_cancel },
|
||||
@ -76,7 +76,7 @@ static struct cmd_func chat_commands[] = {
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
};
|
||||
|
||||
/* Parses input command and puts args into arg array.
|
||||
/* Parses input command and puts args into arg array.
|
||||
Returns number of arguments on success, -1 on failure. */
|
||||
static int parse_command(WINDOW *w, ToxWindow *self, char *cmd, char (*args)[MAX_STR_SIZE])
|
||||
{
|
||||
@ -87,7 +87,7 @@ static int parse_command(WINDOW *w, ToxWindow *self, char *cmd, char (*args)[MAX
|
||||
/* characters wrapped in double quotes count as one arg */
|
||||
while (!cmd_end && num_args < MAX_NUM_ARGS) {
|
||||
if (*cmd == '\"') {
|
||||
end = strchr(cmd+1, '\"');
|
||||
end = strchr(cmd + 1, '\"');
|
||||
|
||||
if (end++ == NULL) { /* Increment past the end quote */
|
||||
uint8_t *errmsg = "Invalid argument. Did you forget a closing \"?";
|
||||
@ -120,7 +120,7 @@ static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, int num_
|
||||
|
||||
for (i = 0; i < num_cmds; ++i) {
|
||||
if (strcmp(args[0], commands[i].name) == 0) {
|
||||
(commands[i].func)(w, self, m, num_args-1, args);
|
||||
(commands[i].func)(w, self, m, num_args - 1, args);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -128,7 +128,7 @@ static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, int num_
|
||||
return 1;
|
||||
}
|
||||
|
||||
void execute(WINDOW* w, ToxWindow *self, Tox *m, char *cmd, int mode)
|
||||
void execute(WINDOW *w, ToxWindow *self, Tox *m, char *cmd, int mode)
|
||||
{
|
||||
if (string_is_empty(cmd))
|
||||
return;
|
||||
@ -139,18 +139,19 @@ void execute(WINDOW* w, ToxWindow *self, Tox *m, char *cmd, int mode)
|
||||
if (num_args == -1)
|
||||
return;
|
||||
|
||||
/* Try to match input command to command functions. If non-global command mode is specified,
|
||||
try specified mode's commands first, then upon failure try global commands.
|
||||
/* Try to match input command to command functions. If non-global command mode is specified,
|
||||
try specified mode's commands first, then upon failure try global commands.
|
||||
|
||||
Note: Global commands must come last in case of duplicate command names */
|
||||
switch (mode) {
|
||||
case CHAT_COMMAND_MODE:
|
||||
if (do_command(w, self, m, num_args, CHAT_NUM_COMMANDS, chat_commands, args) == 0)
|
||||
return;
|
||||
break;
|
||||
case CHAT_COMMAND_MODE:
|
||||
if (do_command(w, self, m, num_args, CHAT_NUM_COMMANDS, chat_commands, args) == 0)
|
||||
return;
|
||||
|
||||
case GROUPCHAT_COMMAND_MODE:
|
||||
break;
|
||||
break;
|
||||
|
||||
case GROUPCHAT_COMMAND_MODE:
|
||||
break;
|
||||
}
|
||||
|
||||
if (do_command(w, self, m, num_args, GLOBAL_NUM_COMMANDS, global_commands, args) == 0)
|
||||
|
@ -22,12 +22,12 @@
|
||||
|
||||
#define MAX_NUM_ARGS 4 /* Includes command */
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#define GLOBAL_NUM_COMMANDS 16
|
||||
#define CHAT_NUM_COMMANDS 10
|
||||
#else
|
||||
#define GLOBAL_NUM_COMMANDS 14
|
||||
#define CHAT_NUM_COMMANDS 5
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#define GLOBAL_NUM_COMMANDS 16
|
||||
#define CHAT_NUM_COMMANDS 10
|
||||
#else
|
||||
#define GLOBAL_NUM_COMMANDS 14
|
||||
#define CHAT_NUM_COMMANDS 5
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
enum {
|
||||
|
@ -42,7 +42,7 @@ static void close_file_sender(int i)
|
||||
int j;
|
||||
|
||||
for (j = max_file_senders_index; j > 0; --j) {
|
||||
if (file_senders[j-1].active)
|
||||
if (file_senders[j - 1].active)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -90,12 +90,12 @@ void do_file_senders(Tox *m)
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (tox_file_send_data(m, friendnum, filenum, file_senders[i].nextpiece,
|
||||
if (tox_file_send_data(m, friendnum, filenum, file_senders[i].nextpiece,
|
||||
file_senders[i].piecelen) == -1)
|
||||
break;
|
||||
|
||||
file_senders[i].timestamp = current_time;
|
||||
file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1,
|
||||
file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1,
|
||||
tox_file_data_size(m, friendnum), fp);
|
||||
|
||||
/* refresh line with percentage complete */
|
||||
|
@ -93,8 +93,8 @@ static void update_friend_last_online(int32_t num, uint64_t timestamp)
|
||||
|
||||
/* if the format changes make sure TIME_STR_SIZE is the correct size */
|
||||
const char *t = user_settings->time == TIME_12 ? "%I:%M %p" : "%H:%M";
|
||||
strftime(friends[num].last_online.hour_min_str, TIME_STR_SIZE, t,
|
||||
&friends[num].last_online.tm);
|
||||
strftime(friends[num].last_online.hour_min_str, TIME_STR_SIZE, t,
|
||||
&friends[num].last_online.tm);
|
||||
}
|
||||
|
||||
static void friendlist_onMessage(ToxWindow *self, Tox *m, int32_t num, uint8_t *str, uint16_t len)
|
||||
@ -110,7 +110,7 @@ static void friendlist_onMessage(ToxWindow *self, Tox *m, int32_t num, uint8_t *
|
||||
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
|
||||
int n_len = tox_get_name(m, num, nick);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
nick[n_len] = '\0';
|
||||
|
||||
uint8_t timefrmt[TIME_STR_SIZE];
|
||||
@ -141,7 +141,7 @@ static void friendlist_onNickChange(ToxWindow *self, Tox *m, int32_t num, uint8_
|
||||
if (len > TOX_MAX_NAME_LENGTH || num >= max_friends_index)
|
||||
return;
|
||||
|
||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
|
||||
str[len] = '\0';
|
||||
strcpy(friends[num].name, str);
|
||||
@ -207,8 +207,8 @@ void friendlist_onFriendAdded(ToxWindow *self, Tox *m, int32_t num, bool sort)
|
||||
}
|
||||
}
|
||||
|
||||
static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum,
|
||||
uint64_t filesize, uint8_t *filename, uint16_t filename_len)
|
||||
static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum,
|
||||
uint64_t filesize, uint8_t *filename, uint16_t filename_len)
|
||||
{
|
||||
if (num >= max_friends_index)
|
||||
return;
|
||||
@ -221,7 +221,7 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u
|
||||
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH];
|
||||
int n_len = tox_get_name(m, num, nick);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
nick[n_len] = '\0';
|
||||
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
@ -244,7 +244,7 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, uint8
|
||||
} else {
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH];
|
||||
int n_len = tox_get_name(m, num, nick);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
nick[n_len] = '\0';
|
||||
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
@ -270,11 +270,11 @@ static void delete_friend(Tox *m, int32_t f_num)
|
||||
{
|
||||
tox_del_friend(m, f_num);
|
||||
memset(&friends[f_num], 0, sizeof(ToxicFriend));
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
for (i = max_friends_index; i > 0; --i) {
|
||||
if (friends[i-1].active)
|
||||
if (friends[i - 1].active)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -305,7 +305,7 @@ static void del_friend_deactivate(ToxWindow *self, Tox *m, wint_t key)
|
||||
{
|
||||
if (key == 'y')
|
||||
delete_friend(m, pendingdelete.num);
|
||||
|
||||
|
||||
memset(&pendingdelete, 0, sizeof(pendingdelete));
|
||||
delwin(self->popup);
|
||||
self->popup = NULL;
|
||||
@ -427,24 +427,27 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
|
||||
} else {
|
||||
wprintw(self->window, " ");
|
||||
}
|
||||
|
||||
|
||||
if (friends[f].online) {
|
||||
uint8_t status = friends[f].status;
|
||||
int colour = WHITE;
|
||||
|
||||
switch (status) {
|
||||
case TOX_USERSTATUS_NONE:
|
||||
colour = GREEN;
|
||||
break;
|
||||
case TOX_USERSTATUS_AWAY:
|
||||
colour = YELLOW;
|
||||
break;
|
||||
case TOX_USERSTATUS_BUSY:
|
||||
colour = RED;
|
||||
break;
|
||||
case TOX_USERSTATUS_INVALID:
|
||||
colour = MAGENTA;
|
||||
break;
|
||||
case TOX_USERSTATUS_NONE:
|
||||
colour = GREEN;
|
||||
break;
|
||||
|
||||
case TOX_USERSTATUS_AWAY:
|
||||
colour = YELLOW;
|
||||
break;
|
||||
|
||||
case TOX_USERSTATUS_BUSY:
|
||||
colour = RED;
|
||||
break;
|
||||
|
||||
case TOX_USERSTATUS_INVALID:
|
||||
colour = MAGENTA;
|
||||
break;
|
||||
}
|
||||
|
||||
wattron(self->window, COLOR_PAIR(colour) | A_BOLD);
|
||||
@ -466,8 +469,8 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
|
||||
uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'};
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
uint16_t s_len = tox_get_status_message(m, friends[f].num, statusmsg,
|
||||
TOX_MAX_STATUSMESSAGE_LENGTH);
|
||||
uint16_t s_len = tox_get_status_message(m, friends[f].num, statusmsg,
|
||||
TOX_MAX_STATUSMESSAGE_LENGTH);
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
friends[f].statusmsg_len = s_len;
|
||||
@ -477,8 +480,9 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
|
||||
|
||||
/* Truncate note if it doesn't fit on one line */
|
||||
uint16_t maxlen = x2 - getcurx(self->window) - 2;
|
||||
|
||||
if (friends[f].statusmsg_len > maxlen) {
|
||||
friends[f].statusmsg[maxlen-3] = '\0';
|
||||
friends[f].statusmsg[maxlen - 3] = '\0';
|
||||
strcat(friends[f].statusmsg, "...");
|
||||
friends[f].statusmsg[maxlen] = '\0';
|
||||
friends[f].statusmsg_len = maxlen;
|
||||
@ -500,7 +504,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
|
||||
|
||||
if (f_selected)
|
||||
wattroff(self->window, COLOR_PAIR(YELLOW));
|
||||
|
||||
|
||||
uint64_t last_seen = friends[f].last_online.last_on;
|
||||
|
||||
if (last_seen != 0) {
|
||||
@ -508,16 +512,18 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
|
||||
const uint8_t *hourmin = friends[f].last_online.hour_min_str;
|
||||
|
||||
switch (day_dist) {
|
||||
case 0:
|
||||
wprintw(self->window, " Last seen: Today %s\n", hourmin);
|
||||
break;
|
||||
case 1:
|
||||
wprintw(self->window, " Last seen: Yesterday %s\n", hourmin);
|
||||
break;
|
||||
default:
|
||||
wprintw(self->window, " Last seen: %d days ago\n", day_dist);
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
wprintw(self->window, " Last seen: Today %s\n", hourmin);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
wprintw(self->window, " Last seen: Yesterday %s\n", hourmin);
|
||||
break;
|
||||
|
||||
default:
|
||||
wprintw(self->window, " Last seen: %d days ago\n", day_dist);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
wprintw(self->window, " Last seen: Never\n");
|
||||
}
|
||||
@ -539,12 +545,13 @@ void disable_chatwin(int32_t f_num)
|
||||
static void friendlist_onAv(ToxWindow *self, ToxAv *av)
|
||||
{
|
||||
int id = toxav_get_peer_id(av, 0);
|
||||
|
||||
/*id++;*/
|
||||
if ( id != ErrorInternal && id >= max_friends_index)
|
||||
return;
|
||||
|
||||
Tox* m = toxav_get_tox(av);
|
||||
|
||||
|
||||
Tox *m = toxav_get_tox(av);
|
||||
|
||||
if (friends[id].chatwin == -1) {
|
||||
if (get_num_active_windows() < MAX_WINDOWS_NUM) {
|
||||
friends[id].chatwin = add_window(m, new_chat(m, friends[id].num));
|
||||
@ -552,7 +559,7 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av)
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
|
||||
int n_len = tox_get_name(m, id, nick);
|
||||
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
nick[n_len] = '\0';
|
||||
|
||||
uint8_t msg[MAX_STR_SIZE];
|
||||
@ -561,7 +568,7 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av)
|
||||
|
||||
uint8_t *errmsg = "* Warning: Too many windows are open.";
|
||||
line_info_add(prompt, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
|
||||
|
||||
|
||||
alert_window(prompt, WINDOW_ALERT_0, true);
|
||||
}
|
||||
}
|
||||
@ -586,7 +593,7 @@ ToxWindow new_friendlist(void)
|
||||
ret.onStatusMessageChange = &friendlist_onStatusMessageChange;
|
||||
ret.onFileSendRequest = &friendlist_onFileSendRequest;
|
||||
ret.onGroupInvite = &friendlist_onGroupInvite;
|
||||
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
ret.onInvite = &friendlist_onAv;
|
||||
ret.onRinging = &friendlist_onAv;
|
||||
|
@ -54,7 +54,7 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
|
||||
int req = atoi(argv[1]);
|
||||
|
||||
if ((req == 0 && strcmp(argv[1], "0"))|| req >= MAX_FRIENDS_NUM) {
|
||||
if ((req == 0 && strcmp(argv[1], "0")) || req >= MAX_FRIENDS_NUM) {
|
||||
msg = "No pending friend request with that number.";
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
@ -80,7 +80,7 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
int i;
|
||||
|
||||
for (i = num_frnd_requests; i > 0; --i) {
|
||||
if (!strlen(pending_frnd_requests[i-1]))
|
||||
if (!strlen(pending_frnd_requests[i - 1]))
|
||||
break;
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
|
||||
return;
|
||||
}
|
||||
|
||||
temp[strlen(++temp)-1] = L'\0';
|
||||
temp[strlen(++temp) - 1] = L'\0';
|
||||
snprintf(msg, sizeof(msg), "%s", temp);
|
||||
} else {
|
||||
uint8_t selfname[TOX_MAX_NAME_LENGTH];
|
||||
@ -151,31 +151,38 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
|
||||
int32_t f_num = tox_add_friend(m, id_bin, msg, strlen(msg));
|
||||
|
||||
switch (f_num) {
|
||||
case TOX_FAERR_TOOLONG:
|
||||
errmsg = "Message is too long.";
|
||||
break;
|
||||
case TOX_FAERR_NOMESSAGE:
|
||||
errmsg = "Please add a message to your request.";
|
||||
break;
|
||||
case TOX_FAERR_OWNKEY:
|
||||
errmsg = "That appears to be your own ID.";
|
||||
break;
|
||||
case TOX_FAERR_ALREADYSENT:
|
||||
errmsg = "Friend request has already been sent.";
|
||||
break;
|
||||
case TOX_FAERR_UNKNOWN:
|
||||
errmsg = "Undefined error when adding friend.";
|
||||
break;
|
||||
case TOX_FAERR_BADCHECKSUM:
|
||||
errmsg = "Bad checksum in address.";
|
||||
break;
|
||||
case TOX_FAERR_SETNEWNOSPAM:
|
||||
errmsg = "Nospam was different (is this contact already added?";
|
||||
break;
|
||||
default:
|
||||
errmsg = "Friend request sent.";
|
||||
on_friendadded(m, f_num, true);
|
||||
break;
|
||||
case TOX_FAERR_TOOLONG:
|
||||
errmsg = "Message is too long.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_NOMESSAGE:
|
||||
errmsg = "Please add a message to your request.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_OWNKEY:
|
||||
errmsg = "That appears to be your own ID.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_ALREADYSENT:
|
||||
errmsg = "Friend request has already been sent.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_UNKNOWN:
|
||||
errmsg = "Undefined error when adding friend.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_BADCHECKSUM:
|
||||
errmsg = "Bad checksum in address.";
|
||||
break;
|
||||
|
||||
case TOX_FAERR_SETNEWNOSPAM:
|
||||
errmsg = "Nospam was different (is this contact already added?";
|
||||
break;
|
||||
|
||||
default:
|
||||
errmsg = "Friend request sent.";
|
||||
on_friendadded(m, f_num, true);
|
||||
break;
|
||||
}
|
||||
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
@ -192,12 +199,11 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
|
||||
|
||||
/* check arguments */
|
||||
if (argc != 3) {
|
||||
errmsg = "Invalid syntax.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
errmsg = "Invalid syntax.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
tox_IP_Port dht;
|
||||
char *ip = argv[1];
|
||||
char *port = argv[2];
|
||||
char *key = argv[3];
|
||||
@ -315,9 +321,9 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
|
||||
/* check arguments */
|
||||
if (argc < 1) {
|
||||
errmsg = "Invalid name.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
errmsg = "Invalid name.";
|
||||
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *nick = argv[1];
|
||||
@ -335,7 +341,7 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
return;
|
||||
}
|
||||
|
||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
|
||||
nick[len] = L'\0';
|
||||
|
||||
@ -363,7 +369,7 @@ void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
return;
|
||||
}
|
||||
|
||||
msg[strlen(++msg)-1] = L'\0';
|
||||
msg[strlen(++msg) - 1] = L'\0';
|
||||
uint16_t len = strlen(msg);
|
||||
tox_set_status_message(m, msg, len);
|
||||
prompt_update_statusmessage(prompt, msg, len);
|
||||
@ -379,31 +385,31 @@ void cmd_prompt_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#define NUMLINES 14
|
||||
#define NUMLINES 14
|
||||
#else
|
||||
#define NUMLINES 12
|
||||
#define NUMLINES 12
|
||||
#endif
|
||||
|
||||
uint8_t lines[NUMLINES][MAX_STR_SIZE] = {
|
||||
|
||||
{ " /add <id> <msg> : Add friend with optional message" },
|
||||
{ " /accept <n> : Accept friend request" },
|
||||
{ " /connect <ip> <port> <key> : Manually connect to a DHT node" },
|
||||
{ " /status <type> <msg> : Set status with optional note" },
|
||||
{ " /note <msg> : Set a personal note" },
|
||||
{ " /nick <nick> : Set your nickname" },
|
||||
{ " /log <on> or <off> : Enable/disable logging" },
|
||||
{ " /groupchat : Create a group chat" },
|
||||
{ " /myid : Print your ID" },
|
||||
{ " /help : Print this message again" },
|
||||
{ " /clear : Clear window history" },
|
||||
{ " /quit or /exit : Exit Toxic" },
|
||||
{ " /add <id> <msg> : Add friend with optional message" },
|
||||
{ " /accept <n> : Accept friend request" },
|
||||
{ " /connect <ip> <port> <key> : Manually connect to a DHT node" },
|
||||
{ " /status <type> <msg> : Set status with optional note" },
|
||||
{ " /note <msg> : Set a personal note" },
|
||||
{ " /nick <nick> : Set your nickname" },
|
||||
{ " /log <on> or <off> : Enable/disable logging" },
|
||||
{ " /groupchat : Create a group chat" },
|
||||
{ " /myid : Print your ID" },
|
||||
{ " /help : Print this message again" },
|
||||
{ " /clear : Clear window history" },
|
||||
{ " /quit or /exit : Exit Toxic" },
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
{ " /lsdev <type> : List devices where type: in|out" },
|
||||
{ " /sdev <type> <id> : Set active device" },
|
||||
{ " /lsdev <type> : List devices where type: in|out" },
|
||||
{ " /sdev <type> <id> : Set active device" },
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
};
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUMLINES; ++i)
|
||||
@ -442,7 +448,7 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
|
||||
char *status = argv[1];
|
||||
int len = strlen(status);
|
||||
char l_status[len+1];
|
||||
char l_status[len + 1];
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= len; ++i)
|
||||
@ -466,7 +472,7 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
prompt_update_status(prompt, status_kind);
|
||||
|
||||
if (msg != NULL) {
|
||||
msg[strlen(++msg)-1] = L'\0'; /* remove opening and closing quotes */
|
||||
msg[strlen(++msg) - 1] = L'\0'; /* remove opening and closing quotes */
|
||||
uint16_t len = strlen(msg);
|
||||
tox_set_status_message(m, msg, len);
|
||||
prompt_update_statusmessage(prompt, msg, len);
|
||||
|
133
src/groupchat.c
133
src/groupchat.c
@ -108,7 +108,7 @@ static void close_groupchat(ToxWindow *self, Tox *m, int groupnum)
|
||||
int i;
|
||||
|
||||
for (i = max_groupchat_index; i > 0; --i) {
|
||||
if (groupchats[i-1].active)
|
||||
if (groupchats[i - 1].active)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -125,21 +125,21 @@ static void print_groupchat_help(ToxWindow *self)
|
||||
uint8_t *msg = "Group chat commands:";
|
||||
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
|
||||
|
||||
#define NUMLINES 9
|
||||
#define NUMLINES 9
|
||||
|
||||
uint8_t lines[NUMLINES][MAX_STR_SIZE] = {
|
||||
|
||||
{ " /add <id> <msg> : Add friend with optional message" },
|
||||
{ " /status <type> <msg>: Set your status with optional note" },
|
||||
{ " /note <msg> : Set a personal note" },
|
||||
{ " /nick <nick> : Set your nickname" },
|
||||
{ " /groupchat : Create a group chat" },
|
||||
{ " /log <on> or <off> : Enable/disable logging" },
|
||||
{ " /close : Close the current group chat" },
|
||||
{ " /help : Print this message again" },
|
||||
{ " /help global : Show a list of global commands" },
|
||||
{ " /add <id> <msg> : Add friend with optional message" },
|
||||
{ " /status <type> <msg>: Set your status with optional note" },
|
||||
{ " /note <msg> : Set a personal note" },
|
||||
{ " /nick <nick> : Set your nickname" },
|
||||
{ " /groupchat : Create a group chat" },
|
||||
{ " /log <on> or <off> : Enable/disable logging" },
|
||||
{ " /close : Close the current group chat" },
|
||||
{ " /help : Print this message again" },
|
||||
{ " /help global : Show a list of global commands" },
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
int i;
|
||||
|
||||
@ -169,7 +169,7 @@ static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, int
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
|
||||
int n_len = tox_group_peername(m, groupnum, peernum, nick);
|
||||
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH-1); /* enforce client max name length */
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1); /* enforce client max name length */
|
||||
nick[n_len] = '\0';
|
||||
|
||||
/* check if message contains own name and alert appropriately */
|
||||
@ -229,7 +229,7 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
|
||||
n_len = tox_group_peername(m, groupnum, peernum, nick);
|
||||
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
nick[n_len] = '\0';
|
||||
|
||||
uint8_t timefrmt[TIME_STR_SIZE];
|
||||
@ -259,7 +259,7 @@ static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], ui
|
||||
memset(groupchats[gnum].peer_name_lengths, 0, sizeof(uint16_t) * npeers);
|
||||
|
||||
if (groupchats[gnum].peer_names == NULL || groupchats[gnum].oldpeer_names == NULL
|
||||
|| groupchats[gnum].peer_name_lengths == NULL || groupchats[gnum].oldpeer_name_lengths == NULL) {
|
||||
|| groupchats[gnum].peer_name_lengths == NULL || groupchats[gnum].oldpeer_name_lengths == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
@ -270,26 +270,26 @@ static void copy_peernames(int gnum, uint8_t peerlist[][TOX_MAX_NAME_LENGTH], ui
|
||||
|
||||
for (i = 0; i < npeers; ++i) {
|
||||
if (string_is_empty(peerlist[i])) {
|
||||
memcpy(&groupchats[gnum].peer_names[i*N], UNKNOWN_NAME, sizeof(UNKNOWN_NAME));
|
||||
memcpy(&groupchats[gnum].peer_names[i * N], UNKNOWN_NAME, sizeof(UNKNOWN_NAME));
|
||||
groupchats[gnum].peer_name_lengths[i] = unknown_len;
|
||||
} else {
|
||||
memcpy(&groupchats[gnum].peer_names[i*N], peerlist[i], N);
|
||||
memcpy(&groupchats[gnum].peer_names[i * N], peerlist[i], N);
|
||||
uint16_t n_len = lengths[i];
|
||||
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
|
||||
groupchats[gnum].peer_names[i*N+n_len] = '\0';
|
||||
groupchats[gnum].peer_names[i * N + n_len] = '\0';
|
||||
groupchats[gnum].peer_name_lengths[i] = n_len;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(groupchats[gnum].oldpeer_names, groupchats[gnum].peer_names, N*npeers);
|
||||
memcpy(groupchats[gnum].oldpeer_name_lengths, groupchats[gnum].peer_name_lengths,
|
||||
sizeof(uint16_t) * npeers);
|
||||
memcpy(groupchats[gnum].oldpeer_names, groupchats[gnum].peer_names, N * npeers);
|
||||
memcpy(groupchats[gnum].oldpeer_name_lengths, groupchats[gnum].peer_name_lengths,
|
||||
sizeof(uint16_t) * npeers);
|
||||
}
|
||||
|
||||
static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnum, int peernum,
|
||||
uint8_t change)
|
||||
uint8_t change)
|
||||
{
|
||||
if (self->num != groupnum)
|
||||
return;
|
||||
@ -301,7 +301,7 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
|
||||
uint8_t oldpeername[TOX_MAX_NAME_LENGTH];
|
||||
|
||||
if (change != TOX_CHAT_CHANGE_PEER_ADD) {
|
||||
memcpy(oldpeername, &groupchats[groupnum].oldpeer_names[peernum*TOX_MAX_NAME_LENGTH],
|
||||
memcpy(oldpeername, &groupchats[groupnum].oldpeer_names[peernum * TOX_MAX_NAME_LENGTH],
|
||||
sizeof(oldpeername));
|
||||
uint16_t old_n_len = groupchats[groupnum].oldpeer_name_lengths[peernum];
|
||||
oldpeername[old_n_len] = '\0';
|
||||
@ -318,7 +318,7 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
|
||||
|
||||
if (change != TOX_CHAT_CHANGE_PEER_DEL) {
|
||||
uint16_t n_len = groupchats[groupnum].peer_name_lengths[peernum];
|
||||
memcpy(peername, &groupchats[groupnum].peer_names[peernum*TOX_MAX_NAME_LENGTH], sizeof(peername));
|
||||
memcpy(peername, &groupchats[groupnum].peer_names[peernum * TOX_MAX_NAME_LENGTH], sizeof(peername));
|
||||
peername[n_len] = '\0';
|
||||
}
|
||||
|
||||
@ -331,36 +331,37 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
|
||||
get_time_str(timefrmt);
|
||||
|
||||
switch (change) {
|
||||
case TOX_CHAT_CHANGE_PEER_ADD:
|
||||
event = "has joined the room";
|
||||
line_info_add(self, timefrmt, peername, NULL, event, CONNECTION, 0, GREEN);
|
||||
write_to_log(event, peername, ctx->log, true);
|
||||
break;
|
||||
case TOX_CHAT_CHANGE_PEER_ADD:
|
||||
event = "has joined the room";
|
||||
line_info_add(self, timefrmt, peername, NULL, event, CONNECTION, 0, GREEN);
|
||||
write_to_log(event, peername, ctx->log, true);
|
||||
break;
|
||||
|
||||
case TOX_CHAT_CHANGE_PEER_DEL:
|
||||
event = "has left the room";
|
||||
line_info_add(self, timefrmt, oldpeername, NULL, event, CONNECTION, 0, 0);
|
||||
case TOX_CHAT_CHANGE_PEER_DEL:
|
||||
event = "has left the room";
|
||||
line_info_add(self, timefrmt, oldpeername, NULL, event, CONNECTION, 0, 0);
|
||||
|
||||
if (groupchats[self->num].side_pos > 0)
|
||||
--groupchats[self->num].side_pos;
|
||||
if (groupchats[self->num].side_pos > 0)
|
||||
--groupchats[self->num].side_pos;
|
||||
|
||||
write_to_log(event, oldpeername, ctx->log, true);
|
||||
break;
|
||||
write_to_log(event, oldpeername, ctx->log, true);
|
||||
break;
|
||||
|
||||
case TOX_CHAT_CHANGE_PEER_NAME:
|
||||
event = " is now known as ";
|
||||
line_info_add(self, timefrmt, oldpeername, peername, event, NAME_CHANGE, 0, 0);
|
||||
case TOX_CHAT_CHANGE_PEER_NAME:
|
||||
event = " is now known as ";
|
||||
line_info_add(self, timefrmt, oldpeername, peername, event, NAME_CHANGE, 0, 0);
|
||||
|
||||
uint8_t tmp_event[TOXIC_MAX_NAME_LENGTH * 2 + 32];
|
||||
snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", peername);
|
||||
write_to_log(tmp_event, oldpeername, ctx->log, true);
|
||||
break;
|
||||
uint8_t tmp_event[TOXIC_MAX_NAME_LENGTH * 2 + 32];
|
||||
snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", peername);
|
||||
write_to_log(tmp_event, oldpeername, ctx->log, true);
|
||||
break;
|
||||
}
|
||||
|
||||
alert_window(self, WINDOW_ALERT_2, false);
|
||||
}
|
||||
|
||||
static void send_group_action(ToxWindow *self, ChatContext *ctx, Tox *m, uint8_t *action) {
|
||||
static void send_group_action(ToxWindow *self, ChatContext *ctx, Tox *m, uint8_t *action)
|
||||
{
|
||||
if (action == NULL) {
|
||||
wprintw(ctx->history, "Invalid syntax.\n");
|
||||
return;
|
||||
@ -393,11 +394,11 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
}
|
||||
|
||||
if (ltr) {
|
||||
if ( (ctx->len < MAX_STR_SIZE-1) && (ctx->len < (x2 * (CHATBOX_HEIGHT - 1)-1)) ) {
|
||||
if ( (ctx->len < MAX_STR_SIZE - 1) && (ctx->len < (x2 * (CHATBOX_HEIGHT - 1) - 1)) ) {
|
||||
add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key);
|
||||
|
||||
if (x == x2-1)
|
||||
wmove(self->window, y+1, 0);
|
||||
if (x == x2 - 1)
|
||||
wmove(self->window, y + 1, 0);
|
||||
else
|
||||
wmove(self->window, y, x + MAX(1, wcwidth(key)));
|
||||
}
|
||||
@ -410,7 +411,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
|
||||
|
||||
if (x == 0)
|
||||
wmove(self->window, y-1, x2 - cur_len);
|
||||
wmove(self->window, y - 1, x2 - cur_len);
|
||||
else
|
||||
wmove(self->window, y, x - cur_len);
|
||||
} else {
|
||||
@ -451,7 +452,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
else if (key == KEY_END || key == T_KEY_C_E) { /* END/C-e key: move cursor to end of line */
|
||||
if (ctx->pos != ctx->len) {
|
||||
ctx->pos = ctx->len;
|
||||
mv_curs_end(self->window, MAX(0, wcswidth(ctx->line, (CHATBOX_HEIGHT-1)*x2)), y2, x2);
|
||||
mv_curs_end(self->window, MAX(0, wcswidth(ctx->line, (CHATBOX_HEIGHT - 1)*x2)), y2, x2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,7 +462,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
|
||||
|
||||
if (x == 0)
|
||||
wmove(self->window, y-1, x2 - cur_len);
|
||||
wmove(self->window, y - 1, x2 - cur_len);
|
||||
else
|
||||
wmove(self->window, y, x - cur_len);
|
||||
} else {
|
||||
@ -474,8 +475,8 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
|
||||
++ctx->pos;
|
||||
|
||||
if (x == x2-1)
|
||||
wmove(self->window, y+1, 0);
|
||||
if (x == x2 - 1)
|
||||
wmove(self->window, y + 1, 0);
|
||||
else
|
||||
wmove(self->window, y, x + cur_len);
|
||||
} else {
|
||||
@ -500,7 +501,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
int diff;
|
||||
|
||||
if ((ctx->line[0] != '/') || (ctx->line[1] == 'm' && ctx->line[2] == 'e'))
|
||||
diff = complete_line(ctx->line, &ctx->pos, &ctx->len, groupchats[self->num].peer_names,
|
||||
diff = complete_line(ctx->line, &ctx->pos, &ctx->len, groupchats[self->num].peer_names,
|
||||
groupchats[self->num].num_peers, TOX_MAX_NAME_LENGTH);
|
||||
else
|
||||
diff = complete_line(ctx->line, &ctx->pos, &ctx->len, glob_cmd_list, AC_NUM_GLOB_COMMANDS,
|
||||
@ -509,9 +510,9 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
if (diff != -1) {
|
||||
if (x + diff > x2 - 1) {
|
||||
int ofst = (x + diff - 1) - (x2 - 1);
|
||||
wmove(self->window, y+1, ofst);
|
||||
wmove(self->window, y + 1, ofst);
|
||||
} else {
|
||||
wmove(self->window, y, x+diff);
|
||||
wmove(self->window, y, x + diff);
|
||||
}
|
||||
} else {
|
||||
beep();
|
||||
@ -606,8 +607,8 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
|
||||
wclear(ctx->sidebar);
|
||||
mvwhline(ctx->linewin, 0, 0, ACS_HLINE, x2);
|
||||
mvwvline(ctx->sidebar, 0, 0, ACS_VLINE, y2-CHATBOX_HEIGHT);
|
||||
mvwaddch(ctx->sidebar, y2-CHATBOX_HEIGHT, 0, ACS_BTEE);
|
||||
mvwvline(ctx->sidebar, 0, 0, ACS_VLINE, y2 - CHATBOX_HEIGHT);
|
||||
mvwaddch(ctx->sidebar, y2 - CHATBOX_HEIGHT, 0, ACS_BTEE);
|
||||
|
||||
int num_peers = groupchats[self->num].num_peers;
|
||||
|
||||
@ -617,20 +618,20 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
wattroff(ctx->sidebar, A_BOLD);
|
||||
|
||||
mvwaddch(ctx->sidebar, 1, 0, ACS_LTEE);
|
||||
mvwhline(ctx->sidebar, 1, 1, ACS_HLINE, SIDEBAR_WIDTH-1);
|
||||
mvwhline(ctx->sidebar, 1, 1, ACS_HLINE, SIDEBAR_WIDTH - 1);
|
||||
|
||||
int N = TOX_MAX_NAME_LENGTH;
|
||||
int maxlines = y2 - SDBAR_OFST - CHATBOX_HEIGHT;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_peers && i < maxlines; ++i) {
|
||||
wmove(ctx->sidebar, i+2, 1);
|
||||
wmove(ctx->sidebar, i + 2, 1);
|
||||
int peer = i + groupchats[self->num].side_pos;
|
||||
|
||||
/* truncate nick to fit in side panel without modifying list */
|
||||
uint8_t tmpnck[TOX_MAX_NAME_LENGTH];
|
||||
memcpy(tmpnck, &groupchats[self->num].peer_names[peer*N], SIDEBAR_WIDTH-2);
|
||||
tmpnck[SIDEBAR_WIDTH-2] = '\0';
|
||||
memcpy(tmpnck, &groupchats[self->num].peer_names[peer * N], SIDEBAR_WIDTH - 2);
|
||||
tmpnck[SIDEBAR_WIDTH - 2] = '\0';
|
||||
|
||||
wprintw(ctx->sidebar, "%s\n", tmpnck);
|
||||
}
|
||||
@ -643,9 +644,9 @@ static void groupchat_onInit(ToxWindow *self, Tox *m)
|
||||
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
ctx->history = subwin(self->window, y-CHATBOX_HEIGHT+1, x-SIDEBAR_WIDTH-1, 0, 0);
|
||||
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x, y-CHATBOX_HEIGHT, 0);
|
||||
ctx->sidebar = subwin(self->window, y-CHATBOX_HEIGHT+1, SIDEBAR_WIDTH, 0, x-SIDEBAR_WIDTH);
|
||||
ctx->history = subwin(self->window, y - CHATBOX_HEIGHT + 1, x - SIDEBAR_WIDTH - 1, 0, 0);
|
||||
ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x, y - CHATBOX_HEIGHT, 0);
|
||||
ctx->sidebar = subwin(self->window, y - CHATBOX_HEIGHT + 1, SIDEBAR_WIDTH, 0, x - SIDEBAR_WIDTH);
|
||||
|
||||
ctx->hst = malloc(sizeof(struct history));
|
||||
ctx->log = malloc(sizeof(struct chatlog));
|
||||
@ -667,7 +668,7 @@ static void groupchat_onInit(ToxWindow *self, Tox *m)
|
||||
|
||||
execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);
|
||||
|
||||
wmove(self->window, y-CURS_Y_OFFSET, 0);
|
||||
wmove(self->window, y - CURS_Y_OFFSET, 0);
|
||||
}
|
||||
|
||||
ToxWindow new_group_chat(Tox *m, int groupnum)
|
||||
|
252
src/line_info.c
252
src/line_info.c
@ -107,7 +107,7 @@ static void line_info_root_fwd(struct history *hst)
|
||||
hst->line_root = tmp;
|
||||
}
|
||||
|
||||
void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *name2, uint8_t *msg,
|
||||
void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *name2, uint8_t *msg,
|
||||
uint8_t type, uint8_t bold, uint8_t colour)
|
||||
{
|
||||
struct history *hst = self->chatwin->hst;
|
||||
@ -125,24 +125,31 @@ void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *na
|
||||
|
||||
/* for type-specific formatting in print function */
|
||||
switch (type) {
|
||||
case ACTION:
|
||||
len += 3;
|
||||
break;
|
||||
default:
|
||||
len += 2;
|
||||
break;
|
||||
case ACTION:
|
||||
len += 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
len += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg) {
|
||||
memcpy(new_line->msg, msg, sizeof(new_line->msg));
|
||||
len += strlen(msg);
|
||||
} if (tmstmp) {
|
||||
}
|
||||
|
||||
if (tmstmp) {
|
||||
memcpy(new_line->timestamp, tmstmp, sizeof(new_line->timestamp));
|
||||
len += strlen(tmstmp);
|
||||
} if (name1) {
|
||||
}
|
||||
|
||||
if (name1) {
|
||||
memcpy(new_line->name1, name1, sizeof(new_line->name1));
|
||||
len += strlen(name1);
|
||||
} if (name2) {
|
||||
}
|
||||
|
||||
if (name2) {
|
||||
memcpy(new_line->name2, name2, sizeof(new_line->name2));
|
||||
len += strlen(name2);
|
||||
}
|
||||
@ -223,112 +230,114 @@ void line_info_print(ToxWindow *self)
|
||||
int offst = self->is_groupchat ? SIDEBAR_WIDTH : 0;
|
||||
int numlines = 0;
|
||||
|
||||
while(line && numlines++ <= y2) {
|
||||
while (line && numlines++ <= y2) {
|
||||
uint8_t type = line->type;
|
||||
|
||||
switch (type) {
|
||||
case OUT_MSG:
|
||||
case IN_MSG:
|
||||
wattron(win, COLOR_PAIR(BLUE));
|
||||
wprintw(win, "%s", line->timestamp);
|
||||
wattroff(win, COLOR_PAIR(BLUE));
|
||||
|
||||
int nameclr = GREEN;
|
||||
|
||||
if (line->colour)
|
||||
nameclr = line->colour;
|
||||
else if (type == IN_MSG)
|
||||
nameclr = CYAN;
|
||||
|
||||
wattron(win, COLOR_PAIR(nameclr));
|
||||
wprintw(win, "%s: ", line->name1);
|
||||
wattroff(win, COLOR_PAIR(nameclr));
|
||||
|
||||
if (line->msg[0] == '>')
|
||||
wattron(win, COLOR_PAIR(GREEN));
|
||||
|
||||
wprintw(win, "%s\n", line->msg);
|
||||
|
||||
if (line->msg[0] == '>')
|
||||
wattroff(win, COLOR_PAIR(GREEN));
|
||||
|
||||
break;
|
||||
|
||||
case ACTION:
|
||||
wattron(win, COLOR_PAIR(BLUE));
|
||||
wprintw(win, "%s", line->timestamp);
|
||||
wattroff(win, COLOR_PAIR(BLUE));
|
||||
|
||||
wattron(win, COLOR_PAIR(YELLOW));
|
||||
wprintw(win, "* %s %s\n", line->name1, line->msg);
|
||||
wattroff(win, COLOR_PAIR(YELLOW));
|
||||
|
||||
break;
|
||||
|
||||
case SYS_MSG:
|
||||
if (line->timestamp[0]) {
|
||||
case OUT_MSG:
|
||||
case IN_MSG:
|
||||
wattron(win, COLOR_PAIR(BLUE));
|
||||
wprintw(win, "%s", line->timestamp);
|
||||
wattroff(win, COLOR_PAIR(BLUE));
|
||||
|
||||
int nameclr = GREEN;
|
||||
|
||||
if (line->colour)
|
||||
nameclr = line->colour;
|
||||
else if (type == IN_MSG)
|
||||
nameclr = CYAN;
|
||||
|
||||
wattron(win, COLOR_PAIR(nameclr));
|
||||
wprintw(win, "%s: ", line->name1);
|
||||
wattroff(win, COLOR_PAIR(nameclr));
|
||||
|
||||
if (line->msg[0] == '>')
|
||||
wattron(win, COLOR_PAIR(GREEN));
|
||||
|
||||
wprintw(win, "%s\n", line->msg);
|
||||
|
||||
if (line->msg[0] == '>')
|
||||
wattroff(win, COLOR_PAIR(GREEN));
|
||||
|
||||
break;
|
||||
|
||||
case ACTION:
|
||||
wattron(win, COLOR_PAIR(BLUE));
|
||||
wprintw(win, "%s", line->timestamp);
|
||||
wattroff(win, COLOR_PAIR(BLUE));
|
||||
|
||||
wattron(win, COLOR_PAIR(YELLOW));
|
||||
wprintw(win, "* %s %s\n", line->name1, line->msg);
|
||||
wattroff(win, COLOR_PAIR(YELLOW));
|
||||
|
||||
break;
|
||||
|
||||
case SYS_MSG:
|
||||
if (line->timestamp[0]) {
|
||||
wattron(win, COLOR_PAIR(BLUE));
|
||||
wprintw(win, "%s", line->timestamp);
|
||||
wattroff(win, COLOR_PAIR(BLUE));
|
||||
}
|
||||
|
||||
if (line->bold)
|
||||
wattron(win, A_BOLD);
|
||||
|
||||
if (line->colour)
|
||||
wattron(win, COLOR_PAIR(line->colour));
|
||||
|
||||
wprintw(win, "%s\n", line->msg);
|
||||
|
||||
if (line->bold)
|
||||
wattroff(win, A_BOLD);
|
||||
|
||||
if (line->colour)
|
||||
wattroff(win, COLOR_PAIR(line->colour));
|
||||
|
||||
break;
|
||||
|
||||
case PROMPT:
|
||||
wattron(win, COLOR_PAIR(GREEN));
|
||||
wprintw(win, "$ ");
|
||||
wattroff(win, COLOR_PAIR(GREEN));
|
||||
|
||||
if (line->msg[0])
|
||||
wprintw(win, "%s", line->msg);
|
||||
|
||||
wprintw(win, "\n");
|
||||
break;
|
||||
|
||||
case CONNECTION:
|
||||
wattron(win, COLOR_PAIR(BLUE));
|
||||
wprintw(win, "%s", line->timestamp);
|
||||
wattroff(win, COLOR_PAIR(BLUE));
|
||||
}
|
||||
|
||||
if (line->bold)
|
||||
wattron(win, A_BOLD);
|
||||
if (line->colour)
|
||||
wattron(win, COLOR_PAIR(line->colour));
|
||||
|
||||
wprintw(win, "%s\n", line->msg);
|
||||
|
||||
if (line->bold)
|
||||
wattron(win, A_BOLD);
|
||||
wprintw(win, "* %s ", line->name1);
|
||||
wattroff(win, A_BOLD);
|
||||
if (line->colour)
|
||||
wprintw(win, "%s\n", line->msg);
|
||||
wattroff(win, COLOR_PAIR(line->colour));
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case PROMPT:
|
||||
wattron(win, COLOR_PAIR(GREEN));
|
||||
wprintw(win, "$ ");
|
||||
wattroff(win, COLOR_PAIR(GREEN));
|
||||
case NAME_CHANGE:
|
||||
wattron(win, COLOR_PAIR(BLUE));
|
||||
wprintw(win, "%s", line->timestamp);
|
||||
wattroff(win, COLOR_PAIR(BLUE));
|
||||
|
||||
wattron(win, COLOR_PAIR(MAGENTA));
|
||||
wattron(win, A_BOLD);
|
||||
wprintw(win, "* %s", line->name1);
|
||||
wattroff(win, A_BOLD);
|
||||
|
||||
if (line->msg[0])
|
||||
wprintw(win, "%s", line->msg);
|
||||
|
||||
wprintw(win, "\n");
|
||||
break;
|
||||
wattron(win, A_BOLD);
|
||||
wprintw(win, "%s\n", line->name2);
|
||||
wattroff(win, A_BOLD);
|
||||
wattroff(win, COLOR_PAIR(MAGENTA));
|
||||
|
||||
case CONNECTION:
|
||||
wattron(win, COLOR_PAIR(BLUE));
|
||||
wprintw(win, "%s", line->timestamp);
|
||||
wattroff(win, COLOR_PAIR(BLUE));
|
||||
|
||||
wattron(win, COLOR_PAIR(line->colour));
|
||||
wattron(win, A_BOLD);
|
||||
wprintw(win, "* %s ", line->name1);
|
||||
wattroff(win, A_BOLD);
|
||||
wprintw(win, "%s\n", line->msg);
|
||||
wattroff(win, COLOR_PAIR(line->colour));
|
||||
|
||||
break;
|
||||
|
||||
case NAME_CHANGE:
|
||||
wattron(win, COLOR_PAIR(BLUE));
|
||||
wprintw(win, "%s", line->timestamp);
|
||||
wattroff(win, COLOR_PAIR(BLUE));
|
||||
|
||||
wattron(win, COLOR_PAIR(MAGENTA));
|
||||
wattron(win, A_BOLD);
|
||||
wprintw(win, "* %s", line->name1);
|
||||
wattroff(win, A_BOLD);
|
||||
|
||||
wprintw(win, "%s", line->msg);
|
||||
|
||||
wattron(win, A_BOLD);
|
||||
wprintw(win, "%s\n", line->name2);
|
||||
wattroff(win, A_BOLD);
|
||||
wattroff(win, COLOR_PAIR(MAGENTA));
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
line = line->next;
|
||||
@ -395,24 +404,29 @@ void line_info_onKey(ToxWindow *self, wint_t key)
|
||||
struct history *hst = self->chatwin->hst;
|
||||
|
||||
switch (key) {
|
||||
case KEY_PPAGE:
|
||||
line_info_page_up(self, hst);
|
||||
break;
|
||||
case KEY_NPAGE:
|
||||
line_info_page_down(self, hst);
|
||||
break;
|
||||
case KEY_UP:
|
||||
line_info_scroll_up(hst);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
line_info_scroll_down(hst);
|
||||
break;
|
||||
case KEY_HOME:
|
||||
line_info_goto_root(hst);
|
||||
break;
|
||||
case KEY_END:
|
||||
line_info_reset_start(hst);
|
||||
break;
|
||||
case KEY_PPAGE:
|
||||
line_info_page_up(self, hst);
|
||||
break;
|
||||
|
||||
case KEY_NPAGE:
|
||||
line_info_page_down(self, hst);
|
||||
break;
|
||||
|
||||
case KEY_UP:
|
||||
line_info_scroll_up(hst);
|
||||
break;
|
||||
|
||||
case KEY_DOWN:
|
||||
line_info_scroll_down(hst);
|
||||
break;
|
||||
|
||||
case KEY_HOME:
|
||||
line_info_goto_root(hst);
|
||||
break;
|
||||
|
||||
case KEY_END:
|
||||
line_info_reset_start(hst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -424,7 +438,7 @@ void line_info_onDraw(ToxWindow *self)
|
||||
mvwprintw(ctx->linewin, 1, 0, "Scroll mode:\n");
|
||||
wattroff(ctx->linewin, A_BOLD | COLOR_PAIR(BLUE));
|
||||
mvwprintw(ctx->linewin, 1, 13, "Use up/down arrows, page up/page down, and home/end to navigate.\n"
|
||||
" ESC to exit.\n");
|
||||
" ESC to exit.\n");
|
||||
}
|
||||
|
||||
void line_info_clear(struct history *hst)
|
||||
|
@ -57,12 +57,12 @@ struct history {
|
||||
bool scroll_mode;
|
||||
|
||||
/* keeps track of lines added between window refreshes */
|
||||
uint32_t queue;
|
||||
uint32_t queue;
|
||||
uint32_t queue_lns;
|
||||
};
|
||||
|
||||
/* adds a line to history (also moves line_start and/or line_root forward if necessary) */
|
||||
void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *name2, uint8_t *msg,
|
||||
void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *name2, uint8_t *msg,
|
||||
uint8_t type, uint8_t bold, uint8_t colour);
|
||||
|
||||
/* Prints a section of history starting at line_start */
|
||||
|
@ -46,7 +46,7 @@ void init_logging_session(uint8_t *name, uint8_t *key, struct chatlog *log)
|
||||
name = UNKNOWN_NAME;
|
||||
|
||||
char *user_config_dir = get_user_config_dir();
|
||||
int path_len = strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(name);
|
||||
int path_len = strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(name);
|
||||
|
||||
/* use first 4 digits of key as log ident. If no key use a timestamp */
|
||||
uint8_t ident[32];
|
||||
@ -56,7 +56,7 @@ void init_logging_session(uint8_t *name, uint8_t *key, struct chatlog *log)
|
||||
|
||||
sprintf(&ident[0], "%02X", key[0] & 0xff);
|
||||
sprintf(&ident[2], "%02X", key[1] & 0xff);
|
||||
ident[KEY_IDENT_DIGITS*2+1] = '\0';
|
||||
ident[KEY_IDENT_DIGITS * 2 + 1] = '\0';
|
||||
} else {
|
||||
strftime(ident, sizeof(ident), "%Y-%m-%d[%H:%M:%S]", get_time());
|
||||
path_len += strlen(ident) + 1;
|
||||
@ -70,7 +70,7 @@ void init_logging_session(uint8_t *name, uint8_t *key, struct chatlog *log)
|
||||
|
||||
uint8_t log_path[MAX_STR_SIZE];
|
||||
|
||||
snprintf(log_path, MAX_STR_SIZE, "%s%s%s-%s.log",
|
||||
snprintf(log_path, MAX_STR_SIZE, "%s%s%s-%s.log",
|
||||
user_config_dir, CONFIGDIR, name, ident);
|
||||
|
||||
free(user_config_dir);
|
||||
@ -105,7 +105,7 @@ void write_to_log(const uint8_t *msg, uint8_t *name, struct chatlog *log, bool e
|
||||
const char *t = user_settings->time == TIME_12 ? "%Y/%m/%d [%I:%M:%S %p]" : "%Y/%m/%d [%H:%M:%S]";
|
||||
uint8_t s[MAX_STR_SIZE];
|
||||
strftime(s, MAX_STR_SIZE, t, get_time());
|
||||
fprintf(log->file,"%s %s %s\n", s, name_frmt, msg);
|
||||
fprintf(log->file, "%s %s %s\n", s, name_frmt, msg);
|
||||
|
||||
uint64_t curtime = get_unix_time();
|
||||
|
||||
|
40
src/main.c
40
src/main.c
@ -25,7 +25,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef SIGWINCH
|
||||
#define SIGWINCH 28
|
||||
#define SIGWINCH 28
|
||||
#endif
|
||||
|
||||
#include <curses.h>
|
||||
@ -41,9 +41,9 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <direct.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <sys/stat.h>
|
||||
@ -64,7 +64,7 @@
|
||||
#include "settings.h"
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#include "audio_call.h"
|
||||
#include "audio_call.h"
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
#ifndef PACKAGE_DATADIR
|
||||
@ -72,7 +72,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
ToxAv* av;
|
||||
ToxAv *av;
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
/* Export for use in Callbacks */
|
||||
@ -95,11 +95,13 @@ static void init_term(void)
|
||||
/* Setup terminal */
|
||||
signal(SIGWINCH, on_window_resize);
|
||||
#if HAVE_WIDECHAR
|
||||
|
||||
if (setlocale(LC_ALL, "") == NULL) {
|
||||
fprintf(stderr, "Could not set your locale, plese check your locale settings or"
|
||||
"disable wide char support\n");
|
||||
"disable wide char support\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#endif
|
||||
initscr();
|
||||
cbreak();
|
||||
@ -112,7 +114,7 @@ static void init_term(void)
|
||||
start_color();
|
||||
|
||||
if (user_settings->colour_theme == NATIVE_COLS) {
|
||||
if (assume_default_colors(-1,-1) == OK)
|
||||
if (assume_default_colors(-1, -1) == OK)
|
||||
bg_color = -1;
|
||||
}
|
||||
|
||||
@ -136,7 +138,7 @@ static Tox *init_tox(int ipv4)
|
||||
int ipv6 = !ipv4;
|
||||
Tox *m = tox_new(ipv6);
|
||||
|
||||
/*
|
||||
/*
|
||||
* TOX_ENABLE_IPV6_DEFAULT is always 1.
|
||||
* Checking it is redundant, this *should* be doing ipv4 fallback
|
||||
*/
|
||||
@ -199,11 +201,13 @@ static int nodelist_load(char *filename)
|
||||
return 1;
|
||||
|
||||
char line[MAXLINE];
|
||||
|
||||
while (fgets(line, sizeof(line), fp) && linecnt < MAXNODES) {
|
||||
if (strlen(line) > MINLINE) {
|
||||
char *name = strtok(line, " ");
|
||||
char *port = strtok(NULL, " ");
|
||||
char *key_ascii = strtok(NULL, " ");
|
||||
|
||||
/* invalid line */
|
||||
if (name == NULL || port == NULL || key_ascii == NULL)
|
||||
continue;
|
||||
@ -232,7 +236,7 @@ static int nodelist_load(char *filename)
|
||||
int init_connection_helper(Tox *m, int line)
|
||||
{
|
||||
return tox_bootstrap_from_address(m, nodes[line], TOX_ENABLE_IPV6_DEFAULT,
|
||||
ports[line], keys[line]);
|
||||
ports[line], keys[line]);
|
||||
}
|
||||
|
||||
/* Connects to a random DHT node listed in the DHTnodes file
|
||||
@ -267,7 +271,7 @@ int init_connection(Tox *m)
|
||||
int i;
|
||||
int n = MIN(NUM_INIT_NODES, linecnt);
|
||||
|
||||
for(i = 0; i < n; ++i) {
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (init_connection_helper(m, rand() % linecnt))
|
||||
res = 0;
|
||||
}
|
||||
@ -425,9 +429,9 @@ void exit_toxic(Tox *m)
|
||||
free(prompt->chatwin);
|
||||
free(user_settings);
|
||||
tox_kill(m);
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
terminate_audio();
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
endwin();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@ -484,15 +488,17 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
config_err = create_user_config_dir(user_config_dir);
|
||||
|
||||
if (DATA_FILE == NULL ) {
|
||||
if (config_err) {
|
||||
DATA_FILE = strdup("data");
|
||||
} else {
|
||||
DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1);
|
||||
|
||||
if (DATA_FILE != NULL) {
|
||||
strcpy(DATA_FILE, user_config_dir);
|
||||
strcat(DATA_FILE, CONFIGDIR);
|
||||
strcat(DATA_FILE, "data");
|
||||
strcat(DATA_FILE, "data");
|
||||
} else {
|
||||
endwin();
|
||||
fprintf(stderr, "malloc() failed. Aborting...\n");
|
||||
@ -570,12 +576,12 @@ int main(int argc, char *argv[])
|
||||
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (settings_err == -1) {
|
||||
msg = "Failed to load user settings";
|
||||
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
sort_friendlist_index();
|
||||
prompt_init_statusbar(prompt, m);
|
||||
@ -585,6 +591,6 @@ int main(int argc, char *argv[])
|
||||
do_toxic(m, prompt);
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ int mbs_to_wcs_buf(wchar_t *buf, const uint8_t *string, size_t n)
|
||||
if (n < len)
|
||||
return -1;
|
||||
|
||||
if ((len = mbstowcs(buf, string, n)) == (size_t) -1)
|
||||
if ((len = mbstowcs(buf, string, n)) == (size_t) - 1)
|
||||
return -1;
|
||||
|
||||
return len;
|
||||
@ -113,7 +113,7 @@ int wcs_to_mbs_buf(uint8_t *buf, const wchar_t *string, size_t n)
|
||||
if (n < len)
|
||||
return -1;
|
||||
|
||||
if ((len = wcstombs(buf, string, n)) == (size_t) -1)
|
||||
if ((len = wcstombs(buf, string, n)) == (size_t) - 1)
|
||||
return -1;
|
||||
|
||||
return len;
|
||||
@ -125,11 +125,11 @@ uint8_t *wcs_to_mbs(wchar_t *string)
|
||||
uint8_t *ret = NULL;
|
||||
size_t len = wcstombs(NULL, string, 0);
|
||||
|
||||
if (len != (size_t) -1) {
|
||||
if (len != (size_t) - 1) {
|
||||
ret = malloc(++len);
|
||||
|
||||
if (ret != NULL) {
|
||||
if (wcstombs(ret, string, len) == (size_t) -1)
|
||||
if (wcstombs(ret, string, len) == (size_t) - 1)
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
@ -176,15 +176,17 @@ int timed_out(uint64_t timestamp, uint64_t curtime, uint64_t timeout)
|
||||
void alert_window(ToxWindow *self, int type, bool is_beep)
|
||||
{
|
||||
switch (type) {
|
||||
case WINDOW_ALERT_0:
|
||||
self->alert0 = true;
|
||||
break;
|
||||
case WINDOW_ALERT_1:
|
||||
self->alert1 = true;
|
||||
break;
|
||||
case WINDOW_ALERT_2:
|
||||
self->alert2 = true;
|
||||
break;
|
||||
case WINDOW_ALERT_0:
|
||||
self->alert0 = true;
|
||||
break;
|
||||
|
||||
case WINDOW_ALERT_1:
|
||||
self->alert1 = true;
|
||||
break;
|
||||
|
||||
case WINDOW_ALERT_2:
|
||||
self->alert2 = true;
|
||||
break;
|
||||
}
|
||||
|
||||
StatusBar *stb = prompt->stb;
|
||||
@ -212,8 +214,9 @@ int valid_nick(uint8_t *nick)
|
||||
int i;
|
||||
|
||||
for (i = 0; nick[i]; ++i) {
|
||||
if (nick[i] == ' ' && nick[i+1] == ' ')
|
||||
if (nick[i] == ' ' && nick[i + 1] == ' ')
|
||||
return 0;
|
||||
|
||||
if (nick[i] == '/')
|
||||
return 0;
|
||||
}
|
||||
@ -226,7 +229,7 @@ void mv_curs_end(WINDOW *w, size_t len, int max_y, int max_x)
|
||||
{
|
||||
int end_y = (len / max_x) + (max_y - CURS_Y_OFFSET);
|
||||
int end_x = len % max_x;
|
||||
wmove(w, end_y, end_x);
|
||||
wmove(w, end_y, end_x);
|
||||
}
|
||||
|
||||
/* gets base file name from path or original file name if no path is supplied */
|
||||
@ -235,10 +238,10 @@ void get_file_name(uint8_t *pathname, uint8_t *namebuf)
|
||||
int idx = strlen(pathname) - 1;
|
||||
|
||||
while (idx >= 0 && pathname[idx] == '/')
|
||||
pathname[idx--] = '\0';
|
||||
pathname[idx--] = '\0';
|
||||
|
||||
uint8_t *filename = strrchr(pathname, '/'); /* Try unix style paths */
|
||||
|
||||
|
||||
if (filename != NULL) {
|
||||
if (!strlen(++filename))
|
||||
filename = pathname;
|
||||
|
56
src/prompt.c
56
src/prompt.c
@ -60,12 +60,12 @@ const uint8_t glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
|
||||
{ "/note" },
|
||||
{ "/quit" },
|
||||
{ "/status" },
|
||||
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
|
||||
|
||||
{ "/lsdev" },
|
||||
{ "/sdev" },
|
||||
|
||||
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
};
|
||||
|
||||
@ -99,7 +99,7 @@ void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected)
|
||||
statusbar->is_online = is_connected;
|
||||
}
|
||||
|
||||
/* Adds friend request to pending friend requests.
|
||||
/* Adds friend request to pending friend requests.
|
||||
Returns request number on success, -1 if queue is full or other error. */
|
||||
static int add_friend_request(uint8_t *public_key)
|
||||
{
|
||||
@ -146,7 +146,7 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
}
|
||||
|
||||
if (ltr) {
|
||||
if (ctx->len < (MAX_STR_SIZE-1)) {
|
||||
if (ctx->len < (MAX_STR_SIZE - 1)) {
|
||||
add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key);
|
||||
}
|
||||
} else { /* if (!ltr) */
|
||||
@ -155,7 +155,7 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
|
||||
if (key == 0x107 || key == 0x8 || key == 0x7f) {
|
||||
if (ctx->pos > 0) {
|
||||
del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
|
||||
wmove(ctx->history, y, x-1); /* not necessary but fixes a display glitch */
|
||||
wmove(ctx->history, y, x - 1); /* not necessary but fixes a display glitch */
|
||||
} else {
|
||||
beep();
|
||||
}
|
||||
@ -308,7 +308,7 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
|
||||
--ctx->orig_y;
|
||||
|
||||
} else { /* Mark point of origin for new line */
|
||||
ctx->orig_y = y;
|
||||
ctx->orig_y = y;
|
||||
}
|
||||
|
||||
wattron(ctx->history, COLOR_PAIR(GREEN));
|
||||
@ -325,23 +325,27 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
|
||||
const uint8_t *status_text = "Unknown";
|
||||
|
||||
switch (statusbar->status) {
|
||||
case TOX_USERSTATUS_NONE:
|
||||
status_text = "Online";
|
||||
colour = GREEN;
|
||||
break;
|
||||
case TOX_USERSTATUS_AWAY:
|
||||
status_text = "Away";
|
||||
colour = YELLOW;
|
||||
break;
|
||||
case TOX_USERSTATUS_BUSY:
|
||||
status_text = "Busy";
|
||||
colour = RED;
|
||||
break;
|
||||
case TOX_USERSTATUS_INVALID:
|
||||
status_text = "ERROR";
|
||||
colour = MAGENTA;
|
||||
break;
|
||||
case TOX_USERSTATUS_NONE:
|
||||
status_text = "Online";
|
||||
colour = GREEN;
|
||||
break;
|
||||
|
||||
case TOX_USERSTATUS_AWAY:
|
||||
status_text = "Away";
|
||||
colour = YELLOW;
|
||||
break;
|
||||
|
||||
case TOX_USERSTATUS_BUSY:
|
||||
status_text = "Busy";
|
||||
colour = RED;
|
||||
break;
|
||||
|
||||
case TOX_USERSTATUS_INVALID:
|
||||
status_text = "ERROR";
|
||||
colour = MAGENTA;
|
||||
break;
|
||||
}
|
||||
|
||||
wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
|
||||
wprintw(statusbar->topline, " [%s]", status_text);
|
||||
wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
|
||||
@ -374,7 +378,7 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum
|
||||
|
||||
uint8_t nick[TOX_MAX_NAME_LENGTH] = {0};
|
||||
int n_len = tox_get_name(m, friendnum, nick);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH-1);
|
||||
n_len = MIN(n_len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
|
||||
if (!nick[0]) {
|
||||
snprintf(nick, sizeof(nick), "%s", UNKNOWN_NAME);
|
||||
@ -456,7 +460,7 @@ void prompt_init_statusbar(ToxWindow *self, Tox *m)
|
||||
|
||||
if ( (!strcmp("Online", statusmsg) || !strncmp("Toxing on Toxic", statusmsg, 15)) && toxic_ver != NULL) {
|
||||
snprintf(statusmsg, MAX_STR_SIZE, "Toxing on Toxic v.%s", toxic_ver);
|
||||
s_len = strlen(statusmsg);
|
||||
s_len = strlen(statusmsg);
|
||||
statusmsg[s_len] = '\0';
|
||||
}
|
||||
|
||||
@ -500,7 +504,7 @@ static void prompt_onInit(ToxWindow *self, Tox *m)
|
||||
}
|
||||
|
||||
execute(ctx->history, self, m, "/help", GLOBAL_COMMAND_MODE);
|
||||
wmove(ctx->history, y2-1, 2);
|
||||
wmove(ctx->history, y2 - 1, 2);
|
||||
}
|
||||
|
||||
ToxWindow new_prompt(void)
|
||||
|
10
src/prompt.h
10
src/prompt.h
@ -26,11 +26,11 @@
|
||||
#define X_OFST 2 /* offset to account for prompt char */
|
||||
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#define AC_NUM_GLOB_COMMANDS 17
|
||||
#else
|
||||
#define AC_NUM_GLOB_COMMANDS 15
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#define AC_NUM_GLOB_COMMANDS 17
|
||||
#else
|
||||
#define AC_NUM_GLOB_COMMANDS 15
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
ToxWindow new_prompt(void);
|
||||
void prep_prompt_win(void);
|
||||
|
@ -38,8 +38,8 @@ static void uset_aout_dev(struct user_settings *s, int val);
|
||||
struct {
|
||||
const char *name;
|
||||
void (*func)(struct user_settings *s, int val);
|
||||
} user_settings_list[] = {
|
||||
{ "autolog", uset_autolog },
|
||||
} user_settings_list[] = {
|
||||
{ "autolog", uset_autolog },
|
||||
{ "time", uset_time },
|
||||
{ "disable_alerts", uset_alerts },
|
||||
{ "colour_theme", uset_colours },
|
||||
@ -53,13 +53,13 @@ static void uset_autolog(struct user_settings *s, int val)
|
||||
s->autolog = val == AUTOLOG_ON ? AUTOLOG_ON : AUTOLOG_OFF;
|
||||
}
|
||||
|
||||
static void uset_time(struct user_settings *s, int val)
|
||||
static void uset_time(struct user_settings *s, int val)
|
||||
{
|
||||
/* default to 24 hour time if invalid value */
|
||||
s->time = val == TIME_12 ? TIME_12 : TIME_24;
|
||||
}
|
||||
|
||||
static void uset_alerts(struct user_settings *s, int val)
|
||||
static void uset_alerts(struct user_settings *s, int val)
|
||||
{
|
||||
/* alerts default on if invalid value */
|
||||
s->alerts = val == ALERTS_DISABLED ? ALERTS_DISABLED : ALERTS_ENABLED;
|
||||
|
@ -41,7 +41,7 @@ void add_char_to_buf(wchar_t *buf, size_t *pos, size_t *len, wint_t ch)
|
||||
int i;
|
||||
|
||||
for (i = *len; i >= *pos && i >= 0; --i)
|
||||
buf[i+1] = buf[i];
|
||||
buf[i + 1] = buf[i];
|
||||
|
||||
buf[(*pos)++] = ch;
|
||||
++(*len);
|
||||
@ -56,8 +56,8 @@ void del_char_buf_bck(wchar_t *buf, size_t *pos, size_t *len)
|
||||
int i;
|
||||
|
||||
/* similar to add_char_to_buf but deletes a char */
|
||||
for (i = *pos-1; i <= *len; ++i)
|
||||
buf[i] = buf[i+1];
|
||||
for (i = *pos - 1; i <= *len; ++i)
|
||||
buf[i] = buf[i + 1];
|
||||
|
||||
--(*pos);
|
||||
--(*len);
|
||||
@ -72,7 +72,7 @@ void del_char_buf_frnt(wchar_t *buf, size_t *pos, size_t *len)
|
||||
int i;
|
||||
|
||||
for (i = *pos; i < *len; ++i)
|
||||
buf[i] = buf[i+1];
|
||||
buf[i] = buf[i + 1];
|
||||
|
||||
--(*len);
|
||||
}
|
||||
@ -120,13 +120,13 @@ static void shift_hist_back(wchar_t (*hst)[MAX_STR_SIZE], int *hst_tot)
|
||||
int n = MAX_LINE_HIST - HIST_PURGE;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
wmemcpy(hst[i], hst[i+HIST_PURGE], MAX_STR_SIZE);
|
||||
wmemcpy(hst[i], hst[i + HIST_PURGE], MAX_STR_SIZE);
|
||||
|
||||
*hst_tot = n;
|
||||
}
|
||||
|
||||
/* adds a line to the ln_history buffer at hst_pos and sets hst_pos to end of history. */
|
||||
void add_line_to_hist(const wchar_t *buf, size_t len, wchar_t (*hst)[MAX_STR_SIZE], int *hst_tot,
|
||||
void add_line_to_hist(const wchar_t *buf, size_t len, wchar_t (*hst)[MAX_STR_SIZE], int *hst_tot,
|
||||
int *hst_pos)
|
||||
{
|
||||
if (len > MAX_STR_SIZE)
|
||||
@ -138,12 +138,12 @@ void add_line_to_hist(const wchar_t *buf, size_t len, wchar_t (*hst)[MAX_STR_SIZ
|
||||
++(*hst_tot);
|
||||
*hst_pos = *hst_tot;
|
||||
|
||||
wmemcpy(hst[*hst_tot-1], buf, len + 1);
|
||||
wmemcpy(hst[*hst_tot - 1], buf, len + 1);
|
||||
}
|
||||
|
||||
/* copies history item at hst_pos to buf. Sets pos and len to the len of the history item.
|
||||
hst_pos is decremented or incremented depending on key_dir.
|
||||
|
||||
|
||||
resets buffer if at end of history */
|
||||
void fetch_hist_item(wchar_t *buf, size_t *pos, size_t *len, wchar_t (*hst)[MAX_STR_SIZE],
|
||||
int hst_tot, int *hst_pos, int key_dir)
|
||||
@ -170,12 +170,12 @@ void fetch_hist_item(wchar_t *buf, size_t *pos, size_t *len, wchar_t (*hst)[MAX_
|
||||
*len = h_len;
|
||||
}
|
||||
|
||||
/* looks for the first instance in list that begins with the last entered word in buf according to pos,
|
||||
then fills buf with the complete word. e.g. "Hello jo" would complete the buffer
|
||||
/* looks for the first instance in list that begins with the last entered word in buf according to pos,
|
||||
then fills buf with the complete word. e.g. "Hello jo" would complete the buffer
|
||||
with "Hello john".
|
||||
|
||||
list is a pointer to the list of strings being compared, n_items is the number of items
|
||||
in the list, and size is the size of each item in the list.
|
||||
in the list, and size is the size of each item in the list.
|
||||
|
||||
Returns the difference between the old len and new len of buf on success, -1 if error */
|
||||
int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int n_items, int size)
|
||||
@ -186,6 +186,7 @@ int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int
|
||||
const uint8_t *L = (uint8_t *) list;
|
||||
|
||||
uint8_t ubuf[MAX_STR_SIZE];
|
||||
|
||||
/* work with multibyte string copy of buf for simplicity */
|
||||
if (wcs_to_mbs_buf(ubuf, buf, MAX_STR_SIZE) == -1)
|
||||
return -1;
|
||||
@ -195,10 +196,11 @@ int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int
|
||||
snprintf(tmp, sizeof(tmp), "%s", ubuf);
|
||||
tmp[*pos] = '\0';
|
||||
uint8_t *sub = strrchr(tmp, ' ');
|
||||
int n_endchrs = 1; /* 1 = append space to end of match, 2 = append ": " */
|
||||
int n_endchrs = 1; /* 1 = append space to end of match, 2 = append ": " */
|
||||
|
||||
if (!sub++) {
|
||||
sub = tmp;
|
||||
|
||||
if (sub[0] != '/') /* make sure it's not a command */
|
||||
n_endchrs = 2;
|
||||
}
|
||||
@ -213,7 +215,8 @@ int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int
|
||||
|
||||
/* look for a match in list */
|
||||
for (i = 0; i < n_items; ++i) {
|
||||
match = &L[i*size];
|
||||
match = &L[i * size];
|
||||
|
||||
if (is_match = strncasecmp(match, sub, s_len) == 0)
|
||||
break;
|
||||
}
|
||||
@ -224,7 +227,7 @@ int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int
|
||||
/* put match in correct spot in buf and append endchars (space or ": ") */
|
||||
const uint8_t *endchrs = n_endchrs == 1 ? " " : ": ";
|
||||
int m_len = strlen(match);
|
||||
int strt = (int) *pos - s_len;
|
||||
int strt = (int) * pos - s_len;
|
||||
int diff = m_len - s_len + n_endchrs;
|
||||
|
||||
if (*len + diff > MAX_STR_SIZE)
|
||||
@ -233,8 +236,8 @@ int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int
|
||||
uint8_t tmpend[MAX_STR_SIZE];
|
||||
strcpy(tmpend, &ubuf[*pos]);
|
||||
strcpy(&ubuf[strt], match);
|
||||
strcpy(&ubuf[strt+m_len], endchrs);
|
||||
strcpy(&ubuf[strt+m_len+n_endchrs], tmpend);
|
||||
strcpy(&ubuf[strt + m_len], endchrs);
|
||||
strcpy(&ubuf[strt + m_len + n_endchrs], tmpend);
|
||||
|
||||
/* convert to widechar and copy back to original buf */
|
||||
wchar_t newbuf[MAX_STR_SIZE];
|
||||
|
@ -38,18 +38,18 @@ void kill_buf(wchar_t *buf, size_t *pos, size_t *len);
|
||||
/* nulls buf and sets pos and len to 0 */
|
||||
void reset_buf(wchar_t *buf, size_t *pos, size_t *len);
|
||||
|
||||
/* looks for the first instance in list that begins with the last entered word in buf according to pos,
|
||||
then fills buf with the complete word. e.g. "Hello jo" would complete the buffer
|
||||
/* looks for the first instance in list that begins with the last entered word in buf according to pos,
|
||||
then fills buf with the complete word. e.g. "Hello jo" would complete the buffer
|
||||
with "Hello john".
|
||||
|
||||
list is a pointer to the list of strings being compared, n_items is the number of items
|
||||
in the list, and size is the size of each item in the list.
|
||||
in the list, and size is the size of each item in the list.
|
||||
|
||||
Returns the difference between the old len and new len of buf on success, -1 if error */
|
||||
int complete_line(wchar_t *buf, size_t *pos, size_t *len, const void *list, int n_items, int size);
|
||||
|
||||
/* adds a line to the ln_history buffer at hst_pos and sets hst_pos to last history item. */
|
||||
void add_line_to_hist(const wchar_t *buf, size_t len, wchar_t (*hst)[MAX_STR_SIZE], int *hst_tot,
|
||||
void add_line_to_hist(const wchar_t *buf, size_t len, wchar_t (*hst)[MAX_STR_SIZE], int *hst_tot,
|
||||
int *hst_pos);
|
||||
|
||||
/* copies history item at hst_pos to buf. Sets pos and len to the len of the history item.
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <tox/tox.h>
|
||||
|
||||
#ifdef _SUPPORT_AUDIO
|
||||
#include <tox/toxav.h>
|
||||
#include <tox/toxav.h>
|
||||
#endif /* _SUPPORT_AUDIO */
|
||||
|
||||
#define UNKNOWN_NAME "Anonymous"
|
||||
@ -112,7 +112,7 @@ struct ToxWindow {
|
||||
void(*onGroupMessage)(ToxWindow *, Tox *, int, int, uint8_t *, uint16_t);
|
||||
void(*onGroupAction)(ToxWindow *, Tox *, int, int, uint8_t *, uint16_t);
|
||||
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, uint8_t *);
|
||||
void(*onGroupNamelistChange)(ToxWindow *, Tox*, int, int, uint8_t);
|
||||
void(*onGroupNamelistChange)(ToxWindow *, Tox *, int, int, uint8_t);
|
||||
void(*onFileSendRequest)(ToxWindow *, Tox *, int32_t, uint8_t, uint64_t, uint8_t *, uint16_t);
|
||||
void(*onFileControl)(ToxWindow *, Tox *, int32_t, uint8_t, uint8_t, uint8_t, uint8_t *, uint16_t);
|
||||
void(*onFileData)(ToxWindow *, Tox *, int32_t, uint8_t, uint8_t *, uint16_t);
|
||||
@ -239,8 +239,10 @@ void on_groupmessage(Tox *m, int groupnumber, int peernumber, uint8_t *message,
|
||||
void on_groupaction(Tox *m, int groupnumber, int peernumber, uint8_t *action, uint16_t length, void *userdata);
|
||||
void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t *group_pub_key, void *userdata);
|
||||
void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t change, void *userdata);
|
||||
void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *pathname, uint16_t pathname_length, void *userdata);
|
||||
void on_file_control(Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *userdata);
|
||||
void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *pathname,
|
||||
uint16_t pathname_length, void *userdata);
|
||||
void on_file_control(Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type,
|
||||
uint8_t *data, uint16_t length, void *userdata);
|
||||
void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata);
|
||||
void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata);
|
||||
|
||||
|
@ -184,7 +184,7 @@ void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t ch
|
||||
}
|
||||
}
|
||||
|
||||
void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize,
|
||||
void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize,
|
||||
uint8_t *filename, uint16_t filename_length, void *userdata)
|
||||
{
|
||||
int i;
|
||||
@ -196,7 +196,7 @@ void on_file_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint6
|
||||
}
|
||||
}
|
||||
|
||||
void on_file_control (Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
|
||||
void on_file_control (Tox *m, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
|
||||
uint8_t control_type, uint8_t *data, uint16_t length, void *userdata)
|
||||
{
|
||||
int i;
|
||||
@ -236,6 +236,7 @@ int add_window(Tox *m, ToxWindow w)
|
||||
|
||||
if (w.window == NULL)
|
||||
return -1;
|
||||
|
||||
#ifdef URXVT_FIX
|
||||
/* Fixes text color problem on some terminals. */
|
||||
wbkgd(w.window, COLOR_PAIR(6));
|
||||
@ -405,6 +406,7 @@ void draw_active_window(Tox *m)
|
||||
ltr = iswprint(ch);
|
||||
else /* if (status == KEY_CODE_YES) */
|
||||
ltr = false;
|
||||
|
||||
#else
|
||||
ch = getch();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user