Use macros instead of raw numbers for login type
[rofl0r-ixchat.git] / src / fe-gtk / fe-gtk.c
blob9528ca9d330b99f4a55ebbfe9388ac94f27357c6
1 /* X-Chat
2 * Copyright (C) 1998 Peter Zelezny.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <unistd.h>
24 #include "fe-gtk.h"
26 #include <gtk/gtkmain.h>
27 #include <gtk/gtkentry.h>
28 #include <gtk/gtkprogressbar.h>
29 #include <gtk/gtkbox.h>
30 #include <gtk/gtklabel.h>
31 #include <gtk/gtktogglebutton.h>
32 #include <gtk/gtkmessagedialog.h>
33 #include <gtk/gtkversion.h>
35 #include "../common/xchat.h"
36 #include "../common/fe.h"
37 #include "../common/util.h"
38 #include "../common/text.h"
39 #include "../common/cfgfiles.h"
40 #include "../common/xchatc.h"
41 #include "../common/plugin.h"
42 #include "gtkutil.h"
43 #include "maingui.h"
44 #include "pixmaps.h"
45 #include "joind.h"
46 #include "xtext.h"
47 #include "palette.h"
48 #include "menu.h"
49 #include "notifygui.h"
50 #include "textgui.h"
51 #include "fkeys.h"
52 #include "plugin-tray.h"
53 #include "urlgrab.h"
55 #ifdef USE_XLIB
56 #include <gdk/gdkx.h>
57 #include <gtk/gtkinvisible.h>
58 #endif
60 #ifdef USE_GTKSPELL
61 #include <gtk/gtktextview.h>
62 #endif
64 GdkPixmap *channelwin_pix;
67 #ifdef USE_XLIB
69 static void
70 redraw_trans_xtexts (void)
72 GSList *list = sess_list;
73 session *sess;
74 int done_main = FALSE;
76 while (list)
78 sess = list->data;
79 if (GTK_XTEXT (sess->gui->xtext)->transparent)
81 if (!sess->gui->is_tab || !done_main)
82 gtk_xtext_refresh (GTK_XTEXT (sess->gui->xtext), 1);
83 if (sess->gui->is_tab)
84 done_main = TRUE;
86 list = list->next;
90 static GdkFilterReturn
91 root_event_cb (GdkXEvent *xev, GdkEventProperty *event, gpointer data)
93 static Atom at = None;
94 XEvent *xevent = (XEvent *)xev;
96 if (xevent->type == PropertyNotify)
98 if (at == None)
99 at = XInternAtom (xevent->xproperty.display, "_XROOTPMAP_ID", True);
101 if (at == xevent->xproperty.atom)
102 redraw_trans_xtexts ();
105 return GDK_FILTER_CONTINUE;
108 #endif
110 /* === command-line parameter parsing : requires glib 2.6 === */
112 static char *arg_cfgdir = NULL;
113 static gint arg_show_autoload = 0;
114 static gint arg_show_config = 0;
115 static gint arg_show_version = 0;
116 static gint arg_minimize = 0;
118 static const GOptionEntry gopt_entries[] =
120 {"no-auto", 'a', 0, G_OPTION_ARG_NONE, &arg_dont_autoconnect, N_("Don't auto connect to servers"), NULL},
121 {"cfgdir", 'd', 0, G_OPTION_ARG_STRING, &arg_cfgdir, N_("Use a different config directory"), "PATH"},
122 {"no-plugins", 'n', 0, G_OPTION_ARG_NONE, &arg_skip_plugins, N_("Don't auto load any plugins"), NULL},
123 {"plugindir", 'p', 0, G_OPTION_ARG_NONE, &arg_show_autoload, N_("Show plugin auto-load directory"), NULL},
124 {"configdir", 'u', 0, G_OPTION_ARG_NONE, &arg_show_config, N_("Show user config directory"), NULL},
125 {"url", 0, 0, G_OPTION_ARG_STRING, &arg_url, N_("Open an irc://server:port/channel URL"), "URL"},
126 {"command", 'c', 0, G_OPTION_ARG_STRING, &arg_command, N_("Execute command:"), "COMMAND"},
127 {"existing", 'e', 0, G_OPTION_ARG_NONE, &arg_existing, N_("Open URL or execute command in an existing XChat"), NULL},
128 {"minimize", 0, 0, G_OPTION_ARG_INT, &arg_minimize, N_("Begin minimized. Level 0=Normal 1=Iconified 2=Tray"), N_("level")},
129 {"version", 'v', 0, G_OPTION_ARG_NONE, &arg_show_version, N_("Show version information"), NULL},
130 {NULL}
134 fe_args (int argc, char *argv[])
136 GError *error = NULL;
137 GOptionContext *context;
139 context = g_option_context_new (NULL);
140 //g_option_context_add_main_entries (context, gopt_entries, GETTEXT_PACKAGE);
141 g_option_context_add_group (context, gtk_get_option_group (FALSE));
142 g_option_context_parse (context, &argc, &argv, &error);
144 if (error)
146 if (error->message)
147 printf ("%s\n", error->message);
148 return 1;
151 g_option_context_free (context);
153 if (arg_show_version)
155 printf (PACKAGE_TARNAME" "PACKAGE_VERSION"\n");
156 return 0;
159 if (arg_show_autoload)
161 printf ("%s\n", XCHATLIBDIR"/plugins");
162 return 0;
165 if (arg_show_config)
167 printf ("%s\n", get_xdir_fs ());
168 return 0;
171 if (arg_cfgdir) /* we want filesystem encoding */
173 xdir_fs = strdup (arg_cfgdir);
174 if (xdir_fs[strlen (xdir_fs) - 1] == '/')
175 xdir_fs[strlen (xdir_fs) - 1] = 0;
176 g_free (arg_cfgdir);
179 gtk_init (&argc, &argv);
181 #ifdef USE_XLIB
182 gdk_window_set_events (gdk_get_default_root_window (), GDK_PROPERTY_CHANGE_MASK);
183 gdk_window_add_filter (gdk_get_default_root_window (),
184 (GdkFilterFunc)root_event_cb, NULL);
185 #endif
187 return -1;
190 const char cursor_color_rc[] =
191 "style \"xc-ib-st\""
193 #ifdef USE_GTKSPELL
194 "GtkTextView::cursor-color=\"#%02x%02x%02x\""
195 #else
196 "GtkEntry::cursor-color=\"#%02x%02x%02x\""
197 #endif
199 "widget \"*.xchat-inputbox\" style : application \"xc-ib-st\"";
201 GtkStyle *
202 create_input_style (GtkStyle *style)
204 char buf[256];
205 static int done_rc = FALSE;
207 pango_font_description_free (style->font_desc);
208 style->font_desc = pango_font_description_from_string (prefs.font_normal);
210 /* fall back */
211 if (pango_font_description_get_size (style->font_desc) == 0)
213 snprintf (buf, sizeof (buf), _("Failed to open font:\n\n%s"), prefs.font_normal);
214 fe_message (buf, FE_MSG_ERROR);
215 pango_font_description_free (style->font_desc);
216 style->font_desc = pango_font_description_from_string ("sans 11");
219 if (prefs.style_inputbox && !done_rc)
221 done_rc = TRUE;
222 sprintf (buf, cursor_color_rc, (colors[COL_FG].red >> 8),
223 (colors[COL_FG].green >> 8), (colors[COL_FG].blue >> 8));
224 gtk_rc_parse_string (buf);
227 style->bg[GTK_STATE_NORMAL] = colors[COL_FG];
228 style->base[GTK_STATE_NORMAL] = colors[COL_BG];
229 style->text[GTK_STATE_NORMAL] = colors[COL_FG];
231 return style;
234 void
235 fe_init (void)
237 palette_load ();
238 key_init ();
239 pixmaps_init ();
241 channelwin_pix = pixmap_load_from_file (prefs.background);
242 input_style = create_input_style (gtk_style_new ());
245 void
246 fe_main (void)
248 gtk_main ();
250 /* sleep for 3 seconds so any QUIT messages are not lost. The */
251 /* GUI is closed at this point, so the user doesn't even know! */
252 if (prefs.wait_on_exit)
253 sleep (3);
256 void
257 fe_cleanup (void)
259 /* it's saved when pressing OK in setup.c */
260 /*palette_save ();*/
263 void
264 fe_exit (void)
266 gtk_main_quit ();
270 fe_timeout_add (int interval, void *callback, void *userdata)
272 return g_timeout_add (interval, (GSourceFunc) callback, userdata);
275 void
276 fe_timeout_remove (int tag)
278 g_source_remove (tag);
281 /* install tray stuff */
283 static int
284 fe_idle (gpointer data)
286 session *sess = sess_list->data;
288 plugin_add (sess, NULL, NULL, tray_plugin_init, tray_plugin_deinit, NULL, FALSE);
290 if (arg_minimize == 1)
291 gtk_window_iconify (GTK_WINDOW (sess->gui->window));
292 else if (arg_minimize == 2)
293 tray_toggle_visibility (FALSE);
295 return 0;
298 void
299 fe_new_window (session *sess, int focus)
301 int tab = FALSE;
303 if (sess->type == SESS_DIALOG)
305 if (prefs.privmsgtab)
306 tab = TRUE;
307 } else
309 if (prefs.tabchannels)
310 tab = TRUE;
313 mg_changui_new (sess, NULL, tab, focus);
315 if (!sess_list->next)
316 g_idle_add (fe_idle, NULL);
319 void
320 fe_new_server (struct server *serv)
322 serv->gui = malloc (sizeof (struct server_gui));
323 memset (serv->gui, 0, sizeof (struct server_gui));
326 void
327 fe_message (char *msg, int flags)
329 GtkWidget *dialog;
330 int type = GTK_MESSAGE_WARNING;
332 if (flags & FE_MSG_ERROR)
333 type = GTK_MESSAGE_ERROR;
334 if (flags & FE_MSG_INFO)
335 type = GTK_MESSAGE_INFO;
337 dialog = gtk_message_dialog_new (GTK_WINDOW (parent_window), 0, type,
338 GTK_BUTTONS_OK, "%s", msg);
339 if (flags & FE_MSG_MARKUP)
340 gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), msg);
341 g_signal_connect (G_OBJECT (dialog), "response",
342 G_CALLBACK (gtk_widget_destroy), 0);
343 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
344 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
345 gtk_widget_show (dialog);
347 if (flags & FE_MSG_WAIT)
348 gtk_dialog_run (GTK_DIALOG (dialog));
351 void
352 fe_idle_add (void *func, void *data)
354 g_idle_add (func, data);
357 void
358 fe_input_remove (int tag)
360 g_source_remove (tag);
364 fe_input_add (int sok, int flags, void *func, void *data)
366 int tag, type = 0;
367 GIOChannel *channel;
369 channel = g_io_channel_unix_new (sok);
371 if (flags & FIA_READ)
372 type |= G_IO_IN | G_IO_HUP | G_IO_ERR;
373 if (flags & FIA_WRITE)
374 type |= G_IO_OUT | G_IO_ERR;
375 if (flags & FIA_EX)
376 type |= G_IO_PRI;
378 tag = g_io_add_watch (channel, type, (GIOFunc) func, data);
379 g_io_channel_unref (channel);
381 return tag;
384 void
385 fe_set_topic (session *sess, char *topic, char *stripped_topic)
387 if (!sess->gui->is_tab || sess == current_tab)
389 gtk_entry_set_text (GTK_ENTRY (sess->gui->topic_entry), stripped_topic);
390 mg_set_topic_tip (sess);
391 } else
393 if (sess->res->topic_text)
394 free (sess->res->topic_text);
395 sess->res->topic_text = strdup (stripped_topic);
399 void
400 fe_set_hilight (struct session *sess)
402 if (sess->gui->is_tab)
403 fe_set_tab_color (sess, 3); /* set tab to blue */
405 if (prefs.input_flash_hilight)
406 fe_flash_window (sess); /* taskbar flash */
409 static void
410 fe_update_mode_entry (session *sess, GtkWidget *entry, char **text, char *new_text)
412 if (!sess->gui->is_tab || sess == current_tab)
414 if (sess->gui->flag_wid[0]) /* channel mode buttons enabled? */
415 gtk_entry_set_text (GTK_ENTRY (entry), new_text);
416 } else
418 if (sess->gui->is_tab)
420 if (*text)
421 free (*text);
422 *text = strdup (new_text);
427 void
428 fe_update_channel_key (struct session *sess)
430 fe_update_mode_entry (sess, sess->gui->key_entry,
431 &sess->res->key_text, sess->channelkey);
432 fe_set_title (sess);
435 void
436 fe_update_channel_limit (struct session *sess)
438 char tmp[16];
440 sprintf (tmp, "%d", sess->limit);
441 fe_update_mode_entry (sess, sess->gui->limit_entry,
442 &sess->res->limit_text, tmp);
443 fe_set_title (sess);
447 fe_is_chanwindow (struct server *serv)
449 if (!serv->gui->chanlist_window)
450 return 0;
451 return 1;
455 fe_is_banwindow (struct session *sess)
457 if (!sess->res->banlist_window)
458 return 0;
459 return 1;
462 void
463 fe_notify_update (char *name)
465 if (!name)
466 notify_gui_update ();
469 void
470 fe_text_clear (struct session *sess, int lines)
472 gtk_xtext_clear (sess->res->buffer, lines);
475 void
476 fe_close_window (struct session *sess)
478 if (sess->gui->is_tab)
479 mg_tab_close (sess);
480 else
481 gtk_widget_destroy (sess->gui->window);
484 void
485 fe_progressbar_start (session *sess)
487 if (!sess->gui->is_tab || current_tab == sess)
488 /* if it's the focused tab, create it for real! */
489 mg_progressbar_create (sess->gui);
490 else
491 /* otherwise just remember to create on when it gets focused */
492 sess->res->c_graph = TRUE;
495 void
496 fe_progressbar_end (server *serv)
498 GSList *list = sess_list;
499 session *sess;
501 while (list) /* check all windows that use this server and *
502 * remove the connecting graph, if it has one. */
504 sess = list->data;
505 if (sess->server == serv)
507 if (sess->gui->bar)
508 mg_progressbar_destroy (sess->gui);
509 sess->res->c_graph = FALSE;
511 list = list->next;
515 void
516 fe_print_text (struct session *sess, char *text, time_t stamp)
518 PrintTextRaw (sess->res->buffer, (unsigned char *)text, prefs.indent_nicks, stamp);
520 if (!sess->new_data && sess != current_tab &&
521 sess->gui->is_tab && !sess->nick_said && stamp == 0)
523 sess->new_data = TRUE;
524 if (sess->msg_said)
525 fe_set_tab_color (sess, 2);
526 else
527 fe_set_tab_color (sess, 1);
531 void
532 fe_beep (void)
534 gdk_beep ();
537 static int
538 lastlog_regex_cmp (char *a, regex_t *reg)
540 return !regexec (reg, a, 1, NULL, REG_NOTBOL);
543 void
544 fe_lastlog (session *sess, session *lastlog_sess, char *sstr, gboolean regexp)
546 regex_t reg;
548 if (gtk_xtext_is_empty (sess->res->buffer))
550 PrintText (lastlog_sess, _("Search buffer is empty.\n"));
551 return;
554 if (!regexp)
556 gtk_xtext_lastlog (lastlog_sess->res->buffer, sess->res->buffer,
557 (void *) nocasestrstr, sstr);
558 return;
561 if (regcomp (&reg, sstr, REG_ICASE | REG_EXTENDED | REG_NOSUB) == 0)
563 gtk_xtext_lastlog (lastlog_sess->res->buffer, sess->res->buffer,
564 (void *) lastlog_regex_cmp, &reg);
565 regfree (&reg);
569 void
570 fe_set_lag (server *serv, int lag)
572 GSList *list = sess_list;
573 session *sess;
574 gdouble per;
575 char lagtext[64];
576 char lagtip[128];
577 unsigned long nowtim;
579 if (lag == -1)
581 if (!serv->lag_sent)
582 return;
583 nowtim = make_ping_time ();
584 lag = (nowtim - serv->lag_sent) / 100000;
587 per = (double)((double)lag / (double)10);
588 if (per > 1.0)
589 per = 1.0;
591 snprintf (lagtext, sizeof (lagtext) - 1, "%s%d.%ds",
592 serv->lag_sent ? "+" : "", lag / 10, lag % 10);
593 snprintf (lagtip, sizeof (lagtip) - 1, "Lag: %s%d.%d seconds",
594 serv->lag_sent ? "+" : "", lag / 10, lag % 10);
596 while (list)
598 sess = list->data;
599 if (sess->server == serv)
601 if (sess->res->lag_tip)
602 free (sess->res->lag_tip);
603 sess->res->lag_tip = strdup (lagtip);
605 if (!sess->gui->is_tab || current_tab == sess)
607 if (sess->gui->lagometer)
609 gtk_progress_bar_set_fraction ((GtkProgressBar *) sess->gui->lagometer, per);
610 add_tip (sess->gui->lagometer->parent, lagtip);
612 if (sess->gui->laginfo)
613 gtk_label_set_text ((GtkLabel *) sess->gui->laginfo, lagtext);
614 } else
616 sess->res->lag_value = per;
617 if (sess->res->lag_text)
618 free (sess->res->lag_text);
619 sess->res->lag_text = strdup (lagtext);
622 list = list->next;
626 void
627 fe_set_throttle (server *serv)
629 GSList *list = sess_list;
630 struct session *sess;
631 float per;
632 char tbuf[96];
633 char tip[160];
635 per = (float) serv->sendq_len / 1024.0;
636 if (per > 1.0)
637 per = 1.0;
639 while (list)
641 sess = list->data;
642 if (sess->server == serv)
644 snprintf (tbuf, sizeof (tbuf) - 1, _("%d bytes"), serv->sendq_len);
645 snprintf (tip, sizeof (tip) - 1, _("Network send queue: %d bytes"), serv->sendq_len);
647 if (sess->res->queue_tip)
648 free (sess->res->queue_tip);
649 sess->res->queue_tip = strdup (tip);
651 if (!sess->gui->is_tab || current_tab == sess)
653 if (sess->gui->throttlemeter)
655 gtk_progress_bar_set_fraction ((GtkProgressBar *) sess->gui->throttlemeter, per);
656 add_tip (sess->gui->throttlemeter->parent, tip);
658 if (sess->gui->throttleinfo)
659 gtk_label_set_text ((GtkLabel *) sess->gui->throttleinfo, tbuf);
660 } else
662 sess->res->queue_value = per;
663 if (sess->res->queue_text)
664 free (sess->res->queue_text);
665 sess->res->queue_text = strdup (tbuf);
668 list = list->next;
672 void
673 fe_ctrl_gui (session *sess, fe_gui_action action, int arg)
675 switch (action)
677 case FE_GUI_HIDE:
678 gtk_widget_hide (sess->gui->window); break;
679 case FE_GUI_SHOW:
680 gtk_widget_show (sess->gui->window);
681 gtk_window_present (GTK_WINDOW (sess->gui->window));
682 break;
683 case FE_GUI_FOCUS:
684 mg_bring_tofront_sess (sess); break;
685 case FE_GUI_FLASH:
686 fe_flash_window (sess); break;
687 case FE_GUI_COLOR:
688 fe_set_tab_color (sess, arg); break;
689 case FE_GUI_ICONIFY:
690 gtk_window_iconify (GTK_WINDOW (sess->gui->window)); break;
691 case FE_GUI_MENU:
692 menu_bar_toggle (); /* toggle menubar on/off */
693 break;
694 case FE_GUI_ATTACH:
695 mg_detach (sess, arg); /* arg: 0=toggle 1=detach 2=attach */
696 break;
697 case FE_GUI_APPLY:
698 setup_apply_real (TRUE, TRUE);
702 static void
703 dcc_saveas_cb (struct DCC *dcc, char *file)
705 if (is_dcc (dcc))
707 if (dcc->dccstat == STAT_QUEUED)
709 if (file)
710 dcc_get_with_destfile (dcc, file);
711 else if (dcc->resume_sent == 0)
712 dcc_abort (dcc->serv->front_session, dcc);
717 void
718 fe_confirm (const char *message, void (*yesproc)(void *), void (*noproc)(void *), void *ud)
720 /* warning, assuming fe_confirm is used by DCC only! */
721 struct DCC *dcc = ud;
723 if (dcc->file)
724 gtkutil_file_req (message, dcc_saveas_cb, ud, dcc->file,
725 FRF_WRITE|FRF_FILTERISINITIAL|FRF_NOASKOVERWRITE);
729 fe_gui_info (session *sess, int info_type)
731 switch (info_type)
733 case 0: /* window status */
734 #if GTK_CHECK_VERSION(2,20,0)
735 if (!gtk_widget_get_visible (GTK_WIDGET (sess->gui->window)))
736 #else
737 if (!GTK_WIDGET_VISIBLE (GTK_WIDGET (sess->gui->window)))
738 #endif
739 return 2; /* hidden (iconified or systray) */
741 if (gtk_window_is_active (GTK_WINDOW (sess->gui->window)))
742 return 1; /* active/focused */
744 return 0; /* normal (no keyboard focus or behind a window) */
747 return -1;
750 void *
751 fe_gui_info_ptr (session *sess, int info_type)
753 switch (info_type)
755 case 0: /* native window pointer (for plugins) */
756 return sess->gui->window;
757 break;
758 case 1: /* GtkWindow * (for plugins) */
759 return sess->gui->window;
761 return NULL;
764 char *
765 fe_get_inputbox_contents (session *sess)
767 /* not the current tab */
768 if (sess->res->input_text)
769 return sess->res->input_text;
771 /* current focused tab */
772 return SPELL_ENTRY_GET_TEXT (sess->gui->input_box);
776 fe_get_inputbox_cursor (session *sess)
778 /* not the current tab (we don't remember the cursor pos) */
779 if (sess->res->input_text)
780 return 0;
782 /* current focused tab */
783 return SPELL_ENTRY_GET_POS (sess->gui->input_box);
786 void
787 fe_set_inputbox_cursor (session *sess, int delta, int pos)
789 if (!sess->gui->is_tab || sess == current_tab)
791 if (delta)
792 pos += SPELL_ENTRY_GET_POS (sess->gui->input_box);
793 SPELL_ENTRY_SET_POS (sess->gui->input_box, pos);
794 } else
796 /* we don't support changing non-front tabs yet */
800 void
801 fe_set_inputbox_contents (session *sess, char *text)
803 if (!sess->gui->is_tab || sess == current_tab)
805 SPELL_ENTRY_SET_TEXT (sess->gui->input_box, text);
806 } else
808 if (sess->res->input_text)
809 free (sess->res->input_text);
810 sess->res->input_text = strdup (text);
814 static gboolean
815 try_browser (const char *browser, const char *arg, const char *url)
817 const char *argv[4];
818 char *path;
820 path = g_find_program_in_path (browser);
821 if (!path)
822 return 0;
824 argv[0] = path;
825 argv[1] = url;
826 argv[2] = NULL;
827 if (arg)
829 argv[1] = arg;
830 argv[2] = url;
831 argv[3] = NULL;
833 xchat_execv (argv);
834 g_free (path);
835 return 1;
838 static void
839 fe_open_url_inner (const char *url)
841 /* universal desktop URL opener (from xdg-utils). Supports gnome,kde,xfce4. */
842 if (try_browser ("xdg-open", NULL, url))
843 return;
845 /* try to detect GNOME */
846 if (g_getenv ("GNOME_DESKTOP_SESSION_ID"))
848 if (try_browser ("gnome-open", NULL, url)) /* Gnome 2.4+ has this */
849 return;
852 /* try to detect KDE */
853 if (g_getenv ("KDE_FULL_SESSION"))
855 if (try_browser ("kfmclient", "exec", url))
856 return;
859 /* everything failed, what now? just try firefox */
860 if (try_browser ("firefox", NULL, url))
861 return;
863 /* fresh out of ideas... */
864 try_browser ("mozilla", NULL, url);
867 static void
868 fe_open_url_locale (const char *url)
870 if (url[0] != '/' && strchr (url, ':') == NULL)
872 url = g_strdup_printf ("http://%s", url);
873 fe_open_url_inner (url);
874 g_free ((char *)url);
875 return;
877 fe_open_url_inner (url);
880 void
881 fe_open_url (const char *url)
883 char *loc;
885 if (prefs.utf8_locale)
887 fe_open_url_locale (url);
888 return;
891 /* the OS expects it in "locale" encoding. This makes it work on
892 unix systems that use ISO-8859-x and Win32. */
893 loc = g_locale_from_utf8 (url, -1, 0, 0, 0);
894 if (loc)
896 fe_open_url_locale (loc);
897 g_free (loc);
901 void
902 fe_server_event (server *serv, int type, int arg)
904 GSList *list = sess_list;
905 session *sess;
907 while (list)
909 sess = list->data;
910 if (sess->server == serv && (current_tab == sess || !sess->gui->is_tab))
912 session_gui *gui = sess->gui;
914 switch (type)
916 case FE_SE_CONNECTING: /* connecting in progress */
917 case FE_SE_RECONDELAY: /* reconnect delay begun */
918 /* enable Disconnect item */
919 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_DISCONNECT], 1);
920 break;
922 case FE_SE_CONNECT:
923 /* enable Disconnect and Away menu items */
924 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_AWAY], 1);
925 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_DISCONNECT], 1);
926 break;
928 case FE_SE_LOGGEDIN: /* end of MOTD */
929 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_JOIN], 1);
930 /* if number of auto-join channels is zero, open joind */
931 if (arg == 0)
932 joind_open (serv);
933 break;
935 case FE_SE_DISCONNECT:
936 /* disable Disconnect and Away menu items */
937 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_AWAY], 0);
938 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_DISCONNECT], 0);
939 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_JOIN], 0);
940 /* close the join-dialog, if one exists */
941 joind_close (serv);
944 list = list->next;
948 void
949 fe_get_file (const char *title, char *initial,
950 void (*callback) (void *userdata, char *file), void *userdata,
951 int flags)
954 /* OK: Call callback once per file, then once more with file=NULL. */
955 /* CANCEL: Call callback once with file=NULL. */
956 gtkutil_file_req (title, callback, userdata, initial, flags | FRF_FILTERISINITIAL);