/*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2011 Hiroyuki Yamamoto and the Claws Mail team
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2020 the Claws Mail team and Hiroyuki Yamamoto
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
+#include "claws-features.h"
#endif
#include <glib.h>
#include <gdk/gdkkeysyms.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
-#if !GTK_CHECK_VERSION(3, 0, 0)
#include "gtk/gtksctree.h"
-#endif
#include <stdlib.h>
#include <stdarg.h>
#include <sys/stat.h>
#include "defs.h"
#include "gtkutils.h"
#include "utils.h"
-#if !GTK_CHECK_VERSION(3, 0, 0)
#include "gtksctree.h"
-#endif
#include "codeconv.h"
#include "stock_pixmap.h"
#include "menu.h"
#include "prefs_account.h"
#include "prefs_common.h"
#include "manage_window.h"
-#include "base64.h"
#include "manual.h"
#include "combobox.h"
*help_btn = gtk_button_new_from_stock(GTK_STOCK_HELP);
- gtkut_widget_set_can_default(*help_btn, TRUE);
+ gtk_widget_set_can_default(*help_btn, TRUE);
gtk_box_pack_end(GTK_BOX (bbox), *help_btn, TRUE, TRUE, 0);
gtk_button_box_set_child_secondary(GTK_BUTTON_BOX (bbox),
*help_btn, TRUE);
gtk_box_set_spacing(GTK_BOX(*bbox), 5);
*button1 = gtk_button_new_from_stock(label1);
- gtkut_widget_set_can_default(*button1, TRUE);
+ gtk_widget_set_can_default(*button1, TRUE);
gtk_box_pack_start(GTK_BOX(*bbox), *button1, TRUE, TRUE, 0);
gtk_widget_show(*button1);
if (button2) {
*button2 = gtk_button_new_from_stock(label2);
- gtkut_widget_set_can_default(*button2, TRUE);
+ gtk_widget_set_can_default(*button2, TRUE);
gtk_box_pack_start(GTK_BOX(*bbox), *button2, TRUE, TRUE, 0);
gtk_widget_show(*button2);
}
if (button3) {
*button3 = gtk_button_new_from_stock(label3);
- gtkut_widget_set_can_default(*button3, TRUE);
+ gtk_widget_set_can_default(*button3, TRUE);
gtk_box_pack_start(GTK_BOX(*bbox), *button3, TRUE, TRUE, 0);
gtk_widget_show(*button3);
}
*button1 = gtk_button_new_with_mnemonic(text1);
gtk_button_set_image(GTK_BUTTON(*button1),
gtk_image_new_from_stock(label1, GTK_ICON_SIZE_BUTTON));
- gtkut_widget_set_can_default(*button1, TRUE);
+ gtk_widget_set_can_default(*button1, TRUE);
gtk_box_pack_start(GTK_BOX(*bbox), *button1, TRUE, TRUE, 0);
gtk_widget_show(*button1);
*button2 = gtk_button_new_with_mnemonic(text2);
gtk_button_set_image(GTK_BUTTON(*button2),
gtk_image_new_from_stock(label2, GTK_ICON_SIZE_BUTTON));
- gtkut_widget_set_can_default(*button2, TRUE);
+ gtk_widget_set_can_default(*button2, TRUE);
gtk_box_pack_start(GTK_BOX(*bbox), *button2, TRUE, TRUE, 0);
gtk_widget_show(*button2);
}
*button3 = gtk_button_new_with_mnemonic(text3);
gtk_button_set_image(GTK_BUTTON(*button3),
gtk_image_new_from_stock(label3, GTK_ICON_SIZE_BUTTON));
- gtkut_widget_set_can_default(*button3, TRUE);
+ gtk_widget_set_can_default(*button3, TRUE);
gtk_box_pack_start(GTK_BOX(*bbox), *button3, TRUE, TRUE, 0);
gtk_widget_show(*button3);
}
GtkCMCList *clist = GTK_CMCLIST(ctree);
gint row;
GtkVisibility row_visibility, prev_row_visibility, next_row_visibility;
+ gfloat row_align;
cm_return_if_fail(ctree != NULL);
cm_return_if_fail(node != NULL);
next_row_visibility = gtk_cmclist_row_is_visible(clist, row + 1);
if (row_visibility == GTK_VISIBILITY_NONE) {
- gtk_cmclist_moveto(clist, row, -1, 0.5, 0);
+ row_align = 0.5;
+ if (gtk_cmclist_row_is_above_viewport(clist, row))
+ row_align = 0.2;
+ else if (gtk_cmclist_row_is_below_viewport(clist, row))
+ row_align = 0.8;
+ gtk_cmclist_moveto(clist, row, -1, row_align, 0);
return;
}
if (row_visibility == GTK_VISIBILITY_FULL &&
void gtkut_ctree_expand_parent_all(GtkCMCTree *ctree, GtkCMCTreeNode *node)
{
+ gtk_cmclist_freeze(GTK_CMCLIST(ctree));
+
while ((node = gtkut_ctree_find_collapsed_parent(ctree, node)) != NULL)
gtk_cmctree_expand(ctree, node);
+
+ gtk_cmclist_thaw(GTK_CMCLIST(ctree));
}
gboolean gtkut_ctree_node_is_parent(GtkCMCTreeNode *parent, GtkCMCTreeNode *node)
wcs = g_utf8_to_ucs4(str, -1, &items_read, &items_written, &error);
if (error != NULL) {
- g_warning("An error occured while converting a string from UTF-8 to UCS-4: %s\n",
+ g_warning("An error occurred while converting a string from UTF-8 to UCS-4: %s",
error->message);
g_error_free(error);
}
wcs = g_utf8_to_ucs4(str, -1, &items_read, &items_written, &error);
if (error != NULL) {
- g_warning("An error occured while converting a string from UTF-8 to UCS-4: %s\n", error->message);
+ g_warning("An error occurred while converting a string from UTF-8 to UCS-4: %s",
+ error->message);
g_error_free(error);
}
if (!wcs || items_written <= 0) return FALSE;
"scroll_vertical", 2,
G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
G_TYPE_FLOAT, 0.0);
- gtk_binding_entry_add_signal(binding_set, GDK_p, GDK_CONTROL_MASK,
+ gtk_binding_entry_add_signal(binding_set, GDK_KEY_p, GDK_CONTROL_MASK,
"scroll_vertical", 2,
G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
G_TYPE_FLOAT, 0.0);
clist = gtk_cmclist_new(1);
g_object_ref(G_OBJECT(clist));
-#if GLIB_CHECK_VERSION(2,10,0)
g_object_ref_sink (G_OBJECT(clist));
-#else
- gtk_object_ref (G_OBJECT(clist));
- gtk_object_sink (G_OBJECT(clist));
-#endif
gtkut_clist_bindings_add(clist);
g_object_unref(G_OBJECT(clist));
clist = gtk_cmctree_new(1, 0);
g_object_ref(G_OBJECT(clist));
-#if GLIB_CHECK_VERSION(2,10,0)
g_object_ref_sink (G_OBJECT(clist));
-#else
- gtk_object_ref (G_OBJECT(clist));
- gtk_object_sink (G_OBJECT(clist));
-#endif
gtkut_clist_bindings_add(clist);
g_object_unref(G_OBJECT(clist));
clist = gtk_sctree_new_with_titles(1, 0, NULL);
g_object_ref(G_OBJECT(clist));
-#if GLIB_CHECK_VERSION(2,10,0)
g_object_ref_sink (G_OBJECT(clist));
-#else
- gtk_object_ref (G_OBJECT(clist));
- gtk_object_sink (G_OBJECT(clist));
-#endif
gtkut_clist_bindings_add(clist);
g_object_unref(G_OBJECT(clist));
}
void gtkut_widget_set_app_icon(GtkWidget *widget)
{
- static GdkPixbuf *icon = NULL;
-
+ static GList *icon_list = NULL;
+
cm_return_if_fail(widget != NULL);
cm_return_if_fail(gtk_widget_get_window(widget) != NULL);
- if (!icon) {
- stock_pixbuf_gdk(widget, STOCK_PIXMAP_CLAWS_MAIL_ICON, &icon);
- }
- if (icon)
- gtk_window_set_icon(GTK_WINDOW(widget), icon);
+ if (!icon_list) {
+ GdkPixbuf *icon = NULL, *big_icon = NULL;
+ stock_pixbuf_gdk(STOCK_PIXMAP_CLAWS_MAIL_ICON, &icon);
+ stock_pixbuf_gdk(STOCK_PIXMAP_CLAWS_MAIL_LOGO, &big_icon);
+ if (icon)
+ icon_list = g_list_append(icon_list, icon);
+ if (big_icon)
+ icon_list = g_list_append(icon_list, big_icon);
+ }
+ if (icon_list)
+ gtk_window_set_icon_list(GTK_WINDOW(widget), icon_list);
}
void gtkut_widget_set_composer_icon(GtkWidget *widget)
{
- static GdkPixbuf *icon = NULL;
-
+ static GList *icon_list = NULL;
+
cm_return_if_fail(widget != NULL);
cm_return_if_fail(gtk_widget_get_window(widget) != NULL);
- if (!icon) {
- stock_pixbuf_gdk(widget, STOCK_PIXMAP_MAIL_COMPOSE, &icon);
- }
- if (icon)
- gtk_window_set_icon(GTK_WINDOW(widget), icon);
+ if (!icon_list) {
+ GdkPixbuf *icon = NULL, *big_icon = NULL;
+ stock_pixbuf_gdk(STOCK_PIXMAP_MAIL_COMPOSE, &icon);
+ stock_pixbuf_gdk(STOCK_PIXMAP_MAIL_COMPOSE_LOGO, &big_icon);
+ if (icon)
+ icon_list = g_list_append(icon_list, icon);
+ if (big_icon)
+ icon_list = g_list_append(icon_list, big_icon);
+ }
+ if (icon_list)
+ gtk_window_set_icon_list(GTK_WINDOW(widget), icon_list);
}
static gboolean move_bar = FALSE;
if (!GTK_IS_PROGRESS_BAR(w)) {
return FALSE;
}
-
+ gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(w), 0.1);
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(w));
GTK_EVENTS_FLUSH();
return TRUE;
newstyle->bg[GTK_STATE_PRELIGHT] = gdk_color;
newstyle->bg[GTK_STATE_ACTIVE] = gdk_color;
gtk_widget_set_style(widget, newstyle);
+ g_object_unref(newstyle);
}
/*!
_end_iter = *iter;
if (!gtk_text_iter_forward_to_tag_toggle(&_end_iter, tag)) {
- debug_print("Can't find end");
+ debug_print("Can't find end.\n");
return FALSE;
}
_start_iter = _end_iter;
if (!gtk_text_iter_backward_to_tag_toggle(&_start_iter, tag)) {
- debug_print("Can't find start.");
+ debug_print("Can't find start.\n");
return FALSE;
}
}
#if HAVE_LIBCOMPFACE
-GtkWidget *xface_get_from_header(const gchar *o_xface, GdkColor *background,
- GdkWindow *window)
+GtkWidget *xface_get_from_header(const gchar *o_xface)
{
static gchar *xpm_xface[XPM_XFACE_HEIGHT];
static gboolean xpm_xface_init = TRUE;
gchar xface[2048];
- strncpy(xface, o_xface, sizeof(xface));
+ strncpy(xface, o_xface, sizeof(xface) - 1);
+ xface[sizeof(xface) - 1] = '\0';
- if (!window) {
- g_warning("no window\n");
- return NULL;
- }
if (uncompface(xface) < 0) {
- g_warning("uncompface failed\n");
+ g_warning("uncompface failed");
return NULL;
}
GtkWidget *face_get_from_header(const gchar *o_face)
{
gchar face[2048];
- gchar face_png[2048];
- gint pngsize;
+ gchar *face_png;
+ gsize pngsize;
GdkPixbuf *pixbuf;
GError *error = NULL;
GdkPixbufLoader *loader = gdk_pixbuf_loader_new ();
unfold_line(face); /* strip all whitespace and linebreaks */
remove_space(face);
- pngsize = base64_decode(face_png, face, strlen(face));
+ face_png = g_base64_decode(face, &pngsize);
+ debug_print("---------------------- loaded face png\n");
if (!gdk_pixbuf_loader_write (loader, face_png, pngsize, &error) ||
!gdk_pixbuf_loader_close (loader, &error)) {
- g_warning("loading face failed\n");
+ g_warning("loading face failed");
g_object_unref(loader);
+ g_free(face_png);
return NULL;
}
+ g_free(face_png);
pixbuf = g_object_ref(gdk_pixbuf_loader_get_pixbuf(loader));
{
GtkWidget *btn;
GtkWidget *btn_label;
-#if !GTK_CHECK_VERSION(3, 0, 0)
GdkColormap *cmap;
gboolean success[2];
-#endif
GdkColor uri_color[2] = {{0, 0, 0, 0xffff}, {0, 0xffff, 0, 0}};
gchar *local_url = NULL;
if (!url)
return NULL;
- gtkut_convert_int_to_gdk_color(prefs_common.uri_col,
+ gtkut_convert_int_to_gdk_color(prefs_common.color[COL_URI],
&uri_color[0]);
- gtkut_convert_int_to_gdk_color(prefs_common.uri_col,
+ gtkut_convert_int_to_gdk_color(prefs_common.color[COL_URI],
&uri_color[1]);
btn = gtk_button_new_with_label(label?label:url);
gtk_button_set_relief(GTK_BUTTON(btn), GTK_RELIEF_NONE);
btn_label = gtk_bin_get_child(GTK_BIN((btn)));
-#if !GTK_CHECK_VERSION(3, 0, 0)
cmap = gdk_drawable_get_colormap(gtk_widget_get_window(window));
gdk_colormap_alloc_colors(cmap, uri_color, 2, FALSE, TRUE, success);
if (success[0] == TRUE && success[1] == TRUE) {
-#endif
GtkStyle *style;
gtk_widget_ensure_style(btn_label);
style = gtk_style_copy
style->fg[GTK_STATE_ACTIVE] = uri_color[1];
style->fg[GTK_STATE_PRELIGHT] = uri_color[0];
gtk_widget_set_style(btn_label, style);
-#if !GTK_CHECK_VERSION(3, 0, 0)
+ g_object_unref(style);
} else
- g_warning("about_create(): color allocation failed.\n");
-#endif
+ g_warning("color allocation failed");
g_signal_connect(G_OBJECT(btn), "enter",
G_CALLBACK(link_btn_enter), window);
if( txt == NULL )
return TRUE;
+
+ g_free(txt);
return FALSE;
}
GtkTreeIter *iter,
const gchar* text)
/* do the same as gtk_tree_model_iter_next, but _prev instead.
- to use with widgets with one text column (gtk_combo_box_new_text()
+ to use with widgets with one text column (gtk_combo_box_text_new()
and with GtkComboBoxEntry's for instance),
*/
{
gtk_tree_model_get(model, &cur_iter, 0, &cur_value, -1);
if (strcmp(text, cur_value) == 0) {
+ g_free(cur_value);
if (count <= 0)
return FALSE;
return gtk_tree_model_iter_nth_child(model, iter, NULL, count - 1);
}
+ g_free(cur_value);
valid = gtk_tree_model_iter_next(model, &cur_iter);
count++;
}
GtkWidget *gtkut_window_new (GtkWindowType type,
const gchar *class)
{
-#ifndef MAEMO
GtkWidget *window = gtk_window_new(type);
-#else
- GtkWidget *window = hildon_window_new();
- hildon_program_add_window(hildon_program, HILDON_WINDOW(window));
-#endif
gtk_window_set_role(GTK_WINDOW(window), class);
return window;
}
for (row = 0; row < n_rows; row++) {
GtkTreeIter itern;
- gtk_tree_model_iter_nth_child(model, &itern, NULL, row);
- if (gtkut_tree_iter_comp(model, &iter, &itern))
+ if (gtk_tree_model_iter_nth_child(model, &itern, NULL, row)
+ && gtkut_tree_iter_comp(model, &iter, &itern))
return row;
}
gpointer data)
{
ClawsIOClosure *closure = data;
-
+ int fd;
+#ifndef G_OS_WIN32
+ fd = g_io_channel_unix_get_fd (source);
+#else
+ fd = g_io_channel_win32_get_fd (source);
+#endif
if (closure->condition & condition)
- closure->function (closure->data, g_io_channel_unix_get_fd (source),
- condition);
+ closure->function (closure->data, fd, condition);
return TRUE;
}
return result;
}
-void gtkut_widget_set_mapped(GtkWidget *widget, gboolean mapped)
-{
-#if GTK_CHECK_VERSION(2,20,0)
- gtk_widget_set_mapped(widget, mapped);
-#else
- if (mapped)
- GTK_WIDGET_SET_FLAGS(widget, GTK_MAPPED);
- else
- GTK_WIDGET_UNSET_FLAGS(widget, GTK_MAPPED);
-#endif
-}
-
-void gtkut_widget_set_realized(GtkWidget *widget, gboolean realized)
-{
-#if GTK_CHECK_VERSION(2,20,0)
- gtk_widget_set_realized(widget, realized);
-#else
- if (realized)
- GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
- else
- GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED);
-#endif
-}
-
-void gtkut_widget_set_can_default(GtkWidget *widget, gboolean can_default)
-{
-#if GTK_CHECK_VERSION(2,20,0)
- gtk_widget_set_can_default(widget, can_default);
-#else
- if (can_default)
- GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_DEFAULT);
- else
- GTK_WIDGET_UNSET_FLAGS(widget, GTK_CAN_DEFAULT);
-#endif
-}
-
-void gtkut_widget_set_receives_default(GtkWidget *widget, gboolean receives_default)
-{
-#if GTK_CHECK_VERSION(2,20,0)
- gtk_widget_set_receives_default(widget, receives_default);
-#else
- if (receives_default)
- GTK_WIDGET_SET_FLAGS(widget, GTK_RECEIVES_DEFAULT);
- else
- GTK_WIDGET_UNSET_FLAGS(widget, GTK_RECEIVES_DEFAULT);
-#endif
-}
-
-void gtkut_widget_set_can_focus(GtkWidget *widget, gboolean can_focus)
-{
-#if GTK_CHECK_VERSION(2,20,0)
- gtk_widget_set_can_focus(widget, can_focus);
-#else
- if (can_focus)
- GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
- else
- GTK_WIDGET_UNSET_FLAGS(widget, GTK_CAN_FOCUS);
-#endif
-}
-
-void gtkut_widget_set_has_window(GtkWidget *widget, gboolean has_window)
-{
-#if GTK_CHECK_VERSION(2,20,0)
- gtk_widget_set_has_window(widget, has_window);
-#else
- if (has_window) /* Inverted logic there */
- GTK_WIDGET_UNSET_FLAGS(widget, GTK_NO_WINDOW);
- else
- GTK_WIDGET_SET_FLAGS(widget, GTK_NO_WINDOW);
-#endif
-}
-
/**
* Load a pixbuf fitting inside the specified size. EXIF orientation is
* respected if available.
return pixbuf;
}
+
+#if defined USE_GNUTLS
+static void auto_configure_done(const gchar *hostname, gint port, gboolean ssl, AutoConfigureData *data)
+{
+ gboolean smtp = strcmp(data->tls_service, "submission") == 0 ? TRUE : FALSE;
+
+ if (hostname != NULL) {
+ if (data->hostname_entry)
+ gtk_entry_set_text(data->hostname_entry, hostname);
+ if (data->set_port)
+ gtk_toggle_button_set_active(data->set_port,
+ (ssl && port != data->default_ssl_port) || (!ssl && port != data->default_port));
+ if (data->port)
+ gtk_spin_button_set_value(data->port, port);
+ else if (data->hostname_entry) {
+ if ((ssl && port != data->default_ssl_port) || (!ssl && port != data->default_port)) {
+ gchar *tmp = g_strdup_printf("%s:%d", hostname, port);
+ gtk_entry_set_text(data->hostname_entry, tmp);
+ g_free(tmp);
+ } else
+ gtk_entry_set_text(data->hostname_entry, hostname);
+ }
+
+ if (ssl && data->ssl_checkbtn) {
+ gtk_toggle_button_set_active(data->ssl_checkbtn, TRUE);
+ gtk_toggle_button_set_active(data->tls_checkbtn, FALSE);
+ } else if (data->tls_checkbtn) {
+ if (!GTK_IS_RADIO_BUTTON(data->ssl_checkbtn)) {
+ /* Wizard where TLS is [x]SSL + [x]TLS */
+ gtk_toggle_button_set_active(data->ssl_checkbtn, TRUE);
+ }
+
+ /* Even though technically this is against the RFCs,
+ * if a "_submission._tcp" SRV record uses port 465,
+ * it is safe to assume TLS-only service, instead of
+ * plaintext + STARTTLS one. */
+ if (smtp && port == 465)
+ gtk_toggle_button_set_active(data->ssl_checkbtn, TRUE);
+ else
+ gtk_toggle_button_set_active(data->tls_checkbtn, TRUE);
+ }
+
+ /* Check authentication by default. This is probably required if
+ * auto-configuration worked.
+ */
+ if (data->auth_checkbtn)
+ gtk_toggle_button_set_active(data->auth_checkbtn, TRUE);
+
+ /* Set user ID to full email address, which is used by the
+ * majority of providers where auto-configuration works.
+ */
+ if (data->uid_entry)
+ gtk_entry_set_text(data->uid_entry, data->address);
+
+ gtk_label_set_text(data->info_label, _("Done."));
+ } else {
+ gchar *msg;
+ switch (data->resolver_error) {
+ case G_RESOLVER_ERROR_NOT_FOUND:
+ msg = g_strdup(_("Failed: no service record found."));
+ break;
+ case G_RESOLVER_ERROR_TEMPORARY_FAILURE:
+ msg = g_strdup(_("Failed: network error."));
+ break;
+ default:
+ msg = g_strdup_printf(_("Failed: unknown error (%d)."), data->resolver_error);
+ }
+ gtk_label_set_text(data->info_label, msg);
+ g_free(msg);
+ }
+ gtk_widget_show(GTK_WIDGET(data->configure_button));
+ gtk_widget_hide(GTK_WIDGET(data->cancel_button));
+ g_free(data->address);
+ g_free(data);
+}
+
+static void resolve_done(GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ AutoConfigureData *data = (AutoConfigureData *)user_data;
+ GResolver *resolver = (GResolver *)source;
+ GError *error = NULL;
+ gchar *hostname = NULL;
+ guint16 port;
+ GList *answers, *cur;
+ gboolean found = FALSE;
+ gboolean abort = FALSE;
+
+ answers = g_resolver_lookup_service_finish(resolver, result, &error);
+
+ if (answers) {
+ for (cur = g_srv_target_list_sort(answers); cur; cur = cur->next) {
+ GSrvTarget *target = (GSrvTarget *)cur->data;
+ const gchar *h = g_srv_target_get_hostname(target);
+ port = g_srv_target_get_port(target);
+ if (h && strcmp(h,"") && port > 0) {
+ hostname = g_strdup(h);
+ found = TRUE;
+ break;
+ }
+ }
+ g_resolver_free_targets(answers);
+ } else if (error) {
+ if (error->code == G_IO_ERROR_CANCELLED)
+ abort = TRUE;
+ else
+ data->resolver_error = error->code;
+ debug_print("error %s\n", error->message);
+ g_error_free(error);
+ }
+
+ if (found) {
+ auto_configure_done(hostname, port, data->ssl_service != NULL, data);
+ } else if (data->ssl_service && !abort) {
+ /* Fallback to TLS */
+ data->ssl_service = NULL;
+ auto_configure_service(data);
+ } else {
+ auto_configure_done(NULL, 0, FALSE, data);
+ }
+ g_free(hostname);
+ g_object_unref(resolver);
+}
+
+void auto_configure_service(AutoConfigureData *data)
+{
+ GResolver *resolver;
+ const gchar *cur_service = data->ssl_service != NULL ? data->ssl_service : data->tls_service;
+
+ cm_return_if_fail(cur_service != NULL);
+ cm_return_if_fail(data->address != NULL);
+
+ resolver = g_resolver_get_default();
+ if (resolver != NULL) {
+ const gchar *domain = strchr(data->address, '@') + 1;
+
+ gtk_label_set_text(data->info_label, _("Configuring..."));
+ gtk_widget_hide(GTK_WIDGET(data->configure_button));
+ gtk_widget_show(GTK_WIDGET(data->cancel_button));
+ g_resolver_lookup_service_async(resolver, cur_service, "tcp", domain,
+ data->cancel, resolve_done, data);
+ }
+}
+
+gboolean auto_configure_service_sync(const gchar *service, const gchar *domain, gchar **srvhost, guint16 *srvport)
+{
+ GResolver *resolver;
+ GList *answers, *cur;
+ GError *error = NULL;
+ gboolean result = FALSE;
+
+ cm_return_val_if_fail(service != NULL, FALSE);
+ cm_return_val_if_fail(domain != NULL, FALSE);
+
+ resolver = g_resolver_get_default();
+ if (resolver == NULL)
+ return FALSE;
+
+ answers = g_resolver_lookup_service(resolver, service, "tcp", domain, NULL, &error);
+
+ *srvhost = NULL;
+ *srvport = 0;
+
+ if (answers) {
+ for (cur = g_srv_target_list_sort(answers); cur; cur = cur->next) {
+ GSrvTarget *target = (GSrvTarget *)cur->data;
+ const gchar *hostname = g_srv_target_get_hostname(target);
+ guint16 port = g_srv_target_get_port(target);
+ if (hostname && strcmp(hostname,"") && port > 0) {
+ result = TRUE;
+ *srvhost = g_strdup(hostname);
+ *srvport = port;
+ break;
+ }
+ }
+ g_resolver_free_targets(answers);
+ } else if (error) {
+ g_error_free(error);
+ }
+
+ g_object_unref(resolver);
+ return result;
+}
+#endif
+
+gpointer gtkut_tree_view_get_selected_pointer(GtkTreeView *view,
+ gint column, GtkTreeModel **_model, GtkTreeSelection **_selection,
+ GtkTreeIter *_iter)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkTreeSelection *sel;
+ gpointer ptr;
+ GType type;
+
+ cm_return_val_if_fail(view != NULL, NULL);
+ cm_return_val_if_fail(column >= 0, NULL);
+
+ model = gtk_tree_view_get_model(view);
+ if (_model != NULL)
+ *_model = model;
+
+ sel = gtk_tree_view_get_selection(view);
+ if (_selection != NULL)
+ *_selection = sel;
+
+ if (!gtk_tree_selection_get_selected(sel, NULL, &iter))
+ return NULL; /* No row selected */
+
+ if (_iter != NULL)
+ *_iter = iter;
+
+ if (gtk_tree_selection_count_selected_rows(sel) > 1)
+ return NULL; /* Can't work with multiselect */
+
+ cm_return_val_if_fail(
+ gtk_tree_model_get_n_columns(model) > column,
+ NULL);
+
+ type = gtk_tree_model_get_column_type(model, column);
+ cm_return_val_if_fail(
+ type == G_TYPE_POINTER || type == G_TYPE_STRING,
+ NULL);
+
+ gtk_tree_model_get(model, &iter, column, &ptr, -1);
+
+ return ptr;
+}
+
+static GList *get_predefined_times(void)
+{
+ int h,m;
+ GList *times = NULL;
+ for (h = 0; h < 24; h++) {
+ for (m = 0; m < 60; m += 15) {
+ gchar *tmp = g_strdup_printf("%02d:%02d", h, m);
+ times = g_list_append(times, tmp);
+ }
+ }
+ return times;
+}
+
+static int get_list_item_num(int h, int m)
+{
+ if (m % 15 != 0)
+ return -1;
+
+ return (h*4 + m/15);
+}
+
+GtkWidget *gtkut_time_select_combo_new()
+{
+ GtkWidget *combo = gtk_combo_box_text_new_with_entry();
+ GList *times = get_predefined_times();
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(combo), -1);
+ combobox_set_popdown_strings(GTK_COMBO_BOX_TEXT(combo), times);
+
+ list_free_strings_full(times);
+
+ return combo;
+}
+
+
+void gtkut_time_select_select_by_time(GtkComboBox *combo, int hour, int minute)
+{
+ gchar *time_text = g_strdup_printf("%02d:%02d", hour, minute);
+ gint num = get_list_item_num(hour, minute);
+
+ if (num > -1)
+ combobox_select_by_text(combo, time_text);
+ else
+ gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(combo))), time_text);
+
+ g_free(time_text);
+}
+
+static void get_time_from_combo(GtkComboBox *combo, int *h, int *m)
+{
+ gchar *tmp;
+ gchar **parts;
+
+ if (!h || !m)
+ return;
+
+ tmp = gtk_editable_get_chars(GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(combo))), 0, -1);
+ parts = g_strsplit(tmp, ":", 2);
+ if (parts[0] && parts[1] && *parts[0] && *parts[1]) {
+ *h = atoi(parts[0]);
+ *m = atoi(parts[1]);
+ }
+ g_strfreev(parts);
+ g_free(tmp);
+}
+
+gboolean gtkut_time_select_get_time(GtkComboBox *combo, int *hour, int *minute)
+{
+ const gchar *value = gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(combo))));
+
+ if (value == NULL || strlen(value) != 5)
+ return FALSE;
+
+ if (hour == NULL || minute == NULL)
+ return FALSE;
+
+ get_time_from_combo(combo, hour, minute);
+
+ if (*hour < 0 || *hour > 23)
+ return FALSE;
+ if (*minute < 0 || *minute > 59)
+ return FALSE;
+
+ return TRUE;
+}
+
+void gtk_calendar_select_today(GtkCalendar *calendar)
+{
+ time_t t = time (NULL);
+ struct tm buft;
+ struct tm *lt = localtime_r (&t, &buft);
+
+ mktime(lt);
+ gtk_calendar_select_day(calendar, lt->tm_mday);
+ gtk_calendar_select_month(calendar, lt->tm_mon, lt->tm_year + 1900);
+}