* editmenu.c (edit_wrap_cmd): Use g_free() on the result
[midnight-commander.git] / gnome / gmain.c
blobaa034c949116fd129c9d1bbdcbfe6f468e8b8f35
1 /*
2 * Midnight Commander -- GNOME frontend
4 * Copyright (C) 1997, 1998 The Free Software Foundation
6 * Author: Miguel de Icaza (miguel@gnu.org)
8 */
10 #include <config.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <signal.h>
15 #define WANT_WIDGETS /* bleah */
16 #include "tty.h" /* for KEY_BACKSPACE */
17 #include "x.h"
18 #include "main.h"
19 #include "key.h"
20 #include "global.h"
21 #include "dir.h"
22 #include "panel.h"
23 #include "gscreen.h"
24 #include "gcmd.h"
25 #include "gcorba.h"
26 #include "gdesktop.h"
27 #include "gsession.h"
28 #include "command.h"
29 #include "cmd.h"
30 #include <gdk/gdkx.h>
32 #ifdef HAVE_GNOME_WINDOW_ICON
33 #include <libgnomeui/gnome-window-icon.h>
34 #endif
36 GdkColorContext *mc_cc;
38 #define MAX_COLOR_PAIRS 40
39 struct gmc_color_pairs_s gmc_color_pairs [MAX_COLOR_PAIRS];
41 char *default_edition_colors =
42 "normal=black:"
43 "selected=white,darkblue:"
44 "viewunderline=red,blue:"
45 "directory=blue:"
46 "markselect=yellow,darkblue:"
47 "marked=yellow,seagreen:"
48 "execute=slateblue:"
49 "link=green:"
50 "stalledlink=red:"
51 "device=magenta:"
52 "core=red:"
53 "menuhotsel=cyan,black:"
54 "errors=white,red:"
55 "reverse=black,lightcyan:"
56 "special=black";
58 int dialog_panel_callback (struct Dlg_head *h, int id, int msg);
60 /* The Dlg_head for the whole desktop */
61 Dlg_head *desktop_dlg;
63 /* Session client */
64 GnomeClient *session_client;
66 /* Used during argument processing */
67 extern int finish_program;
69 /* Whether the gmc server was present or not */
70 int corba_have_server = FALSE;
72 void
73 init_pair (int index, GdkColor *fore, GdkColor *back)
75 if (index < 0 || index > MAX_COLOR_PAIRS){
76 printf ("init_pair called with invalid index\n");
77 exit (1);
79 gmc_color_pairs [index].fore = fore;
80 gmc_color_pairs [index].back = back;
83 void
84 get_color (char *cpp, GdkColor **colp)
86 GdkColor *new_color;
87 int result;
88 gint status;
90 new_color = g_new (GdkColor, 1);
91 result = gdk_color_parse (cpp, new_color);
92 new_color->pixel = 0;
94 if (result) {
95 status = 0;
96 gdk_color_context_get_pixels (mc_cc,
97 &new_color->red, &new_color->green, &new_color->blue,
98 1, &new_color->pixel, &status);
99 } else
100 new_color->red = new_color->green = new_color->blue = 0;
102 *colp = new_color;
105 static void
106 gmc_color_init (void)
108 mc_cc = gdk_color_context_new (gtk_widget_get_default_visual (),
109 gtk_widget_get_default_colormap ());
113 xtoolkit_init (int *argc, char *argv [])
115 signal (SIGTTIN, SIG_IGN);
116 signal (SIGTTOU, SIG_IGN);
117 gmc_color_init ();
118 return 0;
121 void
122 interactive_display (char *filename, char *node)
124 /* FIXME: Implement gnome version */
127 void
128 xtoolkit_end (void)
130 /* Do nothing */
134 * Keystroke event handler for all of the Gtk widgets created by
135 * the GNOME Midnight Commander. A special case is handled at
136 * the top
139 dialog_key_pressed (GtkWidget *win, GdkEventKey *event, Dlg_head *h)
141 GtkWidget *w;
142 static int on_escape;
143 int key;
146 * Find out if the focused widget is an IconList and
147 * if so, check if it has a currently focused item is
148 * on editing mode as we do not want to handle key
149 * events while the icon name is being edited.
151 w = win;
152 while (w && (GTK_IS_CONTAINER (w) && !GNOME_IS_ICON_LIST (w)))
153 w = GTK_CONTAINER (w)->focus_child;
155 if (w && GNOME_IS_ICON_LIST (w)){
156 GnomeCanvas *c = GNOME_CANVAS (w);
158 if (c->focused_item && GNOME_IS_ICON_TEXT_ITEM (c->focused_item)){
159 GnomeIconTextItem *i = GNOME_ICON_TEXT_ITEM (c->focused_item);
161 if (i->editing)
162 return FALSE;
167 key = translate_gdk_keysym_to_curses (event);
168 if (key == -1)
169 return FALSE;
171 if (!on_escape){
172 if (key == 27){
173 on_escape = 1;
174 gtk_signal_emit_stop_by_name (GTK_OBJECT (win), "key_press_event");
175 return TRUE;
177 } else {
178 if (key != 27){
179 if (key >= '0' && key <= '9')
180 key = KEY_F(key - '0');
181 else
182 key = ALT (key);
184 if (key == ALT('<'))
185 key = KEY_HOME;
186 if (key == ALT('>'))
187 key = KEY_END;
189 on_escape = 0;
192 if (dlg_key_event (h, key)){
193 gtk_signal_emit_stop_by_name (GTK_OBJECT (win), "key_press_event");
194 return TRUE;
195 } else
196 return FALSE;
199 void
200 bind_gtk_keys (GtkWidget *w, Dlg_head *h)
202 gtk_signal_connect (GTK_OBJECT (w),
203 "key_press_event",
204 GTK_SIGNAL_FUNC (dialog_key_pressed),
208 widget_data
209 xtoolkit_create_dialog (Dlg_head *h, int flags)
211 GtkWidget *win;
213 if (!(flags & DLG_NO_TOPLEVEL)){
214 if (flags & DLG_GNOME_APP)
215 win = gnome_app_new ("mc", h->name);
216 else {
217 win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
218 gtk_window_set_position (GTK_WINDOW (win), GTK_WIN_POS_MOUSE);
219 #ifdef HAVE_GNOME_WINDOW_ICON
220 gnome_window_icon_set_from_default (GTK_WINDOW (win));
221 #endif
223 } else
224 win = 0;
226 h->grided = flags;
227 h->idle_fn_tag = -1;
228 if (!(flags & DLG_NO_TED)){
229 g_warning ("Should never use GtkTed!!! Write a real dialog!!!");
230 g_assert_not_reached ();
232 if (win){
233 bind_gtk_keys (GTK_WIDGET (win), h);
235 return (widget_data) win;
238 /* Used to bind a window for an already created Dlg_head. This is
239 * used together with the DLG_NO_TOPLEVEL: the dialog is created
240 * with the DLG_NO_TOPLEVEL and later, when the window is created
241 * it is assigned with this routine
243 void
244 x_dlg_set_window (Dlg_head *h, GtkWidget *win)
246 h->wdata = (widget_data) win;
247 bind_gtk_keys (GTK_WIDGET (win), h);
250 void
251 x_set_dialog_title (Dlg_head *h, const char *title)
253 gtk_window_set_title (GTK_WINDOW (h->wdata), title);
256 widget_data
257 xtoolkit_get_main_dialog (Dlg_head *h)
259 GtkWidget *win;
261 win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
262 #ifdef HAVE_GNOME_WINDOW_ICON
263 gnome_window_icon_set_from_default (GTK_WINDOW (win));
264 #endif
265 return (widget_data) win;
268 /* Creates the containers */
269 widget_data
270 x_create_panel_container (int which)
272 GtkWidget *win;
274 win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
275 #ifdef HAVE_GNOME_WINDOW_ICON
276 gnome_window_icon_set_from_default (GTK_WINDOW (win));
277 #endif
278 return (widget_data) 0;
281 void
282 x_panel_container_show (widget_data wdata)
284 gtk_widget_show (GTK_WIDGET (wdata));
287 void
288 x_add_widget (Dlg_head *h, Widget_Item *w)
290 if (!(h->grided & DLG_NO_TED)){
291 GtkTed *ted = GTK_TED (GTK_BIN (h->wdata)->child);
293 g_warning ("Should never use GtkTed!!! Write a real dialog!!!");
295 gtk_ted_add (ted, GTK_WIDGET (w->widget->wdata), w->widget->tkname);
296 bind_gtk_keys (GTK_WIDGET (w->widget->wdata), h);
300 static int
301 gnome_dlg_send_destroy (GtkWidget *widget, GdkEvent *event, Dlg_head *h)
303 gtk_widget_hide (GTK_WIDGET (h->wdata));
304 h->ret_value = B_CANCEL;
305 dlg_stop (h);
306 return TRUE;
309 void
310 x_init_dlg (Dlg_head *h)
312 if (!(h->grided & DLG_NO_TED)){
313 GtkTed *ted = GTK_TED (GTK_BIN (h->wdata)->child);
314 Widget_Item *p, *first;
316 g_warning ("Should never use GtkTed!!! Write a real dialog!!!");
318 first = p = h->current;
319 do {
320 gtk_ted_add (ted, GTK_WIDGET (p->widget->wdata), p->widget->tkname);
321 bind_gtk_keys (GTK_WIDGET (p->widget->wdata), h);
322 p = p->next;
323 } while (p != first);
324 gtk_ted_prepare (ted);
326 if (!ted->need_gui){
327 gtk_grab_add (GTK_WIDGET (ted));
328 gtk_window_set_policy (GTK_WINDOW (h->wdata), 0, 0, 0);
330 gtk_widget_show (GTK_WIDGET (h->wdata));
333 if (!(h->grided & DLG_GNOME_APP)) {
334 gtk_signal_connect (GTK_OBJECT ((void *)h->wdata), "delete_event",
335 GTK_SIGNAL_FUNC (gnome_dlg_send_destroy), h);
338 if (h->current)
339 x_focus_widget (h->current);
343 * This function is invoked when the dialog is started to be
344 * destroyed, before any widgets have been destroyed.
346 * We only hide the toplevel Gtk widget to avoid the flickering
347 * of the destruction process
349 void
350 x_destroy_dlg_start (Dlg_head *h)
352 gtk_widget_hide (GTK_WIDGET (h->wdata));
356 * Called when the Dlg_head has been destroyed. This only cleans
357 * up/releases the frontend resources
359 void
360 x_destroy_dlg (Dlg_head *h)
362 if (!(h->grided & DLG_NO_TED))
363 gtk_grab_remove (GTK_WIDGET (GTK_BIN (h->wdata)->child));
364 if (h->wdata){
365 gtk_widget_destroy (GTK_WIDGET(h->wdata));
366 h->wdata = 0;
370 void
371 gtkrundlg_event (Dlg_head *h)
373 gtk_main ();
376 void
377 edition_pre_exec ()
381 void
382 edition_post_exec ()
386 void
387 done_screen ()
391 void
392 setup_sigwinch ()
396 void
397 x_flush_events (void)
399 while (gtk_events_pending ())
400 gtk_main_iteration ();
403 static int
404 gnome_idle_handler (gpointer data)
406 Dlg_head *h = data;
408 if (h->send_idle_msg){
409 (*h->callback)(h, 0, DLG_IDLE);
410 return TRUE;
411 } else
412 return FALSE;
415 /* Turn on and off the idle message sending */
416 void
417 x_set_idle (Dlg_head *h, int enable_idle)
419 if (enable_idle){
420 if (h->idle_fn_tag != -1)
421 return;
422 h->idle_fn_tag = gtk_idle_add (gnome_idle_handler, h);
423 } else {
424 if (h->idle_fn_tag == -1)
425 return;
426 gtk_idle_remove (h->idle_fn_tag);
427 h->idle_fn_tag = -1;
428 gnome_idle_handler (h);
433 dialog_panel_callback (struct Dlg_head *h, int id, int msg)
435 Widget_Item *dh;
436 void *current_widget; /* The current widget */
438 if (msg == DLG_KEY && id == '\n'){
439 current_widget = (void *) h->current->widget;
441 if (is_a_panel (current_widget))
442 return 0;
444 dh = h->current;
445 do {
446 if (is_a_panel (dh->widget)){
447 WPanel *p = (WPanel *) dh->widget;
449 if (current_widget == p->current_dir){
450 WInput *in = p->current_dir;
452 do_panel_cd (p, in->buffer, cd_parse_command);
453 assign_text (in, p->cwd);
454 update_input (in, 1);
456 return MSG_HANDLED;
459 dh = dh->next;
460 } while (dh != h->current);
463 if (msg == DLG_UNHANDLED_KEY || msg == DLG_HOTKEY_HANDLED)
464 return midnight_callback (h, id, msg);
466 return 0;
469 /* Initializes the desktop and creates the initial panels. This is to be used
470 * when we do not have a CORBA server.
472 static void
473 non_corba_create_panels (char *startup_dir)
475 desktop_init ();
476 gnome_init_panels ();
478 the_hint = label_new (0, 0, 0, NULL);
479 desktop_dlg = create_dlg (0, 0, 24, 80, 0,
480 dialog_panel_callback, "[panel]", "midnight", DLG_NO_TED);
482 session_load ();
483 run_dlg (desktop_dlg);
484 desktop_destroy ();
487 /* The GNOME version of create_panels() */
488 void
489 create_panels (void)
491 corba_activate_server ();
493 if (!corba_have_server)
494 non_corba_create_panels (this_dir ? this_dir : ".");
495 else {
496 if (!nowindows)
497 corba_create_window (this_dir);
499 session_set_restart (FALSE);
503 void
504 gmc_do_quit (void)
506 /* FIXME: This wont get us out from a dialog box */
507 gtk_main_quit ();
508 quit = 1;
509 dlg_stop (desktop_dlg);
513 * Configures the GtkWindow/GnomeDialog from a WPanel.
515 * This makes the window centered on the screen and binds it to
516 * its parent container for better window manager experience
518 void
519 gmc_window_setup_from_panel (GnomeDialog *dialog, WPanel *panel)
521 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
522 if (panel && panel->xwindow) {
523 gnome_dialog_set_parent (dialog, GTK_WINDOW (panel->xwindow));
528 * gnome_check_super_user:
529 * @void:
531 * Puts out a warning if the user is running gmc as root. If the user selects
532 * Cancel, then gmc will terminate.
534 void
535 gnome_check_super_user (void)
537 GtkWidget *warning_dlg;
538 GtkWidget *cbox;
540 gboolean show_dialog;
542 if (geteuid () != 0)
543 return;
545 gnome_config_push_prefix( "/gmc/Root/");
546 show_dialog = gnome_config_get_bool ("show_dialog=true");
547 gnome_config_pop_prefix ();
548 if (!show_dialog)
549 return;
551 cbox = gtk_check_button_new_with_label (_("Don't show this window again"));
552 warning_dlg = gnome_message_box_new (
553 _("You are running the GNOME File Manager as root.\n\n"
554 "As root, you can damage your system, and the "
555 "File Manager will not stop you.\n"
556 "Your manual explains how to add a non-privileged user "
557 "account to the system.\n"),
558 GNOME_MESSAGE_BOX_WARNING,
559 GNOME_STOCK_BUTTON_OK, NULL);
560 gtk_widget_show (cbox);
561 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (warning_dlg)->vbox), cbox, FALSE, FALSE, 0);
562 gnome_dialog_close_hides (GNOME_DIALOG (warning_dlg), TRUE);
563 gnome_dialog_run_and_close (GNOME_DIALOG (warning_dlg));
564 if (GTK_TOGGLE_BUTTON (cbox)->active) {
565 gnome_config_push_prefix( "/gmc/Root/");
566 gnome_config_set_bool ("show_dialog", FALSE);
567 gnome_config_pop_prefix ();
569 gnome_config_sync ();
570 gtk_widget_destroy (warning_dlg);