mirror of
				https://github.com/Tha14/toxic.git
				synced 2025-11-04 14:46:52 +01:00 
			
		
		
		
	Merge branch 'master' of https://github.com/JFreegman/toxic
This commit is contained in:
		@@ -29,7 +29,9 @@ toxic_SOURCES = $(top_srcdir)/src/main.c \
 | 
			
		||||
                $(top_srcdir)/src/log.c \
 | 
			
		||||
                $(top_srcdir)/src/log.h \
 | 
			
		||||
                $(top_srcdir)/src/file_senders.c \
 | 
			
		||||
                $(top_srcdir)/src/file_senders.h
 | 
			
		||||
                $(top_srcdir)/src/file_senders.h \
 | 
			
		||||
                $(top_srcdir)/src/line_info.c \
 | 
			
		||||
                $(top_srcdir)/src/line_info.h
 | 
			
		||||
 | 
			
		||||
toxic_CFLAGS =                 -I$(top_srcdir) \
 | 
			
		||||
				$(NCURSES_CFLAGS) \
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
# Process this file with autoconf to produce a configure script.
 | 
			
		||||
 | 
			
		||||
AC_PREREQ([2.65])
 | 
			
		||||
AC_INIT([toxic], [0.3.1], [https://tox.im/])
 | 
			
		||||
AC_INIT([toxic], [0.3.2], [https://tox.im/])
 | 
			
		||||
AC_CONFIG_AUX_DIR(configure_aux)
 | 
			
		||||
AC_CONFIG_SRCDIR([src/main.c])
 | 
			
		||||
AC_CONFIG_HEADERS([config.h])
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										135
									
								
								src/audio_call.c
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								src/audio_call.c
									
									
									
									
									
								
							@@ -11,6 +11,7 @@
 | 
			
		||||
#include "chat_commands.h"
 | 
			
		||||
#include "global_commands.h"
 | 
			
		||||
#include "toxic_windows.h"
 | 
			
		||||
#include "line_info.h"
 | 
			
		||||
 | 
			
		||||
#include <curses.h>
 | 
			
		||||
#include <AL/al.h>
 | 
			
		||||
@@ -51,7 +52,6 @@ struct _ASettings {
 | 
			
		||||
    int ttas; /* Transmission thread active status (0 - stopped, 1- running) */
 | 
			
		||||
} ASettins;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void callback_recv_invite ( void *arg );
 | 
			
		||||
void callback_recv_ringing ( void *arg );
 | 
			
		||||
void callback_recv_starting ( void *arg );
 | 
			
		||||
@@ -65,16 +65,24 @@ void callback_requ_timeout ( void *arg );
 | 
			
		||||
void callback_peer_timeout ( void* arg );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void print_err (ToxWindow *self, uint8_t *error_str)
 | 
			
		||||
{
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, error_str, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Opens device under current index
 | 
			
		||||
 */
 | 
			
		||||
int device_open (WINDOW *window, _Devices type)
 | 
			
		||||
int device_open (ToxWindow *self, _Devices type)
 | 
			
		||||
{
 | 
			
		||||
    WINDOW *window = self->chatwin->history;
 | 
			
		||||
 | 
			
		||||
    /* Do not error if no device */
 | 
			
		||||
    if ( !ASettins.device[type].size ) return 0;
 | 
			
		||||
    
 | 
			
		||||
    ALCdevice* prev_device = ASettins.device[type].dhndl;
 | 
			
		||||
    
 | 
			
		||||
    const char* error = NULL;
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
    uint8_t* error = NULL;
 | 
			
		||||
    
 | 
			
		||||
    if ( type == input ) {
 | 
			
		||||
        ASettins.device[type].dhndl = alcCaptureOpenDevice(
 | 
			
		||||
@@ -101,7 +109,10 @@ int device_open (WINDOW *window, _Devices type)
 | 
			
		||||
            if ( prev_device )
 | 
			
		||||
                alcCaptureCloseDevice(prev_device);
 | 
			
		||||
            
 | 
			
		||||
            if ( window ) wprintw(window, "Input device: %s\n", ASettins.device[type].devices[ASettins.device[type].index]);
 | 
			
		||||
            if ( window ) {
 | 
			
		||||
                snprintf(msg, sizeof(msg), "Input device: %s", ASettins.device[type].devices[ASettins.device[type].index]);
 | 
			
		||||
                line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        ASettins.device[type].ctx = NULL;
 | 
			
		||||
@@ -136,20 +147,27 @@ int device_open (WINDOW *window, _Devices type)
 | 
			
		||||
            
 | 
			
		||||
            ASettins.device[type].ctx = alcCreateContext(ASettins.device[type].dhndl, NULL);
 | 
			
		||||
            
 | 
			
		||||
            if ( window ) wprintw(window, "Output device: %s\n", ASettins.device[type].devices[ASettins.device[type].index]);
 | 
			
		||||
            if ( window ) {
 | 
			
		||||
                snprintf(msg, sizeof(msg), "Output device: %s", ASettins.device[type].devices[ASettins.device[type].index]);
 | 
			
		||||
                line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if ( error ) {
 | 
			
		||||
        if ( window ) wprintw(window, "Error: %s\n", error);
 | 
			
		||||
        if ( window ) {
 | 
			
		||||
            snprintf(msg, sizeof(msg), "Error: %s", error);
 | 
			
		||||
            line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    else return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int device_close (WINDOW *window, _Devices type)
 | 
			
		||||
int device_close (ToxWindow *self, _Devices type)
 | 
			
		||||
{
 | 
			
		||||
    const char* device = NULL;
 | 
			
		||||
    uint8_t* device = NULL;
 | 
			
		||||
    
 | 
			
		||||
    if ( ASettins.device[type].dhndl ) {
 | 
			
		||||
        if (type == input) {
 | 
			
		||||
@@ -169,11 +187,14 @@ int device_close (WINDOW *window, _Devices type)
 | 
			
		||||
        ASettins.device[type].index = ASettins.device[type].dix;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if ( window && device ) wprintw(window, "Closed %s device\n", device);
 | 
			
		||||
    if ( self && device ) {
 | 
			
		||||
        uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
        snprintf(msg, sizeof(msg), "Closed %s device", device);
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ToxAv* init_audio(ToxWindow* window, Tox* tox)
 | 
			
		||||
ToxAv* init_audio(ToxWindow* self, Tox* tox)
 | 
			
		||||
{
 | 
			
		||||
    ASettins.errors = NoError;
 | 
			
		||||
    ASettins.ttas = 0; /* Not running */
 | 
			
		||||
@@ -214,7 +235,8 @@ ToxAv* init_audio(ToxWindow* window, Tox* tox)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (!ASettins.device[input].size && !ASettins.device[output].size) {
 | 
			
		||||
        wprintw(window->window, "No devices: disabling audio!\n");
 | 
			
		||||
        uint8_t *msg = "No devices: disabling audio!";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        ASettins.av = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
@@ -226,19 +248,19 @@ ToxAv* init_audio(ToxWindow* window, Tox* tox)
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }    
 | 
			
		||||
        
 | 
			
		||||
        toxav_register_callstate_callback(callback_call_started, av_OnStart, window);
 | 
			
		||||
        toxav_register_callstate_callback(callback_call_canceled, av_OnCancel, window);
 | 
			
		||||
        toxav_register_callstate_callback(callback_call_rejected, av_OnReject, window);
 | 
			
		||||
        toxav_register_callstate_callback(callback_call_ended, av_OnEnd, window);
 | 
			
		||||
        toxav_register_callstate_callback(callback_recv_invite, av_OnInvite, window);
 | 
			
		||||
        toxav_register_callstate_callback(callback_call_started, av_OnStart, self);
 | 
			
		||||
        toxav_register_callstate_callback(callback_call_canceled, av_OnCancel, self);
 | 
			
		||||
        toxav_register_callstate_callback(callback_call_rejected, av_OnReject, self);
 | 
			
		||||
        toxav_register_callstate_callback(callback_call_ended, av_OnEnd, self);
 | 
			
		||||
        toxav_register_callstate_callback(callback_recv_invite, av_OnInvite, self);
 | 
			
		||||
        
 | 
			
		||||
        toxav_register_callstate_callback(callback_recv_ringing, av_OnRinging, window);
 | 
			
		||||
        toxav_register_callstate_callback(callback_recv_starting, av_OnStarting, window);
 | 
			
		||||
        toxav_register_callstate_callback(callback_recv_ending, av_OnEnding, window);
 | 
			
		||||
        toxav_register_callstate_callback(callback_recv_ringing, av_OnRinging, self);
 | 
			
		||||
        toxav_register_callstate_callback(callback_recv_starting, av_OnStarting, self);
 | 
			
		||||
        toxav_register_callstate_callback(callback_recv_ending, av_OnEnding, self);
 | 
			
		||||
        
 | 
			
		||||
        toxav_register_callstate_callback(callback_recv_error, av_OnError, window);
 | 
			
		||||
        toxav_register_callstate_callback(callback_requ_timeout, av_OnRequestTimeout, window);
 | 
			
		||||
        toxav_register_callstate_callback(callback_peer_timeout, av_OnPeerTimeout, window);
 | 
			
		||||
        toxav_register_callstate_callback(callback_recv_error, av_OnError, self);
 | 
			
		||||
        toxav_register_callstate_callback(callback_requ_timeout, av_OnRequestTimeout, self);
 | 
			
		||||
        toxav_register_callstate_callback(callback_peer_timeout, av_OnPeerTimeout, self);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return ASettins.av;
 | 
			
		||||
@@ -252,7 +274,6 @@ void terminate_audio()
 | 
			
		||||
        toxav_kill(ASettins.av);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int errors()
 | 
			
		||||
{
 | 
			
		||||
    return ASettins.errors;
 | 
			
		||||
@@ -372,7 +393,7 @@ cleanup:
 | 
			
		||||
    _cbend;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int start_transmission()
 | 
			
		||||
int start_transmission(ToxWindow *self)
 | 
			
		||||
{
 | 
			
		||||
    if ( !ASettins.av ) return -1;
 | 
			
		||||
    
 | 
			
		||||
@@ -381,9 +402,9 @@ int start_transmission()
 | 
			
		||||
        return -1;
 | 
			
		||||
    
 | 
			
		||||
    /* Now open our devices */
 | 
			
		||||
    if ( -1 == device_open(NULL, input) )
 | 
			
		||||
    if ( -1 == device_open(self, input) )
 | 
			
		||||
        return -1;
 | 
			
		||||
    if ( -1 == device_open(NULL, output))
 | 
			
		||||
    if ( -1 == device_open(self, output))
 | 
			
		||||
        return -1;
 | 
			
		||||
    
 | 
			
		||||
    /* Don't provide support for video */
 | 
			
		||||
@@ -479,7 +500,8 @@ void callback_peer_timeout ( void* arg )
 | 
			
		||||
 */
 | 
			
		||||
void cmd_call(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    const char* error_str;
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
    uint8_t* error_str;
 | 
			
		||||
    
 | 
			
		||||
    if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; }
 | 
			
		||||
    
 | 
			
		||||
@@ -493,17 +515,19 @@ void cmd_call(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
 | 
			
		||||
        
 | 
			
		||||
        goto on_error;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    wprintw(window, "Calling...\n");
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    error_str = "Calling...";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, error_str, SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
on_error: 
 | 
			
		||||
    wprintw(window, "%s\n", error_str);
 | 
			
		||||
on_error:
 | 
			
		||||
    snprintf(msg, sizeof(msg), "%s", error_str);
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_answer(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    const char* error_str;
 | 
			
		||||
    uint8_t* error_str;
 | 
			
		||||
    
 | 
			
		||||
    if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; }
 | 
			
		||||
    
 | 
			
		||||
@@ -523,12 +547,12 @@ void cmd_answer(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
 | 
			
		||||
    
 | 
			
		||||
    return;
 | 
			
		||||
on_error: 
 | 
			
		||||
    wprintw(window, "%s\n", error_str);
 | 
			
		||||
    print_err (self, error_str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_reject(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    const char* error_str;
 | 
			
		||||
    uint8_t* error_str;
 | 
			
		||||
    
 | 
			
		||||
    if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; }
 | 
			
		||||
    
 | 
			
		||||
@@ -548,12 +572,12 @@ void cmd_reject(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
 | 
			
		||||
    
 | 
			
		||||
    return;
 | 
			
		||||
on_error: 
 | 
			
		||||
    wprintw(window, "%s\n", error_str);
 | 
			
		||||
    print_err (self, error_str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_hangup(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    const char* error_str;
 | 
			
		||||
    uint8_t* error_str;
 | 
			
		||||
    
 | 
			
		||||
    if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; }
 | 
			
		||||
    
 | 
			
		||||
@@ -571,12 +595,12 @@ void cmd_hangup(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
 | 
			
		||||
        
 | 
			
		||||
    return;
 | 
			
		||||
on_error: 
 | 
			
		||||
    wprintw(window, "%s\n", error_str);
 | 
			
		||||
    print_err (self, error_str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_cancel(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    const char* error_str;
 | 
			
		||||
    uint8_t* error_str;
 | 
			
		||||
    
 | 
			
		||||
    if (argc != 0) { error_str = "Invalid syntax!"; goto on_error; }
 | 
			
		||||
    
 | 
			
		||||
@@ -595,13 +619,14 @@ void cmd_cancel(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
 | 
			
		||||
    
 | 
			
		||||
    return;
 | 
			
		||||
on_error: 
 | 
			
		||||
    wprintw(window, "%s\n", error_str);
 | 
			
		||||
    print_err (self, error_str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void cmd_list_devices(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    const char* error_str;
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
    uint8_t* error_str;
 | 
			
		||||
    
 | 
			
		||||
    if ( argc != 1 ) {
 | 
			
		||||
        if ( argc < 1 ) error_str = "Type must be specified!";        
 | 
			
		||||
@@ -619,22 +644,26 @@ void cmd_list_devices(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*
 | 
			
		||||
        type = output;
 | 
			
		||||
    
 | 
			
		||||
    else {
 | 
			
		||||
        wprintw(window, "Invalid type: %s\n", argv[1]);
 | 
			
		||||
        snprintf(msg, sizeof(msg), "Invalid type: %s", argv[1]);
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    int i = 0;
 | 
			
		||||
    for ( ; i < ASettins.device[type].size; i ++) 
 | 
			
		||||
        wprintw(window, "%d: %s\n", i, ASettins.device[type].devices[i]);
 | 
			
		||||
    
 | 
			
		||||
    for ( ; i < ASettins.device[type].size; i ++) {
 | 
			
		||||
        snprintf(msg, sizeof(msg), "%d: %s", i, ASettins.device[type].devices[i]);
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
on_error: 
 | 
			
		||||
    wprintw(window, "%s\n", error_str); 
 | 
			
		||||
    print_err (self, error_str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_change_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    const char* error_str;
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
    uint8_t* error_str;
 | 
			
		||||
    
 | 
			
		||||
    if ( argc != 2 ) {
 | 
			
		||||
        if ( argc < 1 ) error_str = "Type must be specified!";
 | 
			
		||||
@@ -658,7 +687,8 @@ void cmd_change_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (
 | 
			
		||||
        type = output;
 | 
			
		||||
    
 | 
			
		||||
    else {
 | 
			
		||||
        wprintw(window, "Invalid type: %s\n", argv[1]);
 | 
			
		||||
        snprintf(msg, sizeof(msg), "Invalid type: %s", argv[1]);
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
@@ -677,9 +707,10 @@ void cmd_change_device(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ASettins.device[type].index = selection;
 | 
			
		||||
    wprintw(window, "Selected: %s\n", ASettins.device[type].devices[selection]); 
 | 
			
		||||
    snprintf(msg, sizeof(msg), "Selected: %s", ASettins.device[type].devices[selection]);
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
    
 | 
			
		||||
    return;
 | 
			
		||||
on_error: 
 | 
			
		||||
    wprintw(window, "%s\n", error_str); 
 | 
			
		||||
}
 | 
			
		||||
    print_err (self, error_str);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,11 +20,11 @@ typedef enum _AudioError
 | 
			
		||||
/* You will have to pass pointer to first member of 'windows' 
 | 
			
		||||
 * declared in windows.c otherwise undefined behaviour will 
 | 
			
		||||
 */
 | 
			
		||||
ToxAv* init_audio(ToxWindow* window, Tox* tox);
 | 
			
		||||
ToxAv* init_audio(ToxWindow* self, Tox* tox);
 | 
			
		||||
void terminate_audio();
 | 
			
		||||
 | 
			
		||||
int errors();
 | 
			
		||||
 | 
			
		||||
int start_transmission();
 | 
			
		||||
int start_transmission(ToxWindow *self);
 | 
			
		||||
 | 
			
		||||
#endif /* _audio_h */
 | 
			
		||||
							
								
								
									
										252
									
								
								src/chat.c
									
									
									
									
									
								
							
							
						
						
									
										252
									
								
								src/chat.c
									
									
									
									
									
								
							@@ -34,6 +34,7 @@
 | 
			
		||||
#include "friendlist.h"
 | 
			
		||||
#include "toxic_strings.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "line_info.h"
 | 
			
		||||
 | 
			
		||||
#ifdef _SUPPORT_AUDIO
 | 
			
		||||
    #include "audio_call.h"
 | 
			
		||||
@@ -99,6 +100,7 @@ void kill_chat_window(ToxWindow *self)
 | 
			
		||||
    StatusBar *statusbar = self->stb;
 | 
			
		||||
 | 
			
		||||
    log_disable(ctx->log);
 | 
			
		||||
    line_info_cleanup(ctx->hst);
 | 
			
		||||
 | 
			
		||||
    int f_num = self->num;
 | 
			
		||||
    delwin(ctx->linewin);
 | 
			
		||||
@@ -107,6 +109,7 @@ void kill_chat_window(ToxWindow *self)
 | 
			
		||||
    disable_chatwin(f_num);
 | 
			
		||||
 | 
			
		||||
    free(ctx->log);
 | 
			
		||||
    free(ctx->hst);
 | 
			
		||||
    free(ctx);
 | 
			
		||||
    free(statusbar);
 | 
			
		||||
}
 | 
			
		||||
@@ -122,17 +125,10 @@ static void chat_onMessage(ToxWindow *self, Tox *m, int32_t num, uint8_t *msg, u
 | 
			
		||||
    tox_get_name(m, num, nick);
 | 
			
		||||
    nick[TOXIC_MAX_NAME_LENGTH] = '\0';
 | 
			
		||||
 | 
			
		||||
    print_time(ctx->history);
 | 
			
		||||
    wattron(ctx->history, COLOR_PAIR(CYAN));
 | 
			
		||||
    wprintw(ctx->history, "%s: ", nick);
 | 
			
		||||
    wattroff(ctx->history, COLOR_PAIR(CYAN));
 | 
			
		||||
    uint8_t timefrmt[TIME_STR_SIZE];
 | 
			
		||||
    get_time_str(timefrmt);
 | 
			
		||||
 | 
			
		||||
    if (msg[0] == '>') {
 | 
			
		||||
        wattron(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
        wprintw(ctx->history, "%s\n", msg);
 | 
			
		||||
        wattroff(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
    } else
 | 
			
		||||
        wprintw(ctx->history, "%s\n", msg);
 | 
			
		||||
    line_info_add(self, timefrmt, nick, NULL, msg, IN_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
    write_to_log(msg, nick, ctx->log, false);
 | 
			
		||||
    alert_window(self, WINDOW_ALERT_1, true);
 | 
			
		||||
@@ -173,11 +169,10 @@ static void chat_onAction(ToxWindow *self, Tox *m, int32_t num, uint8_t *action,
 | 
			
		||||
    tox_get_name(m, num, nick);
 | 
			
		||||
    nick[TOXIC_MAX_NAME_LENGTH] = '\0';
 | 
			
		||||
 | 
			
		||||
    print_time(ctx->history);
 | 
			
		||||
    wattron(ctx->history, COLOR_PAIR(YELLOW));
 | 
			
		||||
    wprintw(ctx->history, "* %s %s\n", nick, action);
 | 
			
		||||
    wattroff(ctx->history, COLOR_PAIR(YELLOW));
 | 
			
		||||
    uint8_t timefrmt[TIME_STR_SIZE];
 | 
			
		||||
    get_time_str(timefrmt);
 | 
			
		||||
 | 
			
		||||
    line_info_add(self, timefrmt, nick, NULL, action, ACTION, 0, 0);
 | 
			
		||||
    write_to_log(action, nick, ctx->log, true);
 | 
			
		||||
    alert_window(self, WINDOW_ALERT_1, true);
 | 
			
		||||
}
 | 
			
		||||
@@ -217,16 +212,19 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
 | 
			
		||||
    if (self->num != num)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
    uint8_t *errmsg;
 | 
			
		||||
 | 
			
		||||
    uint8_t filename[MAX_STR_SIZE];
 | 
			
		||||
    get_file_name(pathname, filename);
 | 
			
		||||
 | 
			
		||||
    wprintw(ctx->history, "File transfer request for '%s' (%llu bytes).\n", filename, 
 | 
			
		||||
            (long long unsigned int)filesize);
 | 
			
		||||
    snprintf(msg, sizeof(msg), "File transfer request for '%s' (%llu bytes).", filename, 
 | 
			
		||||
                                                       (long long unsigned int)filesize);
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
    if (filenum >= MAX_FILES) {
 | 
			
		||||
        wprintw(ctx->history, "Too many pending file requests; discarding.\n");
 | 
			
		||||
        errmsg = "Too many pending file requests; discarding.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -243,12 +241,14 @@ static void chat_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, uint8_t
 | 
			
		||||
        filename[len + strlen(d)] = '\0';
 | 
			
		||||
 | 
			
		||||
        if (count > 999) {
 | 
			
		||||
            wprintw(ctx->history, "Error saving file to disk.\n");
 | 
			
		||||
            errmsg = "Error saving file to disk.";
 | 
			
		||||
            line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wprintw(ctx->history, "Type '/savefile %d' to accept the file transfer.\n", filenum);
 | 
			
		||||
    snprintf(msg, sizeof(msg), "Type '/savefile %d' to accept the file transfer.", filenum);
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
    friends[num].file_receiver.pending[filenum] = true;
 | 
			
		||||
    strcpy(friends[num].file_receiver.filenames[filenum], filename);
 | 
			
		||||
@@ -271,8 +271,8 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
 | 
			
		||||
    if (self->num != num)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    const uint8_t *filename;
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE] = {0};
 | 
			
		||||
 | 
			
		||||
    if (receive_send == 0)
 | 
			
		||||
        filename = friends[num].file_receiver.filenames[filenum];
 | 
			
		||||
@@ -281,25 +281,23 @@ static void chat_onFileControl(ToxWindow *self, Tox *m, int32_t num, uint8_t rec
 | 
			
		||||
 | 
			
		||||
    switch (control_type) {
 | 
			
		||||
    case TOX_FILECONTROL_ACCEPT:
 | 
			
		||||
        wprintw(ctx->history, "File transfer for '%s' accepted.\n", filename);
 | 
			
		||||
        snprintf(msg, sizeof(msg), "File transfer for '%s' accepted.", filename);
 | 
			
		||||
        break;
 | 
			
		||||
    /*case TOX_FILECONTROL_PAUSE:
 | 
			
		||||
        wprintw(ctx->history, "File transfer for '%s' paused.\n", filename);
 | 
			
		||||
        break; */
 | 
			
		||||
    case TOX_FILECONTROL_KILL:
 | 
			
		||||
        wprintw(ctx->history, "File transfer for '%s' failed.\n", filename);
 | 
			
		||||
 | 
			
		||||
        snprintf(msg, sizeof(msg), "File transfer for '%s' failed.", filename);
 | 
			
		||||
        if (receive_send == 0)
 | 
			
		||||
            chat_close_file_receiver(num, filenum);
 | 
			
		||||
        else
 | 
			
		||||
            chat_close_file_receiver(num, filenum);
 | 
			
		||||
        break;
 | 
			
		||||
    case TOX_FILECONTROL_FINISHED:
 | 
			
		||||
        wprintw(ctx->history, "File transfer for '%s' complete.\n", filename);
 | 
			
		||||
        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);
 | 
			
		||||
    alert_window(self, WINDOW_ALERT_2, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -309,12 +307,9 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu
 | 
			
		||||
    if (self->num != num)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
 | 
			
		||||
    if (fwrite(data, length, 1, friends[num].file_receiver.files[filenum]) != 1) {
 | 
			
		||||
        wattron(ctx->history, COLOR_PAIR(RED));
 | 
			
		||||
        wprintw(ctx->history, "* Error writing to file.\n");
 | 
			
		||||
        wattroff(ctx->history, COLOR_PAIR(RED));
 | 
			
		||||
        uint8_t *msg = " * Error writing to file.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
 | 
			
		||||
 | 
			
		||||
        tox_file_send_control(m, num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0);
 | 
			
		||||
        chat_close_file_receiver(num, filenum);
 | 
			
		||||
@@ -326,16 +321,17 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, ui
 | 
			
		||||
    if (self->num != friendnumber)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    uint8_t name[TOX_MAX_NAME_LENGTH] = {'\0'};
 | 
			
		||||
    uint8_t name[TOX_MAX_NAME_LENGTH];
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
 | 
			
		||||
    if (tox_get_name(m, friendnumber, name) == -1)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    wprintw(ctx->history, "%s has invited you to a group chat.\n", name);
 | 
			
		||||
    snprintf(msg, sizeof(msg), "%s has invited you to a group chat.\n"
 | 
			
		||||
                               "Type \"/join\" to join the chat.", name);
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
    memcpy(friends[friendnumber].pending_groupchat, group_pub_key, TOX_CLIENT_ID_SIZE);
 | 
			
		||||
    wprintw(ctx->history, "Type \"/join\" to join the chat.\n");
 | 
			
		||||
    alert_window(self, WINDOW_ALERT_2, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -346,144 +342,140 @@ void chat_onInvite (ToxWindow *self, ToxAv *av)
 | 
			
		||||
{
 | 
			
		||||
    if (self->num != toxav_get_peer_id(av, 0))
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    
 | 
			
		||||
    wprintw(ctx->history, "Incoming audio call!\n"
 | 
			
		||||
                          "Answer: \"/answer\" \"/reject\"\n");
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg = "Incoming audio call!\nType: \"/answer\" or \"/reject\"";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
    
 | 
			
		||||
    alert_window(self, WINDOW_ALERT_0, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chat_onRinging (ToxWindow *self, ToxAv *av)
 | 
			
		||||
{
 | 
			
		||||
    if (self->num != toxav_get_peer_id(av, 0))
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    
 | 
			
		||||
    wprintw(ctx->history, "Ringing...\n"
 | 
			
		||||
                          "\"/cancel\" ?\n");
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg = "Ringing...\n\"cancel\" ?";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chat_onStarting (ToxWindow *self, ToxAv *av)
 | 
			
		||||
{
 | 
			
		||||
    if (self->num != toxav_get_peer_id(av, 0))
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    
 | 
			
		||||
    if ( 0 != start_transmission() ) {/* YEAH! */
 | 
			
		||||
        wprintw(ctx->history, "Error starting transmission!\n");
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg;
 | 
			
		||||
 | 
			
		||||
    if ( 0 != start_transmission(self) ) {/* YEAH! */
 | 
			
		||||
        msg = "Error starting transmission!";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    wprintw(ctx->history, "Call started! \n"
 | 
			
		||||
                          "Type: \"/hangup\" to end it.\n");
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    msg = "Call started!\nType: \"/hangup\" to end it.";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chat_onEnding (ToxWindow *self, ToxAv *av)
 | 
			
		||||
{
 | 
			
		||||
    if (self->num != toxav_get_peer_id(av, 0))
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg = "Call ended!";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
    toxav_kill_transmission(av);
 | 
			
		||||
    
 | 
			
		||||
    wprintw(ctx->history, "Call ended! \n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chat_onError (ToxWindow *self, ToxAv *av)
 | 
			
		||||
{
 | 
			
		||||
    if (self->num != toxav_get_peer_id(av, 0))
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    
 | 
			
		||||
    wprintw(ctx->history, "Error! \n");
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg = "Error!";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chat_onStart (ToxWindow *self, ToxAv *av)
 | 
			
		||||
{    
 | 
			
		||||
    if (self->num != toxav_get_peer_id(av, 0))
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    
 | 
			
		||||
    if ( 0 != start_transmission() ) {/* YEAH! */
 | 
			
		||||
        wprintw(ctx->history, "Error starting transmission!\n");
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg;
 | 
			
		||||
 | 
			
		||||
    if ( 0 != start_transmission(self) ) {/* YEAH! */
 | 
			
		||||
        msg = "Error starting transmission!";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    wprintw(ctx->history, "Call started! \n"
 | 
			
		||||
                          "Type: \"/hangup\" to end it.\n");
 | 
			
		||||
 | 
			
		||||
    msg = "Call started!\nType: \"/hangup\" to end it.";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chat_onCancel (ToxWindow *self, ToxAv *av)
 | 
			
		||||
{
 | 
			
		||||
    if (self->num != toxav_get_peer_id(av, 0))
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    
 | 
			
		||||
    wprintw(ctx->history, "Call canceled! \n");
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg = "Call canceled!";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chat_onReject (ToxWindow *self, ToxAv *av)
 | 
			
		||||
{
 | 
			
		||||
    if (self->num != toxav_get_peer_id(av, 0))
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    
 | 
			
		||||
    wprintw(ctx->history, "Rejected! \n");
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg = "Rejected!";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chat_onEnd (ToxWindow *self, ToxAv *av)
 | 
			
		||||
{
 | 
			
		||||
    if (self->num != toxav_get_peer_id(av, 0))
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    toxav_kill_transmission(av);
 | 
			
		||||
    
 | 
			
		||||
    wprintw(ctx->history, "Call ended! \n");
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg = "Call ended!";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chat_onRequestTimeout (ToxWindow *self, ToxAv *av)
 | 
			
		||||
{
 | 
			
		||||
    if (self->num != toxav_get_peer_id(av, 0))
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    
 | 
			
		||||
    wprintw(ctx->history, "No answer! \n");
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg = "No answer!";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void chat_onPeerTimeout (ToxWindow *self, ToxAv *av)
 | 
			
		||||
{
 | 
			
		||||
    if (self->num != toxav_get_peer_id(av, 0))
 | 
			
		||||
        return;
 | 
			
		||||
    
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    
 | 
			
		||||
    wprintw(ctx->history, "Peer disconnected; call ended! \n");
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg = "Peer disconnected; call ended!";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* _SUPPORT_AUDIO */
 | 
			
		||||
 | 
			
		||||
static void send_action(ToxWindow *self, ChatContext *ctx, Tox *m, uint8_t *action) {
 | 
			
		||||
    if (action == NULL) {
 | 
			
		||||
        wprintw(ctx->history, "Invalid syntax.\n");
 | 
			
		||||
    if (action == NULL)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t selfname[TOX_MAX_NAME_LENGTH];
 | 
			
		||||
    tox_get_self_name(m, selfname);
 | 
			
		||||
 | 
			
		||||
    print_time(ctx->history);
 | 
			
		||||
    wattron(ctx->history, COLOR_PAIR(YELLOW));
 | 
			
		||||
    wprintw(ctx->history, "* %s %s\n", selfname, action);
 | 
			
		||||
    wattroff(ctx->history, COLOR_PAIR(YELLOW));
 | 
			
		||||
    uint8_t timefrmt[TIME_STR_SIZE];
 | 
			
		||||
    get_time_str(timefrmt);
 | 
			
		||||
 | 
			
		||||
    line_info_add(self, timefrmt, selfname, NULL, action, ACTION, 0, 0);
 | 
			
		||||
 | 
			
		||||
    if (tox_send_action(m, self->num, action, strlen(action) + 1) == 0) {
 | 
			
		||||
        wattron(ctx->history, COLOR_PAIR(RED));
 | 
			
		||||
        wprintw(ctx->history, " * Failed to send action\n");
 | 
			
		||||
        wattroff(ctx->history, COLOR_PAIR(RED));
 | 
			
		||||
        uint8_t *errmsg = " * Failed to send action.";
 | 
			
		||||
        line_info_add(self, NULL, selfname, NULL, errmsg, SYS_MSG, 0, RED);
 | 
			
		||||
    } else {
 | 
			
		||||
        write_to_log(action, selfname, ctx->log, true);
 | 
			
		||||
    }
 | 
			
		||||
@@ -499,7 +491,18 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
    int cur_len = 0;
 | 
			
		||||
 | 
			
		||||
    if (key == 0x107 || key == 0x8 || key == 0x7f) {  /* BACKSPACE key: Remove character behind pos */
 | 
			
		||||
    if (key == T_KEY_ESC) {   /* ESC key: Toggle history scroll mode */
 | 
			
		||||
        bool scroll = ctx->hst->scroll_mode ? false : true;
 | 
			
		||||
        line_info_toggle_scroll(self, scroll);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* If we're in scroll mode ignore rest of function */
 | 
			
		||||
    if (ctx->hst->scroll_mode) {
 | 
			
		||||
        line_info_onKey(self, key);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (key == 0x107 || key == 0x8 || key == 0x7f) {  /* BACKSPACE key */
 | 
			
		||||
        if (ctx->pos > 0) {
 | 
			
		||||
            cur_len = MAX(1, wcwidth(ctx->line[ctx->pos - 1]));
 | 
			
		||||
            del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
 | 
			
		||||
@@ -580,13 +583,13 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
 | 
			
		||||
    else if (key == KEY_UP) {    /* fetches previous item in history */
 | 
			
		||||
        fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
 | 
			
		||||
                        &ctx->hst_pos, LN_HIST_MV_UP);
 | 
			
		||||
                        &ctx->hst_pos, MOVE_UP);
 | 
			
		||||
        mv_curs_end(self->window, ctx->len, y2, x2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (key == KEY_DOWN) {    /* fetches next item in history */
 | 
			
		||||
        fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
 | 
			
		||||
                        &ctx->hst_pos, LN_HIST_MV_DWN);
 | 
			
		||||
                        &ctx->hst_pos, MOVE_DOWN);
 | 
			
		||||
        mv_curs_end(self->window, ctx->len, y2, x2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -638,7 +641,6 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
 | 
			
		||||
        wclear(ctx->linewin);
 | 
			
		||||
        wmove(self->window, y2 - CURS_Y_OFFSET, 0);
 | 
			
		||||
        wclrtobot(self->window);
 | 
			
		||||
 | 
			
		||||
        if (!string_is_empty(line))
 | 
			
		||||
            add_line_to_hist(ctx->line, ctx->len, ctx->ln_history, &ctx->hst_tot, &ctx->hst_pos);
 | 
			
		||||
@@ -659,22 +661,14 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
            uint8_t selfname[TOX_MAX_NAME_LENGTH];
 | 
			
		||||
            tox_get_self_name(m, selfname);
 | 
			
		||||
 | 
			
		||||
            print_time(ctx->history);
 | 
			
		||||
            wattron(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
            wprintw(ctx->history, "%s: ", selfname);
 | 
			
		||||
            wattroff(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
            uint8_t timefrmt[TIME_STR_SIZE];
 | 
			
		||||
            get_time_str(timefrmt);
 | 
			
		||||
 | 
			
		||||
            if (line[0] == '>') {
 | 
			
		||||
                wattron(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
                wprintw(ctx->history, "%s\n", line);
 | 
			
		||||
                wattroff(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
            } else
 | 
			
		||||
                wprintw(ctx->history, "%s\n", line);
 | 
			
		||||
            line_info_add(self, timefrmt, selfname, NULL, line, OUT_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
            if (!statusbar->is_online || tox_send_message(m, self->num, line, strlen(line) + 1) == 0) {
 | 
			
		||||
                wattron(ctx->history, COLOR_PAIR(RED));
 | 
			
		||||
                wprintw(ctx->history, " * Failed to send message.\n");
 | 
			
		||||
                wattroff(ctx->history, COLOR_PAIR(RED));
 | 
			
		||||
                uint8_t *errmsg = " * Failed to send message.";
 | 
			
		||||
                line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
 | 
			
		||||
            } else {
 | 
			
		||||
                write_to_log(line, selfname, ctx->log, false);
 | 
			
		||||
            }
 | 
			
		||||
@@ -689,13 +683,16 @@ static void chat_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
 | 
			
		||||
static void chat_onDraw(ToxWindow *self, Tox *m)
 | 
			
		||||
{
 | 
			
		||||
    curs_set(1);
 | 
			
		||||
    int x2, y2;
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
 | 
			
		||||
    if (!ctx->hst->scroll_mode)
 | 
			
		||||
        curs_set(1);
 | 
			
		||||
 | 
			
		||||
    wclear(ctx->linewin);
 | 
			
		||||
    line_info_print(self);
 | 
			
		||||
 | 
			
		||||
    if (ctx->len > 0) {
 | 
			
		||||
        uint8_t line[MAX_STR_SIZE];
 | 
			
		||||
@@ -797,12 +794,14 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
 | 
			
		||||
 | 
			
		||||
static void chat_onInit(ToxWindow *self, Tox *m)
 | 
			
		||||
{
 | 
			
		||||
    curs_set(1);
 | 
			
		||||
    int x2, y2;
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
    self->x = x2;
 | 
			
		||||
 | 
			
		||||
    /* Init statusbar info */
 | 
			
		||||
    StatusBar *statusbar = self->stb;
 | 
			
		||||
 | 
			
		||||
    statusbar->status = tox_get_user_status(m, self->num);
 | 
			
		||||
    statusbar->is_online = tox_get_friend_connection_status(m, self->num) == 1;
 | 
			
		||||
 | 
			
		||||
@@ -813,25 +812,29 @@ static void chat_onInit(ToxWindow *self, Tox *m)
 | 
			
		||||
 | 
			
		||||
    /* Init subwindows */
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
 | 
			
		||||
    statusbar->topline = subwin(self->window, 2, x2, 0, 0);
 | 
			
		||||
    ctx->history = subwin(self->window, y2-CHATBOX_HEIGHT+1, x2, 0, 0);
 | 
			
		||||
    scrollok(ctx->history, 1);
 | 
			
		||||
    ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x2, y2-CHATBOX_HEIGHT, 0);
 | 
			
		||||
 | 
			
		||||
    ctx->hst = malloc(sizeof(struct history));
 | 
			
		||||
    ctx->log = malloc(sizeof(struct chatlog));
 | 
			
		||||
 | 
			
		||||
    if (ctx->log == NULL) {
 | 
			
		||||
    if (ctx->log == NULL || ctx->hst == NULL) {
 | 
			
		||||
        endwin();
 | 
			
		||||
        fprintf(stderr, "malloc() failed. Aborting...\n");
 | 
			
		||||
        exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(ctx->hst, 0, sizeof(struct history));
 | 
			
		||||
    memset(ctx->log, 0, sizeof(struct chatlog));
 | 
			
		||||
 | 
			
		||||
    line_info_init(ctx->hst);
 | 
			
		||||
 | 
			
		||||
    if (friends[self->num].logging_on)
 | 
			
		||||
        log_enable(self->name, friends[self->num].pub_key, ctx->log);
 | 
			
		||||
 | 
			
		||||
    wprintw(ctx->history, "\n\n");
 | 
			
		||||
    execute(ctx->history, self, m, "/help", CHAT_COMMAND_MODE);
 | 
			
		||||
    execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);
 | 
			
		||||
 | 
			
		||||
@@ -881,7 +884,10 @@ ToxWindow new_chat(Tox *m, int32_t friendnum)
 | 
			
		||||
    ret.name[TOXIC_MAX_NAME_LENGTH] = '\0';
 | 
			
		||||
 | 
			
		||||
    ChatContext *chatwin = calloc(1, sizeof(ChatContext));
 | 
			
		||||
    memset(chatwin, 0, sizeof(ChatContext));
 | 
			
		||||
 | 
			
		||||
    StatusBar *stb = calloc(1, sizeof(StatusBar));
 | 
			
		||||
    memset(stb, 0, sizeof(StatusBar));
 | 
			
		||||
 | 
			
		||||
    if (stb != NULL && chatwin != NULL) {
 | 
			
		||||
        ret.chatwin = chatwin;
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,7 @@
 | 
			
		||||
#include "misc_tools.h"
 | 
			
		||||
#include "friendlist.h"
 | 
			
		||||
#include "execute.h"
 | 
			
		||||
#include "line_info.h"
 | 
			
		||||
 | 
			
		||||
extern ToxWindow *prompt;
 | 
			
		||||
 | 
			
		||||
@@ -48,81 +49,101 @@ void cmd_chat_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wattron(window, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
    wprintw(window, "Chat commands:\n");
 | 
			
		||||
    wattroff(window, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
    uint8_t *msg = "Chat commands:";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
 | 
			
		||||
 | 
			
		||||
#ifdef _SUPPORT_AUDIO
 | 
			
		||||
    #define NUMLINES 13
 | 
			
		||||
#else
 | 
			
		||||
    #define NUMLINES 9
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    wprintw(window, "    /call                      : Audio call\n");
 | 
			
		||||
    wprintw(window, "    /cancel                    : Cancel call\n");
 | 
			
		||||
    wprintw(window, "    /answer                    : Answer incomming call\n");
 | 
			
		||||
    wprintw(window, "    /reject                    : Reject incomming call\n");
 | 
			
		||||
    wprintw(window, "    /hangup                    : Hangup active call\n");
 | 
			
		||||
    uint8_t lines[NUMLINES][MAX_STR_SIZE] = {
 | 
			
		||||
 | 
			
		||||
#ifdef _SUPPORT_AUDIO
 | 
			
		||||
    { "    /call                      : Audio call"                           },
 | 
			
		||||
    { "    /cancel                    : Cancel call"                          },
 | 
			
		||||
    { "    /answer                    : Answer incomming call"                },
 | 
			
		||||
    { "    /reject                    : Reject incoming call"                 },
 | 
			
		||||
    { "    /hangup                    : Hangup active call"                   },
 | 
			
		||||
#endif /* _SUPPORT_AUDIO */
 | 
			
		||||
    
 | 
			
		||||
    wprintw(window, "    /invite <n>                : Invite friend to a group chat\n");
 | 
			
		||||
    wprintw(window, "    /join                      : Join a pending group chat\n");
 | 
			
		||||
    wprintw(window, "    /log <on> or <off>         : Enable/disable logging\n");
 | 
			
		||||
    wprintw(window, "    /sendfile <filepath>       : Send a file\n");
 | 
			
		||||
    wprintw(window, "    /savefile <n>              : Receive a file\n");
 | 
			
		||||
    wprintw(window, "    /close                     : Close the current chat window\n");
 | 
			
		||||
    wprintw(window, "    /help                      : Print this message again\n");
 | 
			
		||||
    wprintw(window, "    /help global               : Show a list of global commands\n");
 | 
			
		||||
    
 | 
			
		||||
    wattron(window, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
    wprintw(window, " * Argument messages must be enclosed in quotation marks.\n\n");
 | 
			
		||||
    wattroff(window, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
    { "    /invite <n>                : Invite friend to a group chat"        },
 | 
			
		||||
    { "    /join                      : Join a pending group chat"            },
 | 
			
		||||
    { "    /log <on> or <off>         : Enable/disable logging"               },
 | 
			
		||||
    { "    /sendfile <filepath>       : Send a file"                          },
 | 
			
		||||
    { "    /savefile <n>              : Receive a file"                       },
 | 
			
		||||
    { "    /close                     : Close the current chat window"        },
 | 
			
		||||
    { "    /help                      : Print this message again"             },
 | 
			
		||||
    { "    /help global               : Show a list of global commands"       },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < NUMLINES; ++i)
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, lines[i], SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
    msg = " * Use ESC key to toggle history scroll mode\n";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *errmsg;
 | 
			
		||||
 | 
			
		||||
    if (argc < 1) {
 | 
			
		||||
      wprintw(window, "Invalid syntax.\n");
 | 
			
		||||
      return;
 | 
			
		||||
        errmsg = "Invalid syntax";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int groupnum = atoi(argv[1]);
 | 
			
		||||
 | 
			
		||||
    if (groupnum == 0 && strcmp(argv[1], "0")) {    /* atoi returns 0 value on invalid input */
 | 
			
		||||
        wprintw(window, "Invalid syntax.\n");
 | 
			
		||||
        errmsg = "Invalid syntax.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (tox_invite_friend(m, self->num, groupnum) == -1) {
 | 
			
		||||
        wprintw(window, "Failed to invite friend.\n");
 | 
			
		||||
        errmsg = "Failed to invite friend.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wprintw(window, "Invited friend to group chat %d.\n", groupnum);
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
    snprintf(msg, sizeof(msg), "Invited friend to Room #%d.", groupnum);
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *errmsg;
 | 
			
		||||
 | 
			
		||||
    if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
 | 
			
		||||
        wattron(window, COLOR_PAIR(RED));
 | 
			
		||||
        wprintw(window, " * Warning: Too many windows are open.\n");
 | 
			
		||||
        wattron(window, COLOR_PAIR(RED));
 | 
			
		||||
        errmsg = " * Warning: Too many windows are open.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t *groupkey = friends[self->num].pending_groupchat;
 | 
			
		||||
 | 
			
		||||
    if (groupkey[0] == '\0') {
 | 
			
		||||
        wprintw(window, "No pending group chat invite.\n");
 | 
			
		||||
        errmsg = "No pending group chat invite.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int groupnum = tox_join_groupchat(m, self->num, groupkey);
 | 
			
		||||
 | 
			
		||||
    if (groupnum == -1) {
 | 
			
		||||
        wprintw(window, "Group chat instance failed to initialize.\n");
 | 
			
		||||
        errmsg = "Group chat instance failed to initialize.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (init_groupchat_win(prompt, m, groupnum) == -1) {
 | 
			
		||||
        wprintw(window, "Group chat window failed to initialize.\n");
 | 
			
		||||
        errmsg = "Group chat window failed to initialize.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        tox_del_groupchat(m, groupnum);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
@@ -130,36 +151,43 @@ void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
 | 
			
		||||
 | 
			
		||||
void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *errmsg;
 | 
			
		||||
 | 
			
		||||
    if (argc != 1) {
 | 
			
		||||
      wprintw(window, "Invalid syntax.\n");
 | 
			
		||||
      errmsg = "Invalid syntax.";
 | 
			
		||||
      line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t filenum = atoi(argv[1]);
 | 
			
		||||
 | 
			
		||||
    if ((filenum == 0 && strcmp(argv[1], "0")) || filenum >= MAX_FILES) {
 | 
			
		||||
        wprintw(window, "No pending file transfers with that number.\n");
 | 
			
		||||
        errmsg = "No pending file transfers with that number.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!friends[self->num].file_receiver.pending[filenum]) {
 | 
			
		||||
        wprintw(window, "No pending file transfers with that number.\n");
 | 
			
		||||
        errmsg = "No pending file transfers with that number.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t *filename = friends[self->num].file_receiver.filenames[filenum];
 | 
			
		||||
 | 
			
		||||
    if (tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_ACCEPT, 0, 0) == 0) {
 | 
			
		||||
        wprintw(window, "Accepted file transfer %u. Saving file as: '%s'\n", filenum, filename);
 | 
			
		||||
        uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
        snprintf(msg, sizeof(msg), "Accepted file transfer %u. Saving file as: '%s'", filenum, filename);
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
        if ((friends[self->num].file_receiver.files[filenum] = fopen(filename, "a")) == NULL) {
 | 
			
		||||
            wattron(window, COLOR_PAIR(RED));
 | 
			
		||||
            wprintw(window, "* Error writing to file.\n");
 | 
			
		||||
            wattroff(window, COLOR_PAIR(RED));
 | 
			
		||||
            errmsg = "* Error writing to file.";
 | 
			
		||||
            line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
 | 
			
		||||
            tox_file_send_control(m, self->num, 1, filenum, TOX_FILECONTROL_KILL, 0, 0);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        wprintw(window, "File transfer failed.\n");
 | 
			
		||||
        errmsg = "File transfer failed.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    friends[self->num].file_receiver.pending[filenum] = false;
 | 
			
		||||
@@ -167,20 +195,25 @@ void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
 | 
			
		||||
 | 
			
		||||
void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *errmsg;
 | 
			
		||||
 | 
			
		||||
    if (max_file_senders_index >= (MAX_FILES-1)) {
 | 
			
		||||
        wprintw(window,"Please wait for some of your outgoing file transfers to complete.\n");
 | 
			
		||||
        errmsg = "Please wait for some of your outgoing file transfers to complete.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (argc < 1) {
 | 
			
		||||
      wprintw(window, "Invalid syntax.\n");
 | 
			
		||||
      errmsg = "Invalid syntax.";
 | 
			
		||||
      line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t *path = argv[1];
 | 
			
		||||
 | 
			
		||||
    if (path[0] != '\"') {
 | 
			
		||||
        wprintw(window, "File path must be enclosed in quotes.\n");
 | 
			
		||||
        errmsg = "File path must be enclosed in quotes.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -188,14 +221,16 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
 | 
			
		||||
    int path_len = strlen(path);
 | 
			
		||||
 | 
			
		||||
    if (path_len > MAX_STR_SIZE) {
 | 
			
		||||
        wprintw(window, "File path exceeds character limit.\n");
 | 
			
		||||
        errmsg = "File path exceeds character limit.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FILE *file_to_send = fopen(path, "r");
 | 
			
		||||
 | 
			
		||||
    if (file_to_send == NULL) {
 | 
			
		||||
        wprintw(window, "File '%s' not found.\n", path);
 | 
			
		||||
        errmsg = "File not found.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -208,7 +243,8 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
 | 
			
		||||
    int filenum = tox_new_file_sender(m, self->num, filesize, filename, strlen(filename) + 1);
 | 
			
		||||
 | 
			
		||||
    if (filenum == -1) {
 | 
			
		||||
        wprintw(window, "Error sending file.\n");
 | 
			
		||||
        errmsg = "Error sending file.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -226,7 +262,9 @@ void cmd_sendfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
 | 
			
		||||
            file_senders[i].piecelen = fread(file_senders[i].nextpiece, 1,
 | 
			
		||||
                                             tox_file_data_size(m, self->num), file_to_send);
 | 
			
		||||
 | 
			
		||||
            wprintw(window, "Sending file: '%s'\n", path);
 | 
			
		||||
            uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
            snprintf(msg, sizeof(msg), "Sending file: '%s'", path);
 | 
			
		||||
            line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
            if (i == max_file_senders_index)
 | 
			
		||||
                ++max_file_senders_index;
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@
 | 
			
		||||
#include "execute.h"
 | 
			
		||||
#include "chat_commands.h"
 | 
			
		||||
#include "global_commands.h"
 | 
			
		||||
#include "line_info.h"
 | 
			
		||||
 | 
			
		||||
struct cmd_func {
 | 
			
		||||
    const char *name;
 | 
			
		||||
@@ -77,7 +78,7 @@ static struct cmd_func chat_commands[] = {
 | 
			
		||||
 | 
			
		||||
/* Parses input command and puts args into arg array. 
 | 
			
		||||
   Returns number of arguments on success, -1 on failure. */
 | 
			
		||||
static int parse_command(WINDOW *w, char *cmd, char (*args)[MAX_STR_SIZE])
 | 
			
		||||
static int parse_command(WINDOW *w, ToxWindow *self, char *cmd, char (*args)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    int num_args = 0;
 | 
			
		||||
    bool cmd_end = false;    /* flags when we get to the end of cmd */
 | 
			
		||||
@@ -89,7 +90,8 @@ static int parse_command(WINDOW *w, char *cmd, char (*args)[MAX_STR_SIZE])
 | 
			
		||||
            end = strchr(cmd+1, '\"');
 | 
			
		||||
 | 
			
		||||
            if (end++ == NULL) {    /* Increment past the end quote */
 | 
			
		||||
                wprintw(w, "Invalid argument. Did you forget a closing \"?\n");
 | 
			
		||||
                uint8_t *errmsg = "Invalid argument. Did you forget a closing \"?";
 | 
			
		||||
                line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -132,7 +134,7 @@ void execute(WINDOW* w, ToxWindow *self, Tox *m, char *cmd, int mode)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    char args[MAX_NUM_ARGS][MAX_STR_SIZE] = {0};
 | 
			
		||||
    int num_args = parse_command(w, cmd, args);
 | 
			
		||||
    int num_args = parse_command(w, self, cmd, args);
 | 
			
		||||
 | 
			
		||||
    if (num_args == -1)
 | 
			
		||||
        return;
 | 
			
		||||
@@ -154,5 +156,6 @@ void execute(WINDOW* w, ToxWindow *self, Tox *m, char *cmd, int mode)
 | 
			
		||||
    if (do_command(w, self, m, num_args, GLOBAL_NUM_COMMANDS, global_commands, args) == 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    wprintw(w, "Invalid command.\n");
 | 
			
		||||
    uint8_t *errmsg = "Invalid command.";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
 | 
			
		||||
#ifdef _SUPPORT_AUDIO 
 | 
			
		||||
    #define GLOBAL_NUM_COMMANDS 16
 | 
			
		||||
    #define CHAT_NUM_COMMANDS 9
 | 
			
		||||
    #define CHAT_NUM_COMMANDS 10
 | 
			
		||||
#else 
 | 
			
		||||
    #define GLOBAL_NUM_COMMANDS 14
 | 
			
		||||
    #define CHAT_NUM_COMMANDS 5
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@
 | 
			
		||||
#include "chat.h"
 | 
			
		||||
#include "friendlist.h"
 | 
			
		||||
#include "misc_tools.h"
 | 
			
		||||
#include "line_info.h"
 | 
			
		||||
 | 
			
		||||
#ifdef _SUPPORT_AUDIO
 | 
			
		||||
#include "audio_call.h"
 | 
			
		||||
@@ -104,13 +105,14 @@ static void friendlist_onMessage(ToxWindow *self, Tox *m, int32_t num, uint8_t *
 | 
			
		||||
            uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
 | 
			
		||||
            tox_get_name(m, num, nick);
 | 
			
		||||
            nick[TOXIC_MAX_NAME_LENGTH] = '\0';
 | 
			
		||||
            wprintw(prompt->window, "%s: %s\n", nick, str);
 | 
			
		||||
 | 
			
		||||
            prep_prompt_win();
 | 
			
		||||
            wattron(prompt->window, COLOR_PAIR(RED));
 | 
			
		||||
            wprintw(prompt->window, "* Warning: Too many windows are open.\n");
 | 
			
		||||
            wattron(prompt->window, COLOR_PAIR(RED));
 | 
			
		||||
            uint8_t timefrmt[TIME_STR_SIZE];
 | 
			
		||||
            get_time_str(timefrmt);
 | 
			
		||||
 | 
			
		||||
            line_info_add(prompt, timefrmt, nick, NULL, str, IN_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
            uint8_t *msg = "* Warning: Too many windows are open.";
 | 
			
		||||
            line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
 | 
			
		||||
            alert_window(prompt, WINDOW_ALERT_1, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -121,7 +123,7 @@ static void friendlist_onConnectionChange(ToxWindow *self, Tox *m, int32_t num,
 | 
			
		||||
    if (num >= max_friends_index)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    friends[num].online = status == 1 ? true : false;
 | 
			
		||||
    friends[num].online = status;
 | 
			
		||||
    update_friend_last_online(num, get_unix_time());
 | 
			
		||||
    store_data(m, DATA_FILE);
 | 
			
		||||
    sort_friendlist_index();
 | 
			
		||||
@@ -211,10 +213,9 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u
 | 
			
		||||
            tox_get_name(m, num, nick);
 | 
			
		||||
            nick[TOXIC_MAX_NAME_LENGTH] = '\0';
 | 
			
		||||
 | 
			
		||||
            prep_prompt_win();
 | 
			
		||||
            wattron(prompt->window, COLOR_PAIR(RED));
 | 
			
		||||
            wprintw(prompt->window, "* File transfer from %s failed: too many windows are open.\n", nick);
 | 
			
		||||
            wattron(prompt->window, COLOR_PAIR(RED));
 | 
			
		||||
            uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
            snprintf(msg, sizeof(msg), "* File transfer from %s failed: too many windows are open.", nick);
 | 
			
		||||
            line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
 | 
			
		||||
 | 
			
		||||
            alert_window(prompt, WINDOW_ALERT_1, true);
 | 
			
		||||
        }
 | 
			
		||||
@@ -234,10 +235,9 @@ static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, uint8
 | 
			
		||||
            tox_get_name(m, num, nick);
 | 
			
		||||
            nick[TOXIC_MAX_NAME_LENGTH] = '\0';
 | 
			
		||||
 | 
			
		||||
            prep_prompt_win();
 | 
			
		||||
            wattron(prompt->window, COLOR_PAIR(RED));
 | 
			
		||||
            wprintw(prompt->window, "* Group chat invite from %s failed: too many windows are open.\n", nick);
 | 
			
		||||
            wattron(prompt->window, COLOR_PAIR(RED));
 | 
			
		||||
            uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
            snprintf(msg, sizeof(msg), "* Group chat invite from %s failed: too many windows are open.", nick);
 | 
			
		||||
            line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
 | 
			
		||||
 | 
			
		||||
            alert_window(prompt, WINDOW_ALERT_1, true);
 | 
			
		||||
        }
 | 
			
		||||
@@ -343,10 +343,8 @@ static void friendlist_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
            friends[f].chatwin = add_window(m, new_chat(m, friends[f].num));
 | 
			
		||||
            set_active_window(friends[f].chatwin);
 | 
			
		||||
        } else {
 | 
			
		||||
            prep_prompt_win();
 | 
			
		||||
            wattron(prompt->window, COLOR_PAIR(RED));
 | 
			
		||||
            wprintw(prompt->window, "* Warning: Too many windows are open.\n");
 | 
			
		||||
            wattron(prompt->window, COLOR_PAIR(RED));
 | 
			
		||||
            uint8_t *msg = "* Warning: Too many windows are open.";
 | 
			
		||||
            line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, RED);
 | 
			
		||||
 | 
			
		||||
            alert_window(prompt, WINDOW_ALERT_1, true);
 | 
			
		||||
        }
 | 
			
		||||
@@ -538,12 +536,13 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av)
 | 
			
		||||
            uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
 | 
			
		||||
            tox_get_name(m, id, nick);
 | 
			
		||||
            nick[TOXIC_MAX_NAME_LENGTH] = '\0';
 | 
			
		||||
            wprintw(prompt->window, "Audio action from: %s!\n", nick);
 | 
			
		||||
            
 | 
			
		||||
            prep_prompt_win();
 | 
			
		||||
            wattron(prompt->window, COLOR_PAIR(RED));
 | 
			
		||||
            wprintw(prompt->window, "* Warning: Too many windows are open.\n");
 | 
			
		||||
            wattron(prompt->window, COLOR_PAIR(RED));
 | 
			
		||||
 | 
			
		||||
            uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
            snprintf(msg, sizeof(msg), "Audio action from: %s!", nick);
 | 
			
		||||
            line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
            uint8_t *errmsg = "* Warning: Too many windows are open.";
 | 
			
		||||
            line_info_add(prompt, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
 | 
			
		||||
            
 | 
			
		||||
            alert_window(prompt, WINDOW_ALERT_0, true);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,8 @@
 | 
			
		||||
#include "toxic_windows.h"
 | 
			
		||||
#include "misc_tools.h"
 | 
			
		||||
#include "friendlist.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "line_info.h"
 | 
			
		||||
 | 
			
		||||
extern char *DATA_FILE;
 | 
			
		||||
extern ToxWindow *prompt;
 | 
			
		||||
@@ -42,30 +44,34 @@ extern uint8_t num_frnd_requests;
 | 
			
		||||
/* command functions */
 | 
			
		||||
void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    /* check arguments */
 | 
			
		||||
    uint8_t *msg;
 | 
			
		||||
 | 
			
		||||
    if (argc != 1) {
 | 
			
		||||
      wprintw(window, "Invalid syntax.\n");
 | 
			
		||||
      return;
 | 
			
		||||
        msg = "Invalid syntax.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int req = atoi(argv[1]);
 | 
			
		||||
 | 
			
		||||
    if ((req == 0 && strcmp(argv[1], "0"))|| req >= MAX_FRIENDS_NUM) {
 | 
			
		||||
        wprintw(window, "No pending friend request with that number.\n");
 | 
			
		||||
        msg = "No pending friend request with that number.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!strlen(pending_frnd_requests[req])) {
 | 
			
		||||
        wprintw(window, "No pending friend request with that number.\n");
 | 
			
		||||
        msg = "No pending friend request with that number.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int32_t friendnum = tox_add_friend_norequest(m, pending_frnd_requests[req]);
 | 
			
		||||
 | 
			
		||||
    if (friendnum == -1)
 | 
			
		||||
        wprintw(window, "Failed to add friend.\n");
 | 
			
		||||
        msg = "Failed to add friend.";
 | 
			
		||||
    else {
 | 
			
		||||
        wprintw(window, "Friend request accepted.\n");
 | 
			
		||||
        msg = "Friend request accepted.";
 | 
			
		||||
        on_friendadded(m, friendnum, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -79,12 +85,16 @@ void cmd_accept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    num_frnd_requests = i;
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *errmsg;
 | 
			
		||||
 | 
			
		||||
    if (argc < 1) {
 | 
			
		||||
        wprintw(window, "Invalid syntax.\n");
 | 
			
		||||
        errmsg = "Invalid syntax.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -95,7 +105,8 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
 | 
			
		||||
        uint8_t *temp = argv[2];
 | 
			
		||||
 | 
			
		||||
        if (temp[0] != '\"') {
 | 
			
		||||
            wprintw(window, "Message must be enclosed in quotes.\n");
 | 
			
		||||
            errmsg = "Message must be enclosed in quotes.";
 | 
			
		||||
            line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -108,7 +119,8 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (strlen(id) != 2 * TOX_FRIEND_ADDRESS_SIZE) {
 | 
			
		||||
        wprintw(window, "Invalid ID length.\n");
 | 
			
		||||
        errmsg = "Invalid ID length.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -123,7 +135,8 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
 | 
			
		||||
        xx[2] = '\0';
 | 
			
		||||
 | 
			
		||||
        if (sscanf(xx, "%02x", &x) != 1) {
 | 
			
		||||
            wprintw(window, "Invalid ID.\n");
 | 
			
		||||
            errmsg = "Invalid ID.";
 | 
			
		||||
            line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -138,44 +151,48 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
 | 
			
		||||
 | 
			
		||||
    switch (f_num) {
 | 
			
		||||
    case TOX_FAERR_TOOLONG:
 | 
			
		||||
        wprintw(window, "Message is too long.\n");
 | 
			
		||||
        errmsg = "Message is too long.";
 | 
			
		||||
        break;
 | 
			
		||||
    case TOX_FAERR_NOMESSAGE:
 | 
			
		||||
        wprintw(window, "Please add a message to your request.\n");
 | 
			
		||||
        errmsg = "Please add a message to your request.";
 | 
			
		||||
        break;
 | 
			
		||||
    case TOX_FAERR_OWNKEY:
 | 
			
		||||
        wprintw(window, "That appears to be your own ID.\n");
 | 
			
		||||
        errmsg = "That appears to be your own ID.";
 | 
			
		||||
        break;
 | 
			
		||||
    case TOX_FAERR_ALREADYSENT:
 | 
			
		||||
        wprintw(window, "Friend request has already been sent.\n");
 | 
			
		||||
        errmsg = "Friend request has already been sent.";
 | 
			
		||||
        break;
 | 
			
		||||
    case TOX_FAERR_UNKNOWN:
 | 
			
		||||
        wprintw(window, "Undefined error when adding friend.\n");
 | 
			
		||||
        errmsg = "Undefined error when adding friend.";
 | 
			
		||||
        break;
 | 
			
		||||
    case TOX_FAERR_BADCHECKSUM:
 | 
			
		||||
        wprintw(window, "Bad checksum in address.\n");
 | 
			
		||||
        errmsg = "Bad checksum in address.";
 | 
			
		||||
        break;
 | 
			
		||||
    case TOX_FAERR_SETNEWNOSPAM:
 | 
			
		||||
        wprintw(window, "Nospam was different (is this contact already added?)\n");
 | 
			
		||||
        errmsg = "Nospam was different (is this contact already added?";
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        wprintw(window, "Friend request sent.\n");
 | 
			
		||||
        errmsg = "Friend request sent.";
 | 
			
		||||
        on_friendadded(m, f_num, true);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_clear(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    wclear(window);
 | 
			
		||||
    wprintw(window, "\n\n");
 | 
			
		||||
    line_info_clear(self->chatwin->hst);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *errmsg;
 | 
			
		||||
 | 
			
		||||
    /* check arguments */
 | 
			
		||||
    if (argc != 3) {
 | 
			
		||||
      wprintw(window, "Invalid syntax.\n");
 | 
			
		||||
      errmsg = "Invalid syntax.";
 | 
			
		||||
      line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -185,7 +202,8 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
 | 
			
		||||
    char *key = argv[3];
 | 
			
		||||
 | 
			
		||||
    if (atoi(port) == 0) {
 | 
			
		||||
        wprintw(window, "Invalid syntax.\n");
 | 
			
		||||
        errmsg = "Invalid syntax.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -197,53 +215,46 @@ void cmd_connect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)
 | 
			
		||||
 | 
			
		||||
void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *errmsg;
 | 
			
		||||
 | 
			
		||||
    if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
 | 
			
		||||
        wattron(window, COLOR_PAIR(RED));
 | 
			
		||||
        wprintw(window, " * Warning: Too many windows are open.\n");
 | 
			
		||||
        wattron(window, COLOR_PAIR(RED));
 | 
			
		||||
        errmsg = " * Warning: Too many windows are open.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int groupnum = tox_add_groupchat(m);
 | 
			
		||||
 | 
			
		||||
    if (groupnum == -1) {
 | 
			
		||||
        wprintw(window, "Group chat instance failed to initialize.\n");
 | 
			
		||||
        errmsg = "Group chat instance failed to initialize.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (init_groupchat_win(prompt, m, groupnum) == -1) {
 | 
			
		||||
        wprintw(window, "Group chat window failed to initialize.\n");
 | 
			
		||||
        errmsg = "Group chat window failed to initialize.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        tox_del_groupchat(m, groupnum);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wprintw(window, "Group chat created as %d.\n", groupnum);
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
    snprintf(msg, sizeof(msg), "Group chat created as %d.", groupnum);
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *msg;
 | 
			
		||||
    struct chatlog *log = self->chatwin->log;
 | 
			
		||||
 | 
			
		||||
    if (argc == 0) {
 | 
			
		||||
        bool on;
 | 
			
		||||
 | 
			
		||||
        if (self->is_chat || self->is_groupchat)
 | 
			
		||||
            on = self->chatwin->log->log_on;
 | 
			
		||||
        else if (self->is_prompt)
 | 
			
		||||
            on = self->promptbuf->log->log_on;
 | 
			
		||||
 | 
			
		||||
        if (on) {
 | 
			
		||||
            wprintw(window, "Logging for this window is ");
 | 
			
		||||
            wattron(window, COLOR_PAIR(GREEN) | A_BOLD);
 | 
			
		||||
            wprintw(window, "[on]");
 | 
			
		||||
            wattroff(window, COLOR_PAIR(GREEN) | A_BOLD);
 | 
			
		||||
            wprintw(window, ". Type \"/log off\" to disable.\n");
 | 
			
		||||
        } else {
 | 
			
		||||
            wprintw(window, "Logging for this window is ");
 | 
			
		||||
            wattron(window, COLOR_PAIR(RED) | A_BOLD);
 | 
			
		||||
            wprintw(window, "[off]");
 | 
			
		||||
            wattroff(window, COLOR_PAIR(RED) | A_BOLD);
 | 
			
		||||
            wprintw(window, ". Type \"/log on\" to enable.\n");
 | 
			
		||||
        }
 | 
			
		||||
        if (log->log_on)
 | 
			
		||||
            msg = "Logging for this window is ON. Type \"/log off\" to disable.";
 | 
			
		||||
        else
 | 
			
		||||
            msg = "Logging for this window is OFF. Type \"/log on\" to enable.";
 | 
			
		||||
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -253,38 +264,31 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
 | 
			
		||||
 | 
			
		||||
        if (self->is_chat) {
 | 
			
		||||
            friends[self->num].logging_on = true;
 | 
			
		||||
            log_enable(self->name, friends[self->num].pub_key, self->chatwin->log);
 | 
			
		||||
            log_enable(self->name, friends[self->num].pub_key, log);
 | 
			
		||||
        } else if (self->is_prompt) {
 | 
			
		||||
            uint8_t myid[TOX_FRIEND_ADDRESS_SIZE];
 | 
			
		||||
            tox_get_address(m, myid);
 | 
			
		||||
            log_enable(self->name, &myid, self->promptbuf->log);
 | 
			
		||||
            log_enable(self->name, myid, log);
 | 
			
		||||
        } else if (self->is_groupchat) {
 | 
			
		||||
            log_enable(self->name, NULL, self->chatwin->log);
 | 
			
		||||
            log_enable(self->name, NULL, log);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        wprintw(window, "Logging ");
 | 
			
		||||
        wattron(window, COLOR_PAIR(GREEN) | A_BOLD);
 | 
			
		||||
        wprintw(window, "[on]\n");
 | 
			
		||||
        wattroff(window, COLOR_PAIR(GREEN) | A_BOLD);
 | 
			
		||||
        msg = "Logging enabled";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    } else if (!strcmp(swch, "0") || !strcmp(swch, "off")) {
 | 
			
		||||
        if (self->is_chat) {
 | 
			
		||||
        if (self->is_chat)
 | 
			
		||||
            friends[self->num].logging_on = false;
 | 
			
		||||
            log_disable(self->chatwin->log);
 | 
			
		||||
        } else if (self->is_prompt) {
 | 
			
		||||
            log_disable(self->promptbuf->log);
 | 
			
		||||
        } else if (self->is_groupchat) {
 | 
			
		||||
            log_disable(self->chatwin->log);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        wprintw(window, "Logging ");
 | 
			
		||||
        wattron(window, COLOR_PAIR(RED) | A_BOLD);
 | 
			
		||||
        wprintw(window, "[off]\n");
 | 
			
		||||
        wattroff(window, COLOR_PAIR(RED) | A_BOLD);
 | 
			
		||||
        log_disable(log);
 | 
			
		||||
 | 
			
		||||
        msg = "Logging disabled";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wprintw(window, "Invalid option. Use \"/log on\" and \"/log off\" to toggle logging.\n");
 | 
			
		||||
    msg = "Invalid option. Use \"/log on\" and \"/log off\" to toggle logging.";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_myid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
@@ -301,14 +305,17 @@ void cmd_myid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
 | 
			
		||||
        strcat(id, xx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wprintw(window, "%s\n", id);
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, id, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *errmsg;
 | 
			
		||||
 | 
			
		||||
    /* check arguments */
 | 
			
		||||
    if (argc < 1) {
 | 
			
		||||
      wprintw(window, "Invalid name.\n");
 | 
			
		||||
      errmsg = "Invalid name.";
 | 
			
		||||
      line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -322,7 +329,8 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!valid_nick(nick)) {
 | 
			
		||||
        wprintw(window, "Invalid name.\n");
 | 
			
		||||
        errmsg = "Invalid name.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -339,15 +347,19 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
 | 
			
		||||
 | 
			
		||||
void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *errmsg;
 | 
			
		||||
 | 
			
		||||
    if (argc < 1) {
 | 
			
		||||
        wprintw(window, "Wrong number of arguments.\n");
 | 
			
		||||
        errmsg = "Wrong number of arguments.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t *msg = argv[1];
 | 
			
		||||
 | 
			
		||||
    if (msg[0] != '\"') {
 | 
			
		||||
        wprintw(window, "Note must be enclosed in quotes.\n");
 | 
			
		||||
        errmsg = "Note must be enclosed in quotes.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -360,33 +372,43 @@ void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
 | 
			
		||||
 | 
			
		||||
void cmd_prompt_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    wclear(window);
 | 
			
		||||
    wattron(window, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
    wprintw(window, "\n\nGlobal commands:\n");
 | 
			
		||||
    wattroff(window, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
    uint8_t *msg = "Global commands:";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
 | 
			
		||||
 | 
			
		||||
    wprintw(window, "    /add <id> <msg>            : Add friend with optional message\n");
 | 
			
		||||
    wprintw(window, "    /accept <n>                : Accept friend request\n");
 | 
			
		||||
    wprintw(window, "    /connect <ip> <port> <key> : Manually connect to a DHT node\n");
 | 
			
		||||
    wprintw(window, "    /status <type> <msg>       : Set status with optional note\n");
 | 
			
		||||
    wprintw(window, "    /note <msg>                : Set a personal note\n");
 | 
			
		||||
    wprintw(window, "    /nick <nick>               : Set your nickname\n");
 | 
			
		||||
    wprintw(window, "    /log <on> or <off>         : Enable/disable logging\n");
 | 
			
		||||
    wprintw(window, "    /groupchat                 : Create a group chat\n");
 | 
			
		||||
    wprintw(window, "    /myid                      : Print your ID\n");
 | 
			
		||||
    wprintw(window, "    /help                      : Print this message again\n");
 | 
			
		||||
    wprintw(window, "    /clear                     : Clear the window\n");
 | 
			
		||||
    wprintw(window, "    /quit or /exit             : Exit Toxic\n");
 | 
			
		||||
    
 | 
			
		||||
#ifdef _SUPPORT_AUDIO
 | 
			
		||||
    wprintw(window, "    /lsdev <type>              : List devices where type: in|out\n");
 | 
			
		||||
    wprintw(window, "    /sdev <type> <id>          : Set active device\n");
 | 
			
		||||
    #define NUMLINES 14
 | 
			
		||||
#else
 | 
			
		||||
    #define NUMLINES 12
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    uint8_t lines[NUMLINES][MAX_STR_SIZE] = {
 | 
			
		||||
 | 
			
		||||
    { "    /add <id> <msg>            : Add friend with optional message"               },
 | 
			
		||||
    { "    /accept <n>                : Accept friend request"                          },
 | 
			
		||||
    { "    /connect <ip> <port> <key> : Manually connect to a DHT node"                 },
 | 
			
		||||
    { "    /status <type> <msg>       : Set status with optional note"                  },
 | 
			
		||||
    { "    /note <msg>                : Set a personal note"                            },
 | 
			
		||||
    { "    /nick <nick>               : Set your nickname"                              },
 | 
			
		||||
    { "    /log <on> or <off>         : Enable/disable logging"                         },
 | 
			
		||||
    { "    /groupchat                 : Create a group chat"                            },
 | 
			
		||||
    { "    /myid                      : Print your ID"                                  },
 | 
			
		||||
    { "    /help                      : Print this message again"                       },
 | 
			
		||||
    { "    /clear                     : Clear window history"                           },
 | 
			
		||||
    { "    /quit or /exit             : Exit Toxic"                                     },
 | 
			
		||||
#ifdef _SUPPORT_AUDIO
 | 
			
		||||
    { "    /lsdev <type>              : List devices where type: in|out"                },
 | 
			
		||||
    { "    /sdev <type> <id>          : Set active device"                              },
 | 
			
		||||
#endif /* _SUPPORT_AUDIO */
 | 
			
		||||
    
 | 
			
		||||
    wattron(window, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
    wprintw(window, " * Argument messages must be enclosed in quotation marks.\n");
 | 
			
		||||
    wprintw(window, " * Use ctrl-o and ctrl-p to navigate through the tabs.\n\n");
 | 
			
		||||
    wattroff(window, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < NUMLINES; ++i)
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, lines[i], SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
    msg = " * Argument messages must be enclosed in quotation marks.\n"
 | 
			
		||||
          " * Use ctrl-o and ctrl-p to navigate through the tabs.\n";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_quit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
@@ -397,16 +419,19 @@ void cmd_quit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
 | 
			
		||||
void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *msg = NULL;
 | 
			
		||||
    uint8_t *errmsg;
 | 
			
		||||
 | 
			
		||||
    if (argc >= 2) {
 | 
			
		||||
        msg = argv[2];
 | 
			
		||||
 | 
			
		||||
        if (msg[0] != '\"') {
 | 
			
		||||
            wprintw(window, "Note must be enclosed in quotes.\n");
 | 
			
		||||
            errmsg = "Note must be enclosed in quotes.";
 | 
			
		||||
            line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (argc != 1) {
 | 
			
		||||
        wprintw(window, "Wrong number of arguments.\n");
 | 
			
		||||
        errmsg = "Wrong number of arguments.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -427,7 +452,8 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
 | 
			
		||||
    else if (!strcmp(l_status, "busy"))
 | 
			
		||||
        status_kind = TOX_USERSTATUS_BUSY;
 | 
			
		||||
    else {
 | 
			
		||||
        wprintw(window, "Invalid status. Valid statuses are: online, busy and away.\n");
 | 
			
		||||
        errmsg = "Invalid status. Valid statuses are: online, busy and away.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										152
									
								
								src/groupchat.c
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								src/groupchat.c
									
									
									
									
									
								
							@@ -35,6 +35,7 @@
 | 
			
		||||
#include "prompt.h"
 | 
			
		||||
#include "toxic_strings.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "line_info.h"
 | 
			
		||||
 | 
			
		||||
extern char *DATA_FILE;
 | 
			
		||||
extern int store_data(Tox *m, char *path);
 | 
			
		||||
@@ -103,29 +104,38 @@ static void close_groupchat(ToxWindow *self, Tox *m, int groupnum)
 | 
			
		||||
    kill_groupchat_window(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void print_groupchat_help(ChatContext *ctx)
 | 
			
		||||
static void print_groupchat_help(ToxWindow *self)
 | 
			
		||||
{
 | 
			
		||||
    wattron(ctx->history, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
    wprintw(ctx->history, "Group chat commands:\n");
 | 
			
		||||
    wattroff(ctx->history, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
    uint8_t *msg = "Group chat commands:";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
 | 
			
		||||
 | 
			
		||||
    wprintw(ctx->history, "    /add <id> <msg>     : Add friend with optional message\n");
 | 
			
		||||
    wprintw(ctx->history, "    /status <type> <msg>: Set your status with optional note\n");
 | 
			
		||||
    wprintw(ctx->history, "    /note <msg>         : Set a personal note\n");
 | 
			
		||||
    wprintw(ctx->history, "    /nick <nick>        : Set your nickname\n");
 | 
			
		||||
    wprintw(ctx->history, "    /groupchat          : Create a group chat\n");
 | 
			
		||||
    wprintw(ctx->history, "    /log <on> or <off>  : Enable/disable logging\n");
 | 
			
		||||
    wprintw(ctx->history, "    /close              : Close the current group chat\n");
 | 
			
		||||
    wprintw(ctx->history, "    /help               : Print this message again\n");
 | 
			
		||||
    wprintw(ctx->history, "    /help global        : Show a list of global commands\n");
 | 
			
		||||
    
 | 
			
		||||
    wattron(ctx->history, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
    wprintw(ctx->history, " * Argument messages must be enclosed in quotation marks.\n");
 | 
			
		||||
    wprintw(ctx->history, " * Scroll peer list with the Page Up/Page Down keys.\n\n");
 | 
			
		||||
    wattroff(ctx->history, COLOR_PAIR(CYAN) | A_BOLD);
 | 
			
		||||
    wattron(ctx->history, COLOR_PAIR(WHITE) | A_BOLD);
 | 
			
		||||
    wprintw(ctx->history, "    Notice, some friends will be missing names while finding peers\n\n");
 | 
			
		||||
    wattroff(ctx->history, COLOR_PAIR(WHITE) | A_BOLD);
 | 
			
		||||
    #define NUMLINES 9
 | 
			
		||||
 | 
			
		||||
    uint8_t lines[NUMLINES][MAX_STR_SIZE] = {
 | 
			
		||||
 | 
			
		||||
    { "    /add <id> <msg>     : Add friend with optional message"               },
 | 
			
		||||
    { "    /status <type> <msg>: Set your status with optional note"             },
 | 
			
		||||
    { "    /note <msg>         : Set a personal note"                            },
 | 
			
		||||
    { "    /nick <nick>        : Set your nickname"                              },
 | 
			
		||||
    { "    /groupchat          : Create a group chat"                            },
 | 
			
		||||
    { "    /log <on> or <off>  : Enable/disable logging"                         },
 | 
			
		||||
    { "    /close              : Close the current group chat"                   },
 | 
			
		||||
    { "    /help               : Print this message again"                       },
 | 
			
		||||
    { "    /help global        : Show a list of global commands"                 },
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < NUMLINES; ++i)
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, lines[i], SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
    msg = " * Use ESC key to toggle history scroll mode";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
 | 
			
		||||
    msg = " * Scroll peer list with the Page Up/Page Down keys.\n";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, CYAN);
 | 
			
		||||
    msg = " * Notice, some friends will be missing names while finding peers\n";
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 1, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, int peernum,
 | 
			
		||||
@@ -158,19 +168,10 @@ static void groupchat_onGroupMessage(ToxWindow *self, Tox *m, int groupnum, int
 | 
			
		||||
 | 
			
		||||
    alert_window(self, alert_type, beep);
 | 
			
		||||
 | 
			
		||||
    print_time(ctx->history);
 | 
			
		||||
    wattron(ctx->history, COLOR_PAIR(nick_clr));
 | 
			
		||||
    wprintw(ctx->history, "%s: ", nick);
 | 
			
		||||
    wattroff(ctx->history, COLOR_PAIR(nick_clr));
 | 
			
		||||
    
 | 
			
		||||
    if (msg[0] == '>') {
 | 
			
		||||
        wattron(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
        wprintw(ctx->history, "%s\n", msg);
 | 
			
		||||
        wattroff(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
    } else {
 | 
			
		||||
        wprintw(ctx->history, "%s\n", msg);
 | 
			
		||||
    }
 | 
			
		||||
    uint8_t timefrmt[TIME_STR_SIZE];
 | 
			
		||||
    get_time_str(timefrmt);
 | 
			
		||||
 | 
			
		||||
    line_info_add(self, timefrmt, nick, NULL, msg, IN_MSG, 0, nick_clr);
 | 
			
		||||
    write_to_log(msg, nick, ctx->log, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -202,11 +203,10 @@ static void groupchat_onGroupAction(ToxWindow *self, Tox *m, int groupnum, int p
 | 
			
		||||
    tox_group_peername(m, groupnum, peernum, nick);
 | 
			
		||||
    nick[TOXIC_MAX_NAME_LENGTH] = '\0';    /* enforce client max name length */
 | 
			
		||||
 | 
			
		||||
    print_time(ctx->history);
 | 
			
		||||
    wattron(ctx->history, COLOR_PAIR(YELLOW));
 | 
			
		||||
    wprintw(ctx->history, "* %s %s\n", nick, action);
 | 
			
		||||
    wattroff(ctx->history, COLOR_PAIR(YELLOW));
 | 
			
		||||
    uint8_t timefrmt[TIME_STR_SIZE];
 | 
			
		||||
    get_time_str(timefrmt);
 | 
			
		||||
 | 
			
		||||
    line_info_add(self, timefrmt, nick, NULL, action, ACTION, 0, 0);
 | 
			
		||||
    write_to_log(action, nick, ctx->log, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -270,31 +270,21 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
 | 
			
		||||
    qsort(groupchats[groupnum].peer_names, groupchats[groupnum].num_peers, TOX_MAX_NAME_LENGTH, qsort_strcasecmp_hlpr);
 | 
			
		||||
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    print_time(ctx->history);
 | 
			
		||||
 | 
			
		||||
    const uint8_t *event;
 | 
			
		||||
    uint8_t *event;
 | 
			
		||||
    uint8_t timefrmt[TIME_STR_SIZE];
 | 
			
		||||
    get_time_str(timefrmt);
 | 
			
		||||
 | 
			
		||||
    switch (change) {
 | 
			
		||||
    case TOX_CHAT_CHANGE_PEER_ADD:
 | 
			
		||||
        event = "has joined the room";
 | 
			
		||||
 | 
			
		||||
        wattron(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
        wattron(ctx->history, A_BOLD);
 | 
			
		||||
        wprintw(ctx->history, "* %s", peername);
 | 
			
		||||
        wattroff(ctx->history, A_BOLD);
 | 
			
		||||
        wprintw(ctx->history, " %s\n", event);
 | 
			
		||||
        wattroff(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
 | 
			
		||||
        line_info_add(self, timefrmt, peername, NULL, event, CONNECTION, 0, GREEN);
 | 
			
		||||
        write_to_log(event, peername, ctx->log, true);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case TOX_CHAT_CHANGE_PEER_DEL:
 | 
			
		||||
        event = "has left the room";
 | 
			
		||||
 | 
			
		||||
        wattron(ctx->history, A_BOLD);
 | 
			
		||||
        wprintw(ctx->history, "* %s", oldpeername);
 | 
			
		||||
        wattroff(ctx->history, A_BOLD);
 | 
			
		||||
        wprintw(ctx->history, " %s\n", event);
 | 
			
		||||
        line_info_add(self, timefrmt, oldpeername, NULL, event, CONNECTION, 0, 0);
 | 
			
		||||
 | 
			
		||||
        if (groupchats[self->num].side_pos > 0)
 | 
			
		||||
            --groupchats[self->num].side_pos;
 | 
			
		||||
@@ -303,17 +293,8 @@ static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnu
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case TOX_CHAT_CHANGE_PEER_NAME:
 | 
			
		||||
        wattron(ctx->history, COLOR_PAIR(MAGENTA));
 | 
			
		||||
        wattron(ctx->history, A_BOLD);
 | 
			
		||||
        wprintw(ctx->history, "* %s", oldpeername);
 | 
			
		||||
        wattroff(ctx->history, A_BOLD);
 | 
			
		||||
 | 
			
		||||
        wprintw(ctx->history, " is now known as ");
 | 
			
		||||
 | 
			
		||||
        wattron(ctx->history, A_BOLD);
 | 
			
		||||
        wprintw(ctx->history, "%s\n", peername);
 | 
			
		||||
        wattroff(ctx->history, A_BOLD);
 | 
			
		||||
        wattroff(ctx->history, COLOR_PAIR(MAGENTA));
 | 
			
		||||
        event = " is now known as ";
 | 
			
		||||
        line_info_add(self, timefrmt, oldpeername, peername, event, NAME_CHANGE, 0, 0);
 | 
			
		||||
 | 
			
		||||
        uint8_t tmp_event[TOXIC_MAX_NAME_LENGTH + 32];
 | 
			
		||||
        snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", peername);
 | 
			
		||||
@@ -331,9 +312,8 @@ static void send_group_action(ToxWindow *self, ChatContext *ctx, Tox *m, uint8_t
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (tox_group_action_send(m, self->num, action, strlen(action) + 1) == -1) {
 | 
			
		||||
        wattron(ctx->history, COLOR_PAIR(RED));
 | 
			
		||||
        wprintw(ctx->history, " * Failed to send action\n");
 | 
			
		||||
        wattroff(ctx->history, COLOR_PAIR(RED));
 | 
			
		||||
        uint8_t *errmsg = " * Failed to send action.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -346,6 +326,17 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
    int cur_len = 0;
 | 
			
		||||
 | 
			
		||||
    if (key == T_KEY_ESC) {   /* ESC key: Toggle history scroll mode */
 | 
			
		||||
        bool scroll = ctx->hst->scroll_mode ? false : true;
 | 
			
		||||
        line_info_toggle_scroll(self, scroll);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* If we're in scroll mode ignore rest of function */
 | 
			
		||||
    if (ctx->hst->scroll_mode) {
 | 
			
		||||
        line_info_onKey(self, key);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (key == 0x107 || key == 0x8 || key == 0x7f) {  /* BACKSPACE key: Remove character behind pos */
 | 
			
		||||
        if (ctx->pos > 0) {
 | 
			
		||||
            cur_len = MAX(1, wcwidth(ctx->line[ctx->pos - 1]));
 | 
			
		||||
@@ -427,13 +418,13 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
 | 
			
		||||
    else if (key == KEY_UP) {    /* fetches previous item in history */
 | 
			
		||||
        fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
 | 
			
		||||
                        &ctx->hst_pos, LN_HIST_MV_UP);
 | 
			
		||||
                        &ctx->hst_pos, MOVE_UP);
 | 
			
		||||
        mv_curs_end(self->window, ctx->len, y2, x2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (key == KEY_DOWN) {    /* fetches next item in history */
 | 
			
		||||
        fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
 | 
			
		||||
                        &ctx->hst_pos, LN_HIST_MV_DWN);
 | 
			
		||||
                        &ctx->hst_pos, MOVE_DOWN);
 | 
			
		||||
        mv_curs_end(self->window, ctx->len, y2, x2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -502,7 +493,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
 | 
			
		||||
        wclear(ctx->linewin);
 | 
			
		||||
        wmove(self->window, y2 - CURS_Y_OFFSET, 0);
 | 
			
		||||
        wclrtobot(self->window);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if (!string_is_empty(line))
 | 
			
		||||
            add_line_to_hist(ctx->line, ctx->len, ctx->ln_history, &ctx->hst_tot, &ctx->hst_pos);
 | 
			
		||||
@@ -515,7 +506,7 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
                if (strcmp(line, "help global") == 0)
 | 
			
		||||
                    execute(ctx->history, self, m, "/help", GLOBAL_COMMAND_MODE);
 | 
			
		||||
                else
 | 
			
		||||
                    print_groupchat_help(ctx);
 | 
			
		||||
                    print_groupchat_help(self);
 | 
			
		||||
 | 
			
		||||
            } else if (strncmp(line, "/me ", strlen("/me ")) == 0) {
 | 
			
		||||
                send_group_action(self, ctx, m, line + strlen("/me "));
 | 
			
		||||
@@ -524,9 +515,8 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
            }
 | 
			
		||||
        } else if (!string_is_empty(line)) {
 | 
			
		||||
            if (tox_group_message_send(m, self->num, line, strlen(line) + 1) == -1) {
 | 
			
		||||
                wattron(ctx->history, COLOR_PAIR(RED));
 | 
			
		||||
                wprintw(ctx->history, " * Failed to send message.\n");
 | 
			
		||||
                wattroff(ctx->history, COLOR_PAIR(RED));
 | 
			
		||||
                uint8_t *errmsg = " * Failed to send message.";
 | 
			
		||||
                line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, RED);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -536,13 +526,17 @@ static void groupchat_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
 | 
			
		||||
static void groupchat_onDraw(ToxWindow *self, Tox *m)
 | 
			
		||||
{
 | 
			
		||||
    curs_set(1);
 | 
			
		||||
 | 
			
		||||
    int x2, y2;
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
 | 
			
		||||
    if (!ctx->hst->scroll_mode)
 | 
			
		||||
        scrollok(ctx->history, 1);
 | 
			
		||||
 | 
			
		||||
    wclear(ctx->linewin);
 | 
			
		||||
    line_info_print(self);
 | 
			
		||||
 | 
			
		||||
    if (ctx->len > 0) {
 | 
			
		||||
        uint8_t line[MAX_STR_SIZE];
 | 
			
		||||
@@ -593,22 +587,26 @@ static void groupchat_onInit(ToxWindow *self, Tox *m)
 | 
			
		||||
    getmaxyx(self->window, y, x);
 | 
			
		||||
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
 | 
			
		||||
    ctx->history = subwin(self->window, y-CHATBOX_HEIGHT+1, x-SIDEBAR_WIDTH-1, 0, 0);
 | 
			
		||||
    scrollok(ctx->history, 1);
 | 
			
		||||
    ctx->linewin = subwin(self->window, CHATBOX_HEIGHT, x, y-CHATBOX_HEIGHT, 0);
 | 
			
		||||
    ctx->sidebar = subwin(self->window, y-CHATBOX_HEIGHT+1, SIDEBAR_WIDTH, 0, x-SIDEBAR_WIDTH);
 | 
			
		||||
 | 
			
		||||
    ctx->hst = malloc(sizeof(struct history));
 | 
			
		||||
    ctx->log = malloc(sizeof(struct chatlog));
 | 
			
		||||
 | 
			
		||||
    if (ctx->log == NULL) {
 | 
			
		||||
    if (ctx->log == NULL || ctx->hst == NULL) {
 | 
			
		||||
        endwin();
 | 
			
		||||
        fprintf(stderr, "malloc() failed. Aborting...\n");
 | 
			
		||||
        exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(ctx->hst, 0, sizeof(struct history));
 | 
			
		||||
    memset(ctx->log, 0, sizeof(struct chatlog));
 | 
			
		||||
 | 
			
		||||
    print_groupchat_help(ctx);
 | 
			
		||||
    line_info_init(ctx->hst);
 | 
			
		||||
 | 
			
		||||
    print_groupchat_help(self);
 | 
			
		||||
    execute(ctx->history, self, m, "/log", GLOBAL_COMMAND_MODE);
 | 
			
		||||
 | 
			
		||||
    wmove(self->window, y-CURS_Y_OFFSET, 0);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										387
									
								
								src/line_info.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										387
									
								
								src/line_info.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,387 @@
 | 
			
		||||
/*  line_info.c
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2014 Toxic All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 *  This file is part of Toxic.
 | 
			
		||||
 *
 | 
			
		||||
 *  Toxic is free software: you can redistribute it and/or modify
 | 
			
		||||
 *  it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *  the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 *  (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *  Toxic is distributed in the hope that it will be useful,
 | 
			
		||||
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU General Public License
 | 
			
		||||
 *  along with Toxic.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#include "toxic_windows.h"
 | 
			
		||||
#include "line_info.h"
 | 
			
		||||
#include "groupchat.h"
 | 
			
		||||
 | 
			
		||||
void line_info_init(struct history *hst)
 | 
			
		||||
{
 | 
			
		||||
    hst->line_root = malloc(sizeof(struct line_info));
 | 
			
		||||
 | 
			
		||||
    if (hst->line_root == NULL) {
 | 
			
		||||
        endwin();
 | 
			
		||||
        fprintf(stderr, "malloc() failed. Aborting...\n");
 | 
			
		||||
        exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(hst->line_root, 0, sizeof(struct line_info));
 | 
			
		||||
    hst->line_start = hst->line_root;
 | 
			
		||||
    hst->line_end = hst->line_start;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* resets line_start when scroll mode is disabled */
 | 
			
		||||
static void line_info_reset_start(struct history *hst)
 | 
			
		||||
{
 | 
			
		||||
    struct line_info *line = hst->line_end;
 | 
			
		||||
    uint32_t start_id = hst->start_id + 1;
 | 
			
		||||
 | 
			
		||||
    while (line) {
 | 
			
		||||
        if (line->id == start_id) {
 | 
			
		||||
            hst->line_start = line;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        line = line->prev;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void line_info_toggle_scroll(ToxWindow *self, bool scroll)
 | 
			
		||||
{
 | 
			
		||||
    WINDOW *win = self->chatwin->history;
 | 
			
		||||
    struct history *hst = self->chatwin->hst;
 | 
			
		||||
 | 
			
		||||
    if (scroll) {
 | 
			
		||||
        hst->scroll_mode = true;
 | 
			
		||||
        scrollok(win, 0);
 | 
			
		||||
        curs_set(0);
 | 
			
		||||
    } else {
 | 
			
		||||
        hst->scroll_mode = false;
 | 
			
		||||
        scrollok(win, 1);
 | 
			
		||||
        curs_set(1);
 | 
			
		||||
        line_info_reset_start(hst);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void line_info_cleanup(struct history *hst)
 | 
			
		||||
{
 | 
			
		||||
    struct line_info *tmp1 = hst->line_root;
 | 
			
		||||
 | 
			
		||||
    while (tmp1) {
 | 
			
		||||
        struct line_info *tmp2 = tmp1->next;
 | 
			
		||||
        free(tmp1);
 | 
			
		||||
        tmp1 = tmp2;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void line_info_add(ToxWindow *self, uint8_t *tmstmp, uint8_t *name1, uint8_t *name2, uint8_t *msg, 
 | 
			
		||||
                   uint8_t type, uint8_t bold, uint8_t colour)
 | 
			
		||||
{
 | 
			
		||||
    struct history *hst = self->chatwin->hst;
 | 
			
		||||
    struct line_info *new_line = malloc(sizeof(struct line_info));
 | 
			
		||||
 | 
			
		||||
    if (new_line == NULL) {
 | 
			
		||||
        endwin();
 | 
			
		||||
        fprintf(stderr, "malloc() failed. Aborting...\n");
 | 
			
		||||
        exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(new_line, 0, sizeof(struct line_info));
 | 
			
		||||
 | 
			
		||||
    int len = 1;     /* there will always be a newline */
 | 
			
		||||
 | 
			
		||||
    /* for type-specific formatting in print function */
 | 
			
		||||
    switch (type) {
 | 
			
		||||
    case ACTION:
 | 
			
		||||
    case NAME_CHANGE:
 | 
			
		||||
        len += 3;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        len += 2;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg) {
 | 
			
		||||
        memcpy(new_line->msg, msg, MAX_STR_SIZE);
 | 
			
		||||
        len += strlen(msg);
 | 
			
		||||
    } if (tmstmp) {
 | 
			
		||||
        memcpy(new_line->timestamp, tmstmp, TIME_STR_SIZE);
 | 
			
		||||
        len += strlen(tmstmp);
 | 
			
		||||
    } if (name1) {
 | 
			
		||||
        memcpy(new_line->name1, name1, TOXIC_MAX_NAME_LENGTH);
 | 
			
		||||
        len += strlen(name1);
 | 
			
		||||
    } if (name2) {
 | 
			
		||||
        memcpy(new_line->name2, name2, TOXIC_MAX_NAME_LENGTH);
 | 
			
		||||
        len += strlen(name2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    new_line->len = len;
 | 
			
		||||
    new_line->type = type;
 | 
			
		||||
    new_line->bold = bold;
 | 
			
		||||
    new_line->colour = colour;
 | 
			
		||||
    new_line->id = hst->line_end->id + 1;
 | 
			
		||||
 | 
			
		||||
    new_line->prev = hst->line_end;
 | 
			
		||||
    hst->line_end->next = new_line;
 | 
			
		||||
    hst->line_end = new_line;
 | 
			
		||||
 | 
			
		||||
    /* If chat history exceeds limit move root forward and free old root */
 | 
			
		||||
    if (++hst->line_items > MAX_HISTORY) {
 | 
			
		||||
        --hst->line_items;
 | 
			
		||||
        struct line_info *tmp = hst->line_root->next;
 | 
			
		||||
        tmp->prev = NULL;
 | 
			
		||||
 | 
			
		||||
        if (hst->line_start->prev == NULL) {  /* if line_start is root move it forward as well */
 | 
			
		||||
            hst->line_start = hst->line_start->next;
 | 
			
		||||
            hst->line_start->prev = NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        free(hst->line_root);
 | 
			
		||||
        hst->line_root = tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int newlines = 0;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; msg[i]; ++i) {
 | 
			
		||||
        if (msg[i] == '\n')
 | 
			
		||||
            ++newlines;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int y, y2, x, x2;
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
    getyx(self->chatwin->history, y, x);
 | 
			
		||||
 | 
			
		||||
    int offst = self->is_groupchat ? SIDEBAR_WIDTH : 0;   /* offset width of groupchat sidebar */
 | 
			
		||||
    int lines = 1 + (len / (x2 - offst));
 | 
			
		||||
 | 
			
		||||
    int max_y = self->is_prompt ? y2 : y2 - CHATBOX_HEIGHT;
 | 
			
		||||
 | 
			
		||||
    /* move line_start forward proportionate to the number of new lines */
 | 
			
		||||
    if (y >= max_y) {
 | 
			
		||||
        while (lines > 0 && hst->line_start->next) {
 | 
			
		||||
            lines -= (1 + hst->line_start->len / (x2 - offst));
 | 
			
		||||
            hst->line_start = hst->line_start->next;
 | 
			
		||||
            ++hst->start_id;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void line_info_print(ToxWindow *self)
 | 
			
		||||
{
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
    WINDOW *win = ctx->history;
 | 
			
		||||
 | 
			
		||||
    wclear(win);
 | 
			
		||||
    int y2, x2;
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
 | 
			
		||||
    if (self->is_groupchat)
 | 
			
		||||
        wmove(win, 0, 0);
 | 
			
		||||
    else
 | 
			
		||||
        wmove(win, 2, 0);
 | 
			
		||||
 | 
			
		||||
    struct line_info *line = ctx->hst->line_start->next;
 | 
			
		||||
    int numlines = 0;
 | 
			
		||||
 | 
			
		||||
    while(line && numlines <= y2) {
 | 
			
		||||
        uint8_t type = line->type;
 | 
			
		||||
        numlines += line->len / x2;
 | 
			
		||||
 | 
			
		||||
        switch (type) {
 | 
			
		||||
        case OUT_MSG:
 | 
			
		||||
        case IN_MSG:
 | 
			
		||||
            wattron(win, COLOR_PAIR(BLUE));
 | 
			
		||||
            wprintw(win, "%s", line->timestamp);
 | 
			
		||||
            wattroff(win, COLOR_PAIR(BLUE));
 | 
			
		||||
 | 
			
		||||
            int nameclr = GREEN;
 | 
			
		||||
 | 
			
		||||
            if (line->colour)
 | 
			
		||||
                nameclr = line->colour;
 | 
			
		||||
            else if (type == IN_MSG)
 | 
			
		||||
                nameclr = CYAN;
 | 
			
		||||
 | 
			
		||||
            wattron(win, COLOR_PAIR(nameclr));
 | 
			
		||||
            wprintw(win, "%s: ", line->name1);
 | 
			
		||||
            wattroff(win, COLOR_PAIR(nameclr));
 | 
			
		||||
 | 
			
		||||
            if (line->msg[0] == '>')
 | 
			
		||||
                wattron(win, COLOR_PAIR(GREEN));
 | 
			
		||||
 | 
			
		||||
            wprintw(win, "%s\n", line->msg);
 | 
			
		||||
 | 
			
		||||
            if (line->msg[0] == '>')
 | 
			
		||||
                wattroff(win, COLOR_PAIR(GREEN));
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case ACTION:
 | 
			
		||||
            wattron(win, COLOR_PAIR(BLUE));
 | 
			
		||||
            wprintw(win, "%s", line->timestamp);
 | 
			
		||||
            wattroff(win, COLOR_PAIR(BLUE));
 | 
			
		||||
 | 
			
		||||
            wattron(win, COLOR_PAIR(YELLOW));
 | 
			
		||||
            wprintw(win, "* %s %s\n", line->name1, line->msg);
 | 
			
		||||
            wattroff(win, COLOR_PAIR(YELLOW));
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case SYS_MSG:
 | 
			
		||||
            if (line->timestamp[0]) {
 | 
			
		||||
                wattron(win, COLOR_PAIR(BLUE));
 | 
			
		||||
                wprintw(win, "%s", line->timestamp);
 | 
			
		||||
                wattroff(win, COLOR_PAIR(BLUE));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (line->bold)
 | 
			
		||||
                wattron(win, A_BOLD);
 | 
			
		||||
            if (line->colour)
 | 
			
		||||
                wattron(win, COLOR_PAIR(line->colour));
 | 
			
		||||
 | 
			
		||||
            wprintw(win, "%s\n", line->msg);
 | 
			
		||||
 | 
			
		||||
            if (line->bold)
 | 
			
		||||
                wattroff(win, A_BOLD);
 | 
			
		||||
            if (line->colour)
 | 
			
		||||
                wattroff(win, COLOR_PAIR(line->colour));
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case PROMPT:
 | 
			
		||||
            wattron(win, COLOR_PAIR(GREEN));
 | 
			
		||||
            wprintw(win, "$ ");
 | 
			
		||||
            wattroff(win, COLOR_PAIR(GREEN));
 | 
			
		||||
 | 
			
		||||
            if (line->msg[0])
 | 
			
		||||
                wprintw(win, "%s", line->msg);
 | 
			
		||||
 | 
			
		||||
            wprintw(win, "\n");
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CONNECTION:
 | 
			
		||||
            wattron(win, COLOR_PAIR(BLUE));
 | 
			
		||||
            wprintw(win, "%s", line->timestamp);
 | 
			
		||||
            wattroff(win, COLOR_PAIR(BLUE));
 | 
			
		||||
 | 
			
		||||
            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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void line_info_goto_root(struct history *hst)
 | 
			
		||||
{
 | 
			
		||||
    hst->line_start = hst->line_root;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void line_info_scroll_up(struct history *hst)
 | 
			
		||||
{
 | 
			
		||||
    if (hst->line_start->prev)
 | 
			
		||||
        hst->line_start = hst->line_start->prev;
 | 
			
		||||
    else beep();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void line_info_scroll_down(struct history *hst)
 | 
			
		||||
{
 | 
			
		||||
    if (hst->line_start->next)
 | 
			
		||||
        hst->line_start = hst->line_start->next;
 | 
			
		||||
    else beep();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void line_info_page_up(ToxWindow *self, struct history *hst)
 | 
			
		||||
{
 | 
			
		||||
    int x2, y2;
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
    int jump_dist = y2 / 2;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < jump_dist && hst->line_start->prev; ++i)
 | 
			
		||||
        hst->line_start = hst->line_start->prev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void line_info_page_down(ToxWindow *self, struct history *hst)
 | 
			
		||||
{
 | 
			
		||||
    int x2, y2;
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
    int jump_dist = y2 / 2;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < jump_dist && hst->line_start->next; ++i)
 | 
			
		||||
        hst->line_start = hst->line_start->next;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void line_info_onKey(ToxWindow *self, wint_t key)
 | 
			
		||||
{
 | 
			
		||||
    struct history *hst = self->chatwin->hst;
 | 
			
		||||
 | 
			
		||||
    switch (key) {
 | 
			
		||||
    case KEY_PPAGE:
 | 
			
		||||
        line_info_page_up(self, hst);
 | 
			
		||||
        break;
 | 
			
		||||
    case KEY_NPAGE:
 | 
			
		||||
        line_info_page_down(self, hst);
 | 
			
		||||
        break;
 | 
			
		||||
    case KEY_UP:
 | 
			
		||||
        line_info_scroll_up(hst);
 | 
			
		||||
        break;
 | 
			
		||||
    case KEY_DOWN:
 | 
			
		||||
        line_info_scroll_down(hst);
 | 
			
		||||
        break;
 | 
			
		||||
    case KEY_HOME:
 | 
			
		||||
        line_info_goto_root(hst);
 | 
			
		||||
        break;
 | 
			
		||||
    case KEY_END:
 | 
			
		||||
        line_info_reset_start(hst);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void line_info_clear(struct history *hst)
 | 
			
		||||
{
 | 
			
		||||
    hst->line_start = hst->line_end;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										79
									
								
								src/line_info.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/line_info.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
			
		||||
/*  line_info.h
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2014 Toxic All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 *  This file is part of Toxic.
 | 
			
		||||
 *
 | 
			
		||||
 *  Toxic is free software: you can redistribute it and/or modify
 | 
			
		||||
 *  it under the terms of the GNU General Public License as published by
 | 
			
		||||
 *  the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 *  (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *  Toxic is distributed in the hope that it will be useful,
 | 
			
		||||
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU General Public License
 | 
			
		||||
 *  along with Toxic.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define MAX_HISTORY 200
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    SYS_MSG,
 | 
			
		||||
    IN_MSG,
 | 
			
		||||
    OUT_MSG,
 | 
			
		||||
    PROMPT,
 | 
			
		||||
    ACTION,
 | 
			
		||||
    CONNECTION,
 | 
			
		||||
    NAME_CHANGE,
 | 
			
		||||
} LINE_TYPE;
 | 
			
		||||
 | 
			
		||||
struct line_info {
 | 
			
		||||
    uint8_t timestamp[TIME_STR_SIZE];
 | 
			
		||||
    uint8_t name1[TOXIC_MAX_NAME_LENGTH];
 | 
			
		||||
    uint8_t name2[TOXIC_MAX_NAME_LENGTH];
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
    uint8_t type;
 | 
			
		||||
    uint8_t bold;
 | 
			
		||||
    uint8_t colour;
 | 
			
		||||
    uint32_t id;
 | 
			
		||||
    int len;   /* combined len of all strings */
 | 
			
		||||
 | 
			
		||||
    struct line_info *prev;
 | 
			
		||||
    struct line_info *next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Linked list containing chat history lines */
 | 
			
		||||
struct history {
 | 
			
		||||
    struct line_info *line_root;
 | 
			
		||||
    struct line_info *line_start;   /* the first line we want to start printing at */
 | 
			
		||||
    struct line_info *line_end;
 | 
			
		||||
    uint32_t start_id;    /* keeps track of where line_start should be when at bottom of history */
 | 
			
		||||
    uint32_t line_items;
 | 
			
		||||
    bool scroll_mode;
 | 
			
		||||
    int y;
 | 
			
		||||
    int old_y;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* 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, 
 | 
			
		||||
                   uint8_t type, uint8_t bold, uint8_t colour);
 | 
			
		||||
 | 
			
		||||
/* Prints a section of history starting at line_start */
 | 
			
		||||
void line_info_print(ToxWindow *self);
 | 
			
		||||
 | 
			
		||||
/* frees all history lines */
 | 
			
		||||
void line_info_cleanup(struct history *hst);
 | 
			
		||||
 | 
			
		||||
/* Toggles scroll mode for current window */
 | 
			
		||||
void line_info_toggle_scroll(ToxWindow *self, bool scroll);
 | 
			
		||||
 | 
			
		||||
/* clears the screen (does not delete anything) */
 | 
			
		||||
void line_info_clear(struct history *hst);
 | 
			
		||||
 | 
			
		||||
void line_info_init(struct history *hst);
 | 
			
		||||
void line_info_onKey(ToxWindow *self, wint_t key);
 | 
			
		||||
@@ -31,6 +31,7 @@
 | 
			
		||||
#include "configdir.h"
 | 
			
		||||
#include "toxic_windows.h"
 | 
			
		||||
#include "misc_tools.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
 | 
			
		||||
/* Creates/fetches log file by appending to the config dir the name and a pseudo-unique identity */
 | 
			
		||||
void init_logging_session(uint8_t *name, uint8_t *key, struct chatlog *log)
 | 
			
		||||
@@ -51,9 +52,7 @@ void init_logging_session(uint8_t *name, uint8_t *key, struct chatlog *log)
 | 
			
		||||
        sprintf(&ident[2], "%02X", key[1] & 0xff);
 | 
			
		||||
        ident[KEY_IDENT_DIGITS*2+1] = '\0';
 | 
			
		||||
    } else {
 | 
			
		||||
        uint8_t s[MAX_STR_SIZE];
 | 
			
		||||
        strftime(s, MAX_STR_SIZE, "%Y-%m-%d[%H:%M:%S]", get_time());
 | 
			
		||||
        snprintf(ident, sizeof(ident), "%s", s);
 | 
			
		||||
        strftime(ident, sizeof(ident), "%Y-%m-%d[%H:%M:%S]", get_time());
 | 
			
		||||
        path_len += strlen(ident) + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,15 @@
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define LOG_FLUSH_LIMIT 2  /* limits calls to fflush(logfile) to a max of one per LOG_FLUSH_LIMIT seconds */
 | 
			
		||||
 | 
			
		||||
struct chatlog {
 | 
			
		||||
    FILE *file;
 | 
			
		||||
    uint64_t lastwrite;
 | 
			
		||||
    int pos;
 | 
			
		||||
    bool log_on;    /* specific to current chat window */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Creates/fetches log file by appending to the config dir the name and a pseudo-unique identity */
 | 
			
		||||
void init_logging_session(uint8_t *name, uint8_t *key, struct chatlog *log);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								src/main.c
									
									
									
									
									
								
							@@ -60,6 +60,7 @@
 | 
			
		||||
#include "prompt.h"
 | 
			
		||||
#include "misc_tools.h"
 | 
			
		||||
#include "file_senders.h"
 | 
			
		||||
#include "line_info.h"
 | 
			
		||||
 | 
			
		||||
#ifdef _SUPPORT_AUDIO
 | 
			
		||||
    #include "audio_call.h"
 | 
			
		||||
@@ -272,6 +273,8 @@ int init_connection(Tox *m)
 | 
			
		||||
 | 
			
		||||
static void do_connection(Tox *m, ToxWindow *prompt)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE] = {0};
 | 
			
		||||
 | 
			
		||||
    static int conn_try = 0;
 | 
			
		||||
    static int conn_err = 0;
 | 
			
		||||
    static bool dht_on = false;
 | 
			
		||||
@@ -281,21 +284,21 @@ static void do_connection(Tox *m, ToxWindow *prompt)
 | 
			
		||||
    if (!dht_on && !is_connected && !(conn_try++ % 100)) {
 | 
			
		||||
        if (!conn_err) {
 | 
			
		||||
            if ((conn_err = init_connection(m))) {
 | 
			
		||||
                prep_prompt_win();
 | 
			
		||||
                wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err);
 | 
			
		||||
                snprintf(msg, sizeof(msg), "\nAuto-connect failed with error code %d", conn_err);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else if (!dht_on && is_connected) {
 | 
			
		||||
        dht_on = true;
 | 
			
		||||
        prompt_update_connectionstatus(prompt, dht_on);
 | 
			
		||||
        prep_prompt_win();
 | 
			
		||||
        wprintw(prompt->window, "DHT connected.\n");
 | 
			
		||||
        snprintf(msg, sizeof(msg), "DHT connected.");
 | 
			
		||||
    } else if (dht_on && !is_connected) {
 | 
			
		||||
        dht_on = false;
 | 
			
		||||
        prompt_update_connectionstatus(prompt, dht_on);
 | 
			
		||||
        prep_prompt_win();
 | 
			
		||||
        wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n");
 | 
			
		||||
        snprintf(msg, sizeof(msg), "\nDHT disconnected. Attempting to reconnect.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msg[0])
 | 
			
		||||
        line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void load_friendlist(Tox *m)
 | 
			
		||||
@@ -405,11 +408,13 @@ void exit_toxic(Tox *m)
 | 
			
		||||
    store_data(m, DATA_FILE);
 | 
			
		||||
    close_all_file_senders();
 | 
			
		||||
    kill_all_windows();
 | 
			
		||||
    log_disable(prompt->promptbuf->log);
 | 
			
		||||
    log_disable(prompt->chatwin->log);
 | 
			
		||||
    line_info_cleanup(prompt->chatwin->hst);
 | 
			
		||||
    free(DATA_FILE);
 | 
			
		||||
    free(prompt->stb);
 | 
			
		||||
    free(prompt->promptbuf->log);
 | 
			
		||||
    free(prompt->promptbuf);
 | 
			
		||||
    free(prompt->chatwin->log);
 | 
			
		||||
    free(prompt->chatwin->hst);
 | 
			
		||||
    free(prompt->chatwin);
 | 
			
		||||
    tox_kill(m);
 | 
			
		||||
    #ifdef _SUPPORT_AUDIO
 | 
			
		||||
    terminate_audio();
 | 
			
		||||
@@ -513,19 +518,18 @@ int main(int argc, char *argv[])
 | 
			
		||||
        exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef _SUPPORT_AUDIO 
 | 
			
		||||
    uint8_t *msg;
 | 
			
		||||
 | 
			
		||||
    attron(COLOR_PAIR(RED) | A_BOLD);
 | 
			
		||||
    wprintw(prompt->window, "Starting audio...\n");
 | 
			
		||||
    attroff(COLOR_PAIR(RED) | A_BOLD);
 | 
			
		||||
#ifdef _SUPPORT_AUDIO
 | 
			
		||||
 | 
			
		||||
    av = init_audio(prompt, m);
 | 
			
		||||
 | 
			
		||||
    if ( errors() == NoError )
 | 
			
		||||
        wprintw(prompt->window, "Audio started with no problems.\n");
 | 
			
		||||
        msg = "Audio started with no problems.";
 | 
			
		||||
    else /* Get error code and stuff */
 | 
			
		||||
        wprintw(prompt->window, "Error starting audio!\n");
 | 
			
		||||
        msg = "Error starting audio!";
 | 
			
		||||
 | 
			
		||||
    line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
 | 
			
		||||
#endif /* _SUPPORT_AUDIO */
 | 
			
		||||
 | 
			
		||||
@@ -533,17 +537,13 @@ int main(int argc, char *argv[])
 | 
			
		||||
        load_data(m, DATA_FILE);
 | 
			
		||||
 | 
			
		||||
    if (f_flag == -1) {
 | 
			
		||||
        attron(COLOR_PAIR(RED) | A_BOLD);
 | 
			
		||||
        wprintw(prompt->window, "You passed '-f' without giving an argument.\n"
 | 
			
		||||
                "defaulting to 'data' for a keyfile...\n");
 | 
			
		||||
        attroff(COLOR_PAIR(RED) | A_BOLD);
 | 
			
		||||
        msg = "You passed '-f' without giving an argument. Defaulting to 'data' for a keyfile...";
 | 
			
		||||
        line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (config_err) {
 | 
			
		||||
        attron(COLOR_PAIR(RED) | A_BOLD);
 | 
			
		||||
        wprintw(prompt->window, "Unable to determine configuration directory.\n"
 | 
			
		||||
                "defaulting to 'data' for a keyfile...\n");
 | 
			
		||||
        attroff(COLOR_PAIR(RED) | A_BOLD);
 | 
			
		||||
        msg = "Unable to determine configuration directory. Defaulting to 'data' for a keyfile...";
 | 
			
		||||
        line_info_add(prompt, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sort_friendlist_index();
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
 | 
			
		||||
#include "toxic_windows.h"
 | 
			
		||||
#include "misc_tools.h"
 | 
			
		||||
 | 
			
		||||
extern ToxWindow *prompt;
 | 
			
		||||
 | 
			
		||||
@@ -54,15 +55,9 @@ struct tm *get_time(void)
 | 
			
		||||
    return timeinfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Prints the time to given window */
 | 
			
		||||
void print_time(WINDOW *window)
 | 
			
		||||
void get_time_str(uint8_t *buf)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t s[MAX_STR_SIZE];
 | 
			
		||||
    strftime(s, MAX_STR_SIZE, "[%H:%M:%S] ", get_time());
 | 
			
		||||
 | 
			
		||||
    wattron(window, COLOR_PAIR(BLUE));
 | 
			
		||||
    wprintw(window, "%s", s);
 | 
			
		||||
    wattroff(window,COLOR_PAIR(BLUE));
 | 
			
		||||
    strftime(buf, TIME_STR_SIZE, "[%H:%M:%S] ", get_time());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* XXX: FIX */
 | 
			
		||||
 
 | 
			
		||||
@@ -29,8 +29,8 @@ unsigned char *hex_string_to_bin(char hex_string[]);
 | 
			
		||||
/* get the current unix time */
 | 
			
		||||
uint64_t get_unix_time(void);
 | 
			
		||||
 | 
			
		||||
/* Prints the time to given window */
 | 
			
		||||
void print_time(WINDOW *window);
 | 
			
		||||
/*Puts the current time in buf in the format of [Hour:Min:Sec] */
 | 
			
		||||
void get_time_str(uint8_t *buf);
 | 
			
		||||
 | 
			
		||||
/* get the current local time */
 | 
			
		||||
struct tm *get_time(void);
 | 
			
		||||
@@ -67,7 +67,7 @@ int qsort_strcasecmp_hlpr(const void *nick1, const void *nick2);
 | 
			
		||||
      - cannot be empty
 | 
			
		||||
      - cannot start with a space
 | 
			
		||||
      - must not contain contiguous spaces */
 | 
			
		||||
bool valid_nick(uint8_t *nick);
 | 
			
		||||
int valid_nick(uint8_t *nick);
 | 
			
		||||
 | 
			
		||||
/* Moves the cursor to the end of the line in given window */
 | 
			
		||||
void mv_curs_end(WINDOW *w, size_t len, int max_y, int max_x);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										283
									
								
								src/prompt.c
									
									
									
									
									
								
							
							
						
						
									
										283
									
								
								src/prompt.c
									
									
									
									
									
								
							@@ -32,6 +32,8 @@
 | 
			
		||||
#include "execute.h"
 | 
			
		||||
#include "misc_tools.h"
 | 
			
		||||
#include "toxic_strings.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "line_info.h"
 | 
			
		||||
 | 
			
		||||
uint8_t pending_frnd_requests[MAX_FRIENDS_NUM][TOX_CLIENT_ID_SIZE] = {0};
 | 
			
		||||
uint8_t num_frnd_requests = 0;
 | 
			
		||||
@@ -64,25 +66,6 @@ const uint8_t glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
 | 
			
		||||
#endif /* _SUPPORT_AUDIO */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* prevents input string from eating system messages: call this prior to printing a prompt message
 | 
			
		||||
   TODO: This is only a partial fix */
 | 
			
		||||
void prep_prompt_win(void)
 | 
			
		||||
{
 | 
			
		||||
    PromptBuf *prt = prompt->promptbuf;
 | 
			
		||||
 | 
			
		||||
    if (prt->len <= 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    wprintw(prompt->window, "\n");
 | 
			
		||||
 | 
			
		||||
    if (!prt->at_bottom) {
 | 
			
		||||
        wmove(prompt->window, prt->orig_y - 1, X_OFST);
 | 
			
		||||
        ++prt->orig_y;
 | 
			
		||||
    } else {
 | 
			
		||||
        wmove(prompt->window, prt->orig_y - 2, X_OFST);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Updates own nick in prompt statusbar */
 | 
			
		||||
void prompt_update_nick(ToxWindow *prompt, uint8_t *nick, uint16_t len)
 | 
			
		||||
{
 | 
			
		||||
@@ -138,104 +121,113 @@ static int add_friend_request(uint8_t *public_key)
 | 
			
		||||
 | 
			
		||||
static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
{
 | 
			
		||||
    PromptBuf *prt = self->promptbuf;
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
 | 
			
		||||
    int x, y, y2, x2;
 | 
			
		||||
    getyx(self->window, y, x);
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
    getyx(ctx->history, y, x);
 | 
			
		||||
    getmaxyx(ctx->history, y2, x2);
 | 
			
		||||
 | 
			
		||||
    /* this is buggy */
 | 
			
		||||
    //if (key == T_KEY_ESC) {   /* ESC key: Toggle history scroll mode */
 | 
			
		||||
    //    bool scroll = ctx->hst->scroll_mode ? false : true;
 | 
			
		||||
    //    line_info_toggle_scroll(self, scroll);
 | 
			
		||||
    //}
 | 
			
		||||
 | 
			
		||||
    /* If we're in scroll mode ignore rest of function */
 | 
			
		||||
    if (ctx->hst->scroll_mode) {
 | 
			
		||||
        line_info_onKey(self, key);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* BACKSPACE key: Remove one character from line */
 | 
			
		||||
    if (key == 0x107 || key == 0x8 || key == 0x7f) {
 | 
			
		||||
        if (prt->pos > 0) {
 | 
			
		||||
            del_char_buf_bck(prt->line, &prt->pos, &prt->len);
 | 
			
		||||
            wmove(self->window, y, x-1);    /* not necessary but fixes a display glitch */
 | 
			
		||||
            prt->scroll = false;
 | 
			
		||||
        if (ctx->pos > 0) {
 | 
			
		||||
            del_char_buf_bck(ctx->line, &ctx->pos, &ctx->len);
 | 
			
		||||
            wmove(ctx->history, y, x-1);    /* not necessary but fixes a display glitch */
 | 
			
		||||
        } else {
 | 
			
		||||
            beep();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (key == KEY_DC) {      /* DEL key: Remove character at pos */
 | 
			
		||||
        if (prt->pos != prt->len) {
 | 
			
		||||
            del_char_buf_frnt(prt->line, &prt->pos, &prt->len);
 | 
			
		||||
            prt->scroll = false;
 | 
			
		||||
        if (ctx->pos != ctx->len) {
 | 
			
		||||
            del_char_buf_frnt(ctx->line, &ctx->pos, &ctx->len);
 | 
			
		||||
        } else {
 | 
			
		||||
            beep();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (key == T_KEY_DISCARD) {    /* CTRL-U: Delete entire line behind pos */
 | 
			
		||||
        if (prt->pos > 0) {
 | 
			
		||||
            wmove(self->window, prt->orig_y, X_OFST);
 | 
			
		||||
            wclrtobot(self->window);
 | 
			
		||||
            discard_buf(prt->line, &prt->pos, &prt->len);
 | 
			
		||||
        if (ctx->pos > 0) {
 | 
			
		||||
            wmove(ctx->history, ctx->orig_y, X_OFST);
 | 
			
		||||
            wclrtobot(ctx->history);
 | 
			
		||||
            discard_buf(ctx->line, &ctx->pos, &ctx->len);
 | 
			
		||||
        } else {
 | 
			
		||||
            beep();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (key == T_KEY_KILL) {    /* CTRL-K: Delete entire line in front of pos */
 | 
			
		||||
        if (prt->len != prt->pos)
 | 
			
		||||
            kill_buf(prt->line, &prt->pos, &prt->len);
 | 
			
		||||
        if (ctx->len != ctx->pos)
 | 
			
		||||
            kill_buf(ctx->line, &ctx->pos, &ctx->len);
 | 
			
		||||
        else
 | 
			
		||||
            beep();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (key == KEY_HOME || key == T_KEY_C_A) {  /* HOME/C-a key: Move cursor to start of line */
 | 
			
		||||
        if (prt->pos != 0)
 | 
			
		||||
            prt->pos = 0;
 | 
			
		||||
        if (ctx->pos != 0)
 | 
			
		||||
            ctx->pos = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (key == KEY_END || key == T_KEY_C_E) {   /* END/C-e key: move cursor to end of line */
 | 
			
		||||
        if (prt->pos != prt->len)
 | 
			
		||||
            prt->pos = prt->len;
 | 
			
		||||
        if (ctx->pos != ctx->len)
 | 
			
		||||
            ctx->pos = ctx->len;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (key == KEY_LEFT) {
 | 
			
		||||
        if (prt->pos > 0)
 | 
			
		||||
            --prt->pos;
 | 
			
		||||
        if (ctx->pos > 0)
 | 
			
		||||
            --ctx->pos;
 | 
			
		||||
        else
 | 
			
		||||
            beep();
 | 
			
		||||
    } 
 | 
			
		||||
 | 
			
		||||
    else if (key == KEY_RIGHT) {
 | 
			
		||||
        if (prt->pos < prt->len)
 | 
			
		||||
            ++prt->pos;
 | 
			
		||||
        if (ctx->pos < ctx->len)
 | 
			
		||||
            ++ctx->pos;
 | 
			
		||||
        else 
 | 
			
		||||
            beep();
 | 
			
		||||
    } 
 | 
			
		||||
 | 
			
		||||
    else if (key == KEY_UP) {     /* fetches previous item in history */
 | 
			
		||||
        wmove(self->window, prt->orig_y, X_OFST);
 | 
			
		||||
        fetch_hist_item(prt->line, &prt->pos, &prt->len, prt->ln_history, prt->hst_tot,
 | 
			
		||||
                        &prt->hst_pos, LN_HIST_MV_UP);
 | 
			
		||||
        wmove(ctx->history, ctx->orig_y, X_OFST);
 | 
			
		||||
        fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
 | 
			
		||||
                        &ctx->hst_pos, MOVE_UP);
 | 
			
		||||
 | 
			
		||||
        /* adjust line y origin appropriately when window scrolls down */
 | 
			
		||||
        if (prt->at_bottom && prt->len >= x2 - X_OFST) {
 | 
			
		||||
            int px2 = prt->len >= x2 ? x2 : x2 - X_OFST;
 | 
			
		||||
        if (ctx->at_bottom && ctx->len >= x2 - X_OFST) {
 | 
			
		||||
            int px2 = ctx->len >= x2 ? x2 : x2 - X_OFST;
 | 
			
		||||
            int p_ofst = px2 != x2 ? 0 : X_OFST;
 | 
			
		||||
 | 
			
		||||
            if (px2 <= 0)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            int k = prt->orig_y + ((prt->len + p_ofst) / px2);
 | 
			
		||||
            int k = ctx->orig_y + ((ctx->len + p_ofst) / px2);
 | 
			
		||||
 | 
			
		||||
            if (k >= y2) {
 | 
			
		||||
                wprintw(self->window, "\n");
 | 
			
		||||
                --prt->orig_y;
 | 
			
		||||
                --ctx->orig_y;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (key == KEY_DOWN) {    /* fetches next item in history */
 | 
			
		||||
        wmove(self->window, prt->orig_y, X_OFST);
 | 
			
		||||
        fetch_hist_item(prt->line, &prt->pos, &prt->len, prt->ln_history, prt->hst_tot,
 | 
			
		||||
                        &prt->hst_pos, LN_HIST_MV_DWN);
 | 
			
		||||
        wmove(ctx->history, ctx->orig_y, X_OFST);
 | 
			
		||||
        fetch_hist_item(ctx->line, &ctx->pos, &ctx->len, ctx->ln_history, ctx->hst_tot,
 | 
			
		||||
                        &ctx->hst_pos, MOVE_DOWN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    else if (key == '\t') {    /* TAB key: completes command */
 | 
			
		||||
        if (prt->len > 1 && prt->line[0] == '/') {
 | 
			
		||||
            if (complete_line(prt->line, &prt->pos, &prt->len, glob_cmd_list, AC_NUM_GLOB_COMMANDS,
 | 
			
		||||
        if (ctx->len > 1 && ctx->line[0] == '/') {
 | 
			
		||||
            if (complete_line(ctx->line, &ctx->pos, &ctx->len, glob_cmd_list, AC_NUM_GLOB_COMMANDS,
 | 
			
		||||
                              MAX_CMDNAME_SIZE) == -1) 
 | 
			
		||||
                beep();
 | 
			
		||||
        } else {
 | 
			
		||||
@@ -250,39 +242,42 @@ static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key)
 | 
			
		||||
    if (isprint(key))
 | 
			
		||||
#endif
 | 
			
		||||
    {
 | 
			
		||||
        if (prt->len < (MAX_STR_SIZE-1)) {
 | 
			
		||||
            add_char_to_buf(prt->line, &prt->pos, &prt->len, key);
 | 
			
		||||
            prt->scroll = true;
 | 
			
		||||
        if (ctx->len < (MAX_STR_SIZE-1)) {
 | 
			
		||||
            add_char_to_buf(ctx->line, &ctx->pos, &ctx->len, key);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /* RETURN key: execute command */
 | 
			
		||||
    else if (key == '\n') {
 | 
			
		||||
        wprintw(self->window, "\n");
 | 
			
		||||
        uint8_t line[MAX_STR_SIZE];
 | 
			
		||||
        wprintw(ctx->history, "\n");
 | 
			
		||||
        uint8_t line[MAX_STR_SIZE] = {0};
 | 
			
		||||
 | 
			
		||||
        if (wcs_to_mbs_buf(line, prt->line, MAX_STR_SIZE) == -1)
 | 
			
		||||
        if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
 | 
			
		||||
            memset(&line, 0, sizeof(line));
 | 
			
		||||
 | 
			
		||||
        if (!string_is_empty(line))
 | 
			
		||||
            add_line_to_hist(prt->line, prt->len, prt->ln_history, &prt->hst_tot, &prt->hst_pos);
 | 
			
		||||
            add_line_to_hist(ctx->line, ctx->len, ctx->ln_history, &ctx->hst_tot, &ctx->hst_pos);
 | 
			
		||||
 | 
			
		||||
        execute(self->window, self, m, line, GLOBAL_COMMAND_MODE);
 | 
			
		||||
        reset_buf(prt->line, &prt->pos, &prt->len);
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, line, PROMPT, 0, 0);
 | 
			
		||||
        execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE);
 | 
			
		||||
        reset_buf(ctx->line, &ctx->pos, &ctx->len);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void prompt_onDraw(ToxWindow *self, Tox *m)
 | 
			
		||||
{
 | 
			
		||||
    PromptBuf *prt = self->promptbuf;
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
 | 
			
		||||
    curs_set(1);
 | 
			
		||||
    int x, y, x2, y2;
 | 
			
		||||
    getyx(self->window, y, x);
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
    wclrtobot(self->window);
 | 
			
		||||
    getyx(ctx->history, y, x);
 | 
			
		||||
    getmaxyx(ctx->history, y2, x2);
 | 
			
		||||
 | 
			
		||||
    if (!ctx->hst->scroll_mode)
 | 
			
		||||
        curs_set(1);
 | 
			
		||||
 | 
			
		||||
    line_info_print(self);
 | 
			
		||||
 | 
			
		||||
    /* if len is >= screen width offset max x by X_OFST to account for prompt char */
 | 
			
		||||
    int px2 = prt->len >= x2 ? x2 : x2 - X_OFST;
 | 
			
		||||
    int px2 = ctx->len >= x2 ? x2 : x2 - X_OFST;
 | 
			
		||||
 | 
			
		||||
    if (px2 <= 0)
 | 
			
		||||
        return;
 | 
			
		||||
@@ -290,33 +285,31 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
 | 
			
		||||
    /* len offset to account for prompt char (0 if len is < width of screen) */
 | 
			
		||||
    int p_ofst = px2 != x2 ? 0 : X_OFST;
 | 
			
		||||
 | 
			
		||||
    if (prt->len > 0) {
 | 
			
		||||
    if (ctx->len > 0) {
 | 
			
		||||
        uint8_t line[MAX_STR_SIZE];
 | 
			
		||||
 | 
			
		||||
        if (wcs_to_mbs_buf(line, prt->line, MAX_STR_SIZE) == -1)
 | 
			
		||||
            reset_buf(prt->line, &prt->pos, &prt->len);
 | 
			
		||||
        if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1)
 | 
			
		||||
            reset_buf(ctx->line, &ctx->pos, &ctx->len);
 | 
			
		||||
        else
 | 
			
		||||
            mvwprintw(self->window, prt->orig_y, X_OFST, line);
 | 
			
		||||
            mvwprintw(ctx->history, ctx->orig_y, X_OFST, line);
 | 
			
		||||
 | 
			
		||||
        int k = prt->orig_y + ((prt->len + p_ofst) / px2);
 | 
			
		||||
        int k = ctx->orig_y + ((ctx->len + p_ofst) / px2);
 | 
			
		||||
 | 
			
		||||
        prt->at_bottom = k == y2 - 1;
 | 
			
		||||
        ctx->at_bottom = k == y2 - 1;
 | 
			
		||||
        bool botm = k == y2;
 | 
			
		||||
        bool edge = (prt->len + p_ofst) % px2 == 0;
 | 
			
		||||
        bool edge = (ctx->len + p_ofst) % px2 == 0;
 | 
			
		||||
 | 
			
		||||
        /* move point of line origin up when input scrolls screen down */
 | 
			
		||||
        if (prt->scroll && edge && botm) {
 | 
			
		||||
            --prt->orig_y;
 | 
			
		||||
            prt->scroll = false;
 | 
			
		||||
        }
 | 
			
		||||
        if (edge && botm)
 | 
			
		||||
            --ctx->orig_y;
 | 
			
		||||
 | 
			
		||||
    } else {    /* Mark point of origin for new line */
 | 
			
		||||
        prt->orig_y = y;    
 | 
			
		||||
        ctx->orig_y = y;    
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wattron(self->window, COLOR_PAIR(GREEN));
 | 
			
		||||
    mvwprintw(self->window, prt->orig_y, 0, "$ ");
 | 
			
		||||
    wattroff(self->window, COLOR_PAIR(GREEN));
 | 
			
		||||
    wattron(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
    mvwprintw(ctx->history, ctx->orig_y, 0, "$ ");
 | 
			
		||||
    wattroff(ctx->history, COLOR_PAIR(GREEN));
 | 
			
		||||
 | 
			
		||||
    StatusBar *statusbar = self->stb;
 | 
			
		||||
    werase(statusbar->topline);
 | 
			
		||||
@@ -362,40 +355,18 @@ static void prompt_onDraw(ToxWindow *self, Tox *m)
 | 
			
		||||
    if (statusbar->statusmsg[0])
 | 
			
		||||
        wprintw(statusbar->topline, " - %s", statusbar->statusmsg);
 | 
			
		||||
 | 
			
		||||
    wprintw(statusbar->topline, "\n");
 | 
			
		||||
 | 
			
		||||
    /* put cursor back in correct spot */
 | 
			
		||||
    int y_m = prt->orig_y + ((prt->pos + p_ofst) / px2);
 | 
			
		||||
    int x_m = (prt->pos + X_OFST) % x2;
 | 
			
		||||
    int y_m = ctx->orig_y + ((ctx->pos + p_ofst) / px2);
 | 
			
		||||
    int x_m = (ctx->pos + X_OFST) % x2;
 | 
			
		||||
    wmove(self->window, y_m, x_m);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void prompt_onInit(ToxWindow *self, Tox *m)
 | 
			
		||||
{
 | 
			
		||||
    scrollok(self->window, true);
 | 
			
		||||
    PromptBuf *prt = self->promptbuf;
 | 
			
		||||
 | 
			
		||||
    prt->log = malloc(sizeof(struct chatlog));
 | 
			
		||||
 | 
			
		||||
    if (prt->log == NULL) {
 | 
			
		||||
        endwin();
 | 
			
		||||
        fprintf(stderr, "malloc() failed. Aborting...\n");
 | 
			
		||||
        exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(prt->log, 0, sizeof(struct chatlog));
 | 
			
		||||
 | 
			
		||||
    execute(self->window, self, m, "/help", GLOBAL_COMMAND_MODE);
 | 
			
		||||
    wclrtoeol(self->window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum , uint8_t status)
 | 
			
		||||
{
 | 
			
		||||
    if (friendnum < 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    PromptBuf *prt = self->promptbuf;
 | 
			
		||||
    prep_prompt_win();
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
 | 
			
		||||
    uint8_t nick[TOX_MAX_NAME_LENGTH] = {'\0'};
 | 
			
		||||
 | 
			
		||||
@@ -405,32 +376,19 @@ static void prompt_onConnectionChange(ToxWindow *self, Tox *m, int32_t friendnum
 | 
			
		||||
    if (!nick[0])
 | 
			
		||||
        snprintf(nick, sizeof(nick), "%s", UNKNOWN_NAME);
 | 
			
		||||
 | 
			
		||||
    wprintw(self->window, "\n");
 | 
			
		||||
    print_time(self->window);
 | 
			
		||||
 | 
			
		||||
    const uint8_t *msg;
 | 
			
		||||
    uint8_t timefrmt[TIME_STR_SIZE];
 | 
			
		||||
    get_time_str(timefrmt);
 | 
			
		||||
    uint8_t *msg;
 | 
			
		||||
 | 
			
		||||
    if (status == 1) {
 | 
			
		||||
        msg = "has come online";
 | 
			
		||||
        wattron(self->window, COLOR_PAIR(GREEN));
 | 
			
		||||
        wattron(self->window, A_BOLD);
 | 
			
		||||
        wprintw(self->window, "* %s ", nick);
 | 
			
		||||
        wattroff(self->window, A_BOLD);
 | 
			
		||||
        wprintw(self->window, "%s\n", msg);
 | 
			
		||||
        wattroff(self->window, COLOR_PAIR(GREEN));
 | 
			
		||||
 | 
			
		||||
        write_to_log(msg, nick, prt->log, true);
 | 
			
		||||
        line_info_add(self, timefrmt, nick, NULL, msg, CONNECTION, 0, GREEN);
 | 
			
		||||
        write_to_log(msg, nick, ctx->log, true);
 | 
			
		||||
        alert_window(self, WINDOW_ALERT_2, false);
 | 
			
		||||
    } else {
 | 
			
		||||
        msg = "has gone offline";
 | 
			
		||||
        wattron(self->window, COLOR_PAIR(RED));
 | 
			
		||||
        wattron(self->window, A_BOLD);
 | 
			
		||||
        wprintw(self->window, "* %s ", nick);
 | 
			
		||||
        wattroff(self->window, A_BOLD);
 | 
			
		||||
        wprintw(self->window, "%s\n", msg);
 | 
			
		||||
        wattroff(self->window, COLOR_PAIR(RED));
 | 
			
		||||
 | 
			
		||||
        write_to_log(msg, nick, prt->log, true);
 | 
			
		||||
        line_info_add(self, timefrmt, nick, NULL, msg, CONNECTION, 0, RED);
 | 
			
		||||
        write_to_log(msg, nick, ctx->log, true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -438,34 +396,34 @@ static void prompt_onFriendRequest(ToxWindow *self, Tox *m, uint8_t *key, uint8_
 | 
			
		||||
{
 | 
			
		||||
    /* make sure message data is null-terminated */
 | 
			
		||||
    data[length - 1] = 0;
 | 
			
		||||
    PromptBuf *prt = self->promptbuf;
 | 
			
		||||
    prep_prompt_win();
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
 | 
			
		||||
    wprintw(self->window, "\n");
 | 
			
		||||
    print_time(self->window);
 | 
			
		||||
    uint8_t timefrmt[TIME_STR_SIZE];
 | 
			
		||||
    get_time_str(timefrmt);
 | 
			
		||||
 | 
			
		||||
    uint8_t msg[MAX_STR_SIZE];
 | 
			
		||||
    snprintf(msg, sizeof(msg), "Friend request with the message '%s'\n", data);
 | 
			
		||||
    wprintw(self->window, "%s", msg);
 | 
			
		||||
    write_to_log(msg, "", prt->log, true);
 | 
			
		||||
    snprintf(msg, sizeof(msg), "Friend request with the message '%s'", data);
 | 
			
		||||
    line_info_add(self, timefrmt, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
    write_to_log(msg, "", ctx->log, true);
 | 
			
		||||
 | 
			
		||||
    int n = add_friend_request(key);
 | 
			
		||||
 | 
			
		||||
    if (n == -1) {
 | 
			
		||||
        const uint8_t *errmsg = "Friend request queue is full. Discarding request.\n";
 | 
			
		||||
        wprintw(self->window, "%s", errmsg);
 | 
			
		||||
        write_to_log(errmsg, "", prt->log, true);
 | 
			
		||||
        uint8_t *errmsg = "Friend request queue is full. Discarding request.";
 | 
			
		||||
        line_info_add(self, NULL, NULL, NULL, errmsg, SYS_MSG, 0, 0);
 | 
			
		||||
        write_to_log(errmsg, "", ctx->log, true);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wprintw(self->window, "Type \"/accept %d\" to accept it.\n", n);
 | 
			
		||||
    snprintf(msg, sizeof(msg), "Type \"/accept %d\" to accept it.", n);
 | 
			
		||||
    line_info_add(self, NULL, NULL, NULL, msg, SYS_MSG, 0, 0);
 | 
			
		||||
    alert_window(self, WINDOW_ALERT_1, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void prompt_init_statusbar(ToxWindow *self, Tox *m)
 | 
			
		||||
{
 | 
			
		||||
    int x, y;
 | 
			
		||||
    getmaxyx(self->window, y, x);
 | 
			
		||||
    int x2, y2;
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
 | 
			
		||||
    /* Init statusbar info */
 | 
			
		||||
    StatusBar *statusbar = self->stb;
 | 
			
		||||
@@ -495,7 +453,36 @@ void prompt_init_statusbar(ToxWindow *self, Tox *m)
 | 
			
		||||
    prompt_update_status(prompt, status);
 | 
			
		||||
 | 
			
		||||
    /* Init statusbar subwindow */
 | 
			
		||||
    statusbar->topline = subwin(self->window, 2, x, 0, 0);
 | 
			
		||||
    statusbar->topline = subwin(self->window, 2, x2, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void prompt_onInit(ToxWindow *self, Tox *m)
 | 
			
		||||
{
 | 
			
		||||
    ChatContext *ctx = self->chatwin;
 | 
			
		||||
 | 
			
		||||
    curs_set(1);
 | 
			
		||||
    int y2, x2;
 | 
			
		||||
    getmaxyx(self->window, y2, x2);
 | 
			
		||||
 | 
			
		||||
    ctx->history = subwin(self->window, y2, x2, 0, 0);
 | 
			
		||||
    scrollok(ctx->history, 1);
 | 
			
		||||
 | 
			
		||||
    ctx->log = malloc(sizeof(struct chatlog));
 | 
			
		||||
    ctx->hst = malloc(sizeof(struct history));
 | 
			
		||||
 | 
			
		||||
    if (ctx->log == NULL || ctx->hst == NULL) {
 | 
			
		||||
        endwin();
 | 
			
		||||
        fprintf(stderr, "malloc() failed. Aborting...\n");
 | 
			
		||||
        exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(ctx->log, 0, sizeof(struct chatlog));
 | 
			
		||||
    memset(ctx->hst, 0, sizeof(struct history));
 | 
			
		||||
 | 
			
		||||
    line_info_init(ctx->hst);
 | 
			
		||||
    execute(ctx->history, self, m, "/help", GLOBAL_COMMAND_MODE);
 | 
			
		||||
 | 
			
		||||
    wmove(ctx->history, y2-1, 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ToxWindow new_prompt(void)
 | 
			
		||||
@@ -514,11 +501,11 @@ ToxWindow new_prompt(void)
 | 
			
		||||
 | 
			
		||||
    strcpy(ret.name, "prompt");
 | 
			
		||||
 | 
			
		||||
    PromptBuf *promptbuf = calloc(1, sizeof(PromptBuf));
 | 
			
		||||
    ChatContext *chatwin = calloc(1, sizeof(ChatContext));
 | 
			
		||||
    StatusBar *stb = calloc(1, sizeof(StatusBar));
 | 
			
		||||
 | 
			
		||||
    if (stb != NULL && promptbuf != NULL) {
 | 
			
		||||
        ret.promptbuf = promptbuf;
 | 
			
		||||
    if (stb != NULL && chatwin != NULL) {
 | 
			
		||||
        ret.chatwin = chatwin;
 | 
			
		||||
        ret.stb = stb;
 | 
			
		||||
    } else {
 | 
			
		||||
        endwin();
 | 
			
		||||
 
 | 
			
		||||
@@ -148,7 +148,7 @@ void add_line_to_hist(const wchar_t *buf, size_t len, wchar_t (*hst)[MAX_STR_SIZ
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
    if (key_dir == LN_HIST_MV_UP) {
 | 
			
		||||
    if (key_dir == MOVE_UP) {
 | 
			
		||||
        if (--(*hst_pos) < 0) {
 | 
			
		||||
            *hst_pos = 0;
 | 
			
		||||
            beep();
 | 
			
		||||
 
 | 
			
		||||
@@ -48,11 +48,6 @@ void reset_buf(wchar_t *buf, size_t *pos, size_t *len);
 | 
			
		||||
   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);
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    LN_HIST_MV_UP,
 | 
			
		||||
    LN_HIST_MV_DWN,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* 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, 
 | 
			
		||||
                      int *hst_pos);
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,7 @@
 | 
			
		||||
#define CURS_Y_OFFSET 3    /* y-axis cursor offset for chat contexts */
 | 
			
		||||
#define CHATBOX_HEIGHT 4
 | 
			
		||||
#define KEY_IDENT_DIGITS 2    /* number of hex digits to display for the pub-key based identifier */
 | 
			
		||||
#define TIME_STR_SIZE 16
 | 
			
		||||
 | 
			
		||||
#define EXIT_SUCCESS 0
 | 
			
		||||
#define EXIT_FAILURE 1
 | 
			
		||||
@@ -60,6 +61,7 @@
 | 
			
		||||
#define T_KEY_PREV       0x0F     /* ctrl-o */
 | 
			
		||||
#define T_KEY_C_E        0x05     /* ctrl-e */
 | 
			
		||||
#define T_KEY_C_A        0x01     /* ctrl-a */
 | 
			
		||||
#define T_KEY_ESC        0x1B     /* ESC key */
 | 
			
		||||
 | 
			
		||||
/* Curses foreground colours (background is black) */
 | 
			
		||||
enum {
 | 
			
		||||
@@ -80,6 +82,11 @@ enum {
 | 
			
		||||
    WINDOW_ALERT_2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    MOVE_UP,
 | 
			
		||||
    MOVE_DOWN,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Fixes text color problem on some terminals. 
 | 
			
		||||
   Uncomment if necessary */
 | 
			
		||||
/* #define URXVT_FIX */
 | 
			
		||||
@@ -141,7 +148,6 @@ struct ToxWindow {
 | 
			
		||||
    bool alert2;
 | 
			
		||||
 | 
			
		||||
    ChatContext *chatwin;
 | 
			
		||||
    PromptBuf *promptbuf;
 | 
			
		||||
    StatusBar *stb;
 | 
			
		||||
 | 
			
		||||
    WINDOW *popup;
 | 
			
		||||
@@ -159,15 +165,6 @@ struct StatusBar {
 | 
			
		||||
    bool is_online;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define LOG_FLUSH_LIMIT 2  /* limits calls to fflush(logfile) to a max of one per LOG_FLUSH_LIMIT seconds */
 | 
			
		||||
 | 
			
		||||
struct chatlog {
 | 
			
		||||
    FILE *file;
 | 
			
		||||
    uint64_t lastwrite;
 | 
			
		||||
    int pos;
 | 
			
		||||
    bool log_on;    /* specific to current chat window */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define MAX_LINE_HIST 128
 | 
			
		||||
 | 
			
		||||
/* chat and groupchat window/buffer holder */
 | 
			
		||||
@@ -176,35 +173,22 @@ struct ChatContext {
 | 
			
		||||
    size_t pos;
 | 
			
		||||
    size_t len;
 | 
			
		||||
 | 
			
		||||
    wchar_t ln_history[MAX_LINE_HIST][MAX_STR_SIZE];
 | 
			
		||||
    wchar_t ln_history[MAX_LINE_HIST][MAX_STR_SIZE];  /* history for input lines/commands */
 | 
			
		||||
    int hst_pos;
 | 
			
		||||
    int hst_tot;
 | 
			
		||||
 | 
			
		||||
    uint8_t self_is_typing;
 | 
			
		||||
 | 
			
		||||
    struct history *hst;
 | 
			
		||||
    struct chatlog *log;
 | 
			
		||||
 | 
			
		||||
    uint8_t self_is_typing;
 | 
			
		||||
 | 
			
		||||
    WINDOW *history;
 | 
			
		||||
    WINDOW *linewin;
 | 
			
		||||
    WINDOW *sidebar;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* prompt window/buffer holder */
 | 
			
		||||
struct PromptBuf {
 | 
			
		||||
    wchar_t line[MAX_STR_SIZE];
 | 
			
		||||
    size_t pos;
 | 
			
		||||
    size_t len;
 | 
			
		||||
 | 
			
		||||
    /* specific for prompt */
 | 
			
		||||
    bool at_bottom;    /* true if line end is at bottom of window */
 | 
			
		||||
    int orig_y;        /* y axis point of line origin */
 | 
			
		||||
    bool scroll;       /* used for prompt window hack to determine when to scroll down */
 | 
			
		||||
 | 
			
		||||
    wchar_t ln_history[MAX_LINE_HIST][MAX_STR_SIZE];
 | 
			
		||||
    int hst_pos;
 | 
			
		||||
    int hst_tot;
 | 
			
		||||
 | 
			
		||||
    struct chatlog *log;
 | 
			
		||||
    WINDOW *linewin;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Start file transfer code */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user