about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/ui/window.c57
-rw-r--r--src/xmpp/capabilities.c2
-rw-r--r--src/xmpp/message.c19
-rw-r--r--src/xmpp/stanza.h1
-rw-r--r--src/xmpp/xmpp.h3
5 files changed, 75 insertions, 7 deletions
diff --git a/src/ui/window.c b/src/ui/window.c
index c7bb359a..b031ac22 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -3,6 +3,7 @@
  * vim: expandtab:ts=4:sts=4:sw=4
  *
  * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
+ * Copyright (C) 2019 - 2020 Michael Vetter <jubalh@iodoru.org>
  *
  * This file is part of Profanity.
  *
@@ -49,6 +50,7 @@
 #include <ncurses.h>
 #endif
 
+#include "log.h"
 #include "config/theme.h"
 #include "config/preferences.h"
 #include "ui/ui.h"
@@ -62,8 +64,7 @@
 
 #define CEILING(X) (X-(int)(X) > 0 ? (int)(X+1) : (int)(X))
 
-static void _win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *timestamp,
-    int flags, theme_item_t theme_item, const char *const from, const char *const message, ...);
+static void _win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *timestamp, int flags, theme_item_t theme_item, const char *const from, const char *const message_id, const char *const message, ...);
 static void _win_print(ProfWin *window, const char show_char, int pad_indent, GDateTime *time,
     int flags, theme_item_t theme_item, const char *const from, const char *const message, DeliveryReceipt *receipt);
 static void _win_print_wrapped(WINDOW *win, const char *const message, size_t indent, int pad_indent);
@@ -1056,6 +1057,43 @@ win_show_status_string(ProfWin *window, const char *const from,
 }
 
 void
+win_correct_incoming(ProfWin *window, const char *const message, const char *const id, const char *const replace_id)
+{
+    ProfBuffEntry *entry = buffer_get_entry_by_id(window->layout->buffer, replace_id);
+    if (!entry) {
+        log_debug("Replace ID %s could not be found in buffer. Message: %s", replace_id, message);
+        return;
+    }
+
+    /*
+    if (entry->date) {
+        if (entry->date->timestamp) {
+            g_date_time_unref(entry->date->timestamp);
+        }
+        free(entry->date);
+    }
+
+    entry->date = buffer_date_new_now();
+    */
+
+    // TODO: setting
+    //entry->show_char = prefs_get_correction_char();
+    entry->show_char = '+';
+
+    if (entry->message) {
+        free(entry->message);
+    }
+    entry->message = strdup(message);
+
+    if (entry->id) {
+        free(entry->id);
+    }
+    entry->id = strdup(id);
+
+    win_redraw(window);
+}
+
+void
 win_print_incoming(ProfWin *window, const char *const from, ProfMessage *message)
 {
     char enc_char = '-';
@@ -1079,11 +1117,16 @@ win_print_incoming(ProfWin *window, const char *const from, ProfMessage *message
             } else if (message->enc == PROF_MSG_ENC_OMEMO) {
                 enc_char = prefs_get_omemo_char();
             }
-            _win_printf(window, enc_char, 0, message->timestamp, flags, THEME_TEXT_THEM, from, "%s", message->plain);
+
+            if (message->replace_id) {
+                win_correct_incoming(window, message->plain, message->id, message->replace_id);
+            } else {
+                _win_printf(window, enc_char, 0, message->timestamp, flags, THEME_TEXT_THEM, from, message->id, "%s", message->plain);
+            }
             break;
         }
         case WIN_PRIVATE:
-            _win_printf(window, '-', 0, message->timestamp, flags, THEME_TEXT_THEM, from, "%s", message->plain);
+            _win_printf(window, '-', 0, message->timestamp, flags, THEME_TEXT_THEM, from, message->id, "%s", message->plain);
             break;
         default:
             assert(FALSE);
@@ -1094,7 +1137,7 @@ win_print_incoming(ProfWin *window, const char *const from, ProfMessage *message
 void
 win_print_them(ProfWin *window, theme_item_t theme_item, char ch, int flags, const char *const them)
 {
-    _win_printf(window, ch, 0, NULL, flags | NO_ME | NO_EOL, theme_item, them, "");
+    _win_printf(window, ch, 0, NULL, flags | NO_ME | NO_EOL, theme_item, them, NULL, "");
 }
 
 void
@@ -1373,7 +1416,7 @@ win_newline(ProfWin *window)
 
 static void
 _win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *timestamp,
-    int flags, theme_item_t theme_item, const char *const from, const char *const message, ...)
+    int flags, theme_item_t theme_item, const char *const from, const char *const message_id, const char *const message, ...)
 {
     if (timestamp == NULL) {
         timestamp = g_date_time_new_now_local();
@@ -1386,7 +1429,7 @@ _win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *ti
     GString *fmt_msg = g_string_new(NULL);
     g_string_vprintf(fmt_msg, message, arg);
 
-    buffer_append(window->layout->buffer, show_char, pad_indent, timestamp, flags, theme_item, from, fmt_msg->str, NULL, NULL);
+    buffer_append(window->layout->buffer, show_char, pad_indent, timestamp, flags, theme_item, from, fmt_msg->str, NULL, message_id);
 
     _win_print(window, show_char, pad_indent, timestamp, flags, theme_item, from, fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
diff --git a/src/xmpp/capabilities.c b/src/xmpp/capabilities.c
index e1587ef8..ebccec24 100644
--- a/src/xmpp/capabilities.c
+++ b/src/xmpp/capabilities.c
@@ -110,6 +110,8 @@ caps_init(void)
     if (prefs_get_boolean(PREF_LASTACTIVITY)) {
         g_hash_table_add(prof_features, strdup(STANZA_NS_LASTACTIVITY));
     }
+    //TODO: depend on setting
+    g_hash_table_add(prof_features, strdup(STANZA_NS_LAST_MESSAGE_CORRECTION));
     my_sha1 = NULL;
 }
 
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index 1a97d9f1..f6100fa8 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -188,6 +188,7 @@ message_init(void)
     message->jid = NULL;
     message->id = NULL;
     message->originid = NULL;
+    message->replace_id = NULL;
     message->body = NULL;
     message->encrypted = NULL;
     message->plain = NULL;
@@ -215,6 +216,10 @@ message_free(ProfMessage *message)
         xmpp_free(ctx, message->originid);
     }
 
+    if (message->replace_id) {
+        xmpp_free(ctx, message->replace_id);
+    }
+
     if (message->body) {
         xmpp_free(ctx, message->body);
     }
@@ -1113,6 +1118,20 @@ _handle_chat(xmpp_stanza_t *const stanza)
     ProfMessage *message = message_init();
     message->jid = jid;
 
+    // message stanza id
+    const char *id = xmpp_stanza_get_id(stanza);
+    if (id) {
+        message->id = strdup(id);
+    }
+
+    xmpp_stanza_t *replace_id_stanza = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_LAST_MESSAGE_CORRECTION);
+    if (replace_id_stanza) {
+        const char *replace_id = xmpp_stanza_get_id(replace_id_stanza);
+        if (replace_id) {
+            message->replace_id = strdup(replace_id);
+        }
+    }
+
     if (mucuser) {
         message->mucuser = TRUE;
     }
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index 7b5cbe35..dc8c4e34 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -201,6 +201,7 @@
 #define STANZA_NS_STABLE_ID "urn:xmpp:sid:0"
 #define STANZA_NS_USER_AVATAR_DATA "urn:xmpp:avatar:data"
 #define STANZA_NS_USER_AVATAR_METADATA "urn:xmpp:avatar:metadata"
+#define STANZA_NS_LAST_MESSAGE_CORRECTION "urn:xmpp:message-correct:0"
 
 #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
 
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index f5b4ce70..dc1cdf27 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -68,6 +68,7 @@
 #define XMPP_FEATURE_PUBSUB "http://jabber.org/protocol/pubsub"
 #define XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS "http://jabber.org/protocol/pubsub#publish-options"
 #define XMPP_FEATURE_USER_AVATAR_METADATA_NOTIFY "urn:xmpp:avatar:metadata+notify"
+#define XMPP_FEATURE_LAST_MESSAGE_CORRECTION "urn:xmpp:message-correct:0"
 
 typedef enum {
     JABBER_CONNECTING,
@@ -130,6 +131,8 @@ typedef struct prof_message_t {
    char *id;
    /* </origin-id> XEP-0359 */
    char *originid;
+   /* <replace id> XEP-0308 LMC */
+   char *replace_id;
    /* The raw body from xmpp message, either plaintext or OTR encrypted text */
    char *body;
    /* The encrypted message as for PGP */