Large diffs are not rendered by default.

@@ -76,6 +76,11 @@ uint32_t ft_send_file(Tox *tox, uint32_t friend_number, FILE *file, uint8_t *nam

uint32_t ft_send_data(Tox *tox, uint32_t friend_number, uint8_t *data, size_t size, uint8_t *name, size_t name_length);

/** Sets the UI pointer to the File Transfer Message pointer.
*
* This is non robust and could use some LTC */
bool ft_set_ui_data(uint32_t friend_number, uint32_t file_number, MSG_HEADER *ui_data);

int utox_file_start_write(uint32_t friend_number, uint32_t file_number, void *file, bool is_file);

void utox_set_callbacks_file_transfer(Tox *tox);
@@ -1,7 +1,7 @@
#include "filesys.h"

#include "main_native.h"
#include "logging_native.h"
#include "debug.h"

#include <stdlib.h>

@@ -14,19 +14,16 @@ bool utox_move_file(const uint8_t *current_name, const uint8_t *new_name) {
}

void *file_raw(char *path, uint32_t *size) {
FILE *file;
char *data;
int len;

file = fopen(path, "rb");
FILE *file = fopen(path, "rb");
if (!file) {
// debug("File not found (%s)\n", path);
// LOG_TRACE(__FILE__, "File not found (%s)" , path);
return NULL;
}

fseek(file, 0, SEEK_END);
len = ftell(file);
data = malloc(len);
int len = ftell(file);

char *data = calloc(1, len);
if (!data) {
fclose(file);
return NULL;
@@ -35,18 +32,17 @@ void *file_raw(char *path, uint32_t *size) {
fseek(file, 0, SEEK_SET);

if (fread(data, len, 1, file) != 1) {
debug("Read error (%s)\n", path);
LOG_TRACE(__FILE__, "Read error (%s)" , path);
fclose(file);
free(data);
return NULL;
}

fclose(file);

// debug("Read %u bytes (%s)\n", len, path);

if (size) {
*size = len;
}

return data;
}
@@ -1,10 +1,10 @@
#include "flist.h"

// FIXME: Separate from UI or include in UI.
// TODO: Separate from UI or include in UI.

#include "friend.h"
#include "groups.h"
#include "logging_native.h"
#include "debug.h"
#include "macros.h"
#include "main_native.h"
#include "self.h"
@@ -14,15 +14,22 @@
#include "tox.h"
#include "utox.h"

#include "ui/buttons.h"
#include "ui/contextmenu.h"
#include "ui/draw.h"
#include "ui/dropdowns.h"
#include "ui/edits.h"
#include "ui/dropdown.h"
#include "ui/edit.h"
#include "ui/button.h"
#include "ui/scrollable.h"
#include "ui/svg.h"
#include "ui/switch.h"
#include "ui/tooltip.h"

#include "layout/background.h"
#include "layout/friend.h"
#include "layout/group.h"
#include "layout/settings.h"
#include "layout/sidebar.h"

#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -41,8 +48,8 @@ static ITEM item_add, item_settings, item_transfer;
static ITEM item[1024]; /* TODO MAGIC NUMBER*/
static uint32_t itemcount;

static uint32_t shown_list[1024]; // list of chats actually shown in the GUI after filtering(actually indices pointing
// to chats in the chats array)
static uint32_t shown_list[1024]; // list of chats actually shown in the GUI after filtering
// (actually indices pointing to chats in the chats array)
static uint32_t showncount;

// search and filter stuff
@@ -211,7 +218,7 @@ static void drawitem(ITEM *i, int UNUSED(x), int y) {
}

default: {
debug_error("Trying to draw an item that we shouldn't be drawing!\n");
LOG_ERR("F-List", "Trying to draw an item that we shouldn't be drawing!");
break;
}
}
@@ -341,22 +348,23 @@ static void page_close(ITEM *i) {
current_width = f->msg.width;

free(f->typed);
f->typed_length = edit_msg.length;
f->typed = calloc(1, edit_msg.length);
memcpy(f->typed, edit_msg.data, edit_msg.length);
f->typed_length = edit_chat_msg_friend.length;
f->typed = calloc(1, edit_chat_msg_friend.length);
memcpy(f->typed, edit_chat_msg_friend.data, edit_chat_msg_friend.length);

f->msg.scroll = messages_friend.content_scroll->d;

f->edit_history = edit_msg.history;
f->edit_history_cur = edit_msg.history_cur;
f->edit_history_length = edit_msg.history_length;

panel_chat.disabled = 1;
panel_friend.disabled = 1;
panel_friend_chat.disabled = 1;
panel_friend_video.disabled = 1;
panel_friend_settings.disabled = 1;
settings.inline_video = 1;
f->edit_history = edit_chat_msg_friend.history;
f->edit_history_cur = edit_chat_msg_friend.history_cur;
f->edit_history_length = edit_chat_msg_friend.history_length;

panel_chat.disabled = true;
panel_friend.disabled = true;
panel_friend_chat.disabled = true;
panel_friend_video.disabled = true;
panel_friend_settings.disabled = true;
panel_friend_confirm_deletion.disabled = true;
settings.inline_video = true;
break;
}

@@ -372,15 +380,15 @@ static void page_close(ITEM *i) {
current_width = g->msg.width;

free(g->typed);
g->typed_length = edit_msg_group.length;
g->typed = calloc(1, edit_msg_group.length);
memcpy(g->typed, edit_msg_group.data, edit_msg_group.length);
g->typed_length = edit_chat_msg_group.length;
g->typed = calloc(1, edit_chat_msg_group.length);
memcpy(g->typed, edit_chat_msg_group.data, edit_chat_msg_group.length);

g->msg.scroll = messages_group.content_scroll->d;

g->edit_history = edit_msg_group.history;
g->edit_history_cur = edit_msg_group.history_cur;
g->edit_history_length = edit_msg_group.history_length;
g->edit_history = edit_chat_msg_group.history;
g->edit_history_cur = edit_chat_msg_group.history_cur;
g->edit_history_length = edit_chat_msg_group.history_length;

panel_chat.disabled = 1;
panel_group.disabled = 1;
@@ -410,7 +418,7 @@ static void page_close(ITEM *i) {
}

default: {
debug_error("Trying to switch to an item that we shouldn't be selecting\n");
LOG_ERR("F-List", "Trying to switch to an item that we shouldn't be selecting");
break;
}
}
@@ -427,14 +435,14 @@ static void page_open(ITEM *i) {
case ITEM_FRIEND: {
FRIEND *f = i->data;

#ifdef UNITY
#ifdef UNITY
if (unity_running) {
mm_rm_entry(f->cid);
}
#endif
#endif

memcpy(edit_msg.data, f->typed, f->typed_length);
edit_msg.length = f->typed_length;
memcpy(edit_chat_msg_friend.data, f->typed, f->typed_length);
edit_chat_msg_friend.length = f->typed_length;

f->msg.width = current_width;
f->msg.id = f - friend;
@@ -452,10 +460,10 @@ static void page_open(ITEM *i) {
scrollbar_friend.content_height = f->msg.height;
messages_friend.content_scroll->d = f->msg.scroll;

edit_msg.history = f->edit_history;
edit_msg.history_cur = f->edit_history_cur;
edit_msg.history_length = f->edit_history_length;
edit_setfocus(&edit_msg);
edit_chat_msg_friend.history = f->edit_history;
edit_chat_msg_friend.history_cur = f->edit_history_cur;
edit_chat_msg_friend.history_length = f->edit_history_length;
edit_setfocus(&edit_chat_msg_friend);

panel_chat.disabled = 0;
panel_friend.disabled = 0;
@@ -468,8 +476,8 @@ static void page_open(ITEM *i) {
case ITEM_GROUP: {
GROUPCHAT *g = i->data;

memcpy(edit_msg_group.data, g->typed, g->typed_length);
edit_msg_group.length = g->typed_length;
memcpy(edit_chat_msg_group.data, g->typed, g->typed_length);
edit_chat_msg_group.length = g->typed_length;

g->msg.width = current_width;
g->msg.id = g - group;
@@ -486,11 +494,11 @@ static void page_open(ITEM *i) {

messages_group.content_scroll->content_height = g->msg.height;
messages_group.content_scroll->d = g->msg.scroll;
edit_setfocus(&edit_msg_group);
edit_setfocus(&edit_chat_msg_group);

edit_msg_group.history = g->edit_history;
edit_msg_group.history_cur = g->edit_history_cur;
edit_msg_group.history_length = g->edit_history_length;
edit_chat_msg_group.history = g->edit_history;
edit_chat_msg_group.history_cur = g->edit_history_cur;
edit_chat_msg_group.history_length = g->edit_history_length;

panel_chat.disabled = 0;
panel_group.disabled = 0;
@@ -513,7 +521,7 @@ static void page_open(ITEM *i) {
button_add_new_contact.disabled = 1;
panel_overhead.disabled = 0;
panel_add_friend.disabled = 0;
edit_setfocus(&edit_add_id);
edit_setfocus(&edit_add_new_friend_id);
break;
}

@@ -523,7 +531,7 @@ static void page_open(ITEM *i) {
}

default: {
debug_error("Trying to switch to an item that we shouldn't be selecting\n");
LOG_ERR("F-List", "Trying to switch to an item that we shouldn't be selecting.");
break;
}
}
@@ -813,6 +821,24 @@ ITEM *flist_get_selected(void) {
return selected_item;
}

FRIEND *flist_get_friend(void) {
if (flist_get_type() == ITEM_FRIEND) {
return selected_item->data;
}
return NULL;
}

GROUPCHAT *flist_get_groupchat(void) {
if (flist_get_type() == ITEM_GROUP) {
return selected_item->data;
}
return NULL;
}

ITEM_TYPE flist_get_type(void) {
return selected_item->item;
}

/******************************************************************************
****** UI functions ******
******************************************************************************/
@@ -923,7 +949,7 @@ static void flist_init_friend_settings_page(void) {
maybe_i18nal_string_set_plain(&edit_friend_alias.empty_str, f->name, f->name_length);
edit_setstr(&edit_friend_alias, f->alias, f->alias_length);

dropdown_friend_autoaccept_ft.over = dropdown_friend_autoaccept_ft.selected = f->ft_autoaccept;
switch_friend_autoaccept_ft.switch_on = f->ft_autoaccept;
}

static void flist_init_group_settings_page(void) {
@@ -967,7 +993,8 @@ static void contextmenu_friend(uint8_t rcase) {
}
case 3: {
/* Should be: delete friend */
flist_delete_rmouse_item();
panel_friend_chat.disabled = true;
panel_friend_confirm_deletion.disabled = false;
}
}
}
@@ -992,7 +1019,7 @@ static void contextmenu_list_onselect(uint8_t i) {
char str[g->name_length + 7];
strcpy(str, "/topic ");
memcpy(str + 7, g->name, g->name_length);
edit_setfocus(&edit_msg_group);
edit_setfocus(&edit_chat_msg_group);
edit_paste((char *)str, sizeof(str), 0);
} else if (i == 2 && g->av_group) {
g->muted = !g->muted;
@@ -1017,7 +1044,7 @@ static void contextmenu_list_onselect(uint8_t i) {
}
}
default: {
debug("blerg\n");
LOG_TRACE(__FILE__, "blerg" );
return;
}
}
@@ -1078,7 +1105,7 @@ bool flist_mright(void *UNUSED(n)) {
}

default: {
debug_error("MRIGHT on a flist entry that shouldn't exist!\n");
LOG_ERR("F-List", "MRIGHT on a flist entry that shouldn't exist!");
break;
}
}
@@ -50,7 +50,7 @@ void flist_addfriend2(FRIEND *f, FRIENDREQ *req);
void flist_addgroup(GROUPCHAT *g);
void flist_addfriendreq(FRIENDREQ *f);
void flist_deletesitem(void);
void flist_deleteright_mouse_item(void);
void flist_delete_rmouse_item(void);

void flist_selectchat(int index);
void flist_selectaddfriend(void);
@@ -68,6 +68,9 @@ void flist_dump_contacts(void);
void flist_reload_contacts(void);

ITEM *flist_get_selected(void);
FRIEND *flist_get_friend(void);
GROUPCHAT *flist_get_groupchat(void);
ITEM_TYPE flist_get_type(void);

/* UI functions */
void flist_draw(void *n, int x, int y, int width, int height);
@@ -1,21 +1,26 @@
#include "friend.h"

#include "chatlog.h"
#include "debug.h"
#include "dns.h"
#include "filesys.h"
#include "flist.h"
#include "logging_native.h"
#include "main_native.h"
#include "self.h"
#include "settings.h"
#include "text.h"
#include "tox.h"
#include "ui.h"
#include "utox.h"

#include "av/audio.h"
#include "ui/edits.h"
#include "ui/scrollable.h"

#include "layout/friend.h" // TODO, remove this and sent the name differently
// utox_friend_init()
#include "ui/edit.h" // friend_set_name()


#include "main.h" // addfriend_status

FRIEND* get_friend(uint32_t friend_number){
@@ -69,13 +74,13 @@ static void friend_meta_data_read(FRIEND *f) {
FILE *file = native_get_file(path, &size, UTOX_FILE_OPTS_READ);

if (!file) {
debug_notice("Meta Data not found (%s)\n", path);
LOG_TRACE("Friend", "Meta Data not found %s", path);
return;
}

FRIEND_META_DATA *metadata = calloc(1, sizeof(*metadata) + size);
if (metadata == NULL) {
debug("Metadata:\tCould not allocate memory for metadata.\n");
LOG_ERR("Metadata", "Could not allocate memory for metadata." );
fclose(file);
return;
}
@@ -84,13 +89,13 @@ static void friend_meta_data_read(FRIEND *f) {
fclose(file);

if (metadata->version != 0) {
debug_notice("Metadata:\tWARNING! This version of utox does not support this metadata file version.\n");
LOG_ERR("Metadata", "WARNING! This version of utox does not support this metadata file version." );
free(metadata);
return;
}

if (size < sizeof(*metadata)) {
debug_error("Metadata:\tMeta Data was incomplete\n");
LOG_ERR("Metadata", "Meta Data was incomplete");
free(metadata);
return;
}
@@ -200,8 +205,12 @@ void friend_setname(FRIEND *f, uint8_t *name, size_t length) {
f->name[f->name_length] = 0;

if (!f->alias_length) {
if (flist_get_selected()->item == ITEM_FRIEND) {
FRIEND *selected = flist_get_selected()->data;
if (flist_get_type()== ITEM_FRIEND) {
FRIEND *selected = flist_get_friend();
if (!selected) {
LOG_ERR(__FILE__, "Unable to get selected friend.");
return;
}
if (selected && f->number == selected->number) {
maybe_i18nal_string_set_plain(&edit_friend_alias.empty_str, f->name, f->name_length);
}
@@ -213,9 +222,9 @@ void friend_setname(FRIEND *f, uint8_t *name, size_t length) {

void friend_set_alias(FRIEND *f, uint8_t *alias, uint16_t length) {
if (alias && length > 0) {
debug("New Alias set for friend %s\n", f->name);
LOG_TRACE("Friend", "New Alias set for friend %s" , f->name);
} else {
debug("Alias for friend %s unset\n", f->name);
LOG_TRACE("Friend", "Alias for friend %s unset" , f->name);
}

free(f->alias);
@@ -254,10 +263,10 @@ void friend_notify_msg(FRIEND *f, const char *msg, size_t msg_length) {
size_t title_length = snprintf((char *)title, UTOX_FRIEND_NAME_LENGTH(f) + 25, "uTox new message from %.*s",
(int)UTOX_FRIEND_NAME_LENGTH(f), UTOX_FRIEND_NAME(f));

postmessage_utox(FRIEND_MESSAGE, 0, 0, NULL);
postmessage_utox(FRIEND_MESSAGE, f->number, 0, NULL);
notify(title, title_length, msg, msg_length, f, 0);

if (flist_get_selected()->data != f) {
if (flist_get_friend() != f) {
f->unread_msg = 1;
postmessage_audio(UTOXAUDIO_PLAY_NOTIFICATION, NOTIFY_TONE_FRIEND_NEW_MSG, 0, NULL);
}
@@ -76,13 +76,13 @@ typedef struct utox_friend {
/* File transfers */
bool ft_autoaccept;

FILE_TRANSFER *file_transfers_incoming;
uint16_t file_transfers_incoming_size;
uint16_t file_transfers_incoming_active_count;
FILE_TRANSFER *ft_incoming;
uint16_t ft_incoming_size;
uint16_t ft_incoming_active_count;

FILE_TRANSFER *file_transfers_outgoing;
uint16_t file_transfers_outgoing_size;
uint16_t file_transfers_outgoing_active_count;
FILE_TRANSFER *ft_outgoing;
uint16_t ft_outgoing_size;
uint16_t ft_outgoing_active_count;
} FRIEND;

typedef struct utox_friend_request {
@@ -1,7 +1,7 @@
#include "groups.h"

#include "flist.h"
#include "logging_native.h"
#include "debug.h"
#include "macros.h"
#include "main_native.h"
#include "self.h"
@@ -12,14 +12,16 @@
#include "ui/edit.h"
#include "ui/scrollable.h"

#include "layout/group.h"

#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <tox/tox.h>

GROUPCHAT *get_group(uint32_t group_number) {
if (group_number >= UTOX_MAX_NUM_GROUPS) {
debug_error("get_group:\t index: %u is out of bounds.\n", group_number);
LOG_ERR("get_group", " index: %u is out of bounds." , group_number);
return NULL;
}

@@ -29,13 +31,14 @@ GROUPCHAT *get_group(uint32_t group_number) {
void group_init(GROUPCHAT *g, uint32_t group_number, bool av_group) {
pthread_mutex_lock(&messages_lock); /* make sure that messages has posted before we continue */
if (!g->peer) {
g->peer = calloc(MAX_GROUP_PEERS, sizeof(void));
g->peer = calloc(UTOX_MAX_GROUP_PEERS, sizeof(GROUP_PEER *));
}

g->name_length = snprintf((char *)g->name, sizeof(g->name), "Groupchat #%u", group_number);
if (g->name_length >= sizeof(g->name)) {
g->name_length = sizeof(g->name) - 1;
}

if (av_group) {
g->topic_length = sizeof("Error creating voice group, not supported yet") - 1;
strcpy2(g->topic, "Error creating voice group, not supported yet");
@@ -50,50 +53,59 @@ void group_init(GROUPCHAT *g, uint32_t group_number, bool av_group) {
g->msg.panel.y = MAIN_TOP;
g->msg.panel.height = CHAT_BOX_TOP;
g->msg.panel.width = -SCROLL_WIDTH;
g->msg.is_groupchat = 1;
g->msg.is_groupchat = true;

g->number = group_number;
g->notify = settings.group_notifications;
g->av_group = av_group;
pthread_mutex_unlock(&messages_lock); /* make sure that messages has posted before we continue */
pthread_mutex_unlock(&messages_lock);

flist_addgroup(g);
flist_select_last();
}

uint32_t group_add_message(GROUPCHAT *g, uint32_t peer_id, const uint8_t *message, size_t length, uint8_t m_type) {
pthread_mutex_lock(&messages_lock); /* make sure that messages has posted before we continue */

if (peer_id >= UTOX_MAX_GROUP_PEERS) {
LOG_ERR("Groupchats", "Unable to add message from peer %u - peer id too large.", peer_id);
return UINT32_MAX;
}

const GROUP_PEER *peer = g->peer[peer_id];
MESSAGES *m = &g->msg;
if (!peer) {
LOG_ERR("Groupchats", "Unable to get peer %u for adding message.", peer_id);
pthread_mutex_unlock(&messages_lock);
return UINT32_MAX;
}

MSG_HEADER *msg = calloc(1, sizeof(MSG_HEADER));
MSG_HEADER *msg = calloc(1, sizeof(MSG_HEADER));
if (!msg) {
debug_error("Groupchats:\t Unable to allocate memory for message header.\n");
LOG_ERR("Groupchats", "Unable to allocate memory for message header.");
return UINT32_MAX;
}
msg->our_msg = (g->our_peer_number == peer_id ? true : false);
msg->msg_type = m_type;

msg->via.grp.length = length;
msg->via.grp.author_id = peer_id;
msg->our_msg = (g->our_peer_number == peer_id ? true : false);
msg->msg_type = m_type;

msg->via.grp.length = length;
msg->via.grp.author_id = peer_id;

msg->via.grp.author_length = peer->name_length;
msg->via.grp.author_color = peer->name_color;
time(&msg->time);

msg->via.grp.author = calloc(1, peer->name_length);
if (!msg->via.grp.author) {
debug_error("Groupchat:\tUnable to allocate space for author nickname.\n");

LOG_ERR("Groupchat", "Unable to allocate space for author nickname.");
free(msg);
return UINT32_MAX;
}
memcpy(msg->via.grp.author, peer->name, peer->name_length);

msg->via.grp.msg = calloc(1, length);
if (!msg->via.grp.msg) {
debug_error("Groupchat:\tUnable to allocate space for message.\n");

LOG_ERR("Groupchat", "Unable to allocate space for message.");
free(msg->via.grp.author);
free(msg);
return UINT32_MAX;
@@ -102,25 +114,23 @@ uint32_t group_add_message(GROUPCHAT *g, uint32_t peer_id, const uint8_t *messag

pthread_mutex_unlock(&messages_lock);

MESSAGES *m = &g->msg;
return message_add_group(m, msg);
}

void group_peer_add(GROUPCHAT *g, uint32_t peer_id, bool UNUSED(our_peer_number), uint32_t name_color) {
pthread_mutex_lock(&messages_lock); /* make sure that messages has posted before we continue */
if (!g->peer) {
g->peer = calloc(MAX_GROUP_PEERS, sizeof(void));
debug_notice("Groupchat:\tNeeded to calloc peers for this group chat. (%u)\n", peer_id);
g->peer = calloc(UTOX_MAX_GROUP_PEERS, sizeof(GROUP_PEER *));
LOG_NOTE("Groupchat", "Needed to calloc peers for this group chat. (%u)" , peer_id);
}

GROUP_PEER *peer = g->peer[peer_id];

char *default_peer_name = "<unknown>";
const char *default_peer_name = "<unknown>";

// Allocate space for the struct and the dynamic array holding the peer's name.
peer = calloc(1, sizeof(GROUP_PEER) + strlen(default_peer_name) + 1);
GROUP_PEER *peer = calloc(1, sizeof(GROUP_PEER) + strlen(default_peer_name) + 1);
if (!peer) {
debug_error("Groupchat:\tUnable to allocate space for group peer.\n");
exit(42); // TODO: Header file for exit codes. This is just silly.
LOG_FATAL_ERR(EXIT_MALLOC, "Groupchat", "Unable to allocate space for group peer.");
}
strcpy2(peer->name, default_peer_name);
peer->name_length = 0;
@@ -138,16 +148,16 @@ void group_peer_del(GROUPCHAT *g, uint32_t peer_id) {
pthread_mutex_lock(&messages_lock); /* make sure that messages has posted before we continue */

if (!g->peer) {
debug("Groupchat:\tUnable to del peer from NULL group\n");
LOG_TRACE("Groupchat", "Unable to del peer from NULL group" );
}

GROUP_PEER *peer = g->peer[peer_id];

if (peer) {
debug("Freeing peer %u, name %.*s\n", peer_id, (int)peer->name_length, peer->name);
LOG_TRACE(__FILE__, "Freeing peer %u, name %.*s" , peer_id, (int)peer->name_length, peer->name);
free(peer);
} else {
debug("Groupchat:\tUnable to find peer for deletion\n");
LOG_TRACE("Groupchat", "Unable to find peer for deletion" );
return;
}
g->peer_count--;
@@ -158,7 +168,7 @@ void group_peer_del(GROUPCHAT *g, uint32_t peer_id) {
void group_peer_name_change(GROUPCHAT *g, uint32_t peer_id, const uint8_t *name, size_t length) {
pthread_mutex_lock(&messages_lock); /* make sure that messages has posted before we continue */
if (!g->peer) {
debug("Groupchat:\tUnable to add peer to NULL group\n");
LOG_TRACE("Groupchat", "Unable to add peer to NULL group" );
return;
}

@@ -172,33 +182,40 @@ void group_peer_name_change(GROUPCHAT *g, uint32_t peer_id, const uint8_t *name,
memcpy(old, peer->name, peer->name_length);
size = snprintf((char *)msg, TOX_MAX_NAME_LENGTH, "<- has changed their name from %.*s",
(int)peer->name_length, old);
peer = realloc(peer, sizeof(GROUP_PEER) + sizeof(char) * length);

if (peer) {
peer->name_length = utf8_validate(name, length);
memcpy(peer->name, name, length);
g->peer[peer_id] = peer;
pthread_mutex_unlock(&messages_lock);
group_add_message(g, peer_id, msg, size, MSG_TYPE_NOTICE);
return;

GROUP_PEER *new_peer = realloc(peer, sizeof(GROUP_PEER) + sizeof(char) * length);

if (new_peer) {
peer = new_peer;
} else {
debug_error("Groupchat:\t couldn't realloc for group peer name!\n");
exit(40);
free(peer);
LOG_FATAL_ERR(EXIT_MALLOC, "Groupchat", "couldn't realloc for group peer name!");
}

peer->name_length = utf8_validate(name, length);
memcpy(peer->name, name, length);
g->peer[peer_id] = peer;
pthread_mutex_unlock(&messages_lock);
group_add_message(g, peer_id, msg, size, MSG_TYPE_NOTICE);
return;
} else if (peer) {
/* Hopefully, they just joined, because that's the UX message we're going with! */
peer = realloc(peer, sizeof(GROUP_PEER) + sizeof(char) * length);
if (peer) {
peer->name_length = utf8_validate(name, length);
memcpy(peer->name, name, length);
g->peer[peer_id] = peer;
pthread_mutex_unlock(&messages_lock);
group_add_message(g, peer_id, (const uint8_t *)"<- has joined the chat!", 23, MSG_TYPE_NOTICE);
return;
GROUP_PEER *new_peer = realloc(peer, sizeof(GROUP_PEER) + sizeof(char) * length);

if (new_peer) {
peer = new_peer;
} else {
LOG_FATAL_ERR(EXIT_MALLOC, "Groupchat", "Unable to realloc for group peer who just joined.");
}

peer->name_length = utf8_validate(name, length);
memcpy(peer->name, name, length);
g->peer[peer_id] = peer;
pthread_mutex_unlock(&messages_lock);
group_add_message(g, peer_id, (const uint8_t *)"<- has joined the chat!", 23, MSG_TYPE_NOTICE);
return;
} else {
debug_error("Groupchat:\tWe can't set a name for a null peer! %u\n", peer_id);
exit(41);
LOG_FATAL_ERR(EXIT_FAILURE, "Groupchat", "We can't set a name for a null peer! %u" , peer_id);
}
}

@@ -6,7 +6,7 @@
typedef unsigned int ALuint;
typedef struct edit_change EDIT_CHANGE;

#define MAX_GROUP_PEERS 256
#define UTOX_MAX_GROUP_PEERS 256
#define UTOX_MAX_NUM_GROUPS 64

/* UTOX_SAVE limits 8 as the max */
@@ -44,9 +44,9 @@ typedef struct groupchat {
char *typed;

/* Audio sources */
unsigned int source[MAX_GROUP_PEERS];
unsigned int source[UTOX_MAX_GROUP_PEERS];
volatile uint64_t
last_recv_audio[MAX_GROUP_PEERS]; /* TODO: thread safety (This should work fine but it isn't very clean.) */
last_recv_audio[UTOX_MAX_GROUP_PEERS]; /* TODO: thread safety (This should work fine but it isn't very clean.) */

MESSAGES msg;
EDIT_CHANGE **edit_history;
@@ -13,11 +13,13 @@

#include "inline_video.h"

#include "logging_native.h"
#include "debug.h"
#include "macros.h"
#include "main_native.h"
#include "settings.h"

#include "ui.h"

#include "av/video.h"

#include <stdlib.h>
@@ -48,7 +50,7 @@ void inline_video_draw(INLINE_VID *UNUSED(p), int x, int y, int width, int heigh
return;
}

debug("Inline Video:\tDrawing new frame.\n");
LOG_TRACE(__FILE__, "Inline Video:\tDrawing new frame." );

if (current_frame.img && current_frame.size) {
draw_inline_image(current_frame.img, current_frame.size,
@@ -1,7 +1,7 @@
#ifndef INLINE_VIDEO_H
#define INLINE_VIDEO_H

#include "ui.h"
#include "ui/panel.h"

#include <inttypes.h>
#include <stdbool.h>
@@ -0,0 +1,12 @@
## Hi, and thanks for helping with uTox. We're all glad for the support!

The structure for the layout/ directory is a bit different. All of
the #includes should be placed inline instead of the header; ideally right
before the first use. But thats a loose requirement.

Apart from that, the PRIMARY goal should be readability, a close second would
be easy of editing, meaning fewer files are probably better. But #include
exists for a reason. Make the code easy to read, then both my and your life
easy and everyone will be happy!

Thanks again! ![who's awesome?](https://cmdline.org/who.png)
@@ -0,0 +1,123 @@
#include "background.h"

#include "friend.h"
#include "group.h"
#include "notify.h"
#include "settings.h"
#include "sidebar.h"

#include "../macros.h"
#include "../theme.h"

#include "../ui.h"

#include "../ui/draw.h"
#include "../ui/panel.h"
#include "../ui/text.h"

static void draw_background(int UNUSED(x), int UNUSED(y), int width, int height) {
/* Default background */
drawrect(0, 0, width, height, COLOR_BKGRND_MAIN);
/* Friend list (roster) background */
drawrect(0, 0, SIDEBAR_WIDTH, height, COLOR_BKGRND_LIST);
/* Current user badge background */
drawrect(0, 0, SIDEBAR_WIDTH, ROSTER_TOP, COLOR_BKGRND_MENU);

if (!panel_chat.disabled) {
/* Top frame for main chat panel */
drawrect(MAIN_LEFT, 0, width, MAIN_TOP_FRAME_THICK, COLOR_BKGRND_ALT);
drawhline(MAIN_LEFT, MAIN_TOP_FRAME_THICK - 1, width, COLOR_EDGE_NORMAL);
/* Frame for the bottom chat text entry box */
drawrect(MAIN_LEFT, height + CHAT_BOX_TOP, width, height, COLOR_BKGRND_ALT);
drawhline(MAIN_LEFT, height + CHAT_BOX_TOP, width, COLOR_EDGE_NORMAL);
}
// Chat and chat header separation
if (panel_settings_master.disabled) {
drawhline(MAIN_LEFT, MAIN_TOP_FRAME_THICK - 1, width, COLOR_EDGE_NORMAL);
} else {
drawhline(MAIN_LEFT, MAIN_TOP_FRAME_THIN - 1, width, COLOR_EDGE_NORMAL);
}
}

static void draw_splash_page(int x, int y, int w, int h) {
setcolor(COLOR_MAIN_TEXT);

x += SCALE(10);

/* Generic Splash */
setfont(FONT_SELF_NAME);
int ny = utox_draw_text_multiline_within_box(x, y, w + x, y, y + h, font_small_lineheight, S(SPLASH_TITLE),
SLEN(SPLASH_TITLE), ~0, ~0, 0, 0, 1);
setfont(FONT_TEXT);
ny = utox_draw_text_multiline_within_box(x, ny, w + x, ny, ny + h, font_small_lineheight, S(SPLASH_TEXT),
SLEN(SPLASH_TEXT), ~0, ~0, 0, 0, 1);

ny += SCALE(30);
/* Change log */
setfont(FONT_SELF_NAME);
ny = utox_draw_text_multiline_within_box(x, ny, w + x, y, ny + h, font_small_lineheight, S(CHANGE_LOG_TITLE),
SLEN(CHANGE_LOG_TITLE), ~0, ~0, 0, 0, 1);
setfont(FONT_TEXT);
ny = utox_draw_text_multiline_within_box(x, ny, w + x, ny, ny + h, font_small_lineheight, S(CHANGE_LOG_TEXT),
SLEN(CHANGE_LOG_TEXT), ~0, ~0, 0, 0, 1);
}


PANEL
panel_root = {
.type = PANEL_NONE,
.drawfunc = draw_background,
.disabled = 0,
.child = (PANEL*[]) {
&panel_side_bar,
&panel_main,
NULL
}
},

/* Main panel, holds the overhead/settings, or the friend/group containers */
panel_main = {
.type = PANEL_NONE,
.disabled = 0,
.child = (PANEL*[]) {
&panel_chat,
&panel_overhead,
NULL
}
},

/* Chat panel, friend or group, depending on what's selected */
panel_chat = {
.type = PANEL_NONE,
.disabled = 1,
.child = (PANEL*[]) {
&panel_group,
&panel_friend,
&panel_friend_request,
NULL
}
},

/* Settings master panel, holds the lower level settings */
panel_overhead = {
.type = PANEL_NONE,
.disabled = 0,
.child = (PANEL*[]) {
&panel_splash_page,
&panel_profile_password,
&panel_add_friend,
&panel_settings_master,
// (PANEL*)&button_notify_create, // FIXME, left as a comment for later work on popup notifications
NULL
}
},

panel_splash_page = {
.type = PANEL_NONE,
.disabled = 1,
.drawfunc = draw_splash_page,
.content_scroll = &scrollbar_settings,
.child = (PANEL*[]) {
NULL,
}
};
@@ -0,0 +1,11 @@
#ifndef LAYOUT_BACKGROUND_H
#define LAYOUT_BACKGROUND_H

typedef struct panel PANEL;
extern PANEL panel_root,
panel_main,
panel_chat,
panel_overhead,
panel_splash_page;

#endif // LAYOUT_BACKGROUND_H
@@ -0,0 +1,72 @@
#ifndef LAYOUT_CREATE_H
#define LAYOUT_CREATE_H

/* Space keeping file for the macros I want to create to make changing/creating
* layouts easier and/of faster. */

/* These macros are broken right now.
* TODO: Fix them. */

/*
#define CREATE_BUTTON(n, a, b, w, h) button_##n = { \
panel.type = PANEL_BUTTON, \
panel.x = a, \
panel.y = b, \
panel.width = w, \
panel.height = h, \
};
#define CREATE_EDIT(n, a, b, w, h) edit_##n = { \
panel.type = PANEL_EDIT, \
panel.x = a, \
panel.y = b, \
panel.width = w, \
panel.height = h, \
};
#define CREATE_SWITCH(n, a, b, w, h) switch_##n = { \
panel.type = PANEL_SWITCH, \
panel.x = a, \
panel.y = b, \
panel.width = w, \
panel.height = h, \
};
#define CREATE_DROPDOWN(n, a, b, h, w) dropdown_##n = { \
panel.type = PANEL_DROPDOWN, \
panel.x = a, \
panel.y = b, \
panel.height = h, \
panel.width = w, \
};
*/

#define CREATE_BUTTON(n, a, b, w, h) \
button_##n.panel.type = PANEL_BUTTON; \
button_##n.panel.x = a; \
button_##n.panel.y = b; \
button_##n.panel.width = w; \
button_##n.panel.height = h;

#define CREATE_EDIT(n, a, b, w, h) \
edit_##n.panel.type = PANEL_EDIT; \
edit_##n.panel.x = a; \
edit_##n.panel.y = b; \
edit_##n.panel.width = w; \
edit_##n.panel.height = h;

#define CREATE_SWITCH(n, a, b, w, h) \
switch_##n.panel.type = PANEL_SWITCH; \
switch_##n.panel.x = a; \
switch_##n.panel.y = b; \
switch_##n.panel.width = w; \
switch_##n.panel.height = h;

#define CREATE_DROPDOWN(n, a, b, h, w) \
dropdown_##n.panel.type = PANEL_DROPDOWN; \
dropdown_##n.panel.x = a; \
dropdown_##n.panel.y = b; \
dropdown_##n.panel.height = h; \
dropdown_##n.panel.width = w;

#endif // LAYOUT_CREATE_H

Large diffs are not rendered by default.

@@ -0,0 +1,52 @@
#ifndef LAYOUT_FRIEND_H
#define LAYOUT_FRIEND_H

typedef struct scrollable SCROLLABLE;
extern SCROLLABLE scrollbar_friend;

typedef struct panel PANEL;
extern PANEL messages_friend;

extern PANEL panel_friend,
panel_add_friend,
panel_friend_chat,
panel_friend_video,
panel_friend_settings,
panel_friend_request,
panel_friend_confirm_deletion;


typedef struct button BUTTON;
// Top Bar
extern BUTTON button_call_decline,
button_call_audio,
button_call_video;
// Bottom Bar
extern BUTTON button_send_file,
button_send_screenshot,
button_chat_send_friend;

// Friend Requests
extern BUTTON button_send_friend_request,
button_accept_friend;

// Friend Settings
extern BUTTON button_export_chatlog;

// Friend Deletion model
extern BUTTON button_confirm_deletion,
button_deny_deletion;

typedef struct uiswitch UISWITCH;
extern UISWITCH switch_friend_autoaccept_ft;


typedef struct edit EDIT;
extern EDIT edit_add_new_friend_id,
edit_add_new_friend_msg,

edit_chat_msg_friend,
edit_friend_pubkey,
edit_friend_alias;

#endif // LAYOUT_FRIEND_H

Large diffs are not rendered by default.

@@ -0,0 +1,25 @@
#ifndef LAYOUT_GROUP_H
#define LAYOUT_GROUP_H

typedef struct scrollable SCROLLABLE;
extern SCROLLABLE scrollbar_group;

typedef struct panel PANEL;
extern PANEL panel_group,
panel_group_chat,
panel_group_video,
panel_group_settings,
messages_group;

typedef struct button BUTTON;
extern BUTTON button_group_audio,
button_chat_send_group;

typedef struct dropdown DROPDOWN;
extern DROPDOWN dropdown_notify_groupchats;

typedef struct edit EDIT;
extern EDIT edit_chat_msg_group,
edit_group_topic;

#endif // LAYOUT_GROUP_H
@@ -0,0 +1,123 @@
#include "notify.h"

#include "userbadge.h"

#include "../ui.h"
#include "../self.h"
#include "../avatar.h"
#include "../debug.h"
#include "../theme.h"
#include "../notify.h"

#include "../ui/svg.h"
#include "../ui/draw.h"
#include "../ui/button.h"

#include "../main.h" // tox_thread_init

bool btn_move_window_down;

static void draw_notification(int x, int y, int w, int h) {
if (!tox_thread_init) {
return;
}

drawrect(x, y, w, h, COLOR_BKGRND_MAIN);

if (self_has_avatar()) {
draw_avatar_image(self.avatar->img, SIDEBAR_AVATAR_LEFT, SIDEBAR_AVATAR_TOP, self.avatar->width,
self.avatar->height, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH);
} else {
drawalpha(BM_CONTACT, SIDEBAR_AVATAR_LEFT, SIDEBAR_AVATAR_TOP, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH,
COLOR_MENU_TEXT);
}

setcolor(!button_name.mouseover ? COLOR_MENU_TEXT : COLOR_MENU_TEXT_SUBTEXT);
setfont(FONT_SELF_NAME);
drawtext(SIDEBAR_NAME_LEFT, SIDEBAR_NAME_TOP, "This is a test of the new uTox popup", 36);
}

PANEL
panel_notify_generic = {
.type = PANEL_NONE,
.drawfunc = draw_notification,
.disabled = 0,
.child = (PANEL*[]) {
(PANEL*)&button_notify_one,
(PANEL*)&button_notify_two,
(PANEL*)&button_notify_three,

// (PANEL*)&button_move_notify,
NULL
}
};


static void btn_notify_one_mup(void) {
LOG_ERR("Layout Notify", "Button 1 pressed");
}

BUTTON button_notify_one = {
// .bm = BM_SBUTTON,
.update = button_setcolors_success,
.on_mup = btn_notify_one_mup,
.nodraw = false,
};

static void btn_notify_two_mup(void) {
LOG_ERR("Layout Notify", "Button 2 pressed");
}

BUTTON button_notify_two = {
// .bm = BM_SBUTTON,
.update = button_setcolors_success,
.on_mup = btn_notify_two_mup,
.nodraw = false,
};

static void btn_notify_three_mup(void) {
LOG_ERR("Layout Notify", "Button 3 pressed");
}

BUTTON button_notify_three = {
// .bm = BM_SBUTTON,
.update = button_setcolors_success,
.on_mup = btn_notify_three_mup,
.nodraw = false,
};

#if 0
static void btn_move_window_mdn(void) {
LOG_NOTE(__FILE__, "button move down\n");
btn_move_window_down = true;
}

static void btn_move_window_mup(void) {
LOG_NOTE(__FILE__, "button move up\n");
btn_move_window_down = false;
}
#endif

static void btn_move_notify_mup(void) {
LOG_NOTE(__FILE__, "button tween\n");
// window_tween();
}

BUTTON button_move_notify = {
.nodraw = false,
.disabled = false,
.on_mup = btn_move_notify_mup,
};


static void btn_notify_create_mup(void) {
notify_new(NOTIFY_TYPE_MSG);
}

BUTTON button_notify_create = {
.bm = BM_SBUTTON,
.update = button_setcolors_success,
.on_mup = btn_notify_create_mup,
.button_text = {.i18nal = STR_SHOW },
.tooltip_text = {.i18nal = STR_SHOW },
};
@@ -0,0 +1,21 @@
#ifndef LAYOUT_NOTIFY_H
#define LAYOUT_NOTIFY_H

#include <stdbool.h>

typedef struct panel PANEL;
extern PANEL panel_notify_generic;

typedef struct button BUTTON;
extern BUTTON button_notify_one,
button_notify_two,
button_notify_three,
button_move_notify,
button_notify_create;


// TODO, no good capin'
extern bool btn_move_window_down;


#endif // LAYOUT_NOTIFY_H

Large diffs are not rendered by default.

@@ -0,0 +1,90 @@
#ifndef LAYOUT_SETTINGS_H
#define LAYOUT_SETTINGS_H

typedef struct scrollable SCROLLABLE;
extern SCROLLABLE scrollbar_settings;

typedef struct panel PANEL;
extern PANEL panel_settings_master,
panel_settings_subheader,
panel_settings_profile,
panel_profile_password_settings,
panel_settings_devices,
panel_settings_ui,
panel_settings_av,
panel_settings_notifications,
panel_settings_adv,
panel_nospam_settings;

extern PANEL panel_profile_password;

typedef struct button BUTTON;
extern BUTTON button_settings,
button_settings_sub_profile,
button_settings_sub_devices,
button_settings_sub_net,
button_settings_sub_ui,
button_settings_sub_av,
button_settings_sub_adv,
button_settings_sub_notifications;

extern BUTTON button_add_new_device_to_self;

extern BUTTON button_callpreview,
button_videopreview,
button_copyid,
button_lock_uTox,
button_show_password_settings,
button_change_nospam,
button_revert_nospam,
button_show_nospam;

typedef struct uiswitch UISWITCH;
extern UISWITCH /* User Interface Tab */
switch_save_chat_history,
switch_close_to_tray,
switch_start_in_tray,
switch_auto_startup,
switch_mini_contacts,
/* AV Tab */
switch_push_to_talk,
switch_audio_filtering,
/* Notifications Tab */
switch_audible_notifications,
switch_status_notifications,
switch_typing_notes,
/* Advanced Tab */
switch_ipv6,
switch_udp,
switch_proxy,
switch_proxy_force,
switch_auto_update,
switch_block_friend_requests;

typedef struct dropdown DROPDOWN;
extern DROPDOWN /* Profile */
dropdown_language,
/* User interface */
dropdown_theme,
dropdown_dpi,
/* AV */
dropdown_audio_in,
dropdown_audio_out,
dropdown_video,
/* Notifications */
dropdown_global_group_notifications;

typedef struct edit EDIT;
extern EDIT /* Profile */
edit_name,
edit_status_msg,
edit_toxid,
/* Advanced */
edit_proxy_ip,
edit_proxy_port,
edit_profile_password,
edit_nospam,
/* MDevice */
edit_add_new_device_to_self;

#endif // LAYOUT_SETTINGS_H
@@ -0,0 +1,192 @@
#include "sidebar.h"

#include "settings.h"
#include "friend.h"

#include "../avatar.h"
#include "../flist.h"
#include "../macros.h"
#include "../main_native.h"
#include "../self.h"
#include "../theme.h"

#include "../ui.h"
#include "../ui/draw.h"
#include "../ui/scrollable.h"
#include "../ui/edit.h"
#include "../ui/button.h"
#include "../ui/svg.h"

#include "../main.h" // tox_thread global

// Scrollbar or friend list
SCROLLABLE scrollbar_flist = {
.panel = { .type = PANEL_SCROLLABLE, },
.color = C_SCROLL,
.x = 2,
.left = 1,
.small = 1,
};

/* Top left self interface Avatar, name, statusmsg, status icon */
static void draw_user_badge(int UNUSED(x), int UNUSED(y), int UNUSED(width), int UNUSED(height)) {
if (tox_thread_init == UTOX_TOX_THREAD_INIT_SUCCESS) {
/* Only draw the user badge if toxcore is running */
/*draw avatar or default image */
if (self_has_avatar()) {
draw_avatar_image(self.avatar->img, SIDEBAR_AVATAR_LEFT, SIDEBAR_AVATAR_TOP, self.avatar->width,
self.avatar->height, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH);
} else {
drawalpha(BM_CONTACT, SIDEBAR_AVATAR_LEFT, SIDEBAR_AVATAR_TOP, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH,
COLOR_MENU_TEXT);
}
/* Draw name */
setcolor(!button_name.mouseover ? COLOR_MENU_TEXT : COLOR_MENU_TEXT_SUBTEXT);
setfont(FONT_SELF_NAME);
drawtextrange(SIDEBAR_NAME_LEFT, SIDEBAR_NAME_WIDTH * 1.5, SIDEBAR_NAME_TOP, self.name, self.name_length);

/*&Draw current status message
@TODO: separate these colors if needed (COLOR_MAIN_TEXT_HINT) */
setcolor(!button_status_msg.mouseover ? COLOR_MENU_TEXT_SUBTEXT : COLOR_MAIN_TEXT_HINT);
setfont(FONT_STATUS);
drawtextrange(SIDEBAR_STATUSMSG_LEFT, SIDEBAR_STATUSMSG_WIDTH * 1.5, SIDEBAR_STATUSMSG_TOP, self.statusmsg,
self.statusmsg_length);

/* Draw status button icon */
drawalpha(BM_STATUSAREA, SELF_STATUS_ICON_LEFT, SELF_STATUS_ICON_TOP, BM_STATUSAREA_WIDTH, BM_STATUSAREA_HEIGHT,
button_usr_state.mouseover ? COLOR_BKGRND_LIST_HOVER : COLOR_BKGRND_LIST);
uint8_t status = tox_connected ? self.status : 3;
drawalpha(BM_ONLINE + status, SELF_STATUS_ICON_LEFT + BM_STATUSAREA_WIDTH / 2 - BM_STATUS_WIDTH / 2,
SELF_STATUS_ICON_TOP + BM_STATUSAREA_HEIGHT / 2 - BM_STATUS_WIDTH / 2, BM_STATUS_WIDTH,
BM_STATUS_WIDTH, status_color[status]);

/* Draw online/all friends filter text. */
setcolor(!button_filter_friends.mouseover ? COLOR_MENU_TEXT_SUBTEXT : COLOR_MAIN_TEXT_HINT);
setfont(FONT_STATUS);
drawtextrange(SIDEBAR_FILTER_FRIENDS_LEFT, SIDEBAR_FILTER_FRIENDS_WIDTH, SIDEBAR_FILTER_FRIENDS_TOP,
flist_get_filter() ? S(FILTER_ONLINE) : S(FILTER_ALL),
flist_get_filter() ? SLEN(FILTER_ONLINE) : SLEN(FILTER_ALL));
} else {
drawalpha(BM_CONTACT, SIDEBAR_AVATAR_LEFT, SIDEBAR_AVATAR_TOP, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH,
COLOR_MENU_TEXT);

setcolor(!button_name.mouseover ? COLOR_MENU_TEXT : COLOR_MENU_TEXT_SUBTEXT);
setfont(FONT_SELF_NAME);
drawtextrange(SIDEBAR_NAME_LEFT, SIDEBAR_WIDTH - SIDEBAR_AVATAR_LEFT, SIDEBAR_NAME_TOP, S(NOT_CONNECTED), SLEN(NOT_CONNECTED));

if (tox_thread_init == UTOX_TOX_THREAD_INIT_ERROR) {
setcolor(!button_status_msg.mouseover ? COLOR_MENU_TEXT_SUBTEXT : COLOR_MAIN_TEXT_HINT);
setfont(FONT_STATUS);
drawtextrange(SIDEBAR_STATUSMSG_LEFT, SIDEBAR_WIDTH, SIDEBAR_STATUSMSG_TOP, S(NOT_CONNECTED_SETTINGS), SLEN(NOT_CONNECTED_SETTINGS));
}
}
}

/* Left side bar, holds the user, the roster, and the setting buttons */
PANEL panel_side_bar = {
.type = PANEL_NONE,
.disabled = 0,
.child = (PANEL*[]) {
&panel_self,
&panel_quick_buttons,
&panel_flist,
NULL
}
},
/* The user badge and buttons */
panel_self = {
.type = PANEL_NONE,
.disabled = 0,
.drawfunc = draw_user_badge,
.child = (PANEL*[]) {
(PANEL*)&button_avatar, (PANEL*)&button_name, (PANEL*)&button_usr_state,
(PANEL*)&button_status_msg,
NULL
}
},
/* Left sided toggles */
panel_quick_buttons = {
.type = PANEL_NONE,
.disabled = 0,
.child = (PANEL*[]) {
(PANEL*)&button_filter_friends, /* Top of roster */
(PANEL*)&edit_search, /* Bottom of roster*/
(PANEL*)&button_settings,
(PANEL*)&button_add_new_contact,
NULL
}
},
/* The friends and group was called list */
panel_flist = {
.type = PANEL_NONE,
.disabled = 0,
.child = (PANEL*[]) {
// TODO rename these
&panel_flist_list,
(PANEL*)&scrollbar_flist,
NULL
}
},
panel_flist_list = {
.type = PANEL_LIST,
.content_scroll = &scrollbar_flist,
};


#include "../friend.h"
static void e_search_onchange(EDIT *edit) {
char *data = edit->data;
uint16_t length = edit->length > sizeof search_data ? sizeof search_data - 1 : edit->length;

if (length) {
button_add_new_contact.panel.disabled = 0;
button_add_new_contact.nodraw = 0;
button_settings.panel.disabled = 1;
button_settings.nodraw = 1;
memcpy(search_data, data, length);
search_data[length] = 0;
flist_search((char *)search_data);
} else {
button_add_new_contact.panel.disabled = 1;
button_add_new_contact.nodraw = 1;
button_settings.panel.disabled = 0;
button_settings.nodraw = 0;
flist_search(NULL);
}

redraw();
}

static void e_search_onenter(EDIT *edit) {
char * data = edit->data;
uint16_t length = edit->length;

if (length == 76) { // FIXME, this should be error checked!
// No, srsly... this is lucky, not right.
friend_add(data, length, (char *)"", 0);
edit_setstr(&edit_search, (char *)"", 0);
} else {
if (tox_thread_init == UTOX_TOX_THREAD_INIT_SUCCESS) {
/* Only change if we're logged in! */
edit_setstr(&edit_add_new_friend_id, data, length);
edit_setstr(&edit_search, (char *)"", 0);
flist_selectaddfriend();
edit_setfocus(&edit_add_new_friend_msg);
}
}
return;
}

static char e_search_data[1024];
EDIT edit_search = {
.data = e_search_data,
.maxlength = sizeof e_search_data - 1,
.onchange = e_search_onchange,
.onenter = e_search_onenter,
.style = AUXILIARY_STYLE,
.vcentered = true,
.empty_str = { .i18nal = STR_CONTACT_SEARCH_ADD_HINT },
};



@@ -0,0 +1,29 @@
#ifndef LAYOUT_SIDEBAR_H
#define LAYOUT_SIDEBAR_H

typedef struct scrollable SCROLLABLE;
extern SCROLLABLE scrollbar_flist;

typedef struct panel PANEL;
extern PANEL panel_side_bar,
panel_self,

panel_flist,
panel_flist_list,

panel_quick_buttons,
panel_lower_buttons;

typedef struct button BUTTON;
extern BUTTON button_avatar,
button_name,
button_status_msg,
button_usr_state,

button_filter_friends,
button_add_new_contact;

typedef struct edit EDIT;
extern EDIT edit_search;

#endif //LAYOUT_SIDEBAR_H
@@ -0,0 +1,133 @@
#include "userbadge.h"

#include "settings.h"

#include "../avatar.h"
#include "../flist.h"
#include "../macros.h"
#include "../main_native.h"
#include "../self.h"
#include "../tox.h"

#include "../ui/button.h"
#include "../ui/contextmenu.h"
#include "../ui/edit.h"

#include "../main.h" // tox_tread_init


/* On-press functions followed by the update functions when needed... */
static void button_avatar_on_mup(void) {
if (tox_thread_init == UTOX_TOX_THREAD_INIT_SUCCESS) {
openfileavatar();
}
}

static void button_name_on_mup(void) {
flist_selectsettings();
if (tox_thread_init != UTOX_TOX_THREAD_INIT_SUCCESS) {
// jump to the network settings when unable to create tox instance
panel_settings_adv.disabled = false;
panel_settings_profile.disabled = true;
panel_settings_devices.disabled = true;
panel_settings_ui.disabled = true;
panel_settings_av.disabled = true;
panel_settings_notifications.disabled = true;
} else {
panel_settings_profile.disabled = false;
panel_settings_devices.disabled = true;
panel_settings_ui.disabled = true;
panel_settings_av.disabled = true;
panel_settings_adv.disabled = true;
panel_settings_notifications.disabled = true;
edit_setfocus(&edit_name);
}
}

static void button_statusmsg_on_mup(void) {
flist_selectsettings();
if (tox_thread_init != UTOX_TOX_THREAD_INIT_SUCCESS) {
// jump to the network settings when unable to create tox instance
panel_settings_adv.disabled = false;

panel_settings_profile.disabled = true;
panel_settings_devices.disabled = true;
panel_settings_ui.disabled = true;
panel_settings_av.disabled = true;
panel_settings_notifications.disabled = true;
} else {
panel_settings_profile.disabled = false;

panel_settings_devices.disabled = true;
panel_settings_ui.disabled = true;
panel_settings_av.disabled = true;
panel_settings_adv.disabled = true;
panel_settings_notifications.disabled = true;
edit_setfocus(&edit_status_msg);
}
}


#ifdef UNITY
#include "xlib/mmenu.h"
extern bool unity_running;
#endif
static void button_status_on_mup(void) {
self.status++;
if (self.status == 3) { // TODO typedef enum
self.status = 0;
}

#ifdef UNITY
if (unity_running) {
mm_set_status(self.status);
}
#endif

postmessage_toxcore(TOX_SELF_SET_STATE, self.status, 0, NULL);
}

static void contextmenu_avatar_onselect(uint8_t i) {
if (i == 0) {
avatar_unset_self();
}
}

static void button_avatar_onright(void) {
if (self_has_avatar()) {
static UTOX_I18N_STR menu[] = { STR_REMOVE };
contextmenu_new(COUNTOF(menu), menu, contextmenu_avatar_onselect);
}
}

BUTTON button_avatar = {
.nodraw = true, .on_mup = button_avatar_on_mup, .onright = button_avatar_onright,
};

BUTTON button_name = {
.nodraw = true, .on_mup = button_name_on_mup,
};

BUTTON button_status_msg = {
.nodraw = true, .on_mup = button_statusmsg_on_mup,
};

BUTTON button_usr_state = {
.nodraw = true,
.on_mup = button_status_on_mup,
.tooltip_text = {
.i18nal = STR_STATUS
},
};

static void button_filter_friends_on_mup(void) {
// this only works because right now there are only 2 filters
// (none or online), basically a bool
flist_set_filter(!flist_get_filter());
}
BUTTON button_filter_friends = {
.nodraw = true,
.on_mup = button_filter_friends_on_mup,
.tooltip_text = {.i18nal = STR_FILTER_CONTACT_TOGGLE },
};

@@ -0,0 +1,16 @@
#ifndef LAYOUT_USERBADGE_H
#define LAYOUT_USERBADGE_H

typedef struct button BUTTON;
extern BUTTON button_avatar,
button_name,
button_status_msg,
button_usr_state,
button_filter_friends;

typedef struct edit EDIT;
extern EDIT edit_search,
edit_add_new_friend,
edit_add_new_friend_msg;

#endif // LAYOUT_USERBADGE_H
@@ -1,7 +1,22 @@
#include "logging_native.h"
#include "debug.h"

#include "settings.h"

#include <stdio.h>
#include <stdarg.h>

int utox_verbosity() {
return settings.verbose;
}

void debug(const char *fmt, ...){
va_list list;

va_start(list, fmt);
vfprintf(settings.debug_file, fmt, list);
va_end(list);

#ifdef __WIN32__
fflush(settings.debug_file);
#endif
}

This file was deleted.

@@ -4,67 +4,74 @@

#include "main.h"

#include "debug.h"
#include "flist.h"
#include "friend.h"
#include "groups.h"
#include "logging_native.h"
#include "main_native.h"
#include "settings.h"
#include "theme.h"
#include "updater.h"

#include "ui/dropdowns.h"
#include "ui/edits.h"
#include "ui/switches.h"

#include <getopt.h>

/* The utox_ functions contained in src/main.c are wrappers for the platform native_ functions
* if you need to localize them to a specific platform, move them from here, to each
* src/<platform>/main.x and change from utox_ to native_ */
* src/<platform>/main.x and change from utox_ to native_
*/

bool utox_data_save_tox(uint8_t *data, size_t length) {
FILE *fp= native_get_file((uint8_t *)"tox_save.tox", NULL, UTOX_FILE_OPTS_WRITE);
if (fp == NULL) {
debug("Can not open tox_save.tox to write to it.\n");
LOG_ERR(__FILE__, "Can not open tox_save.tox to write to it.");
return true;
}

if (fwrite(data, length, 1, fp) != 1) {
LOG_ERR(__FILE__, "Unable to write Tox save to file.");
return true;
}

fwrite(data, length, 1, fp);
flush_file(fp);
fclose(fp);

return false;
}

uint8_t *utox_data_load_tox(size_t *size) {
uint8_t name[][20] = { "tox_save.tox", "tox_save.tox.atomic", "tox_save.tmp", "tox_save" };
const uint8_t name[][20] = { "tox_save.tox", "tox_save.tox.atomic", "tox_save.tmp", "tox_save" };

uint8_t *data;
FILE * fp;
size_t length = 0;
for (uint8_t i = 0; i < 4; i++) {
size_t length = 0;

for (int i = 0; i < 4; i++) {
fp = native_get_file(name[i], &length, UTOX_FILE_OPTS_READ);
FILE *fp = native_get_file(name[i], &length, UTOX_FILE_OPTS_READ);
if (fp == NULL) {
continue;
}
data = calloc(length + 1, 1);

uint8_t *data = calloc(1, length + 1);

if (data == NULL) {
debug("Could not allocate memory for tox save.\n");
LOG_ERR(__FILE__, "Could not allocate memory for tox save.");
fclose(fp);
return NULL; // quit were out of memory, calloc will fail again
// Quit. We're out of memory, calloc will fail again.
return NULL;
}
if (fread(data, 1, length, fp) != length) {
debug("Could not read: %s.\n", name[i]);

if (fread(data, length, 1, fp) != 1) {
LOG_ERR(__FILE__, "Could not read: %s.", name[i]);
fclose(fp);
free(data);
return NULL; // return because if this file exits we don't want to fall back to an old version, we need the
// user to decide
// Return NULL, because if a Tox save exits we don't want to fall
// back to an old version, we need the user to decide what to do.
return NULL;
}

fclose(fp);
*size = length;
return data;
}

return NULL;
}

@@ -75,7 +82,11 @@ bool utox_data_save_utox(UTOX_SAVE *data, size_t size) {
return false;
}

fwrite(data, size, 1, fp);
if (fwrite(data, size, 1, fp) != 1) {
LOG_ERR(__FILE__, "Unable to write uTox settings to file.");
return false;
}

flush_file(fp);
fclose(fp);

@@ -90,18 +101,20 @@ UTOX_SAVE *utox_data_load_utox(void) {
return NULL;
}

UTOX_SAVE *save = calloc(size + 1, 1);
UTOX_SAVE *save = calloc(1, size + 1);
if (save == NULL) {
fclose(fp);
return NULL;
}

if (fread(save, 1, size, fp) != size) {
debug("Could not read save file\n");
if (fread(save, size, 1, fp) != 1) {
LOG_ERR(__FILE__, "Could not read save file");

fclose(fp);
free(save);
return NULL;
}

fclose(fp);
return save;
}
@@ -116,35 +129,15 @@ bool utox_data_save_ftinfo(char hex[TOX_PUBLIC_KEY_SIZE * 2], uint8_t *data, siz
return false;
}

fwrite(data, length, 1, fp);
flush_file(fp);
fclose(fp);

return true;
}

uint8_t *utox_data_load_custom_theme(size_t *out) {
FILE *fp = native_get_file((uint8_t *)"utox_theme.ini", out, UTOX_FILE_OPTS_READ);

if (fp == NULL) {
return NULL;
}

uint8_t *data = calloc(*out + 1, 1);
if (data == NULL) {
if (fwrite(data, length, 1, fp) != 1) {
LOG_ERR(__FILE__, "Unable to write ftinfo to file.");
fclose(fp);
return NULL;
return false;
}

if (fread(data, 1, *out, fp) != *out) {
debug_error("Theme:\tCould not read custom theme from file\n");
fclose(fp);
free(data);
return NULL;
}
fclose(fp);

return data;
return true;
}

/* Shared function between all four platforms */
@@ -180,7 +173,8 @@ void parse_args(int argc, char *argv[],
{ "skip-updater", no_argument, NULL, 'N' }, { "signal-updater", no_argument, NULL, 'S' },
{ "version", no_argument, NULL, 0 },
{ "silent", no_argument, NULL, 1 }, { "verbose", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0 }
{ "help", no_argument, NULL, 'h' }, { "debug", required_argument, NULL, 2 },
{ 0, 0, 0, 0 }
};

int opt, long_index = 0;
@@ -203,17 +197,16 @@ void parse_args(int argc, char *argv[],
} else if (!strcmp(optarg, "solarized-dark")) {
settings.theme = THEME_SOLARIZED_DARK;
} else {
debug_error(
"Please specify correct theme (please check user manual for list of correct values).\n");
LOG_NORM("Please specify correct theme (please check user manual for list of correct values).\n");
exit(EXIT_FAILURE);
}
*theme_was_set_on_argv = 1;
break;
}

case 'p': {
debug("Launching uTox in portable mode: All data will be saved to the tox folder in the current "
"working directory\n");
LOG_INFO("uTox", "Launching uTox in portable mode: All data will be saved to the tox folder in the current "
"working directory\n");
settings.portable_mode = 1;
break;
}
@@ -226,8 +219,7 @@ void parse_args(int argc, char *argv[],
} else if (!strcmp(optarg, "hide-window")) {
*set_show_window = -1;
} else {
debug_error(
"Please specify a correct set option (please check user manual for list of correct values).\n");
LOG_NORM("Please specify a correct set option (please check user manual for list of correct values).\n");
exit(EXIT_FAILURE);
}
break;
@@ -237,8 +229,7 @@ void parse_args(int argc, char *argv[],
if (!strcmp(optarg, "start-on-boot")) {
*should_launch_at_startup = -1;
} else {
debug_error("Please specify a correct unset option (please check user manual for list of correct "
"values).\n");
LOG_NORM("Please specify a correct unset option (please check user manual for list of correct values).\n");
exit(EXIT_FAILURE);
}
break;
@@ -258,16 +249,16 @@ void parse_args(int argc, char *argv[],
}

case 0: {
debug_error("uTox version: %s\n", VERSION);
LOG_NORM("uTox version: %s\n", VERSION);
#ifdef GIT_VERSION
debug_error("git version %s\n", GIT_VERSION);
LOG_NORM("git version %s\n", GIT_VERSION);
#endif
exit(EXIT_SUCCESS);
break;
}

case 1: {
settings.verbose = 0;
settings.verbose = LOG_LVL_FATAL;
break;
}

@@ -276,38 +267,57 @@ void parse_args(int argc, char *argv[],
break;
}

case 2: {
settings.debug_file = fopen(optarg, "a+");
if (!settings.debug_file) {
settings.debug_file = stdout;
LOG_NORM("Could not open %s. Logging to stdout.\n", optarg);
}
break;
}

case 'h': {
debug_error("µTox - Lightweight Tox client version %s.\n\n", VERSION);
debug_error("The following options are available:\n");
debug_error(" -t --theme=<theme-name> Specify a UI theme, where <theme-name> can be one of default, "
LOG_NORM("µTox - Lightweight Tox client version %s.\n\n", VERSION);
LOG_NORM("The following options are available:\n");
LOG_NORM(" -t --theme=<theme-name> Specify a UI theme, where <theme-name> can be one of default, "
"dark, light, highcontrast, zenburn.\n");
debug_error(" -p --portable Launch in portable mode: All data will be saved to the tox "
LOG_NORM(" -p --portable Launch in portable mode: All data will be saved to the tox "
"folder in the current working directory.\n");
debug_error(" -s --set=<option> Set an option: start-on-boot, show-window, hide-window.\n");
debug_error(" -u --unset=<option> Unset an option: start-on-boot.\n");
debug_error(" -n --no-updater Disable the updater.\n");
debug_error(" -v --verbose Increase the amount of output, use -v multiple times to get "
LOG_NORM(" -s --set=<option> Set an option: start-on-boot, show-window, hide-window.\n");
LOG_NORM(" -u --unset=<option> Unset an option: start-on-boot.\n");
LOG_NORM(" -n --no-updater Disable the updater.\n");
LOG_NORM(" -v --verbose Increase the amount of output, use -v multiple times to get "
"full debug output.\n");
debug_error(" -h --help Shows this help text.\n");
debug_error(" --version Print the version and exit.\n");
debug_error(" --silent Set the verbosity level to 0, disable all debugging output.\n");
LOG_NORM(" -h --help Shows this help text.\n");
LOG_NORM(" --version Print the version and exit.\n");
LOG_NORM(" --silent Set the verbosity level to 0, disable all debugging output.\n");
LOG_NORM(" --debug Set a file for utox to log errors to.\n");
exit(EXIT_SUCCESS);
break;
}

case '?': debug("Invalid option: %c!\n", (char)optopt); break;
case '?': LOG_TRACE(__FILE__, ", (char)optopt" ); break;
}
}
}

void utox_init(void) {
/* Called by the native main for every platform after loading utox setting, before showing/drawing any windows. */
if (settings.curr_version != settings.last_version) {
settings.show_splash = 1;
settings.show_splash = true;
}

if (settings.auto_update) {
updater_check();
// TODO(grayhatter)
// if (settings.auto_update) {
// updater_check();
// }

settings.debug_file = stdout;
}

void utox_raze(void) {
if (settings.debug_file != stdout) {
fclose(settings.debug_file);
}
}

@@ -134,6 +134,11 @@ typedef enum {

UTOX_TOX_THREAD_INIT tox_thread_init;

bool move_window_down; // When the mouse is currently down over the move_window_button().
// non-ideal but I wasn't ready to write a better state system for
// moving windows from inside uTox.


// add friend page
uint8_t addfriend_status;

@@ -180,14 +185,6 @@ uint8_t *utox_data_load_tox(size_t *size);
*/
UTOX_SAVE *utox_data_load_utox(void);

/**
* Loads a custom theme and sets out to the size of the data
*
* Returns a pointer to the theme data on success, the caller needs to free this
* Returns NULL on failure
*/
uint8_t *utox_data_load_custom_theme(size_t *out);

/**
* Parses the arguments passed to uTox
*/
@@ -204,6 +201,11 @@ void parse_args(int argc, char *argv[],
*/
void utox_init(void);

/**
* Free used resources
*/
void utox_raze(void);

// Android audio
void audio_play(int32_t call_index, const int16_t *data, int length, uint8_t channels);
void audio_begin(int32_t call_index);
@@ -95,6 +95,7 @@ bool native_move_file(const uint8_t *current_name, const uint8_t *new_name);
void init_ptt(void);
bool get_ptt_key(void); // Never used. Remove?
bool set_ptt_key(void); // Never used. Remove?
// Returns a bool indicating whether you should send audio or not.
bool check_ptt_key(void);
void exit_ptt(void);

Large diffs are not rendered by default.

@@ -1,13 +1,16 @@
#ifndef MESSAGES_H
#define MESSAGES_H

#include "ui.h"
#include "ui/panel.h"

#include <stdint.h>
#include <time.h>
#include <pthread.h>

pthread_mutex_t messages_lock;

typedef struct native_image NATIVE_IMAGE;

typedef enum UTOX_MSG_TYPE {
MSG_TYPE_NULL,
/* MSG_TEXT must start here */
@@ -16,13 +19,13 @@ typedef enum UTOX_MSG_TYPE {
MSG_TYPE_NOTICE,
MSG_TYPE_NOTICE_DAY_CHANGE, // Seperated so I can localize this later!
/* MSG_TEXT should end here */
MSG_TYPE_OTHER, // Unused, expect to seperate MSG_TEXT type
// MSG_TYPE_OTHER, // Unused, expect to seperate MSG_TEXT type
MSG_TYPE_IMAGE,
MSG_TYPE_IMAGE_HISTORY,
// MSG_TYPE_IMAGE_HISTORY,
MSG_TYPE_FILE,
MSG_TYPE_FILE_HISTORY,
MSG_TYPE_CALL_ACTIVE,
MSG_TYPE_CALL_HISTORY,
// MSG_TYPE_FILE_HISTORY,
// MSG_TYPE_CALL_ACTIVE,
// MSG_TYPE_CALL_HISTORY,
} UTOX_MSG_TYPE;

typedef struct {
@@ -72,7 +75,7 @@ typedef struct msg_file {

/* Generic Message type */
typedef struct msg_header {
uint8_t msg_type;
UTOX_MSG_TYPE msg_type;

// true, if we're the author, false, if someone else.
bool our_msg;
@@ -166,8 +169,11 @@ bool messages_mdown(PANEL *panel);
bool messages_dclick(PANEL *panel, bool triclick);
bool messages_mright(PANEL *panel);
bool messages_mwheel(PANEL *panel, int height, double d, bool smooth);
// Always returns false.
bool messages_mup(PANEL *panel);
bool messages_mleave(PANEL *m);
// Relay keypress to message panel.
// Returns bool indicating whether a redraw is needed or not.
bool messages_char(uint32_t ch);
int messages_selection(PANEL *panel, void *buffer, uint32_t len, bool names);

@@ -0,0 +1,45 @@
#include "notify.h"

#include "main.h"
#include "debug.h"

#include "ui.h"
#include "window.h"

#include "layout/notify.h"

static uint16_t notification_number = 0;

UTOX_WINDOW *notify_new(NOTIFY_TYPE type) {
LOG_NOTE("Notifier", "Notify:\tCreating Notification #%u", notification_number);

const int notify_w = 400;
const int notify_h = 150;


const int x = 30;
const int y = 30 + (20 + notify_h) * notification_number;
++notification_number;

PANEL *panel;
switch (type) {
case NOTIFY_TYPE_NONE: {
return NULL;
}
case NOTIFY_TYPE_MSG: {
panel = &panel_notify_generic;
break;
}
case NOTIFY_TYPE_CALL:
case NOTIFY_TYPE_CALL_VIDEO: {
panel = &panel_notify_generic; // TODO create a video call panel type
break;
}
}

UTOX_WINDOW *w = window_create_notify(x, y, notify_w, notify_h, panel);

native_window_set_target(w);

return w;
}
@@ -0,0 +1,22 @@
#ifndef NOTIFY_H
#define NOTIFY_H

#include "window.h"

typedef enum {
NOTIFY_TYPE_NONE,
NOTIFY_TYPE_MSG,
NOTIFY_TYPE_CALL,
NOTIFY_TYPE_CALL_VIDEO,
} NOTIFY_TYPE;

typedef enum {
TWEEN_NONE,
TWEEN_UP,
} NOTIFY_TWEEN;

UTOX_WINDOW *notify_new(NOTIFY_TYPE type);

void notify_tween(void);

#endif
@@ -1,6 +1,6 @@
#include <assert.h>
#include "../filesys.h"

#include "../logging_native.h"
#include "../debug.h"
#include "../settings.h"

#ifdef __OBJC__
@@ -10,6 +10,8 @@
#include "../xlib/main.h"
#endif

#include <assert.h>

bool native_create_dir(const uint8_t *filepath) {
const int status = mkdir((char *)filepath, S_IRWXU);
if (status == 0 || errno == EEXIST) {
@@ -60,7 +62,7 @@ FILE *native_get_file(const uint8_t *name, size_t *size, UTOX_FILE_OPTS opts) {
}

if (strlen((char *)path) + strlen((char *)name) >= UTOX_FILE_NAME_LENGTH) {
debug("NATIVE:\tLoad directory name too long\n");
LOG_ERR("Filesys", "Load directory name too long" );
return NULL;
} else {
snprintf((char *)path + strlen((char *)path), UTOX_FILE_NAME_LENGTH - strlen((char *)path), "%s", name);
@@ -87,15 +89,15 @@ FILE *native_get_file(const uint8_t *name, size_t *size, UTOX_FILE_OPTS opts) {
FILE *fp = fopen((char *)path, mode);

if (!fp && opts & UTOX_FILE_OPTS_READ && opts & UTOX_FILE_OPTS_WRITE) {
debug_notice("POSIX:\tUnable to simple open, falling back to fd\n");
LOG_WARN("POSIX", "Unable to simple open, falling back to fd" );
// read wont create a file if it doesn't' already exist. If we're allowed to write, lets try
// to create the file, then reopen it.
int fd = open((char *)path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
fp = fdopen(fd, mode);
}

if (fp == NULL) {
debug_notice("NATIVE:\tCould not open %s\n", path);
LOG_TRACE("Filesys", "Could not open %s" , path);
return NULL;
}

@@ -0,0 +1,9 @@
#include "screen_grab.h"

#include "main_native.h"



void utox_screen_grab_desktop(bool video) {
native_screen_grab_desktop(video);
}
@@ -0,0 +1,10 @@
#ifndef SCREEN_GRAB_H
#define SCREEN_GRAB_H

#include <stdbool.h>

void native_screen_grab_desktop(bool video);

void utox_screen_grab_desktop(bool video);

#endif
@@ -1,28 +1,30 @@
#include "self.h"

#include "tox.h"
#include "avatar.h"
#include "logging_native.h"
#include "debug.h"
#include "tox.h"

#include "ui/edit.h"
#include "layout/settings.h"

#include <stdio.h>

void init_self(Tox *tox) {
/* Set local info for self */
edit_setstr(&edit_name, self.name, self.name_length);
edit_setstr(&edit_status, self.statusmsg, self.statusmsg_length);
edit_setstr(&edit_status_msg, self.statusmsg, self.statusmsg_length);

/* Get tox id, and gets the hex version for utox */
tox_self_get_address(tox, self.id_binary);
id_to_string(self.id_str, self.id_binary);
self.id_str_length = TOX_ADDRESS_SIZE * 2;
debug("Tox ID: %.*s\n", (int)self.id_str_length, self.id_str);
LOG_TRACE("Self INIT", "Tox ID: %.*s" , (int)self.id_str_length, self.id_str);

/* Get nospam */
self.nospam = tox_self_get_nospam(tox);
self.old_nospam = self.nospam;
sprintf(self.nospam_str, "%08X", self.nospam);
edit_setstr(&edit_nospam, self.nospam_str, sizeof(uint32_t) * 2);

avatar_init_self();
}
@@ -1,13 +1,17 @@
#include "settings.h"

#include "main_native.h"
#include "logging_native.h"
#include "debug.h"
#include "flist.h"
#include "groups.h"
#include "main_native.h"

#include "ui/dropdowns.h"
#include "ui/edits.h"
#include "ui/switches.h"
// TODO do we want to include the UI headers here?
// Or would it be better to supply a callback after settings are loaded?
#include "ui/edit.h"
#include "ui/switch.h"
#include "ui/dropdown.h"

#include "layout/settings.h"

#include "main.h" // UTOX_VERSION_NUMBER, MAIN_HEIGHT, MAIN_WIDTH, all save things..

@@ -56,7 +60,8 @@ SETTINGS settings = {
.status_notifications = true,
.group_notifications = GNOTIFY_ALWAYS,

.verbose = 1,
.verbose = LOG_LVL_ERROR,
.debug_file = NULL,

// .theme // included here to match the full struct
// OS interface settings
@@ -73,7 +78,7 @@ UTOX_SAVE *config_load(void) {
save = utox_data_load_utox();

if (!save) {
debug_notice("unable to load utox_save data\n");
LOG_ERR("Settings", "unable to load utox_save data");
/* Create and set defaults */
save = calloc(1, sizeof(UTOX_SAVE));
save->enableipv6 = 1;
@@ -98,10 +103,14 @@ UTOX_SAVE *config_load(void) {
}

dropdown_dpi.selected = dropdown_dpi.over = save->scale - 5;
dropdown_proxy.selected = dropdown_proxy.over = save->proxyenable <= 2 ? save->proxyenable : 2;

switch_ipv6.switch_on = save->enableipv6;
switch_udp.switch_on = !save->disableudp;
switch_ipv6.switch_on = save->enableipv6;
switch_udp.switch_on = !save->disableudp;
switch_proxy.switch_on = save->proxyenable;
switch_proxy_force.switch_on = false; // TODO, this is a bug. We really should be saving this data, but I don't want
// to touch this until we decide how we want to save uTox data in the future.
// -- Grayhatter, probably...

switch_save_chat_history.switch_on = save->logging_enabled;
switch_mini_contacts.switch_on = save->use_mini_flist;
switch_auto_startup.switch_on = save->auto_startup;
@@ -188,7 +197,7 @@ void config_save(UTOX_SAVE *save_in) {

save->save_version = UTOX_SAVE_VERSION;
save->scale = ui_scale - 1;
save->proxyenable = dropdown_proxy.selected;
save->proxyenable = switch_proxy.switch_on;
save->logging_enabled = settings.logging_enabled;
save->close_to_tray = settings.close_to_tray;
save->start_in_tray = settings.start_in_tray;
@@ -219,7 +228,7 @@ void config_save(UTOX_SAVE *save_in) {

memcpy(save->proxy_ip, proxy_address, 256); /* Magic number inside toxcore */

debug_notice("uTox:\tWriting uTox Save\n");
LOG_NOTE("uTox", "Writing uTox Save" );
utox_data_save_utox(save, sizeof(*save) + 256); /* Magic number inside toxcore */
free(save);
}
@@ -3,6 +3,9 @@

typedef struct utox_save UTOX_SAVE;

#include "debug.h"

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

@@ -50,7 +53,8 @@ typedef struct utox_settings {
bool status_notifications;
uint8_t group_notifications;

uint8_t verbose;
LOG_LVL verbose;
FILE *debug_file;

uint32_t theme;

Large diffs are not rendered by default.

@@ -4,18 +4,17 @@
#include <inttypes.h>
#include <stddef.h>

enum {
typedef enum {
THEME_DEFAULT,
THEME_LIGHT,
THEME_DARK,
THEME_HIGHCONTRAST,
THEME_CUSTOM,
THEME_ZENBURN, // !!!!
THEME_ZENBURN,
THEME_SOLARIZED_LIGHT,
THEME_SOLARIZED_DARK,
// @TODO
// THEME_XRESOURCE
};
// TODO: THEME_XRESOURCE
} THEME;

/* Colors for drawing the backgrounds */
uint32_t COLOR_BKGRND_MAIN;
@@ -99,8 +98,7 @@ uint32_t COLOR_BTN_INPROGRESS_TEXT;
uint32_t COLOR_BTN_DISABLED_FORGRND;
uint32_t COLOR_BTN_INPROGRESS_FORGRND;

void theme_load(const char loadtheme);
void read_custom_theme(const uint8_t *data, size_t length);
void theme_load(const THEME loadtheme);

uint32_t status_color[4];

133 src/tox.c

Large diffs are not rendered by default.

@@ -3,15 +3,17 @@
#include "file_transfers.h"
#include "friend.h"
#include "groups.h"
#include "logging_native.h"
#include "debug.h"
#include "macros.h"
#include "settings.h"
#include "text.h"
#include "utox.h"
#include "ui.h"

#include "av/audio.h"
#include "av/utox_av.h"


#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -20,7 +22,7 @@ static void callback_friend_request(Tox *UNUSED(tox), const uint8_t *id, const u
void *UNUSED(userdata)) {

if (settings.block_friend_requests) {
debug_warning("Friend request ignored.\n");
LOG_WARN("Tox Callbacks", "Friend request ignored."); // TODO move to friend.c
return;
}

@@ -42,20 +44,22 @@ static void callback_friend_message(Tox *UNUSED(tox), uint32_t friend_number, TO
switch (type) {
case TOX_MESSAGE_TYPE_NORMAL: {
message_add_type_text(&friend[friend_number].msg, 0, (char *)message, length, 1, 0);
debug("Friend(%u) Standard Message: %.*s\n", friend_number, (int)length, message);
LOG_INFO("Tox Callbacks", "Friend\t%u\t--\tStandard Message: %.*s" , friend_number, (int)length, message);
break;
}

case TOX_MESSAGE_TYPE_ACTION: {
message_add_type_action(&friend[friend_number].msg, 0, (char *)message, length, 1, 0);
debug("Friend(%u) Action Message: %.*s\n", friend_number, (int)length, message);
LOG_INFO("Tox Callbacks", "Friend\t%u\t--\tAction Message: %.*s" , friend_number, (int)length, message);
break;
}

default: { debug("Message from Friend(%u) of unsupported type: %.*s\n", friend_number, (int)length, message); }
default: {
LOG_ERR("Tox Callbacks", "Friend\t%u\t--\tUnsupported message type: %.*s" , friend_number, (int)length, message);
break;
}
}
friend_notify_msg(&friend[friend_number], (char *)message, length);
postmessage_utox(FRIEND_MESSAGE, friend_number, 0, NULL);
}

static void callback_name_change(Tox *UNUSED(tox), uint32_t fid, const uint8_t *newname, size_t length,
@@ -64,7 +68,7 @@ static void callback_name_change(Tox *UNUSED(tox), uint32_t fid, const uint8_t *
void *data = malloc(length);
memcpy(data, newname, length);
postmessage_utox(FRIEND_NAME, fid, length, data);
debug_info("Friend-%u Name:\t%.*s\n", fid, (int)length, newname);
LOG_INFO("Tox Callbacks", "Friend\t%u\t--\tName:\t%.*s", fid, (int)length, newname);
}

static void callback_status_message(Tox *UNUSED(tox), uint32_t fid, const uint8_t *newstatus, size_t length,
@@ -73,29 +77,29 @@ static void callback_status_message(Tox *UNUSED(tox), uint32_t fid, const uint8_
void *data = malloc(length);
memcpy(data, newstatus, length);
postmessage_utox(FRIEND_STATUS_MESSAGE, fid, length, data);
debug_info("Friend-%u Status Message:\t%.*s\n", fid, (int)length, newstatus);
LOG_INFO("Tox Callbacks", "Friend\t%u\t--\tStatus Message:\t%.*s", fid, (int)length, newstatus);
}

static void callback_user_status(Tox *UNUSED(tox), uint32_t fid, TOX_USER_STATUS status, void *UNUSED(userdata)) {
postmessage_utox(FRIEND_STATE, fid, status, NULL);
debug_info("Friend-%u State:\t%u\n", fid, status);
LOG_INFO("Tox Callbacks", "Friend\t%u\t--\tState:\t%u", fid, status);
}

static void callback_typing_change(Tox *UNUSED(tox), uint32_t fid, bool is_typing, void *UNUSED(userdata)) {
postmessage_utox(FRIEND_TYPING, fid, is_typing, NULL);
debug_info("Friend-%u Typing:\t%u\n", fid, is_typing);
LOG_DEBUG("Tox Callbacks", "Friend\t%u\t--\tTyping:\t%u", fid, is_typing);
}

static void callback_read_receipt(Tox *UNUSED(tox), uint32_t fid, uint32_t receipt, void *UNUSED(userdata)) {
messages_clear_receipt(&friend[fid].msg, receipt);
debug_info("Friend-%u Receipt:\t%u\n", fid, receipt);
LOG_INFO("Tox Callbacks", "Friend\t%u\t--\tReceipt:\t%u", fid, receipt);
}

static void callback_connection_status(Tox *tox, uint32_t fid, TOX_CONNECTION status, void *UNUSED(userdata)) {
if (friend[fid].online && !status) {
ft_friend_offline(tox, fid);
if (friend[fid].call_state_self || friend[fid].call_state_friend) {
utox_av_local_disconnect(NULL, fid); /* TODO HACK, toxav doesn't supply a toxav_get_toxav_from_otx() yet. */
utox_av_local_disconnect(NULL, fid); /* TODO HACK, toxav doesn't supply a toxav_get_toxav_from_tox() yet. */
}
} else if (!friend[fid].online && !!status) {
ft_friend_online(tox, fid);
@@ -107,11 +111,11 @@ static void callback_connection_status(Tox *tox, uint32_t fid, TOX_CONNECTION st
postmessage_utox(FRIEND_ONLINE, fid, !!status, NULL);

if (status == TOX_CONNECTION_UDP) {
debug_info("Friend-%u:\tOnline (UDP)\n", fid);
LOG_INFO("Tox Callbacks", "Friend\t%u\t--\tOnline (UDP)", fid);
} else if (status == TOX_CONNECTION_TCP) {
debug_info("Friend-%u:\tOnline (TCP)\n", fid);
LOG_INFO("Tox Callbacks", "Friend\t%u\t--\tOnline (TCP)", fid);
} else {
debug_info("Friend-%u:\tOffline\n", fid);
LOG_INFO("Tox Callbacks", "Friend\t%u\t--\tOffline", fid);
friend_notify_status(&friend[fid], NULL, 0, "offline");
}
}
@@ -145,7 +149,7 @@ static void callback_group_invite(Tox *tox, uint32_t fid, TOX_CONFERENCE_TYPE ty
postmessage_utox(GROUP_ADD, gid, 0, tox);
}

debug("Group Invite (%i,f:%i) type %u\n", gid, fid, type);
LOG_TRACE("Tox Callbacks", "Group Invite (%i,f:%i) type %u" , gid, fid, type);
}

static void callback_group_message(Tox *UNUSED(tox), uint32_t gid, uint32_t pid, TOX_MESSAGE_TYPE type,
@@ -154,12 +158,12 @@ static void callback_group_message(Tox *UNUSED(tox), uint32_t gid, uint32_t pid,

switch (type) {
case TOX_MESSAGE_TYPE_ACTION: {
debug("Group Action (%u, %u): %.*s\n", gid, pid, (int)length, message);
LOG_TRACE("Tox Callbacks", "Group Action (%u, %u): %.*s" , gid, pid, (int)length, message);
group_add_message(g, pid, message, length, MSG_TYPE_ACTION_TEXT);
break;
}
case TOX_MESSAGE_TYPE_NORMAL: {
debug_notice("Group Message (%u, %u): %.*s\n", gid, pid, (int)length, message);
LOG_INFO("Tox Callbacks", "Group Message (%u, %u): %.*s", gid, pid, (int)length, message);
group_add_message(g, pid, message, length, MSG_TYPE_TEXT);
break;
}
@@ -179,7 +183,7 @@ static void callback_group_namelist_change(Tox *tox, uint32_t gid, uint32_t pid,
} else {
g->peer = calloc(g->peer_count + 2, sizeof(void *));
}
debug("Group:\tAdd (%u, %u)\n", gid, pid);
LOG_TRACE("Group", "Add (%u, %u)" , gid, pid);
bool is_us = 0;
if (tox_conference_peer_number_is_ours(tox, gid, pid, 0)) {
g->our_peer_number = pid;
@@ -204,15 +208,15 @@ static void callback_group_namelist_change(Tox *tox, uint32_t gid, uint32_t pid,
}

case TOX_CONFERENCE_STATE_CHANGE_PEER_NAME_CHANGE: {
debug("Group:\tPeer name change (%u, %u)\n", gid, pid);
LOG_TRACE("Tox Callbacks", "Group:\tPeer name change (%u, %u)" , gid, pid);

if (g->peer) {
if (!g->peer[pid]) {
debug("Tox Group:\tERROR, can't sent a name, for non-existant peer!\n");
LOG_TRACE("Tox Callbacks", "Tox Group:\tERROR, can't sent a name, for non-existant peer!" );
break;
}
} else {
debug("Tox Group:\tERROR, can't sent a name, for non-existant Group!\n");
LOG_TRACE("Tox Callbacks", "Tox Group:\tERROR, can't sent a name, for non-existant Group!" );
}

uint8_t name[TOX_MAX_NAME_LENGTH];
@@ -226,7 +230,7 @@ static void callback_group_namelist_change(Tox *tox, uint32_t gid, uint32_t pid,
}

case TOX_CONFERENCE_STATE_CHANGE_PEER_EXIT: {
debug("Group:\tPeer Quit (%u, %u)\n", gid, pid);
LOG_TRACE("Group", "Peer Quit (%u, %u)" , gid, pid);
group_add_message(g, pid, (const uint8_t *)"<- has Quit!", 12, MSG_TYPE_NOTICE);

pthread_mutex_lock(&messages_lock); /* make sure that messages has posted before we continue */
@@ -238,8 +242,7 @@ static void callback_group_namelist_change(Tox *tox, uint32_t gid, uint32_t pid,
g->peer = calloc(number_peers, sizeof(void *));

if (!g->peer) {
debug("Group:\tToxcore is very broken, but we couldn't alloc here.");
exit(44);
LOG_FATAL_ERR(EXIT_MALLOC, "Tox Callbacks", "Group:\tToxcore is very broken, but we couldn't alloc here.");
}

/* I'm about to break some uTox style here, because I'm expecting
@@ -250,8 +253,7 @@ static void callback_group_namelist_change(Tox *tox, uint32_t gid, uint32_t pid,
tox_conference_peer_get_name(tox, gid, i, tmp, NULL);
GROUP_PEER *peer = calloc(1, len * sizeof(void *) + sizeof(*peer));
if (!peer) {
debug("Group:\tToxcore is very broken, but we couldn't calloc here.");
exit(45);
LOG_FATAL_ERR(EXIT_MALLOC, "Group", "Toxcore is very broken, but we couldn't calloc here.");
}
/* name and id number (it's worthless, but it's needed */
memcpy(peer->name, tmp, len);
@@ -292,7 +294,7 @@ static void callback_group_topic(Tox *UNUSED(tox), uint32_t gid, uint32_t pid, c
memcpy(copy_title, title, length);
postmessage_utox(GROUP_TOPIC, gid, length, copy_title);

debug("Group Title (%u, %u): %.*s\n", gid, pid, (int)length, title);
LOG_TRACE("Tox Callbacks", "Group Title (%u, %u): %.*s" , gid, pid, (int)length, title);
}

void utox_set_callbacks_groups(Tox *tox) {
@@ -304,7 +306,7 @@ void utox_set_callbacks_groups(Tox *tox) {

#ifdef ENABLE_MULTIDEVICE
static void callback_friend_list_change(Tox *tox, void *user_data) {
debug_error("friend list change, updating roster\n");
LOG_ERR(__FILE__, "friend list change, updating roster");

flist_dump_contacts();
utox_friend_list_init(tox);
@@ -314,7 +316,7 @@ static void callback_friend_list_change(Tox *tox, void *user_data) {
static void callback_mdev_self_name(Tox *tox, uint32_t dev_num, const uint8_t *name, size_t length,
void *UNUSED(userdata)) {

debug_info("Name changed on remote device %u\n", dev_num);
LOG_TRACE("Tox Callbacks", "Name changed on remote device %u", dev_num);

memcpy(self.name, name, length);
self.name_length = length;
@@ -330,7 +332,7 @@ typedef void tox_mdev_self_status_message_cb(Tox *tox, uint32_t device_number, c
static void callback_mdev_self_status_msg(Tox *tox, uint32_t dev_num, const uint8_t *smsg, size_t length,
void *UNUSED(userdata)) {

debug_info("Status Message changed on remote device %u\n", dev_num);
LOG_TRACE("Tox Callbacks", "Status Message changed on remote device %u", dev_num);

memcpy(self.statusmsg, smsg, length);
self.statusmsg_length = length;
@@ -347,7 +349,7 @@ static void callback_mdev_self_state(Tox *tox, uint32_t device_number, TOX_USER_

static void callback_device_sent_message(Tox *tox, uint32_t sending_device, uint32_t target_friend,
TOX_MESSAGE_TYPE type, uint8_t *msg, size_t msg_length) {
debug("Message sent from other device %u\n\t\t%.*s\n", sending_device, (uint32_t)msg_length, msg);
LOG_TRACE("Tox Callbacks", "Message sent from other device %u\n\t\t%.*s" , sending_device, (uint32_t)msg_length, msg);

switch (type) {
case TOX_MESSAGE_TYPE_NORMAL: {
@@ -361,11 +363,11 @@ static void callback_device_sent_message(Tox *tox, uint32_t sending_device, uint
}

default: {
debug_error("Message from Friend(%u) of unsupported type: %.*s\n", target_friend, (uint32_t)msg_length, msg);
LOG_ERR(__FILE__, "Message from Friend\t%u\t--\tof unsupported type: %.*s", target_friend, (uint32_t)msg_length, msg);
}
}
friend_notify_msg(&friend[target_friend], msg, msg_length);
postmessage_utox(FRIEND_MESSAGE, target_friend, 0, NULL);
postmessage_utox(FRIEND_MESSAGE_UPDATE, target_friend, 0, NULL);
}

void utox_set_callbacks_mdevice(Tox *tox) {