/*
    main.c - Provide the main window and related routines
    Copyright (c) 1999,2006  Joey Schulze <joey@infodrom.org>

    This file is part of the Gerstensaft package.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/

#define _GNU_SOURCE

#include <unistd.h>
#include <string.h>
#include <malloc.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "msgbox.h"
#include "main.h"
#include "io.h"
#include "beer.h"
#include "send.h"
#include "nls.h"
#include "gutils.h"
#include "config.h"
#include "receive.h"
#include "options.h"
#include <stdio.h>

GdkPixmap *dir_pixmap = NULL,
          *linkdir_pixmap = NULL,
          *linkfile_pixmap = NULL,
          *updir_pixmap = NULL,
          *doc_pixmap = NULL;
GdkBitmap *dir_mask = NULL,
          *linkdir_mask = NULL,
          *linkfile_mask = NULL,
          *updir_mask = NULL,
          *doc_mask = NULL;

gint main_delete(GtkWidget *widget, GdkEvent *event, gpointer data)
{
  return (FALSE);
}

void main_destroy (GtkWidget *widget, gpointer data)
{
  if (((struct s_main_data *) data) != NULL) {
    if (((struct s_main_data *) data)->dir != NULL)
      free (((struct s_main_data *) data)->dir);
    free (((struct s_main_data *) data));
  }

  gtk_main_quit ();
}

void menu_mode_send (GtkWidget *widget, gpointer data)
{
  if (((struct s_main_data *) data)->mode != MOD_SEND) {
    if (((struct s_main_data *) data)->mode == MOD_RECEIVE)
      gtk_widget_hide (((struct s_main_data *) data)->container_receive);
    else
      gtk_widget_hide (((struct s_main_data *) data)->container_message);
    gtk_widget_show (((struct s_main_data *) data)->container_send);

    gtk_widget_set_sensitive (GTK_WIDGET(((struct s_main_data *) data)->modeitem[((struct s_main_data *) data)->mode]), TRUE);
    ((struct s_main_data *) data)->mode = MOD_SEND;
    gtk_widget_set_sensitive (GTK_WIDGET(((struct s_main_data *) data)->modeitem[((struct s_main_data *) data)->mode]), FALSE);
  }
}

void menu_mode_receive (GtkWidget *widget, gpointer data)
{
  if (((struct s_main_data *) data)->mode != MOD_RECEIVE) {
    parse_receive ((struct s_main_data *)data);

    if (((struct s_main_data *) data)->mode == MOD_SEND)
      gtk_widget_hide (((struct s_main_data *) data)->container_send);
    else
      gtk_widget_hide (((struct s_main_data *) data)->container_message);
    gtk_widget_show (((struct s_main_data *) data)->container_receive);

    gtk_widget_set_sensitive (GTK_WIDGET(((struct s_main_data *) data)->modeitem[((struct s_main_data *) data)->mode]), TRUE);
    ((struct s_main_data *) data)->mode = MOD_RECEIVE;
    gtk_widget_set_sensitive (GTK_WIDGET(((struct s_main_data *) data)->modeitem[((struct s_main_data *) data)->mode]), FALSE);
  }
}

void menu_mode_message (GtkWidget *widget, gpointer data)
{
  if (((struct s_main_data *) data)->mode != MOD_MESSAGE) {
    if (((struct s_main_data *) data)->mode == MOD_SEND)
      gtk_widget_hide (((struct s_main_data *) data)->container_send);
    else
      gtk_widget_hide (((struct s_main_data *) data)->container_receive);
    gtk_widget_show (((struct s_main_data *) data)->container_message);

    gtk_widget_set_sensitive (GTK_WIDGET(((struct s_main_data *) data)->modeitem[((struct s_main_data *) data)->mode]), TRUE);
    ((struct s_main_data *) data)->mode = MOD_MESSAGE;
    gtk_widget_set_sensitive (GTK_WIDGET(((struct s_main_data *) data)->modeitem[((struct s_main_data *) data)->mode]), FALSE);
  }
}

void message_addr_change (GtkWidget *widget, gpointer data)
{
  GtkTextBuffer *buffer;

  if (strlen(gtk_entry_get_text (GTK_ENTRY(widget))) > 0) {
    if (!((struct s_main_data *) data)->addrok) {
      buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(((struct s_main_data *) data)->msginput));
      if (gtk_text_buffer_get_char_count(buffer) > 0) {
	((struct s_main_data *) data)->addrok = 1;
	gtk_widget_set_sensitive (((struct s_main_data *) data)->msgsend, TRUE);
      }
    }
  } else {
    if (((struct s_main_data *) data)->addrok) {
      ((struct s_main_data *) data)->addrok = 0;
      gtk_widget_set_sensitive (((struct s_main_data *) data)->msgsend, FALSE);
    }
  }
}

void message_input_change (GObject *object, gpointer data)
{
  if (((struct s_main_data *) data)->addrok) {
    if (gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(object)) == 0) {
      ((struct s_main_data *) data)->addrok = 0;
      gtk_widget_set_sensitive (((struct s_main_data *) data)->msgsend, FALSE);
    }
  } else {
    if (gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(object)) > 0
	&& strlen(gtk_entry_get_text (GTK_ENTRY(GTK_COMBO(((struct s_main_data *) data)->addrinput)->entry))) > 0) {
      ((struct s_main_data *) data)->addrok = 1;
      gtk_widget_set_sensitive (((struct s_main_data *) data)->msgsend, TRUE);
    }
  }
}

void menu_clear_history (GtkWidget *widget, gpointer data)
{
  clear_history();
}

void load_pixmap (const char *name, GtkWidget *parent, GdkPixmap **pixmap, GdkBitmap **mask)
{
  char fname[1024];
  GtkStyle *style;
  
  snprintf (fname, sizeof(fname), "%s/%s", PIXMAP_DIR, name);
  style = gtk_widget_get_style (parent);

  *pixmap = gdk_pixmap_create_from_xpm (parent->window, mask, &style->bg[GTK_STATE_NORMAL], fname);
}

void read_directory (struct s_main_data *wdata, const char *dir)
{
  struct s_file *files, *fp;
  char *name, size[10];
  char **clp;
  gint pos;
  GdkColor background;
  GdkColormap *colormap;

#ifdef DEBUG
  printf ("read_directory(%s)\n", dir);
#endif

  if ((clp = (char **)malloc(sizeof(char *)*3)) == NULL)
    return;
  clp[0] = NULL;

 /* Copy the new directory into local variable */
  if (wdata->dir)
    free (wdata->dir);
  wdata->dir = check_and_adjust_dir (dir);

 if ((files = get_dir (wdata->dir)) != NULL) {
   gtk_clist_freeze (GTK_CLIST(wdata->listbox));
   gtk_clist_clear (GTK_CLIST(wdata->listbox));
   for (fp = files; fp; fp=fp->next) {
     if ((name = (char *)malloc(strlen(fp->name)+1)) == NULL)
       continue;
     memcpy (name, fp->name, strlen(fp->name)+1);
     clp[1] = name;

#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64
     snprintf (size, sizeof (size), "%lld", (fp->size+1023)/1024);
#else
     snprintf (size, sizeof (size), "%ld", (fp->size+1023)/1024);
#endif

     if ((name = strdup(size)) == NULL)
       continue;
     clp[2] = name;

     pos = gtk_clist_append (GTK_CLIST(wdata->listbox), clp);

     background.red = background.green = background.blue =  ~0;
     colormap = gdk_colormap_get_system();
     gdk_color_alloc (colormap, &background);

     gtk_clist_set_background (GTK_CLIST(wdata->listbox), pos, &background);
     switch (fp->type)
       {
       case FILE_REGULAR:
	 gtk_clist_set_pixmap (GTK_CLIST(wdata->listbox), pos, 0, doc_pixmap, doc_mask);
	 break;
       case FILE_DIRECTORY:
	 gtk_clist_set_pixmap (GTK_CLIST(wdata->listbox), pos, 0, dir_pixmap, dir_mask);
	 break;
       case FILE_LINK:
	 gtk_clist_set_pixmap (GTK_CLIST(wdata->listbox), pos, 0, linkfile_pixmap, linkfile_mask);
	 break;
       case FILE_LINKDIR:
	 gtk_clist_set_pixmap (GTK_CLIST(wdata->listbox), pos, 0, linkdir_pixmap, linkdir_mask);
	 break;
       case FILE_UPDIR:
	 gtk_clist_set_pixmap (GTK_CLIST(wdata->listbox), pos, 0, updir_pixmap, updir_mask);
	 break;
       }
   }
   gtk_clist_set_column_width (GTK_CLIST(wdata->listbox), 2,
			       gtk_clist_optimal_column_width (GTK_CLIST(wdata->listbox), 2));
   gtk_clist_thaw (GTK_CLIST(wdata->listbox));
 }

 /* Now adjust the input field */
 gtk_entry_set_text (GTK_ENTRY(wdata->dirinput), wdata->dir);

 /* Deactivate the Add button since there's nothing selected */
 gtk_widget_set_sensitive (wdata->addbutton, FALSE);
 gtk_widget_set_sensitive (wdata->unselectbutton, FALSE);
}

void dirinput_change (GtkWidget *widget, gpointer data)
{
#ifdef DEBUG
  printf ("dirinput_change()\n");
  printf ("  Old value: %s\n", ((struct s_main_data *)data)->dir);
  printf ("  New value: %s\n", gtk_entry_get_text (GTK_ENTRY(widget)));
#endif

  read_directory ((struct s_main_data *)data, gtk_entry_get_text (GTK_ENTRY(widget)));
}

gint main_row_button (GtkWidget *widget, GdkEventButton *event, gpointer data)
{
  gint row, col;
  gchar *file;
  char *fname, *cp;

#ifdef DEBUG
  printf ("main_row_button(%d)\n", event->type);
#endif

  if (event) {
    gtk_clist_get_selection_info (GTK_CLIST (widget), event->x, event->y, &row, &col);
    if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) {

      gtk_clist_get_text(GTK_CLIST(((struct s_main_data *) data)->listbox), row, 1, &file);
      if (!strcmp(file, "..")) {
	if ((fname = (char *)malloc (strlen (((struct s_main_data *) data)->dir) +1)) == NULL)
	  return FALSE;
	strcpy (fname, ((struct s_main_data *) data)->dir);
	if ((cp = strrchr (fname, '/')) != NULL) {
	  *cp = '\0';
	  if (fname[0] == '\0') {
	    fname[0] = '/';
	    fname[1] = '\0';
	  }
	  read_directory ((struct s_main_data *)data, fname);
	  free (fname);
	}
      } else {
	if ((fname = (char *)malloc (strlen (((struct s_main_data *) data)->dir) + strlen (file) +2)) == NULL)
	  return FALSE;
	if (strlen (((struct s_main_data *) data)->dir) == 1)
	  sprintf (fname, "/%s", file);
	else
	  sprintf (fname, "%s/%s", ((struct s_main_data *) data)->dir, file);

	if (is_dir (fname, NULL)) {
	  read_directory ((struct s_main_data *)data, fname);
	  free (fname);
	} else {
	  gtk_clist_freeze (GTK_CLIST(((struct s_main_data *) data)->listbox));
	  gtk_clist_unselect_row (GTK_CLIST(((struct s_main_data *) data)->listbox), row, col);
	  gtk_clist_thaw (GTK_CLIST(((struct s_main_data *) data)->listbox));

	  if (!filebox_append (GTK_CLIST(((struct s_main_data *) data)->filebox), fname))
	    free (fname);
	  gtk_widget_set_sensitive (((struct s_main_data *) data)->sendbutton, TRUE);
	  gtk_widget_set_sensitive (((struct s_main_data *) data)->clearbutton, TRUE);
	}
	return TRUE;
      }
      /* could be used for a context menu
	 } else if (event->button == 3) {
      */
    }
  }
  return FALSE;
}

void main_button_select_all (GtkWidget *widget, gpointer data)
{
  int i;

  gtk_clist_freeze (GTK_CLIST(((struct s_main_data *) data)->listbox));

  for (i=1; i < GTK_CLIST(((struct s_main_data *) data)->listbox)->rows; i++) {
      gtk_clist_select_row (GTK_CLIST(((struct s_main_data *) data)->listbox), i, 0);
  }

  gtk_clist_thaw (GTK_CLIST(((struct s_main_data *) data)->listbox));
  gtk_widget_set_sensitive (((struct s_main_data *) data)->selectbutton, FALSE);
}

void main_button_unselect_all (GtkWidget *widget, gpointer data)
{
  int i;

  gtk_clist_freeze (GTK_CLIST(((struct s_main_data *) data)->listbox));

  for (i=0; i < GTK_CLIST(((struct s_main_data *) data)->listbox)->rows; i++) {
      gtk_clist_unselect_row (GTK_CLIST(((struct s_main_data *) data)->listbox), i, 0);
  }
  gtk_clist_thaw (GTK_CLIST(((struct s_main_data *) data)->listbox));
  gtk_widget_set_sensitive (((struct s_main_data *) data)->addbutton, FALSE);
  gtk_widget_set_sensitive (((struct s_main_data *) data)->unselectbutton, FALSE);
}

void button_add (GtkWidget *widget, gpointer data)
{
  gchar *fname;
  char *fullname;
  GList *selection;

#ifdef DEBUG
  printf ("button_add()\n");
#endif

  for (selection = GTK_CLIST(((struct s_main_data *) data)->listbox)->selection;
       selection;
       selection = selection->next) {
    
    gtk_clist_get_text (GTK_CLIST(((struct s_main_data *) data)->listbox), (int)selection->data, 1, &fname);

    if (!strcmp(fname, ".."))
      continue;
    if ((fullname = (char *)malloc (strlen(fname) + strlen(((struct s_main_data *) data)->dir) + 2)) == NULL)
      return;

    if (strlen (((struct s_main_data *) data)->dir) > 1)
      sprintf (fullname, "%s/%s", ((struct s_main_data *) data)->dir, fname);
    else
      sprintf (fullname, "/%s", fname);

    if (!filebox_append (GTK_CLIST(((struct s_main_data *) data)->filebox), fullname))
      free (fullname);
    gtk_widget_set_sensitive (((struct s_main_data *) data)->sendbutton, TRUE);
  }

  main_button_unselect_all (widget, data);
  gtk_widget_set_sensitive (((struct s_main_data *) data)->clearbutton, TRUE);
}

void main_clear (gpointer data)
{
  gtk_clist_clear (GTK_CLIST(((struct s_main_data *) data)->filebox));
  gtk_widget_set_sensitive (((struct s_main_data *) data)->clearbutton, FALSE);
  gtk_widget_set_sensitive (((struct s_main_data *) data)->sendbutton, FALSE);
}

void button_clear (GtkWidget *widget, gpointer data)
{
  gtk_clist_clear (GTK_CLIST(((struct s_main_data *) data)->filebox));

  main_clear (data);
}

void button_send (GtkWidget *widget, gpointer data)
{
  if (GTK_CLIST(((struct s_main_data *) data)->filebox)->rows > 0)
    send_dialog (data);
}

gint receiver_row_select (GtkWidget *widget, gint row_select, gint column, GdkEventButton * event, gpointer data)
{
  gchar *sender;
  gchar *comment = NULL;
  char *s;

  gtk_clist_get_text (GTK_CLIST(((struct s_main_data *)data)->receiver), row_select, 5, &sender);
  gtk_clist_get_text (GTK_CLIST(((struct s_main_data *)data)->receiver), row_select, 6, &comment);

  if ((s = (char *)malloc(strlen(sender) + strlen(_("From: %s")))) == NULL)
    return FALSE;

  sprintf (s, _("From: %s"), sender);
  gtk_label_set_text (GTK_LABEL(((struct s_main_data *) data)->rinfo), s);

  if (comment)
    gtk_label_set_text (GTK_LABEL(((struct s_main_data *) data)->rcomment), strdup(comment));
  else
    gtk_label_set_text (GTK_LABEL(((struct s_main_data *) data)->rcomment), NULL);

  return FALSE;
}

gint main_row_select (GtkWidget *widget, gint row_select, gint column, GdkEventButton * event, gpointer data)
{
  GList *selection;

  if (row_select > 0) {
    gtk_widget_set_sensitive (((struct s_main_data *) data)->addbutton, TRUE);
    gtk_widget_set_sensitive (((struct s_main_data *) data)->unselectbutton, TRUE);
  } else
    if ((selection = GTK_CLIST(((struct s_main_data *) data)->listbox)->selection)
	&& !selection->next) {
      gtk_widget_set_sensitive (((struct s_main_data *) data)->addbutton, FALSE);
      gtk_widget_set_sensitive (((struct s_main_data *) data)->unselectbutton, FALSE);
    }

  return FALSE;
}

gint main_row_unselect (GtkWidget *widget, gint row_select, gint column, GdkEventButton * event, gpointer data)
{
  if (row_select > 0)
    gtk_widget_set_sensitive (((struct s_main_data *) data)->selectbutton, TRUE);

  return FALSE;
}

gint receiver_row_button (GtkWidget *widget, GdkEventButton *event, gpointer data)
{
  gint row, col;
  /*
  gchar *nr;
  gchar *fname;
  gchar *dir;
  */

  if (event) {
    gtk_clist_get_selection_info (GTK_CLIST (widget), event->x, event->y, &row, &col);
    if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) {
      /*
       * Sorry, but but when activating this code, gtk_run_dialog() will
       * freeze the entire X and you can only operate the window with the
       * keyboard, not quite promising.  This doesn't happen when being
       * called from the "Receive" button, though.
       *
      dir = gtk_entry_get_text (GTK_ENTRY(((struct s_main_data *) data)->rdirinput));
      gtk_clist_get_text(GTK_CLIST(widget), row, 4, &nr);
      gtk_clist_get_text(GTK_CLIST(widget), row, 1, &fname);
      if (receive_file (nr, dir, fname))
	gtk_clist_remove (GTK_CLIST(((struct s_main_data *)data)->receiver), row);
      else
	gtk_clist_unselect_row (GTK_CLIST(widget), row, 0);
      */

      return TRUE;
    /* could be used for a context menu      
    } else if (event->button == 3) {
    */
    }
  }
  return FALSE;
}

void button_receive (GtkWidget *widget, gpointer data)
{
  GList *selection;
  gchar *nr;
  gchar *fname;
  const gchar *dir;

  dir = gtk_entry_get_text (GTK_ENTRY(((struct s_main_data *) data)->rdirinput));

  gtk_clist_freeze (GTK_CLIST(((struct s_main_data *) data)->receiver));

  while ((selection = GTK_CLIST(((struct s_main_data *) data)->receiver)->selection)) {
    gtk_clist_get_text (GTK_CLIST(((struct s_main_data *) data)->receiver), (int)selection->data, 4, &nr);
    gtk_clist_get_text (GTK_CLIST(((struct s_main_data *) data)->receiver), (int)selection->data, 1, &fname);
    if (receive_file (nr, dir, fname))
      gtk_clist_remove (GTK_CLIST(((struct s_main_data *)data)->receiver), (int)selection->data);
    else
      gtk_clist_unselect_row (GTK_CLIST(((struct s_main_data *)data)->receiver), (int)selection->data, 0);
  }

  gtk_clist_thaw (GTK_CLIST(((struct s_main_data *) data)->receiver));
}

void button_refresh (GtkWidget *widget, gpointer data)
{
  parse_receive ((struct s_main_data *)data);

  gtk_label_set_text (GTK_LABEL(((struct s_main_data *) data)->rinfo), NULL);
  gtk_label_set_text (GTK_LABEL(((struct s_main_data *) data)->rcomment), NULL);
}

void button_msgsend (GtkWidget *widget, gpointer data)
{
  GtkTextBuffer *buffer;
  GtkTextIter start_iter, end_iter;
  const gchar *addr;
  gchar *text;

  if (!((struct s_main_data *) data)->addrok)
    return;

  addr = gtk_entry_get_text (GTK_ENTRY(GTK_COMBO(((struct s_main_data *) data)->addrinput)->entry));

  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(((struct s_main_data *) data)->msginput));
  gtk_text_buffer_get_start_iter (buffer, &start_iter);
  gtk_text_buffer_get_end_iter (buffer, &end_iter);
  text = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);

  if (sendmessage (addr, text))
    gtk_text_buffer_set_text (buffer, "", 0);

  send_history_add (addr, GTK_COMBO(((struct s_main_data *) data)->addrinput));
}

/*
 * FIXME: Prevent the Size field from being size-increased if the dialog gets resized
 */
/**
 * main_window:
 *
 * Opens the main window with menu etc.
 * 
 * return values: nothing
+------+-------+-------+
| File | ..... | Help  |
+------+-------+-------+
| Open |       | Index |
|      |       |       |
| Quit |       | About |
+------+       +-------+
 */
void main_window(unsigned short int startmode)
{
  GtkWidget *window;
  GtkWidget *mainbox, *hbox, *vbox;
  GtkWidget *menubar, *menu, *menuitem;
  GtkWidget *frame;
  GtkWidget *button;
  GtkWidget *label;
#if GTK_MAJOR_VERSION >= 1 && GTK_MINOR_VERSION >= 1
  GtkWidget *scrollwin;
#endif
  GtkTooltips *tooltips;
  GtkTextBuffer *buffer;
  GtkAccelGroup* accelgroup;
  char *titles[3] = {"", _("Filename"), _("Size")};
  char *rtitles[7] = {"", _("Filename"), _("Date"), _("Size"), "", "", ""};
  char cwd[255];
  char *cp;
  struct s_main_data *wdata;

  if ((wdata = (struct s_main_data *) malloc (sizeof(struct s_main_data))) == NULL)
    return;
  memset (wdata, 0, sizeof (struct s_main_data));
  wdata->mode = startmode;

  /* Create a new dialog box */
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), _("Gerstensaft"));
  gtk_widget_set_usize (GTK_WIDGET (window), 450, 350);

  accelgroup = gtk_accel_group_new();
  gtk_window_add_accel_group (GTK_WINDOW (window), accelgroup);

  /* Connect the appropriate signal handlers */
  g_signal_connect (G_OBJECT (window), "delete_event",
		    G_CALLBACK (main_delete), NULL);
  g_signal_connect (G_OBJECT (window), "destroy",
		    G_CALLBACK (main_destroy), (gpointer) wdata);

  mainbox = gtk_vbox_new(FALSE, 0);
  gtk_container_add (GTK_CONTAINER (window), mainbox);
  menubar = gtk_menu_bar_new();
  gtk_box_pack_start (GTK_BOX(mainbox), menubar, FALSE, FALSE, 2);

  menu = gtk_menu_new();
  menuitem = gtk_menu_item_new_with_mnemonic(_("_File"));
  gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuitem), menu );
  gtk_menu_bar_append( GTK_MENU_BAR (menubar), menuitem );
  gtk_widget_show(menuitem);

    /* Should be moved into the Options menu */
    menuitem = gtk_menu_item_new_with_mnemonic(_("_Clear History"));
    g_signal_connect (G_OBJECT (menuitem), "activate",
		      G_CALLBACK (menu_clear_history), NULL);
    gtk_menu_append( GTK_MENU(menu), menuitem);
    gtk_widget_show(menuitem);

    menuitem = gtk_menu_item_new_with_mnemonic(_("_Preferences..."));
    g_signal_connect (G_OBJECT (menuitem), "activate",
		      G_CALLBACK (options_dialog), NULL);
    gtk_menu_append (GTK_MENU(menu), menuitem);
    gtk_widget_show (menuitem);
    gtk_widget_add_accelerator ( GTK_WIDGET (menuitem), "activate", accelgroup,
				 GDK_P, GDK_MOD1_MASK, GTK_ACCEL_VISIBLE);

    menuitem = gtk_menu_item_new_with_mnemonic(_("_Quit"));
    g_signal_connect (G_OBJECT (menuitem), "activate",
		      G_CALLBACK (main_destroy), (gpointer) wdata);
    gtk_menu_append( GTK_MENU(menu), menuitem);
    gtk_widget_show(menuitem);
    gtk_widget_add_accelerator ( GTK_WIDGET (menuitem), "activate", accelgroup,
				 GDK_Q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);

  menu = gtk_menu_new();
  menuitem = gtk_menu_item_new_with_mnemonic(_("_Mode"));
  gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuitem), menu );
  gtk_menu_bar_append( GTK_MENU_BAR (menubar), menuitem );
  gtk_widget_show(menuitem);

    wdata->modeitem[MOD_SEND] = gtk_menu_item_new_with_mnemonic(_("_Send"));
    g_signal_connect (G_OBJECT (wdata->modeitem[MOD_SEND]), "activate",
		      G_CALLBACK (menu_mode_send), (gpointer) wdata);
    gtk_menu_append( GTK_MENU(menu), wdata->modeitem[MOD_SEND]);
    gtk_widget_show(wdata->modeitem[MOD_SEND]);

    wdata->modeitem[MOD_RECEIVE] = gtk_menu_item_new_with_mnemonic(_("_Receive"));
    g_signal_connect (G_OBJECT (wdata->modeitem[MOD_RECEIVE]), "activate",
		      G_CALLBACK (menu_mode_receive), (gpointer) wdata);
    gtk_menu_append( GTK_MENU(menu), wdata->modeitem[MOD_RECEIVE]);
    gtk_widget_show(wdata->modeitem[MOD_RECEIVE]);
 
    wdata->modeitem[MOD_MESSAGE] = gtk_menu_item_new_with_mnemonic(_("_Message"));
    g_signal_connect (G_OBJECT (wdata->modeitem[MOD_MESSAGE]), "activate",
		      G_CALLBACK (menu_mode_message), (gpointer) wdata);
    gtk_menu_append( GTK_MENU(menu), wdata->modeitem[MOD_MESSAGE]);
    gtk_widget_show(wdata->modeitem[MOD_MESSAGE]);
 
    gtk_widget_set_sensitive (GTK_WIDGET(wdata->modeitem[wdata->mode]), FALSE);

  menu = gtk_menu_new();
  menuitem = gtk_menu_item_new_with_mnemonic(_("_Help"));
  gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuitem), menu );
  gtk_menu_item_right_justify( GTK_MENU_ITEM(menuitem) );
  gtk_menu_bar_append( GTK_MENU_BAR (menubar), menuitem );
  gtk_widget_show(menuitem);

    menuitem = gtk_menu_item_new_with_mnemonic(_("_Todo"));
    g_signal_connect (G_OBJECT (menuitem), "activate",
		      G_CALLBACK (msgbox_todo), NULL);
    gtk_menu_append( GTK_MENU(menu), menuitem);
    gtk_widget_show(menuitem);

    menuitem = gtk_menu_item_new_with_mnemonic(_("_About"));
    g_signal_connect (G_OBJECT (menuitem), "activate",
		      G_CALLBACK (msgbox_about), NULL);
    gtk_menu_append( GTK_MENU(menu), menuitem);
    gtk_widget_show(menuitem);

  gtk_widget_show(menubar);

  /* Vertical box containing the send container */
  wdata->container_send = gtk_vbox_new(FALSE, 0);

  /* Horizontal box containing Clist on the left and buttons on the right */
  hbox = gtk_hbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER(wdata->container_send), hbox);

  /* Listbox containing files to select */
  frame = gtk_frame_new (NULL);
  gtk_container_border_width (GTK_CONTAINER(frame), 5);
  gtk_container_add (GTK_CONTAINER(hbox), frame);

  vbox = gtk_vbox_new (FALSE, 0);
  gtk_container_border_width (GTK_CONTAINER(vbox), 5);
  gtk_container_add (GTK_CONTAINER(frame), vbox);

  /* Input field for directory, will be updated automatically */
  wdata->dirinput = gtk_entry_new_with_max_length (60);
  g_signal_connect (G_OBJECT (wdata->dirinput), "activate",
		    G_CALLBACK (dirinput_change), (gpointer) wdata);
  gtk_box_pack_start (GTK_BOX(vbox), wdata->dirinput, FALSE, FALSE, FALSE);
  gtk_widget_show (wdata->dirinput);

  wdata->listbox = gtk_clist_new_with_titles (3, titles);
  gtk_widget_set_usize (GTK_WIDGET (wdata->listbox), 100, 100);
  gtk_clist_column_titles_passive (GTK_CLIST(wdata->listbox));
  gtk_clist_set_selection_mode (GTK_CLIST(wdata->listbox), GTK_SELECTION_MULTIPLE);
  gtk_clist_set_column_width (GTK_CLIST(wdata->listbox), 0, 16);
  gtk_clist_set_column_justification (GTK_CLIST(wdata->listbox), 0, GTK_JUSTIFY_CENTER);
  gtk_clist_set_column_width (GTK_CLIST(wdata->listbox), 1, 210);
  gtk_clist_set_column_justification (GTK_CLIST(wdata->listbox), 1, GTK_JUSTIFY_LEFT);
  gtk_clist_set_column_width (GTK_CLIST(wdata->listbox), 2, 30);
  gtk_clist_set_column_justification (GTK_CLIST(wdata->listbox), 2, GTK_JUSTIFY_RIGHT);

  g_signal_connect (G_OBJECT (wdata->listbox), "button_press_event",
		    G_CALLBACK (main_row_button), (gpointer) wdata);
  g_signal_connect (G_OBJECT (wdata->listbox), "select_row",
                    G_CALLBACK (main_row_select), (gpointer) wdata);
  g_signal_connect (G_OBJECT (wdata->listbox), "unselect_row",
                    G_CALLBACK (main_row_unselect), (gpointer) wdata);

#if GTK_MAJOR_VERSION >= 1 && GTK_MINOR_VERSION >= 1
  scrollwin = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_box_pack_start (GTK_BOX(vbox), scrollwin, TRUE, TRUE, 0);
  gtk_container_add (GTK_CONTAINER(scrollwin), wdata->listbox);
  gtk_widget_show (scrollwin);
#else
  gtk_box_pack_start (GTK_BOX(vbox) , wdata->listbox, TRUE, TRUE, 0);
#endif

  gtk_widget_show (window);

  load_pixmap ("updir.xpm", window, &updir_pixmap, &updir_mask);
  load_pixmap ("dir.xpm", window, &dir_pixmap, &dir_mask);
  load_pixmap ("doc.xpm", window, &doc_pixmap, &doc_mask);
  load_pixmap ("linkdir.xpm", window, &linkdir_pixmap, &linkdir_mask);
  load_pixmap ("linkfile.xpm", window, &linkfile_pixmap, &linkfile_mask);

  gtk_widget_show (wdata->listbox);

  gtk_widget_show (frame);
  gtk_widget_show (vbox); /* listbox */

  /* Vertical box containing buttons */
  vbox = gtk_vbox_new (FALSE, 0);
  gtk_container_border_width (GTK_CONTAINER(vbox), 5);
  gtk_box_pack_start (GTK_BOX(hbox) , vbox, FALSE, TRUE, 0);

  wdata->selectbutton = gtk_button_new_with_mnemonic (_(" _Select all "));
  g_signal_connect (G_OBJECT (wdata->selectbutton), "clicked",
		    G_CALLBACK (main_button_select_all), (gpointer) wdata);
  tooltips = gtk_tooltips_new();
  gtk_tooltips_set_tip (tooltips, wdata->selectbutton, _("Select all files"), NULL);
  gtk_box_pack_start (GTK_BOX(vbox), wdata->selectbutton, TRUE, FALSE, 0);
  gtk_widget_show (wdata->selectbutton);

  wdata->unselectbutton = gtk_button_new_with_mnemonic (_(" _Unselect all "));
  g_signal_connect (G_OBJECT (wdata->unselectbutton), "clicked",
		    G_CALLBACK (main_button_unselect_all), (gpointer) wdata);
  tooltips = gtk_tooltips_new();
  gtk_tooltips_set_tip (tooltips, wdata->unselectbutton, _("Unselected all files"), NULL);
  gtk_box_pack_start (GTK_BOX(vbox), wdata->unselectbutton, TRUE, FALSE, 0);
  gtk_widget_show (wdata->unselectbutton);

  wdata->addbutton = gtk_button_new_from_stock ("gtk-add");
  g_signal_connect (G_OBJECT (wdata->addbutton), "clicked",
		    G_CALLBACK (button_add), (gpointer) wdata);
  tooltips = gtk_tooltips_new();
  gtk_tooltips_set_tip (tooltips, wdata->addbutton, _("Add selected files to sendlist"), NULL);
  gtk_box_pack_start (GTK_BOX(vbox), wdata->addbutton, TRUE, FALSE, 0);
  gtk_widget_show (wdata->addbutton);

  wdata->sendbutton = gtk_button_new_with_label (_(" Send "));
  gtk_widget_set_sensitive (wdata->sendbutton, FALSE);
  g_signal_connect (G_OBJECT (wdata->sendbutton), "clicked",
		    G_CALLBACK (button_send), (gpointer) wdata);
  tooltips = gtk_tooltips_new();
  gtk_tooltips_set_tip (tooltips, wdata->sendbutton, _("Send recorded files to recipient"), NULL);
  gtk_box_pack_start (GTK_BOX(vbox), wdata->sendbutton, TRUE, FALSE, 0);
  gtk_widget_show (wdata->sendbutton);

  wdata->clearbutton = gtk_button_new_from_stock ("gtk-clear");
  gtk_widget_set_sensitive (wdata->clearbutton, FALSE);
  g_signal_connect (G_OBJECT (wdata->clearbutton), "clicked",
		    G_CALLBACK (button_clear), (gpointer) wdata);
  tooltips = gtk_tooltips_new();
  gtk_tooltips_set_tip (tooltips, wdata->clearbutton, _("Clear list of selected files"), NULL);
  gtk_box_pack_start (GTK_BOX(vbox), wdata->clearbutton, TRUE, FALSE, 0);
  gtk_widget_show (wdata->clearbutton);

  gtk_widget_show (vbox);
  gtk_widget_show (hbox);

  /* Add another box so we get some space between object and border */
  hbox = gtk_hbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER(wdata->container_send), hbox);
  gtk_container_border_width (GTK_CONTAINER(hbox), 5);

  /* This should be an additional box containing all selected files */
  wdata->filebox = gtk_clist_new_with_titles (3, titles);
  gtk_clist_column_titles_passive (GTK_CLIST(wdata->filebox));
  gtk_clist_set_selection_mode (GTK_CLIST(wdata->filebox), GTK_SELECTION_SINGLE);
  gtk_clist_set_column_width (GTK_CLIST(wdata->filebox), 0, 16);
  gtk_clist_set_column_justification (GTK_CLIST(wdata->filebox), 0, GTK_JUSTIFY_CENTER);
  gtk_clist_set_column_width (GTK_CLIST(wdata->filebox), 1, 340);
  gtk_clist_set_column_justification (GTK_CLIST(wdata->filebox), 1, GTK_JUSTIFY_LEFT);
  gtk_clist_set_column_width (GTK_CLIST(wdata->filebox), 2, 30);
  gtk_clist_set_column_justification (GTK_CLIST(wdata->filebox), 2, GTK_JUSTIFY_RIGHT);

#if GTK_MAJOR_VERSION >= 1 && GTK_MINOR_VERSION >= 1
  scrollwin = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_box_pack_start (GTK_BOX(hbox), scrollwin, TRUE, TRUE, 0);
  gtk_container_add (GTK_CONTAINER(scrollwin), wdata->filebox);
  gtk_widget_show (scrollwin);
#else
  gtk_box_pack_start (GTK_BOX(hbox) , wdata->filebox, TRUE, TRUE, 0);
#endif
  gtk_widget_show (wdata->filebox);
  gtk_widget_show (hbox);

  /* Vertical box containing the receive container */
  wdata->container_receive = gtk_vbox_new(FALSE, 0);

  /* Input field for directory */
  wdata->rdirinput = gtk_entry_new_with_max_length (60);
  gtk_box_pack_start (GTK_BOX(wdata->container_receive), wdata->rdirinput, FALSE, FALSE, FALSE);
  gtk_widget_show (wdata->rdirinput);

  if ((cp = get_current_dir_name()))
    gtk_entry_set_text (GTK_ENTRY(wdata->rdirinput), cp);

  wdata->receiver = gtk_clist_new_with_titles (7, rtitles);
  gtk_clist_column_titles_passive (GTK_CLIST(wdata->receiver));
  gtk_clist_set_selection_mode (GTK_CLIST(wdata->receiver), GTK_SELECTION_MULTIPLE);
  gtk_clist_set_column_width (GTK_CLIST(wdata->receiver), 0, 16);
  gtk_clist_set_column_justification (GTK_CLIST(wdata->receiver), 0, GTK_JUSTIFY_CENTER);
  gtk_clist_set_column_width (GTK_CLIST(wdata->receiver), 1, 230);
  gtk_clist_set_column_justification (GTK_CLIST(wdata->receiver), 1, GTK_JUSTIFY_LEFT);
  gtk_clist_set_column_width (GTK_CLIST(wdata->receiver), 2, 90);
  gtk_clist_set_column_justification (GTK_CLIST(wdata->receiver), 1, GTK_JUSTIFY_LEFT);
  gtk_clist_set_column_width (GTK_CLIST(wdata->receiver), 3, 30);
  gtk_clist_set_column_justification (GTK_CLIST(wdata->receiver), 3, GTK_JUSTIFY_RIGHT);
  gtk_clist_set_column_visibility (GTK_CLIST(wdata->receiver), 4, FALSE);
  gtk_clist_set_column_visibility (GTK_CLIST(wdata->receiver), 5, FALSE);
  gtk_clist_set_column_visibility (GTK_CLIST(wdata->receiver), 6, FALSE);

  g_signal_connect (G_OBJECT (wdata->receiver), "select_row",
		    G_CALLBACK (receiver_row_select), (gpointer) wdata);
  g_signal_connect (G_OBJECT (wdata->receiver), "button_press_event",
		    G_CALLBACK (receiver_row_button), (gpointer) wdata);

#if GTK_MAJOR_VERSION >= 1 && GTK_MINOR_VERSION >= 1
  scrollwin = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_box_pack_start (GTK_BOX(wdata->container_receive), scrollwin, TRUE, TRUE, 0);
  gtk_container_add (GTK_CONTAINER(scrollwin), wdata->receiver);
  gtk_widget_show (scrollwin);
#else
  gtk_box_pack_start (GTK_BOX(wdata->container_receive), clist, TRUE, TRUE, 0);
#endif

  gtk_widget_show (wdata->receiver);

  /* Frame containing aditional information about files */
  frame = gtk_frame_new (NULL);
  gtk_container_border_width (GTK_CONTAINER(frame), 2);
  gtk_widget_show (frame);
  gtk_box_pack_start (GTK_BOX(wdata->container_receive), frame, FALSE, TRUE, 0);

  vbox = gtk_vbox_new(FALSE, 0);
  gtk_widget_show (vbox);
  gtk_container_add (GTK_CONTAINER(frame), vbox);

  hbox = gtk_hbox_new(FALSE, 5);
  gtk_widget_show (hbox);
  gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);

  wdata->rinfo = gtk_label_new (NULL);
  gtk_widget_show (wdata->rinfo);
  gtk_box_pack_start (GTK_BOX(hbox), wdata->rinfo, FALSE, FALSE, 3);

  hbox = gtk_hbox_new(FALSE, 5);
  gtk_widget_show (hbox);
  gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);

  wdata->rcomment = gtk_label_new (NULL);
  gtk_widget_show (wdata->rcomment);
  gtk_box_pack_start (GTK_BOX(hbox), wdata->rcomment, FALSE, FALSE, 3);

  hbox = gtk_hbox_new(FALSE, 5);
  gtk_widget_show (hbox);
  gtk_box_set_homogeneous (GTK_BOX(hbox), FALSE);
  gtk_box_pack_end (GTK_BOX (wdata->container_receive), hbox, FALSE, FALSE, 5);

  button = gtk_button_new_with_label (_("Receive"));
  gtk_widget_set_sensitive (button, TRUE);
  g_signal_connect (G_OBJECT (button), "clicked",
		    G_CALLBACK (button_receive), (gpointer) wdata);
  tooltips = gtk_tooltips_new();
  gtk_tooltips_set_tip (tooltips, button, _("Receive all selected files and archives"), NULL);
  gtk_box_pack_start (GTK_BOX(hbox), button, TRUE, FALSE, 3);
  gtk_widget_show (button);

  button = gtk_button_new_from_stock ("gtk-refresh");
  gtk_widget_set_sensitive (button, TRUE);
  g_signal_connect (G_OBJECT (button), "clicked",
		    G_CALLBACK (button_refresh), (gpointer) wdata);
  tooltips = gtk_tooltips_new();
  gtk_tooltips_set_tip (tooltips, button, _("Refresh receive queue listing"), NULL);
  gtk_box_pack_start (GTK_BOX(hbox), button, TRUE, FALSE, 3);
  gtk_widget_show (button);

  /* Vertical box containing the message container */
  wdata->container_message = gtk_vbox_new(FALSE, 0);

  frame = gtk_frame_new (NULL);
  gtk_container_border_width (GTK_CONTAINER(frame), 5);
  gtk_container_add (GTK_CONTAINER(wdata->container_message), frame);
  gtk_widget_show (frame);

  vbox = gtk_vbox_new (FALSE, 0);
  gtk_container_border_width (GTK_CONTAINER(vbox), 5);
  gtk_container_add (GTK_CONTAINER(frame), vbox);
  gtk_widget_show (vbox);

  label = gtk_label_new (_("Recipient"));
  gtk_misc_set_alignment (GTK_MISC(label), 0, 0);
  gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

  wdata->addrok = 0;
  wdata->addrinput = gtk_combo_new();
  if (config.addrs)
    gtk_combo_set_popdown_strings (GTK_COMBO(wdata->addrinput), config.addrs);
  gtk_entry_set_text (GTK_ENTRY(GTK_COMBO(wdata->addrinput)->entry), "");
  g_signal_connect (G_OBJECT (GTK_COMBO(wdata->addrinput)->entry), "changed",
		    G_CALLBACK (message_addr_change), (gpointer) wdata);
  tooltips = gtk_tooltips_new();
  gtk_tooltips_set_tip (tooltips, GTK_COMBO(wdata->addrinput)->entry,
			_("Enter recipient's address"), NULL);
  gtk_box_pack_start (GTK_BOX(vbox), GTK_WIDGET(wdata->addrinput), FALSE, FALSE, 0);
  gtk_widget_show (wdata->addrinput);

  label = gtk_label_new ("");
  gtk_misc_set_alignment (GTK_MISC(label), 0, 0);
  gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

  label = gtk_label_new (_("Message"));
  gtk_misc_set_alignment (GTK_MISC(label), 0, 0);
  gtk_box_pack_start (GTK_BOX(vbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

  wdata->msginput = gtk_text_view_new();
  gtk_widget_show (wdata->msginput);
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(wdata->msginput));
  g_signal_connect (G_OBJECT (buffer), "changed",
		    G_CALLBACK (message_input_change), (gpointer) wdata);
  tooltips = gtk_tooltips_new();
  gtk_tooltips_set_tip (tooltips, wdata->msginput,
			_("Type your message here"), NULL);

#if GTK_MAJOR_VERSION >= 1 && GTK_MINOR_VERSION >= 1
  scrollwin = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_box_pack_start (GTK_BOX(vbox), scrollwin, TRUE, TRUE, 0);
  gtk_container_add (GTK_CONTAINER(scrollwin), wdata->msginput);
  gtk_widget_show (scrollwin);
#else
  gtk_box_pack_start (GTK_BOX(vbox), wdata->msginput, TRUE, TRUE, 5);  
#endif

  hbox = gtk_hbox_new(FALSE, 5);
  gtk_widget_show (hbox);
  gtk_box_set_homogeneous (GTK_BOX(hbox), FALSE);
  gtk_box_pack_end (GTK_BOX(wdata->container_message), hbox, FALSE, FALSE, 5);

  wdata->msgsend = gtk_button_new_with_label (_("Send"));
  gtk_widget_set_sensitive (wdata->msgsend, FALSE);
  g_signal_connect (G_OBJECT (wdata->msgsend), "clicked",
		    G_CALLBACK (button_msgsend), (gpointer) wdata);
  tooltips = gtk_tooltips_new();
  gtk_tooltips_set_tip (tooltips, wdata->msgsend, _("Send the message to the recipient"), NULL);
  gtk_box_pack_start (GTK_BOX(hbox), wdata->msgsend, TRUE, FALSE, 3);
  gtk_widget_show (wdata->msgsend);

  /* -------------------------------------------------- */

  switch (startmode) {
  case MOD_SEND:
    if (getcwd (cwd, sizeof(cwd)))
      read_directory (wdata, cwd);
    gtk_widget_show (wdata->container_send);
    break;
  case MOD_RECEIVE:
    parse_receive (wdata);
    gtk_widget_show (wdata->container_receive);
    break;
  case MOD_MESSAGE:
    gtk_widget_show (wdata->container_message);
    break;
  }

  gtk_container_add (GTK_CONTAINER (mainbox), wdata->container_send);
  gtk_container_add (GTK_CONTAINER (mainbox), wdata->container_receive);
  gtk_container_add (GTK_CONTAINER (mainbox), wdata->container_message);

  gtk_widget_show (mainbox);
}
