changeset 6465:fb64cc87bc96

[gaim-migrate @ 6974] open_url() is gone forever! WOOHOO! Now we have gaim_notify_uri(). Oh, and whitespace changes in some files, because they just really bugged me. committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Thu, 14 Aug 2003 03:55:13 +0000
parents 059649ed25ed
children 11c8ecdd28f4
files src/browser.c src/dialogs.c src/gtknotify.c src/gtknotify.h src/gtkutils.c src/notify.c src/notify.h src/protocols/oscar/oscar.c src/protocols/trepia/trepia.c src/protocols/yahoo/yahoo.c src/server.c src/ui.h
diffstat 12 files changed, 165 insertions(+), 122 deletions(-) [+]
line wrap: on
line diff
--- a/src/browser.c	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/browser.c	Thu Aug 14 03:55:13 2003 +0000
@@ -196,12 +196,12 @@
 	unsigned char *version = 0;
 	gchar *retval = NULL;
 
-	if (XGetWindowProperty(gdk_display, window, 
+	if (XGetWindowProperty(gdk_display, window,
 					gdk_x11_atom_to_xatom(GDKA_MOZILLA_VERSION),
 					0, (65536 / sizeof(long)),
 					False, XA_STRING,
 					&type, &format, &nitems, &bytesafter,
-					&version) != Success) {	
+					&version) != Success) {
 		return NULL;
 	}
 
@@ -309,7 +309,7 @@
 	static char *lock_data = NULL;
 
 	if (lock_data == NULL) {
-		char hostname[HOST_NAME_MAX + 1] = {0}; 
+		char hostname[HOST_NAME_MAX + 1] = {0};
 
 		if (gethostname(hostname, HOST_NAME_MAX + 1) == 0) {
 			lock_data = g_strdup_printf("pid%d@%s", getpid(), hostname);
@@ -360,7 +360,7 @@
 {
 	int result = 0;
 	GdkAtom actual_type;
-	gint actual_format; 
+	gint actual_format;
 	gint nitems;
 	unsigned char *data = 0;
 	const char *lock_data = get_lock_data();
@@ -369,7 +369,7 @@
 			   "%s: deleting " MOZILLA_LOCK_PROP " \"%s\" from 0x%x\n",
 			   progname, lock_data, (unsigned int)window);
 
-	result = gdk_property_get(window, GDKA_MOZILLA_LOCK, 
+	result = gdk_property_get(window, GDKA_MOZILLA_LOCK,
 				  gdk_x11_xatom_to_atom (XA_STRING),
 				  0, (65536 / sizeof(long)),
 				  1, &actual_type, &actual_format, &nitems, &data);
@@ -424,32 +424,32 @@
 
 	if (XGetWindowProperty (gdk_display, xid, mozilla_response,
 							 0, (65536 / sizeof (long)),
-							 True, 
-							 XA_STRING, 
+							 True,
+							 XA_STRING,
 							 &actual_type, &actual_format,
 							 &nitems, &bytes_after,
-							 &data) != Success 
+							 &data) != Success
 		|| data == NULL || (data[0] != '1' && data[0] != '2')) {
 
 		gaim_notify_error(NULL, NULL,
 						  _("Communication with the browser failed. "
 							"Please close all windows and try again."), NULL);
-	} 
+	}
 
     if (data[0] == '1') {
 		/* Netscape isn't ready yet */
 		gaim_debug(GAIM_DEBUG_ERROR, "browser",
 				   "Remote Netscape window isn't ready yet.\n");
 		return GDK_FILTER_REMOVE;
-	} 
-	
+	}
+
 	if (data[0] == '2') {
-		/* Yay! It worked */ 
+		/* Yay! It worked */
 		gaim_debug(GAIM_DEBUG_INFO, "browser",
 				   "Successfully sent command to remote Netscape window.\n");
 	}
 
-	gdk_window_remove_filter(window, (GdkFilterFunc) netscape_response_cb, window); 
+	gdk_window_remove_filter(window, (GdkFilterFunc) netscape_response_cb, window);
 	mozilla_remote_free_lock(window);
 	netscape_lock = 0;
 	return GDK_FILTER_REMOVE;
@@ -478,8 +478,8 @@
 			   "%s: Writing " MOZILLA_COMMAND_PROP " \"%s\" to 0x%x\n",
 			   progname, command, (unsigned int)window);
 
-	gdk_property_change(window, GDKA_MOZILLA_COMMAND, 
-			    gdk_x11_xatom_to_atom (XA_STRING), 
+	gdk_property_change(window, GDKA_MOZILLA_COMMAND,
+			    gdk_x11_xatom_to_atom (XA_STRING),
 			    8, GDK_PROP_MODE_REPLACE, (unsigned char *)command, strlen(command));
 
 	gdk_window_add_filter(window, (GdkFilterFunc) netscape_response_cb, window);
@@ -488,7 +488,7 @@
 static gboolean netscape_command(const char *command)
 {
  	GdkWindow *window = NULL;
- 
+
  	if (netscape_lock) {
 		gaim_debug(GAIM_DEBUG_WARNING, "browser",
 				   "netscape_command() is currently in use.\n");
@@ -512,56 +512,58 @@
 	netscape_lock = 0;
 	return TRUE;
 }
+#endif /* _WIN32 */
 
-void open_url(GtkWidget *w, const char *url)
+void *
+gaim_gtk_notify_uri(const char *uri)
 {
+#ifndef _WIN32
 	char *command = NULL;
 	GError *error = NULL;
 	const char *web_browser;
-	
+
 	web_browser = gaim_prefs_get_string("/gaim/gtk/browsers/browser");
 
 	if (!strcmp(web_browser, "netscape")) {
 		char *args = NULL;
 
 		if (gaim_prefs_get_bool("/gaim/gtk/browsers/new_window"))
-			args = g_strdup_printf("OpenURL(%s, new-window)", url);
+			args = g_strdup_printf("OpenURL(%s, new-window)", uri);
 		else
-			args = g_strdup_printf("OpenURL(%s)", url);
+			args = g_strdup_printf("OpenURL(%s)", uri);
 
 		if (netscape_command(args)) {
 			g_free(args);
-			return;
+			return NULL;
 		}
 
 		/* if netscape is running ...
 		command = g_strdup_printf("netscape -remote %s", args); */
 
-		command = g_strdup_printf("netscape \"%s\"", url);
+		command = g_strdup_printf("netscape \"%s\"", uri);
 		g_free(args);
 	}
 	else if (!strcmp(web_browser, "opera")) {
 		if (gaim_prefs_get_bool("/gaim/gtk/browsers/new_window"))
-			command = g_strdup_printf("opera -newwindow \"%s\"", url);
+			command = g_strdup_printf("opera -newwindow \"%s\"", uri);
 		else
-			command = g_strdup_printf("opera \"%s\"", url);
+			command = g_strdup_printf("opera \"%s\"", uri);
 	}
 	else if (!strcmp(web_browser, "kfmclient")) {
-		command = g_strdup_printf("kfmclient openURL \"%s\"", url);
+		command = g_strdup_printf("kfmclient openURL \"%s\"", uri);
 	}
 	else if (!strcmp(web_browser, "galeon")) {
 		if (gaim_prefs_get_bool("/gaim/gtk/browsers/new_window"))
-			command = g_strdup_printf("galeon -w \"%s\"", url);
+			command = g_strdup_printf("galeon -w \"%s\"", uri);
 		else
-			command = g_strdup_printf("galeon \"%s\"", url);
+			command = g_strdup_printf("galeon \"%s\"", uri);
 	}
 	else if (!strcmp(web_browser, "mozilla")) {
-		command = g_strdup_printf("mozilla \"%s\"", url);
+		command = g_strdup_printf("mozilla \"%s\"", uri);
 	}
 	else if (!strcmp(web_browser, "custom")) {
 		const char *web_command;
 
-
 		web_command = gaim_prefs_get_string("/gaim/gtk/browsers/command");
 
 		if (web_command == NULL || *web_command == '\0') {
@@ -570,52 +572,36 @@
 								"the 'Manual' browser command has been "
 								"chosen, but no command has been set."),
 							  NULL);
-			return;
+			return NULL;
 		}
 
 		if (strstr(web_command, "%s"))
-			command = gaim_strreplace(web_command, "%s", url);
+			command = gaim_strreplace(web_command, "%s", uri);
 		else {
-			/* There is no "%s" in the browser command.  Assume the user
-			 * wanted the URL tacked on to the end of the command. */
-			command = g_strdup_printf("%s %s", web_command, url);
+			/*
+			 * There is no "%s" in the browser command.  Assume the user
+			 * wanted the URL tacked on to the end of the command.
+			 */
+			command = g_strdup_printf("%s %s", web_command, uri);
 		}
 	}
 
-	if (g_spawn_command_line_async(command, &error) == FALSE) {
-		char *tmp = g_strdup_printf(_("There was an error launching your chosen browser: %s"), error->message);
+	if (!g_spawn_command_line_async(command, &error)) {
+		char *tmp = g_strdup_printf(
+				_("There was an error launching your chosen browser: %s"),
+				error->message);
+
 		gaim_notify_error(NULL, NULL, tmp, NULL);
+
 		g_free(tmp);
 		g_error_free(error);
  	}
 
 	g_free(command);
-}
-
-void add_bookmark(GtkWidget *w, char *url)
-{
-	const char *web_browser;
 
-	web_browser = gaim_prefs_get_string("/gaim/gtk/browsers/browser");
+#else
+	ShellExecute(NULL, NULL, uri, NULL, ".\\", 0);
+#endif
 
-	if (!strcmp(web_browser, "netscape")) {
-		char *command = g_strdup_printf("AddBookmark(%s)", url);
-
-		netscape_command(command);
-		g_free(command);
-	}
+	return NULL;
 }
-
-#else /* _WIN32 */
-
-/* Sooner or later, I shall support Windows clicking! */
-
-void add_bookmark(GtkWidget *w, char *url)
-{
-}
-void open_url(GtkWidget *w, char *url)
-{
-	ShellExecute(NULL, NULL, url, NULL, ".\\", 0);
-}
-
-#endif /* _WIN32 */
--- a/src/dialogs.c	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/dialogs.c	Thu Aug 14 03:55:13 2003 +0000
@@ -2,7 +2,7 @@
  * gaim
  *
  * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- * 
+ *
  * 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
  * the Free Software Foundation; either version 2 of the License, or
@@ -112,7 +112,7 @@
 	GtkWidget *window;
 	GtkWidget *entry;
 	GtkWidget *account;
-	GaimConnection *gc; 
+	GaimConnection *gc;
 };
 
 typedef struct
@@ -349,7 +349,7 @@
 	hbox = gtk_hbox_new(FALSE, 12);
 	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(w->window)->vbox), hbox);
 	gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
-	
+
 	vbox = gtk_vbox_new(FALSE, 0);
 	gtk_container_add(GTK_CONTAINER(hbox), vbox);
 	labeltext = g_strdup_printf(_("<span weight=\"bold\" size=\"larger\">Warn %s?</span>\n\n"
@@ -363,7 +363,7 @@
 
 	w->anon = gtk_check_button_new_with_mnemonic(_("Warn _anonymously?"));
 	gtk_box_pack_start(GTK_BOX(vbox), w->anon, FALSE, FALSE, 0);
-	
+
 	hbox = gtk_hbox_new(FALSE, 6);
 	gtk_container_add(GTK_CONTAINER(vbox), hbox);
 	img = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_MENU);
@@ -469,7 +469,7 @@
 
 void show_confirm_del_group(struct group *g)
 {
-	char *text = g_strdup_printf(_("You are about to remove the group %s and all its members from your buddy list.  Do you want to continue?"), 
+	char *text = g_strdup_printf(_("You are about to remove the group %s and all its members from your buddy list.  Do you want to continue?"),
 			       g->name);
 
 	gaim_request_action(NULL, NULL, _("Remove Group"), text, -1, g, 2,
@@ -526,7 +526,7 @@
 			g_free(who);
 			return;
 		}
-	
+
 		/* what do we want to do about this case? */
 		if (info->gc)
 			serv_get_info(info->gc, who);
@@ -548,37 +548,37 @@
 
 	label = gtk_label_new(NULL);
 	if (ee == 0)
-		gtk_label_set_markup(GTK_LABEL(label), 
+		gtk_label_set_markup(GTK_LABEL(label),
 				     "<span weight=\"bold\" size=\"large\" foreground=\"purple\">Amazing!  Simply Amazing!</span>");
 	else if (ee == 1)
-		gtk_label_set_markup(GTK_LABEL(label), 
+		gtk_label_set_markup(GTK_LABEL(label),
 				     "<span weight=\"bold\" size=\"large\" foreground=\"#1f6bad\">Pimpin\' Penguin Style! *Waddle Waddle*</span>");
 	else if (ee == 2)
-		gtk_label_set_markup(GTK_LABEL(label), 
+		gtk_label_set_markup(GTK_LABEL(label),
 				      "<span weight=\"bold\" size=\"large\" foreground=\"blue\">You should be me.  I'm so cute!</span>");
 	else if (ee == 3)
-		gtk_label_set_markup(GTK_LABEL(label), 
+		gtk_label_set_markup(GTK_LABEL(label),
 				     "<span weight=\"bold\" size=\"large\" foreground=\"orange\">Now that's what I like!</span>");
 	else if (ee == 4)
-		gtk_label_set_markup(GTK_LABEL(label), 
+		gtk_label_set_markup(GTK_LABEL(label),
 				     "<span weight=\"bold\" size=\"large\" foreground=\"brown\">Ahh, and excellent choice!</span>");
 	else  if (ee == 5)
-		gtk_label_set_markup(GTK_LABEL(label), 
+		gtk_label_set_markup(GTK_LABEL(label),
 				     "<span weight=\"bold\" size=\"large\" foreground=\"#009900\">Everytime you click my name, an angel gets its wings.</span>");
 	else if (ee == 6)
-		gtk_label_set_markup(GTK_LABEL(label), 
+		gtk_label_set_markup(GTK_LABEL(label),
 				     "<span weight=\"bold\" size=\"large\" foreground=\"red\">This sunflower seed taste like pizza.</span>");
 	else if (ee == 7)
-		gtk_label_set_markup(GTK_LABEL(label), 
+		gtk_label_set_markup(GTK_LABEL(label),
 				     "<span weight=\"bold\" size=\"large\" foreground=\"#6364B1\">Hey!  I was in that tumbleweed!</span>");
 	else
-		gtk_label_set_markup(GTK_LABEL(label), 
+		gtk_label_set_markup(GTK_LABEL(label),
 				     "<span weight=\"bold\" size=\"large\" foreground=\"gray\">I'm not anything.</span>");
-	
+
 	window = gtk_dialog_new_with_buttons("", GTK_WINDOW(gtkblist->window), 0, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
 	gtk_dialog_set_default_response (GTK_DIALOG(window), GTK_RESPONSE_OK);
 	g_signal_connect(G_OBJECT(window), "response", G_CALLBACK(gtk_widget_destroy), NULL);
-	
+
 	gtk_container_set_border_width (GTK_CONTAINER(window), 6);
 	gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
 	gtk_dialog_set_has_separator(GTK_DIALOG(window), FALSE);
@@ -588,7 +588,7 @@
 	hbox = gtk_hbox_new(FALSE, 12);
 	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->vbox), hbox);
 	gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
-	
+
 	gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
@@ -703,7 +703,7 @@
 
 	info->gc = gaim_connections_get_all()->data;
 
-	window = gtk_dialog_new_with_buttons(_("Get User Info"), gtkblist->window ? GTK_WINDOW(gtkblist->window) : NULL, 0, 
+	window = gtk_dialog_new_with_buttons(_("Get User Info"), gtkblist->window ? GTK_WINDOW(gtkblist->window) : NULL, 0,
 					     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
 	gtk_dialog_set_default_response (GTK_DIALOG(window), GTK_RESPONSE_OK);
 	gtk_container_set_border_width (GTK_CONTAINER(window), 6);
@@ -721,18 +721,18 @@
 
 	vbox = gtk_vbox_new(FALSE, 0);
 	gtk_container_add(GTK_CONTAINER(hbox), vbox);
-		
+
 	label = gtk_label_new(_("Please enter the screenname of the person whose info you would like to view.\n"));
 	gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
-	
+
 	table = gtk_table_new(2, 2, FALSE);
 	gtk_table_set_row_spacings(GTK_TABLE(table), 6);
 	gtk_table_set_col_spacings(GTK_TABLE(table), 6);
 	gtk_container_set_border_width(GTK_CONTAINER(table), 12);
 	gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
-	
+
 	label = gtk_label_new(NULL);
 	gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), _("_Screenname:"));
 	gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
@@ -745,7 +745,7 @@
 
 	g_signal_connect(G_OBJECT(info->entry), "changed",
 			G_CALLBACK(dialog_set_ok_sensitive), window);
-	
+
 	if (gaim_connections_get_all()->next) {
 
 		label = gtk_label_new(NULL);
@@ -761,8 +761,8 @@
 	}
 
 	g_signal_connect(G_OBJECT(window), "response", G_CALLBACK(do_info), info);
-	
-	
+
+
 	gtk_widget_show_all(window);
 	if (info->entry)
 		gtk_widget_grab_focus(GTK_WIDGET(info->entry));
@@ -934,7 +934,7 @@
 	a->entry = gtk_entry_new();
 	gtk_table_attach_defaults(GTK_TABLE(table), a->entry, 1, 2, 0, 1);
 	gtk_widget_grab_focus(a->entry);
-	
+
 	if (buddy != NULL)
 		gtk_entry_set_text(GTK_ENTRY(a->entry), buddy);
 
@@ -976,7 +976,7 @@
 
 	gtk_widget_show_all(a->window);
 
-	if (group != NULL) 
+	if (group != NULL)
 		gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(a->combo)->entry), group);
 }
 
@@ -1910,7 +1910,7 @@
 
 		g_snprintf(buf, BUF_LEN - 1, "%s" G_DIR_SEPARATOR_S "%s.log",
 				   gaim_home_dir(), normalize(c->name));
-		g_object_set_data(G_OBJECT(gtkconv->dialogs.log), "dialog_type", 
+		g_object_set_data(G_OBJECT(gtkconv->dialogs.log), "dialog_type",
 								 "log dialog");
 		gtk_file_selection_set_filename(GTK_FILE_SELECTION(gtkconv->dialogs.log),
 										buf);
@@ -2176,11 +2176,11 @@
 	if (resp == GTK_RESPONSE_OK) {
 
 		open_tag = g_malloc(2048);
-		
+
 		urltext = gtk_entry_get_text(GTK_ENTRY(b->url));
 		showtext = gtk_entry_get_text(GTK_ENTRY(b->text));
 
-		if (!strlen(showtext)) 
+		if (!strlen(showtext))
 			showtext = urltext;
 
 		g_snprintf(open_tag, 2048, "<A HREF=\"%s\">%s", urltext, showtext);
@@ -2227,53 +2227,53 @@
 		gtk_container_set_border_width(
 			GTK_CONTAINER(GTK_DIALOG(a->window)->vbox), 6);
 		gtk_window_set_role(GTK_WINDOW(a->window), "insert_link");
-	
+
 		hbox = gtk_hbox_new(FALSE, 12);
 		gtk_container_add(GTK_CONTAINER(GTK_DIALOG(a->window)->vbox), hbox);
 		gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
 		gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
-	
+
 		vbox = gtk_vbox_new(FALSE, 0);
 		gtk_container_add(GTK_CONTAINER(hbox), vbox);
-	
+
 		label = gtk_label_new(_("Please enter the URL and description of "
 								"the link that you want to insert.  The "
 								"description is optional.\n"));
-	
+
 		gtk_widget_set_size_request(GTK_WIDGET(label), 335, -1);
 		gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 		gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 		gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
-	
+
 		hbox = gtk_hbox_new(FALSE, 6);
 		gtk_container_add(GTK_CONTAINER(vbox), hbox);
-	
+
 		g_signal_connect(G_OBJECT(a->window), "destroy",
 						 G_CALLBACK(destroy_dialog), a->window);
 		g_signal_connect(G_OBJECT(a->window), "destroy",
 						 G_CALLBACK(free_dialog), a);
 		dialogwindows = g_list_prepend(dialogwindows, a->window);
-	
+
 		table = gtk_table_new(4, 2, FALSE);
 		gtk_table_set_row_spacings(GTK_TABLE(table), 5);
 		gtk_table_set_col_spacings(GTK_TABLE(table), 5);
 		gtk_container_set_border_width(GTK_CONTAINER(table), 0);
 		gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
-	
+
 		label = gtk_label_new(_("URL"));
 		gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 		gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
-	
+
 		a->url = gtk_entry_new();
 		gtk_table_attach_defaults(GTK_TABLE(table), a->url, 1, 2, 0, 1);
 		gtk_widget_grab_focus(a->url);
-		
+
 		gtk_entry_set_activates_default (GTK_ENTRY(a->url), TRUE);
-	
+
 		label = gtk_label_new(_("Description"));
 		gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 		gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
-	
+
 		a->text = gtk_entry_new();
 		gtk_table_attach_defaults(GTK_TABLE(table), a->text, 1, 2, 1, 2);
 		gtk_entry_set_activates_default (GTK_ENTRY(a->text), TRUE);
@@ -2640,7 +2640,7 @@
 		am = ca->mess;
 	}
 
-	
+
 	g_snprintf(am->name, sizeof(am->name), "%s", gtk_entry_get_text(GTK_ENTRY(ca->entry)));
 	away_message = gtk_text_view_get_text(GTK_TEXT_VIEW(ca->text), FALSE);
 
@@ -3283,6 +3283,12 @@
 	g_free(name);
 }
 
+static void
+url_clicked_cb(GtkWidget *widget, const char *uri)
+{
+	gaim_notify_uri(NULL, uri);
+}
+
 void show_log(char *nm)
 {
 	gchar filename[256];
@@ -3396,7 +3402,7 @@
 				temp++;
 				length = strcspn(temp, "-");
 				if (length > 31) length = 31;
-				
+
 				offset = ftell(fp);
 				g_snprintf(convo_start, length, "%s", temp);
 				gtk_list_store_append(list_store, &iter);
@@ -3440,7 +3446,8 @@
 	gtk_container_add(GTK_CONTAINER(frame), sw);
 	gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
 
-	g_signal_connect(G_OBJECT(layout), "url_clicked", G_CALLBACK(open_url), NULL);
+	g_signal_connect(G_OBJECT(layout), "url_clicked",
+					 G_CALLBACK(url_clicked_cb), NULL);
 	gtk_container_add(GTK_CONTAINER(sw), layout);
 	gaim_setup_imhtml(layout);
 
--- a/src/gtknotify.c	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/gtknotify.c	Thu Aug 14 03:55:13 2003 +0000
@@ -5,7 +5,7 @@
  * gaim
  *
  * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
- * 
+ *
  * 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
  * the Free Software Foundation; either version 2 of the License, or
@@ -26,6 +26,7 @@
 #include "debug.h"
 #include "prefs.h"
 #include "stock.h"
+#include "util.h"
 
 #include "gtkimhtml.h"
 #include "gtknotify.h"
@@ -58,7 +59,7 @@
 email_response_cb(GtkDialog *dialog, gint id, GaimNotifyMailData *data)
 {
 	if (id == 0)
-		open_url(NULL, data->url);
+		gaim_notify_uri(NULL, data->url);
 
 	gaim_notify_close(GAIM_NOTIFY_EMAILS, data);
 }
@@ -357,6 +358,7 @@
 	gaim_gtk_notify_email,
 	gaim_gtk_notify_emails,
 	gaim_gtk_notify_formatted,
+	gaim_gtk_notify_uri,
 	gaim_gtk_close_notify
 };
 
--- a/src/gtknotify.h	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/gtknotify.h	Thu Aug 14 03:55:13 2003 +0000
@@ -5,7 +5,7 @@
  * gaim
  *
  * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
- * 
+ *
  * 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
  * the Free Software Foundation; either version 2 of the License, or
--- a/src/gtkutils.c	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/gtkutils.c	Thu Aug 14 03:55:13 2003 +0000
@@ -51,6 +51,12 @@
 #include "wspell.h"
 #endif
 
+static void
+url_clicked_cb(GtkWidget *w, const char *uri)
+{
+	gaim_notify_uri(NULL, uri);
+}
+
 void
 gaim_setup_imhtml(GtkWidget *imhtml)
 {
@@ -61,7 +67,7 @@
 		gtk_imhtml_show_smileys(GTK_IMHTML(imhtml), FALSE);
 
 	g_signal_connect(G_OBJECT(imhtml), "url_clicked",
-					 G_CALLBACK(open_url), NULL);
+					 G_CALLBACK(url_clicked_cb), NULL);
 
 	smiley_themeize(imhtml);
 }
--- a/src/notify.c	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/notify.c	Thu Aug 14 03:55:13 2003 +0000
@@ -5,7 +5,7 @@
  * gaim
  *
  * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
- * 
+ *
  * 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
  * the Free Software Foundation; either version 2 of the License, or
@@ -153,6 +153,31 @@
 	return NULL;
 }
 
+void *
+gaim_notify_uri(void *handle, const char *uri)
+{
+	GaimNotifyUiOps *ops;
+
+	g_return_val_if_fail(uri != NULL, NULL);
+
+	ops = gaim_get_notify_ui_ops();
+
+	if (ops != NULL && ops->notify_uri != NULL) {
+		GaimNotifyInfo *info;
+
+		info            = g_new0(GaimNotifyInfo, 1);
+		info->type      = GAIM_NOTIFY_URI;
+		info->handle    = handle;
+		info->ui_handle = ops->notify_uri(uri);
+
+		handles = g_list_append(handles, info);
+
+		return info->ui_handle;
+	}
+
+	return NULL;
+}
+
 void
 gaim_notify_close(GaimNotifyType type, void *ui_handle)
 {
--- a/src/notify.h	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/notify.h	Thu Aug 14 03:55:13 2003 +0000
@@ -5,7 +5,7 @@
  * gaim
  *
  * Copyright (C) 2003 Christian Hammond <chipx86@gnupdate.org>
- * 
+ *
  * 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
  * the Free Software Foundation; either version 2 of the License, or
@@ -35,7 +35,8 @@
 	GAIM_NOTIFY_MESSAGE = 0, /**< Message notification.         */
 	GAIM_NOTIFY_EMAIL,       /**< Single e-mail notification.   */
 	GAIM_NOTIFY_EMAILS,      /**< Multiple e-mail notification. */
-	GAIM_NOTIFY_FORMATTED    /**< Formatted text.               */
+	GAIM_NOTIFY_FORMATTED,   /**< Formatted text.               */
+	GAIM_NOTIFY_URI          /**< URI notification or display.  */
 
 } GaimNotifyType;
 
@@ -68,6 +69,7 @@
 	void *(*notify_formatted)(const char *title, const char *primary,
 							  const char *secondary, const char *text,
 							  GCallback cb, void *user_data);
+	void *(*notify_uri)(const char *uri);
 
 	void (*close_notify)(GaimNotifyType type, void *ui_handle);
 
@@ -164,6 +166,18 @@
 							const char *text, GCallback cb, void *user_data);
 
 /**
+ * Opens a URI or somehow presents it to the user.
+ *
+ * @param handle The plugin or connection handle.
+ * @param url    The URI to display or go to.
+ *
+ * @return A UI-specific handle, if any. This may only be presented if
+ *         the UI code displays a dialog instead of a webpage, or something
+ *         similar.
+ */
+void *gaim_notify_uri(void *handle, const char *uri);
+
+/**
  * Closes a notification.
  *
  * This should be used only by the UI operation functions and part of the
--- a/src/protocols/oscar/oscar.c	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/protocols/oscar/oscar.c	Thu Aug 14 03:55:13 2003 +0000
@@ -46,7 +46,6 @@
 /* XXX CORE/UI */
 #include "gtkinternal.h"
 #include "gaim.h"
-#include "ui.h"
 
 
 #define UC_AOL		0x02
@@ -6082,7 +6081,7 @@
 {
 	struct oscar_data *od = gc->proto_data;
 	gchar *substituted = gaim_strreplace(od->sess->authinfo->chpassurl, "%s", gaim_account_get_username(gaim_connection_get_account(gc)));
-	open_url(NULL, substituted);
+	gaim_notify_uri(gc, substituted);
 	g_free(substituted);
 }
 
--- a/src/protocols/trepia/trepia.c	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/protocols/trepia/trepia.c	Thu Aug 14 03:55:13 2003 +0000
@@ -35,7 +35,6 @@
 /* XXX */
 #include "gaim.h"
 #include "multi.h"
-#include "ui.h" /* XXX for open_url */
 
 #ifndef _WIN32
 # include <sys/socket.h>
@@ -539,7 +538,7 @@
 	profile = b->proto_data;
 
 	if ((value = trepia_profile_get_homepage(profile)) != NULL)
-		open_url(NULL, value);
+		gaim_notify_uri(gc, value);
 }
 
 static GList *
--- a/src/protocols/yahoo/yahoo.c	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/protocols/yahoo/yahoo.c	Thu Aug 14 03:55:13 2003 +0000
@@ -1089,7 +1089,7 @@
 		t++;
 	*t = 0;
 	g_snprintf(url, sizeof url, "http://games.yahoo.com/games/%s", game);
-	open_url(NULL, url);
+	gaim_notify_uri(gc, url);
 	g_free(game);
 }
 
--- a/src/server.c	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/server.c	Thu Aug 14 03:55:13 2003 +0000
@@ -1431,6 +1431,12 @@
 	gtk_widget_destroy(window);
 }
 
+static void
+url_clicked_cb(GtkWidget *w, const char *uri)
+{
+	gaim_notify_uri(NULL, uri);
+}
+
 void serv_got_popup(const char *msg, const char *u, int wid, int hei)
 {
 	GtkWidget *window;
@@ -1474,7 +1480,7 @@
 	button = gaim_pixbuf_button_from_stock(_("More Info"), GTK_STOCK_FIND, GAIM_BUTTON_HORIZONTAL);
 	gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 5);
 	g_signal_connect(G_OBJECT(button), "clicked",
-					 G_CALLBACK(open_url), url);
+					 G_CALLBACK(url_clicked_cb), url);
 
 	gtk_widget_show_all(window);
 
--- a/src/ui.h	Thu Aug 14 03:28:17 2003 +0000
+++ b/src/ui.h	Thu Aug 14 03:55:13 2003 +0000
@@ -137,8 +137,7 @@
 extern void do_im_back(GtkWidget *w, GtkWidget *x);
 
 /* Functions in browser.c */
-extern void open_url(GtkWidget *, const char *);
-extern void add_bookmark(GtkWidget *, char *);
+void *gaim_gtk_notify_uri(const char *uri);
 
 /* Functions in dialogs.c */
 extern void alias_dialog_bud(struct buddy *);