mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-03-16 18:50:19 +00:00
feat: multiline topic bar w/ clickable URLs + no bare-/ opens
This commit is contained in:
@@ -758,11 +758,15 @@ fe_set_topic (session *sess, char *topic, char *stripped_topic)
|
|||||||
{
|
{
|
||||||
if (prefs.hex_text_stripcolor_topic)
|
if (prefs.hex_text_stripcolor_topic)
|
||||||
{
|
{
|
||||||
gtk_entry_set_text (GTK_ENTRY (sess->gui->topic_entry), stripped_topic);
|
gtk_text_buffer_set_text (
|
||||||
|
gtk_text_view_get_buffer (GTK_TEXT_VIEW (sess->gui->topic_entry)),
|
||||||
|
stripped_topic, -1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gtk_entry_set_text (GTK_ENTRY (sess->gui->topic_entry), topic);
|
gtk_text_buffer_set_text (
|
||||||
|
gtk_text_view_get_buffer (GTK_TEXT_VIEW (sess->gui->topic_entry)),
|
||||||
|
topic, -1);
|
||||||
}
|
}
|
||||||
mg_set_topic_tip (sess);
|
mg_set_topic_tip (sess);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -920,13 +920,18 @@ mg_unpopulate (session *sess)
|
|||||||
{
|
{
|
||||||
restore_gui *res;
|
restore_gui *res;
|
||||||
session_gui *gui;
|
session_gui *gui;
|
||||||
|
GtkTextBuffer *topic_buffer;
|
||||||
|
GtkTextIter start;
|
||||||
|
GtkTextIter end;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
gui = sess->gui;
|
gui = sess->gui;
|
||||||
res = sess->res;
|
res = sess->res;
|
||||||
|
|
||||||
res->input_text = g_strdup (SPELL_ENTRY_GET_TEXT (gui->input_box));
|
res->input_text = g_strdup (SPELL_ENTRY_GET_TEXT (gui->input_box));
|
||||||
res->topic_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->topic_entry)));
|
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (gui->topic_entry));
|
||||||
|
gtk_text_buffer_get_bounds (topic_buffer, &start, &end);
|
||||||
|
res->topic_text = gtk_text_buffer_get_text (topic_buffer, &start, &end, FALSE);
|
||||||
res->limit_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->limit_entry)));
|
res->limit_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->limit_entry)));
|
||||||
res->key_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->key_entry)));
|
res->key_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (gui->key_entry)));
|
||||||
if (gui->laginfo)
|
if (gui->laginfo)
|
||||||
@@ -1003,6 +1008,9 @@ void
|
|||||||
mg_set_topic_tip (session *sess)
|
mg_set_topic_tip (session *sess)
|
||||||
{
|
{
|
||||||
char *text;
|
char *text;
|
||||||
|
GtkTextBuffer *topic_buffer;
|
||||||
|
GtkTextIter start;
|
||||||
|
GtkTextIter end;
|
||||||
|
|
||||||
switch (sess->type)
|
switch (sess->type)
|
||||||
{
|
{
|
||||||
@@ -1017,11 +1025,14 @@ mg_set_topic_tip (session *sess)
|
|||||||
gtk_widget_set_tooltip_text (sess->gui->topic_entry, _("No topic is set"));
|
gtk_widget_set_tooltip_text (sess->gui->topic_entry, _("No topic is set"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (gtk_entry_get_text (GTK_ENTRY (sess->gui->topic_entry)) &&
|
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (sess->gui->topic_entry));
|
||||||
gtk_entry_get_text (GTK_ENTRY (sess->gui->topic_entry))[0])
|
gtk_text_buffer_get_bounds (topic_buffer, &start, &end);
|
||||||
gtk_widget_set_tooltip_text (sess->gui->topic_entry, (char *)gtk_entry_get_text (GTK_ENTRY (sess->gui->topic_entry)));
|
text = gtk_text_buffer_get_text (topic_buffer, &start, &end, FALSE);
|
||||||
|
if (text[0])
|
||||||
|
gtk_widget_set_tooltip_text (sess->gui->topic_entry, text);
|
||||||
else
|
else
|
||||||
gtk_widget_set_tooltip_text (sess->gui->topic_entry, NULL);
|
gtk_widget_set_tooltip_text (sess->gui->topic_entry, NULL);
|
||||||
|
g_free (text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1164,7 +1175,7 @@ mg_populate (session *sess)
|
|||||||
/* hide the userlist */
|
/* hide the userlist */
|
||||||
mg_decide_userlist (sess, FALSE);
|
mg_decide_userlist (sess, FALSE);
|
||||||
/* shouldn't edit the topic */
|
/* shouldn't edit the topic */
|
||||||
gtk_editable_set_editable (GTK_EDITABLE (gui->topic_entry), FALSE);
|
gtk_text_view_set_editable (GTK_TEXT_VIEW (gui->topic_entry), FALSE);
|
||||||
/* might be hidden from server tab */
|
/* might be hidden from server tab */
|
||||||
if (prefs.hex_gui_topicbar)
|
if (prefs.hex_gui_topicbar)
|
||||||
gtk_widget_show (gui->topic_bar);
|
gtk_widget_show (gui->topic_bar);
|
||||||
@@ -1186,8 +1197,8 @@ mg_populate (session *sess)
|
|||||||
gtk_widget_show (gui->topicbutton_box);
|
gtk_widget_show (gui->topicbutton_box);
|
||||||
/* show the userlist */
|
/* show the userlist */
|
||||||
mg_decide_userlist (sess, FALSE);
|
mg_decide_userlist (sess, FALSE);
|
||||||
/* let the topic be editted */
|
/* let the topic be edited */
|
||||||
gtk_editable_set_editable (GTK_EDITABLE (gui->topic_entry), TRUE);
|
gtk_text_view_set_editable (GTK_TEXT_VIEW (gui->topic_entry), TRUE);
|
||||||
if (prefs.hex_gui_topicbar)
|
if (prefs.hex_gui_topicbar)
|
||||||
gtk_widget_show (gui->topic_bar);
|
gtk_widget_show (gui->topic_bar);
|
||||||
}
|
}
|
||||||
@@ -1207,8 +1218,21 @@ mg_populate (session *sess)
|
|||||||
if (gui->is_tab)
|
if (gui->is_tab)
|
||||||
gtk_widget_set_sensitive (gui->menu, TRUE);
|
gtk_widget_set_sensitive (gui->menu, TRUE);
|
||||||
|
|
||||||
/* restore all the GtkEntry's */
|
if (res->topic_text)
|
||||||
mg_restore_entry (gui->topic_entry, &res->topic_text);
|
{
|
||||||
|
GtkTextBuffer *topic_buffer;
|
||||||
|
|
||||||
|
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (gui->topic_entry));
|
||||||
|
gtk_text_buffer_set_text (topic_buffer, res->topic_text, -1);
|
||||||
|
g_free (res->topic_text);
|
||||||
|
res->topic_text = NULL;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
GtkTextBuffer *topic_buffer;
|
||||||
|
|
||||||
|
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (gui->topic_entry));
|
||||||
|
gtk_text_buffer_set_text (topic_buffer, "", -1);
|
||||||
|
}
|
||||||
mg_restore_speller (gui->input_box, &res->input_text);
|
mg_restore_speller (gui->input_box, &res->input_text);
|
||||||
mg_restore_entry (gui->key_entry, &res->key_text);
|
mg_restore_entry (gui->key_entry, &res->key_text);
|
||||||
mg_restore_entry (gui->limit_entry, &res->limit_text);
|
mg_restore_entry (gui->limit_entry, &res->limit_text);
|
||||||
@@ -2114,24 +2138,173 @@ mg_create_userlistbuttons (GtkWidget *box)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mg_topic_cb (GtkWidget *entry, gpointer userdata)
|
mg_topic_cb (GtkWidget *entry)
|
||||||
{
|
{
|
||||||
session *sess = current_sess;
|
session *sess = current_sess;
|
||||||
|
GtkTextBuffer *topic_buffer;
|
||||||
|
GtkTextIter start;
|
||||||
|
GtkTextIter end;
|
||||||
char *text;
|
char *text;
|
||||||
|
|
||||||
if (sess->channel[0] && sess->server->connected && sess->type == SESS_CHANNEL)
|
if (sess->channel[0] && sess->server->connected && sess->type == SESS_CHANNEL)
|
||||||
{
|
{
|
||||||
text = (char *)gtk_entry_get_text (GTK_ENTRY (entry));
|
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (entry));
|
||||||
|
gtk_text_buffer_get_bounds (topic_buffer, &start, &end);
|
||||||
|
text = gtk_text_buffer_get_text (topic_buffer, &start, &end, FALSE);
|
||||||
if (text[0] == 0)
|
if (text[0] == 0)
|
||||||
text = NULL;
|
sess->server->p_topic (sess->server, sess->channel, NULL);
|
||||||
sess->server->p_topic (sess->server, sess->channel, text);
|
else
|
||||||
|
sess->server->p_topic (sess->server, sess->channel, text);
|
||||||
|
g_free (text);
|
||||||
} else
|
} else
|
||||||
gtk_entry_set_text (GTK_ENTRY (entry), "");
|
{
|
||||||
|
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (entry));
|
||||||
|
gtk_text_buffer_set_text (topic_buffer, "", -1);
|
||||||
|
}
|
||||||
/* restore focus to the input widget, where the next input will most
|
/* restore focus to the input widget, where the next input will most
|
||||||
likely be */
|
likely be */
|
||||||
gtk_widget_grab_focus (sess->gui->input_box);
|
gtk_widget_grab_focus (sess->gui->input_box);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mg_topic_key_press_cb (GtkWidget *entry, GdkEventKey *event, gpointer userdata)
|
||||||
|
{
|
||||||
|
if (event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter)
|
||||||
|
{
|
||||||
|
mg_topic_cb (entry);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
mg_topic_get_word_at_pos (GtkWidget *entry, gdouble event_x, gdouble event_y)
|
||||||
|
{
|
||||||
|
GtkTextBuffer *buffer;
|
||||||
|
GtkTextIter iter;
|
||||||
|
GtkTextIter start;
|
||||||
|
GtkTextIter end;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
x = (int)event_x;
|
||||||
|
y = (int)event_y;
|
||||||
|
gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (entry), GTK_TEXT_WINDOW_TEXT,
|
||||||
|
x, y, &x, &y);
|
||||||
|
gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (entry), &iter, x, y);
|
||||||
|
|
||||||
|
start = iter;
|
||||||
|
while (!gtk_text_iter_starts_line (&start))
|
||||||
|
{
|
||||||
|
GtkTextIter prev = start;
|
||||||
|
gunichar ch;
|
||||||
|
|
||||||
|
gtk_text_iter_backward_char (&prev);
|
||||||
|
ch = gtk_text_iter_get_char (&prev);
|
||||||
|
if (g_unichar_isspace (ch))
|
||||||
|
break;
|
||||||
|
start = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = iter;
|
||||||
|
while (!gtk_text_iter_ends_line (&end))
|
||||||
|
{
|
||||||
|
gunichar ch;
|
||||||
|
|
||||||
|
ch = gtk_text_iter_get_char (&end);
|
||||||
|
if (ch == 0 || g_unichar_isspace (ch))
|
||||||
|
break;
|
||||||
|
gtk_text_iter_forward_char (&end);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gtk_text_iter_equal (&start, &end))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (entry));
|
||||||
|
return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mg_topic_set_cursor (GtkWidget *entry, GdkCursorType cursor_type)
|
||||||
|
{
|
||||||
|
GdkWindow *text_window;
|
||||||
|
GdkDisplay *display;
|
||||||
|
GdkCursor *cursor;
|
||||||
|
|
||||||
|
text_window = gtk_text_view_get_window (GTK_TEXT_VIEW (entry), GTK_TEXT_WINDOW_TEXT);
|
||||||
|
if (!text_window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
display = gdk_window_get_display (text_window);
|
||||||
|
cursor = gdk_cursor_new_for_display (display, cursor_type);
|
||||||
|
gdk_window_set_cursor (text_window, cursor);
|
||||||
|
g_object_unref (cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mg_topic_word_is_clickable (const char *word)
|
||||||
|
{
|
||||||
|
if (!word || word[0] == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (strcmp (word, "/") == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return url_check_word (word) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mg_topic_motion_cb (GtkWidget *entry, GdkEventMotion *event, gpointer userdata)
|
||||||
|
{
|
||||||
|
char *word;
|
||||||
|
gboolean word_is_clickable;
|
||||||
|
|
||||||
|
word = mg_topic_get_word_at_pos (entry, event->x, event->y);
|
||||||
|
word_is_clickable = mg_topic_word_is_clickable (word);
|
||||||
|
if (word_is_clickable)
|
||||||
|
mg_topic_set_cursor (entry, GDK_HAND2);
|
||||||
|
else
|
||||||
|
mg_topic_set_cursor (entry, GDK_XTERM);
|
||||||
|
g_free (word);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mg_topic_leave_cb (GtkWidget *entry, GdkEventCrossing *event, gpointer userdata)
|
||||||
|
{
|
||||||
|
mg_topic_set_cursor (entry, GDK_XTERM);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
mg_topic_button_release_cb (GtkWidget *entry, GdkEventButton *event, gpointer userdata)
|
||||||
|
{
|
||||||
|
char *word;
|
||||||
|
int start;
|
||||||
|
int end;
|
||||||
|
|
||||||
|
if (event->button != 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
word = mg_topic_get_word_at_pos (entry, event->x, event->y);
|
||||||
|
if (!word)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (mg_topic_word_is_clickable (word))
|
||||||
|
{
|
||||||
|
url_last (&start, &end);
|
||||||
|
word[end] = 0;
|
||||||
|
fe_open_url (word + start);
|
||||||
|
g_free (word);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (word);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mg_tabwindow_kill_cb (GtkWidget *win, gpointer userdata)
|
mg_tabwindow_kill_cb (GtkWidget *win, gpointer userdata)
|
||||||
{
|
{
|
||||||
@@ -2488,12 +2661,18 @@ mg_dialog_button_cb (GtkWidget *wid, char *cmd)
|
|||||||
char buf[128];
|
char buf[128];
|
||||||
char *host = "";
|
char *host = "";
|
||||||
char *topic;
|
char *topic;
|
||||||
|
char *topic_text;
|
||||||
|
GtkTextBuffer *topic_buffer;
|
||||||
|
GtkTextIter start;
|
||||||
|
GtkTextIter end;
|
||||||
|
|
||||||
if (!current_sess)
|
if (!current_sess)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
topic = (char *)(gtk_entry_get_text (GTK_ENTRY (current_sess->gui->topic_entry)));
|
topic_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (current_sess->gui->topic_entry));
|
||||||
topic = strrchr (topic, '@');
|
gtk_text_buffer_get_bounds (topic_buffer, &start, &end);
|
||||||
|
topic_text = gtk_text_buffer_get_text (topic_buffer, &start, &end, FALSE);
|
||||||
|
topic = strrchr (topic_text, '@');
|
||||||
if (topic)
|
if (topic)
|
||||||
host = topic + 1;
|
host = topic + 1;
|
||||||
|
|
||||||
@@ -2502,6 +2681,7 @@ mg_dialog_button_cb (GtkWidget *wid, char *cmd)
|
|||||||
current_sess->channel, "");
|
current_sess->channel, "");
|
||||||
|
|
||||||
handle_command (current_sess, buf, TRUE);
|
handle_command (current_sess, buf, TRUE);
|
||||||
|
g_free (topic_text);
|
||||||
|
|
||||||
/* dirty trick to avoid auto-selection */
|
/* dirty trick to avoid auto-selection */
|
||||||
SPELL_ENTRY_SET_EDITABLE (current_sess->gui->input_box, FALSE);
|
SPELL_ENTRY_SET_EDITABLE (current_sess->gui->input_box, FALSE);
|
||||||
@@ -2548,18 +2728,23 @@ mg_create_topicbar (session *sess, GtkWidget *box)
|
|||||||
if (!gui->is_tab)
|
if (!gui->is_tab)
|
||||||
sess->res->tab = NULL;
|
sess->res->tab = NULL;
|
||||||
|
|
||||||
gui->topic_entry = topic = sexy_spell_entry_new ();
|
gui->topic_entry = topic = gtk_text_view_new ();
|
||||||
gtk_widget_set_name (topic, "zoitechat-inputbox");
|
gtk_widget_set_name (topic, "zoitechat-inputbox");
|
||||||
sexy_spell_entry_set_checked (SEXY_SPELL_ENTRY (topic), FALSE);
|
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (topic), GTK_WRAP_WORD_CHAR);
|
||||||
|
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (topic), 4);
|
||||||
|
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (topic), 4);
|
||||||
gtk_box_pack_start (GTK_BOX (hbox), topic, TRUE, TRUE, 0);
|
gtk_box_pack_start (GTK_BOX (hbox), topic, TRUE, TRUE, 0);
|
||||||
mg_apply_emoji_fallback_widget (topic);
|
mg_apply_emoji_fallback_widget (topic);
|
||||||
g_signal_connect (G_OBJECT (topic), "activate",
|
gtk_widget_add_events (topic, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
|
||||||
G_CALLBACK (mg_topic_cb), 0);
|
GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
|
||||||
g_signal_connect (G_OBJECT (topic), "key_press_event",
|
g_signal_connect (G_OBJECT (topic), "key-press-event",
|
||||||
G_CALLBACK (mg_entry_select_all), NULL);
|
G_CALLBACK (mg_topic_key_press_cb), NULL);
|
||||||
|
g_signal_connect (G_OBJECT (topic), "button-release-event",
|
||||||
if (prefs.hex_gui_input_style)
|
G_CALLBACK (mg_topic_button_release_cb), NULL);
|
||||||
mg_apply_entry_style (topic);
|
g_signal_connect (G_OBJECT (topic), "motion-notify-event",
|
||||||
|
G_CALLBACK (mg_topic_motion_cb), NULL);
|
||||||
|
g_signal_connect (G_OBJECT (topic), "leave-notify-event",
|
||||||
|
G_CALLBACK (mg_topic_leave_cb), NULL);
|
||||||
|
|
||||||
gui->topicbutton_box = bbox = mg_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
|
gui->topicbutton_box = bbox = mg_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 0);
|
||||||
gtk_box_pack_start (GTK_BOX (hbox), bbox, 0, 0, 0);
|
gtk_box_pack_start (GTK_BOX (hbox), bbox, 0, 0, 0);
|
||||||
@@ -4108,7 +4293,8 @@ fe_clear_channel (session *sess)
|
|||||||
|
|
||||||
if (!sess->gui->is_tab || sess == current_tab)
|
if (!sess->gui->is_tab || sess == current_tab)
|
||||||
{
|
{
|
||||||
gtk_entry_set_text (GTK_ENTRY (gui->topic_entry), "");
|
gtk_text_buffer_set_text (
|
||||||
|
gtk_text_view_get_buffer (GTK_TEXT_VIEW (gui->topic_entry)), "", -1);
|
||||||
|
|
||||||
if (gui->op_xpm)
|
if (gui->op_xpm)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user