glayout.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. /*
  2. * Layout routines for the GNOME edition of the GNU Midnight Commander
  3. *
  4. * (C) 1998 the Free Software Foundation
  5. *
  6. * Author: Miguel de Icaza (miguel@kernel.org)
  7. */
  8. #include <config.h>
  9. #include "x.h"
  10. #include <stdio.h>
  11. #include <sys/stat.h>
  12. #include <unistd.h>
  13. #include "global.h"
  14. #include "dir.h"
  15. #include "panel.h"
  16. #include "gscreen.h"
  17. #include "main.h"
  18. #include "gmain.h"
  19. #include "cmd.h"
  20. #include "dialog.h"
  21. #include "boxes.h"
  22. #include "panelize.h"
  23. #include "gcmd.h"
  24. #include "gcliplabel.h"
  25. #include "gdesktop.h"
  26. #include "setup.h"
  27. #include "../vfs/vfs.h"
  28. #include "gprefs.h"
  29. #include "gsession.h"
  30. #include "listing-iconic.xpm"
  31. #include "listing-brief-list.xpm"
  32. #include "listing-list.xpm"
  33. #include "listing-custom.xpm"
  34. #define UNDEFINED_INDEX -1
  35. /* Keep these two arrays in sync! */
  36. GnomeUIInfo panel_view_menu_uiinfo[] = {
  37. GNOMEUIINFO_RADIOITEM (N_("_Icon View"),
  38. N_("Switch view to an icon display"),
  39. gnome_icon_view_cmd, NULL),
  40. GNOMEUIINFO_RADIOITEM (N_("_Brief View"),
  41. N_("Switch view to show just file name and type"),
  42. gnome_brief_view_cmd, NULL),
  43. GNOMEUIINFO_RADIOITEM (N_("_Detailed View"),
  44. N_("Switch view to show detailed file statistics"),
  45. gnome_detailed_view_cmd, NULL),
  46. GNOMEUIINFO_RADIOITEM (N_("_Custom View"),
  47. N_("Switch view to show user-defined statistics"),
  48. gnome_custom_view_cmd, NULL),
  49. GNOMEUIINFO_END
  50. };
  51. GnomeUIInfo panel_view_toolbar_uiinfo[] = {
  52. GNOMEUIINFO_RADIOITEM (N_("Icons"),
  53. N_("Switch view to an icon display"),
  54. gnome_icon_view_cmd, listing_iconic_xpm),
  55. GNOMEUIINFO_RADIOITEM (N_("Brief"),
  56. N_("Switch view to show just file name and type"),
  57. gnome_brief_view_cmd, listing_brief_list_xpm),
  58. GNOMEUIINFO_RADIOITEM (N_("Detailed"),
  59. N_("Switch view to show detailed file statistics"),
  60. gnome_detailed_view_cmd, listing_list_xpm),
  61. GNOMEUIINFO_RADIOITEM (N_("Custom"),
  62. N_("Switch view to show user-defined statistics"),
  63. gnome_custom_view_cmd, listing_custom_xpm),
  64. GNOMEUIINFO_END
  65. };
  66. GList *containers = 0;
  67. int output_lines = 0;
  68. int command_prompt = 1;
  69. int keybar_visible = 1;
  70. int message_visible = 1;
  71. int xterm_hintbar = 0;
  72. PanelContainer *current_panel_ptr, *other_panel_ptr;
  73. WPanel *
  74. get_current_panel (void)
  75. {
  76. if (current_panel_ptr)
  77. return current_panel_ptr->panel;
  78. else
  79. return NULL;
  80. }
  81. WPanel *
  82. get_other_panel (void)
  83. {
  84. if (other_panel_ptr)
  85. return other_panel_ptr->panel;
  86. else
  87. return NULL;
  88. }
  89. /* FIXME: we probably want to get rid of this code */
  90. int
  91. get_current_index (void)
  92. {
  93. GList *p;
  94. int i;
  95. for (i = 0, p = containers; p; p = p->next, i++){
  96. if (p->data == current_panel_ptr)
  97. return i;
  98. }
  99. printf ("FATAL: current panel is not in the list\n");
  100. g_assert_not_reached ();
  101. return -1; /* keep -Wall happy */
  102. }
  103. int
  104. get_other_index (void)
  105. {
  106. GList *p;
  107. int i;
  108. for (i = 0, p = containers; p; p = p->next, i++){
  109. if (p->data == other_panel_ptr)
  110. return i;
  111. }
  112. return UNDEFINED_INDEX;
  113. }
  114. void
  115. set_current_panel (WPanel *panel)
  116. {
  117. GList *p;
  118. if (g_list_length (containers) > 1)
  119. other_panel_ptr = current_panel_ptr;
  120. for (p = containers; p; p = p->next){
  121. if (((PanelContainer *)p->data)->panel == panel){
  122. current_panel_ptr = p->data;
  123. break;
  124. }
  125. }
  126. }
  127. /*
  128. * Tries to assign other_panel (ie, if there is anything to assign to
  129. */
  130. static void
  131. assign_other (void)
  132. {
  133. GList *p;
  134. other_panel_ptr = NULL;
  135. for (p = containers; p; p = p->next)
  136. if (p->data != current_panel_ptr){
  137. other_panel_ptr = p->data;
  138. break;
  139. }
  140. }
  141. /*
  142. * This keeps track of the current_panel_ptr and other_panel_ptr as
  143. * well as the list of active containers
  144. */
  145. void
  146. layout_panel_gone (WPanel *panel)
  147. {
  148. PanelContainer *pc_holder = 0;
  149. int len = g_list_length (containers);
  150. GList *p;
  151. for (p = containers; p; p = p->next){
  152. PanelContainer *pc = p->data;
  153. if (pc->panel == panel){
  154. pc_holder = pc;
  155. break;
  156. }
  157. }
  158. if (len > 1){
  159. containers = g_list_remove (containers, pc_holder);
  160. }
  161. /* Check if this is not the current panel */
  162. if (current_panel_ptr->panel == panel){
  163. if (other_panel_ptr){
  164. current_panel_ptr = other_panel_ptr;
  165. assign_other ();
  166. } else {
  167. current_panel_ptr = NULL;
  168. }
  169. } else if (other_panel_ptr->panel == panel){
  170. /* Check if it was the other panel */
  171. if (len == 1){
  172. other_panel_ptr = 0;
  173. } else
  174. assign_other ();
  175. } else {
  176. }
  177. if (len == 1){
  178. g_free (containers->data);
  179. g_list_free (containers);
  180. containers = NULL;
  181. } else
  182. g_free (pc_holder);
  183. }
  184. void
  185. set_hintbar (char *str)
  186. {
  187. /*gtk_label_set (GTK_LABEL (current_panel_ptr->panel->status), str);*/
  188. /* x_flush_events (); */
  189. }
  190. void
  191. print_vfs_message (char *msg, ...)
  192. {
  193. va_list ap;
  194. char str [256];
  195. va_start(ap, msg);
  196. vsprintf(str, msg, ap);
  197. va_end(ap);
  198. if (midnight_shutdown)
  199. return;
  200. set_hintbar(str);
  201. }
  202. void
  203. rotate_dash (void)
  204. {
  205. }
  206. int
  207. get_current_type (void)
  208. {
  209. return view_listing;
  210. }
  211. int
  212. get_other_type (void)
  213. {
  214. return other_panel_ptr ? view_listing : view_nothing;
  215. }
  216. int
  217. get_display_type (int index)
  218. {
  219. GList *p;
  220. if (index == UNDEFINED_INDEX)
  221. return -1;
  222. p = g_list_nth (containers, index);
  223. if (p)
  224. return ((PanelContainer *)p->data)->panel->list_type;
  225. else
  226. return -1;
  227. }
  228. void
  229. use_dash (int ignore)
  230. {
  231. /* we dont care in the gnome edition */
  232. }
  233. Widget *
  234. get_panel_widget (int index)
  235. {
  236. GList *p;
  237. for (p = containers; index; p = p->next)
  238. index--;
  239. return (Widget *) ((PanelContainer *)p->data)->panel;
  240. }
  241. /* FIXME: This routine is wrong. It should follow what the original save_panel_types
  242. * does. I can not remember which problem the original routine was trying to address
  243. * when I did the "New {Left|Rigth} Panel" sections.
  244. */
  245. void
  246. save_panel_types (void)
  247. {
  248. GList *p;
  249. for (p = containers; p; p = p->next){
  250. PanelContainer *pc = p->data;
  251. if (!is_a_desktop_panel (pc->panel))
  252. panel_save_setup (pc->panel, pc->panel->panel_name);
  253. }
  254. }
  255. static void
  256. run_cmd (void)
  257. {
  258. char *cmd = _("Enter command to run");
  259. cmd = input_dialog (cmd, cmd, "");
  260. if (cmd){
  261. if (*cmd){
  262. my_system (EXECUTE_AS_SHELL, shell, cmd);
  263. }
  264. g_free (cmd);
  265. }
  266. }
  267. static void
  268. gnome_exit (void)
  269. {
  270. GtkWidget *w;
  271. int v;
  272. w = gnome_message_box_new (
  273. _("Notice that if you choose to terminate the file manager, you will\n"
  274. "also terminate the GNOME desktop handler.\n\n"
  275. "Are you sure you want to exit?"),
  276. GNOME_MESSAGE_BOX_WARNING,
  277. GNOME_STOCK_BUTTON_YES,
  278. GNOME_STOCK_BUTTON_NO,
  279. NULL);
  280. v = gnome_dialog_run (GNOME_DIALOG (w));
  281. if (v != 0)
  282. return;
  283. w = gnome_message_box_new (
  284. _("The file manager and the desktop handler are now terminating\n\n"
  285. "If you want to start up again the desktop handler or the file manager\n"
  286. "you can launch it from the Panel, or you can run the UNIX command `gmc'\n\n"
  287. "Press OK to terminate the application, or cancel to continue using it."),
  288. GNOME_MESSAGE_BOX_INFO,
  289. GNOME_STOCK_BUTTON_OK,
  290. GNOME_STOCK_BUTTON_CANCEL,
  291. NULL);
  292. v = gnome_dialog_run (GNOME_DIALOG (w));
  293. if (v == 0) {
  294. /*
  295. * We do not want to be restarted by the session manager now
  296. */
  297. session_set_restart (FALSE);
  298. gmc_do_quit ();
  299. }
  300. }
  301. static void
  302. do_rescan_desktop (void)
  303. {
  304. desktop_reload_icons (FALSE, 0, 0);
  305. }
  306. static void
  307. gnome_launch_mime_editor (void)
  308. {
  309. my_system (EXECUTE_AS_SHELL, shell, "mime-type-capplet");
  310. }
  311. void configure_box (void);
  312. GtkCheckMenuItem *gnome_toggle_snap (void);
  313. static GnomeUIInfo gnome_panel_new_menu [] = {
  314. GNOMEUIINFO_ITEM_NONE(N_("_Terminal"),
  315. N_("Launch a new terminal in the current directory"), gnome_open_terminal),
  316. /* If this ever changes, make sure you update create_new_menu accordingly. */
  317. GNOMEUIINFO_ITEM_NONE(N_("_Directory..."),
  318. N_("Creates a new directory"), gnome_mkdir_cmd),
  319. GNOMEUIINFO_ITEM_NONE(N_("_File..."),
  320. N_("Creates a new file in this directory"), gnome_newfile_cmd),
  321. GNOMEUIINFO_END
  322. };
  323. GnomeUIInfo gnome_panel_file_menu [] = {
  324. GNOMEUIINFO_MENU_NEW_WINDOW_ITEM(gnome_open_panel, NULL),
  325. /*GNOMEUIINFO_MENU_NEW_ITEM(N_("New _Window"), N_("Opens a new window"), gnome_open_panel, NULL),*/
  326. /* We want to make a new menu entry here... */
  327. /* For example: */
  328. /* New-> */
  329. /* Command Prompt */
  330. /* Gimp Image */
  331. /* Gnumeric Spreadsheet */
  332. /* Text Document */
  333. /* etc... */
  334. GNOMEUIINFO_MENU_NEW_SUBTREE(gnome_panel_new_menu),
  335. GNOMEUIINFO_SEPARATOR,
  336. GNOMEUIINFO_MENU_OPEN_ITEM(gnome_open_files, NULL),
  337. /* GNOMEUIINFO_ITEM_NONE(N_("Open _FTP site"), N_("Opens an FTP site"), ftplink_cmd },*/
  338. GNOMEUIINFO_ITEM_STOCK(N_("_Copy..."), N_("Copy files"), copy_cmd, GNOME_STOCK_PIXMAP_COPY),
  339. GNOMEUIINFO_ITEM_STOCK(N_("_Delete..."), N_("Delete files"), delete_cmd, GNOME_STOCK_PIXMAP_TRASH),
  340. GNOMEUIINFO_ITEM_NONE(N_("_Move..."), N_("Rename or move files"), ren_cmd),
  341. GNOMEUIINFO_SEPARATOR,
  342. GNOMEUIINFO_ITEM_NONE(N_("Show directory sizes"), N_("Shows the disk space used by each directory"), dirsizes_cmd),
  343. GNOMEUIINFO_SEPARATOR,
  344. { GNOME_APP_UI_ITEM, N_("Close window"), N_("Closes this window"),
  345. gnome_close_panel, NULL, NULL, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_CLOSE,
  346. 'w', GDK_CONTROL_MASK, NULL },
  347. GNOMEUIINFO_END
  348. };
  349. GnomeUIInfo gnome_panel_edit_menu [] = {
  350. { GNOME_APP_UI_ITEM, N_("Select _All"), N_("Select all files in the current Panel"), gnome_select_all_cmd,
  351. NULL, NULL, 0, NULL, 'a', GDK_CONTROL_MASK },
  352. GNOMEUIINFO_ITEM_NONE(N_("_Select Files..."), N_("Select a group of files"), gnome_select),
  353. GNOMEUIINFO_ITEM_NONE(N_("_Invert Selection"), N_("Reverses the list of tagged files"),
  354. gnome_reverse_selection_cmd_panel),
  355. GNOMEUIINFO_SEPARATOR,
  356. { GNOME_APP_UI_ITEM, N_("Search"), N_("Search for a file in the current Panel"), gnome_start_search,
  357. NULL, NULL, 0, NULL, 's', GDK_CONTROL_MASK },
  358. GNOMEUIINFO_SEPARATOR,
  359. GNOMEUIINFO_ITEM_NONE(N_("_Rescan Directory"), N_("Rescan the directory contents"), reread_cmd),
  360. GNOMEUIINFO_END
  361. };
  362. GnomeUIInfo gnome_panel_settings_menu [] = {
  363. GNOMEUIINFO_MENU_PREFERENCES_ITEM(gnome_configure_box, NULL),
  364. GNOMEUIINFO_END
  365. };
  366. GnomeUIInfo gnome_panel_layout_menu [] = {
  367. GNOMEUIINFO_ITEM_NONE(N_("_Sort By..."), N_("Confirmation settings"), gnome_sort_cmd),
  368. GNOMEUIINFO_ITEM_NONE(N_("_Filter View..."), N_("Global option settings"), gnome_filter_cmd),
  369. GNOMEUIINFO_SEPARATOR,
  370. GNOMEUIINFO_RADIOLIST(panel_view_menu_uiinfo),
  371. GNOMEUIINFO_END
  372. };
  373. GnomeUIInfo gnome_panel_commands_menu [] = {
  374. GNOMEUIINFO_ITEM_STOCK(N_("_Find File..."), N_("Locate files on disk"), find_cmd, GNOME_STOCK_MENU_JUMP_TO),
  375. /* { GNOME_APP_UI_ITEM, N_("_Compare panels..."), N_("Compare two panel contents"), gnome_compare_panels },*/
  376. GNOMEUIINFO_ITEM_NONE(N_("_Edit mime types..."), N_("Edits the MIME type bindings"),
  377. gnome_launch_mime_editor),
  378. { GNOME_APP_UI_ITEM, N_("_Run Command..."), N_("Runs a command"), run_cmd, NULL,
  379. NULL, GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_OPEN, GDK_F2, 0 },
  380. GNOMEUIINFO_ITEM_NONE(N_("_Run Command in panel..."),N_("Run a command and put the results in a panel"), gnome_external_panelize),
  381. #ifdef USE_VFS
  382. /* GNOMEUIINFO_ITEM_NONE(N_("_Active VFS list..."),N_("List of active virtual file systems"), reselect_vfs), */
  383. #endif
  384. #ifdef USE_EXT2FSLIB
  385. /*does this do anything?*/
  386. /* GNOMEUIINFO_ITEM_NONE(N_("_Undelete files (ext2fs only)..."), N_("Recover deleted files"), undelete_cmd),*/
  387. #endif
  388. #ifdef WITH_BACKGROUND
  389. GNOMEUIINFO_ITEM_NONE(N_("_Background jobs..."), N_("List of background operations"), jobs_cmd),
  390. #endif
  391. GNOMEUIINFO_SEPARATOR,
  392. GNOMEUIINFO_ITEM_STOCK (N_("Exit"), N_("Terminates the file manager and the desktop"),
  393. gnome_exit, GNOME_STOCK_PIXMAP_QUIT),
  394. GNOMEUIINFO_END
  395. };
  396. GnomeUIInfo gnome_panel_about_menu [] = {
  397. GNOMEUIINFO_MENU_ABOUT_ITEM(gnome_about_cmd, NULL),
  398. GNOMEUIINFO_HELP ("gmc"),
  399. GNOMEUIINFO_END
  400. };
  401. GnomeUIInfo gnome_panel_desktop_menu [] = {
  402. GNOMEUIINFO_SUBTREE(N_("_Arrange Icons"), desktop_arrange_icons_items),
  403. GNOMEUIINFO_SEPARATOR,
  404. GNOMEUIINFO_ITEM_NONE (N_("Rescan _Desktop Directory"), NULL, do_rescan_desktop),
  405. GNOMEUIINFO_ITEM_NONE (N_("Rescan De_vices"), NULL, desktop_rescan_devices),
  406. GNOMEUIINFO_ITEM_NONE (N_("Recreate Default _Icons"), NULL, desktop_recreate_default_icons),
  407. GNOMEUIINFO_END
  408. };
  409. GnomeUIInfo gnome_panel_menu_with_desktop [] = {
  410. GNOMEUIINFO_MENU_FILE_TREE(gnome_panel_file_menu),
  411. GNOMEUIINFO_MENU_EDIT_TREE(gnome_panel_edit_menu),
  412. GNOMEUIINFO_SUBTREE(N_("_Settings"),gnome_panel_settings_menu),
  413. GNOMEUIINFO_SUBTREE(N_("_Layout"),gnome_panel_layout_menu),
  414. GNOMEUIINFO_SUBTREE(N_("_Commands"),gnome_panel_commands_menu),
  415. GNOMEUIINFO_SUBTREE(N_("_Desktop"), gnome_panel_desktop_menu),
  416. GNOMEUIINFO_SUBTREE(N_("_Help"), gnome_panel_about_menu),
  417. GNOMEUIINFO_END
  418. };
  419. GnomeUIInfo gnome_panel_menu_without_desktop [] = {
  420. GNOMEUIINFO_MENU_FILE_TREE(gnome_panel_file_menu),
  421. GNOMEUIINFO_MENU_EDIT_TREE(gnome_panel_edit_menu),
  422. GNOMEUIINFO_SUBTREE(N_("_Settings"),gnome_panel_settings_menu),
  423. GNOMEUIINFO_SUBTREE(N_("_Layout"),gnome_panel_layout_menu),
  424. GNOMEUIINFO_SUBTREE(N_("_Commands"),gnome_panel_commands_menu),
  425. GNOMEUIINFO_SUBTREE(N_("_Help"), gnome_panel_about_menu),
  426. GNOMEUIINFO_END
  427. };
  428. GtkCheckMenuItem *
  429. gnome_toggle_snap (void)
  430. {
  431. return NULL; /*GTK_CHECK_MENU_ITEM (gnome_panel_desktop_menu [1].widget);*/
  432. }
  433. void
  434. gnome_init_panels (void)
  435. {
  436. current_panel_ptr = NULL;
  437. other_panel_ptr = NULL;
  438. }
  439. static int
  440. gnome_close_panel_event (GtkWidget *widget, GdkEvent *event, WPanel *panel)
  441. {
  442. gnome_close_panel (widget, panel);
  443. return TRUE;
  444. }
  445. static void
  446. panel_enter_event (GtkWidget *widget, GdkEvent *event, WPanel *panel)
  447. {
  448. /* Avoid unnecessary code execution */
  449. if (get_current_panel () == panel)
  450. return;
  451. set_current_panel (panel);
  452. dlg_select_widget (panel->widget.parent, panel);
  453. send_message (panel->widget.parent, (Widget *) panel, WIDGET_FOCUS, 0);
  454. }
  455. void
  456. destroy_gde (GtkWidget *unused, void *data)
  457. {
  458. gnome_desktop_entry_free ((GnomeDesktopEntry *) (data));
  459. }
  460. gint
  461. create_new_menu_from (char *file, GtkWidget *shell, gint pos)
  462. {
  463. DIR *dir;
  464. struct stat filedata;
  465. gboolean add_separator = TRUE;
  466. struct dirent *dirstruc;
  467. GnomeDesktopEntry *gde;
  468. GtkWidget *menu;
  469. char *file2;
  470. g_return_val_if_fail (shell != NULL, pos);
  471. if (shell == NULL){
  472. return pos;
  473. }
  474. dir = opendir (file);
  475. if (dir == NULL)
  476. return pos;
  477. while ((dirstruc = readdir (dir)) != NULL){
  478. if (dirstruc->d_name[0] == '.')
  479. continue;
  480. file2 = g_concat_dir_and_file (file, dirstruc->d_name);
  481. if ((stat (file2, &filedata) != -1) && (S_ISREG (filedata.st_mode))){
  482. char *path;
  483. int len;
  484. const int desktoplen = sizeof (".desktop") - 1;
  485. len = strlen (dirstruc->d_name);
  486. if (strcmp (dirstruc->d_name + len - desktoplen, ".desktop") != 0) {
  487. g_free (file2);
  488. continue;
  489. }
  490. gde = gnome_desktop_entry_load (file2);
  491. if (gde == NULL) {
  492. g_free (file2);
  493. continue;
  494. }
  495. path = gnome_is_program_in_path (gde->tryexec);
  496. g_free (path);
  497. if (!path){
  498. gnome_desktop_entry_free (gde);
  499. g_free (file2);
  500. continue;
  501. }
  502. if (add_separator) {
  503. menu = gtk_menu_item_new ();
  504. gtk_widget_show (menu);
  505. gtk_menu_shell_insert (GTK_MENU_SHELL (shell), menu, pos++);
  506. add_separator = !add_separator;
  507. }
  508. menu = gtk_menu_item_new_with_label (gde->name);
  509. gtk_widget_show (menu);
  510. gtk_menu_shell_insert (GTK_MENU_SHELL (shell), menu, pos++);
  511. /* This is really bad, but it works. */
  512. /* FIXME: it doesn't work if we free the gde below. --
  513. * need to do this right sometime -jrb
  514. */
  515. if (gde->comment)
  516. gtk_object_set_data (GTK_OBJECT (menu),
  517. "apphelper_statusbar_hint",
  518. gde->comment);
  519. gtk_signal_connect (GTK_OBJECT (menu), "activate",
  520. GTK_SIGNAL_FUNC (gnome_run_new),
  521. gde);
  522. gtk_signal_connect (GTK_OBJECT (menu), "destroy",
  523. GTK_SIGNAL_FUNC (destroy_gde),
  524. gde);
  525. }
  526. g_free (file2);
  527. }
  528. closedir (dir);
  529. return pos;
  530. }
  531. /**
  532. * create_new_menu:
  533. *
  534. * Creates the child New menu items
  535. */
  536. static void
  537. create_new_menu (GnomeApp *app, WPanel *panel)
  538. {
  539. gchar *file, *file2;
  540. gint pos;
  541. GtkWidget *shell;
  542. shell = gnome_app_find_menu_pos (app->menubar, _("File/New/Directory..."), &pos);
  543. file = gnome_unconditional_datadir_file ("mc/templates");
  544. pos = create_new_menu_from (file, shell, pos);
  545. file2 = gnome_datadir_file ("mc/templates");
  546. if (file2 != NULL){
  547. if (strcmp (file, file2) != 0)
  548. create_new_menu_from (file2, shell, pos);
  549. }
  550. g_free (file);
  551. g_free (file2);
  552. }
  553. /*
  554. * This routine is a menu relay.
  555. *
  556. * This is called before the actual command specified in the GnomeUIInfo
  557. * structure. This allows me to select the panel (ie, set the global cpanel
  558. * variable to which this menu is bound).
  559. *
  560. * This is important, as we can have a menu tearoffed. And the current hack
  561. * of setting cpanel on the focus-in event wont work.
  562. *
  563. */
  564. static void
  565. panel_menu_relay (GtkObject *object, WPanel *panel)
  566. {
  567. void (*real_func)(GtkObject *object, WPanel *panel);
  568. real_func = gtk_object_get_user_data (object);
  569. set_current_panel (panel);
  570. (*real_func)(object, panel);
  571. }
  572. static void
  573. my_menu_signal_connect (GnomeUIInfo *uiinfo, gchar *signal_name,
  574. GnomeUIBuilderData *uibdata)
  575. {
  576. gtk_object_set_user_data (GTK_OBJECT (uiinfo->widget), uiinfo->moreinfo);
  577. gtk_signal_connect (GTK_OBJECT (uiinfo->widget),
  578. signal_name, panel_menu_relay, uibdata->data ?
  579. uibdata->data : uiinfo->user_data);
  580. }
  581. static void
  582. my_app_create_menus (GnomeApp *app, GnomeUIInfo *uiinfo, void *data)
  583. {
  584. GnomeUIBuilderData uibdata;
  585. g_return_if_fail (app != NULL);
  586. g_return_if_fail (GNOME_IS_APP (app));
  587. g_return_if_fail (uiinfo != NULL);
  588. uibdata.connect_func = my_menu_signal_connect;
  589. uibdata.data = data;
  590. uibdata.is_interp = FALSE;
  591. uibdata.relay_func = NULL;
  592. uibdata.destroy_func = NULL;
  593. gnome_app_create_menus_custom (app, uiinfo, &uibdata);
  594. }
  595. /**
  596. * copy_uiinfo_widgets:
  597. * @uiinfo: A GnomeUIInfo array
  598. *
  599. * Allocates an array of widgets and copies the widgets from the uiinfo array to
  600. * it. The array will be NULL-terminated.
  601. *
  602. * Returns: The allocated array of widgets.
  603. **/
  604. gpointer *
  605. copy_uiinfo_widgets (GnomeUIInfo *uiinfo)
  606. {
  607. gpointer *dest;
  608. int n;
  609. int i;
  610. g_return_val_if_fail (uiinfo != NULL, NULL);
  611. /* Count number of items */
  612. for (n = 0; uiinfo[n].type != GNOME_APP_UI_ENDOFINFO; n++);
  613. /* Copy the widgets */
  614. dest = g_new (gpointer, n + 1);
  615. for (i = 0; i < n; i++)
  616. dest[i] = uiinfo[i].widget;
  617. dest[i] = NULL;
  618. return dest;
  619. }
  620. WPanel *
  621. create_container (Dlg_head *h, const char *name, const char *geometry)
  622. {
  623. PanelContainer *container;
  624. WPanel *panel;
  625. GtkWidget *app, *vbox;
  626. int xpos, ypos, width, height;
  627. GnomeUIInfo *uiinfo;
  628. char buf[50];
  629. container = g_new (PanelContainer, 1);
  630. gnome_parse_geometry (geometry, &xpos, &ypos, &width, &height);
  631. container->splitted = 0;
  632. app = gnome_app_new ("gmc", name);
  633. /* Geometry configuration */
  634. if (width != -1 && height != -1)
  635. gtk_window_set_default_size (GTK_WINDOW (app), width, height);
  636. else
  637. gtk_window_set_default_size (GTK_WINDOW (app), 540, 360);
  638. if (xpos != -1 && ypos != -1)
  639. gtk_widget_set_uposition (GTK_WIDGET (app), xpos, ypos);
  640. panel = panel_new (name);
  641. /* Set the unique name for session management */
  642. sprintf (buf, "%d", panel->id);
  643. gtk_window_set_wmclass (GTK_WINDOW (app), "gmc", buf);
  644. /* Create the holder for the contents */
  645. vbox = gtk_vbox_new (FALSE, 0);
  646. gtk_container_set_border_width (GTK_CONTAINER (vbox), 0);
  647. gnome_app_set_contents (GNOME_APP (app), vbox);
  648. if (desktop_wm_is_gnome_compliant == 1)
  649. uiinfo = gnome_panel_menu_without_desktop;
  650. else
  651. uiinfo = gnome_panel_menu_with_desktop;
  652. my_app_create_menus (GNOME_APP (app), uiinfo, panel);
  653. panel->view_menu_items = copy_uiinfo_widgets (panel_view_menu_uiinfo);
  654. create_new_menu (GNOME_APP (app), panel);
  655. panel->ministatus = GNOME_APPBAR(gnome_appbar_new(FALSE, TRUE, GNOME_PREFERENCES_NEVER));
  656. gnome_app_set_statusbar(GNOME_APP (app), GTK_WIDGET(panel->ministatus));
  657. if (desktop_wm_is_gnome_compliant)
  658. gnome_app_install_menu_hints (GNOME_APP (app), gnome_panel_menu_without_desktop);
  659. else
  660. gnome_app_install_menu_hints (GNOME_APP (app), gnome_panel_menu_with_desktop);
  661. gtk_signal_connect (GTK_OBJECT (app),
  662. "enter_notify_event",
  663. GTK_SIGNAL_FUNC (panel_enter_event),
  664. panel);
  665. gtk_signal_connect (GTK_OBJECT (app),
  666. "delete_event",
  667. GTK_SIGNAL_FUNC (gnome_close_panel_event),
  668. panel);
  669. /* Ultra nasty hack follows:
  670. * I am setting the panel->widget.wdata value here before the
  671. * panel X stuff gets created in the INIT message section of the
  672. * widget. There I put a pointer to the vbox where the panel
  673. * should pack itself
  674. */
  675. panel->widget.wdata = (widget_data) vbox;
  676. container->panel = panel;
  677. containers = g_list_append (containers, container);
  678. if (!current_panel_ptr){
  679. current_panel_ptr = container;
  680. } else if (!other_panel_ptr)
  681. other_panel_ptr = container;
  682. bind_gtk_keys (GTK_WIDGET (app), h);
  683. return panel;
  684. }
  685. WPanel *
  686. new_panel_with_geometry_at (const char *dir, const char *geometry)
  687. {
  688. WPanel *panel;
  689. mc_chdir ((char *) dir);
  690. panel = create_container (desktop_dlg, dir, geometry);
  691. set_current_panel (panel);
  692. add_widget (desktop_dlg, panel);
  693. #if 0
  694. x_flush_events ();
  695. #endif
  696. return panel;
  697. }
  698. WPanel *
  699. new_panel_at (const char *dir)
  700. {
  701. return new_panel_with_geometry_at (dir, NULL);
  702. }
  703. void
  704. setup_panels (void)
  705. {
  706. load_hint ();
  707. }
  708. /*
  709. * GNOME's implementation of the update_panels routine
  710. */
  711. void
  712. update_panels (int force_update, char *current_file)
  713. {
  714. int reload_others = !(force_update & UP_ONLY_CURRENT);
  715. GList *p;
  716. /* Test if there are panels open */
  717. if (!cpanel)
  718. return;
  719. if (!is_a_desktop_panel (cpanel))
  720. update_one_panel_widget (cpanel, force_update, current_file);
  721. if (reload_others){
  722. for (p = containers; p; p = p->next){
  723. PanelContainer *pc = p->data;
  724. if (p->data == current_panel_ptr)
  725. continue;
  726. if (!is_a_desktop_panel (pc->panel))
  727. update_one_panel_widget (pc->panel, force_update, UP_KEEPSEL);
  728. }
  729. }
  730. mc_chdir (cpanel->cwd);
  731. }