1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-06-26 20:47:45 +02:00

General cleanup

Signed-off-by: Sean Qureshi <sean@tox.im>
This commit is contained in:
Sean Qureshi 2014-04-19 14:58:13 -07:00
parent 7f5dc0a756
commit 4cac797b40
No known key found for this signature in database
GPG Key ID: 13D2043169D25DF4
23 changed files with 806 additions and 723 deletions

View File

@ -26,23 +26,23 @@
#define AUDIO_FRAME_SIZE (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000) #define AUDIO_FRAME_SIZE (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000)
typedef struct _DeviceIx { typedef struct _DeviceIx {
ALCdevice* dhndl; /* Handle of device selected/opened */ ALCdevice *dhndl; /* Handle of device selected/opened */
ALCcontext* ctx; /* Device context */ ALCcontext *ctx; /* Device context */
const char* devices[MAX_DEVICES]; /* Container of available devices */ const char *devices[MAX_DEVICES]; /* Container of available devices */
int size; /* Size of above container */ int size; /* Size of above container */
int dix; /* Index of default device */ int dix; /* Index of default device */
int index; /* Current index */ int index; /* Current index */
} DeviceIx; } DeviceIx;
struct _ASettings { struct _ASettings {
DeviceIx device[2]; DeviceIx device[2];
AudioError errors; AudioError errors;
ToxAv* av; ToxAv *av;
pthread_t ttid; /* Transmission thread id */ pthread_t ttid; /* Transmission thread id */
int ttas; /* Transmission thread active status (0 - stopped, 1- running) */ int ttas; /* Transmission thread active status (0 - stopped, 1- running) */
} ASettins; } ASettins;
@ -57,7 +57,7 @@ void callback_call_canceled ( void *arg );
void callback_call_rejected ( void *arg ); void callback_call_rejected ( void *arg );
void callback_call_ended ( void *arg ); void callback_call_ended ( void *arg );
void callback_requ_timeout ( 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) 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 */ /* Do not error if no device */
if ( !ASettins.device[type].size ) return 0; 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 msg[MAX_STR_SIZE];
uint8_t* error = NULL; uint8_t *error = NULL;
if ( type == input ) { if ( type == input ) {
ASettins.device[type].dhndl = alcCaptureOpenDevice( ASettins.device[type].dhndl = alcCaptureOpenDevice(
ASettins.device[type].devices[ASettins.device[type].index], ASettins.device[type].devices[ASettins.device[type].index],
av_DefaultSettings.audio_sample_rate, av_DefaultSettings.audio_sample_rate,
AL_FORMAT_MONO16, AL_FORMAT_MONO16,
AUDIO_FRAME_SIZE * 4); AUDIO_FRAME_SIZE * 4);
if (alcGetError(ASettins.device[type].dhndl) != AL_NO_ERROR) { if (alcGetError(ASettins.device[type].dhndl) != AL_NO_ERROR) {
/* Now check if we have previous device and act acording to it */ /* Now check if we have previous device and act acording to it */
if ( !prev_device ) { if ( !prev_device ) {
error = "Error starting input device!"; error = "Error starting input device!";
ASettins.errors |= ErrorStartingCaptureDevice; ASettins.errors |= ErrorStartingCaptureDevice;
} } else {
else {
error = "Could not start input device, falling back to previous"; error = "Could not start input device, falling back to previous";
/* NOTE: What if device is opened? */ /* NOTE: What if device is opened? */
ASettins.device[type].dhndl = prev_device; ASettins.device[type].dhndl = prev_device;
} }
} } else {
else
{
/* Close previous */ /* Close previous */
if ( prev_device ) if ( prev_device )
alcCaptureCloseDevice(prev_device); alcCaptureCloseDevice(prev_device);
if ( window ) { if ( window ) {
snprintf(msg, sizeof(msg), "Input device: %s", ASettins.device[type].devices[ASettins.device[type].index]); 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); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
} }
} }
ASettins.device[type].ctx = NULL; ASettins.device[type].ctx = NULL;
} } else {
else {
ASettins.device[type].dhndl = alcOpenDevice(ASettins.device[type].devices[ASettins.device[type].index]); ASettins.device[type].dhndl = alcOpenDevice(ASettins.device[type].devices[ASettins.device[type].index]);
if (alcGetError(ASettins.device[type].dhndl) != AL_NO_ERROR) { if (alcGetError(ASettins.device[type].dhndl) != AL_NO_ERROR) {
/* Now check if we have previous device and act acording to it */ /* Now check if we have previous device and act acording to it */
if ( !prev_device ) { if ( !prev_device ) {
error = "Error starting output device!"; error = "Error starting output device!";
ASettins.errors |= ErrorStartingOutputDevice; ASettins.errors |= ErrorStartingOutputDevice;
ASettins.device[type].ctx = NULL; ASettins.device[type].ctx = NULL;
} } else {
else {
error = "Could not start output device, falling back to previous"; error = "Could not start output device, falling back to previous";
/* NOTE: What if device is opened? */ /* NOTE: What if device is opened? */
ASettins.device[type].dhndl = prev_device; ASettins.device[type].dhndl = prev_device;
} }
} } else {
else {
/* Close previous */ /* Close previous */
if ( prev_device ) { if ( prev_device ) {
alcCaptureCloseDevice(prev_device); alcCaptureCloseDevice(prev_device);
alcMakeContextCurrent(NULL); alcMakeContextCurrent(NULL);
alcDestroyContext(ASettins.device[type].ctx); alcDestroyContext(ASettins.device[type].ctx);
} }
ASettins.device[type].ctx = alcCreateContext(ASettins.device[type].dhndl, NULL); ASettins.device[type].ctx = alcCreateContext(ASettins.device[type].dhndl, NULL);
if ( window ) { if ( window ) {
snprintf(msg, sizeof(msg), "Output device: %s", ASettins.device[type].devices[ASettins.device[type].index]); 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); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
} }
} }
} }
if ( error ) { if ( error ) {
if ( window ) { if ( window ) {
snprintf(msg, sizeof(msg), "Error: %s", error); snprintf(msg, sizeof(msg), "Error: %s", error);
@ -174,32 +168,30 @@ int device_open (ToxWindow *self, _Devices type)
} }
return -1; return -1;
} } else return 0;
else return 0;
} }
int device_close (ToxWindow *self, _Devices type) int device_close (ToxWindow *self, _Devices type)
{ {
uint8_t* device = NULL; uint8_t *device = NULL;
if ( ASettins.device[type].dhndl ) { if ( ASettins.device[type].dhndl ) {
if (type == input) { if (type == input) {
alcCaptureCloseDevice(ASettins.device[type].dhndl); alcCaptureCloseDevice(ASettins.device[type].dhndl);
device = "input"; device = "input";
} } else {
else {
alcCloseDevice(ASettins.device[type].dhndl); alcCloseDevice(ASettins.device[type].dhndl);
alcMakeContextCurrent(NULL); alcMakeContextCurrent(NULL);
if ( ASettins.device[type].ctx ) if ( ASettins.device[type].ctx )
alcDestroyContext(ASettins.device[type].ctx); alcDestroyContext(ASettins.device[type].ctx);
device = "output"; device = "output";
} }
ASettins.device[type].index = ASettins.device[type].dix; ASettins.device[type].index = ASettins.device[type].dix;
} }
if ( self && device ) { if ( self && device ) {
uint8_t msg[MAX_STR_SIZE]; uint8_t msg[MAX_STR_SIZE];
snprintf(msg, sizeof(msg), "Closed %s device", device); 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.errors = NoError;
ASettins.ttas = 0; /* Not running */ ASettins.ttas = 0; /* Not running */
/* Capture devices */ /* 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; ASettins.device[input].size = 0;
if ( stringed_device_list ) { 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 ) { for ( ; *stringed_device_list; ++ASettins.device[input].size ) {
ASettins.device[input].devices[ASettins.device[input].size] = stringed_device_list; ASettins.device[input].devices[ASettins.device[input].size] = stringed_device_list;
if ( strcmp( default_device , ASettins.device[input].devices[ASettins.device[input].size] ) == 0 ) 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; ASettins.device[input].index = ASettins.device[input].dix = ASettins.device[input].size;
stringed_device_list += strlen( stringed_device_list ) + 1; stringed_device_list += strlen( stringed_device_list ) + 1;
} }
} }
/* Output devices */ /* Output devices */
stringed_device_list = alcGetString(NULL, ALC_DEVICE_SPECIFIER); stringed_device_list = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
ASettins.device[output].size = 0; ASettins.device[output].size = 0;
if ( stringed_device_list ) { 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 ) { 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 ) 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; ASettins.device[output].index = ASettins.device[output].dix = ASettins.device[output].size;
stringed_device_list += strlen( stringed_device_list ) + 1; stringed_device_list += strlen( stringed_device_list ) + 1;
} }
} }
if (!ASettins.device[input].size && !ASettins.device[output].size) { if (!ASettins.device[input].size && !ASettins.device[output].size) {
uint8_t *msg = "No devices: disabling audio!"; uint8_t *msg = "No devices: disabling audio!";
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
ASettins.av = NULL; ASettins.av = NULL;
} } else {
else {
/* Streaming stuff from core */ /* Streaming stuff from core */
ToxAvCodecSettings cs = av_DefaultSettings; ToxAvCodecSettings cs = av_DefaultSettings;
cs.video_height = cs.video_width = 0; cs.video_height = cs.video_width = 0;
ASettins.av = toxav_new(tox, &cs); ASettins.av = toxav_new(tox, &cs);
if ( !ASettins.av ) { if ( !ASettins.av ) {
ASettins.errors |= ErrorStartingCoreAudio; ASettins.errors |= ErrorStartingCoreAudio;
return NULL; return NULL;
} }
toxav_register_callstate_callback(callback_call_started, av_OnStart, self); 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_canceled, av_OnCancel, self);
toxav_register_callstate_callback(callback_call_rejected, av_OnReject, 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_call_ended, av_OnEnd, self);
toxav_register_callstate_callback(callback_recv_invite, av_OnInvite, 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_ringing, av_OnRinging, self);
toxav_register_callstate_callback(callback_recv_starting, av_OnStarting, 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_ending, av_OnEnding, self);
toxav_register_callstate_callback(callback_recv_error, av_OnError, 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_requ_timeout, av_OnRequestTimeout, self);
toxav_register_callstate_callback(callback_peer_timeout, av_OnPeerTimeout, self); toxav_register_callstate_callback(callback_peer_timeout, av_OnPeerTimeout, self);
} }
return ASettins.av; return ASettins.av;
} }
void terminate_audio() void terminate_audio()
{ {
stop_transmission(); stop_transmission();
if ( ASettins.av ) if ( ASettins.av )
toxav_kill(ASettins.av); toxav_kill(ASettins.av);
} }
@ -302,133 +293,135 @@ int errors()
* Transmission * Transmission
*/ */
void* transmission(void* arg) void *transmission(void *arg)
{ {
(void)arg; /* Avoid warning */ (void)arg; /* Avoid warning */
/* Missing audio support */ /* Missing audio support */
if ( !ASettins.av ) _cbend; if ( !ASettins.av ) _cbend;
ASettins.ttas = 1; ASettins.ttas = 1;
/* Prepare devices */ /* Prepare devices */
alcCaptureStart(ASettins.device[input].dhndl); alcCaptureStart(ASettins.device[input].dhndl);
alcMakeContextCurrent(ASettins.device[output].ctx); alcMakeContextCurrent(ASettins.device[output].ctx);
int32_t dec_frame_len; int32_t dec_frame_len;
int16_t frame[4096]; int16_t frame[4096];
int32_t sample = 0; int32_t sample = 0;
uint32_t buffer; uint32_t buffer;
int32_t ready; int32_t ready;
int32_t openal_buffers = 5; int32_t openal_buffers = 5;
uint32_t source, *buffers; uint32_t source, *buffers;
/* Prepare buffers */ /* Prepare buffers */
buffers = calloc(sizeof(uint32_t), openal_buffers); buffers = calloc(sizeof(uint32_t), openal_buffers);
alGenBuffers(openal_buffers, buffers); alGenBuffers(openal_buffers, buffers);
alGenSources((uint32_t)1, &source); alGenSources((uint32_t)1, &source);
alSourcei(source, AL_LOOPING, AL_FALSE); alSourcei(source, AL_LOOPING, AL_FALSE);
uint16_t zeros[AUDIO_FRAME_SIZE]; uint16_t zeros[AUDIO_FRAME_SIZE];
memset(zeros, 0, AUDIO_FRAME_SIZE); memset(zeros, 0, AUDIO_FRAME_SIZE);
int16_t PCM[AUDIO_FRAME_SIZE]; int16_t PCM[AUDIO_FRAME_SIZE];
int32_t i = 0; int32_t i = 0;
for (; i < openal_buffers; ++i) { for (; i < openal_buffers; ++i) {
alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, AUDIO_FRAME_SIZE, 48000); alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, AUDIO_FRAME_SIZE, 48000);
} }
alSourceQueueBuffers(source, openal_buffers, buffers); alSourceQueueBuffers(source, openal_buffers, buffers);
alSourcePlay(source); alSourcePlay(source);
if (alGetError() != AL_NO_ERROR) { if (alGetError() != AL_NO_ERROR) {
/* Print something? */ /* Print something? */
/*fprintf(stderr, "Error starting audio\n");*/ /*fprintf(stderr, "Error starting audio\n");*/
goto cleanup; goto cleanup;
} }
/* Start transmission */ /* Start transmission */
while (ASettins.ttas) { while (ASettins.ttas) {
alcGetIntegerv(ASettins.device[input].dhndl, ALC_CAPTURE_SAMPLES, (int32_t) sizeof(int32_t), &sample); alcGetIntegerv(ASettins.device[input].dhndl, ALC_CAPTURE_SAMPLES, (int32_t) sizeof(int32_t), &sample);
/* RECORD AND SEND */ /* RECORD AND SEND */
if (sample >= AUDIO_FRAME_SIZE) { if (sample >= AUDIO_FRAME_SIZE) {
alcCaptureSamples(ASettins.device[input].dhndl, frame, 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")*/; /*fprintf(stderr, "Could not encode or send audio packet\n")*/;
} else usleep(1000); } else usleep(1000);
/* PLAYBACK */ /* PLAYBACK */
alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready); alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready);
if (ready <= 0) if (ready <= 0)
continue; continue;
dec_frame_len = toxav_recv_audio(ASettins.av, AUDIO_FRAME_SIZE, PCM); dec_frame_len = toxav_recv_audio(ASettins.av, AUDIO_FRAME_SIZE, PCM);
/* Play the packet */ /* Play the packet */
if (dec_frame_len > 0) { if (dec_frame_len > 0) {
alSourceUnqueueBuffers(source, 1, &buffer); alSourceUnqueueBuffers(source, 1, &buffer);
alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000); alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000);
int32_t error = alGetError(); int32_t error = alGetError();
if (error != AL_NO_ERROR) { if (error != AL_NO_ERROR) {
/*fprintf(stderr, "Error setting buffer %d\n", error);*/ /*fprintf(stderr, "Error setting buffer %d\n", error);*/
break; break;
} }
alSourceQueueBuffers(source, 1, &buffer); alSourceQueueBuffers(source, 1, &buffer);
if (alGetError() != AL_NO_ERROR) { if (alGetError() != AL_NO_ERROR) {
/*fprintf(stderr, "Error: could not buffer audio\n");*/ /*fprintf(stderr, "Error: could not buffer audio\n");*/
break; break;
} }
alGetSourcei(source, AL_SOURCE_STATE, &ready); alGetSourcei(source, AL_SOURCE_STATE, &ready);
if (ready != AL_PLAYING) alSourcePlay(source); if (ready != AL_PLAYING) alSourcePlay(source);
} }
usleep(1000); usleep(1000);
} }
cleanup: cleanup:
alDeleteSources(1, &source); alDeleteSources(1, &source);
alDeleteBuffers(openal_buffers, buffers); alDeleteBuffers(openal_buffers, buffers);
device_close(NULL, input); device_close(NULL, input);
device_close(NULL, output); device_close(NULL, output);
_cbend; _cbend;
} }
int start_transmission(ToxWindow *self) int start_transmission(ToxWindow *self)
{ {
if ( !ASettins.av ) return -1; if ( !ASettins.av ) return -1;
if ( !toxav_capability_supported(ASettins.av, AudioDecoding) || if ( !toxav_capability_supported(ASettins.av, AudioDecoding) ||
!toxav_capability_supported(ASettins.av, AudioEncoding) ) !toxav_capability_supported(ASettins.av, AudioEncoding) )
return -1; return -1;
/* Now open our devices */ /* Now open our devices */
if ( -1 == device_open(self, input) ) if ( -1 == device_open(self, input) )
return -1; return -1;
if ( -1 == device_open(self, output)) if ( -1 == device_open(self, output))
return -1; return -1;
/* Don't provide support for video */ /* Don't provide support for video */
toxav_prepare_transmission(ASettins.av, 0); toxav_prepare_transmission(ASettins.av, 0);
if ( 0 != pthread_create(&ASettins.ttid, NULL, transmission, NULL ) && if ( 0 != pthread_create(&ASettins.ttid, NULL, transmission, NULL ) &&
0 != pthread_detach(ASettins.ttid) ) { 0 != pthread_detach(ASettins.ttid) ) {
return -1; return -1;
} }
} }
@ -452,53 +445,53 @@ int stop_transmission()
#define CB_BODY(Arg, onFunc) do { ToxWindow* windows = (Arg); int i;\ #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) 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); CB_BODY(arg, onInvite);
} }
void callback_recv_ringing ( void* arg ) void callback_recv_ringing ( void *arg )
{ {
CB_BODY(arg, onRinging); CB_BODY(arg, onRinging);
} }
void callback_recv_starting ( void* arg ) void callback_recv_starting ( void *arg )
{ {
CB_BODY(arg, onStarting); CB_BODY(arg, onStarting);
} }
void callback_recv_ending ( void* arg ) void callback_recv_ending ( void *arg )
{ {
CB_BODY(arg, onEnding); CB_BODY(arg, onEnding);
stop_transmission(); stop_transmission();
} }
void callback_recv_error ( void* arg ) void callback_recv_error ( void *arg )
{ {
CB_BODY(arg, onError); CB_BODY(arg, onError);
} }
void callback_call_started ( void* arg ) void callback_call_started ( void *arg )
{ {
CB_BODY(arg, onStart); CB_BODY(arg, onStart);
} }
void callback_call_canceled ( void* arg ) void callback_call_canceled ( void *arg )
{ {
CB_BODY(arg, onCancel); CB_BODY(arg, onCancel);
/* In case call is active */ /* In case call is active */
stop_transmission(); stop_transmission();
} }
void callback_call_rejected ( void* arg ) void callback_call_rejected ( void *arg )
{ {
CB_BODY(arg, onReject); CB_BODY(arg, onReject);
} }
void callback_call_ended ( void* arg ) void callback_call_ended ( void *arg )
{ {
CB_BODY(arg, onEnd); CB_BODY(arg, onEnd);
stop_transmission(); stop_transmission();
} }
void callback_requ_timeout ( void* arg ) void callback_requ_timeout ( void *arg )
{ {
CB_BODY(arg, onRequestTimeout); CB_BODY(arg, onRequestTimeout);
} }
void callback_peer_timeout ( void* arg ) void callback_peer_timeout ( void *arg )
{ {
CB_BODY(arg, onPeerTimeout); CB_BODY(arg, onPeerTimeout);
stop_transmission(); stop_transmission();
@ -507,8 +500,8 @@ void callback_peer_timeout ( void* arg )
*/ */
toxav_stop_call(ASettins.av); 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]) void cmd_call(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
uint8_t msg[MAX_STR_SIZE]; uint8_t msg[MAX_STR_SIZE];
uint8_t* error_str; uint8_t *error_str;
if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; } if (argc != 0) {
error_str = "Invalid syntax!";
if ( !ASettins.av ) { error_str = "Audio not supported!"; goto on_error; } goto on_error;
}
if ( !ASettins.av ) {
error_str = "Audio not supported!";
goto on_error;
}
ToxAvError error = toxav_call(ASettins.av, self->num, TypeAudio, 30); ToxAvError error = toxav_call(ASettins.av, self->num, TypeAudio, 30);
if ( error != ErrorNone ) { if ( error != ErrorNone ) {
if ( error == ErrorAlreadyInCall ) error_str = "Already in a call!"; if ( error == ErrorAlreadyInCall ) error_str = "Already in a call!";
else error_str = "Internal error!"; else error_str = "Internal error!";
goto on_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]) void cmd_answer(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
uint8_t* error_str; uint8_t *error_str;
if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; } if (argc != 0) {
error_str = "Invalid syntax!";
if ( !ASettins.av ) { error_str = "Audio not supported!"; goto on_error; } goto on_error;
}
if ( !ASettins.av ) {
error_str = "Audio not supported!";
goto on_error;
}
ToxAvError error = toxav_answer(ASettins.av, TypeAudio); ToxAvError error = toxav_answer(ASettins.av, TypeAudio);
if ( error != ErrorNone ) { if ( error != ErrorNone ) {
if ( error == ErrorInvalidState ) error_str = "Cannot answer in invalid state!"; if ( error == ErrorInvalidState ) error_str = "Cannot answer in invalid state!";
else if ( error == ErrorNoCall ) error_str = "No incomming call!"; else if ( error == ErrorNoCall ) error_str = "No incomming call!";
else error_str = "Internal error!"; else error_str = "Internal error!";
goto on_error; goto on_error;
} }
/* Callback will print status... */ /* Callback will print status... */
return; return;
on_error: on_error:
print_err (self, error_str); print_err (self, error_str);
} }
void cmd_reject(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_reject(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
uint8_t* error_str; uint8_t *error_str;
if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; } if (argc != 0) {
error_str = "Invalid syntax!";
if ( !ASettins.av ) { error_str = "Audio not supported!"; goto on_error; } goto on_error;
}
if ( !ASettins.av ) {
error_str = "Audio not supported!";
goto on_error;
}
ToxAvError error = toxav_reject(ASettins.av, "Why not?"); ToxAvError error = toxav_reject(ASettins.av, "Why not?");
if ( error != ErrorNone ) { if ( error != ErrorNone ) {
if ( error == ErrorInvalidState ) error_str = "Cannot reject in invalid state!"; if ( error == ErrorInvalidState ) error_str = "Cannot reject in invalid state!";
else if ( error == ErrorNoCall ) error_str = "No incomming call!"; else if ( error == ErrorNoCall ) error_str = "No incomming call!";
else error_str = "Internal error!"; else error_str = "Internal error!";
goto on_error; goto on_error;
} }
/* Callback will print status... */ /* Callback will print status... */
return; return;
on_error: on_error:
print_err (self, error_str); print_err (self, error_str);
} }
void cmd_hangup(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_hangup(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
uint8_t* error_str; uint8_t *error_str;
if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; } if (argc != 0) {
error_str = "Invalid syntax!";
if ( !ASettins.av ) { error_str = "Audio not supported!"; goto on_error; } goto on_error;
}
if ( !ASettins.av ) {
error_str = "Audio not supported!";
goto on_error;
}
ToxAvError error = toxav_hangup(ASettins.av); ToxAvError error = toxav_hangup(ASettins.av);
if ( error != ErrorNone ) { if ( error != ErrorNone ) {
if ( error == ErrorInvalidState ) error_str = "Cannot hangup in invalid state!"; if ( error == ErrorInvalidState ) error_str = "Cannot hangup in invalid state!";
else if ( error == ErrorNoCall ) error_str = "No call!"; else if ( error == ErrorNoCall ) error_str = "No call!";
else error_str = "Internal error!"; else error_str = "Internal error!";
goto on_error; goto on_error;
} }
return; return;
on_error: on_error:
print_err (self, error_str); print_err (self, error_str);
} }
void cmd_cancel(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_cancel(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
uint8_t* error_str; uint8_t *error_str;
if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; } if (argc != 0) {
error_str = "Invalid syntax!";
if ( !ASettins.av ) { error_str = "Audio not supported!"; goto on_error; } goto on_error;
}
ToxAvError error = toxav_cancel(ASettins.av, self->num, "Only those who appreciate small things know the beauty of life");
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 != ErrorNone ) {
if ( error == ErrorNoCall ) error_str = "No call!"; if ( error == ErrorNoCall ) error_str = "No call!";
else error_str = "Internal error!"; else error_str = "Internal error!";
goto on_error; goto on_error;
} }
/* Callback will print status... */ /* Callback will print status... */
return; return;
on_error: on_error:
print_err (self, error_str); 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]) 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 msg[MAX_STR_SIZE];
uint8_t* error_str; uint8_t *error_str;
if ( argc != 1 ) { 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!"; else error_str = "Only one argument allowed!";
goto on_error; goto on_error;
} }
_Devices type; _Devices type;
if ( strcmp(argv[1], "in") == 0 ) /* Input devices */ if ( strcmp(argv[1], "in") == 0 ) /* Input devices */
type = input; type = input;
else if ( strcmp(argv[1], "out") == 0 ) /* Output devices */ else if ( strcmp(argv[1], "out") == 0 ) /* Output devices */
type = output; type = output;
else { else {
snprintf(msg, sizeof(msg), "Invalid type: %s", argv[1]); snprintf(msg, sizeof(msg), "Invalid type: %s", argv[1]);
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
return; return;
} }
int i = 0; int i = 0;
for ( ; i < ASettins.device[type].size; i ++) { for ( ; i < ASettins.device[type].size; i ++) {
snprintf(msg, sizeof(msg), "%d: %s", i, ASettins.device[type].devices[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); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
} }
return; return;
on_error: on_error:
print_err (self, error_str); print_err (self, error_str);
} }
void cmd_change_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) 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 msg[MAX_STR_SIZE];
uint8_t* error_str; uint8_t *error_str;
if ( argc != 2 ) { if ( argc != 2 ) {
if ( argc < 1 ) error_str = "Type must be specified!"; if ( argc < 1 ) error_str = "Type must be specified!";
else if ( argc < 2 ) error_str = "Must have id!"; else if ( argc < 2 ) error_str = "Must have id!";
else error_str = "Only two arguments allowed!"; else error_str = "Only two arguments allowed!";
goto on_error; goto on_error;
} }
if ( ASettins.ttas ) { /* Transmission is active */ if ( ASettins.ttas ) { /* Transmission is active */
error_str = "Cannot change device while active transmission"; error_str = "Cannot change device while active transmission";
goto on_error; goto on_error;
} }
_Devices type; _Devices type;
if ( strcmp(argv[1], "in") == 0 ) /* Input devices */ if ( strcmp(argv[1], "in") == 0 ) /* Input devices */
type = input; type = input;
else if ( strcmp(argv[1], "out") == 0 ) /* Output devices */ else if ( strcmp(argv[1], "out") == 0 ) /* Output devices */
type = output; type = output;
else { else {
snprintf(msg, sizeof(msg), "Invalid type: %s", argv[1]); snprintf(msg, sizeof(msg), "Invalid type: %s", argv[1]);
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
return; return;
} }
char *end; char *end;
long int selection = strtol(argv[2], &end, 10); long int selection = strtol(argv[2], &end, 10);
if ( *end ) { if ( *end ) {
error_str = "Invalid input"; error_str = "Invalid input";
goto on_error; goto on_error;
@ -724,6 +749,6 @@ void cmd_change_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (
} }
return; return;
on_error: on_error:
print_err (self, error_str); print_err (self, error_str);
} }

View File

@ -9,24 +9,22 @@
#define MAX_DEVICES 32 #define MAX_DEVICES 32
typedef enum _AudioError typedef enum _AudioError {
{
NoError = 0, NoError = 0,
ErrorStartingCaptureDevice = 1 << 0, ErrorStartingCaptureDevice = 1 << 0,
ErrorStartingOutputDevice = 1 << 1, ErrorStartingOutputDevice = 1 << 1,
ErrorStartingCoreAudio = 1 << 2 ErrorStartingCoreAudio = 1 << 2
} AudioError; } AudioError;
typedef enum _Devices typedef enum _Devices {
{
input, input,
output, output,
} _Devices; } _Devices;
/* You will have to pass pointer to first member of 'windows' /* You will have to pass pointer to first member of 'windows'
* declared in windows.c otherwise undefined behaviour will * 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(); void terminate_audio();
int errors(); int errors();

View File

@ -38,7 +38,7 @@
#include "settings.h" #include "settings.h"
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
#include "audio_call.h" #include "audio_call.h"
#endif /* _SUPPORT_AUDIO */ #endif /* _SUPPORT_AUDIO */
extern char *DATA_FILE; extern char *DATA_FILE;
@ -51,9 +51,9 @@ extern struct _Winthread Winthread;
extern struct user_settings *user_settings; extern struct user_settings *user_settings;
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
#define AC_NUM_CHAT_COMMANDS 23 #define AC_NUM_CHAT_COMMANDS 23
#else #else
#define AC_NUM_CHAT_COMMANDS 18 #define AC_NUM_CHAT_COMMANDS 18
#endif /* _SUPPORT_AUDIO */ #endif /* _SUPPORT_AUDIO */
/* Array of chat command names used for tab completion. */ /* 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" }, { "/savefile" },
{ "/sendfile" }, { "/sendfile" },
{ "/status" }, { "/status" },
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
{ "/call" }, { "/call" },
{ "/cancel" }, { "/cancel" },
{ "/answer" }, { "/answer" },
{ "/reject" }, { "/reject" },
{ "/hangup" }, { "/hangup" },
#endif /* _SUPPORT_AUDIO */ #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]; uint8_t nick[TOX_MAX_NAME_LENGTH];
int n_len = tox_get_name(m, num, nick); 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'; nick[n_len] = '\0';
uint8_t timefrmt[TIME_STR_SIZE]; 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]; uint8_t nick[TOX_MAX_NAME_LENGTH];
int n_len = tox_get_name(m, num, nick); 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'; nick[n_len] = '\0';
uint8_t timefrmt[TIME_STR_SIZE]; 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) if (self->num != num)
return; return;
len = MIN(len, TOXIC_MAX_NAME_LENGTH-1); len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
nick[len] = '\0'; nick[len] = '\0';
strcpy(self->name, nick); strcpy(self->name, nick);
} }
@ -219,7 +219,7 @@ static void chat_onStatusMessageChange(ToxWindow *self, int32_t num, uint8_t *st
statusbar->statusmsg[len] = '\0'; 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) uint64_t filesize, uint8_t *pathname, uint16_t path_len)
{ {
if (self->num != num) 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]; uint8_t filename[MAX_STR_SIZE];
get_file_name(pathname, filename); get_file_name(pathname, filename);
snprintf(msg, sizeof(msg), "File transfer request for '%s' (%llu bytes).", filename, snprintf(msg, sizeof(msg), "File transfer request for '%s' (%llu bytes).", filename,
(long long unsigned int)filesize); (long long unsigned int)filesize);
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
if (filenum >= MAX_FILES) { 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"))) { while ((filecheck = fopen(filename, "r"))) {
filename[len] = '\0'; filename[len] = '\0';
char d[9]; char d[9];
sprintf(d,"(%d)", count++); sprintf(d, "(%d)", count++);
strcat(filename, d); strcat(filename, d);
filename[len + strlen(d)] = '\0'; filename[len + strlen(d)] = '\0';
@ -280,7 +280,7 @@ static void chat_close_file_receiver(int num, uint8_t filenum)
fclose(file); 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) uint8_t filenum, uint8_t control_type, uint8_t *data, uint16_t length)
{ {
if (self->num != num) 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; filename = file_senders[filenum].pathname;
switch (control_type) { switch (control_type) {
case TOX_FILECONTROL_ACCEPT: case TOX_FILECONTROL_ACCEPT:
snprintf(msg, sizeof(msg), "File transfer for '%s' accepted (%.1f%%)", filename, 0.0); 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; file_senders[filenum].line_id = self->chatwin->hst->line_end->id + 1;
break; break;
/*case TOX_FILECONTROL_PAUSE:
wprintw(ctx->history, "File transfer for '%s' paused.\n", filename); /*case TOX_FILECONTROL_PAUSE:
break; */ wprintw(ctx->history, "File transfer for '%s' paused.\n", filename);
case TOX_FILECONTROL_KILL: break; */
snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", filename); case TOX_FILECONTROL_KILL:
if (receive_send == 0) 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); chat_close_file_receiver(num, filenum);
break; break;
case TOX_FILECONTROL_FINISHED:
snprintf(msg, sizeof(msg), "File transfer for '%s' complete.", filename);
chat_close_file_receiver(num, filenum);
break;
} }
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); 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]; uint8_t msg[MAX_STR_SIZE + TOX_MAX_NAME_LENGTH];
int n_len = tox_get_name(m, friendnumber, name); 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'; name[n_len] = '\0';
snprintf(msg, sizeof(msg), "%s has invited you to a group chat.\n" 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); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
memcpy(friends[friendnumber].pending_groupchat, group_pub_key, TOX_CLIENT_ID_SIZE); 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\""; uint8_t *msg = "Incoming audio call!\nType: \"/answer\" or \"/reject\"";
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
alert_window(self, WINDOW_ALERT_0, true); 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) void chat_onStart (ToxWindow *self, ToxAv *av)
{ {
if (self->num != toxav_get_peer_id(av, 0)) if (self->num != toxav_get_peer_id(av, 0))
return; return;
@ -492,7 +496,8 @@ void chat_onPeerTimeout (ToxWindow *self, ToxAv *av)
#endif /* _SUPPORT_AUDIO */ #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) if (action == NULL)
return; return;
@ -536,11 +541,11 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (ltr) { if (ltr) {
/* prevents buffer overflows and strange behaviour when cursor goes past the window */ /* 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); add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key);
if (x == x2-1) if (x == x2 - 1)
wmove(self->window, y+1, 0); wmove(self->window, y + 1, 0);
else else
wmove(self->window, y, x + MAX(1, wcwidth(key))); 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); del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
if (x == 0) if (x == 0)
wmove(self->window, y-1, x2 - cur_len); wmove(self->window, y - 1, x2 - cur_len);
else else
wmove(self->window, y, x - cur_len); wmove(self->window, y, x - cur_len);
} else { } 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 */ 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) { if (ctx->pos != ctx->len) {
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])); cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
if (x == 0) if (x == 0)
wmove(self->window, y-1, x2 - cur_len); wmove(self->window, y - 1, x2 - cur_len);
else else
wmove(self->window, y, x - cur_len); wmove(self->window, y, x - cur_len);
} else { } 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])); cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
++ctx->pos; ++ctx->pos;
if (x == x2-1) if (x == x2 - 1)
wmove(self->window, y+1, 0); wmove(self->window, y + 1, 0);
else else
wmove(self->window, y, x + cur_len); wmove(self->window, y, x + cur_len);
} else { } else {
@ -649,9 +654,9 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
if (diff != -1) { if (diff != -1) {
if (x + diff > x2 - 1) { if (x + diff > x2 - 1) {
int ofst = (x + diff - 1) - (x2 - 1); int ofst = (x + diff - 1) - (x2 - 1);
wmove(self->window, y+1, ofst); wmove(self->window, y + 1, ofst);
} else { } else {
wmove(self->window, y, x+diff); wmove(self->window, y, x + diff);
} }
} else { } else {
beep(); beep();
@ -730,7 +735,7 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
if (ctx->len > 0 && !ctx->hst->scroll_mode) { if (ctx->len > 0 && !ctx->hst->scroll_mode) {
uint8_t line[MAX_STR_SIZE]; uint8_t line[MAX_STR_SIZE];
if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) { if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) {
reset_buf(ctx->line, &ctx->pos, &ctx->len); reset_buf(ctx->line, &ctx->pos, &ctx->len);
wmove(self->window, y2 - CURS_Y_OFFSET, 0); 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; uint8_t status = statusbar->status;
switch (status) { switch (status) {
case TOX_USERSTATUS_NONE: case TOX_USERSTATUS_NONE:
status_text = "Online"; status_text = "Online";
colour = GREEN; colour = GREEN;
break; break;
case TOX_USERSTATUS_AWAY:
status_text = "Away"; case TOX_USERSTATUS_AWAY:
colour = YELLOW; status_text = "Away";
break; colour = YELLOW;
case TOX_USERSTATUS_BUSY: break;
status_text = "Busy";
colour = RED; case TOX_USERSTATUS_BUSY:
break; status_text = "Busy";
case TOX_USERSTATUS_INVALID: colour = RED;
status_text = "ERROR"; break;
colour = MAGENTA;
break; case TOX_USERSTATUS_INVALID:
status_text = "ERROR";
colour = MAGENTA;
break;
} }
wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD); 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 */ /* Truncate note if it doesn't fit in statusbar */
uint16_t maxlen = x2 - getcurx(statusbar->topline) - (KEY_IDENT_DIGITS * 2) - 7; uint16_t maxlen = x2 - getcurx(statusbar->topline) - (KEY_IDENT_DIGITS * 2) - 7;
if (statusbar->statusmsg_len > maxlen) { if (statusbar->statusmsg_len > maxlen) {
statusbar->statusmsg[maxlen] = '\0'; statusbar->statusmsg[maxlen] = '\0';
statusbar->statusmsg_len = maxlen; statusbar->statusmsg_len = maxlen;
@ -852,9 +861,9 @@ static void chat_onInit(ToxWindow *self, Tox *m)
ChatContext *ctx = self->chatwin; ChatContext *ctx = self->chatwin;
statusbar->topline = subwin(self->window, 2, x2, 0, 0); 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); 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->hst = malloc(sizeof(struct history));
ctx->log = malloc(sizeof(struct chatlog)); ctx->log = malloc(sizeof(struct chatlog));
@ -901,7 +910,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
ret.onFileSendRequest = &chat_onFileSendRequest; ret.onFileSendRequest = &chat_onFileSendRequest;
ret.onFileControl = &chat_onFileControl; ret.onFileControl = &chat_onFileControl;
ret.onFileData = &chat_onFileData; ret.onFileData = &chat_onFileData;
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
ret.onInvite = &chat_onInvite; ret.onInvite = &chat_onInvite;
ret.onRinging = &chat_onRinging; ret.onRinging = &chat_onRinging;
@ -919,7 +928,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
uint8_t name[TOX_MAX_NAME_LENGTH] = {'\0'}; uint8_t name[TOX_MAX_NAME_LENGTH] = {'\0'};
int len = tox_get_name(m, friendnum, name); 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'; name[len] = '\0';
strcpy(ret.name, name); strcpy(ret.name, name);

View File

@ -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); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
#define NUMLINES 13 #define NUMLINES 13
#else #else
#define NUMLINES 9 #define NUMLINES 9
#endif #endif
uint8_t lines[NUMLINES][MAX_STR_SIZE] = { uint8_t lines[NUMLINES][MAX_STR_SIZE] = {
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
{ " /call : Audio call" }, { " /call : Audio call" },
{ " /cancel : Cancel call" }, { " /cancel : Cancel call" },
{ " /answer : Answer incomming call" }, { " /answer : Answer incomming call" },
{ " /reject : Reject incoming call" }, { " /reject : Reject incoming call" },
{ " /hangup : Hangup active call" }, { " /hangup : Hangup active call" },
#endif /* _SUPPORT_AUDIO */ #endif /* _SUPPORT_AUDIO */
{ " /invite <n> : Invite friend to a group chat" }, { " /invite <n> : Invite friend to a group chat" },
{ " /join : Join a pending group chat" }, { " /join : Join a pending group chat" },
{ " /log <on> or <off> : Enable/disable logging" }, { " /log <on> or <off> : Enable/disable logging" },
{ " /sendfile <filepath> : Send a file" }, { " /sendfile <filepath> : Send a file" },
{ " /savefile <n> : Receive a file" }, { " /savefile <n> : Receive a file" },
{ " /close : Close the current chat window" }, { " /close : Close the current chat window" },
{ " /help : Print this message again" }, { " /help : Print this message again" },
{ " /help global : Show a list of global commands" }, { " /help global : Show a list of global commands" },
}; };
int i; int i;
@ -160,9 +160,9 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
uint8_t *errmsg; uint8_t *errmsg;
if (argc != 1) { if (argc != 1) {
errmsg = "Invalid syntax."; errmsg = "Invalid syntax.";
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
return; return;
} }
uint8_t filenum = atoi(argv[1]); 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; 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."; errmsg = "Please wait for some of your outgoing file transfers to complete.";
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
return; return;
} }
if (argc < 1) { if (argc < 1) {
errmsg = "Invalid syntax."; errmsg = "Invalid syntax.";
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
return; return;
} }
uint8_t *path = argv[1]; uint8_t *path = argv[1];
@ -224,7 +224,7 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
return; return;
} }
path[strlen(++path)-1] = L'\0'; path[strlen(++path) - 1] = L'\0';
int path_len = strlen(path); int path_len = strlen(path);
if (path_len > MAX_STR_SIZE) { if (path_len > MAX_STR_SIZE) {
@ -279,5 +279,5 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
return; return;
} }
} }
} }

View File

@ -110,6 +110,7 @@ char *get_user_config_dir(void)
# else /* __APPLE__ */ # else /* __APPLE__ */
const char *tmp; const char *tmp;
if (!(tmp = getenv("XDG_CONFIG_HOME"))) { if (!(tmp = getenv("XDG_CONFIG_HOME"))) {
len = strlen(home) + strlen("/.config") + 1; len = strlen(home) + strlen("/.config") + 1;
user_config_dir = malloc(len); user_config_dir = malloc(len);

View File

@ -66,7 +66,7 @@ static struct cmd_func chat_commands[] = {
{ "/join", cmd_join_group }, { "/join", cmd_join_group },
{ "/savefile", cmd_savefile }, { "/savefile", cmd_savefile },
{ "/sendfile", cmd_sendfile }, { "/sendfile", cmd_sendfile },
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
{ "/call", cmd_call }, { "/call", cmd_call },
{ "/cancel", cmd_cancel }, { "/cancel", cmd_cancel },
@ -76,7 +76,7 @@ static struct cmd_func chat_commands[] = {
#endif /* _SUPPORT_AUDIO */ #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. */ Returns number of arguments on success, -1 on failure. */
static int parse_command(WINDOW *w, ToxWindow *self, char *cmd, char (*args)[MAX_STR_SIZE]) 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 */ /* characters wrapped in double quotes count as one arg */
while (!cmd_end && num_args < MAX_NUM_ARGS) { while (!cmd_end && num_args < MAX_NUM_ARGS) {
if (*cmd == '\"') { if (*cmd == '\"') {
end = strchr(cmd+1, '\"'); end = strchr(cmd + 1, '\"');
if (end++ == NULL) { /* Increment past the end quote */ if (end++ == NULL) { /* Increment past the end quote */
uint8_t *errmsg = "Invalid argument. Did you forget a closing \"?"; 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) { for (i = 0; i < num_cmds; ++i) {
if (strcmp(args[0], commands[i].name) == 0) { 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; return 0;
} }
} }
@ -128,7 +128,7 @@ static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, int num_
return 1; 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)) if (string_is_empty(cmd))
return; return;
@ -139,18 +139,19 @@ void execute(WINDOW* w, ToxWindow *self, Tox *m, char *cmd, int mode)
if (num_args == -1) if (num_args == -1)
return; return;
/* Try to match input command to command functions. If non-global command mode is specified, /* 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 specified mode's commands first, then upon failure try global commands.
Note: Global commands must come last in case of duplicate command names */ Note: Global commands must come last in case of duplicate command names */
switch (mode) { switch (mode) {
case CHAT_COMMAND_MODE: case CHAT_COMMAND_MODE:
if (do_command(w, self, m, num_args, CHAT_NUM_COMMANDS, chat_commands, args) == 0) if (do_command(w, self, m, num_args, CHAT_NUM_COMMANDS, chat_commands, args) == 0)
return; return;
break;
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) if (do_command(w, self, m, num_args, GLOBAL_NUM_COMMANDS, global_commands, args) == 0)

View File

@ -22,12 +22,12 @@
#define MAX_NUM_ARGS 4 /* Includes command */ #define MAX_NUM_ARGS 4 /* Includes command */
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
#define GLOBAL_NUM_COMMANDS 16 #define GLOBAL_NUM_COMMANDS 16
#define CHAT_NUM_COMMANDS 10 #define CHAT_NUM_COMMANDS 10
#else #else
#define GLOBAL_NUM_COMMANDS 14 #define GLOBAL_NUM_COMMANDS 14
#define CHAT_NUM_COMMANDS 5 #define CHAT_NUM_COMMANDS 5
#endif /* _SUPPORT_AUDIO */ #endif /* _SUPPORT_AUDIO */
enum { enum {

View File

@ -42,7 +42,7 @@ static void close_file_sender(int i)
int j; int j;
for (j = max_file_senders_index; j > 0; --j) { for (j = max_file_senders_index; j > 0; --j) {
if (file_senders[j-1].active) if (file_senders[j - 1].active)
break; break;
} }
@ -90,12 +90,12 @@ void do_file_senders(Tox *m)
} }
while (true) { 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) file_senders[i].piecelen) == -1)
break; break;
file_senders[i].timestamp = current_time; 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); tox_file_data_size(m, friendnum), fp);
/* refresh line with percentage complete */ /* refresh line with percentage complete */

View File

@ -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 */ /* 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"; 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, strftime(friends[num].last_online.hour_min_str, TIME_STR_SIZE, t,
&friends[num].last_online.tm); &friends[num].last_online.tm);
} }
static void friendlist_onMessage(ToxWindow *self, Tox *m, int32_t num, uint8_t *str, uint16_t len) 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'}; uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
int n_len = tox_get_name(m, num, nick); 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'; nick[n_len] = '\0';
uint8_t timefrmt[TIME_STR_SIZE]; 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) if (len > TOX_MAX_NAME_LENGTH || num >= max_friends_index)
return; return;
len = MIN(len, TOXIC_MAX_NAME_LENGTH-1); len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
str[len] = '\0'; str[len] = '\0';
strcpy(friends[num].name, str); 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, static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t filenum,
uint64_t filesize, uint8_t *filename, uint16_t filename_len) uint64_t filesize, uint8_t *filename, uint16_t filename_len)
{ {
if (num >= max_friends_index) if (num >= max_friends_index)
return; return;
@ -221,7 +221,7 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u
uint8_t nick[TOX_MAX_NAME_LENGTH]; uint8_t nick[TOX_MAX_NAME_LENGTH];
int n_len = tox_get_name(m, num, nick); 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'; nick[n_len] = '\0';
uint8_t msg[MAX_STR_SIZE]; uint8_t msg[MAX_STR_SIZE];
@ -244,7 +244,7 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, uint8
} else { } else {
uint8_t nick[TOX_MAX_NAME_LENGTH]; uint8_t nick[TOX_MAX_NAME_LENGTH];
int n_len = tox_get_name(m, num, nick); 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'; nick[n_len] = '\0';
uint8_t msg[MAX_STR_SIZE]; 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); tox_del_friend(m, f_num);
memset(&friends[f_num], 0, sizeof(ToxicFriend)); memset(&friends[f_num], 0, sizeof(ToxicFriend));
int i; int i;
for (i = max_friends_index; i > 0; --i) { for (i = max_friends_index; i > 0; --i) {
if (friends[i-1].active) if (friends[i - 1].active)
break; break;
} }
@ -305,7 +305,7 @@ static void del_friend_deactivate(ToxWindow *self, Tox *m, wint_t key)
{ {
if (key == 'y') if (key == 'y')
delete_friend(m, pendingdelete.num); delete_friend(m, pendingdelete.num);
memset(&pendingdelete, 0, sizeof(pendingdelete)); memset(&pendingdelete, 0, sizeof(pendingdelete));
delwin(self->popup); delwin(self->popup);
self->popup = NULL; self->popup = NULL;
@ -427,24 +427,27 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
} else { } else {
wprintw(self->window, " "); wprintw(self->window, " ");
} }
if (friends[f].online) { if (friends[f].online) {
uint8_t status = friends[f].status; uint8_t status = friends[f].status;
int colour = WHITE; int colour = WHITE;
switch (status) { switch (status) {
case TOX_USERSTATUS_NONE: case TOX_USERSTATUS_NONE:
colour = GREEN; colour = GREEN;
break; break;
case TOX_USERSTATUS_AWAY:
colour = YELLOW; case TOX_USERSTATUS_AWAY:
break; colour = YELLOW;
case TOX_USERSTATUS_BUSY: break;
colour = RED;
break; case TOX_USERSTATUS_BUSY:
case TOX_USERSTATUS_INVALID: colour = RED;
colour = MAGENTA; break;
break;
case TOX_USERSTATUS_INVALID:
colour = MAGENTA;
break;
} }
wattron(self->window, COLOR_PAIR(colour) | A_BOLD); 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'}; uint8_t statusmsg[TOX_MAX_STATUSMESSAGE_LENGTH] = {'\0'};
pthread_mutex_lock(&Winthread.lock); pthread_mutex_lock(&Winthread.lock);
uint16_t s_len = tox_get_status_message(m, friends[f].num, statusmsg, uint16_t s_len = tox_get_status_message(m, friends[f].num, statusmsg,
TOX_MAX_STATUSMESSAGE_LENGTH); TOX_MAX_STATUSMESSAGE_LENGTH);
pthread_mutex_unlock(&Winthread.lock); pthread_mutex_unlock(&Winthread.lock);
friends[f].statusmsg_len = s_len; 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 */ /* Truncate note if it doesn't fit on one line */
uint16_t maxlen = x2 - getcurx(self->window) - 2; uint16_t maxlen = x2 - getcurx(self->window) - 2;
if (friends[f].statusmsg_len > maxlen) { if (friends[f].statusmsg_len > maxlen) {
friends[f].statusmsg[maxlen-3] = '\0'; friends[f].statusmsg[maxlen - 3] = '\0';
strcat(friends[f].statusmsg, "..."); strcat(friends[f].statusmsg, "...");
friends[f].statusmsg[maxlen] = '\0'; friends[f].statusmsg[maxlen] = '\0';
friends[f].statusmsg_len = maxlen; friends[f].statusmsg_len = maxlen;
@ -500,7 +504,7 @@ static void friendlist_onDraw(ToxWindow *self, Tox *m)
if (f_selected) if (f_selected)
wattroff(self->window, COLOR_PAIR(YELLOW)); wattroff(self->window, COLOR_PAIR(YELLOW));
uint64_t last_seen = friends[f].last_online.last_on; uint64_t last_seen = friends[f].last_online.last_on;
if (last_seen != 0) { 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; const uint8_t *hourmin = friends[f].last_online.hour_min_str;
switch (day_dist) { switch (day_dist) {
case 0: case 0:
wprintw(self->window, " Last seen: Today %s\n", hourmin); wprintw(self->window, " Last seen: Today %s\n", hourmin);
break; break;
case 1:
wprintw(self->window, " Last seen: Yesterday %s\n", hourmin); case 1:
break; wprintw(self->window, " Last seen: Yesterday %s\n", hourmin);
default: break;
wprintw(self->window, " Last seen: %d days ago\n", day_dist);
break; default:
} wprintw(self->window, " Last seen: %d days ago\n", day_dist);
break;
}
} else { } else {
wprintw(self->window, " Last seen: Never\n"); 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) static void friendlist_onAv(ToxWindow *self, ToxAv *av)
{ {
int id = toxav_get_peer_id(av, 0); int id = toxav_get_peer_id(av, 0);
/*id++;*/ /*id++;*/
if ( id != ErrorInternal && id >= max_friends_index) if ( id != ErrorInternal && id >= max_friends_index)
return; return;
Tox* m = toxav_get_tox(av); Tox *m = toxav_get_tox(av);
if (friends[id].chatwin == -1) { if (friends[id].chatwin == -1) {
if (get_num_active_windows() < MAX_WINDOWS_NUM) { if (get_num_active_windows() < MAX_WINDOWS_NUM) {
friends[id].chatwin = add_window(m, new_chat(m, friends[id].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'}; uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
int n_len = tox_get_name(m, id, nick); 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'; nick[n_len] = '\0';
uint8_t msg[MAX_STR_SIZE]; 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."; uint8_t *errmsg = "* Warning: Too many windows are open.";
line_info_add(prompt, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED); line_info_add(prompt, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
alert_window(prompt, WINDOW_ALERT_0, true); alert_window(prompt, WINDOW_ALERT_0, true);
} }
} }
@ -586,7 +593,7 @@ ToxWindow new_friendlist(void)
ret.onStatusMessageChange = &friendlist_onStatusMessageChange; ret.onStatusMessageChange = &friendlist_onStatusMessageChange;
ret.onFileSendRequest = &friendlist_onFileSendRequest; ret.onFileSendRequest = &friendlist_onFileSendRequest;
ret.onGroupInvite = &friendlist_onGroupInvite; ret.onGroupInvite = &friendlist_onGroupInvite;
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
ret.onInvite = &friendlist_onAv; ret.onInvite = &friendlist_onAv;
ret.onRinging = &friendlist_onAv; ret.onRinging = &friendlist_onAv;

View File

@ -54,7 +54,7 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
int req = atoi(argv[1]); 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."; msg = "No pending friend request with that number.";
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
return; return;
@ -80,7 +80,7 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
int i; int i;
for (i = num_frnd_requests; i > 0; --i) { for (i = num_frnd_requests; i > 0; --i) {
if (!strlen(pending_frnd_requests[i-1])) if (!strlen(pending_frnd_requests[i - 1]))
break; break;
} }
@ -110,7 +110,7 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
return; return;
} }
temp[strlen(++temp)-1] = L'\0'; temp[strlen(++temp) - 1] = L'\0';
snprintf(msg, sizeof(msg), "%s", temp); snprintf(msg, sizeof(msg), "%s", temp);
} else { } else {
uint8_t selfname[TOX_MAX_NAME_LENGTH]; 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)); int32_t f_num = tox_add_friend(m, id_bin, msg, strlen(msg));
switch (f_num) { switch (f_num) {
case TOX_FAERR_TOOLONG: case TOX_FAERR_TOOLONG:
errmsg = "Message is too long."; errmsg = "Message is too long.";
break; break;
case TOX_FAERR_NOMESSAGE:
errmsg = "Please add a message to your request."; case TOX_FAERR_NOMESSAGE:
break; errmsg = "Please add a message to your request.";
case TOX_FAERR_OWNKEY: break;
errmsg = "That appears to be your own ID.";
break; case TOX_FAERR_OWNKEY:
case TOX_FAERR_ALREADYSENT: errmsg = "That appears to be your own ID.";
errmsg = "Friend request has already been sent."; break;
break;
case TOX_FAERR_UNKNOWN: case TOX_FAERR_ALREADYSENT:
errmsg = "Undefined error when adding friend."; errmsg = "Friend request has already been sent.";
break; break;
case TOX_FAERR_BADCHECKSUM:
errmsg = "Bad checksum in address."; case TOX_FAERR_UNKNOWN:
break; errmsg = "Undefined error when adding friend.";
case TOX_FAERR_SETNEWNOSPAM: break;
errmsg = "Nospam was different (is this contact already added?";
break; case TOX_FAERR_BADCHECKSUM:
default: errmsg = "Bad checksum in address.";
errmsg = "Friend request sent."; break;
on_friendadded(m, f_num, true);
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); line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
@ -192,9 +199,9 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
/* check arguments */ /* check arguments */
if (argc != 3) { if (argc != 3) {
errmsg = "Invalid syntax."; errmsg = "Invalid syntax.";
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
return; return;
} }
char *ip = argv[1]; char *ip = argv[1];
@ -314,9 +321,9 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
/* check arguments */ /* check arguments */
if (argc < 1) { if (argc < 1) {
errmsg = "Invalid name."; errmsg = "Invalid name.";
line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0); line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
return; return;
} }
uint8_t *nick = argv[1]; uint8_t *nick = argv[1];
@ -334,7 +341,7 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
return; return;
} }
len = MIN(len, TOXIC_MAX_NAME_LENGTH-1); len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
nick[len] = L'\0'; nick[len] = L'\0';
@ -362,7 +369,7 @@ void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
return; return;
} }
msg[strlen(++msg)-1] = L'\0'; msg[strlen(++msg) - 1] = L'\0';
uint16_t len = strlen(msg); uint16_t len = strlen(msg);
tox_set_status_message(m, msg, len); tox_set_status_message(m, msg, len);
prompt_update_statusmessage(prompt, msg, len); prompt_update_statusmessage(prompt, msg, len);
@ -378,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); line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
#define NUMLINES 14 #define NUMLINES 14
#else #else
#define NUMLINES 12 #define NUMLINES 12
#endif #endif
uint8_t lines[NUMLINES][MAX_STR_SIZE] = { uint8_t lines[NUMLINES][MAX_STR_SIZE] = {
{ " /add <id> <msg> : Add friend with optional message" }, { " /add <id> <msg> : Add friend with optional message" },
{ " /accept <n> : Accept friend request" }, { " /accept <n> : Accept friend request" },
{ " /connect <ip> <port> <key> : Manually connect to a DHT node" }, { " /connect <ip> <port> <key> : Manually connect to a DHT node" },
{ " /status <type> <msg> : Set status with optional note" }, { " /status <type> <msg> : Set status with optional note" },
{ " /note <msg> : Set a personal note" }, { " /note <msg> : Set a personal note" },
{ " /nick <nick> : Set your nickname" }, { " /nick <nick> : Set your nickname" },
{ " /log <on> or <off> : Enable/disable logging" }, { " /log <on> or <off> : Enable/disable logging" },
{ " /groupchat : Create a group chat" }, { " /groupchat : Create a group chat" },
{ " /myid : Print your ID" }, { " /myid : Print your ID" },
{ " /help : Print this message again" }, { " /help : Print this message again" },
{ " /clear : Clear window history" }, { " /clear : Clear window history" },
{ " /quit or /exit : Exit Toxic" }, { " /quit or /exit : Exit Toxic" },
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
{ " /lsdev <type> : List devices where type: in|out" }, { " /lsdev <type> : List devices where type: in|out" },
{ " /sdev <type> <id> : Set active device" }, { " /sdev <type> <id> : Set active device" },
#endif /* _SUPPORT_AUDIO */ #endif /* _SUPPORT_AUDIO */
}; };
int i; int i;
for (i = 0; i < NUMLINES; ++i) for (i = 0; i < NUMLINES; ++i)
@ -441,7 +448,7 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
char *status = argv[1]; char *status = argv[1];
int len = strlen(status); int len = strlen(status);
char l_status[len+1]; char l_status[len + 1];
int i; int i;
for (i = 0; i <= len; ++i) for (i = 0; i <= len; ++i)
@ -465,7 +472,7 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
prompt_update_status(prompt, status_kind); prompt_update_status(prompt, status_kind);
if (msg != NULL) { 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); uint16_t len = strlen(msg);
tox_set_status_message(m, msg, len); tox_set_status_message(m, msg, len);
prompt_update_statusmessage(prompt, msg, len); prompt_update_statusmessage(prompt, msg, len);

View File

@ -108,7 +108,7 @@ static void close_groupchat(ToxWindow *self, Tox *m, int groupnum)
int i; int i;
for (i = max_groupchat_index; i > 0; --i) { for (i = max_groupchat_index; i > 0; --i) {
if (groupchats[i-1].active) if (groupchats[i - 1].active)
break; break;
} }
@ -125,21 +125,21 @@ static void print_groupchat_help(ToxWindow *self)
uint8_t *msg = "Group chat commands:"; uint8_t *msg = "Group chat commands:";
line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN); 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] = { uint8_t lines[NUMLINES][MAX_STR_SIZE] = {
{ " /add <id> <msg> : Add friend with optional message" }, { " /add <id> <msg> : Add friend with optional message" },
{ " /status <type> <msg>: Set your status with optional note" }, { " /status <type> <msg>: Set your status with optional note" },
{ " /note <msg> : Set a personal note" }, { " /note <msg> : Set a personal note" },
{ " /nick <nick> : Set your nickname" }, { " /nick <nick> : Set your nickname" },
{ " /groupchat : Create a group chat" }, { " /groupchat : Create a group chat" },
{ " /log <on> or <off> : Enable/disable logging" }, { " /log <on> or <off> : Enable/disable logging" },
{ " /close : Close the current group chat" }, { " /close : Close the current group chat" },
{ " /help : Print this message again" }, { " /help : Print this message again" },
{ " /help global : Show a list of global commands" }, { " /help global : Show a list of global commands" },
}; };
int i; 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'}; uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
int n_len = tox_group_peername(m, groupnum, peernum, nick); 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'; nick[n_len] = '\0';
/* check if message contains own name and alert appropriately */ /* 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'}; uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
n_len = tox_group_peername(m, groupnum, peernum, nick); 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'; nick[n_len] = '\0';
uint8_t timefrmt[TIME_STR_SIZE]; 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); memset(groupchats[gnum].peer_name_lengths, 0, sizeof(uint16_t) * npeers);
if (groupchats[gnum].peer_names == NULL || groupchats[gnum].oldpeer_names == NULL 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(); endwin();
fprintf(stderr, "malloc() failed. Aborting...\n"); fprintf(stderr, "malloc() failed. Aborting...\n");
exit(EXIT_FAILURE); 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) { for (i = 0; i < npeers; ++i) {
if (string_is_empty(peerlist[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; groupchats[gnum].peer_name_lengths[i] = unknown_len;
} else { } 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]; 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; groupchats[gnum].peer_name_lengths[i] = n_len;
} }
} }
memcpy(groupchats[gnum].oldpeer_names, groupchats[gnum].peer_names, N*npeers); memcpy(groupchats[gnum].oldpeer_names, groupchats[gnum].peer_names, N * npeers);
memcpy(groupchats[gnum].oldpeer_name_lengths, groupchats[gnum].peer_name_lengths, memcpy(groupchats[gnum].oldpeer_name_lengths, groupchats[gnum].peer_name_lengths,
sizeof(uint16_t) * npeers); sizeof(uint16_t) * npeers);
} }
static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnum, int peernum, static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnum, int peernum,
uint8_t change) uint8_t change)
{ {
if (self->num != groupnum) if (self->num != groupnum)
return; return;
@ -301,7 +301,7 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
uint8_t oldpeername[TOX_MAX_NAME_LENGTH]; uint8_t oldpeername[TOX_MAX_NAME_LENGTH];
if (change != TOX_CHAT_CHANGE_PEER_ADD) { 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)); sizeof(oldpeername));
uint16_t old_n_len = groupchats[groupnum].oldpeer_name_lengths[peernum]; uint16_t old_n_len = groupchats[groupnum].oldpeer_name_lengths[peernum];
oldpeername[old_n_len] = '\0'; 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) { if (change != TOX_CHAT_CHANGE_PEER_DEL) {
uint16_t n_len = groupchats[groupnum].peer_name_lengths[peernum]; 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'; peername[n_len] = '\0';
} }
@ -331,36 +331,37 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
get_time_str(timefrmt); get_time_str(timefrmt);
switch (change) { switch (change) {
case TOX_CHAT_CHANGE_PEER_ADD: case TOX_CHAT_CHANGE_PEER_ADD:
event = "has joined the room"; event = "has joined the room";
line_info_add(self, timefrmt, peername, NULL, event, CONNECTION, 0, GREEN); line_info_add(self, timefrmt, peername, NULL, event, CONNECTION, 0, GREEN);
write_to_log(event, peername, ctx->log, true); write_to_log(event, peername, ctx->log, true);
break; break;
case TOX_CHAT_CHANGE_PEER_DEL: case TOX_CHAT_CHANGE_PEER_DEL:
event = "has left the room"; event = "has left the room";
line_info_add(self, timefrmt, oldpeername, NULL, event, CONNECTION, 0, 0); line_info_add(self, timefrmt, oldpeername, NULL, event, CONNECTION, 0, 0);
if (groupchats[self->num].side_pos > 0) if (groupchats[self->num].side_pos > 0)
--groupchats[self->num].side_pos; --groupchats[self->num].side_pos;
write_to_log(event, oldpeername, ctx->log, true); write_to_log(event, oldpeername, ctx->log, true);
break; break;
case TOX_CHAT_CHANGE_PEER_NAME: case TOX_CHAT_CHANGE_PEER_NAME:
event = " is now known as "; event = " is now known as ";
line_info_add(self, timefrmt, oldpeername, peername, event, NAME_CHANGE, 0, 0); line_info_add(self, timefrmt, oldpeername, peername, event, NAME_CHANGE, 0, 0);
uint8_t tmp_event[TOXIC_MAX_NAME_LENGTH * 2 + 32]; uint8_t tmp_event[TOXIC_MAX_NAME_LENGTH * 2 + 32];
snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", peername); snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", peername);
write_to_log(tmp_event, oldpeername, ctx->log, true); write_to_log(tmp_event, oldpeername, ctx->log, true);
break; break;
} }
alert_window(self, WINDOW_ALERT_2, false); 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) { if (action == NULL) {
wprintw(ctx->history, "Invalid syntax.\n"); wprintw(ctx->history, "Invalid syntax.\n");
return; return;
@ -393,11 +394,11 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
} }
if (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); add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key);
if (x == x2-1) if (x == x2 - 1)
wmove(self->window, y+1, 0); wmove(self->window, y + 1, 0);
else else
wmove(self->window, y, x + MAX(1, wcwidth(key))); 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); del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
if (x == 0) if (x == 0)
wmove(self->window, y-1, x2 - cur_len); wmove(self->window, y - 1, x2 - cur_len);
else else
wmove(self->window, y, x - cur_len); wmove(self->window, y, x - cur_len);
} else { } 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 */ 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) { if (ctx->pos != ctx->len) {
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])); cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
if (x == 0) if (x == 0)
wmove(self->window, y-1, x2 - cur_len); wmove(self->window, y - 1, x2 - cur_len);
else else
wmove(self->window, y, x - cur_len); wmove(self->window, y, x - cur_len);
} else { } 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])); cur_len = MAX(1, wcwidth(ctx->line[ctx->pos]));
++ctx->pos; ++ctx->pos;
if (x == x2-1) if (x == x2 - 1)
wmove(self->window, y+1, 0); wmove(self->window, y + 1, 0);
else else
wmove(self->window, y, x + cur_len); wmove(self->window, y, x + cur_len);
} else { } else {
@ -500,7 +501,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr)
int diff; int diff;
if ((ctx->line[0] != '/') || (ctx->line[1] == 'm' && ctx->line[2] == 'e')) 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); groupchats[self->num].num_peers, TOX_MAX_NAME_LENGTH);
else else
diff = complete_line(ctx->line, &ctx->pos, &ctx->len, glob_cmd_list, AC_NUM_GLOB_COMMANDS, 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 (diff != -1) {
if (x + diff > x2 - 1) { if (x + diff > x2 - 1) {
int ofst = (x + diff - 1) - (x2 - 1); int ofst = (x + diff - 1) - (x2 - 1);
wmove(self->window, y+1, ofst); wmove(self->window, y + 1, ofst);
} else { } else {
wmove(self->window, y, x+diff); wmove(self->window, y, x + diff);
} }
} else { } else {
beep(); beep();
@ -606,8 +607,8 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
wclear(ctx->sidebar); wclear(ctx->sidebar);
mvwhline(ctx->linewin, 0, 0, ACS_HLINE, x2); mvwhline(ctx->linewin, 0, 0, ACS_HLINE, x2);
mvwvline(ctx->sidebar, 0, 0, ACS_VLINE, y2-CHATBOX_HEIGHT); mvwvline(ctx->sidebar, 0, 0, ACS_VLINE, y2 - CHATBOX_HEIGHT);
mvwaddch(ctx->sidebar, y2-CHATBOX_HEIGHT, 0, ACS_BTEE); mvwaddch(ctx->sidebar, y2 - CHATBOX_HEIGHT, 0, ACS_BTEE);
int num_peers = groupchats[self->num].num_peers; 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); wattroff(ctx->sidebar, A_BOLD);
mvwaddch(ctx->sidebar, 1, 0, ACS_LTEE); 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 N = TOX_MAX_NAME_LENGTH;
int maxlines = y2 - SDBAR_OFST - CHATBOX_HEIGHT; int maxlines = y2 - SDBAR_OFST - CHATBOX_HEIGHT;
int i; int i;
for (i = 0; i < num_peers && i < maxlines; ++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; int peer = i + groupchats[self->num].side_pos;
/* truncate nick to fit in side panel without modifying list */ /* truncate nick to fit in side panel without modifying list */
uint8_t tmpnck[TOX_MAX_NAME_LENGTH]; uint8_t tmpnck[TOX_MAX_NAME_LENGTH];
memcpy(tmpnck, &groupchats[self->num].peer_names[peer*N], SIDEBAR_WIDTH-2); memcpy(tmpnck, &groupchats[self->num].peer_names[peer * N], SIDEBAR_WIDTH - 2);
tmpnck[SIDEBAR_WIDTH-2] = '\0'; tmpnck[SIDEBAR_WIDTH - 2] = '\0';
wprintw(ctx->sidebar, "%s\n", tmpnck); wprintw(ctx->sidebar, "%s\n", tmpnck);
} }
@ -643,9 +644,9 @@ static void groupchat_onInit(ToxWindow *self, Tox *m)
ChatContext *ctx = self->chatwin; ChatContext *ctx = self->chatwin;
ctx->history = subwin(self->window, y-CHATBOX_HEIGHT+1, x-SIDEBAR_WIDTH-1, 0, 0); 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->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->sidebar = subwin(self->window, y - CHATBOX_HEIGHT + 1, SIDEBAR_WIDTH, 0, x - SIDEBAR_WIDTH);
ctx->hst = malloc(sizeof(struct history)); ctx->hst = malloc(sizeof(struct history));
ctx->log = malloc(sizeof(struct chatlog)); 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); 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) ToxWindow new_group_chat(Tox *m, int groupnum)

View File

@ -107,7 +107,7 @@ static void line_info_root_fwd(struct history *hst)
hst->line_root = tmp; 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) uint8_t type, uint8_t bold, uint8_t colour)
{ {
struct history *hst = self->chatwin->hst; 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 */ /* for type-specific formatting in print function */
switch (type) { switch (type) {
case ACTION: case ACTION:
len += 3; len += 3;
break; break;
default:
len += 2; default:
break; len += 2;
break;
} }
if (msg) { if (msg) {
memcpy(new_line->msg, msg, sizeof(new_line->msg)); memcpy(new_line->msg, msg, sizeof(new_line->msg));
len += strlen(msg); len += strlen(msg);
} if (tmstmp) { }
if (tmstmp) {
memcpy(new_line->timestamp, tmstmp, sizeof(new_line->timestamp)); memcpy(new_line->timestamp, tmstmp, sizeof(new_line->timestamp));
len += strlen(tmstmp); len += strlen(tmstmp);
} if (name1) { }
if (name1) {
memcpy(new_line->name1, name1, sizeof(new_line->name1)); memcpy(new_line->name1, name1, sizeof(new_line->name1));
len += strlen(name1); len += strlen(name1);
} if (name2) { }
if (name2) {
memcpy(new_line->name2, name2, sizeof(new_line->name2)); memcpy(new_line->name2, name2, sizeof(new_line->name2));
len += strlen(name2); len += strlen(name2);
} }
@ -223,112 +230,114 @@ void line_info_print(ToxWindow *self)
int offst = self->is_groupchat ? SIDEBAR_WIDTH : 0; int offst = self->is_groupchat ? SIDEBAR_WIDTH : 0;
int numlines = 0; int numlines = 0;
while(line && numlines++ <= y2) { while (line && numlines++ <= y2) {
uint8_t type = line->type; uint8_t type = line->type;
switch (type) { switch (type) {
case OUT_MSG: case OUT_MSG:
case IN_MSG: case IN_MSG:
wattron(win, COLOR_PAIR(BLUE)); wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp); wprintw(win, "%s", line->timestamp);
wattroff(win, COLOR_PAIR(BLUE)); wattroff(win, COLOR_PAIR(BLUE));
int nameclr = GREEN; int nameclr = GREEN;
if (line->colour) if (line->colour)
nameclr = line->colour; nameclr = line->colour;
else if (type == IN_MSG) else if (type == IN_MSG)
nameclr = CYAN; nameclr = CYAN;
wattron(win, COLOR_PAIR(nameclr)); wattron(win, COLOR_PAIR(nameclr));
wprintw(win, "%s: ", line->name1); wprintw(win, "%s: ", line->name1);
wattroff(win, COLOR_PAIR(nameclr)); wattroff(win, COLOR_PAIR(nameclr));
if (line->msg[0] == '>') if (line->msg[0] == '>')
wattron(win, COLOR_PAIR(GREEN)); wattron(win, COLOR_PAIR(GREEN));
wprintw(win, "%s\n", line->msg); wprintw(win, "%s\n", line->msg);
if (line->msg[0] == '>') if (line->msg[0] == '>')
wattroff(win, COLOR_PAIR(GREEN)); wattroff(win, COLOR_PAIR(GREEN));
break; break;
case ACTION: case ACTION:
wattron(win, COLOR_PAIR(BLUE)); wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp); wprintw(win, "%s", line->timestamp);
wattroff(win, COLOR_PAIR(BLUE)); wattroff(win, COLOR_PAIR(BLUE));
wattron(win, COLOR_PAIR(YELLOW)); wattron(win, COLOR_PAIR(YELLOW));
wprintw(win, "* %s %s\n", line->name1, line->msg); wprintw(win, "* %s %s\n", line->name1, line->msg);
wattroff(win, COLOR_PAIR(YELLOW)); wattroff(win, COLOR_PAIR(YELLOW));
break; break;
case SYS_MSG: case SYS_MSG:
if (line->timestamp[0]) { 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)); wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s", line->timestamp); wprintw(win, "%s", line->timestamp);
wattroff(win, COLOR_PAIR(BLUE)); wattroff(win, COLOR_PAIR(BLUE));
}
if (line->bold)
wattron(win, A_BOLD);
if (line->colour)
wattron(win, COLOR_PAIR(line->colour)); wattron(win, COLOR_PAIR(line->colour));
wattron(win, A_BOLD);
wprintw(win, "%s\n", line->msg); wprintw(win, "* %s ", line->name1);
if (line->bold)
wattroff(win, A_BOLD); wattroff(win, A_BOLD);
if (line->colour) wprintw(win, "%s\n", line->msg);
wattroff(win, COLOR_PAIR(line->colour)); wattroff(win, COLOR_PAIR(line->colour));
break; break;
case PROMPT: case NAME_CHANGE:
wattron(win, COLOR_PAIR(GREEN)); wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "$ "); wprintw(win, "%s", line->timestamp);
wattroff(win, COLOR_PAIR(GREEN)); 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, "%s", line->msg);
wprintw(win, "\n"); wattron(win, A_BOLD);
break; wprintw(win, "%s\n", line->name2);
wattroff(win, A_BOLD);
wattroff(win, COLOR_PAIR(MAGENTA));
case CONNECTION: break;
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;
} }
line = line->next; line = line->next;
@ -395,24 +404,29 @@ void line_info_onKey(ToxWindow *self, wint_t key)
struct history *hst = self->chatwin->hst; struct history *hst = self->chatwin->hst;
switch (key) { switch (key) {
case KEY_PPAGE: case KEY_PPAGE:
line_info_page_up(self, hst); line_info_page_up(self, hst);
break; break;
case KEY_NPAGE:
line_info_page_down(self, hst); case KEY_NPAGE:
break; line_info_page_down(self, hst);
case KEY_UP: break;
line_info_scroll_up(hst);
break; case KEY_UP:
case KEY_DOWN: line_info_scroll_up(hst);
line_info_scroll_down(hst); break;
break;
case KEY_HOME: case KEY_DOWN:
line_info_goto_root(hst); line_info_scroll_down(hst);
break; break;
case KEY_END:
line_info_reset_start(hst); case KEY_HOME:
break; 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"); mvwprintw(ctx->linewin, 1, 0, "Scroll mode:\n");
wattroff(ctx->linewin, A_BOLD | COLOR_PAIR(BLUE)); 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" 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) void line_info_clear(struct history *hst)

View File

@ -57,12 +57,12 @@ struct history {
bool scroll_mode; bool scroll_mode;
/* keeps track of lines added between window refreshes */ /* keeps track of lines added between window refreshes */
uint32_t queue; uint32_t queue;
uint32_t queue_lns; uint32_t queue_lns;
}; };
/* adds a line to history (also moves line_start and/or line_root forward if necessary) */ /* 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); uint8_t type, uint8_t bold, uint8_t colour);
/* Prints a section of history starting at line_start */ /* Prints a section of history starting at line_start */

View File

@ -46,7 +46,7 @@ void init_logging_session(uint8_t *name, uint8_t *key, struct chatlog *log)
name = UNKNOWN_NAME; name = UNKNOWN_NAME;
char *user_config_dir = get_user_config_dir(); 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 */ /* use first 4 digits of key as log ident. If no key use a timestamp */
uint8_t ident[32]; 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[0], "%02X", key[0] & 0xff);
sprintf(&ident[2], "%02X", key[1] & 0xff); sprintf(&ident[2], "%02X", key[1] & 0xff);
ident[KEY_IDENT_DIGITS*2+1] = '\0'; ident[KEY_IDENT_DIGITS * 2 + 1] = '\0';
} else { } else {
strftime(ident, sizeof(ident), "%Y-%m-%d[%H:%M:%S]", get_time()); strftime(ident, sizeof(ident), "%Y-%m-%d[%H:%M:%S]", get_time());
path_len += strlen(ident) + 1; 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]; 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); user_config_dir, CONFIGDIR, name, ident);
free(user_config_dir); 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]"; 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]; uint8_t s[MAX_STR_SIZE];
strftime(s, MAX_STR_SIZE, t, get_time()); 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(); uint64_t curtime = get_unix_time();

View File

@ -25,7 +25,7 @@
#endif #endif
#ifndef SIGWINCH #ifndef SIGWINCH
#define SIGWINCH 28 #define SIGWINCH 28
#endif #endif
#include <curses.h> #include <curses.h>
@ -41,9 +41,9 @@
#include <pthread.h> #include <pthread.h>
#ifdef _WIN32 #ifdef _WIN32
#include <direct.h> #include <direct.h>
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#else #else
#include <netdb.h> #include <netdb.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -64,7 +64,7 @@
#include "settings.h" #include "settings.h"
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
#include "audio_call.h" #include "audio_call.h"
#endif /* _SUPPORT_AUDIO */ #endif /* _SUPPORT_AUDIO */
#ifndef PACKAGE_DATADIR #ifndef PACKAGE_DATADIR
@ -72,7 +72,7 @@
#endif #endif
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
ToxAv* av; ToxAv *av;
#endif /* _SUPPORT_AUDIO */ #endif /* _SUPPORT_AUDIO */
/* Export for use in Callbacks */ /* Export for use in Callbacks */
@ -95,11 +95,13 @@ static void init_term(void)
/* Setup terminal */ /* Setup terminal */
signal(SIGWINCH, on_window_resize); signal(SIGWINCH, on_window_resize);
#if HAVE_WIDECHAR #if HAVE_WIDECHAR
if (setlocale(LC_ALL, "") == NULL) { if (setlocale(LC_ALL, "") == NULL) {
fprintf(stderr, "Could not set your locale, plese check your locale settings or" 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); exit(EXIT_FAILURE);
} }
#endif #endif
initscr(); initscr();
cbreak(); cbreak();
@ -112,7 +114,7 @@ static void init_term(void)
start_color(); start_color();
if (user_settings->colour_theme == NATIVE_COLS) { if (user_settings->colour_theme == NATIVE_COLS) {
if (assume_default_colors(-1,-1) == OK) if (assume_default_colors(-1, -1) == OK)
bg_color = -1; bg_color = -1;
} }
@ -136,7 +138,7 @@ static Tox *init_tox(int ipv4)
int ipv6 = !ipv4; int ipv6 = !ipv4;
Tox *m = tox_new(ipv6); Tox *m = tox_new(ipv6);
/* /*
* TOX_ENABLE_IPV6_DEFAULT is always 1. * TOX_ENABLE_IPV6_DEFAULT is always 1.
* Checking it is redundant, this *should* be doing ipv4 fallback * Checking it is redundant, this *should* be doing ipv4 fallback
*/ */
@ -199,11 +201,13 @@ static int nodelist_load(char *filename)
return 1; return 1;
char line[MAXLINE]; char line[MAXLINE];
while (fgets(line, sizeof(line), fp) && linecnt < MAXNODES) { while (fgets(line, sizeof(line), fp) && linecnt < MAXNODES) {
if (strlen(line) > MINLINE) { if (strlen(line) > MINLINE) {
char *name = strtok(line, " "); char *name = strtok(line, " ");
char *port = strtok(NULL, " "); char *port = strtok(NULL, " ");
char *key_ascii = strtok(NULL, " "); char *key_ascii = strtok(NULL, " ");
/* invalid line */ /* invalid line */
if (name == NULL || port == NULL || key_ascii == NULL) if (name == NULL || port == NULL || key_ascii == NULL)
continue; continue;
@ -232,7 +236,7 @@ static int nodelist_load(char *filename)
int init_connection_helper(Tox *m, int line) int init_connection_helper(Tox *m, int line)
{ {
return tox_bootstrap_from_address(m, nodes[line], TOX_ENABLE_IPV6_DEFAULT, 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 /* Connects to a random DHT node listed in the DHTnodes file
@ -267,7 +271,7 @@ int init_connection(Tox *m)
int i; int i;
int n = MIN(NUM_INIT_NODES, linecnt); 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)) if (init_connection_helper(m, rand() % linecnt))
res = 0; res = 0;
} }
@ -425,9 +429,9 @@ void exit_toxic(Tox *m)
free(prompt->chatwin); free(prompt->chatwin);
free(user_settings); free(user_settings);
tox_kill(m); tox_kill(m);
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
terminate_audio(); terminate_audio();
#endif /* _SUPPORT_AUDIO */ #endif /* _SUPPORT_AUDIO */
endwin(); endwin();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
@ -484,15 +488,17 @@ int main(int argc, char *argv[])
} }
config_err = create_user_config_dir(user_config_dir); config_err = create_user_config_dir(user_config_dir);
if (DATA_FILE == NULL ) { if (DATA_FILE == NULL ) {
if (config_err) { if (config_err) {
DATA_FILE = strdup("data"); DATA_FILE = strdup("data");
} else { } else {
DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1);
if (DATA_FILE != NULL) { if (DATA_FILE != NULL) {
strcpy(DATA_FILE, user_config_dir); strcpy(DATA_FILE, user_config_dir);
strcat(DATA_FILE, CONFIGDIR); strcat(DATA_FILE, CONFIGDIR);
strcat(DATA_FILE, "data"); strcat(DATA_FILE, "data");
} else { } else {
endwin(); endwin();
fprintf(stderr, "malloc() failed. Aborting...\n"); 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); line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
} }
if (settings_err == -1) { if (settings_err == -1) {
msg = "Failed to load user settings"; msg = "Failed to load user settings";
line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0); line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
} }
sort_friendlist_index(); sort_friendlist_index();
prompt_init_statusbar(prompt, m); prompt_init_statusbar(prompt, m);
@ -585,6 +591,6 @@ int main(int argc, char *argv[])
do_toxic(m, prompt); do_toxic(m, prompt);
usleep(10000); usleep(10000);
} }
return 0; return 0;
} }

View File

@ -98,7 +98,7 @@ int mbs_to_wcs_buf(wchar_t *buf, const uint8_t *string, size_t n)
if (n < len) if (n < len)
return -1; return -1;
if ((len = mbstowcs(buf, string, n)) == (size_t) -1) if ((len = mbstowcs(buf, string, n)) == (size_t) - 1)
return -1; return -1;
return len; return len;
@ -113,7 +113,7 @@ int wcs_to_mbs_buf(uint8_t *buf, const wchar_t *string, size_t n)
if (n < len) if (n < len)
return -1; return -1;
if ((len = wcstombs(buf, string, n)) == (size_t) -1) if ((len = wcstombs(buf, string, n)) == (size_t) - 1)
return -1; return -1;
return len; return len;
@ -125,11 +125,11 @@ uint8_t *wcs_to_mbs(wchar_t *string)
uint8_t *ret = NULL; uint8_t *ret = NULL;
size_t len = wcstombs(NULL, string, 0); size_t len = wcstombs(NULL, string, 0);
if (len != (size_t) -1) { if (len != (size_t) - 1) {
ret = malloc(++len); ret = malloc(++len);
if (ret != NULL) { if (ret != NULL) {
if (wcstombs(ret, string, len) == (size_t) -1) if (wcstombs(ret, string, len) == (size_t) - 1)
return NULL; return NULL;
} }
} else { } 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) void alert_window(ToxWindow *self, int type, bool is_beep)
{ {
switch (type) { switch (type) {
case WINDOW_ALERT_0: case WINDOW_ALERT_0:
self->alert0 = true; self->alert0 = true;
break; break;
case WINDOW_ALERT_1:
self->alert1 = true; case WINDOW_ALERT_1:
break; self->alert1 = true;
case WINDOW_ALERT_2: break;
self->alert2 = true;
break; case WINDOW_ALERT_2:
self->alert2 = true;
break;
} }
StatusBar *stb = prompt->stb; StatusBar *stb = prompt->stb;
@ -212,8 +214,9 @@ int valid_nick(uint8_t *nick)
int i; int i;
for (i = 0; nick[i]; ++i) { for (i = 0; nick[i]; ++i) {
if (nick[i] == ' ' && nick[i+1] == ' ') if (nick[i] == ' ' && nick[i + 1] == ' ')
return 0; return 0;
if (nick[i] == '/') if (nick[i] == '/')
return 0; 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_y = (len / max_x) + (max_y - CURS_Y_OFFSET);
int end_x = len % max_x; 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 */ /* 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; int idx = strlen(pathname) - 1;
while (idx >= 0 && pathname[idx] == '/') while (idx >= 0 && pathname[idx] == '/')
pathname[idx--] = '\0'; pathname[idx--] = '\0';
uint8_t *filename = strrchr(pathname, '/'); /* Try unix style paths */ uint8_t *filename = strrchr(pathname, '/'); /* Try unix style paths */
if (filename != NULL) { if (filename != NULL) {
if (!strlen(++filename)) if (!strlen(++filename))
filename = pathname; filename = pathname;

View File

@ -60,12 +60,12 @@ const uint8_t glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/note" }, { "/note" },
{ "/quit" }, { "/quit" },
{ "/status" }, { "/status" },
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
{ "/lsdev" }, { "/lsdev" },
{ "/sdev" }, { "/sdev" },
#endif /* _SUPPORT_AUDIO */ #endif /* _SUPPORT_AUDIO */
}; };
@ -99,7 +99,7 @@ void prompt_update_connectionstatus(ToxWindow *prompt, bool is_connected)
statusbar->is_online = 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. */ Returns request number on success, -1 if queue is full or other error. */
static int add_friend_request(uint8_t *public_key) 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 (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); add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key);
} }
} else { /* if (!ltr) */ } 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 (key == 0x107 || key == 0x8 || key == 0x7f) {
if (ctx->pos > 0) { if (ctx->pos > 0) {
del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len); 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 { } else {
beep(); beep();
} }
@ -308,7 +308,7 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
--ctx->orig_y; --ctx->orig_y;
} else { /* Mark point of origin for new line */ } else { /* Mark point of origin for new line */
ctx->orig_y = y; ctx->orig_y = y;
} }
wattron(ctx->history, COLOR_PAIR(GREEN)); wattron(ctx->history, COLOR_PAIR(GREEN));
@ -325,23 +325,27 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
const uint8_t *status_text = "Unknown"; const uint8_t *status_text = "Unknown";
switch (statusbar->status) { switch (statusbar->status) {
case TOX_USERSTATUS_NONE: case TOX_USERSTATUS_NONE:
status_text = "Online"; status_text = "Online";
colour = GREEN; colour = GREEN;
break; break;
case TOX_USERSTATUS_AWAY:
status_text = "Away"; case TOX_USERSTATUS_AWAY:
colour = YELLOW; status_text = "Away";
break; colour = YELLOW;
case TOX_USERSTATUS_BUSY: break;
status_text = "Busy";
colour = RED; case TOX_USERSTATUS_BUSY:
break; status_text = "Busy";
case TOX_USERSTATUS_INVALID: colour = RED;
status_text = "ERROR"; break;
colour = MAGENTA;
break; case TOX_USERSTATUS_INVALID:
status_text = "ERROR";
colour = MAGENTA;
break;
} }
wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD); wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD);
wprintw(statusbar->topline, " [%s]", status_text); wprintw(statusbar->topline, " [%s]", status_text);
wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD); 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}; uint8_t nick[TOX_MAX_NAME_LENGTH] = {0};
int n_len = tox_get_name(m, friendnum, nick); 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]) { if (!nick[0]) {
snprintf(nick, sizeof(nick), "%s", UNKNOWN_NAME); 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) { 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); snprintf(statusmsg, MAX_STR_SIZE, "Toxing on Toxic v.%s", toxic_ver);
s_len = strlen(statusmsg); s_len = strlen(statusmsg);
statusmsg[s_len] = '\0'; 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); 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) ToxWindow new_prompt(void)

View File

@ -26,11 +26,11 @@
#define X_OFST 2 /* offset to account for prompt char */ #define X_OFST 2 /* offset to account for prompt char */
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
#define AC_NUM_GLOB_COMMANDS 17 #define AC_NUM_GLOB_COMMANDS 17
#else #else
#define AC_NUM_GLOB_COMMANDS 15 #define AC_NUM_GLOB_COMMANDS 15
#endif /* _SUPPORT_AUDIO */ #endif /* _SUPPORT_AUDIO */
ToxWindow new_prompt(void); ToxWindow new_prompt(void);
void prep_prompt_win(void); void prep_prompt_win(void);

View File

@ -38,8 +38,8 @@ static void uset_aout_dev(struct user_settings *s, int val);
struct { struct {
const char *name; const char *name;
void (*func)(struct user_settings *s, int val); void (*func)(struct user_settings *s, int val);
} user_settings_list[] = { } user_settings_list[] = {
{ "autolog", uset_autolog }, { "autolog", uset_autolog },
{ "time", uset_time }, { "time", uset_time },
{ "disable_alerts", uset_alerts }, { "disable_alerts", uset_alerts },
{ "colour_theme", uset_colours }, { "colour_theme", uset_colours },
@ -47,19 +47,19 @@ struct {
{ "audio_out_dev", uset_aout_dev }, { "audio_out_dev", uset_aout_dev },
}; };
static void uset_autolog(struct user_settings *s, int val) static void uset_autolog(struct user_settings *s, int val)
{ {
/* default off if invalid value */ /* default off if invalid value */
s->autolog = val == AUTOLOG_ON ? AUTOLOG_ON : AUTOLOG_OFF; 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 */ /* default to 24 hour time if invalid value */
s->time = val == TIME_12 ? TIME_12 : TIME_24; 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 */ /* alerts default on if invalid value */
s->alerts = val == ALERTS_DISABLED ? ALERTS_DISABLED : ALERTS_ENABLED; s->alerts = val == ALERTS_DISABLED ? ALERTS_DISABLED : ALERTS_ENABLED;

View File

@ -41,7 +41,7 @@ void add_char_to_buf(wchar_t *buf, size_t *pos, size_t *len, wint_t ch)
int i; int i;
for (i = *len; i >= *pos && i >= 0; --i) for (i = *len; i >= *pos && i >= 0; --i)
buf[i+1] = buf[i]; buf[i + 1] = buf[i];
buf[(*pos)++] = ch; buf[(*pos)++] = ch;
++(*len); ++(*len);
@ -56,8 +56,8 @@ void del_char_buf_bck(wchar_t *buf, size_t *pos, size_t *len)
int i; int i;
/* similar to add_char_to_buf but deletes a char */ /* similar to add_char_to_buf but deletes a char */
for (i = *pos-1; i <= *len; ++i) for (i = *pos - 1; i <= *len; ++i)
buf[i] = buf[i+1]; buf[i] = buf[i + 1];
--(*pos); --(*pos);
--(*len); --(*len);
@ -72,7 +72,7 @@ void del_char_buf_frnt(wchar_t *buf, size_t *pos, size_t *len)
int i; int i;
for (i = *pos; i < *len; ++i) for (i = *pos; i < *len; ++i)
buf[i] = buf[i+1]; buf[i] = buf[i + 1];
--(*len); --(*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; int n = MAX_LINE_HIST - HIST_PURGE;
for (i = 0; i < n; ++i) 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; *hst_tot = n;
} }
/* adds a line to the ln_history buffer at hst_pos and sets hst_pos to end of history. */ /* 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) int *hst_pos)
{ {
if (len > MAX_STR_SIZE) 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_tot);
*hst_pos = *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. /* 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. hst_pos is decremented or incremented depending on key_dir.
resets buffer if at end of history */ 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], 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) 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; *len = h_len;
} }
/* looks for the first instance in list that begins with the last entered word in buf according to pos, /* 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 then fills buf with the complete word. e.g. "Hello jo" would complete the buffer
with "Hello john". with "Hello john".
list is a pointer to the list of strings being compared, n_items is the number of items 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 */ 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) 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; const uint8_t *L = (uint8_t *) list;
uint8_t ubuf[MAX_STR_SIZE]; uint8_t ubuf[MAX_STR_SIZE];
/* work with multibyte string copy of buf for simplicity */ /* work with multibyte string copy of buf for simplicity */
if (wcs_to_mbs_buf(ubuf, buf, MAX_STR_SIZE) == -1) if (wcs_to_mbs_buf(ubuf, buf, MAX_STR_SIZE) == -1)
return -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); snprintf(tmp, sizeof(tmp), "%s", ubuf);
tmp[*pos] = '\0'; tmp[*pos] = '\0';
uint8_t *sub = strrchr(tmp, ' '); 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++) { if (!sub++) {
sub = tmp; sub = tmp;
if (sub[0] != '/') /* make sure it's not a command */ if (sub[0] != '/') /* make sure it's not a command */
n_endchrs = 2; 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 */ /* look for a match in list */
for (i = 0; i < n_items; ++i) { for (i = 0; i < n_items; ++i) {
match = &L[i*size]; match = &L[i * size];
if (is_match = strncasecmp(match, sub, s_len) == 0) if (is_match = strncasecmp(match, sub, s_len) == 0)
break; 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 ": ") */ /* put match in correct spot in buf and append endchars (space or ": ") */
const uint8_t *endchrs = n_endchrs == 1 ? " " : ": "; const uint8_t *endchrs = n_endchrs == 1 ? " " : ": ";
int m_len = strlen(match); 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; int diff = m_len - s_len + n_endchrs;
if (*len + diff > MAX_STR_SIZE) 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]; uint8_t tmpend[MAX_STR_SIZE];
strcpy(tmpend, &ubuf[*pos]); strcpy(tmpend, &ubuf[*pos]);
strcpy(&ubuf[strt], match); strcpy(&ubuf[strt], match);
strcpy(&ubuf[strt+m_len], endchrs); strcpy(&ubuf[strt + m_len], endchrs);
strcpy(&ubuf[strt+m_len+n_endchrs], tmpend); strcpy(&ubuf[strt + m_len + n_endchrs], tmpend);
/* convert to widechar and copy back to original buf */ /* convert to widechar and copy back to original buf */
wchar_t newbuf[MAX_STR_SIZE]; wchar_t newbuf[MAX_STR_SIZE];

View File

@ -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 */ /* nulls buf and sets pos and len to 0 */
void reset_buf(wchar_t *buf, size_t *pos, size_t *len); 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, /* 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 then fills buf with the complete word. e.g. "Hello jo" would complete the buffer
with "Hello john". with "Hello john".
list is a pointer to the list of strings being compared, n_items is the number of items 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 */ 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); 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. */ /* 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); int *hst_pos);
/* copies history item at hst_pos to buf. Sets pos and len to the len of the history item. /* copies history item at hst_pos to buf. Sets pos and len to the len of the history item.

View File

@ -35,7 +35,7 @@
#include <tox/tox.h> #include <tox/tox.h>
#ifdef _SUPPORT_AUDIO #ifdef _SUPPORT_AUDIO
#include <tox/toxav.h> #include <tox/toxav.h>
#endif /* _SUPPORT_AUDIO */ #endif /* _SUPPORT_AUDIO */
#define UNKNOWN_NAME "Anonymous" #define UNKNOWN_NAME "Anonymous"
@ -112,7 +112,7 @@ struct ToxWindow {
void(*onGroupMessage)(ToxWindow *, Tox *, int, int, uint8_t *, uint16_t); void(*onGroupMessage)(ToxWindow *, Tox *, int, int, uint8_t *, uint16_t);
void(*onGroupAction)(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(*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(*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(*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); 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_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_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_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_sendrequest(Tox *m, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, uint8_t *pathname,
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); 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_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); void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata);

View File

@ -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) uint8_t *filename, uint16_t filename_length, void *userdata)
{ {
int i; 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) uint8_t control_type, uint8_t *data, uint16_t length, void *userdata)
{ {
int i; int i;
@ -236,6 +236,7 @@ int add_window(Tox *m, ToxWindow w)
if (w.window == NULL) if (w.window == NULL)
return -1; return -1;
#ifdef URXVT_FIX #ifdef URXVT_FIX
/* Fixes text color problem on some terminals. */ /* Fixes text color problem on some terminals. */
wbkgd(w.window, COLOR_PAIR(6)); wbkgd(w.window, COLOR_PAIR(6));
@ -405,6 +406,7 @@ void draw_active_window(Tox *m)
ltr = iswprint(ch); ltr = iswprint(ch);
else /* if (status == KEY_CODE_YES) */ else /* if (status == KEY_CODE_YES) */
ltr = false; ltr = false;
#else #else
ch = getch(); ch = getch();