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/console.c8
-rw-r--r--src/ui/ui.h8
-rw-r--r--src/ui/vcardwin.c75
-rw-r--r--src/ui/win_types.h12
-rw-r--r--src/ui/window.c189
-rw-r--r--src/ui/window_list.c33
-rw-r--r--src/ui/window_list.h2
7 files changed, 326 insertions, 1 deletions
diff --git a/src/ui/console.c b/src/ui/console.c
index 822e6d3e..e7b656f5 100644
--- a/src/ui/console.c
+++ b/src/ui/console.c
@@ -1517,6 +1517,10 @@ cons_time_setting(void)
     char* pref_time_lastactivity = prefs_get_string(PREF_TIME_LASTACTIVITY);
     cons_show("Time last activity (/time)          : %s", pref_time_lastactivity);
     g_free(pref_time_lastactivity);
+
+    char* pref_time_vcard = prefs_get_string(PREF_TIME_VCARD);
+    cons_show("Time vCard (/time)                  : %s", pref_time_vcard);
+    g_free(pref_time_vcard);
 }
 
 void
@@ -2262,6 +2266,10 @@ cons_executable_setting(void)
     gchar* editor = prefs_get_string(PREF_COMPOSE_EDITOR);
     cons_show("Default '/editor' command (/executable editor)                           : %s", editor);
     g_free(editor);
+
+    gchar* vcard_cmd = prefs_get_string(PREF_VCARD_PHOTO_CMD);
+    cons_show("Default '/vcard photo open' command (/executable vcard_photo)            : %s", vcard_cmd);
+    g_free(vcard_cmd);
 }
 
 void
diff --git a/src/ui/ui.h b/src/ui/ui.h
index a3377690..78632aa0 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -230,6 +230,11 @@ char* confwin_get_string(ProfConfWin* confwin);
 void xmlwin_show(ProfXMLWin* xmlwin, const char* const msg);
 char* xmlwin_get_string(ProfXMLWin* xmlwin);
 
+// vCard window
+void vcardwin_show_vcard_config(ProfVcardWin* vcardwin);
+char* vcardwin_get_string(ProfVcardWin* vcardwin);
+void vcardwin_update(void);
+
 // Input window
 char* inp_readline(void);
 void inp_nonblocking(gboolean reset);
@@ -371,6 +376,7 @@ ProfWin* win_create_muc(const char* const roomjid);
 ProfWin* win_create_config(const char* const title, DataForm* form, ProfConfWinCallback submit, ProfConfWinCallback cancel, const void* userdata);
 ProfWin* win_create_private(const char* const fulljid);
 ProfWin* win_create_plugin(const char* const plugin_name, const char* const tag);
+ProfWin* win_create_vcard(vCard* vcard);
 void win_update_virtual(ProfWin* window);
 void win_free(ProfWin* window);
 gboolean win_notify_remind(ProfWin* window);
@@ -396,6 +402,8 @@ void win_show_occupant(ProfWin* window, Occupant* occupant);
 void win_show_occupant_info(ProfWin* window, const char* const room, Occupant* occupant);
 void win_show_contact(ProfWin* window, PContact contact);
 void win_show_info(ProfWin* window, PContact contact);
+void win_show_vcard(ProfWin* window, vCard* vcard);
+
 void win_clear(ProfWin* window);
 char* win_get_tab_identifier(ProfWin* window);
 char* win_to_string(ProfWin* window);
diff --git a/src/ui/vcardwin.c b/src/ui/vcardwin.c
new file mode 100644
index 00000000..a49f240c
--- /dev/null
+++ b/src/ui/vcardwin.c
@@ -0,0 +1,75 @@
+/*
+ * vcardwin.c
+ * vim: expandtab:ts=4:sts=4:sw=4
+ *
+ * Copyright (C) 2022 Marouane L. <techmetx11@disroot.org>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ */
+
+#include "ui/ui.h"
+#include "ui/window_list.h"
+#include "xmpp/vcard.h"
+
+void
+vcardwin_show_vcard_config(ProfVcardWin* vcardwin)
+{
+    ProfWin* window = &vcardwin->window;
+
+    win_clear(window);
+    win_show_vcard(window, vcardwin->vcard);
+
+    win_println(window, THEME_DEFAULT, "-", "Use '/vcard save' to save changes.");
+    win_println(window, THEME_DEFAULT, "-", "Use '/help vcard' for more information.");
+}
+
+char*
+vcardwin_get_string(ProfVcardWin* vcardwin)
+{
+    GString* string = g_string_new("vCard: ");
+    char* jid = connection_get_barejid();
+    g_string_append(string, jid);
+
+    if (vcardwin->vcard && vcardwin->vcard->modified) {
+        g_string_append(string, " (modified)");
+    }
+
+    free(jid);
+    return g_string_free(string, FALSE);
+}
+
+void
+vcardwin_update(void)
+{
+    ProfVcardWin* win = wins_get_vcard();
+
+    if (win) {
+        vcardwin_show_vcard_config(win);
+    }
+}
diff --git a/src/ui/win_types.h b/src/ui/win_types.h
index 70d226b0..b7cd3519 100644
--- a/src/ui/win_types.h
+++ b/src/ui/win_types.h
@@ -52,6 +52,7 @@
 #include "tools/autocomplete.h"
 #include "ui/buffer.h"
 #include "xmpp/chat_state.h"
+#include "xmpp/vcard.h"
 
 #define LAYOUT_SPLIT_MEMCHECK   12345671
 #define PROFCHATWIN_MEMCHECK    22374522
@@ -60,6 +61,7 @@
 #define PROFCONFWIN_MEMCHECK    64334685
 #define PROFXMLWIN_MEMCHECK     87333463
 #define PROFPLUGINWIN_MEMCHECK  43434777
+#define PROFVCARDWIN_MEMCHECK   68947523
 
 typedef enum {
     FIELD_HIDDEN,
@@ -140,7 +142,8 @@ typedef enum {
     WIN_CONFIG,
     WIN_PRIVATE,
     WIN_XML,
-    WIN_PLUGIN
+    WIN_PLUGIN,
+    WIN_VCARD
 } win_type_t;
 
 typedef struct prof_win_t
@@ -239,4 +242,11 @@ typedef struct prof_plugin_win_t
     unsigned long memcheck;
 } ProfPluginWin;
 
+typedef struct prof_vcard_win_t
+{
+    ProfWin window;
+    vCard* vcard;
+    unsigned long memcheck;
+} ProfVcardWin;
+
 #endif
diff --git a/src/ui/window.c b/src/ui/window.c
index e25002d6..fbff3374 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -281,6 +281,19 @@ win_create_plugin(const char* const plugin_name, const char* const tag)
     return &new_win->window;
 }
 
+ProfWin*
+win_create_vcard(vCard* vcard)
+{
+    ProfVcardWin* new_win = malloc(sizeof(ProfVcardWin));
+    new_win->window.type = WIN_VCARD;
+    new_win->window.layout = _win_create_simple_layout();
+
+    new_win->vcard = vcard;
+    new_win->memcheck = PROFVCARDWIN_MEMCHECK;
+
+    return &new_win->window;
+}
+
 char*
 win_get_title(ProfWin* window)
 {
@@ -351,7 +364,22 @@ win_get_title(ProfWin* window)
         assert(pluginwin->memcheck == PROFPLUGINWIN_MEMCHECK);
         return strdup(pluginwin->tag);
     }
+    if (window->type == WIN_VCARD) {
+        ProfVcardWin* vcardwin = (ProfVcardWin*)window;
+        assert(vcardwin->memcheck == PROFVCARDWIN_MEMCHECK);
+
+        GString* title = g_string_new("vCard ");
+        char* jid = connection_get_barejid();
+
+        g_string_append(title, jid);
+
+        if (vcardwin->vcard->modified) {
+            g_string_append(title, " *");
+        }
 
+        free(jid);
+        return g_string_free(title, FALSE);
+    }
     return NULL;
 }
 
@@ -474,6 +502,11 @@ win_to_string(ProfWin* window)
         g_string_free(gstring, FALSE);
         return res;
     }
+    case WIN_VCARD:
+    {
+        ProfVcardWin* vcardwin = (ProfVcardWin*)window;
+        return vcardwin_get_string(vcardwin);
+    }
     default:
         return NULL;
     }
@@ -1083,6 +1116,162 @@ win_show_info(ProfWin* window, PContact contact)
 }
 
 void
+win_show_vcard(ProfWin* window, vCard* vcard)
+{
+    GList* pointer;
+    int index = 0;
+
+    if (vcard->fullname) {
+        win_println(window, THEME_DEFAULT, "!", "Full name: %s", vcard->fullname);
+    }
+    if (vcard->name.family || vcard->name.given || vcard->name.middle || vcard->name.prefix || vcard->name.suffix) {
+        win_println(window, THEME_DEFAULT, "!", "Name: ");
+        if (vcard->name.family) {
+            win_println(window, THEME_DEFAULT, "!", "    Family: %s", vcard->name.family);
+        }
+        if (vcard->name.given) {
+            win_println(window, THEME_DEFAULT, "!", "    Given: %s", vcard->name.given);
+        }
+        if (vcard->name.middle) {
+            win_println(window, THEME_DEFAULT, "!", "    Middle: %s", vcard->name.middle);
+        }
+        if (vcard->name.prefix) {
+            win_println(window, THEME_DEFAULT, "!", "    Prefix: %s", vcard->name.prefix);
+        }
+        if (vcard->name.suffix) {
+            win_println(window, THEME_DEFAULT, "!", "    Suffix: %s", vcard->name.suffix);
+        }
+    }
+    index = 0;
+    for (pointer = g_queue_peek_head_link(vcard->elements); pointer != NULL; pointer = pointer->next, index++) {
+        assert(pointer->data != NULL);
+        vcard_element_t* element = (vcard_element_t*)pointer->data;
+
+        switch (element->type) {
+        case VCARD_NICKNAME:
+        {
+            win_println(window, THEME_DEFAULT, "!", "[%d] Nickname: %s", index, element->nickname);
+            break;
+        }
+        case VCARD_PHOTO:
+        {
+            if (element->photo.external) {
+                win_println(window, THEME_DEFAULT, "!", "[%d] Photo, External value: %s", index, element->photo.extval);
+            } else {
+                win_println(window, THEME_DEFAULT, "!", "[%d] Photo (%s), size: %zu", index, element->photo.type, element->photo.length);
+            }
+            break;
+        }
+        case VCARD_BIRTHDAY:
+        {
+            char* date_format = prefs_get_string(PREF_TIME_VCARD);
+            gchar* date = g_date_time_format(element->birthday, date_format);
+            g_free(date_format);
+
+            assert(date != NULL);
+            win_println(window, THEME_DEFAULT, "!", "[%d] Birthday: %s", index, date);
+            g_free(date);
+            break;
+        }
+        case VCARD_ADDRESS:
+        {
+            // Print the header with flags
+            win_println(window, THEME_DEFAULT, "!", "[%d] Address%s%s%s%s%s%s%s", index,
+                        (element->address.options & VCARD_HOME) ? " [home]" : "",
+                        (element->address.options & VCARD_WORK) == VCARD_WORK ? " [work]" : "",
+                        (element->address.options & VCARD_POSTAL) == VCARD_POSTAL ? " [postal]" : "",
+                        (element->address.options & VCARD_PARCEL) == VCARD_PARCEL ? " [parcel]" : "",
+                        (element->address.options & VCARD_INTL) == VCARD_INTL ? " [international]" : "",
+                        (element->address.options & VCARD_DOM) == VCARD_DOM ? " [domestic]" : "",
+                        (element->address.options & VCARD_PREF) == VCARD_PREF ? " [preferred]" : "");
+
+            if (element->address.pobox) {
+                win_println(window, THEME_DEFAULT, "!", "    P.O. Box: %s", element->address.pobox);
+            }
+            if (element->address.extaddr) {
+                win_println(window, THEME_DEFAULT, "!", "    Extended address: %s", element->address.extaddr);
+            }
+            if (element->address.street) {
+                win_println(window, THEME_DEFAULT, "!", "    Street: %s", element->address.street);
+            }
+            if (element->address.locality) {
+                win_println(window, THEME_DEFAULT, "!", "    Locality: %s", element->address.locality);
+            }
+            if (element->address.region) {
+                win_println(window, THEME_DEFAULT, "!", "    Region: %s", element->address.region);
+            }
+            if (element->address.pcode) {
+                win_println(window, THEME_DEFAULT, "!", "    Postal code: %s", element->address.pcode);
+            }
+            if (element->address.country) {
+                win_println(window, THEME_DEFAULT, "!", "    Country: %s", element->address.country);
+            }
+            break;
+        }
+        case VCARD_TELEPHONE:
+        {
+            // Print the header with flags
+            win_println(window, THEME_DEFAULT, "!", "[%d] Telephone%s%s%s%s%s%s%s%s%s%s%s%s%s", index,
+                        (element->telephone.options & VCARD_HOME) ? " [home]" : "",
+                        (element->telephone.options & VCARD_WORK) == VCARD_WORK ? " [work]" : "",
+                        (element->telephone.options & VCARD_TEL_VOICE) == VCARD_TEL_VOICE ? " [voice]" : "",
+                        (element->telephone.options & VCARD_TEL_FAX) == VCARD_TEL_FAX ? " [fax]" : "",
+                        (element->telephone.options & VCARD_TEL_PAGER) == VCARD_TEL_PAGER ? " [pager]" : "",
+                        (element->telephone.options & VCARD_TEL_MSG) == VCARD_TEL_MSG ? " [msg]" : "",
+                        (element->telephone.options & VCARD_TEL_CELL) == VCARD_TEL_CELL ? " [cell]" : "",
+                        (element->telephone.options & VCARD_TEL_VIDEO) == VCARD_TEL_VIDEO ? " [video]" : "",
+                        (element->telephone.options & VCARD_TEL_BBS) == VCARD_TEL_BBS ? " [bbs]" : "",
+                        (element->telephone.options & VCARD_TEL_MODEM) == VCARD_TEL_MODEM ? " [modem]" : "",
+                        (element->telephone.options & VCARD_TEL_ISDN) == VCARD_TEL_ISDN ? " [isdn]" : "",
+                        (element->telephone.options & VCARD_TEL_PCS) == VCARD_TEL_PCS ? " [pcs]" : "",
+                        (element->telephone.options & VCARD_PREF) == VCARD_PREF ? " [preferred]" : "");
+            if (element->telephone.number) {
+                win_println(window, THEME_DEFAULT, "!", "    Number: %s", element->telephone.number);
+            }
+            break;
+        }
+        case VCARD_EMAIL:
+        {
+            // Print the header with flags
+            win_println(window, THEME_DEFAULT, "!", "[%d] E-mail%s%s%s%s%s", index,
+                        (element->email.options & VCARD_HOME) ? " [home]" : "",
+                        (element->email.options & VCARD_WORK) == VCARD_WORK ? " [work]" : "",
+                        (element->email.options & VCARD_EMAIL_X400) == VCARD_EMAIL_X400 ? " [x400]" : "",
+                        (element->email.options & VCARD_EMAIL_INTERNET) == VCARD_EMAIL_INTERNET ? " [internet]" : "",
+                        (element->email.options & VCARD_PREF) == VCARD_PREF ? " [preferred]" : "");
+            if (element->email.userid) {
+                win_println(window, THEME_DEFAULT, "!", "    ID: %s", element->email.userid);
+            }
+            break;
+        }
+        case VCARD_JID:
+        {
+            win_println(window, THEME_DEFAULT, "!", "[%d] Jabber ID: %s", index, element->jid);
+            break;
+        }
+        case VCARD_TITLE:
+        {
+            win_println(window, THEME_DEFAULT, "!", "[%d] Title: %s", index, element->title);
+            break;
+        }
+        case VCARD_ROLE:
+        {
+            win_println(window, THEME_DEFAULT, "!", "[%d] Role: %s", index, element->role);
+            break;
+        }
+        case VCARD_NOTE:
+        {
+            win_println(window, THEME_DEFAULT, "!", "[%d] Note: %s", index, element->note);
+            break;
+        }
+        case VCARD_URL:
+            win_println(window, THEME_DEFAULT, "!", "[%d] URL: %s", index, element->url);
+            break;
+        }
+    }
+}
+
+void
 win_show_status_string(ProfWin* window, const char* const from,
                        const char* const show, const char* const status,
                        GDateTime* last_activity, const char* const pre,
diff --git a/src/ui/window_list.c b/src/ui/window_list.c
index 56370bca..cdb87de4 100644
--- a/src/ui/window_list.c
+++ b/src/ui/window_list.c
@@ -711,6 +711,18 @@ wins_new_plugin(const char* const plugin_name, const char* const tag)
     return newwin;
 }
 
+ProfWin*
+wins_new_vcard(vCard* vcard)
+{
+    GList* keys = g_hash_table_get_keys(windows);
+    int result = _wins_get_next_available_num(keys);
+    g_list_free(keys);
+    ProfWin* newwin = win_create_vcard(vcard);
+    g_hash_table_insert(windows, GINT_TO_POINTER(result), newwin);
+
+    return newwin;
+}
+
 gboolean
 wins_do_notify_remind(void)
 {
@@ -805,6 +817,27 @@ wins_get_xmlconsole(void)
     return NULL;
 }
 
+ProfVcardWin*
+wins_get_vcard(void)
+{
+    GList* values = g_hash_table_get_values(windows);
+    GList* curr = values;
+
+    while (curr) {
+        ProfWin* window = curr->data;
+        if (window->type == WIN_VCARD) {
+            ProfVcardWin* vcardwin = (ProfVcardWin*)window;
+            assert(vcardwin->memcheck == PROFVCARDWIN_MEMCHECK);
+            g_list_free(values);
+            return vcardwin;
+        }
+        curr = g_list_next(curr);
+    }
+
+    g_list_free(values);
+    return NULL;
+}
+
 GSList*
 wins_get_chat_recipients(void)
 {
diff --git a/src/ui/window_list.h b/src/ui/window_list.h
index bcb18d14..788248b9 100644
--- a/src/ui/window_list.h
+++ b/src/ui/window_list.h
@@ -46,6 +46,7 @@ ProfWin* wins_new_muc(const char* const roomjid);
 ProfWin* wins_new_config(const char* const roomjid, DataForm* form, ProfConfWinCallback submit, ProfConfWinCallback cancel, const void* userdata);
 ProfWin* wins_new_private(const char* const fulljid);
 ProfWin* wins_new_plugin(const char* const plugin_name, const char* const tag);
+ProfWin* wins_new_vcard(vCard* vcard);
 
 gboolean wins_chat_exists(const char* const barejid);
 GList* wins_get_private_chats(const char* const roomjid);
@@ -61,6 +62,7 @@ ProfConfWin* wins_get_conf(const char* const roomjid);
 ProfPrivateWin* wins_get_private(const char* const fulljid);
 ProfPluginWin* wins_get_plugin(const char* const tag);
 ProfXMLWin* wins_get_xmlconsole(void);
+ProfVcardWin* wins_get_vcard(void);
 
 void wins_close_plugin(char* tag);