bookmarks.c
上传用户:tjfeida
上传日期:2013-03-10
资源大小:1917k
文件大小:43k
源码类别:

Ftp客户端

开发平台:

Visual C++

  1. /*****************************************************************************/
  2. /*  bookmarks.c - routines for the bookmarks                                 */
  3. /*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
  4. /*                                                                           */
  5. /*  This program is free software; you can redistribute it and/or modify     */
  6. /*  it under the terms of the GNU General Public License as published by     */
  7. /*  the Free Software Foundation; either version 2 of the License, or        */
  8. /*  (at your option) any later version.                                      */
  9. /*                                                                           */
  10. /*  This program is distributed in the hope that it will be useful,          */
  11. /*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
  12. /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
  13. /*  GNU General Public License for more details.                             */
  14. /*                                                                           */
  15. /*  You should have received a copy of the GNU General Public License        */
  16. /*  along with this program; if not, write to the Free Software              */
  17. /*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA      */
  18. /*****************************************************************************/
  19. #include "gftp-gtk.h"
  20. static const char cvsid[] = "$Id: bookmarks.c,v 1.9 2002/12/03 02:36:37 masneyb Exp $";
  21. static GtkWidget * bm_hostedit, * bm_portedit, * bm_localdiredit,
  22.   * bm_remotediredit, * bm_useredit, * bm_passedit, * bm_acctedit, * anon_chk,
  23.   * bm_pathedit, * bm_protocol, * tree, *bm_sftppath;
  24. static GHashTable * new_bookmarks_htable;
  25. static gftp_bookmarks * new_bookmarks;
  26. static GtkItemFactory * edit_factory;
  27. void
  28. run_bookmark (gpointer data)
  29. {
  30.   gftp_bookmarks * tempentry;
  31.   int i;
  32.   if (window1.request->stopable || window2.request->stopable)
  33.     {
  34.       ftp_log (gftp_logging_misc, NULL,
  35.                _("%s: Please hit the stop button first to do anything elsen"),
  36.                _("Run Bookmark"));
  37.       return;
  38.     }
  39.   if ((tempentry = g_hash_table_lookup (bookmarks_htable, (char *) data)) == NULL)
  40.     {
  41.       ftp_log (gftp_logging_misc, NULL,
  42.        _("Internal gFTP Error: Could not look up bookmark entry. This is definately a bug. Please email masneyb@gftp.org about it. Please be sure to include the version number and how you can reproduce itn"));
  43.       return;
  44.     }
  45.   else if (tempentry->hostname == NULL || *tempentry->hostname == '' ||
  46.    tempentry->user == NULL || *tempentry->user == '')
  47.     {
  48.       ftp_log (gftp_logging_misc, NULL, _("Bookmarks Error: There are some missing entries in this bookmark. Make sure you have a hostname and usernamen"));
  49.       return;
  50.     }
  51.   if (GFTP_IS_CONNECTED (current_wdata->request))
  52.     disconnect (current_wdata);
  53.   if (tempentry->local_dir && *tempentry->local_dir != '')
  54.     {
  55.       gftp_set_directory (other_wdata->request, tempentry->local_dir);
  56.       gtk_clist_freeze (GTK_CLIST (other_wdata->listbox));
  57.       remove_files_window (other_wdata);
  58.       ftp_list_files (other_wdata, 1);
  59.       gtk_clist_thaw (GTK_CLIST (other_wdata->listbox));
  60.     }
  61.   gftp_set_username (current_wdata->request, tempentry->user);
  62.   if (strncmp (tempentry->pass, "@EMAIL@", 7) == 0)
  63.     gftp_set_password (current_wdata->request, emailaddr);
  64.   else
  65.     gftp_set_password (current_wdata->request, tempentry->pass);
  66.   if (tempentry->acct != NULL)
  67.     gftp_set_account (current_wdata->request, tempentry->acct);
  68.   gftp_set_hostname (current_wdata->request, tempentry->hostname);
  69.   gftp_set_directory (current_wdata->request, tempentry->remote_dir);
  70.   gftp_set_port (current_wdata->request, tempentry->port);
  71.   gftp_set_sftpserv_path (current_wdata->request, tempentry->sftpserv_path);
  72.   for (i = 0; gftp_protocols[i].name; i++)
  73.     {
  74.       if (strcmp (gftp_protocols[i].name, tempentry->protocol) == 0)
  75. {
  76.   gftp_protocols[i].init (current_wdata->request);
  77.   break;
  78. }
  79.     }
  80.   if (!gftp_protocols[i].name)
  81.     gftp_protocols[0].init (current_wdata->request);
  82.   ftp_connect (current_wdata, current_wdata->request, 1);
  83. }
  84. static void
  85. doadd_bookmark (gpointer * data, gftp_dialog_data * ddata)
  86. {
  87.   GtkItemFactoryEntry test = { NULL, NULL, run_bookmark, 0 };
  88.   const char *edttxt, *spos;
  89.   gftp_bookmarks * tempentry;
  90.   char *dpos;
  91.   edttxt = gtk_entry_get_text (GTK_ENTRY (ddata->edit));
  92.   if (*edttxt == '')
  93.     {
  94.       ftp_log (gftp_logging_error, NULL,
  95.        _("Add Bookmark: You must enter a name for the bookmarkn"));
  96.       return;
  97.     }
  98.   if (g_hash_table_lookup (bookmarks_htable, edttxt) != NULL)
  99.     {
  100.       ftp_log (gftp_logging_error, NULL,
  101.        _("Add Bookmark: Cannot add bookmark %s because that name already existsn"), edttxt);
  102.       return;
  103.     }
  104.   tempentry = g_malloc0 (sizeof (*tempentry));
  105.   dpos = tempentry->path = g_malloc (strlen (edttxt) + 1);
  106.   for (spos = edttxt; *spos != '';)
  107.     {
  108.       *dpos++ = *spos++;
  109.       if (*spos == '/')
  110.         {
  111.           *dpos++ = '/';
  112.           for (; *spos == '/'; spos++);
  113.         }
  114.     }
  115.   *dpos = '';
  116.   edttxt = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (hostedit)->entry));
  117.   tempentry->hostname = g_malloc (strlen (edttxt) + 1);
  118.   strcpy (tempentry->hostname, edttxt);
  119.   edttxt = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (portedit)->entry));
  120.   tempentry->port = strtol (edttxt, NULL, 10);
  121.   tempentry->protocol =
  122.     g_malloc (strlen (GFTP_GET_PROTOCOL_NAME (current_wdata->request)) + 1);
  123.   strcpy (tempentry->protocol, GFTP_GET_PROTOCOL_NAME (current_wdata->request));
  124.   edttxt = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (other_wdata->combo)->entry));
  125.   tempentry->local_dir = g_malloc (strlen (edttxt) + 1);
  126.   strcpy (tempentry->local_dir, edttxt);
  127.   edttxt = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (current_wdata->combo)->entry));
  128.   tempentry->remote_dir = g_malloc (strlen (edttxt) + 1);
  129.   strcpy (tempentry->remote_dir, edttxt);
  130.   if ((edttxt = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (useredit)->entry))) != NULL)
  131.     {
  132.       tempentry->user = g_malloc (strlen (edttxt) + 1);
  133.       strcpy (tempentry->user, edttxt);
  134.       edttxt = gtk_entry_get_text (GTK_ENTRY (passedit));
  135.       tempentry->pass = g_malloc (strlen (edttxt) + 1);
  136.       strcpy (tempentry->pass, edttxt);
  137.       tempentry->save_password = GTK_TOGGLE_BUTTON (ddata->checkbox)->active;
  138.     }
  139.   add_to_bookmark (tempentry);
  140.   test.path = g_strconcat ("/Bookmarks/", tempentry->path, NULL);
  141.   gtk_item_factory_create_item (factory, &test, (gpointer) tempentry->path,
  142. 1);
  143.   g_free (test.path);
  144.   gftp_write_bookmarks_file ();
  145. }
  146. void
  147. add_bookmark (gpointer data)
  148. {
  149.   const char *edttxt;
  150.   if (!check_status (_("Add Bookmark"), current_wdata, 0, 0, 0, 1))
  151.     return;
  152.   edttxt = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (hostedit)->entry));
  153.   if (*edttxt == '')
  154.     {
  155.       ftp_log (gftp_logging_error, NULL,
  156.        _("Add Bookmark: You must enter a hostnamen"));
  157.       return;
  158.     }
  159.   MakeEditDialog (_("Add Bookmark"), _("Enter the name of the bookmark you want to addnYou can separate items by a / to put it into a submenun(ex: Linux Sites/Debian)"), NULL, 1, _("Remember password"), gftp_dialog_button_create, doadd_bookmark, data, NULL, NULL);
  160. }
  161. void
  162. build_bookmarks_menu (void)
  163. {
  164.   GtkItemFactoryEntry test = { NULL, NULL, NULL, 0 };
  165.   gftp_bookmarks * tempentry;
  166.   tempentry = bookmarks->children;
  167.   while (tempentry != NULL)
  168.     {
  169.       test.path = g_strconcat ("/Bookmarks/", tempentry->path, NULL);
  170.       if (tempentry->isfolder)
  171.         {
  172.           test.item_type = "<Branch>";
  173.           test.callback = NULL;
  174.         }
  175.       else
  176.         {
  177.           test.item_type = "";
  178.           test.callback = run_bookmark;
  179.         }
  180.       gtk_item_factory_create_item (factory, &test,
  181.                                     (gpointer) tempentry->path, 1);
  182.       g_free (test.path);
  183.       if (tempentry->children != NULL)
  184.         {
  185.           tempentry = tempentry->children;
  186.           continue;
  187.         }
  188.       while (tempentry->next == NULL && tempentry->prev != NULL)
  189.         tempentry = tempentry->prev;
  190.       tempentry = tempentry->next;
  191.     }
  192. }
  193. static void
  194. free_bookmark_entry_items (gftp_bookmarks * entry)
  195. {
  196.   if (entry->hostname)
  197.     g_free (entry->hostname);
  198.   if (entry->remote_dir)
  199.     g_free (entry->remote_dir);
  200.   if (entry->local_dir)
  201.     g_free (entry->local_dir);
  202.   if (entry->user)
  203.     g_free (entry->user);
  204.   if (entry->pass)
  205.     g_free (entry->pass);
  206.   if (entry->acct)
  207.     g_free (entry->acct);
  208.   if (entry->protocol)
  209.     g_free (entry->protocol);
  210. }
  211. static gftp_bookmarks *
  212. copy_bookmarks (gftp_bookmarks * bookmarks)
  213. {
  214.   gftp_bookmarks * new_bm, * preventry, * tempentry, * sibling, * newentry,
  215.                  * tentry;
  216.   new_bm = g_malloc0 (sizeof (*new_bm));
  217.   /* FIXME - memory leak */
  218.   new_bm->path = g_malloc0 (1);
  219.   new_bm->isfolder = bookmarks->isfolder;
  220.   preventry = new_bm;
  221.   tempentry = bookmarks->children;
  222.   sibling = NULL;
  223.   while (tempentry != NULL)
  224.     {
  225.       newentry = g_malloc0 (sizeof (*newentry));
  226.       newentry->isfolder = tempentry->isfolder;
  227.       newentry->save_password = tempentry->save_password;
  228.       newentry->cnode = tempentry->cnode;
  229.       if (tempentry->path)
  230. {
  231.   newentry->path = g_malloc (strlen (tempentry->path) + 1);
  232.   strcpy (newentry->path, tempentry->path);
  233. }
  234.       if (tempentry->hostname)
  235. {
  236.   newentry->hostname = g_malloc (strlen (tempentry->hostname) + 1);
  237.   strcpy (newentry->hostname, tempentry->hostname);
  238. }
  239.       if (tempentry->protocol)
  240. {
  241.   newentry->protocol = g_malloc (strlen (tempentry->protocol) + 1);
  242.   strcpy (newentry->protocol, tempentry->protocol);
  243. }
  244.       if (tempentry->local_dir)
  245. {
  246.   newentry->local_dir = g_malloc (strlen (tempentry->local_dir) + 1);
  247.   strcpy (newentry->local_dir, tempentry->local_dir);
  248. }
  249.       if (tempentry->remote_dir)
  250. {
  251.   newentry->remote_dir =
  252.     g_malloc (strlen (tempentry->remote_dir) + 1);
  253.   strcpy (newentry->remote_dir, tempentry->remote_dir);
  254. }
  255.       if (tempentry->user)
  256. {
  257.   newentry->user = g_malloc (strlen (tempentry->user) + 1);
  258.   strcpy (newentry->user, tempentry->user);
  259. }
  260.       if (tempentry->pass)
  261. {
  262.   newentry->pass = g_malloc (strlen (tempentry->pass) + 1);
  263.   strcpy (newentry->pass, tempentry->pass);
  264. }
  265.       if (tempentry->acct)
  266. {
  267.   newentry->acct = g_malloc (strlen (tempentry->acct) + 1);
  268.   strcpy (newentry->acct, tempentry->acct);
  269. }
  270.       if (tempentry->sftpserv_path)
  271.         {
  272.           newentry->sftpserv_path = g_malloc (strlen (tempentry->sftpserv_path) + 1);
  273.           strcpy (newentry->sftpserv_path, tempentry->sftpserv_path);
  274.         }
  275.       newentry->port = tempentry->port;
  276.       if (sibling == NULL)
  277. {
  278.   if (preventry->children == NULL)
  279.     preventry->children = newentry;
  280.   else
  281.     {
  282.       tentry = preventry->children;
  283.       while (tentry->next != NULL)
  284. tentry = tentry->next;
  285.       tentry->next = newentry;
  286.     }
  287. }
  288.       else
  289. sibling->next = newentry;
  290.       newentry->prev = preventry;
  291.       if (tempentry->children != NULL)
  292. {
  293.   preventry = newentry;
  294.   sibling = NULL;
  295.   tempentry = tempentry->children;
  296. }
  297.       else
  298. {
  299.   if (tempentry->next == NULL)
  300.     {
  301.       sibling = NULL;
  302.       while (tempentry->next == NULL && tempentry->prev != NULL)
  303. {
  304.   tempentry = tempentry->prev;
  305.   preventry = preventry->prev;
  306. }
  307.       tempentry = tempentry->next;
  308.     }
  309.   else
  310.     {
  311.       sibling = newentry;
  312.       tempentry = tempentry->next;
  313.     }
  314. }
  315.     }
  316.   return (new_bm);
  317. }
  318. static void
  319. bm_apply_changes (GtkWidget * widget, gpointer backup_data)
  320. {
  321.   gftp_bookmarks * tempentry, * delentry;
  322.   char *tempstr;
  323.   tempentry = bookmarks->children;
  324.   while (tempentry != NULL)
  325.     {
  326.       if (tempentry->path && !tempentry->isfolder)
  327. {
  328.   tempstr = g_strdup_printf ("/Bookmarks/%s", tempentry->path);
  329.           gtk_widget_destroy (gtk_item_factory_get_item (factory, tempstr));
  330.   g_free (tempentry->path);
  331.   g_free (tempstr);
  332. }
  333.       free_bookmark_entry_items (tempentry);
  334.       if (tempentry->children != NULL)
  335. tempentry = tempentry->children;
  336.       else
  337. {
  338.   if (tempentry->next == NULL)
  339.     {
  340.       while (tempentry->next == NULL && tempentry->prev != NULL)
  341. {
  342.   delentry = tempentry;
  343.   tempentry = tempentry->prev;
  344.   if (delentry->isfolder)
  345.     {
  346.       tempstr = g_strdup_printf ("/Bookmarks/%s", 
  347.                                                  delentry->path);
  348.                       gtk_widget_destroy (gtk_item_factory_get_item (factory, 
  349.                                                                      tempstr));
  350.       g_free (tempstr);
  351.       g_free (delentry->path);
  352.     }
  353.   g_free (delentry);
  354. }
  355.       delentry = tempentry;
  356.       tempentry = tempentry->next;
  357.       if (delentry->isfolder && tempentry != NULL)
  358. {
  359.   tempstr = g_strdup_printf ("/Bookmarks/%s", 
  360.                                              delentry->path);
  361.                     gtk_widget_destroy (gtk_item_factory_get_item (factory, 
  362.                                                                    tempstr));
  363.   g_free (delentry->path);
  364.   g_free (tempstr);
  365.   g_free (delentry);
  366. }
  367.     }
  368.   else
  369.     {
  370.       delentry = tempentry;
  371.       tempentry = tempentry->next;
  372.       g_free (delentry);
  373.     }
  374. }
  375.     }
  376.   g_free (bookmarks);
  377.   g_hash_table_destroy (bookmarks_htable);
  378.   bookmarks = new_bookmarks;
  379.   bookmarks_htable = new_bookmarks_htable;
  380.   if (backup_data)
  381.     {
  382.       new_bookmarks = copy_bookmarks (bookmarks);
  383.       new_bookmarks_htable = build_bookmarks_hash_table (new_bookmarks);
  384.     }
  385.   else
  386.     {
  387.       new_bookmarks = NULL;
  388.       new_bookmarks_htable = NULL;
  389.     }
  390.   build_bookmarks_menu ();
  391.   gftp_write_bookmarks_file ();
  392. }
  393. static void
  394. bm_close_dialog (GtkWidget * widget, GtkWidget * dialog)
  395. {
  396.   gftp_bookmarks * tempentry, * delentry;
  397.   if (new_bookmarks_htable)
  398.     g_hash_table_destroy (new_bookmarks_htable);
  399.   tempentry = new_bookmarks;
  400.   while (tempentry != NULL)
  401.     {
  402.       free_bookmark_entry_items (tempentry);
  403.       g_free (tempentry->path);
  404.       if (tempentry->children != NULL)
  405. {
  406.   tempentry = tempentry->children;
  407.   continue;
  408. }
  409.       while (tempentry->next == NULL && tempentry->prev != NULL)
  410.         {
  411.           delentry = tempentry;
  412.   tempentry = tempentry->prev;
  413.           g_free (delentry);
  414.         }
  415.       delentry = tempentry;
  416.       tempentry = tempentry->next;
  417.       g_free (delentry);
  418.     }
  419.   new_bookmarks = NULL;
  420.   new_bookmarks_htable = NULL;
  421.   gtk_widget_destroy (dialog);
  422. }
  423. #if GTK_MAJOR_VERSION > 1 
  424. static void
  425. editbm_action (GtkWidget * widget, gint response, gpointer user_data)
  426. {
  427.   switch (response)
  428.     {
  429.       case GTK_RESPONSE_OK:
  430.         bm_apply_changes (widget, NULL);
  431.         /* no break */
  432.       default:
  433.         bm_close_dialog (NULL, widget);
  434.     }
  435. }
  436. #endif
  437. static void
  438. do_make_new (gpointer data, gftp_dialog_data * ddata)
  439. {
  440.   GdkPixmap * closedir_pixmap, * opendir_pixmap;
  441.   GdkBitmap * closedir_bitmap, * opendir_bitmap;  
  442.   gftp_bookmarks * tempentry, * newentry;
  443.   GtkCTreeNode * sibling;
  444.   char *pos, *text[2];
  445.   const char *str;
  446. #if GTK_MAJOR_VERSION > 1
  447.   gsize bread, bwrite;
  448. #endif
  449.   gftp_get_pixmap (tree, "open_dir.xpm", &opendir_pixmap, &opendir_bitmap);
  450.   gftp_get_pixmap (tree, "dir.xpm", &closedir_pixmap, &closedir_bitmap);
  451.   str = gtk_entry_get_text (GTK_ENTRY (ddata->edit));
  452.   newentry = g_malloc0 (sizeof (*newentry));
  453. #if GTK_MAJOR_VERSION == 1
  454.   newentry->path = g_strdup (str);
  455.   while ((pos = strchr (str, '/')) != NULL)
  456.     *pos++ = ' ';
  457. #else
  458.   if (g_utf8_validate (str, -1, NULL))
  459.     newentry->path = g_strdup (str);
  460.   else
  461.     newentry->path = g_locale_to_utf8 (str, -1, &bread, &bwrite, NULL);
  462.   while ((pos = g_utf8_strchr (str, -1, '/')) != NULL)
  463.     *pos++ = ' ';
  464. #endif
  465.   newentry->prev = new_bookmarks;
  466.   if (data)
  467.     newentry->isfolder = 1;
  468.   if (new_bookmarks->children == NULL)
  469.     {
  470.       new_bookmarks->children = newentry;
  471.       sibling = NULL;
  472.     }
  473.   else
  474.     {
  475.       tempentry = new_bookmarks->children;
  476.       while (tempentry->next != NULL)
  477. tempentry = tempentry->next;
  478.       tempentry->next = newentry;
  479.       sibling = tempentry->cnode;
  480.     }
  481.   text[0] = text[1] = newentry->path;
  482.   if (newentry->isfolder)
  483.     newentry->cnode = gtk_ctree_insert_node (GTK_CTREE (tree), 
  484.                                              new_bookmarks->cnode, NULL,
  485.                      text, 5, closedir_pixmap, 
  486.                                              closedir_bitmap, opendir_pixmap,
  487.                      opendir_bitmap, FALSE, FALSE);
  488.   else
  489.     newentry->cnode = gtk_ctree_insert_node (GTK_CTREE (tree), 
  490.                                              new_bookmarks->cnode, NULL,
  491.                                              text, 5, NULL, NULL, NULL, NULL, 
  492.                                              FALSE, FALSE);
  493.   gtk_ctree_node_set_row_data (GTK_CTREE (tree), newentry->cnode, newentry);
  494.   g_hash_table_insert (new_bookmarks_htable, newentry->path, newentry);
  495. }
  496. static void
  497. new_folder_entry (gpointer data)
  498. {
  499.   MakeEditDialog (_("New Folder"),
  500.   _("Enter the name of the new folder to create"), NULL, 1,
  501.   NULL, gftp_dialog_button_create, 
  502.                   do_make_new, (gpointer) 0x1, NULL, NULL);
  503. }
  504. static void
  505. new_item_entry (gpointer data)
  506. {
  507.   MakeEditDialog (_("New Folder"),
  508.   _("Enter the name of the new item to create"), NULL, 1,
  509.   NULL, gftp_dialog_button_create,
  510.                   do_make_new, NULL, NULL, NULL);
  511. }
  512. static void
  513. do_delete_entry (gftp_bookmarks * entry, gftp_dialog_data * ddata)
  514. {
  515.   gftp_bookmarks * tempentry, * delentry;
  516.   g_hash_table_remove (new_bookmarks_htable, entry->path);
  517.   gtk_ctree_remove_node (GTK_CTREE (tree), entry->cnode);
  518.   if (entry->prev->children == entry)
  519.     entry->prev->children = entry->prev->children->next;
  520.   else
  521.     {
  522.       tempentry = entry->prev->children;
  523.       while (tempentry->next != entry)
  524. tempentry = tempentry->next;
  525.       tempentry->next = entry->next;
  526.     }
  527.   entry->prev = NULL;
  528.   entry->next = NULL;
  529.   tempentry = entry;
  530.   while (tempentry != NULL)
  531.     {
  532.       if (tempentry->path)
  533. g_free (tempentry->path);
  534.       if (tempentry->hostname)
  535. g_free (tempentry->hostname);
  536.       if (tempentry->remote_dir)
  537. g_free (tempentry->remote_dir);
  538.       if (tempentry->user)
  539. g_free (tempentry->user);
  540.       if (tempentry->pass)
  541. g_free (tempentry->pass);
  542.       if (tempentry->sftpserv_path)
  543.         g_free (tempentry->sftpserv_path);
  544.       if (tempentry->children != NULL)
  545. {
  546.   tempentry = tempentry->children;
  547.   continue;
  548. }
  549.       else if (tempentry->next == NULL && tempentry->prev != NULL)
  550. {
  551.   delentry = tempentry->prev;
  552.   g_free (tempentry);
  553.   tempentry = delentry->next;
  554.   if (delentry != entry)
  555.     g_free (delentry);
  556. }
  557.       else
  558. tempentry = tempentry->next;
  559.     }
  560.   g_free (entry);
  561. }
  562. static void
  563. delete_entry (gpointer data)
  564. {
  565.   gftp_bookmarks * entry;
  566.   char *tempstr, *pos;
  567.   if (GTK_CLIST (tree)->selection == NULL)
  568.     return;
  569.   entry =
  570.     gtk_ctree_node_get_row_data (GTK_CTREE (tree),
  571.  GTK_CLIST (tree)->selection->data);
  572.   if (entry == NULL || entry->prev == NULL)
  573.     return;
  574.   if (!entry->isfolder)
  575.     do_delete_entry (entry, NULL);
  576.   else
  577.     {
  578.       if ((pos = strrchr (entry->path, '/')) == NULL)
  579. pos = entry->path;
  580.       else
  581. pos++;
  582.       tempstr = g_strdup_printf (_("Are you sure you want to erase the bookmarkn%s and all it's children?"), pos);
  583.       MakeYesNoDialog (_("Delete Bookmark"), tempstr, do_delete_entry, entry, 
  584.                        NULL, NULL);
  585.       g_free (tempstr);
  586.     }
  587. }
  588. static void
  589. set_userpass_visible (GtkWidget * checkbutton, GtkWidget * entry)
  590. {
  591.   gtk_widget_set_sensitive (bm_useredit, !GTK_TOGGLE_BUTTON (anon_chk)->active);
  592.   gtk_widget_set_sensitive (bm_passedit, !GTK_TOGGLE_BUTTON (anon_chk)->active);
  593.   gtk_widget_set_sensitive (bm_acctedit, !GTK_TOGGLE_BUTTON (anon_chk)->active);
  594. }
  595. static void
  596. build_bookmarks_tree (void)
  597. {
  598.   GdkPixmap * closedir_pixmap, * opendir_pixmap;
  599.   GdkBitmap * closedir_bitmap, * opendir_bitmap;  
  600.   gftp_bookmarks * tempentry, * preventry;
  601.   char *pos, *prevpos, *text[2], *str;
  602.   GtkCTreeNode * parent;
  603.   gftp_get_pixmap (tree, "open_dir.xpm", &opendir_pixmap, &opendir_bitmap);
  604.   gftp_get_pixmap (tree, "dir.xpm", &closedir_pixmap, &closedir_bitmap);
  605.   text[0] = text[1] = _("Bookmarks");
  606.   parent = gtk_ctree_insert_node (GTK_CTREE (tree), NULL, NULL, text, 5, 
  607.                                   closedir_pixmap, closedir_bitmap, 
  608.                                   opendir_pixmap, opendir_bitmap, FALSE, TRUE);
  609.   gtk_ctree_node_set_row_data (GTK_CTREE (tree), parent, new_bookmarks);
  610.   new_bookmarks->cnode = parent;
  611.   tempentry = new_bookmarks->children;
  612.   while (tempentry != NULL)
  613.     {
  614.       tempentry->cnode = NULL;
  615.       if (tempentry->children != NULL)
  616. {
  617.   tempentry = tempentry->children;
  618.   continue;
  619. }
  620.       else
  621. {
  622.   pos = tempentry->path;
  623.   while ((pos = strchr (pos, '/')) != NULL)
  624.     {
  625.       *pos = '';
  626.       str = g_malloc (strlen (tempentry->path) + 1);
  627.       strcpy (str, tempentry->path);
  628.       *pos = '/';
  629.       preventry = g_hash_table_lookup (new_bookmarks_htable, str);
  630.       if (preventry->cnode == NULL)
  631. {
  632.   if ((prevpos = strrchr (str, '/')) == NULL)
  633.     prevpos = str;
  634.   else
  635.     prevpos++;
  636.   text[0] = text[1] = prevpos;
  637.   preventry->cnode = gtk_ctree_insert_node (GTK_CTREE (tree),
  638.    preventry->prev->cnode, NULL, text,
  639.    5, closedir_pixmap, closedir_bitmap,
  640.    opendir_pixmap, opendir_bitmap,
  641.    FALSE, FALSE);
  642.   gtk_ctree_node_set_row_data (GTK_CTREE (tree),
  643.        preventry->cnode, preventry);
  644. }
  645.       g_free (str);
  646.       pos++;
  647.     }
  648. }
  649.       if ((pos = strrchr (tempentry->path, '/')) == NULL)
  650. pos = tempentry->path;
  651.       else
  652. pos++;
  653.       text[0] = text[1] = pos;
  654.       tempentry->cnode = gtk_ctree_insert_node (GTK_CTREE (tree), 
  655.                                tempentry->prev->cnode, NULL,
  656.        text, 5, NULL, NULL, NULL, NULL, FALSE, FALSE);
  657.       gtk_ctree_node_set_row_data (GTK_CTREE (tree), tempentry->cnode,
  658.    tempentry);
  659.       while (tempentry->next == NULL && tempentry->prev != NULL)
  660. tempentry = tempentry->prev;
  661.       tempentry = tempentry->next;
  662.     }
  663. }
  664. static void
  665. clear_bookmarks_tree (void)
  666. {
  667.   gftp_bookmarks * tempentry;
  668.   tempentry = new_bookmarks->children;
  669.   while (tempentry != NULL)
  670.     {
  671.       if (tempentry->children != NULL)
  672. {
  673.   tempentry = tempentry->children;
  674.   continue;
  675. }
  676.       while (tempentry->next == NULL && tempentry->prev != NULL)
  677. {
  678.   gtk_ctree_remove_node (GTK_CTREE (tree), tempentry->cnode);
  679.   tempentry->cnode = NULL;
  680.   tempentry = tempentry->prev;
  681. }
  682.       gtk_ctree_remove_node (GTK_CTREE (tree), tempentry->cnode);
  683.       tempentry->cnode = NULL;
  684.       tempentry = tempentry->next;
  685.     }
  686. }
  687. static void
  688. entry_apply_changes (GtkWidget * widget, gftp_bookmarks * entry)
  689. {
  690.   char *pos, *newpath, tempchar, *tempstr, *origpath;
  691.   gftp_bookmarks * tempentry, * nextentry;
  692.   GtkWidget * tempwid;
  693.   const char *str;
  694.   int oldpathlen;
  695.   oldpathlen = strlen (entry->path);
  696.   if ((pos = strrchr (entry->path, '/')) == NULL)
  697.     {
  698.       pos = entry->path;
  699.       tempchar = *entry->path;
  700.       *entry->path = '';
  701.     }
  702.   else
  703.     {
  704.       tempchar = *pos;
  705.       *pos = '';
  706.     }
  707.   origpath = newpath = g_strconcat (entry->path, "/",
  708.                          gtk_entry_get_text (GTK_ENTRY (bm_pathedit)), NULL);
  709.   remove_double_slashes (newpath);
  710.   for (; *newpath == '/'; newpath++);
  711.   *pos = tempchar;
  712.   str = gtk_entry_get_text (GTK_ENTRY (bm_hostedit));
  713.   if (entry->hostname)
  714.     g_free (entry->hostname);
  715.   entry->hostname = g_malloc (strlen (str) + 1);
  716.   strcpy (entry->hostname, str);
  717.   str = gtk_entry_get_text (GTK_ENTRY (bm_portedit));
  718.   entry->port = strtol (str, NULL, 10);
  719.   tempwid = gtk_menu_get_active (GTK_MENU (bm_protocol));
  720.   str = gtk_object_get_user_data (GTK_OBJECT (tempwid));
  721.   if (entry->protocol)
  722.     g_free (entry->protocol);
  723.   entry->protocol = g_malloc (strlen (str) + 1);
  724.   strcpy (entry->protocol, str);
  725.   str = gtk_entry_get_text (GTK_ENTRY (bm_remotediredit));
  726.   if (entry->remote_dir)
  727.     g_free (entry->remote_dir);
  728.   entry->remote_dir = g_malloc (strlen (str) + 1);
  729.   strcpy (entry->remote_dir, str);
  730.   str = gtk_entry_get_text (GTK_ENTRY (bm_localdiredit));
  731.   if (entry->local_dir)
  732.     g_free (entry->local_dir);
  733.   entry->local_dir = g_malloc (strlen (str) + 1);
  734.   strcpy (entry->local_dir, str);
  735.   str = gtk_entry_get_text (GTK_ENTRY (bm_sftppath));
  736.   if (entry->sftpserv_path)
  737.     g_free (entry->sftpserv_path);
  738.   if (strlen (str) > 0)
  739.     {
  740.       entry->sftpserv_path = g_malloc (strlen (str) + 1);
  741.       strcpy (entry->sftpserv_path, str);
  742.     }
  743.   else
  744.     entry->sftpserv_path = NULL;
  745.   if (GTK_TOGGLE_BUTTON (anon_chk)->active)
  746.     str = "anonymous";
  747.   else
  748.     str = gtk_entry_get_text (GTK_ENTRY (bm_useredit));
  749.   if (entry->user)
  750.     g_free (entry->user);
  751.   entry->user = g_malloc (strlen (str) + 1);
  752.   strcpy (entry->user, str);
  753.   if (GTK_TOGGLE_BUTTON (anon_chk)->active)
  754.     str = "@EMAIL@";
  755.   else
  756.     str = gtk_entry_get_text (GTK_ENTRY (bm_passedit));
  757.   if (entry->pass)
  758.     g_free (entry->pass);
  759.   entry->pass = g_malloc (strlen (str) + 1);
  760.   strcpy (entry->pass, str);
  761.   entry->save_password = *entry->pass != '';
  762.   if (GTK_TOGGLE_BUTTON (anon_chk)->active)
  763.     str = "";
  764.   else
  765.     str = gtk_entry_get_text (GTK_ENTRY (bm_acctedit));
  766.   if (entry->acct)
  767.     g_free (entry->acct);
  768.   entry->acct = g_malloc (strlen (str) + 1);
  769.   strcpy (entry->acct, str);
  770.   if (strcmp (entry->path, newpath) != 0)
  771.     {
  772.       tempentry = entry;
  773.       nextentry = entry->next;
  774.       entry->next = NULL;
  775.       while (tempentry != NULL)
  776. {
  777.   g_hash_table_remove (new_bookmarks_htable, tempentry->path);
  778.   tempstr = g_strconcat (newpath, "/", tempentry->path + oldpathlen, 
  779.                                  NULL);
  780.   remove_double_slashes (tempstr);
  781.   g_free (tempentry->path);
  782.   tempentry->path = tempstr;
  783.   g_hash_table_insert (new_bookmarks_htable, tempentry->path,
  784.        tempentry);
  785.   if (tempentry->children != NULL)
  786.     {
  787.       tempentry = tempentry->children;
  788.       continue;
  789.     }
  790.   while (tempentry->next == NULL && tempentry != entry &&
  791.  tempentry->prev != NULL)
  792.     tempentry = tempentry->prev;
  793.   tempentry = tempentry->next;
  794. }
  795.       entry->next = nextentry;
  796.       clear_bookmarks_tree ();
  797.       build_bookmarks_tree ();
  798.     }
  799.   g_free (origpath);
  800. }
  801. #if GTK_MAJOR_VERSION > 1
  802. static void
  803. bmedit_action (GtkWidget * widget, gint response, gpointer user_data)
  804. {
  805.   switch (response)
  806.     {
  807.       case GTK_RESPONSE_APPLY:
  808.         entry_apply_changes (widget, user_data);
  809.         break;
  810.       case GTK_RESPONSE_OK:
  811.         entry_apply_changes (widget, user_data);
  812.         /* no break */
  813.       default:
  814.         gtk_widget_destroy (widget);
  815.     }
  816. }   
  817. #endif
  818. static void
  819. edit_entry (gpointer data)
  820. {
  821.   GtkWidget * table, * tempwid, * dialog, * menu;
  822.   gftp_bookmarks * entry;
  823.   int i, num;
  824.   char *pos;
  825.   if (GTK_CLIST (tree)->selection == NULL)
  826.     return;
  827.   entry = gtk_ctree_node_get_row_data (GTK_CTREE (tree),
  828.  GTK_CLIST (tree)->selection->data);
  829.   if (entry == NULL || entry == new_bookmarks)
  830.     return;
  831. #if GTK_MAJOR_VERSION == 1
  832.   dialog = gtk_dialog_new ();
  833.   gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Entry"));
  834.   gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 15);
  835. #else
  836.   dialog = gtk_dialog_new_with_buttons (_("Edit Entry"), NULL, 0,
  837.                                         GTK_STOCK_SAVE,
  838.                                         GTK_RESPONSE_OK,
  839.                                         GTK_STOCK_CANCEL,
  840.                                         GTK_RESPONSE_CANCEL,
  841.                                         GTK_STOCK_APPLY,
  842.                                         GTK_RESPONSE_APPLY,
  843.                                         NULL);
  844. #endif
  845.   gtk_window_set_wmclass (GTK_WINDOW (dialog), "Edit Bookmark Entry", "gFTP");
  846.   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
  847.   gtk_container_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 10);
  848.   gtk_widget_realize (dialog);
  849.   if (gftp_icon != NULL)
  850.     {
  851.       gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap,
  852.                            gftp_icon->bitmap);
  853.       gdk_window_set_icon_name (dialog->window, _("gFTP Icon"));
  854.     }
  855.   tempwid = gtk_frame_new (NULL);
  856.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), tempwid, TRUE,
  857.       TRUE, 0);
  858.   gtk_widget_show (tempwid);
  859.   table = gtk_table_new (11, 2, FALSE);
  860.   gtk_container_border_width (GTK_CONTAINER (table), 5);
  861.   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
  862.   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
  863.   gtk_container_add (GTK_CONTAINER (tempwid), table);
  864.   gtk_widget_show (table);
  865.   tempwid = gtk_label_new (_("Description:"));
  866.   gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
  867.   gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 0, 1);
  868.   gtk_widget_show (tempwid);
  869.   bm_pathedit = gtk_entry_new ();
  870.   gtk_table_attach_defaults (GTK_TABLE (table), bm_pathedit, 1, 2, 0, 1);
  871.   if ((pos = strrchr (entry->path, '/')) == NULL)
  872.     pos = entry->path;
  873.   else
  874.     pos++;
  875.   if (pos)
  876.     gtk_entry_set_text (GTK_ENTRY (bm_pathedit), pos);
  877.   gtk_widget_show (bm_pathedit);
  878.   tempwid = gtk_label_new (_("Hostname:"));
  879.   gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
  880.   gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 1, 2);
  881.   gtk_widget_show (tempwid);
  882.   bm_hostedit = gtk_entry_new ();
  883.   gtk_table_attach_defaults (GTK_TABLE (table), bm_hostedit, 1, 2, 1, 2);
  884.   if (entry->isfolder)
  885.     gtk_widget_set_sensitive (bm_hostedit, 0);
  886.   else if (entry->hostname)
  887.     gtk_entry_set_text (GTK_ENTRY (bm_hostedit), entry->hostname);
  888.   gtk_widget_show (bm_hostedit);
  889.   tempwid = gtk_label_new (_("Port:"));
  890.   gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
  891.   gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 2, 3);
  892.   gtk_widget_show (tempwid);
  893.   bm_portedit = gtk_entry_new ();
  894.   gtk_table_attach_defaults (GTK_TABLE (table), bm_portedit, 1, 2, 2, 3);
  895.   if (entry->isfolder)
  896.     gtk_widget_set_sensitive (bm_portedit, 0);
  897.   else if (entry->port)
  898.     {
  899.       pos = g_strdup_printf ("%d", entry->port);
  900.       gtk_entry_set_text (GTK_ENTRY (bm_portedit), pos);
  901.       g_free (pos);
  902.     }
  903.   gtk_widget_show (bm_portedit);
  904.   tempwid = gtk_label_new (_("Protocol:"));
  905.   gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
  906.   gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 3, 4);
  907.   gtk_widget_show (tempwid);
  908.   menu = gtk_option_menu_new ();
  909.   gtk_table_attach_defaults (GTK_TABLE (table), menu, 1, 2, 3, 4);
  910.   gtk_widget_show (menu);
  911.   num = 0;
  912.   bm_protocol = gtk_menu_new ();
  913.   for (i = 0; gftp_protocols[i].name; i++)
  914.     {
  915.       tempwid = gtk_menu_item_new_with_label (gftp_protocols[i].name);
  916.       gtk_object_set_user_data (GTK_OBJECT (tempwid), gftp_protocols[i].name);
  917.       gtk_menu_append (GTK_MENU (bm_protocol), tempwid);
  918.       gtk_widget_show (tempwid);
  919.       if (entry->protocol &&
  920.           strcmp (gftp_protocols[i].name, entry->protocol) == 0)
  921. num = i;
  922.     }
  923.   gtk_option_menu_set_menu (GTK_OPTION_MENU (menu), bm_protocol);
  924.   gtk_option_menu_set_history (GTK_OPTION_MENU (menu), num);
  925.   tempwid = gtk_label_new (_("Remote Directory:"));
  926.   gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
  927.   gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 4, 5);
  928.   gtk_widget_show (tempwid);
  929.   bm_remotediredit = gtk_entry_new ();
  930.   gtk_table_attach_defaults (GTK_TABLE (table), bm_remotediredit, 1, 2, 4, 5);
  931.   if (entry->isfolder)
  932.     gtk_widget_set_sensitive (bm_remotediredit, 0);
  933.   else if (entry->remote_dir)
  934.     gtk_entry_set_text (GTK_ENTRY (bm_remotediredit), entry->remote_dir);
  935.   gtk_widget_show (bm_remotediredit);
  936.   tempwid = gtk_label_new (_("Local Directory:"));
  937.   gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
  938.   gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 5, 6);
  939.   gtk_widget_show (tempwid);
  940.   bm_localdiredit = gtk_entry_new ();
  941.   gtk_table_attach_defaults (GTK_TABLE (table), bm_localdiredit, 1, 2, 5, 6);
  942.   if (entry->isfolder)
  943.     gtk_widget_set_sensitive (bm_localdiredit, 0);
  944.   else if (entry->local_dir)
  945.     gtk_entry_set_text (GTK_ENTRY (bm_localdiredit), entry->local_dir);
  946.   gtk_widget_show (bm_localdiredit);
  947.   tempwid = gtk_label_new (_("Remote SSH sftp path:"));
  948.   gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
  949.   gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 6, 7);
  950.   gtk_widget_show (tempwid);
  951.   bm_sftppath = gtk_entry_new ();
  952.   gtk_table_attach_defaults (GTK_TABLE (table), bm_sftppath, 1, 2, 6, 7);
  953.   if (entry->isfolder)
  954.     gtk_widget_set_sensitive (bm_sftppath, 0);
  955.   else if (entry->sftpserv_path)
  956.     gtk_entry_set_text (GTK_ENTRY (bm_sftppath), entry->sftpserv_path);
  957.   gtk_widget_show (bm_sftppath);
  958.   tempwid = gtk_hseparator_new ();
  959.   gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 2, 7, 8);
  960.   gtk_widget_show (tempwid);
  961.   tempwid = gtk_label_new (_("Username:"));
  962.   gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
  963.   gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 8, 9);
  964.   gtk_widget_show (tempwid);
  965.   bm_useredit = gtk_entry_new ();
  966.   gtk_table_attach_defaults (GTK_TABLE (table), bm_useredit, 1, 2, 8, 9);
  967.   if (entry->isfolder)
  968.     gtk_widget_set_sensitive (bm_useredit, 0);
  969.   else if (entry->user)
  970.     gtk_entry_set_text (GTK_ENTRY (bm_useredit), entry->user);
  971.   gtk_widget_show (bm_useredit);
  972.   tempwid = gtk_label_new (_("Password:"));
  973.   gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
  974.   gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 9, 10);
  975.   gtk_widget_show (tempwid);
  976.   bm_passedit = gtk_entry_new ();
  977.   gtk_table_attach_defaults (GTK_TABLE (table), bm_passedit, 1, 2, 9, 10);
  978.   gtk_entry_set_visibility (GTK_ENTRY (bm_passedit), FALSE);
  979.   if (entry->isfolder)
  980.     gtk_widget_set_sensitive (bm_passedit, 0);
  981.   else if (entry->pass)
  982.     gtk_entry_set_text (GTK_ENTRY (bm_passedit), entry->pass);
  983.   gtk_widget_show (bm_passedit);
  984.   tempwid = gtk_label_new (_("Account:"));
  985.   gtk_misc_set_alignment (GTK_MISC (tempwid), 1, 0.5);
  986.   gtk_table_attach_defaults (GTK_TABLE (table), tempwid, 0, 1, 10, 11);
  987.   gtk_widget_show (tempwid);
  988.   bm_acctedit = gtk_entry_new ();
  989.   gtk_table_attach_defaults (GTK_TABLE (table), bm_acctedit, 1, 2, 10, 11);
  990.   gtk_entry_set_visibility (GTK_ENTRY (bm_acctedit), FALSE);
  991.   if (entry->isfolder)
  992.     gtk_widget_set_sensitive (bm_acctedit, 0);
  993.   else if (entry->acct)
  994.     gtk_entry_set_text (GTK_ENTRY (bm_acctedit), entry->acct);
  995.   gtk_widget_show (bm_acctedit);
  996.   anon_chk = gtk_check_button_new_with_label (_("Log in as ANONYMOUS"));
  997.   gtk_table_attach_defaults (GTK_TABLE (table), anon_chk, 0, 2, 11, 12);
  998.   if (entry->isfolder)
  999.     gtk_widget_set_sensitive (anon_chk, 0);
  1000.   else
  1001.     {
  1002.       gtk_signal_connect (GTK_OBJECT (anon_chk), "toggled",
  1003.   GTK_SIGNAL_FUNC (set_userpass_visible), NULL);
  1004.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (anon_chk), entry->user
  1005.     && strcmp (entry->user, "anonymous") == 0);
  1006.     }
  1007.   gtk_widget_show (anon_chk);
  1008. #if GTK_MAJOR_VERSION == 1
  1009.   tempwid = gtk_button_new_with_label (_("OK"));
  1010.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
  1011.       TRUE, TRUE, 0);
  1012.   gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
  1013.       GTK_SIGNAL_FUNC (entry_apply_changes),
  1014.       (gpointer) entry);
  1015.   gtk_signal_connect_object (GTK_OBJECT (tempwid), "clicked",
  1016.      GTK_SIGNAL_FUNC (gtk_widget_destroy),
  1017.      GTK_OBJECT (dialog));
  1018.   GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
  1019.   gtk_widget_show (tempwid);
  1020.   tempwid = gtk_button_new_with_label (_("  Cancel  "));
  1021.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
  1022.       TRUE, TRUE, 0);
  1023.   gtk_signal_connect_object (GTK_OBJECT (tempwid), "clicked",
  1024.      GTK_SIGNAL_FUNC (gtk_widget_destroy),
  1025.      GTK_OBJECT (dialog));
  1026.   GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
  1027.   gtk_widget_grab_focus (tempwid);
  1028.   gtk_widget_show (tempwid);
  1029.   tempwid = gtk_button_new_with_label (_("Apply"));
  1030.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
  1031.       TRUE, TRUE, 0);
  1032.   gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
  1033.       GTK_SIGNAL_FUNC (entry_apply_changes),
  1034.       (gpointer) entry);
  1035.   GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
  1036.   gtk_widget_show (tempwid);
  1037. #else
  1038.   g_signal_connect (GTK_OBJECT (dialog), "response",
  1039.                     G_CALLBACK (bmedit_action), (gpointer) entry);
  1040. #endif
  1041.   gtk_widget_show (dialog);
  1042. }
  1043. static gint
  1044. bm_enter (GtkWidget * widget, GdkEventKey * event, gpointer data)
  1045. {
  1046.   if (event->type == GDK_KEY_PRESS)
  1047.     {
  1048.       if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter)
  1049. {
  1050.   edit_entry (NULL);
  1051.   return (FALSE);
  1052. }
  1053.       else if (event->keyval == GDK_KP_Delete || event->keyval == GDK_Delete)
  1054. {
  1055.   delete_entry (NULL);
  1056.   return (FALSE);
  1057. }
  1058.     }
  1059.   return (TRUE);
  1060. }
  1061. static void
  1062. after_move (GtkCTree * ctree, GtkCTreeNode * child, GtkCTreeNode * parent,
  1063.     GtkCTreeNode * sibling, gpointer data)
  1064. {
  1065.   gftp_bookmarks * childentry, * siblingentry, * parententry, * tempentry;
  1066.   char *tempstr, *pos, *stpos;
  1067.   childentry = gtk_ctree_node_get_row_data (ctree, child);
  1068.   parententry = gtk_ctree_node_get_row_data (ctree, parent);
  1069.   siblingentry = gtk_ctree_node_get_row_data (ctree, sibling);
  1070.   tempentry = childentry->prev->children;
  1071.   if (tempentry == childentry)
  1072.     childentry->prev->children = childentry->prev->children->next;
  1073.   else
  1074.     {
  1075.       while (tempentry->next != childentry)
  1076. tempentry = tempentry->next;
  1077.       tempentry->next = childentry->next;
  1078.     }
  1079.   childentry->prev = parententry;
  1080.   if (!parententry->isfolder)
  1081.     {
  1082.       childentry->next = parententry->children;
  1083.       parententry->children = childentry;
  1084.       gtk_ctree_move (ctree, child, parententry->prev->cnode,
  1085.       parententry->cnode);
  1086.     }
  1087.   else
  1088.     {
  1089.       if (siblingentry == NULL || parententry->children == siblingentry)
  1090. {
  1091.   childentry->next = parententry->children;
  1092.   parententry->children = childentry;
  1093. }
  1094.       else
  1095. {
  1096.   tempentry = parententry->children;
  1097.   while (tempentry->next != siblingentry)
  1098.     tempentry = tempentry->next;
  1099.   childentry->next = tempentry->next;
  1100.   tempentry->next = childentry;
  1101. }
  1102.       tempentry = childentry;
  1103.       while (tempentry != NULL)
  1104. {
  1105.   g_hash_table_remove (new_bookmarks_htable, tempentry->path);
  1106.   if ((pos = strrchr (tempentry->path, '/')) == NULL)
  1107.     pos = tempentry->path;
  1108.   else
  1109.     pos++;
  1110.   tempstr = g_strdup_printf ("%s/%s", tempentry->prev->path, pos);
  1111.   for (stpos = tempstr; *stpos == '/'; stpos++);
  1112.   g_free (tempentry->path);
  1113.   tempentry->path = g_malloc (strlen (stpos) + 1);
  1114.   strcpy (tempentry->path, stpos);
  1115.   g_free (tempstr);
  1116.   g_hash_table_insert (new_bookmarks_htable, tempentry->path,
  1117.        tempentry);
  1118.   if (tempentry->children != NULL)
  1119.     tempentry = tempentry->children;
  1120.   else
  1121.     {
  1122.       if (tempentry->next == NULL)
  1123. {
  1124.   if (tempentry->prev == childentry)
  1125.     break;
  1126.   else
  1127.     {
  1128.       while (tempentry->next == NULL
  1129.      && tempentry->prev != NULL)
  1130. tempentry = tempentry->prev;
  1131.     }
  1132. }
  1133.       tempentry = tempentry->next;
  1134.     }
  1135. }
  1136.     }
  1137. }
  1138. static gint
  1139. bm_dblclick (GtkWidget * widget, GdkEventButton * event, gpointer data)
  1140. {
  1141.   if (event->button == 3)
  1142.     gtk_item_factory_popup (edit_factory, (guint) event->x_root,
  1143.     (guint) event->y_root, 1, 0);
  1144.   else if (event->type == GDK_2BUTTON_PRESS)
  1145.     {
  1146.       edit_entry (NULL);
  1147.       return (FALSE);
  1148.     }
  1149.   return (TRUE);
  1150. }
  1151. void
  1152. edit_bookmarks (gpointer data)
  1153. {
  1154.   GtkWidget * dialog, * scroll;
  1155.   GtkItemFactory * ifactory;
  1156.   GtkItemFactoryEntry menu_items[] = {
  1157.     {N_("/_File"), NULL, 0, 0, "<Branch>"},
  1158.     {N_("/File/tearoff"), NULL, 0, 0, "<Tearoff>"},
  1159.     {N_("/File/New Folder..."), NULL, new_folder_entry, 0, MN_(NULL)},
  1160.     {N_("/File/New Item..."), NULL, new_item_entry, 0, MS_(GTK_STOCK_NEW)},
  1161.     {N_("/File/Delete"), NULL, delete_entry, 0, MS_(GTK_STOCK_DELETE)},
  1162.     {N_("/File/Properties..."), NULL, edit_entry, 0, MS_(GTK_STOCK_PROPERTIES)},
  1163.     {N_("/File/sep"), NULL, 0, 0, "<Separator>"},
  1164.     {N_("/File/Close"), NULL, gtk_widget_destroy, 0, MS_(GTK_STOCK_CLOSE)}
  1165.   };
  1166. #if GTK_MAJOR_VERSION == 1
  1167.   GtkWidget * tempwid;
  1168. #endif
  1169.   new_bookmarks = copy_bookmarks (bookmarks);
  1170.   new_bookmarks_htable = build_bookmarks_hash_table (new_bookmarks);
  1171. #if GTK_MAJOR_VERSION == 1
  1172.   dialog = gtk_dialog_new ();
  1173.   gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Bookmarks"));
  1174.   gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 15);
  1175. #else
  1176.   dialog = gtk_dialog_new_with_buttons (_("Edit Bookmarks"), NULL, 0,
  1177.                                         GTK_STOCK_SAVE,
  1178.                                         GTK_RESPONSE_OK,
  1179.                                         GTK_STOCK_CANCEL,
  1180.                                         GTK_RESPONSE_CANCEL,
  1181.                                         NULL);
  1182. #endif
  1183.   gtk_window_set_wmclass (GTK_WINDOW(dialog), "Edit Bookmarks", "gFTP");
  1184.   gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
  1185.   gtk_widget_realize (dialog);
  1186.   if (gftp_icon != NULL)
  1187.     {
  1188.       gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap,
  1189.                            gftp_icon->bitmap);
  1190.       gdk_window_set_icon_name (dialog->window, _("gFTP Icon"));
  1191.     }
  1192.   /* FIXME - memory leak */
  1193.   ifactory = item_factory_new (GTK_TYPE_MENU_BAR, "<bookmarks>", NULL, NULL);
  1194.   create_item_factory (ifactory, 7, menu_items, NULL);
  1195.   create_item_factory (ifactory, 1, menu_items + 7, dialog);
  1196.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), ifactory->widget,
  1197.       FALSE, FALSE, 0);
  1198.   gtk_widget_show (ifactory->widget);
  1199.   scroll = gtk_scrolled_window_new (NULL, NULL);
  1200.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
  1201.   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  1202.   gtk_widget_set_size_request (scroll, 150, 200);
  1203.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), scroll, TRUE, TRUE,
  1204.       0);
  1205.   gtk_container_border_width (GTK_CONTAINER (scroll), 3);
  1206.   gtk_widget_show (scroll);
  1207.   /* FIXME - memory leak */
  1208.   edit_factory = item_factory_new (GTK_TYPE_MENU, "<edit_bookmark>", NULL, "/File");
  1209.   create_item_factory (edit_factory, 6, menu_items + 2, dialog);
  1210.   tree = gtk_ctree_new (1, 0);
  1211.   gtk_clist_set_selection_mode (GTK_CLIST (tree), GTK_SELECTION_BROWSE);
  1212.   gtk_clist_set_reorderable (GTK_CLIST (tree), 1);
  1213.   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scroll), tree);
  1214.   gtk_signal_connect_after (GTK_OBJECT (tree), "key_press_event",
  1215.     GTK_SIGNAL_FUNC (bm_enter), (gpointer) tree);
  1216.   gtk_signal_connect_after (GTK_OBJECT (tree), "tree_move",
  1217.     GTK_SIGNAL_FUNC (after_move), NULL);
  1218.   gtk_signal_connect_after (GTK_OBJECT (tree), "button_press_event",
  1219.     GTK_SIGNAL_FUNC (bm_dblclick), (gpointer) tree);
  1220.   gtk_widget_show (tree);
  1221. #if GTK_MAJOR_VERSION == 1
  1222.   tempwid = gtk_button_new_with_label (_("OK"));
  1223.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
  1224.       TRUE, TRUE, 0);
  1225.   gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
  1226.       GTK_SIGNAL_FUNC (bm_apply_changes), NULL);
  1227.   gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
  1228.       GTK_SIGNAL_FUNC (bm_close_dialog), (gpointer) dialog);
  1229.   GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
  1230.   gtk_widget_show (tempwid);
  1231.   tempwid = gtk_button_new_with_label (_("  Cancel  "));
  1232.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), tempwid,
  1233.       TRUE, TRUE, 0);
  1234.   gtk_signal_connect (GTK_OBJECT (tempwid), "clicked",
  1235.       GTK_SIGNAL_FUNC (bm_close_dialog), (gpointer) dialog);
  1236.   GTK_WIDGET_SET_FLAGS (tempwid, GTK_CAN_DEFAULT);
  1237.   gtk_widget_grab_focus (tempwid);
  1238.   gtk_widget_show (tempwid);
  1239. #else
  1240.   g_signal_connect (GTK_OBJECT (dialog), "response",
  1241.                     G_CALLBACK (editbm_action), NULL);
  1242. #endif
  1243.   gtk_widget_show (dialog);
  1244.   build_bookmarks_tree ();
  1245. }