about summary refs log tree commit diff stats
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/buffer.c7
-rw-r--r--src/ui/buffer.h7
-rw-r--r--src/ui/chatwin.c25
-rw-r--r--src/ui/console.c13
-rw-r--r--src/ui/mucwin.c23
-rw-r--r--src/ui/privwin.c2
-rw-r--r--src/ui/ui.h6
-rw-r--r--src/ui/win_types.h6
-rw-r--r--src/ui/window.c135
-rw-r--r--src/ui/window.h10
10 files changed, 179 insertions, 55 deletions
diff --git a/src/ui/buffer.c b/src/ui/buffer.c
index 916aba1a..86f87563 100644
--- a/src/ui/buffer.c
+++ b/src/ui/buffer.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.
  *
@@ -81,7 +82,7 @@ buffer_free(ProfBuff buffer)
 
 void
 buffer_append(ProfBuff buffer, 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, const char *const id)
+    int flags, theme_item_t theme_item, const char *const display_from, const char *const message, DeliveryReceipt *receipt, const char *const id)
 {
     ProfBuffEntry *e = malloc(sizeof(struct prof_buff_entry_t));
     e->show_char = show_char;
@@ -89,7 +90,7 @@ buffer_append(ProfBuff buffer, const char show_char, int pad_indent, GDateTime *
     e->flags = flags;
     e->theme_item = theme_item;
     e->time = g_date_time_ref(time);
-    e->from = from ? strdup(from) : NULL;
+    e->display_from = display_from ? strdup(display_from) : NULL;
     e->message = strdup(message);
     e->receipt = receipt;
     if (id) {
@@ -163,7 +164,7 @@ static void
 _free_entry(ProfBuffEntry *entry)
 {
     free(entry->message);
-    free(entry->from);
+    free(entry->display_from);
     free(entry->id);
     free(entry->receipt);
     g_date_time_unref(entry->time);
diff --git a/src/ui/buffer.h b/src/ui/buffer.h
index 10151d17..813ac38e 100644
--- a/src/ui/buffer.h
+++ b/src/ui/buffer.h
@@ -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.
  *
@@ -51,7 +52,9 @@ typedef struct prof_buff_entry_t {
     GDateTime *time;
     int flags;
     theme_item_t theme_item;
-    char *from;
+    // from as it is displayed
+    // might be nick, jid..
+    char *display_from;
     char *message;
     DeliveryReceipt *receipt;
     // message id, in case we have it
@@ -63,7 +66,7 @@ typedef struct prof_buff_t *ProfBuff;
 ProfBuff buffer_create();
 void buffer_free(ProfBuff buffer);
 void buffer_append(ProfBuff buffer, 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, const char *const id);
+    int flags, theme_item_t theme_item, const char *const display_from, const char *const message, DeliveryReceipt *receipt, const char *const id);
 void buffer_remove_entry_by_id(ProfBuff buffer, const char *const id);
 int buffer_size(ProfBuff buffer);
 ProfBuffEntry* buffer_get_entry(ProfBuff buffer, int entry);
diff --git a/src/ui/chatwin.c b/src/ui/chatwin.c
index 8faf4934..4b0fd889 100644
--- a/src/ui/chatwin.c
+++ b/src/ui/chatwin.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.
  *
@@ -56,6 +57,7 @@
 #endif
 
 static void _chatwin_history(ProfChatWin *chatwin, const char *const contact);
+static void _chatwin_set_last_message(ProfChatWin *chatwin, const char *const id, const char *const message);
 
 ProfChatWin*
 chatwin_new(const char *const barejid)
@@ -308,7 +310,7 @@ chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_cr
 
 void
 chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id, prof_enc_t enc_mode,
-    gboolean request_receipt)
+    gboolean request_receipt, const char *const replace_id)
 {
     assert(chatwin != NULL);
 
@@ -324,9 +326,14 @@ chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id,
     }
 
     if (request_receipt && id) {
-        win_print_with_receipt((ProfWin*)chatwin, enc_char, "me", message, id);
+        win_print_outgoing_with_receipt((ProfWin*)chatwin, enc_char, "me", message, id, replace_id);
     } else {
-        win_print_outgoing((ProfWin*)chatwin, enc_char, "%s", message);
+        win_print_outgoing((ProfWin*)chatwin, enc_char, id, replace_id, "%s", message);
+    }
+
+    // save last id and message for LMC
+    if (id) {
+        _chatwin_set_last_message(chatwin, id, message);
     }
 }
 
@@ -344,7 +351,7 @@ chatwin_outgoing_carbon(ProfChatWin *chatwin, ProfMessage *message)
 
     ProfWin *window = (ProfWin*)chatwin;
 
-    win_print_outgoing(window, enc_char, "%s", message->plain);
+    win_print_outgoing(window, enc_char, message->id, message->replace_id, "%s", message->plain);
     int num = wins_get_num(window);
     status_bar_active(num, WIN_CHAT, chatwin->barejid);
 }
@@ -496,3 +503,13 @@ _chatwin_history(ProfChatWin *chatwin, const char *const contact)
         g_slist_free_full(history, free);
     }
 }
+
+static void
+_chatwin_set_last_message(ProfChatWin *chatwin, const char *const id, const char *const message)
+{
+    free(chatwin->last_message);
+    chatwin->last_message = strdup(message);
+
+    free(chatwin->last_msg_id);
+    chatwin->last_msg_id = strdup(id);
+}
diff --git a/src/ui/console.c b/src/ui/console.c
index 1a716a7a..f7fa448d 100644
--- a/src/ui/console.c
+++ b/src/ui/console.c
@@ -2022,6 +2022,19 @@ cons_os_setting(void)
 }
 
 void
+cons_correction_setting(void)
+{
+    if (prefs_get_boolean(PREF_CORRECTION_ALLOW)) {
+        cons_show("Last Message Correction (XEP-0308) (/correction)                   : ON");
+    } else {
+        cons_show("Last Message Correction (XEP-0308) (/correction)                   : OFF");
+    }
+
+    char cc = prefs_get_correction_char();
+    cons_show("LMC indication char (/correction char)                             : %c", cc);
+}
+
+void
 cons_show_connection_prefs(void)
 {
     cons_show("Connection preferences:");
diff --git a/src/ui/mucwin.c b/src/ui/mucwin.c
index 0179c22b..28c3beea 100644
--- a/src/ui/mucwin.c
+++ b/src/ui/mucwin.c
@@ -50,6 +50,8 @@
 #include "omemo/omemo.h"
 #endif
 
+static void _mucwin_set_last_message(ProfMucWin *mucwin, const char *const id, const char *const message);
+
 ProfMucWin*
 mucwin_new(const char *const barejid)
 {
@@ -501,7 +503,7 @@ _mucwin_print_triggers(ProfWin *window, const char *const message, GList *trigge
 }
 
 void
-mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode)
+mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode, const char *const replace_id)
 {
     assert(mucwin != NULL);
 
@@ -519,7 +521,12 @@ mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *c
         ch = prefs_get_omemo_char();
     }
 
-    win_println_me_message(window, ch, mynick, "%s", message);
+    win_print_outgoing_muc_msg(window, ch, mynick, id, replace_id, "%s", message);
+
+    // save last id and message for LMC
+    if (id) {
+        _mucwin_set_last_message(mucwin, id, message);
+    }
 }
 
 void
@@ -559,7 +566,7 @@ mucwin_incoming_msg(ProfMucWin *mucwin, ProfMessage *message, GSList *mentions,
         win_print_them(window, THEME_ROOMTRIGGER, ch, flags, message->jid->resourcepart);
         _mucwin_print_triggers(window, message->plain, triggers);
     } else {
-        win_println_them_message(window, ch, flags, message->jid->resourcepart, "%s", message->plain);
+        win_println_incoming_muc_msg(window, ch, flags, message->jid->resourcepart, message->id, message->replace_id, "%s", message->plain);
     }
 }
 
@@ -951,3 +958,13 @@ mucwin_unset_message_char(ProfMucWin *mucwin)
         mucwin->message_char = NULL;
     }
 }
+
+static void
+_mucwin_set_last_message(ProfMucWin *mucwin, const char *const id, const char *const message)
+{
+    free(mucwin->last_message);
+    mucwin->last_message = strdup(message);
+
+    free(mucwin->last_msg_id);
+    mucwin->last_msg_id = strdup(id);
+}
diff --git a/src/ui/privwin.c b/src/ui/privwin.c
index 4befc325..8fc1bcc7 100644
--- a/src/ui/privwin.c
+++ b/src/ui/privwin.c
@@ -95,7 +95,7 @@ privwin_outgoing_msg(ProfPrivateWin *privwin, const char *const message)
 {
     assert(privwin != NULL);
 
-    win_print_outgoing((ProfWin*)privwin, '-', "%s", message);
+    win_print_outgoing((ProfWin*)privwin, '-', NULL, NULL ,"%s", message);
 }
 
 void
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 4783131e..77bdc1d5 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -124,8 +124,7 @@ ProfChatWin* chatwin_new(const char *const barejid);
 void chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_created);
 void chatwin_receipt_received(ProfChatWin *chatwin, const char *const id);
 void chatwin_recipient_gone(ProfChatWin *chatwin);
-void chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id, prof_enc_t enc_mode,
-    gboolean request_receipt);
+void chatwin_outgoing_msg(ProfChatWin *chatwin, const char *const message, char *id, prof_enc_t enc_mode, gboolean request_receipt, const char *const replace_id);
 void chatwin_outgoing_carbon(ProfChatWin *chatwin, ProfMessage *message);
 void chatwin_contact_online(ProfChatWin *chatwin, Resource *resource, GDateTime *last_activity);
 void chatwin_contact_offline(ProfChatWin *chatwin, char *resource, char *status);
@@ -159,7 +158,7 @@ void mucwin_occupant_role_and_affiliation_change(ProfMucWin *mucwin, const char
     const char *const role, const char *const affiliation, const char *const actor, const char *const reason);
 void mucwin_roster(ProfMucWin *mucwin, GList *occupants, const char *const presence);
 void mucwin_history(ProfMucWin *mucwin, const char *const nick, GDateTime *timestamp, const char *const message);
-void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode);
+void mucwin_outgoing_msg(ProfMucWin *mucwin, const char *const message, const char *const id, prof_enc_t enc_mode, const char *const replace_id);
 void mucwin_incoming_msg(ProfMucWin *mucwin, ProfMessage *message, GSList *mentions, GList *triggers);
 void mucwin_subject(ProfMucWin *mucwin, const char *const nick, const char *const subject);
 void mucwin_requires_config(ProfMucWin *mucwin);
@@ -319,6 +318,7 @@ void cons_statusbar_setting(void);
 void cons_winpos_setting(void);
 void cons_color_setting(void);
 void cons_os_setting(void);
+void cons_correction_setting(void);
 void cons_show_contact_online(PContact contact, Resource *resource, GDateTime *last_activity);
 void cons_show_contact_offline(PContact contact, char *resource, char *status);
 void cons_theme_properties(void);
diff --git a/src/ui/win_types.h b/src/ui/win_types.h
index 68ed719e..81944bc0 100644
--- a/src/ui/win_types.h
+++ b/src/ui/win_types.h
@@ -160,6 +160,9 @@ typedef struct prof_chat_win_t {
     char *enctext;
     char *incoming_char;
     char *outgoing_char;
+    // For LMC
+    char *last_message;
+    char *last_msg_id;
 } ProfChatWin;
 
 typedef struct prof_muc_win_t {
@@ -175,6 +178,9 @@ typedef struct prof_muc_win_t {
     char *enctext;
     char *message_char;
     GDateTime *last_msg_timestamp;
+    // For LMC
+    char *last_message;
+    char *last_msg_id;
 } ProfMucWin;
 
 typedef struct prof_conf_win_t ProfConfWin;
diff --git a/src/ui/window.c b/src/ui/window.c
index c7bb359a..a1c71241 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,9 +64,8 @@
 
 #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_print(ProfWin *window, const char show_char, int pad_indent, GDateTime *time,
+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_internal(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);
 
@@ -151,6 +152,8 @@ win_create_chat(const char *const barejid)
     new_win->enctext = NULL;
     new_win->incoming_char = NULL;
     new_win->outgoing_char = NULL;
+    new_win->last_message = NULL;
+    new_win->last_msg_id = NULL;
 
     new_win->memcheck = PROFCHATWIN_MEMCHECK;
 
@@ -200,6 +203,8 @@ win_create_muc(const char *const roomjid)
     new_win->enctext = NULL;
     new_win->message_char = NULL;
     new_win->is_omemo = FALSE;
+    new_win->last_message = NULL;
+    new_win->last_msg_id = NULL;
 
     new_win->memcheck = PROFMUCWIN_MEMCHECK;
 
@@ -487,6 +492,8 @@ win_free(ProfWin* window)
         free(chatwin->enctext);
         free(chatwin->incoming_char);
         free(chatwin->outgoing_char);
+        free(chatwin->last_message);
+        free(chatwin->last_msg_id);
         chat_state_free(chatwin->state);
         break;
     }
@@ -1055,8 +1062,43 @@ win_show_status_string(ProfWin *window, const char *const from,
     win_appendln(window, presence_colour, "");
 }
 
+static void
+_win_correct(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;
+    }
+
+    /*TODO: set date?
+    if (entry->date) {
+        if (entry->date->timestamp) {
+            g_date_time_unref(entry->date->timestamp);
+        }
+        free(entry->date);
+    }
+
+    entry->date = buffer_date_new_now();
+    */
+
+    entry->show_char = prefs_get_correction_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)
+win_print_incoming(ProfWin *window, const char *const display_name_from, ProfMessage *message)
 {
     char enc_char = '-';
     int flags = NO_ME;
@@ -1079,11 +1121,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 (prefs_get_boolean(PREF_CORRECTION_ALLOW) && message->replace_id) {
+                _win_correct(window, message->plain, message->id, message->replace_id);
+            } else {
+                _win_printf(window, enc_char, 0, message->timestamp, flags, THEME_TEXT_THEM, display_name_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, display_name_from, message->id, "%s", message->plain);
             break;
         default:
             assert(FALSE);
@@ -1094,12 +1141,13 @@ 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
-win_println_them_message(ProfWin *window, char ch, int flags, const char *const them, const char *const message, ...)
+win_println_incoming_muc_msg(ProfWin *window, char ch, int flags, const char *const them, const char *const id, const char *const replace_id, const char *const message, ...)
 {
+    //TODO: we always use current timestamp here. instead of the message->timestamp one if available. i think somewhere else we check whether it exists first.
     GDateTime *timestamp = g_date_time_new_now_local();
 
     va_list arg;
@@ -1107,9 +1155,14 @@ win_println_them_message(ProfWin *window, char ch, int flags, const char *const
     GString *fmt_msg = g_string_new(NULL);
     g_string_vprintf(fmt_msg, message, arg);
 
-    buffer_append(window->layout->buffer, ch, 0, timestamp, flags | NO_ME, THEME_TEXT_THEM, them, fmt_msg->str, NULL, NULL);
+    if (prefs_get_boolean(PREF_CORRECTION_ALLOW) && replace_id) {
+        _win_correct(window, fmt_msg->str, id, replace_id);
+    } else {
+        _win_printf(window, ch, 0, timestamp, flags | NO_ME, THEME_TEXT_THEM, them, id, "%s", fmt_msg->str);
+    }
+//    buffer_append(window->layout->buffer, ch, 0, timestamp, flags | NO_ME, THEME_TEXT_THEM, them, fmt_msg->str, NULL, NULL);
+ //   _win_print_internal(window, ch, 0, timestamp, flags | NO_ME, THEME_TEXT_THEM, them, fmt_msg->str, NULL);
 
-    _win_print(window, ch, 0, timestamp, flags | NO_ME, THEME_TEXT_THEM, them, fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
 
@@ -1118,7 +1171,7 @@ win_println_them_message(ProfWin *window, char ch, int flags, const char *const
 }
 
 void
-win_println_me_message(ProfWin *window, char ch, const char *const me, const char *const message, ...)
+win_print_outgoing_muc_msg(ProfWin *window, char ch, const char *const me, const char *const id, const char *const replace_id, const char *const message, ...)
 {
     GDateTime *timestamp = g_date_time_new_now_local();
 
@@ -1127,9 +1180,14 @@ win_println_me_message(ProfWin *window, char ch, const char *const me, const cha
     GString *fmt_msg = g_string_new(NULL);
     g_string_vprintf(fmt_msg, message, arg);
 
-    buffer_append(window->layout->buffer, ch, 0, timestamp, 0, THEME_TEXT_ME, me, fmt_msg->str, NULL, NULL);
+    if (prefs_get_boolean(PREF_CORRECTION_ALLOW) && replace_id) {
+        _win_correct(window, fmt_msg->str, id, replace_id);
+    } else {
+        _win_printf(window, ch, 0, timestamp, 0, THEME_TEXT_ME, me, id, "%s", fmt_msg->str);
+    }
+//    buffer_append(window->layout->buffer, ch, 0, timestamp, 0, THEME_TEXT_ME, me, fmt_msg->str, NULL, NULL);
+//    _win_print_internal(window, ch, 0, timestamp, 0, THEME_TEXT_ME, me, fmt_msg->str, NULL);
 
-    _win_print(window, ch, 0, timestamp, 0, THEME_TEXT_ME, me, fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
 
@@ -1138,7 +1196,7 @@ win_println_me_message(ProfWin *window, char ch, const char *const me, const cha
 }
 
 void
-win_print_outgoing(ProfWin *window, const char ch, const char *const message, ...)
+win_print_outgoing(ProfWin *window, const char ch, const char *const id, const char *const replace_id, const char *const message, ...)
 {
     GDateTime *timestamp = g_date_time_new_now_local();
 
@@ -1147,9 +1205,12 @@ win_print_outgoing(ProfWin *window, const char ch, const char *const message, ..
     GString *fmt_msg = g_string_new(NULL);
     g_string_vprintf(fmt_msg, message, arg);
 
-    buffer_append(window->layout->buffer, ch, 0, timestamp, 0, THEME_TEXT_ME, "me", fmt_msg->str, NULL, NULL);
+    if (replace_id) {
+        _win_correct(window, fmt_msg->str, id, replace_id);
+    } else {
+        _win_printf(window, ch, 0, timestamp, 0, THEME_TEXT_THEM, "me", id, "%s", fmt_msg->str);
+    }
 
-    _win_print(window, ch, 0, timestamp, 0, THEME_TEXT_ME, "me", fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
 
@@ -1168,7 +1229,7 @@ win_print_history(ProfWin *window, GDateTime *timestamp, const char *const messa
     g_string_vprintf(fmt_msg, message, arg);
 
     buffer_append(window->layout->buffer, '-', 0, timestamp, 0, THEME_TEXT_HISTORY, "", fmt_msg->str, NULL, NULL);
-    _win_print(window, '-', 0, timestamp, 0, THEME_TEXT_HISTORY, "", fmt_msg->str, NULL);
+    _win_print_internal(window, '-', 0, timestamp, 0, THEME_TEXT_HISTORY, "", fmt_msg->str, NULL);
 
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
@@ -1188,8 +1249,8 @@ win_print(ProfWin *window, theme_item_t theme_item, const char ch, const char *c
     g_string_vprintf(fmt_msg, message, arg);
 
     buffer_append(window->layout->buffer, ch, 0, timestamp, NO_EOL, theme_item, "", fmt_msg->str, NULL, NULL);
+    _win_print_internal(window, ch, 0, timestamp, NO_EOL, theme_item, "", fmt_msg->str, NULL);
 
-    _win_print(window, ch, 0, timestamp, NO_EOL, theme_item, "", fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
 
@@ -1208,8 +1269,8 @@ win_println(ProfWin *window, theme_item_t theme_item, const char ch, const char
     g_string_vprintf(fmt_msg, message, arg);
 
     buffer_append(window->layout->buffer, ch, 0, timestamp, 0, theme_item, "", fmt_msg->str, NULL, NULL);
+    _win_print_internal(window, ch, 0, timestamp, 0, theme_item, "", fmt_msg->str, NULL);
 
-    _win_print(window, ch, 0, timestamp, 0, theme_item, "", fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
 
@@ -1228,8 +1289,8 @@ win_println_indent(ProfWin *window, int pad, const char *const message, ...)
     g_string_vprintf(fmt_msg, message, arg);
 
     buffer_append(window->layout->buffer, '-', pad, timestamp, 0, THEME_DEFAULT, "", fmt_msg->str, NULL, NULL);
+    _win_print_internal(window, '-', pad, timestamp, 0, THEME_DEFAULT, "", fmt_msg->str, NULL);
 
-    _win_print(window, '-', pad, timestamp, 0, THEME_DEFAULT, "", fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
 
@@ -1248,8 +1309,8 @@ win_append(ProfWin *window, theme_item_t theme_item, const char *const message,
     g_string_vprintf(fmt_msg, message, arg);
 
     buffer_append(window->layout->buffer, '-', 0, timestamp, NO_DATE | NO_EOL, theme_item, "", fmt_msg->str, NULL, NULL);
+    _win_print_internal(window, '-', 0, timestamp, NO_DATE | NO_EOL, theme_item, "", fmt_msg->str, NULL);
 
-    _win_print(window, '-', 0, timestamp, NO_DATE | NO_EOL, theme_item, "", fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
 
@@ -1268,8 +1329,8 @@ win_appendln(ProfWin *window, theme_item_t theme_item, const char *const message
     g_string_vprintf(fmt_msg, message, arg);
 
     buffer_append(window->layout->buffer, '-', 0, timestamp, NO_DATE, theme_item, "", fmt_msg->str, NULL, NULL);
+    _win_print_internal(window, '-', 0, timestamp, NO_DATE, theme_item, "", fmt_msg->str, NULL);
 
-    _win_print(window, '-', 0, timestamp, NO_DATE, theme_item, "", fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
 
@@ -1288,8 +1349,8 @@ win_append_highlight(ProfWin *window, theme_item_t theme_item, const char *const
     g_string_vprintf(fmt_msg, message, arg);
 
     buffer_append(window->layout->buffer, '-', 0, timestamp, NO_DATE | NO_ME | NO_EOL, theme_item, "", fmt_msg->str, NULL, NULL);
+    _win_print_internal(window, '-', 0, timestamp, NO_DATE | NO_ME | NO_EOL, theme_item, "", fmt_msg->str, NULL);
 
-    _win_print(window, '-', 0, timestamp, NO_DATE | NO_ME | NO_EOL, theme_item, "", fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
 
@@ -1308,8 +1369,8 @@ win_appendln_highlight(ProfWin *window, theme_item_t theme_item, const char *con
     g_string_vprintf(fmt_msg, message, arg);
 
     buffer_append(window->layout->buffer, '-', 0, timestamp, NO_DATE | NO_ME, theme_item, "", fmt_msg->str, NULL, NULL);
+    _win_print_internal(window, '-', 0, timestamp, NO_DATE | NO_ME, theme_item, "", fmt_msg->str, NULL);
 
-    _win_print(window, '-', 0, timestamp, NO_DATE | NO_ME, theme_item, "", fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
 
@@ -1320,19 +1381,24 @@ win_appendln_highlight(ProfWin *window, theme_item_t theme_item, const char *con
 void
 win_print_http_upload(ProfWin *window, const char *const message, char *url)
 {
-    win_print_with_receipt(window, '!', NULL, message, url);
+    win_print_outgoing_with_receipt(window, '!', NULL, message, url, NULL);
 }
 
 void
-win_print_with_receipt(ProfWin *window, const char show_char, const char *const from, const char *const message, char *id)
+win_print_outgoing_with_receipt(ProfWin *window, const char show_char, const char *const from, const char *const message, char *id, const char *const replace_id)
 {
     GDateTime *time = g_date_time_new_now_local();
 
     DeliveryReceipt *receipt = malloc(sizeof(struct delivery_receipt_t));
     receipt->received = FALSE;
 
-    buffer_append(window->layout->buffer, show_char, 0, time, 0, THEME_TEXT_ME, from, message, receipt, id);
-    _win_print(window, show_char, 0, time, 0, THEME_TEXT_ME, from, message, receipt);
+    if (replace_id) {
+        _win_correct(window, message, id, replace_id);
+    } else {
+        buffer_append(window->layout->buffer, show_char, 0, time, 0, THEME_TEXT_ME, from, message, receipt, id);
+        _win_print_internal(window, show_char, 0, time, 0, THEME_TEXT_ME, from, message, receipt);
+    }
+
     // TODO: cross-reference.. this should be replaced by a real event-based system
     inp_nonblocking(TRUE);
     g_date_time_unref(time);
@@ -1373,7 +1439,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,9 +1452,10 @@ _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_internal(window, show_char, pad_indent, timestamp, flags, theme_item, from, fmt_msg->str, NULL);
 
-    _win_print(window, show_char, pad_indent, timestamp, flags, theme_item, from, fmt_msg->str, NULL);
     inp_nonblocking(TRUE);
     g_date_time_unref(timestamp);
 
@@ -1397,7 +1464,7 @@ _win_printf(ProfWin *window, const char show_char, int pad_indent, GDateTime *ti
 }
 
 static void
-_win_print(ProfWin *window, const char show_char, int pad_indent, GDateTime *time,
+_win_print_internal(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)
 {
     // flags : 1st bit =  0/1 - me/not me
@@ -1676,12 +1743,12 @@ win_redraw(ProfWin *window)
     for (i = 0; i < size; i++) {
         ProfBuffEntry *e = buffer_get_entry(window->layout->buffer, i);
 
-        if (e->from == NULL && e->message && e->message[0] == '-') {
+        if (e->display_from == NULL && e->message && e->message[0] == '-') {
             // just an indicator to print the separator not the actual message
             win_print_separator(window);
         } else {
             // regular thing to print
-            _win_print(window, e->show_char, e->pad_indent, e->time, e->flags, e->theme_item, e->from, e->message, e->receipt);
+            _win_print_internal(window, e->show_char, e->pad_indent, e->time, e->flags, e->theme_item, e->display_from, e->message, e->receipt);
         }
     }
 }
diff --git a/src/ui/window.h b/src/ui/window.h
index b1f9a4af..2bd11621 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -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.
  *
@@ -62,17 +63,16 @@ void win_show_status_string(ProfWin *window, const char *const from,
     const char *const default_show);
 
 void win_print_them(ProfWin *window, theme_item_t theme_item, char ch, int flags, const char *const them);
-void win_println_them_message(ProfWin *window, char ch, int flags, const char *const them, const char *const message, ...);
-void win_println_me_message(ProfWin *window, char ch, const char *const me, const char *const message, ...);
+void win_println_incoming_muc_msg(ProfWin *window, char ch, int flags, const char *const them, const char *const id, const char *const replace_id, const char *const message, ...);
+void win_print_outgoing_muc_msg(ProfWin *window, char ch, const char *const me, const char *const id, const char *const replace_id, const char *const message, ...);
 
-void win_print_outgoing(ProfWin *window, const char ch, const char *const message, ...);
+void win_print_outgoing(ProfWin *window, const char ch, const char *const id, const char *const replace_id, const char *const message, ...);
 void win_print_incoming(ProfWin *window, const char *const from, ProfMessage *message);
 void win_print_history(ProfWin *window, GDateTime *timestamp, const char *const message, ...);
 
 void win_print_http_upload(ProfWin *window, const char *const message, char *url);
 
-void win_print_with_receipt(ProfWin *window, const char show_char, const char *const from, const char *const message,
-    char *id);
+void win_print_outgoing_with_receipt(ProfWin *window, const char show_char, const char *const from, const char *const message, char *id, const char *const replace_id);
 
 void win_newline(ProfWin *window);
 void win_redraw(ProfWin *window);