fix implicit declarations
[rofl0r-ixchat.git] / src / fe-gtk / fe-gtk.c
blob949b7d9f46165db499ffb3951dfdbaa217734a93
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 "setup.h"
50 #include "notifygui.h"
51 #include "textgui.h"
52 #include "fkeys.h"
53 #include "plugin-tray.h"
54 #include "urlgrab.h"
56 #ifdef USE_XLIB
57 #include <gdk/gdkx.h>
58 #include <gtk/gtkinvisible.h>
59 #endif
61 #ifdef USE_GTKSPELL
62 #include <gtk/gtktextview.h>
63 #endif
65 GdkPixmap *channelwin_pix;
68 #ifdef USE_XLIB
70 static void
71 redraw_trans_xtexts (void)
73 GSList *list = sess_list;
74 session *sess;
75 int done_main = FALSE;
77 while (list)
79 sess = list->data;
80 if (GTK_XTEXT (sess->gui->xtext)->transparent)
82 if (!sess->gui->is_tab || !done_main)
83 gtk_xtext_refresh (GTK_XTEXT (sess->gui->xtext), 1);
84 if (sess->gui->is_tab)
85 done_main = TRUE;
87 list = list->next;
91 static GdkFilterReturn
92 root_event_cb (GdkXEvent *xev, GdkEventProperty *event, gpointer data)
94 static Atom at = None;
95 XEvent *xevent = (XEvent *)xev;
97 if (xevent->type == PropertyNotify)
99 if (at == None)
100 at = XInternAtom (xevent->xproperty.display, "_XROOTPMAP_ID", True);
102 if (at == xevent->xproperty.atom)
103 redraw_trans_xtexts ();
106 return GDK_FILTER_CONTINUE;
109 #endif
111 /* === command-line parameter parsing : requires glib 2.6 === */
113 static char *arg_cfgdir = NULL;
114 static gint arg_show_autoload = 0;
115 static gint arg_show_config = 0;
116 static gint arg_show_version = 0;
117 static gint arg_minimize = 0;
119 static const GOptionEntry gopt_entries[] =
121 {"no-auto", 'a', 0, G_OPTION_ARG_NONE, &arg_dont_autoconnect, N_("Don't auto connect to servers"), NULL},
122 {"cfgdir", 'd', 0, G_OPTION_ARG_STRING, &arg_cfgdir, N_("Use a different config directory"), "PATH"},
123 {"no-plugins", 'n', 0, G_OPTION_ARG_NONE, &arg_skip_plugins, N_("Don't auto load any plugins"), NULL},
124 {"plugindir", 'p', 0, G_OPTION_ARG_NONE, &arg_show_autoload, N_("Show plugin auto-load directory"), NULL},
125 {"configdir", 'u', 0, G_OPTION_ARG_NONE, &arg_show_config, N_("Show user config directory"), NULL},
126 {"url", 0, 0, G_OPTION_ARG_STRING, &arg_url, N_("Open an irc://server:port/channel URL"), "URL"},
127 {"command", 'c', 0, G_OPTION_ARG_STRING, &arg_command, N_("Execute command:"), "COMMAND"},
128 {"existing", 'e', 0, G_OPTION_ARG_NONE, &arg_existing, N_("Open URL or execute command in an existing XChat"), NULL},
129 {"minimize", 0, 0, G_OPTION_ARG_INT, &arg_minimize, N_("Begin minimized. Level 0=Normal 1=Iconified 2=Tray"), N_("level")},
130 {"version", 'v', 0, G_OPTION_ARG_NONE, &arg_show_version, N_("Show version information"), NULL},
131 {NULL}
135 fe_args (int argc, char *argv[])
137 GError *error = NULL;
138 GOptionContext *context;
140 context = g_option_context_new (NULL);
141 //g_option_context_add_main_entries (context, gopt_entries, GETTEXT_PACKAGE);
142 g_option_context_add_group (context, gtk_get_option_group (FALSE));
143 g_option_context_parse (context, &argc, &argv, &error);
145 if (error)
147 if (error->message)
148 printf ("%s\n", error->message);
149 return 1;
152 g_option_context_free (context);
154 if (arg_show_version)
156 printf (PACKAGE_TARNAME" "PACKAGE_VERSION"\n");
157 return 0;
160 if (arg_show_autoload)
162 printf ("%s\n", XCHATLIBDIR"/plugins");
163 return 0;
166 if (arg_show_config)
168 printf ("%s\n", get_xdir_fs ());
169 return 0;
172 if (arg_cfgdir) /* we want filesystem encoding */
174 xdir_fs = strdup (arg_cfgdir);
175 if (xdir_fs[strlen (xdir_fs) - 1] == '/')
176 xdir_fs[strlen (xdir_fs) - 1] = 0;
177 g_free (arg_cfgdir);
180 gtk_init (&argc, &argv);
182 #ifdef USE_XLIB
183 gdk_window_set_events (gdk_get_default_root_window (), GDK_PROPERTY_CHANGE_MASK);
184 gdk_window_add_filter (gdk_get_default_root_window (),
185 (GdkFilterFunc)root_event_cb, NULL);
186 #endif
188 return -1;
191 const char cursor_color_rc[] =
192 "style \"xc-ib-st\""
194 #ifdef USE_GTKSPELL
195 "GtkTextView::cursor-color=\"#%02x%02x%02x\""
196 #else
197 "GtkEntry::cursor-color=\"#%02x%02x%02x\""
198 #endif
200 "widget \"*.xchat-inputbox\" style : application \"xc-ib-st\"";
202 GtkStyle *
203 create_input_style (GtkStyle *style)
205 char buf[256];
206 static int done_rc = FALSE;
208 pango_font_description_free (style->font_desc);
209 style->font_desc = pango_font_description_from_string (prefs.font_normal);
211 /* fall back */
212 if (pango_font_description_get_size (style->font_desc) == 0)
214 snprintf (buf, sizeof (buf), _("Failed to open font:\n\n%s"), prefs.font_normal);
215 fe_message (buf, FE_MSG_ERROR);
216 pango_font_description_free (style->font_desc);
217 style->font_desc = pango_font_description_from_string ("sans 11");
220 if (prefs.style_inputbox && !done_rc)
222 done_rc = TRUE;
223 sprintf (buf, cursor_color_rc, (colors[COL_FG].red >> 8),
224 (colors[COL_FG].green >> 8), (colors[COL_FG].blue >> 8));
225 gtk_rc_parse_string (buf);
228 style->bg[GTK_STATE_NORMAL] = colors[COL_FG];
229 style->base[GTK_STATE_NORMAL] = colors[COL_BG];
230 style->text[GTK_STATE_NORMAL] = colors[COL_FG];
232 return style;
235 void
236 fe_init (void)
238 palette_load ();
239 key_init ();
240 pixmaps_init ();
242 channelwin_pix = pixmap_load_from_file (prefs.background);
243 input_style = create_input_style (gtk_style_new ());
246 void
247 fe_main (void)
249 gtk_main ();
251 /* sleep for 3 seconds so any QUIT messages are not lost. The */
252 /* GUI is closed at this point, so the user doesn't even know! */
253 if (prefs.wait_on_exit)
254 sleep (3);
257 void
258 fe_cleanup (void)
260 /* it's saved when pressing OK in setup.c */
261 /*palette_save ();*/
264 void
265 fe_exit (void)
267 gtk_main_quit ();
271 fe_timeout_add (int interval, void *callback, void *userdata)
273 return g_timeout_add (interval, (GSourceFunc) callback, userdata);
276 void
277 fe_timeout_remove (int tag)
279 g_source_remove (tag);
282 /* install tray stuff */
284 static int
285 fe_idle (gpointer data)
287 session *sess = sess_list->data;
289 plugin_add (sess, NULL, NULL, tray_plugin_init, tray_plugin_deinit, NULL, FALSE);
291 if (arg_minimize == 1)
292 gtk_window_iconify (GTK_WINDOW (sess->gui->window));
293 else if (arg_minimize == 2)
294 tray_toggle_visibility (FALSE);
296 return 0;
299 void
300 fe_new_window (session *sess, int focus)
302 int tab = FALSE;
304 if (sess->type == SESS_DIALOG)
306 if (prefs.privmsgtab)
307 tab = TRUE;
308 } else
310 if (prefs.tabchannels)
311 tab = TRUE;
314 mg_changui_new (sess, NULL, tab, focus);
316 if (!sess_list->next)
317 g_idle_add (fe_idle, NULL);
320 void
321 fe_new_server (struct server *serv)
323 serv->gui = malloc (sizeof (struct server_gui));
324 memset (serv->gui, 0, sizeof (struct server_gui));
327 void
328 fe_message (char *msg, int flags)
330 GtkWidget *dialog;
331 int type = GTK_MESSAGE_WARNING;
333 if (flags & FE_MSG_ERROR)
334 type = GTK_MESSAGE_ERROR;
335 if (flags & FE_MSG_INFO)
336 type = GTK_MESSAGE_INFO;
338 dialog = gtk_message_dialog_new (GTK_WINDOW (parent_window), 0, type,
339 GTK_BUTTONS_OK, "%s", msg);
340 if (flags & FE_MSG_MARKUP)
341 gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), msg);
342 g_signal_connect (G_OBJECT (dialog), "response",
343 G_CALLBACK (gtk_widget_destroy), 0);
344 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
345 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
346 gtk_widget_show (dialog);
348 if (flags & FE_MSG_WAIT)
349 gtk_dialog_run (GTK_DIALOG (dialog));
352 void
353 fe_idle_add (void *func, void *data)
355 g_idle_add (func, data);
358 void
359 fe_input_remove (int tag)
361 g_source_remove (tag);
365 fe_input_add (int sok, int flags, void *func, void *data)
367 int tag, type = 0;
368 GIOChannel *channel;
370 channel = g_io_channel_unix_new (sok);
372 if (flags & FIA_READ)
373 type |= G_IO_IN | G_IO_HUP | G_IO_ERR;
374 if (flags & FIA_WRITE)
375 type |= G_IO_OUT | G_IO_ERR;
376 if (flags & FIA_EX)
377 type |= G_IO_PRI;
379 tag = g_io_add_watch (channel, type, (GIOFunc) func, data);
380 g_io_channel_unref (channel);
382 return tag;
385 void
386 fe_set_topic (session *sess, char *topic, char *stripped_topic)
388 if (!sess->gui->is_tab || sess == current_tab)
390 gtk_entry_set_text (GTK_ENTRY (sess->gui->topic_entry), stripped_topic);
391 mg_set_topic_tip (sess);
392 } else
394 if (sess->res->topic_text)
395 free (sess->res->topic_text);
396 sess->res->topic_text = strdup (stripped_topic);
400 void
401 fe_set_hilight (struct session *sess)
403 if (sess->gui->is_tab)
404 fe_set_tab_color (sess, 3); /* set tab to blue */
406 if (prefs.input_flash_hilight)
407 fe_flash_window (sess); /* taskbar flash */
410 static void
411 fe_update_mode_entry (session *sess, GtkWidget *entry, char **text, char *new_text)
413 if (!sess->gui->is_tab || sess == current_tab)
415 if (sess->gui->flag_wid[0]) /* channel mode buttons enabled? */
416 gtk_entry_set_text (GTK_ENTRY (entry), new_text);
417 } else
419 if (sess->gui->is_tab)
421 if (*text)
422 free (*text);
423 *text = strdup (new_text);
428 void
429 fe_update_channel_key (struct session *sess)
431 fe_update_mode_entry (sess, sess->gui->key_entry,
432 &sess->res->key_text, sess->channelkey);
433 fe_set_title (sess);
436 void
437 fe_update_channel_limit (struct session *sess)
439 char tmp[16];
441 sprintf (tmp, "%d", sess->limit);
442 fe_update_mode_entry (sess, sess->gui->limit_entry,
443 &sess->res->limit_text, tmp);
444 fe_set_title (sess);
448 fe_is_chanwindow (struct server *serv)
450 if (!serv->gui->chanlist_window)
451 return 0;
452 return 1;
456 fe_is_banwindow (struct session *sess)
458 if (!sess->res->banlist_window)
459 return 0;
460 return 1;
463 void
464 fe_notify_update (char *name)
466 if (!name)
467 notify_gui_update ();
470 void
471 fe_text_clear (struct session *sess, int lines)
473 gtk_xtext_clear (sess->res->buffer, lines);
476 void
477 fe_close_window (struct session *sess)
479 if (sess->gui->is_tab)
480 mg_tab_close (sess);
481 else
482 gtk_widget_destroy (sess->gui->window);
485 void
486 fe_progressbar_start (session *sess)
488 if (!sess->gui->is_tab || current_tab == sess)
489 /* if it's the focused tab, create it for real! */
490 mg_progressbar_create (sess->gui);
491 else
492 /* otherwise just remember to create on when it gets focused */
493 sess->res->c_graph = TRUE;
496 void
497 fe_progressbar_end (server *serv)
499 GSList *list = sess_list;
500 session *sess;
502 while (list) /* check all windows that use this server and *
503 * remove the connecting graph, if it has one. */
505 sess = list->data;
506 if (sess->server == serv)
508 if (sess->gui->bar)
509 mg_progressbar_destroy (sess->gui);
510 sess->res->c_graph = FALSE;
512 list = list->next;
516 void
517 fe_print_text (struct session *sess, char *text, time_t stamp)
519 PrintTextRaw (sess->res->buffer, (unsigned char *)text, prefs.indent_nicks, stamp);
521 if (!sess->new_data && sess != current_tab &&
522 sess->gui->is_tab && !sess->nick_said && stamp == 0)
524 sess->new_data = TRUE;
525 if (sess->msg_said)
526 fe_set_tab_color (sess, 2);
527 else
528 fe_set_tab_color (sess, 1);
532 void
533 fe_beep (void)
535 gdk_beep ();
538 static int
539 lastlog_regex_cmp (char *a, regex_t *reg)
541 return !regexec (reg, a, 1, NULL, REG_NOTBOL);
544 void
545 fe_lastlog (session *sess, session *lastlog_sess, char *sstr, gboolean regexp)
547 regex_t reg;
549 if (gtk_xtext_is_empty (sess->res->buffer))
551 PrintText (lastlog_sess, _("Search buffer is empty.\n"));
552 return;
555 if (!regexp)
557 gtk_xtext_lastlog (lastlog_sess->res->buffer, sess->res->buffer,
558 (void *) nocasestrstr, sstr);
559 return;
562 if (regcomp (&reg, sstr, REG_ICASE | REG_EXTENDED | REG_NOSUB) == 0)
564 gtk_xtext_lastlog (lastlog_sess->res->buffer, sess->res->buffer,
565 (void *) lastlog_regex_cmp, &reg);
566 regfree (&reg);
570 void
571 fe_set_lag (server *serv, int lag)
573 GSList *list = sess_list;
574 session *sess;
575 gdouble per;
576 char lagtext[64];
577 char lagtip[128];
578 unsigned long nowtim;
580 if (lag == -1)
582 if (!serv->lag_sent)
583 return;
584 nowtim = make_ping_time ();
585 lag = (nowtim - serv->lag_sent) / 100000;
588 per = (double)((double)lag / (double)10);
589 if (per > 1.0)
590 per = 1.0;
592 snprintf (lagtext, sizeof (lagtext) - 1, "%s%d.%ds",
593 serv->lag_sent ? "+" : "", lag / 10, lag % 10);
594 snprintf (lagtip, sizeof (lagtip) - 1, "Lag: %s%d.%d seconds",
595 serv->lag_sent ? "+" : "", lag / 10, lag % 10);
597 while (list)
599 sess = list->data;
600 if (sess->server == serv)
602 if (sess->res->lag_tip)
603 free (sess->res->lag_tip);
604 sess->res->lag_tip = strdup (lagtip);
606 if (!sess->gui->is_tab || current_tab == sess)
608 if (sess->gui->lagometer)
610 gtk_progress_bar_set_fraction ((GtkProgressBar *) sess->gui->lagometer, per);
611 add_tip (sess->gui->lagometer->parent, lagtip);
613 if (sess->gui->laginfo)
614 gtk_label_set_text ((GtkLabel *) sess->gui->laginfo, lagtext);
615 } else
617 sess->res->lag_value = per;
618 if (sess->res->lag_text)
619 free (sess->res->lag_text);
620 sess->res->lag_text = strdup (lagtext);
623 list = list->next;
627 void
628 fe_set_throttle (server *serv)
630 GSList *list = sess_list;
631 struct session *sess;
632 float per;
633 char tbuf[96];
634 char tip[160];
636 per = (float) serv->sendq_len / 1024.0;
637 if (per > 1.0)
638 per = 1.0;
640 while (list)
642 sess = list->data;
643 if (sess->server == serv)
645 snprintf (tbuf, sizeof (tbuf) - 1, _("%d bytes"), serv->sendq_len);
646 snprintf (tip, sizeof (tip) - 1, _("Network send queue: %d bytes"), serv->sendq_len);
648 if (sess->res->queue_tip)
649 free (sess->res->queue_tip);
650 sess->res->queue_tip = strdup (tip);
652 if (!sess->gui->is_tab || current_tab == sess)
654 if (sess->gui->throttlemeter)
656 gtk_progress_bar_set_fraction ((GtkProgressBar *) sess->gui->throttlemeter, per);
657 add_tip (sess->gui->throttlemeter->parent, tip);
659 if (sess->gui->throttleinfo)
660 gtk_label_set_text ((GtkLabel *) sess->gui->throttleinfo, tbuf);
661 } else
663 sess->res->queue_value = per;
664 if (sess->res->queue_text)
665 free (sess->res->queue_text);
666 sess->res->queue_text = strdup (tbuf);
669 list = list->next;
673 void
674 fe_ctrl_gui (session *sess, fe_gui_action action, int arg)
676 switch (action)
678 case FE_GUI_HIDE:
679 gtk_widget_hide (sess->gui->window); break;
680 case FE_GUI_SHOW:
681 gtk_widget_show (sess->gui->window);
682 gtk_window_present (GTK_WINDOW (sess->gui->window));
683 break;
684 case FE_GUI_FOCUS:
685 mg_bring_tofront_sess (sess); break;
686 case FE_GUI_FLASH:
687 fe_flash_window (sess); break;
688 case FE_GUI_COLOR:
689 fe_set_tab_color (sess, arg); break;
690 case FE_GUI_ICONIFY:
691 gtk_window_iconify (GTK_WINDOW (sess->gui->window)); break;
692 case FE_GUI_MENU:
693 menu_bar_toggle (); /* toggle menubar on/off */
694 break;
695 case FE_GUI_ATTACH:
696 mg_detach (sess, arg); /* arg: 0=toggle 1=detach 2=attach */
697 break;
698 case FE_GUI_APPLY:
699 setup_apply_real (TRUE, TRUE, FALSE);
703 static void
704 dcc_saveas_cb (struct DCC *dcc, char *file)
706 if (is_dcc (dcc))
708 if (dcc->dccstat == STAT_QUEUED)
710 if (file)
711 dcc_get_with_destfile (dcc, file);
712 else if (dcc->resume_sent == 0)
713 dcc_abort (dcc->serv->front_session, dcc);
718 void
719 fe_confirm (const char *message, void (*yesproc)(void *), void (*noproc)(void *), void *ud)
721 /* warning, assuming fe_confirm is used by DCC only! */
722 struct DCC *dcc = ud;
724 if (dcc->file)
725 gtkutil_file_req (message, dcc_saveas_cb, ud, dcc->file,
726 FRF_WRITE|FRF_FILTERISINITIAL|FRF_NOASKOVERWRITE);
730 fe_gui_info (session *sess, int info_type)
732 switch (info_type)
734 case 0: /* window status */
735 #if GTK_CHECK_VERSION(2,20,0)
736 if (!gtk_widget_get_visible (GTK_WIDGET (sess->gui->window)))
737 #else
738 if (!GTK_WIDGET_VISIBLE (GTK_WIDGET (sess->gui->window)))
739 #endif
740 return 2; /* hidden (iconified or systray) */
742 if (gtk_window_is_active (GTK_WINDOW (sess->gui->window)))
743 return 1; /* active/focused */
745 return 0; /* normal (no keyboard focus or behind a window) */
748 return -1;
751 void *
752 fe_gui_info_ptr (session *sess, int info_type)
754 switch (info_type)
756 case 0: /* native window pointer (for plugins) */
757 return sess->gui->window;
758 break;
759 case 1: /* GtkWindow * (for plugins) */
760 return sess->gui->window;
762 return NULL;
765 char *
766 fe_get_inputbox_contents (session *sess)
768 /* not the current tab */
769 if (sess->res->input_text)
770 return sess->res->input_text;
772 /* current focused tab */
773 return SPELL_ENTRY_GET_TEXT (sess->gui->input_box);
777 fe_get_inputbox_cursor (session *sess)
779 /* not the current tab (we don't remember the cursor pos) */
780 if (sess->res->input_text)
781 return 0;
783 /* current focused tab */
784 return SPELL_ENTRY_GET_POS (sess->gui->input_box);
787 void
788 fe_set_inputbox_cursor (session *sess, int delta, int pos)
790 if (!sess->gui->is_tab || sess == current_tab)
792 if (delta)
793 pos += SPELL_ENTRY_GET_POS (sess->gui->input_box);
794 SPELL_ENTRY_SET_POS (sess->gui->input_box, pos);
795 } else
797 /* we don't support changing non-front tabs yet */
801 void
802 fe_set_inputbox_contents (session *sess, char *text)
804 if (!sess->gui->is_tab || sess == current_tab)
806 SPELL_ENTRY_SET_TEXT (sess->gui->input_box, text);
807 } else
809 if (sess->res->input_text)
810 free (sess->res->input_text);
811 sess->res->input_text = strdup (text);
815 static gboolean
816 try_browser (const char *browser, const char *arg, const char *url)
818 const char *argv[4];
819 char *path;
821 path = g_find_program_in_path (browser);
822 if (!path)
823 return 0;
825 argv[0] = path;
826 argv[1] = url;
827 argv[2] = NULL;
828 if (arg)
830 argv[1] = arg;
831 argv[2] = url;
832 argv[3] = NULL;
834 xchat_execv (argv);
835 g_free (path);
836 return 1;
839 static void
840 fe_open_url_inner (const char *url)
842 /* universal desktop URL opener (from xdg-utils). Supports gnome,kde,xfce4. */
843 if (try_browser ("xdg-open", NULL, url))
844 return;
846 /* try to detect GNOME */
847 if (g_getenv ("GNOME_DESKTOP_SESSION_ID"))
849 if (try_browser ("gnome-open", NULL, url)) /* Gnome 2.4+ has this */
850 return;
853 /* try to detect KDE */
854 if (g_getenv ("KDE_FULL_SESSION"))
856 if (try_browser ("kfmclient", "exec", url))
857 return;
860 /* everything failed, what now? just try firefox */
861 if (try_browser ("firefox", NULL, url))
862 return;
864 /* fresh out of ideas... */
865 try_browser ("mozilla", NULL, url);
868 static void
869 fe_open_url_locale (const char *url)
871 if (url[0] != '/' && strchr (url, ':') == NULL)
873 url = g_strdup_printf ("http://%s", url);
874 fe_open_url_inner (url);
875 g_free ((char *)url);
876 return;
878 fe_open_url_inner (url);
881 void
882 fe_open_url (const char *url)
884 char *loc;
886 if (prefs.utf8_locale)
888 fe_open_url_locale (url);
889 return;
892 /* the OS expects it in "locale" encoding. This makes it work on
893 unix systems that use ISO-8859-x and Win32. */
894 loc = g_locale_from_utf8 (url, -1, 0, 0, 0);
895 if (loc)
897 fe_open_url_locale (loc);
898 g_free (loc);
902 void
903 fe_server_event (server *serv, int type, int arg)
905 GSList *list = sess_list;
906 session *sess;
908 while (list)
910 sess = list->data;
911 if (sess->server == serv && (current_tab == sess || !sess->gui->is_tab))
913 session_gui *gui = sess->gui;
915 switch (type)
917 case FE_SE_CONNECTING: /* connecting in progress */
918 case FE_SE_RECONDELAY: /* reconnect delay begun */
919 /* enable Disconnect item */
920 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_DISCONNECT], 1);
921 break;
923 case FE_SE_CONNECT:
924 /* enable Disconnect and Away menu items */
925 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_AWAY], 1);
926 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_DISCONNECT], 1);
927 break;
929 case FE_SE_LOGGEDIN: /* end of MOTD */
930 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_JOIN], 1);
931 /* if number of auto-join channels is zero, open joind */
932 if (arg == 0)
933 joind_open (serv);
934 break;
936 case FE_SE_DISCONNECT:
937 /* disable Disconnect and Away menu items */
938 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_AWAY], 0);
939 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_DISCONNECT], 0);
940 gtk_widget_set_sensitive (gui->menu_item[MENU_ID_JOIN], 0);
941 /* close the join-dialog, if one exists */
942 joind_close (serv);
945 list = list->next;
949 void
950 fe_get_file (const char *title, char *initial,
951 void (*callback) (void *userdata, char *file), void *userdata,
952 int flags)
955 /* OK: Call callback once per file, then once more with file=NULL. */
956 /* CANCEL: Call callback once with file=NULL. */
957 gtkutil_file_req (title, callback, userdata, initial, flags | FRF_FILTERISINITIAL);