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

Ftp客户端

开发平台:

Visual C++

  1. /*****************************************************************************/
  2. /*  gftp-gtk.c - GTK+ 1.2 port of gftp                                       */
  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: gftp-gtk.c,v 1.20 2002/11/23 13:45:05 masneyb Exp $";
  21. static GtkItemFactory *log_factory, *dl_factory;
  22. static GtkWidget * local_frame, * remote_frame, * log_table, * transfer_scroll,
  23.                  * openurl_btn;
  24. gftp_window_data window1, window2, *other_wdata, *current_wdata;
  25. GtkWidget * stop_btn, * hostedit, * useredit, * passedit, * portedit, * logwdw,
  26.           * dlwdw, * protocol_menu, * optionmenu;
  27. GtkAdjustment * logwdw_vadj;
  28. #if GTK_MAJOR_VERSION > 1
  29. GtkTextMark * logwdw_textmark;
  30. #endif
  31. int local_start, remote_start, trans_start, log_start, tools_start;
  32. GHashTable * graphic_hash_table = NULL;
  33. GtkItemFactoryEntry * menus = NULL;
  34. GtkItemFactory * factory = NULL;
  35. pthread_mutex_t transfer_mutex = PTHREAD_MUTEX_INITIALIZER;
  36. pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
  37. gftp_graphic * gftp_icon;
  38. sigjmp_buf jmp_environment;
  39. volatile int use_jmp_environment = 0;
  40. pthread_t main_thread_id;
  41. static int
  42. get_column (GtkCListColumn * col)
  43. {
  44.   if (col->auto_resize)
  45.     return (0);
  46.   else if (!col->visible)
  47.     return (-1);
  48.   else
  49.     return (col->width);
  50. }
  51. static void
  52. doexit (GtkWidget * widget, gpointer data)
  53. {
  54.   listbox_local_width = GTK_WIDGET (local_frame)->allocation.width;
  55.   listbox_remote_width = GTK_WIDGET (remote_frame)->allocation.width;
  56.   listbox_file_height = GTK_WIDGET (remote_frame)->allocation.height;
  57.   log_height = GTK_WIDGET (log_table)->allocation.height;
  58.   transfer_height = GTK_WIDGET (transfer_scroll)->allocation.height;
  59.   local_columns[0] = get_column (&GTK_CLIST (window1.listbox)->column[1]);
  60.   local_columns[1] = get_column (&GTK_CLIST (window1.listbox)->column[2]);
  61.   local_columns[2] = get_column (&GTK_CLIST (window1.listbox)->column[3]);
  62.   local_columns[3] = get_column (&GTK_CLIST (window1.listbox)->column[4]);
  63.   local_columns[4] = get_column (&GTK_CLIST (window1.listbox)->column[5]);
  64.   local_columns[5] = get_column (&GTK_CLIST (window1.listbox)->column[6]);
  65.   remote_columns[0] = get_column (&GTK_CLIST (window2.listbox)->column[1]);
  66.   remote_columns[1] = get_column (&GTK_CLIST (window2.listbox)->column[2]);
  67.   remote_columns[2] = get_column (&GTK_CLIST (window2.listbox)->column[3]);
  68.   remote_columns[3] = get_column (&GTK_CLIST (window2.listbox)->column[4]);
  69.   remote_columns[4] = get_column (&GTK_CLIST (window2.listbox)->column[5]);
  70.   remote_columns[5] = get_column (&GTK_CLIST (window2.listbox)->column[6]);
  71.   file_trans_column = get_column (&GTK_CLIST (dlwdw)->column[0]);
  72.   gftp_write_config_file ();
  73.   gftp_clear_cache_files ();
  74.   exit (0);
  75. }
  76. static gint
  77. delete_event (GtkWidget * widget, GdkEvent * event, gpointer data)
  78. {
  79.   if (file_transfers == NULL)
  80.     doexit (NULL, NULL);
  81.   else
  82.     {
  83.       MakeYesNoDialog (_("Exit"), _("There are file transfers in progress.nAre you sure you want to exit?"), doexit, NULL, NULL, NULL);
  84.       return (TRUE);
  85.     }
  86.   return (FALSE);
  87. }
  88. static void
  89. destroy (GtkWidget * widget, gpointer data)
  90. {
  91.   exit (0);
  92. }
  93. static RETSIGTYPE
  94. sig_child (int signo)
  95. {
  96.   viewedit_process_done = 1;
  97. }
  98. static void
  99. menu_exit (GtkWidget * widget, gpointer data)
  100. {
  101.   if (!delete_event (widget, NULL, data))
  102.     doexit (widget, data);
  103. }
  104. static void
  105. chfunc (gpointer data)
  106. {
  107.   chdir_dialog (data);
  108. }
  109. static GtkWidget *
  110. CreateMenus (GtkWidget * parent)
  111. {
  112.   int local_len, remote_len, len, i, trans_len, log_len, tools_len;
  113.   GtkAccelGroup *accel_group;
  114.   GtkWidget * tempwid;
  115.   static GtkItemFactoryEntry menu_items[] = {
  116.     {N_("/_FTP"), NULL, 0, 0, MN_("<Branch>")},
  117.     {N_("/FTP/tearoff"), NULL, 0, 0, MN_("<Tearoff>")},
  118.     {N_("/FTP/Window 1"), NULL, change_setting, 3, MN_("<RadioItem>")},
  119.     {N_("/FTP/Window 2"), NULL, change_setting, 4, MN_("/FTP/Window 1")},
  120.     {N_("/FTP/sep"), NULL, 0, 0, MN_("<Separator>")},
  121.     {N_("/FTP/Ascii"), NULL, change_setting, 1, MN_("<RadioItem>")},
  122.     {N_("/FTP/Binary"), NULL, change_setting, 2, MN_("/FTP/Ascii")},
  123.     {N_("/FTP/sep"), NULL, 0, 0, MN_("<Separator>")},
  124.     {N_("/FTP/_Options..."), "<control>O", options_dialog, 0,
  125. MS_(GTK_STOCK_PREFERENCES)},
  126.     {N_("/FTP/sep"), NULL, 0, 0, MN_("<Separator>")},
  127.     {N_("/FTP/_Quit"), "<control>Q", menu_exit, 0, MS_(GTK_STOCK_QUIT)},
  128.     {N_("/_Local"), NULL, 0, 0, MN_("<Branch>")},
  129.     {N_("/Local/tearoff"), NULL, 0, 0, MN_("<Tearoff>")},
  130.     {N_("/Local/Open _URL..."), NULL, openurl_dialog, 0, MS_(GTK_STOCK_OPEN)},
  131.     {N_("/Local/Disconnect"), NULL, disconnect, 0, MS_(GTK_STOCK_CLOSE)},
  132.     {N_("/Local/sep"), NULL, 0, 0, MN_("<Separator>")},
  133.     {N_("/Local/Change Filespec..."), NULL, change_filespec, 0, MN_(NULL)},
  134.     {N_("/Local/Show selected"), NULL, show_selected, 0, MN_(NULL)},
  135.     {N_("/Local/Select All"), NULL, selectall, 0, MN_(NULL)},
  136.     {N_("/Local/Select All Files"), NULL, selectallfiles, 0, MN_(NULL)},
  137.     {N_("/Local/Deselect All"), NULL, deselectall, 0, MN_(NULL)},
  138.     {N_("/Local/sep"), NULL, 0, 0, MN_("<Separator>")},
  139.     {N_("/Local/Save Directory Listing..."), NULL, save_directory_listing, 0, MN_(NULL)},
  140.     {N_("/Local/Send SITE Command..."), NULL, site_dialog, 0, MN_(NULL)},
  141.     {N_("/Local/Change Directory"), NULL, chfunc, 0, MN_(NULL)},
  142.     {N_("/Local/Chmod..."), NULL, chmod_dialog, 0, MN_(NULL)},
  143.     {N_("/Local/Make Directory..."), NULL, mkdir_dialog, 0, MN_(NULL)},
  144.     {N_("/Local/Rename..."), NULL, rename_dialog, 0, MN_(NULL)},
  145.     {N_("/Local/Delete..."), NULL, delete_dialog, 0, MN_(NULL)},
  146.     {N_("/Local/Edit..."), NULL, edit_dialog, 0, MN_(NULL)},
  147.     {N_("/Local/View..."), NULL, view_dialog, 0, MN_(NULL)},
  148.     {N_("/Local/Refresh"), NULL, refresh, 0, MS_(GTK_STOCK_REFRESH)},
  149.     {N_("/_Remote"), NULL, 0, 0, MN_("<Branch>")},
  150.     {N_("/Remote/tearoff"), NULL, 0, 0, MN_("<Tearoff>")},
  151.     {N_("/Remote/Open _URL..."), "<control>U", openurl_dialog, 0,
  152. MS_(GTK_STOCK_OPEN)},
  153.     {N_("/Remote/Disconnect"), "<control>D", disconnect, 0,
  154. MS_(GTK_STOCK_CLOSE)},
  155.     {N_("/Remote/sep"), NULL, 0, 0, MN_("<Separator>")},
  156.     {N_("/Remote/Change Filespec..."), NULL, change_filespec, 0, MN_(NULL)},
  157.     {N_("/Remote/Show selected"), NULL, show_selected, 0, MN_(NULL)},
  158.     {N_("/Remote/Select All"), NULL, selectall, 0, MN_(NULL)},
  159.     {N_("/Remote/Select All Files"), NULL, selectallfiles, 0, MN_(NULL)},
  160.     {N_("/Remote/Deselect All"), NULL, deselectall, 0, MN_(NULL)},
  161.     {N_("/Remote/sep"), NULL, 0, 0, MN_("<Separator>")},
  162.     {N_("/Remote/Save Directory Listing..."), NULL, save_directory_listing, 0, MN_(NULL)},
  163.     {N_("/Remote/Send SITE Command..."), NULL, site_dialog, 0, MN_(NULL)},
  164.     {N_("/Remote/Change Directory"), NULL, chfunc, 0, MN_(NULL)},
  165.     {N_("/Remote/Chmod..."), NULL, chmod_dialog, 0, MN_(NULL)},
  166.     {N_("/Remote/Make Directory..."), NULL, mkdir_dialog, 0, MN_(NULL)},
  167.     {N_("/Remote/Rename..."), NULL, rename_dialog, 0, MN_(NULL)},
  168.     {N_("/Remote/Delete..."), NULL, delete_dialog, 0, MN_(NULL)},
  169.     {N_("/Remote/Edit..."), NULL, edit_dialog, 0, MN_(NULL)},
  170.     {N_("/Remote/View..."), NULL, view_dialog, 0, MN_(NULL)},
  171.     {N_("/Remote/Refresh"), NULL, refresh, 0, MS_(GTK_STOCK_REFRESH)},
  172.     {N_("/_Bookmarks"), NULL, 0, 0, MN_("<Branch>")},
  173.     {N_("/Bookmarks/tearoff"), NULL, 0, 0, MN_("<Tearoff>")},
  174.     {N_("/Bookmarks/Add bookmark"), "<control>A", add_bookmark, 0,
  175. MS_(GTK_STOCK_ADD)},
  176.     {N_("/Bookmarks/Edit bookmarks"), NULL, edit_bookmarks, 0, MN_(NULL)},
  177.     {N_("/Bookmarks/sep"), NULL, 0, 0, MN_("<Separator>")},
  178.     {N_("/_Transfers"), NULL, 0, 0, MN_("<Branch>")},
  179.     {N_("/Transfers/tearoff"), NULL, 0, 0, MN_("<Tearoff>")},
  180.     {N_("/Transfers/Start Transfer"), NULL, start_transfer, 0, MN_(NULL)},
  181.     {N_("/Transfers/Stop Transfer"), NULL, stop_transfer, 0,
  182. MS_(GTK_STOCK_STOP)},
  183.     {N_("/Transfers/sep"), NULL, 0, 0, MN_("<Separator>")},
  184.     {N_("/Transfers/Skip Current File"), NULL, skip_transfer, 0, MN_(NULL)},
  185.     {N_("/Transfers/Remove File"), NULL, remove_file_transfer, 0,
  186. MS_(GTK_STOCK_DELETE)},
  187.     {N_("/Transfers/Move File _Up"), NULL, move_transfer_up, 0,
  188. MS_(GTK_STOCK_GO_UP)},
  189.     {N_("/Transfers/Move File _Down"), NULL, move_transfer_down, 0,
  190. MS_(GTK_STOCK_GO_DOWN)},
  191.     {N_("/Transfers/sep"), NULL, 0, 0, MN_("<Separator>")},
  192.     {N_("/Transfers/Retrieve Files"), "<control>R", get_files, 0, MN_(NULL)},
  193.     {N_("/Transfers/Put Files"), "<control>P", put_files, 0, MN_(NULL)},
  194.     {N_("/L_ogging"), NULL, 0, 0, MN_("<Branch>")},
  195.     {N_("/Logging/tearoff"), NULL, 0, 0, MN_("<Tearoff>")},
  196.     {N_("/Logging/Clear"), NULL, clearlog, 0, MS_(GTK_STOCK_CLEAR)},
  197.     {N_("/Logging/View log..."), NULL, viewlog, 0, MN_(NULL)},
  198.     {N_("/Logging/Save log..."), NULL, savelog, 0, MS_(GTK_STOCK_SAVE)},
  199.     {N_("/Tool_s"), NULL, 0, 0, MN_("<Branch>")},
  200.     {N_("/Tools/tearoff"), NULL, 0, 0, MN_("<Tearoff>")},
  201.     {N_("/Tools/Compare Windows"), NULL, compare_windows, 0, MN_(NULL)},
  202.     {N_("/Tools/Clear Cache"), NULL, clear_cache, 0, MS_(GTK_STOCK_CLEAR)},
  203.     {N_("/_Help"), NULL, 0, 0, MN_("<LastBranch>")},
  204.     {N_("/Help/tearoff"), NULL, 0, 0, MN_("<Tearoff>")},
  205.     {N_("/Help/About..."), NULL, about_dialog, 0, MS_(GTK_STOCK_HELP)}
  206.   };
  207.   menus = menu_items;
  208.   accel_group = gtk_accel_group_new ();
  209.   factory = item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group, NULL);
  210.   i = 0;
  211.   len = 11;
  212.   /* FTP Menu */
  213.   create_item_factory (factory, len, menu_items, &window2);
  214.   i += len;
  215.   /* Local Menu */
  216.   local_start = i;
  217.   local_len = 21;
  218.   create_item_factory (factory, local_len, menu_items + i, &window1);
  219.   i += local_len;
  220.   /* Remote Menu */
  221.   remote_start = i;
  222.   remote_len = 21;
  223.   create_item_factory (factory, remote_len, menu_items + i, &window2);
  224.   i += remote_len;
  225.   len = 5;
  226.   /* Bookmarks Menu */
  227.   create_item_factory (factory, len, menu_items + i, &window2);
  228.   i += len;
  229.   /* Transfers Menu */
  230.   trans_start = i;
  231.   trans_len = 12;
  232.   create_item_factory (factory, trans_len, menu_items + i, NULL);
  233.   i += trans_len;
  234.   /* Logging Menu */
  235.   log_start = i;
  236.   log_len = 5;
  237.   create_item_factory (factory, log_len, menu_items + i, NULL);
  238.   i += log_len;
  239.   /* Tools Menu */
  240.   tools_start = i;
  241.   tools_len = 4;
  242.   create_item_factory (factory, tools_len, menu_items + i, NULL);
  243.   i += tools_len;
  244.   /* Help Menu */
  245.   create_item_factory (factory, 3, menu_items + i, NULL);
  246.   build_bookmarks_menu ();
  247.   gtk_window_add_accel_group (GTK_WINDOW (parent), accel_group);
  248.   tempwid = gtk_item_factory_get_widget (factory, menu_items[6].path);
  249.   gtk_check_menu_item_set_state (GTK_CHECK_MENU_ITEM (tempwid), TRUE);
  250.   tempwid = gtk_item_factory_get_widget (factory, menu_items[3].path);
  251.   gtk_check_menu_item_set_state (GTK_CHECK_MENU_ITEM (tempwid), TRUE);
  252.   window1.ifactory = item_factory_new (GTK_TYPE_MENU, "<local>", NULL, "/Local");
  253.   create_item_factory (window1.ifactory, local_len - 2, menu_items + local_start + 2, &window1);
  254.   window2.ifactory = item_factory_new (GTK_TYPE_MENU, "<remote>", NULL, "/Remote");
  255.   create_item_factory (window2.ifactory, remote_len - 2, menu_items + remote_start + 2, &window2);
  256.   log_factory = item_factory_new (GTK_TYPE_MENU, "<log>", NULL, "/Logging");
  257.   create_item_factory (log_factory, log_len - 2, menu_items + log_start + 2, NULL);
  258.   dl_factory = item_factory_new (GTK_TYPE_MENU, "<download>", NULL, "/Transfers");
  259.   create_item_factory (dl_factory, trans_len - 2, menu_items + trans_start + 2, NULL);
  260.   return (factory->widget);
  261. }
  262. static GtkWidget *
  263. CreateToolbar (GtkWidget * parent)
  264. {
  265.   const GtkTargetEntry possible_types[] = {
  266.     {"STRING", 0, 0},
  267.     {"text/plain", 0, 0},
  268.     {"application/x-rootwin-drop", 0, 1}
  269.   };
  270.   GtkWidget *toolbar, *box, *tempwid;
  271.   int i, num;
  272.   toolbar = gtk_handle_box_new ();
  273.   box = gtk_hbox_new (FALSE, 4);
  274.   gtk_container_add (GTK_CONTAINER (toolbar), box);
  275.   gtk_container_border_width (GTK_CONTAINER (box), 5);
  276.   tempwid = toolbar_pixmap (parent, "connect.xpm");
  277.   openurl_btn = gtk_button_new ();
  278.   gtk_container_add (GTK_CONTAINER (openurl_btn), tempwid);
  279.   gtk_signal_connect_object (GTK_OBJECT (openurl_btn), "clicked",
  280.      GTK_SIGNAL_FUNC (tb_openurl_dialog), NULL);
  281.   gtk_signal_connect (GTK_OBJECT (openurl_btn), "drag_data_received",
  282.       GTK_SIGNAL_FUNC (openurl_get_drag_data), NULL);
  283.   gtk_drag_dest_set (openurl_btn, GTK_DEST_DEFAULT_ALL, possible_types, 2,
  284.      GDK_ACTION_COPY | GDK_ACTION_MOVE);
  285.   gtk_container_border_width (GTK_CONTAINER (openurl_btn), 1);
  286.   gtk_box_pack_start (GTK_BOX (box), openurl_btn, FALSE, FALSE, 0);
  287.   tempwid = gtk_label_new (_("Host: "));
  288.   gtk_box_pack_start (GTK_BOX (box), tempwid, FALSE, FALSE, 0);
  289.   hostedit = gtk_combo_new ();
  290.   gtk_combo_set_case_sensitive (GTK_COMBO (hostedit), 1);
  291.   gtk_widget_set_size_request (hostedit, 130, -1);
  292.   gtk_signal_connect (GTK_OBJECT (GTK_COMBO (hostedit)->entry), "activate",
  293.       GTK_SIGNAL_FUNC (toolbar_hostedit), NULL);
  294.   if (host_history)
  295.     gtk_combo_set_popdown_strings (GTK_COMBO (hostedit), host_history);
  296.   gtk_combo_disable_activate (GTK_COMBO (hostedit));
  297.   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (hostedit)->entry), "");
  298.   gtk_box_pack_start (GTK_BOX (box), hostedit, TRUE, TRUE, 0);
  299.   tempwid = gtk_label_new (_("Port: "));
  300.   gtk_box_pack_start (GTK_BOX (box), tempwid, FALSE, FALSE, 0);
  301.   portedit = gtk_combo_new ();
  302.   gtk_combo_set_case_sensitive (GTK_COMBO (portedit), 1);
  303.   gtk_widget_set_size_request (portedit, 45, -1);
  304.   gtk_signal_connect (GTK_OBJECT (GTK_COMBO (portedit)->entry), "activate",
  305.       GTK_SIGNAL_FUNC (toolbar_hostedit), NULL);
  306.   if (port_history)
  307.     gtk_combo_set_popdown_strings (GTK_COMBO (portedit), port_history);
  308.   gtk_combo_disable_activate (GTK_COMBO (portedit));
  309.   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (portedit)->entry), "");
  310.   gtk_box_pack_start (GTK_BOX (box), portedit, FALSE, FALSE, 0);
  311.   tempwid = gtk_label_new (_("User: "));
  312.   gtk_box_pack_start (GTK_BOX (box), tempwid, FALSE, FALSE, 0);
  313.   useredit = gtk_combo_new ();
  314.   gtk_combo_set_case_sensitive (GTK_COMBO (useredit), 1);
  315.   gtk_widget_set_size_request (useredit, 75, -1);
  316.   gtk_signal_connect (GTK_OBJECT (GTK_COMBO (useredit)->entry), "activate",
  317.       GTK_SIGNAL_FUNC (toolbar_hostedit), NULL);
  318.   if (user_history)
  319.     gtk_combo_set_popdown_strings (GTK_COMBO (useredit), user_history);
  320.   gtk_combo_disable_activate (GTK_COMBO (useredit));
  321.   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (useredit)->entry), "");
  322.   gtk_box_pack_start (GTK_BOX (box), useredit, TRUE, TRUE, 0);
  323.   tempwid = gtk_label_new (_("Pass: "));
  324.   gtk_box_pack_start (GTK_BOX (box), tempwid, FALSE, FALSE, 0);
  325.   passedit = gtk_entry_new ();
  326.   gtk_widget_set_size_request (passedit, 55, -1);
  327.   gtk_entry_set_visibility (GTK_ENTRY (passedit), FALSE);
  328.   gtk_signal_connect (GTK_OBJECT (passedit), "activate",
  329.       GTK_SIGNAL_FUNC (toolbar_hostedit), NULL);
  330.   gtk_box_pack_start (GTK_BOX (box), passedit, FALSE, FALSE, 0);
  331.   tempwid = gtk_vbox_new (FALSE, 0);
  332.   gtk_box_pack_start (GTK_BOX (box), tempwid, FALSE, FALSE, 0);
  333.   optionmenu = gtk_option_menu_new ();
  334.   gtk_box_pack_start (GTK_BOX (tempwid), optionmenu, TRUE, FALSE, 0);
  335.   num = 0;
  336.   protocol_menu = gtk_menu_new ();
  337.   for (i = 0; gftp_protocols[i].name; i++)
  338.     {
  339.       if (!gftp_protocols[i].shown)
  340.         continue;
  341.       if (strcmp (gftp_protocols[i].name, default_protocol) == 0)
  342.         num = i;
  343.       tempwid = gtk_menu_item_new_with_label (gftp_protocols[i].name);
  344.       gtk_object_set_user_data (GTK_OBJECT (tempwid), (gpointer) i);
  345.       gtk_menu_append (GTK_MENU (protocol_menu), tempwid);
  346.       gtk_widget_show (tempwid);
  347.     }
  348.   gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), protocol_menu);
  349.   gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), num);
  350. #if GTK_MAJOR_VERSION == 1
  351.   tempwid = toolbar_pixmap (parent, "stop.xpm");
  352. #else
  353.   tempwid = gtk_image_new_from_stock (GTK_STOCK_STOP,
  354.                                       GTK_ICON_SIZE_LARGE_TOOLBAR);
  355. #endif
  356.   stop_btn = gtk_button_new ();
  357.   gtk_container_add (GTK_CONTAINER (stop_btn), tempwid);
  358.   gtk_widget_set_sensitive (stop_btn, 0);
  359.   gtk_signal_connect_object (GTK_OBJECT (stop_btn), "clicked",
  360.      GTK_SIGNAL_FUNC (stop_button), NULL);
  361.   gtk_container_border_width (GTK_CONTAINER (stop_btn), 1);
  362.   gtk_box_pack_start (GTK_BOX (box), stop_btn, FALSE, FALSE, 0);
  363.   return (toolbar);
  364. }
  365. static void
  366. setup_column (GtkWidget * listbox, int column, int width)
  367. {
  368.   if (width == 0)
  369.     gtk_clist_set_column_auto_resize (GTK_CLIST (listbox), column, TRUE);
  370.   else if (width == -1)
  371.     gtk_clist_set_column_visibility (GTK_CLIST (listbox), column, FALSE);
  372.   else
  373.     gtk_clist_set_column_width (GTK_CLIST (listbox), column, width);
  374. }
  375. static void
  376. list_doaction (gftp_window_data * wdata)
  377. {
  378.   GList *templist, *filelist;
  379.   int num, dir, success;
  380.   gftp_file *tempfle;
  381.   filelist = wdata->files;
  382.   templist = GTK_CLIST (wdata->listbox)->selection;
  383.   num = 0;
  384.   templist = get_next_selection (templist, &filelist, &num);
  385.   tempfle = (gftp_file *) filelist->data;
  386.   dir = tempfle->isdir;
  387.   success = 0;
  388.   if (tempfle->islink || tempfle->isdir)
  389.     success = chdir_dialog (wdata);
  390.   if (!dir && !success)
  391.     {
  392.       switch (listbox_dblclick_action)
  393.         {
  394.           case 0:
  395.             view_dialog (wdata);
  396.             break;
  397.           case 1:
  398.             edit_dialog (wdata);
  399.             break;
  400.           case 2:
  401.             if (wdata == &window2)
  402.               get_files (wdata);
  403.             else
  404.               put_files (wdata);
  405.             break;
  406.         }
  407.     }
  408. }
  409. static gint
  410. list_enter (GtkWidget * widget, GdkEventKey * event, gpointer data)
  411. {
  412.   gftp_window_data * wdata;
  413.   wdata = data;
  414.   if (!GFTP_IS_CONNECTED (wdata->request))
  415.     return (TRUE);
  416.   if (event->type == GDK_KEY_PRESS && 
  417.            (event->keyval == GDK_KP_Delete || event->keyval == GDK_Delete))
  418.     {
  419.       delete_dialog (wdata);
  420.       return (FALSE);
  421.     }
  422.   else if (IS_ONE_SELECTED (wdata) && event->type == GDK_KEY_PRESS && 
  423.       event->keyval == GDK_Return)
  424.     {
  425.       list_doaction (wdata);
  426.       return (FALSE);
  427.     }
  428.   return (TRUE);
  429. }
  430. static gint
  431. list_dblclick (GtkWidget * widget, GdkEventButton * event, gpointer data)
  432. {
  433.   gftp_window_data * wdata;
  434.   wdata = data;
  435.   if (event->button == 3)
  436.     gtk_item_factory_popup (wdata->ifactory, (guint) event->x_root,
  437.                             (guint) event->y_root, 3, event->time);
  438.   return (FALSE);
  439. }
  440. void 
  441. select_row_callback (GtkWidget *widget, gint row, gint column,
  442.                      GdkEventButton *event, gpointer data)
  443. {
  444.   gftp_window_data * wdata;
  445.   wdata = data;
  446.   if (event != NULL && event->type == GDK_2BUTTON_PRESS && event->button == 1 &&
  447.       GFTP_IS_CONNECTED (wdata->request) && IS_ONE_SELECTED (wdata))
  448.     list_doaction (wdata);
  449. }
  450. static GtkWidget *
  451. CreateFTPWindow (gftp_window_data * wdata, int width, int columns[6])
  452. {
  453.   const GtkTargetEntry possible_types[] = {
  454.     {"STRING", 0, 0},
  455.     {"text/plain", 0, 0},
  456.     {"application/x-rootwin-drop", 0, 1}
  457.   };
  458.   GtkWidget *box, *scroll_list, *parent;
  459.   char *titles[7];
  460.   titles[0] = "";
  461.   titles[1] = _("Filename");
  462.   titles[2] = _("Size");
  463.   titles[3] = _("User");
  464.   titles[4] = _("Group");
  465.   titles[5] = _("Date");
  466.   titles[6] = _("Attribs");
  467.   wdata->request = gftp_request_new ();
  468.   wdata->request->logging_function = ftp_log;
  469.   wdata->filespec = g_malloc0 (2);
  470.   *wdata->filespec = '*';
  471.   parent = gtk_frame_new (NULL);
  472.   gtk_widget_set_size_request (parent, width, listbox_file_height);
  473.   gtk_container_border_width (GTK_CONTAINER (parent), 5);
  474.   box = gtk_vbox_new (FALSE, 0);
  475.   gtk_container_border_width (GTK_CONTAINER (box), 5);
  476.   gtk_container_add (GTK_CONTAINER (parent), box);
  477.   wdata->combo = gtk_combo_new ();
  478.   gtk_combo_set_case_sensitive (GTK_COMBO (wdata->combo), 1);
  479.   gtk_box_pack_start (GTK_BOX (box), wdata->combo, FALSE, FALSE, 0);
  480.   gtk_signal_connect (GTK_OBJECT (GTK_COMBO (wdata->combo)->entry),
  481.       "activate", GTK_SIGNAL_FUNC (chdir_edit),
  482.       (gpointer) wdata);
  483.   if (*wdata->history)
  484.     gtk_combo_set_popdown_strings (GTK_COMBO (wdata->combo), *wdata->history);
  485.   gtk_combo_disable_activate (GTK_COMBO (wdata->combo));
  486.   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (wdata->combo)->entry), "");
  487.   wdata->hoststxt = gtk_label_new (NULL);
  488.   gtk_misc_set_alignment (GTK_MISC (wdata->hoststxt), 0, 0);
  489.   gtk_box_pack_start (GTK_BOX (box), wdata->hoststxt, FALSE, FALSE, 0);
  490.   scroll_list = gtk_scrolled_window_new (NULL, NULL);
  491.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_list),
  492.   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  493.   wdata->listbox = gtk_clist_new_with_titles (7, titles);
  494.   gtk_container_add (GTK_CONTAINER (scroll_list), wdata->listbox);
  495.   gtk_drag_source_set (wdata->listbox, GDK_BUTTON1_MASK, possible_types, 3,
  496.        GDK_ACTION_COPY | GDK_ACTION_MOVE);
  497.   gtk_drag_dest_set (wdata->listbox, GTK_DEST_DEFAULT_ALL, possible_types, 2,
  498.      GDK_ACTION_COPY | GDK_ACTION_MOVE);
  499.   gtk_clist_set_selection_mode (GTK_CLIST (wdata->listbox),
  500. GTK_SELECTION_EXTENDED);
  501.   gtk_clist_set_column_width (GTK_CLIST (wdata->listbox), 0, 16);
  502.   gtk_clist_set_column_justification (GTK_CLIST (wdata->listbox), 0,
  503.       GTK_JUSTIFY_CENTER);
  504.   setup_column (wdata->listbox, 1, columns[0]);
  505.   gtk_clist_set_column_justification (GTK_CLIST (wdata->listbox), 2,
  506.       GTK_JUSTIFY_RIGHT);
  507.   setup_column (wdata->listbox, 2, columns[1]);
  508.   setup_column (wdata->listbox, 3, columns[2]);
  509.   setup_column (wdata->listbox, 4, columns[3]);
  510.   setup_column (wdata->listbox, 5, columns[4]);
  511.   setup_column (wdata->listbox, 6, columns[5]);
  512.   gtk_box_pack_start (GTK_BOX (box), scroll_list, TRUE, TRUE, 0);
  513.   gtk_signal_connect (GTK_OBJECT (wdata->listbox), "click_column",
  514.         GTK_SIGNAL_FUNC (sortrows), (gpointer) wdata);
  515.   gtk_signal_connect (GTK_OBJECT (wdata->listbox), "drag_data_get",
  516.       GTK_SIGNAL_FUNC (listbox_drag), (gpointer) wdata);
  517.   gtk_signal_connect (GTK_OBJECT (wdata->listbox), "drag_data_received",
  518.       GTK_SIGNAL_FUNC (listbox_get_drag_data),
  519.       (gpointer) wdata);
  520.   gtk_signal_connect_after (GTK_OBJECT (wdata->listbox), "key_press_event",
  521.                             GTK_SIGNAL_FUNC (list_enter), (gpointer) wdata);
  522.   gtk_signal_connect (GTK_OBJECT (wdata->listbox), "select_row",
  523.                       GTK_SIGNAL_FUNC(select_row_callback),
  524.                       (gpointer) wdata);
  525.   gtk_signal_connect_after (GTK_OBJECT (wdata->listbox), "button_press_event",
  526.                             GTK_SIGNAL_FUNC (list_dblclick), (gpointer) wdata);
  527.   return (parent);
  528. }
  529. static gint
  530. menu_mouse_click (GtkWidget * widget, GdkEventButton * event, gpointer data)
  531. {
  532.   GtkItemFactory *factory;
  533.   factory = (GtkItemFactory *) data;
  534.   if (event->button == 3)
  535.     gtk_item_factory_popup (factory, (guint) event->x_root,
  536.     (guint) event->y_root, 3, event->time);
  537.   return (FALSE);
  538. }
  539. static GtkWidget *
  540. CreateFTPWindows (GtkWidget * ui)
  541. {
  542.   GtkWidget *box, *dlbox, *winpane, *dlpane, *logpane, *mainvbox, *tempwid,
  543.             *button;
  544.   char *dltitles[2];
  545. #if GTK_MAJOR_VERSION > 1
  546.   GtkTextBuffer * textbuf;
  547.   GtkTextIter iter;
  548.   GtkTextTag *tag;
  549.   GdkColor fore;
  550. #endif
  551.   memset (&window1, 0, sizeof (window1));
  552.   memset (&window2, 0, sizeof (window2));
  553.   window1.history = &localhistory;
  554.   window1.histlen = &localhistlen;
  555.   window2.history = &remotehistory;
  556.   window2.histlen = &remotehistlen;
  557.  
  558.   mainvbox = gtk_vbox_new (FALSE, 0);
  559.   tempwid = CreateMenus (ui);
  560.   gtk_box_pack_start (GTK_BOX (mainvbox), tempwid, FALSE, FALSE, 0);
  561.   tempwid = CreateToolbar (ui);
  562.   gtk_box_pack_start (GTK_BOX (mainvbox), tempwid, FALSE, FALSE, 0);
  563.   winpane = gtk_hpaned_new ();
  564.   box = gtk_hbox_new (FALSE, 0);
  565.   local_frame = CreateFTPWindow (&window1, listbox_local_width, local_columns);
  566.   window1.sortcol = &local_sortcol;
  567.   window1.sortasds = &local_sortasds;
  568.   gtk_box_pack_start (GTK_BOX (box), local_frame, TRUE, TRUE, 0);
  569.   dlbox = gtk_vbox_new (FALSE, 0);
  570.   gtk_container_border_width (GTK_CONTAINER (dlbox), 5);
  571.   gtk_box_pack_start (GTK_BOX (box), dlbox, FALSE, FALSE, 0);
  572. #if GTK_MAJOR_VERSION == 1
  573.   tempwid = toolbar_pixmap (ui, "right.xpm");
  574. #else
  575.   tempwid = gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
  576.                                       GTK_ICON_SIZE_SMALL_TOOLBAR);
  577. #endif
  578.   button = gtk_button_new ();
  579.   gtk_box_pack_start (GTK_BOX (dlbox), button, TRUE, FALSE, 0);
  580.   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
  581.      GTK_SIGNAL_FUNC (put_files), NULL);
  582.   gtk_container_add (GTK_CONTAINER (button), tempwid);
  583. #if GTK_MAJOR_VERSION == 1
  584.   tempwid = toolbar_pixmap (ui, "left.xpm");
  585. #else
  586.   tempwid = gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
  587.                                       GTK_ICON_SIZE_SMALL_TOOLBAR);
  588. #endif
  589.   button = gtk_button_new ();
  590.   gtk_box_pack_start (GTK_BOX (dlbox), button, TRUE, FALSE, 0);
  591.   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
  592.      GTK_SIGNAL_FUNC (get_files), NULL);
  593.   gtk_container_add (GTK_CONTAINER (button), tempwid);
  594.   gtk_paned_pack1 (GTK_PANED (winpane), box, 1, 1);
  595.   remote_frame = CreateFTPWindow (&window2, listbox_remote_width, 
  596.                                   remote_columns);
  597.   window2.sortcol = &remote_sortcol;
  598.   window2.sortasds = &remote_sortasds;
  599.   gtk_paned_pack2 (GTK_PANED (winpane), remote_frame, 1, 1);
  600.   dlpane = gtk_vpaned_new ();
  601.   gtk_paned_pack1 (GTK_PANED (dlpane), winpane, 1, 1);
  602.   transfer_scroll = gtk_scrolled_window_new (NULL, NULL);
  603.   gtk_widget_set_size_request (transfer_scroll, -1, transfer_height);
  604.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (transfer_scroll),
  605.   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  606.   dltitles[0] = _("Filename");
  607.   dltitles[1] = _("Progress");
  608.   dlwdw = gtk_ctree_new_with_titles (2, 0, dltitles);
  609.   gtk_clist_set_selection_mode (GTK_CLIST (dlwdw), GTK_SELECTION_SINGLE);
  610.   gtk_clist_set_reorderable (GTK_CLIST (dlwdw), 0);
  611.   if (file_trans_column == 0)
  612.     gtk_clist_set_column_auto_resize (GTK_CLIST (dlwdw), 0, TRUE);
  613.   else
  614.     gtk_clist_set_column_width (GTK_CLIST (dlwdw), 0, file_trans_column);
  615.   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (transfer_scroll),                                          dlwdw);
  616.   gtk_signal_connect (GTK_OBJECT (dlwdw), "button_press_event",
  617.       GTK_SIGNAL_FUNC (menu_mouse_click), (gpointer) dl_factory);
  618.   gtk_paned_pack2 (GTK_PANED (dlpane), transfer_scroll, 1, 1);
  619.   logpane = gtk_vpaned_new ();
  620.   gtk_paned_pack1 (GTK_PANED (logpane), dlpane, 1, 1);
  621.   log_table = gtk_table_new (1, 2, FALSE);
  622.   gtk_widget_set_size_request (log_table, -1, log_height);
  623. #if GTK_MAJOR_VERSION == 1
  624.   logwdw = gtk_text_new (NULL, NULL);
  625.   gtk_text_set_editable (GTK_TEXT (logwdw), FALSE);
  626.   gtk_text_set_word_wrap (GTK_TEXT (logwdw), TRUE);
  627.   gtk_table_attach (GTK_TABLE (log_table), logwdw, 0, 1, 0, 1,
  628.     GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
  629.     0, 0);
  630.   gtk_signal_connect (GTK_OBJECT (logwdw), "button_press_event",
  631.       GTK_SIGNAL_FUNC (menu_mouse_click), 
  632.                       (gpointer) log_factory);
  633.   tempwid = gtk_vscrollbar_new (GTK_TEXT (logwdw)->vadj);
  634.   gtk_table_attach (GTK_TABLE (log_table), tempwid, 1, 2, 0, 1,
  635.     GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
  636.   logwdw_vadj = GTK_TEXT (logwdw)->vadj;
  637. #else
  638.   logwdw = gtk_text_view_new ();
  639.   gtk_text_view_set_editable (GTK_TEXT_VIEW (logwdw), FALSE);
  640.   gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (logwdw), FALSE);
  641.   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (logwdw), GTK_WRAP_WORD);
  642.   textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logwdw));
  643.   tag = gtk_text_buffer_create_tag (textbuf, "send", NULL);
  644.   fore.red = send_color.red;
  645.   fore.green = send_color.green;
  646.   fore.blue = send_color.blue;
  647.   g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
  648.   tag = gtk_text_buffer_create_tag (textbuf, "recv", NULL);
  649.   fore.red = recv_color.red;
  650.   fore.green = recv_color.green;
  651.   fore.blue = recv_color.blue;
  652.   g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
  653.   tag = gtk_text_buffer_create_tag (textbuf, "error", NULL);
  654.   fore.red = error_color.red;
  655.   fore.green = error_color.green;
  656.   fore.blue = error_color.blue;
  657.   g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
  658.   tag = gtk_text_buffer_create_tag (textbuf, "misc", NULL);
  659.   fore.red = misc_color.red;
  660.   fore.green = misc_color.green;
  661.   fore.blue = misc_color.blue;
  662.   g_object_set (G_OBJECT (tag), "foreground_gdk", &fore, NULL);
  663.   tempwid = gtk_scrolled_window_new (NULL, NULL);
  664.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (tempwid),
  665.                                  GTK_POLICY_AUTOMATIC,
  666.                                  GTK_POLICY_AUTOMATIC);
  667.   gtk_container_add (GTK_CONTAINER (tempwid), logwdw);
  668.   gtk_table_attach (GTK_TABLE (log_table), tempwid, 0, 1, 0, 1,
  669.     GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND | GTK_SHRINK,
  670.     0, 0);
  671.   logwdw_vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (tempwid));
  672.   gtk_text_buffer_get_iter_at_offset (textbuf, &iter, 0);
  673.   logwdw_textmark = gtk_text_buffer_create_mark (textbuf, "end", &iter, 1);
  674. #endif
  675.   gtk_paned_pack2 (GTK_PANED (logpane), log_table, 1, 1);
  676.   gtk_box_pack_start (GTK_BOX (mainvbox), logpane, TRUE, TRUE, 0);
  677.   gtk_widget_show_all (mainvbox);
  678.   return (mainvbox);
  679. }
  680. void
  681. init_gftp (int argc, char *argv[], GtkWidget * parent)
  682. {
  683.   if (argc == 2 && strncmp (argv[1], "--", 2) != 0)
  684.     {
  685.       if (gftp_parse_url (window2.request, argv[1]) == 0)
  686. ftp_connect (&window2, window2.request, 1);
  687.       else
  688. gftp_usage ();
  689.     }
  690. }
  691. void
  692. toolbar_hostedit (GtkWidget * widget, gpointer data)
  693. {
  694.   void (*init) (gftp_request * request);
  695.   GtkWidget *tempwid;
  696.   const char *txt;
  697.   int num;
  698.   if (current_wdata->request->stopable)
  699.     {
  700.       ftp_log (gftp_logging_misc, NULL,
  701.                _("%s: Please hit the stop button first to do anything elsen"),
  702.                _("Connect"));
  703.       return;
  704.     }
  705.   if (GFTP_IS_CONNECTED (current_wdata->request))
  706.     disconnect (current_wdata);
  707.   tempwid = gtk_menu_get_active (GTK_MENU (protocol_menu));
  708.   num = (int) gtk_object_get_user_data (GTK_OBJECT (tempwid));
  709.   init = gftp_protocols[num].init;
  710.   init (current_wdata->request);
  711.  
  712.   gftp_set_hostname (current_wdata->request, gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (hostedit)->entry)));
  713.   alltrim (current_wdata->request->hostname);
  714.   if (current_wdata->request->need_hostport && 
  715.       *current_wdata->request->hostname == '')
  716.     {
  717.       ftp_log (gftp_logging_error, NULL,
  718.        _("Error: You must type in a host to connect ton"));
  719.       return;
  720.     }
  721.   add_history (hostedit, &host_history, &host_len, 
  722.                current_wdata->request->hostname);
  723.   if (strchr (current_wdata->request->hostname, '/') != NULL &&
  724.       gftp_parse_url (current_wdata->request, 
  725.                       current_wdata->request->hostname) == 0)
  726.     {
  727.       ftp_connect (current_wdata, current_wdata->request, 1);
  728.       return;
  729.     }
  730.  
  731.   txt = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (portedit)->entry));
  732.   gftp_set_port (current_wdata->request, strtol (txt, NULL, 10));
  733.   add_history (portedit, &port_history, &port_len, txt);
  734.   gftp_set_username (current_wdata->request, gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (useredit)->entry)));
  735.   alltrim (current_wdata->request->username);
  736.   add_history (useredit, &user_history, &user_len, 
  737.                current_wdata->request->username);
  738.   gftp_set_password (current_wdata->request,
  739.      gtk_entry_get_text (GTK_ENTRY (passedit)));
  740.   gftp_set_directory (current_wdata->request, gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (current_wdata->combo)->entry)));
  741.   alltrim (current_wdata->request->directory);
  742.   add_history (current_wdata->combo, current_wdata->history, 
  743.                current_wdata->histlen, current_wdata->request->directory);
  744.   ftp_connect (current_wdata, current_wdata->request, 1);
  745. }
  746. void
  747. sortrows (GtkCList * clist, gint column, gpointer data)
  748. {
  749.   gftp_window_data * wdata;
  750.   GtkWidget * sort_wid;
  751.   GList * templist;
  752.   int swap_col;
  753.   wdata = data;
  754.   if (column == 0 || (column == *wdata->sortcol && wdata->sorted))
  755.     {
  756.       *wdata->sortasds = !(*wdata->sortasds);
  757.       swap_col = 1;
  758.     }
  759.   else
  760.     swap_col = 0;
  761.   if (swap_col || !wdata->sorted)
  762.     {
  763.       sort_wid = gtk_clist_get_column_widget (clist, 0);
  764.       gtk_widget_destroy (sort_wid);
  765. #if GTK_MAJOR_VERSION == 1
  766.       if (*wdata->sortasds)
  767. sort_wid = toolbar_pixmap (wdata->listbox, "down.xpm");
  768.       else
  769. sort_wid = toolbar_pixmap (wdata->listbox, "up.xpm");
  770. #else
  771.       if (*wdata->sortasds)
  772.         sort_wid = gtk_image_new_from_stock (GTK_STOCK_SORT_ASCENDING, 
  773.                                              GTK_ICON_SIZE_SMALL_TOOLBAR);
  774.       else
  775.         sort_wid = gtk_image_new_from_stock (GTK_STOCK_SORT_DESCENDING, 
  776.                                              GTK_ICON_SIZE_SMALL_TOOLBAR);
  777. #endif
  778.       gtk_clist_set_column_widget (clist, 0, sort_wid);
  779.     }
  780.   else
  781.     *wdata->sortcol = column;
  782.   if (!GFTP_IS_CONNECTED (wdata->request))
  783.     return;
  784.   gtk_clist_freeze (clist);
  785.   gtk_clist_clear (clist);
  786.   wdata->files = gftp_sort_filelist (wdata->files, *wdata->sortcol, 
  787.                                      *wdata->sortasds);
  788.   templist = wdata->files; 
  789.   while (templist != NULL)
  790.     {
  791.       add_file_listbox (wdata, templist->data);
  792.       templist = templist->next;
  793.     }
  794.   wdata->sorted = 1;
  795.   gtk_clist_thaw (clist);
  796.   update_window_info ();
  797. }
  798. void
  799. stop_button (GtkWidget * widget, gpointer data)
  800. {
  801.   pthread_t comptid;
  802.   memset (&comptid, 0, sizeof (comptid));
  803.   if (!pthread_equal (comptid, window1.tid))
  804.     pthread_kill (window1.tid, SIGINT);
  805.   else if (!pthread_equal (comptid, window2.tid))
  806.     pthread_kill (window2.tid, SIGINT);
  807. }
  808. int
  809. main (int argc, char **argv)
  810. {
  811.   GtkWidget *window, *ui;
  812. #ifdef HAVE_GETTEXT
  813.   setlocale (LC_ALL, "");
  814.   bindtextdomain ("gftp", LOCALE_DIR);
  815. #if GTK_MAJOR_VERSION > 1
  816.   bind_textdomain_codeset ("gftp", "UTF-8");
  817. #endif
  818.   textdomain ("gftp");
  819. #endif
  820.   g_thread_init (NULL);
  821.   main_thread_id = pthread_self ();
  822.   gtk_set_locale ();
  823.   gtk_init (&argc, &argv);
  824.   signal (SIGCHLD, sig_child);
  825.   signal (SIGPIPE, SIG_IGN);
  826.   signal (SIGALRM, signal_handler);
  827.   signal (SIGINT, signal_handler);
  828.   graphic_hash_table = g_hash_table_new (string_hash_function, string_hash_compare);
  829.   gftp_read_config_file (argv, 1);
  830.   if (gftp_parse_command_line (&argc, &argv) != 0)
  831.     exit (0);
  832.   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  833.   gtk_signal_connect (GTK_OBJECT (window), "delete_event",
  834.       GTK_SIGNAL_FUNC (delete_event), NULL);
  835.   gtk_signal_connect (GTK_OBJECT (window), "destroy",
  836.       GTK_SIGNAL_FUNC (destroy), NULL);
  837.   gtk_window_set_title (GTK_WINDOW (window), version);
  838.   gtk_window_set_wmclass (GTK_WINDOW(window), "main", "gFTP");
  839.   gtk_widget_set_name (window, version);
  840.   gtk_window_set_policy (GTK_WINDOW (window), TRUE, TRUE, FALSE);
  841.   gtk_widget_realize (window);
  842.   gftp_icon = open_xpm (window, "gftp.xpm");
  843.   if (gftp_icon != NULL)
  844.     {
  845.       gdk_window_set_icon (window->window, NULL, gftp_icon->pixmap,
  846.                            gftp_icon->bitmap);
  847.       gdk_window_set_icon_name (window->window, _("gFTP Icon"));
  848.     }
  849.   other_wdata = &window1;
  850.   current_wdata = &window2;
  851.   ui = CreateFTPWindows (window);
  852.   gtk_container_add (GTK_CONTAINER (window), ui);
  853.   gtk_widget_show (window);
  854.   ftp_log (gftp_logging_misc, NULL,
  855.    "%s, Copyright (C) 1998-2002 Brian Masney <", version);
  856.   ftp_log (gftp_logging_recv, NULL, "masneyb@gftp.org");
  857.   ftp_log (gftp_logging_misc, NULL,
  858.    _(">. If you have any questions, comments, or suggestions about this program, please feel free to email them to me. You can always find out the latest news about gFTP from my website at http://www.gftp.org/n"));
  859.   ftp_log (gftp_logging_misc, NULL,
  860.    _("gFTP comes with ABSOLUTELY NO WARRANTY; for details, see the COPYING file. This is free software, and you are welcome to redistribute it under certain conditions; for details, see the COPYING filen"));
  861.   gtk_timeout_add (1000, update_downloads, NULL);
  862.   gftp_protocols[GFTP_LOCAL_NUM].init (window1.request);
  863.   if (startup_directory != NULL && *startup_directory != '')
  864.     gftp_set_directory (window1.request, startup_directory);
  865.   gftp_connect (window1.request);
  866.   ftp_list_files (&window1, 0);
  867.   /* On the remote window, even though we aren't connected, draw the sort
  868.      icon on that side */
  869.   sortrows (GTK_CLIST (window2.listbox), *window2.sortcol, &window2);
  870.   init_gftp (argc, argv, window);
  871.   GDK_THREADS_ENTER ();
  872.   gtk_main ();
  873.   GDK_THREADS_LEAVE ();
  874.   return (0);
  875. }