gmain.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. /*
  2. * Midnight Commander -- GNOME frontend
  3. *
  4. * Copyright (C) 1997, 1998 The Free Software Foundation
  5. *
  6. * Author: Miguel de Icaza (miguel@gnu.org)
  7. *
  8. */
  9. #include <config.h>
  10. #include <stdarg.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #define WANT_WIDGETS
  14. #include "tty.h" /* for KEY_BACKSPACE */
  15. #include "x.h"
  16. #include "main.h"
  17. #include "key.h"
  18. #include "global.h"
  19. #include "dir.h"
  20. #include "panel.h"
  21. #include "gscreen.h"
  22. #include "command.h"
  23. #include "cmd.h"
  24. #include "gdesktop.h"
  25. GdkColorContext *mc_cc;
  26. #define MAX_COLOR_PAIRS 32
  27. struct gmc_color_pairs_s gmc_color_pairs [MAX_COLOR_PAIRS];
  28. char *default_edition_colors =
  29. "normal=black:"
  30. "selected=white,darkblue:"
  31. "viewunderline=brightred,blue:"
  32. "directory=blue:"
  33. "markselect=yellow,darkblue:"
  34. "marked=yellow,seagreen:"
  35. "execute=slateblue:"
  36. "link=green:"
  37. "device=magenta:"
  38. "core=red:"
  39. "menuhotsel=cyan,black:"
  40. "errors=white,red:"
  41. "reverse=black,lightcyan:"
  42. "special=black";
  43. int dialog_panel_callback (struct Dlg_head *h, int id, int msg);
  44. /* The Dlg_head for the whole desktop */
  45. Dlg_head *desktop_dlg;
  46. /* This is only used by the editor, so we provide a dummy implementation */
  47. void
  48. try_alloc_color_pair (char *str, char *str2)
  49. {
  50. }
  51. void
  52. init_pair (int index, GdkColor *fore, GdkColor *back)
  53. {
  54. if (index < 0 || index > MAX_COLOR_PAIRS){
  55. printf ("init_pair called with invalid index\n");
  56. exit (1);
  57. }
  58. gmc_color_pairs [index].fore = fore;
  59. gmc_color_pairs [index].back = back;
  60. }
  61. void
  62. get_color (char *cpp, GdkColor **colp)
  63. {
  64. GdkColor *new_color;
  65. gint status;
  66. new_color = g_new (GdkColor, 1);
  67. gdk_color_parse (cpp, new_color);
  68. new_color->pixel = 0;
  69. status = 0;
  70. gdk_color_context_get_pixels (mc_cc, &new_color->red, &new_color->green, &new_color->blue, 1,
  71. &new_color->pixel, &status);
  72. *colp = new_color;
  73. }
  74. static void
  75. gmc_color_init (void)
  76. {
  77. mc_cc = gdk_color_context_new (gtk_widget_get_default_visual (),
  78. gtk_widget_get_default_colormap ());
  79. }
  80. int
  81. xtoolkit_init (int *argc, char *argv [])
  82. {
  83. LINES = 40;
  84. COLS = 80;
  85. printf (
  86. "The GNOME file manager is going trough a massive code\n"
  87. "rewrite, so many problems are known to exist due to a major\n"
  88. "code design shift.\n\n"
  89. "Yes, we know there are lots of problems in the current code\n"
  90. "so dont even report them, when the major design has finished\n"
  91. "I will remove this notice\n");
  92. gmc_color_init ();
  93. return 0;
  94. }
  95. int
  96. xtoolkit_end (void)
  97. {
  98. return 1;
  99. }
  100. /*
  101. * Keystroke event handler for all of the Gtk widgets created by
  102. * the GNOME Midnight Commander. A special case is handled at
  103. * the top
  104. */
  105. int
  106. dialog_key_pressed (GtkWidget *win, GdkEventKey *event, Dlg_head *h)
  107. {
  108. GtkWidget *w;
  109. static int on_escape;
  110. int key;
  111. /*
  112. * Find out if the focused widget is an IconList and
  113. * if so, check if it has a currently focused item is
  114. * on editing mode as we do not want to handle key
  115. * events while the icon name is being edited.
  116. */
  117. w = win;
  118. while (w && (GTK_IS_CONTAINER (w) && !GNOME_IS_ICON_LIST (w)))
  119. w = GTK_CONTAINER (w)->focus_child;
  120. if (w && GNOME_IS_ICON_LIST (w)){
  121. GnomeCanvas *c = GNOME_CANVAS (w);
  122. if (c->focused_item && GNOME_IS_ICON_TEXT_ITEM (c->focused_item)){
  123. GnomeIconTextItem *i = GNOME_ICON_TEXT_ITEM (c->focused_item);
  124. if (i->editing)
  125. return FALSE;
  126. }
  127. }
  128. key = translate_gdk_keysym_to_curses (event);
  129. if (key == -1)
  130. return FALSE;
  131. if (!on_escape){
  132. if (key == 27){
  133. on_escape = 1;
  134. gtk_signal_emit_stop_by_name (GTK_OBJECT (win), "key_press_event");
  135. return TRUE;
  136. }
  137. } else {
  138. if (key != 27){
  139. if (key >= '0' && key <= '9')
  140. key = KEY_F(key - '0');
  141. else
  142. key = ALT (key);
  143. if (key == ALT('<'))
  144. key = KEY_HOME;
  145. if (key == ALT('>'))
  146. key = KEY_END;
  147. }
  148. on_escape = 0;
  149. }
  150. if (dlg_key_event (h, key)){
  151. gtk_signal_emit_stop_by_name (GTK_OBJECT (win), "key_press_event");
  152. return TRUE;
  153. } else
  154. return FALSE;
  155. }
  156. void
  157. bind_gtk_keys (GtkWidget *w, Dlg_head *h)
  158. {
  159. gtk_signal_connect (GTK_OBJECT (w),
  160. "key_press_event",
  161. GTK_SIGNAL_FUNC (dialog_key_pressed),
  162. h);
  163. }
  164. widget_data
  165. xtoolkit_create_dialog (Dlg_head *h, int flags)
  166. {
  167. GtkWidget *win, *ted;
  168. if (!(flags & DLG_NO_TOPLEVEL)){
  169. if (flags & DLG_GNOME_APP)
  170. win = gnome_app_new ("mc", h->name);
  171. else {
  172. win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  173. gtk_window_position (GTK_WINDOW (win), GTK_WIN_POS_MOUSE);
  174. }
  175. } else
  176. win = 0;
  177. h->grided = flags;
  178. h->idle_fn_tag = -1;
  179. if (!(flags & DLG_NO_TED)){
  180. ted = gtk_ted_new_layout (h->name, LIBDIR "/layout");
  181. gtk_container_add (GTK_CONTAINER (win), ted);
  182. gtk_widget_show (ted);
  183. bind_gtk_keys (GTK_WIDGET (ted), h);
  184. }
  185. if (win){
  186. bind_gtk_keys (GTK_WIDGET (win), h);
  187. }
  188. return (widget_data) win;
  189. }
  190. /* Used to bind a window for an already created Dlg_head. This is
  191. * used together with the DLG_NO_TOPLEVEL: the dialog is created
  192. * with the DLG_NO_TOPLEVEL and later, when the window is created
  193. * it is assigned with this routine
  194. */
  195. void
  196. x_dlg_set_window (Dlg_head *h, GtkWidget *win)
  197. {
  198. h->wdata = (widget_data) win;
  199. bind_gtk_keys (GTK_WIDGET (win), h);
  200. }
  201. void
  202. x_set_dialog_title (Dlg_head *h, char *title)
  203. {
  204. gtk_window_set_title (GTK_WINDOW (h->wdata), title);
  205. }
  206. widget_data
  207. xtoolkit_get_main_dialog (Dlg_head *h)
  208. {
  209. GtkWidget *win;
  210. win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  211. return (widget_data) win;
  212. }
  213. /* Creates the containers */
  214. widget_data
  215. x_create_panel_container (int which)
  216. {
  217. GtkWidget *win;
  218. win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  219. return (widget_data) 0;
  220. }
  221. void
  222. x_panel_container_show (widget_data wdata)
  223. {
  224. gtk_widget_show (GTK_WIDGET (wdata));
  225. }
  226. void
  227. x_add_widget (Dlg_head *h, Widget_Item *w)
  228. {
  229. if (!(h->grided & DLG_NO_TED)){
  230. GtkTed *ted = GTK_TED (GTK_BIN (h->wdata)->child);
  231. gtk_ted_add (ted, GTK_WIDGET (w->widget->wdata), w->widget->tkname);
  232. bind_gtk_keys (GTK_WIDGET (w->widget->wdata), h);
  233. }
  234. }
  235. static int
  236. gnome_dlg_send_destroy (GtkWidget *widget, GdkEvent *event, Dlg_head *h)
  237. {
  238. gtk_widget_hide (GTK_WIDGET (h->wdata));
  239. h->ret_value = B_CANCEL;
  240. dlg_stop (h);
  241. return TRUE;
  242. }
  243. void
  244. x_init_dlg (Dlg_head *h)
  245. {
  246. if (!(h->grided & DLG_NO_TED)){
  247. GtkTed *ted = GTK_TED (GTK_BIN (h->wdata)->child);
  248. Widget_Item *p, *first;
  249. first = p = h->current;
  250. do {
  251. gtk_ted_add (ted, GTK_WIDGET (p->widget->wdata), p->widget->tkname);
  252. bind_gtk_keys (GTK_WIDGET (p->widget->wdata), h);
  253. p = p->next;
  254. } while (p != first);
  255. gtk_ted_prepare (ted);
  256. if (!ted->need_gui){
  257. gtk_grab_add (GTK_WIDGET (ted));
  258. gtk_window_set_policy (GTK_WINDOW (h->wdata), 0, 0, 0);
  259. }
  260. gtk_widget_show (GTK_WIDGET (h->wdata));
  261. }
  262. gtk_signal_connect (GTK_OBJECT (h->wdata), "delete_event",
  263. GTK_SIGNAL_FUNC (gnome_dlg_send_destroy), h);
  264. x_focus_widget (h->current);
  265. }
  266. /*
  267. * This function is invoked when the dialog is started to be
  268. * destroyed, before any widgets have been destroyed.
  269. *
  270. * We only hide the toplevel Gtk widget to avoid the flickering
  271. * of the destruction process
  272. */
  273. void
  274. x_destroy_dlg_start (Dlg_head *h)
  275. {
  276. gtk_widget_hide (GTK_WIDGET (h->wdata));
  277. }
  278. /*
  279. * Called when the Dlg_head has been destroyed. This only cleans
  280. * up/releases the frontend resources
  281. */
  282. void
  283. x_destroy_dlg (Dlg_head *h)
  284. {
  285. if (!(h->grided & DLG_NO_TED))
  286. gtk_grab_remove (GTK_WIDGET (GTK_BIN (h->wdata)->child));
  287. if (h->wdata){
  288. gtk_widget_destroy (GTK_WIDGET(h->wdata));
  289. h->wdata = 0;
  290. }
  291. }
  292. void
  293. gtkrundlg_event (Dlg_head *h)
  294. {
  295. gtk_main ();
  296. }
  297. void
  298. edition_pre_exec ()
  299. {
  300. }
  301. void
  302. edition_post_exec ()
  303. {
  304. }
  305. void
  306. done_screen ()
  307. {
  308. }
  309. void
  310. setup_sigwinch ()
  311. {
  312. }
  313. void
  314. x_flush_events (void)
  315. {
  316. while (gtk_events_pending ())
  317. gtk_main_iteration ();
  318. }
  319. static int
  320. gnome_idle_handler (gpointer data)
  321. {
  322. Dlg_head *h = data;
  323. if (h->send_idle_msg){
  324. (*h->callback)(h, 0, DLG_IDLE);
  325. return TRUE;
  326. } else
  327. return FALSE;
  328. }
  329. /* Turn on and off the idle message sending */
  330. void
  331. x_set_idle (Dlg_head *h, int enable_idle)
  332. {
  333. if (enable_idle){
  334. if (h->idle_fn_tag != -1)
  335. return;
  336. h->idle_fn_tag = gtk_idle_add (gnome_idle_handler, h);
  337. } else {
  338. if (h->idle_fn_tag == -1)
  339. return;
  340. gtk_idle_remove (h->idle_fn_tag);
  341. h->idle_fn_tag = -1;
  342. gnome_idle_handler (h);
  343. }
  344. }
  345. int
  346. dialog_panel_callback (struct Dlg_head *h, int id, int msg)
  347. {
  348. WPanel *p;
  349. WInput *in;
  350. Widget_Item *dh;
  351. void *current_widget; /* The current widget */
  352. if (msg == DLG_KEY && id == '\n'){
  353. current_widget = (void *) h->current->widget;
  354. if (is_a_panel (current_widget))
  355. return 0;
  356. dh = h->current;
  357. do {
  358. if (is_a_panel (dh->widget)){
  359. WPanel *p = (WPanel *) dh->widget;
  360. if (current_widget == p->filter_w){
  361. in = (WInput *) current_widget;
  362. set_panel_filter_to (p, strdup (in->buffer));
  363. return MSG_HANDLED;
  364. }
  365. if (current_widget == p->current_dir){
  366. WInput *in = p->current_dir;
  367. do_panel_cd (p, in->buffer, cd_parse_command);
  368. assign_text (in, p->cwd);
  369. update_input (in, 1);
  370. return MSG_HANDLED;
  371. }
  372. }
  373. dh = dh->next;
  374. } while (dh != h->current);
  375. }
  376. if (msg == DLG_UNHANDLED_KEY || msg == DLG_HOTKEY_HANDLED)
  377. return midnight_callback (h, id, msg);
  378. return 0;
  379. }
  380. extern char *cmdline_geometry;
  381. typedef struct {
  382. char *dir; char *geometry;
  383. } dir_and_geometry;
  384. static int
  385. idle_create_panel (void *data)
  386. {
  387. dir_and_geometry *dg = data;
  388. new_panel_with_geometry_at (dg->dir, dg->geometry);
  389. g_free (data);
  390. return 0;
  391. }
  392. static int
  393. idle_destroy_window (void *data)
  394. {
  395. WPanel *panel = data;
  396. gnome_close_panel (GTK_WIDGET (panel->widget.wdata), panel);
  397. return 0;
  398. }
  399. /*
  400. * wrapper for new_panel_with_geometry_at.
  401. * first invocation is called directly, further calls use
  402. * the idle handler
  403. */
  404. static WPanel *
  405. create_one_panel (char *dir, char *geometry)
  406. {
  407. static int first = 1;
  408. if (first){
  409. first = 0;
  410. return new_panel_with_geometry_at (dir, geometry);
  411. } else {
  412. dir_and_geometry *dg = g_new (dir_and_geometry, 1);
  413. dg->dir = dir;
  414. dg->geometry = geometry;
  415. gtk_idle_add (idle_create_panel, dg);
  416. return NULL;
  417. }
  418. }
  419. /*
  420. * Only at startup we have a strange condition: if more than one
  421. * panel is created, then the code hangs inside X, it keeps waiting
  422. * for a reply for something in Imlib that never returns.
  423. *
  424. * Creating the panels on the idle loop takes care of this
  425. */
  426. void
  427. create_panels (void)
  428. {
  429. GList *p, *g;
  430. char *geo;
  431. WPanel *panel;
  432. #if 1
  433. desktop_init ();
  434. #else
  435. start_desktop ();
  436. #endif
  437. cmdline = command_new (0, 0, 0);
  438. the_hint = label_new (0, 0, 0, NULL);
  439. gnome_init_panels ();
  440. desktop_dlg = create_dlg (0, 0, 24, 80, 0, dialog_panel_callback, "[panel]", "midnight", DLG_NO_TED);
  441. #if 0
  442. if (directory_list){
  443. for (p = directory_list; p; p = p->next){
  444. create_one_panel (p->data, cmdline_geometry);
  445. }
  446. panel = NULL;
  447. } else
  448. #endif
  449. {
  450. panel = create_one_panel (".", cmdline_geometry);
  451. if (nowindows){
  452. gtk_idle_add (idle_destroy_window, panel);
  453. panel->widget.options |= W_PANEL_HIDDEN;
  454. }
  455. }
  456. #if 0
  457. g_list_free (directory_list);
  458. #endif
  459. run_dlg (desktop_dlg);
  460. /* shutdown gnome specific bits of midnight commander */
  461. #if 1
  462. desktop_destroy ();
  463. #else
  464. stop_desktop ();
  465. #endif
  466. }
  467. static void
  468. session_die (void)
  469. {
  470. extern int quit;
  471. /* FIXME: This wont get us out from a dialog box */
  472. gtk_main_quit ();
  473. quit = 1;
  474. dlg_stop (desktop_dlg);
  475. }
  476. /*
  477. * Save the session callback
  478. */
  479. static int
  480. session_save_state (GnomeClient *client, gint phase, GnomeRestartStyle save_style, gint shutdown,
  481. GnomeInteractStyle interact_style, gint fast, gpointer client_data)
  482. {
  483. char *sess_id;
  484. char **argv = g_malloc (sizeof (char *) * ((g_list_length (containers) * 3) + 2));
  485. GList *l, *free_list = 0;
  486. int i;
  487. sess_id = gnome_client_get_id (client);
  488. argv [0] = client_data;
  489. for (i = 1, l = containers; l; l = l->next){
  490. PanelContainer *pc = l->data;
  491. int x, y, w, h;
  492. char *buffer = g_malloc (32);
  493. gdk_window_get_origin (GTK_WIDGET (pc->panel->widget.wdata)->window, &x, &y);
  494. gdk_window_get_size (GTK_WIDGET (pc->panel->widget.wdata)->window, &w, &h);
  495. sprintf (buffer, "%dx%d+%d+%d", w, h, x, y);
  496. argv [i++] = pc->panel->cwd;
  497. argv [i++] = "--geometry";
  498. argv [i++] = buffer;
  499. free_list = g_list_append (free_list, buffer);
  500. }
  501. /* If no windows were open */
  502. if (i == 1){
  503. argv [i++] = "--nowindows";
  504. }
  505. argv [i] = NULL;
  506. gnome_client_set_clone_command (client, i, argv);
  507. gnome_client_set_restart_command (client, i, argv);
  508. for (l = free_list; l; l = l->next)
  509. g_free (l->data);
  510. g_list_free (free_list);
  511. g_free (argv);
  512. if (shutdown){
  513. quit = 1;
  514. dlg_stop (midnight_dlg);
  515. }
  516. return 1;
  517. }
  518. void
  519. session_management_setup (char *name)
  520. {
  521. GnomeClient *client;
  522. client = gnome_master_client ();
  523. if (client){
  524. gtk_signal_connect (GTK_OBJECT (client), "save_yourself",
  525. GTK_SIGNAL_FUNC (session_save_state), name);
  526. gtk_signal_connect (GTK_OBJECT (client), "die",
  527. GTK_SIGNAL_FUNC (session_die), NULL);
  528. }
  529. }