diff options
author | xengineering <me@xengineering.eu> | 2022-08-19 10:51:24 +0200 |
---|---|---|
committer | xengineering <me@xengineering.eu> | 2022-08-19 12:13:49 +0200 |
commit | 43aa02ccbd484d8c7cecec7c38c446847b34e007 (patch) | |
tree | 5e34779ee75c8788760d74a9f73a01575c335f54 | |
parent | 4c848f4085cd174d1ad54169632a95023774717b (diff) | |
download | limox-43aa02ccbd484d8c7cecec7c38c446847b34e007.tar limox-43aa02ccbd484d8c7cecec7c38c446847b34e007.tar.zst limox-43aa02ccbd484d8c7cecec7c38c446847b34e007.zip |
Implement new datastructures
-rw-r--r-- | data.c | 95 | ||||
-rw-r--r-- | data.h | 38 | ||||
-rw-r--r-- | gtk.c | 39 | ||||
-rw-r--r-- | gui.h | 13 | ||||
-rw-r--r-- | limox.c | 19 | ||||
-rw-r--r-- | limox.h | 5 |
6 files changed, 133 insertions, 76 deletions
@@ -5,36 +5,34 @@ #include <stdio.h> #include "gui.h" +#include "data.h" -// https://www.rfc-editor.org/rfc/rfc6121#section-2.1.2.5 -typedef enum { - SUB_NONE, - SUB_TO, - SUB_FROM, - SUB_BOTH -} subscription_t; +static roster_item_t* roster = NULL; -typedef struct _roster_item_t { - const char* name; - const char* jid; - subscription_t sub; - void* widget; // the roster item in the contact list view - void* page_widget; // the chat page corresponding to this roster item - struct _roster_item_t* next; -} roster_item_t; +void data_add_roster_item(const char* jid, const char* subscription, + const char* name) { -// the RAM-stored data payload -static roster_item_t* roster = NULL; + // FIXME check if roster item already exists and handle updates + // allocate datastructures + roster_item_t* item = malloc(sizeof(roster_item_t)); + chat_t* chat = malloc(sizeof(chat_t)); -void add_roster_item(const char* jid, const char* subscription, const char* name) { + // initialize chat + chat->messages = NULL; + gui_add_chat_widget(chat); - // parse roster item - roster_item_t* item = malloc(sizeof(roster_item_t)); - item->name = name; - item->jid = jid; + // initialize roster item + if (name == NULL) { + item->name = NULL; + } else { + item->name = malloc(sizeof(char)*strlen(name)); + strcpy(item->name, name); + } + item->jid = malloc(sizeof(char)*strlen(jid)); + strcpy(item->jid, jid); if (strcmp(subscription, "none") == 0) { item->sub = SUB_NONE; } else if (strcmp(subscription, "to") == 0) { @@ -47,7 +45,9 @@ void add_roster_item(const char* jid, const char* subscription, const char* name printf("Invalid subscription '%s'!\n", subscription); return; } + item->chat = chat; item->next = NULL; + gui_add_roster_item_widget(item); // add item to roster datastructure if (roster == NULL) { @@ -59,29 +59,40 @@ void add_roster_item(const char* jid, const char* subscription, const char* name current->next = item; } - // notify GUI - item->widget = gui_add_roster_item(jid, subscription, name); - item->page_widget = gui_add_chat(); - } -void* data_get_chat_page(void* roster_item_widget) { - - if (roster == NULL) { - printf("Empty roster!\n"); - exit(1); - } else { - roster_item_t* current = roster; - while (1) { - if (current->widget == roster_item_widget) { - return current->page_widget; - } - if (current->next == NULL) { - printf("Could not find matching roster item!\n"); - exit(1); - } - current = current->next; +void data_add_incoming_message(const char* sender_jid, const char* content) { + + // find correct chat + chat_t* chat = NULL; + roster_item_t* i; + int bare_len; // length of bare JID + for (i = roster; i != NULL; i=i->next) { + bare_len = strlen(i->jid); + if (strncmp(i->jid, sender_jid, bare_len) == 0) { + chat = i->chat; + break; } } + if (chat == NULL) { + printf("Could not find chat for message from '%s'!\n", sender_jid); + return; + } + + // initialize message_t + message_t* msg = malloc(sizeof(message_t)); + msg->sender_jid = malloc(sizeof(char)*strlen(sender_jid)); + strcpy(msg->sender_jid, sender_jid); + msg->content = malloc(sizeof(char)*strlen(content)); + strcpy(msg->content, content); + msg->next = NULL; + gui_add_message_widget(msg, i->chat); + + // find pointer to next message of chat + message_t* m; + for (m = chat->messages; m != NULL; m=m->next); + + // append message to chat + m = msg; } @@ -1,2 +1,36 @@ -void add_roster_item(const char* jid, const char* subscription, const char* name); -void* data_get_chat_page(void* roster_item_widget); +#ifndef DATA_H +#define DATA_H + +// https://www.rfc-editor.org/rfc/rfc6121#section-2.1.2.5 +typedef enum { + SUB_NONE, + SUB_TO, + SUB_FROM, + SUB_BOTH +} subscription_t; + +typedef struct _message_t { + char* content; + char* sender_jid; + struct _message_t* next; + void* widget; +} message_t; + +typedef struct _chat_t { + message_t* messages; + void* widget; +} chat_t; + +typedef struct _roster_item_t { + char* name; // could be NULL + char* jid; + subscription_t sub; + chat_t* chat; + struct _roster_item_t* next; + void* widget; +} roster_item_t; + +void data_add_roster_item(const char* jid, const char* subscription, + const char* name); +void data_add_incoming_message(const char* sender_jid, const char* content); +#endif @@ -185,7 +185,7 @@ static void to_roster(void) { } -void* gui_add_chat(void) { +void gui_add_chat_widget(chat_t* chat) { // create chat page (GtkBox) and add it to the stack GtkWidget* chat_layout_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 20); @@ -206,6 +206,9 @@ void* gui_add_chat(void) { gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scrolled), chat_content_box); + // save widget pointer + chat->widget = (void*)chat_content_box; + // create and add text input field GtkWidget* text_entry = gtk_entry_new(); gtk_box_append(GTK_BOX(chat_layout_box), text_entry); @@ -216,44 +219,46 @@ void* gui_add_chat(void) { //g_signal_connect_swapped(send_button, "clicked", G_CALLBACK(send_message), // chat); // TODO - // return chat page as void pointer for future reference - return (void*)chat_layout_box; - } -void gui_add_message(const char* sender_jid, const char* content) { +void gui_add_message_widget(message_t* message, chat_t* chat) { - printf("Received from %s:\n%s\n", sender_jid, content); + // TODO + printf("Received from %s:\n%s\n", message->sender_jid, message->content); } -static void to_chat(GtkWidget* roster_item_widget) { +static void to_chat(chat_t* chat) { - GtkWidget* chat_page = data_get_chat_page((void*)roster_item_widget); + //GtkWidget* chat_page = data_get_chat_page((void*)roster_item_widget); + GtkWidget* chat_page = chat->widget; // initialize as a far child + for (int i=0; i<3; i++) { // and then jump three levels up + chat_page = gtk_widget_get_parent(chat_page); + } gtk_stack_set_visible_child(GTK_STACK(stack), chat_page); } -void* gui_add_roster_item(const char* jid, const char* sub, const char* name) { +void gui_add_roster_item_widget(roster_item_t* item) { // print debug message - if (name) { - printf("roster item: %s, %s, sub:%s\n", name, jid, sub); + if (item->name) { + printf("roster item: %s, %s, sub:%d\n", item->name, item->jid, + item->sub); } else { - printf("roster item: (no name), %s, sub:%s\n", jid, sub); + printf("roster item: (no name), %s, sub:%d\n", item->jid, item->sub); } // create widget for roster item GtkWidget* roster_item_widget; - if (name == NULL || strcmp(name, "") == 0) { - roster_item_widget = gtk_button_new_with_label(name); + if (item->name == NULL || strcmp(item->name, "") == 0) { + roster_item_widget = gtk_button_new_with_label(item->jid); } else { - roster_item_widget = gtk_button_new_with_label(jid); + roster_item_widget = gtk_button_new_with_label(item->name); } // add roster item widget to roster page gtk_box_append(GTK_BOX(roster_content_box), roster_item_widget); g_signal_connect_swapped(roster_item_widget, "clicked", G_CALLBACK(to_chat), - roster_item_widget); + item->chat); - return (void*)roster_item_widget; } @@ -1,3 +1,8 @@ +#ifndef GUI_H +#define GUI_H + +#include "data.h" + // interface for main.c void gui_run(void); @@ -6,6 +11,8 @@ void gui_connected(char* jid, char* password); void gui_disconnected(void); void gui_suspended(void); void gui_resumed(void); -void* gui_add_chat(void); -void gui_add_message(const char* sender_jid, const char* content); -void* gui_add_roster_item(const char* jid, const char* sub, const char* name); +void gui_add_roster_item_widget(roster_item_t* item); +void gui_add_chat_widget(chat_t* chat); +void gui_add_message_widget(message_t* message, chat_t* chat); + +#endif @@ -40,19 +40,16 @@ static xmpp_sm_state_t* sm_state; static int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { - // local variables - xmpp_stanza_t* body; - const char* content; - - body = xmpp_stanza_get_child_by_name(stanza, "body"); + xmpp_stanza_t* body = xmpp_stanza_get_child_by_name(stanza, "body"); if (body == NULL) { printf("DEBUG: Got message stanza of type char without body!\n"); return 1; } - content = xmpp_stanza_get_text(body); + const char* content = xmpp_stanza_get_text(body); + const char* sender = xmpp_stanza_get_from(stanza); - gui_add_message(xmpp_stanza_get_from(stanza), content); + data_add_incoming_message(sender, content); return 1; } @@ -60,16 +57,14 @@ static int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, static int roster_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) { - printf("DEBUG: Received roster.\n"); - // iterate over roster result xmpp_stanza_t* query = xmpp_stanza_get_child_by_name(stanza, "query"); for (xmpp_stanza_t* item = xmpp_stanza_get_children(query); item; item = xmpp_stanza_get_next(item)) { - add_roster_item(xmpp_stanza_get_attribute(item, "jid"), - xmpp_stanza_get_attribute(item, "subscription"), - xmpp_stanza_get_attribute(item, "name")); + data_add_roster_item(xmpp_stanza_get_attribute(item, "jid"), + xmpp_stanza_get_attribute(item, "subscription"), + xmpp_stanza_get_attribute(item, "name")); } return 1; @@ -1,3 +1,6 @@ +#ifndef LIMOX_H +#define LIMOX_H + // life cycle / event loop related functions void limox_init(void); // initialize limox void limox_run_once(void); // process event loop for a short amount of time @@ -6,3 +9,5 @@ void limox_quit(void); // disconnect and clean up // interface for the GUI implementation void limox_connect(const char* jid, const char* password); void limox_disconnect(void); + +#endif |