/* IglooFTP - Graphical and User Friendly FTP Client.
 * Copyright (c) 1998-1999 Jean-Marc Jacquet. 
 * All rights reserved.
 * 
 * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE
 *
 * IglooFTP Original Packages, information and support,  
 * can be obtained at :
 *                              http://www.littleigloo.org
 * 
 *
 */

#include <gtk/gtk.h>
#include <unistd.h>
#include <string.h>

#include "protos.h"
#include "IglooEdit.h"







/* INFO Functions */

/* STATIC : 
 * IGLOO_EDIT_set_window_title
 * IGLOO_EDIT_show_size 
 * IGLOO_EDIT_show_pos 
 */

static void
IGLOO_EDIT_set_window_title (TEXTinfo * text_info)
{
  char title_buf[1024];
  char *ptr = strrchr (text_info->name, '/');
  sprintf (title_buf, "IglooEdit: %s%c", ptr == NULL ? text_info->name : ptr + 1, text_info->modified ? '*' : ' ');
  gtk_window_set_title (GTK_WINDOW (text_info->edit_window), title_buf);
}

static void
IGLOO_EDIT_show_size (TEXTinfo * text_info)
{
  char label_buf[258];
  guint this_size = gtk_text_get_length (GTK_TEXT (text_info->edit_text));
  sprintf (label_buf, " FILE: %s (%u Byte%c)", text_info->name, this_size, this_size > 1 ? 's' : 32);
  gtk_label_set_text (GTK_LABEL (text_info->edit_size_label), label_buf);
}

static void
IGLOO_EDIT_show_status (TEXTinfo * text_info)
{
  gtk_label_set_text (GTK_LABEL (text_info->edit_status_label), text_info->modified ? "  UNSAVED " : "");
  IGLOO_EDIT_set_window_title (text_info);
}

static void
IGLOO_EDIT_show_pos (TEXTinfo * text_info)
{
  register int col = 0;
  register guint this_pos = GTK_EDITABLE (text_info->edit_text)->current_pos + 1;
  gchar *c;
  char label_buf[15];

  while (this_pos > 1)
    {
      c = gtk_editable_get_chars (GTK_EDITABLE (text_info->edit_text), this_pos - 1, this_pos--);
      if (c == NULL)
	break;
      if (*c == 10)
	break;
      col++;
    }

  sprintf (label_buf, "   COL: %03i", col);
  gtk_label_set_text (GTK_LABEL (text_info->edit_pos_label), label_buf);
  gtk_widget_grab_focus (text_info->edit_text);
}






/* IO FUNCTIONS */

/* STATIC : 
 * IGLOO_EDIT_load_file 
 * IGLOO_EDIT_save_file 
 */

static void
IGLOO_EDIT_load_file (TEXTinfo * text_info)
{
#define TEXT_LEN (off_t) stat_buf.st_size
  FILE *in;
  gchar *text_buf;
  struct stat stat_buf;

  if (access (text_info->name, F_OK) || stat (text_info->name, &stat_buf))
    {
      char msg_buf[1024];
      sprintf (msg_buf, "Can't open %s for reading.", text_info->name);
      alert_ok ("Load Error", msg_buf, "Ok");
      return;
    }

  if ((text_buf = (char *) g_malloc (TEXT_LEN + 1)) == NULL)
    return;

  MEM0 (text_buf);
  in = fopen (text_info->name, "r");
  fread (text_buf, TEXT_LEN, 1, in);
  fclose (in);
  text_buf[TEXT_LEN] = 0;

  clear_text (text_info->edit_text);
  realize_text (text_info->edit_text, text_buf);

  g_free (text_buf);

  text_info->modified = FALSE;
  IGLOO_EDIT_show_size (text_info);
  IGLOO_EDIT_show_status (text_info);
}



static void
IGLOO_EDIT_save_file (TEXTinfo * text_info)
{
#define SAVE_BUF_SIZE 2048
  FILE *out;
  gchar *buf = g_malloc0 (SAVE_BUF_SIZE + 1);
  guint pos = 0;
  int buf_size;
  guint file_length = gtk_text_get_length (GTK_TEXT (text_info->edit_text));

  if ((out = fopen (text_info->name, "w")) == NULL)
    {
      sprintf (buf, "Can't open %s for writing.", text_info->name);
      alert_ok ("Save Error", buf, "Ok");
      return;
    }

  while (pos < file_length)
    {
      buf_size = file_length - pos >= SAVE_BUF_SIZE ? SAVE_BUF_SIZE : file_length - pos;
      strcpy (buf, gtk_editable_get_chars (GTK_EDITABLE (text_info->edit_text), pos, pos + buf_size));
      fwrite (buf, buf_size, 1, out);
      pos += buf_size;
    }

  fflush (out);
  fclose (out);
  g_free (buf);
  text_info->modified = FALSE;
  IGLOO_EDIT_show_size (text_info);
  IGLOO_EDIT_show_status (text_info);
  gtk_label_set_text (GTK_LABEL (text_info->edit_status_label), "  SAVED ");
}








/* FILE MENU FUNCTIONS */

/* STATIC:
 *  IGLOO_EDIT_save 
 *  IGLOO_EDIT_save_on_fileselect_ok
 *  IGLOO_EDIT_save_as 
 *  IGLOO_EDIT_open_on_fileselect_ok 
 *  IGLOO_EDIT_open 
 *  IGLOO_EDIT_new 
 */

static void
IGLOO_EDIT_save (GtkWidget * widget, TEXTinfo * text_info)
{
  IGLOO_EDIT_save_file (text_info);
}

static void
IGLOO_EDIT_save_on_fileselect_ok (GtkWidget * widget, TEXTinfo * text_info)
{
  char buf[1024];
  GtkWidget *fs = gtk_widget_get_toplevel (widget);
  MEM0 (buf);
  strncpy (buf, gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)), sizeof (buf) - 1);
  gtk_widget_destroy (GTK_WIDGET (fs));
  if (strlen (buf))
    {
      strncpy (text_info->name, buf, sizeof (text_info->name) - 1);
      IGLOO_EDIT_save_file (text_info);
      IGLOO_EDIT_save_set_sensitive (text_info, TRUE);
    }
}

static void
IGLOO_EDIT_save_as (GtkWidget * widget, TEXTinfo * text_info)
{
  create_file_select (text_info->edit_window, "Save file as ...", text_info->name, IGLOO_EDIT_save_on_fileselect_ok, (TEXTinfo *) text_info);
}


static void
IGLOO_EDIT_open_on_fileselect_ok (GtkWidget * widget, TEXTinfo * text_info)
{
  char buf[1024];
  GtkWidget *fs = gtk_widget_get_toplevel (widget);
  MEM0 (buf);
  strncpy (buf, gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)), sizeof (buf) - 1);
  gtk_widget_destroy (GTK_WIDGET (fs));
  if (strlen (buf))
    {
      strncpy (text_info->name, buf, sizeof (text_info->name) - 1);
      IGLOO_EDIT_load_file (text_info);
      IGLOO_EDIT_save_set_sensitive (text_info, TRUE);
    }
}

static void
IGLOO_EDIT_open (GtkWidget * widget, TEXTinfo * text_info)
{
  if (text_info->modified)
    if (!IGLOO_EDIT_ask_to_save_modified_file (text_info))
      return;
  create_file_select (text_info->edit_window, "Open file ...", "./", IGLOO_EDIT_open_on_fileselect_ok, (TEXTinfo *) text_info);
}


static void
IGLOO_EDIT_new (GtkWidget * widget, TEXTinfo * text_info)
{
  if (text_info->modified)
    if (!IGLOO_EDIT_ask_to_save_modified_file (text_info))
      return;

  clear_text (text_info->edit_text);
  strcpy (text_info->name, "untitled");
  text_info->modified = FALSE;
  IGLOO_EDIT_show_size (text_info);
  IGLOO_EDIT_show_status (text_info);
  IGLOO_EDIT_save_set_sensitive (text_info, FALSE);
}









/* QUIT FUNCTIONS */

/* STATIC
 * static char IGLOO_EDIT_ask_to_save_modified_file 
 * static void IGLOO_EDIT_quit
 * static gint IGLOO_EDIT_delete_event 
 * static void IGLOO_EDIT_destroy_window
 */

static char
IGLOO_EDIT_ask_to_save_modified_file (TEXTinfo * text_info)
{
  char buf[1024];
  char *ptr = strrchr (text_info->name, '/');
  int user_say;

  sprintf (buf, "\"%s\" has been modified.\nDo you want to save it ?", ptr == NULL ? text_info->name : ptr);

  if (!(user_say = alert_yes_no_cancel_modal ("Save modified file?", buf, "Yes", "No")))
    return FALSE;

  if (user_say == 1)
    IGLOO_EDIT_save_file (text_info);

  return TRUE;
}


static void
IGLOO_EDIT_quit (GtkWidget * widget, TEXTinfo * text_info)
{
  if (text_info->modified)
    if (!IGLOO_EDIT_ask_to_save_modified_file (text_info))
      return;
  gtk_widget_destroy (text_info->edit_window);
}


static gint
IGLOO_EDIT_delete_event (GtkWidget * widget, GdkEvent * event, TEXTinfo * text_info)
{
  return text_info->modified ? !IGLOO_EDIT_ask_to_save_modified_file (text_info) : FALSE;
}

static void
IGLOO_EDIT_destroy_window (GtkWidget * widget, TEXTinfo * text_info)
{
  if (text_info->REXEC)
    {
      REXEC_end ();
      gtk_main_quit ();
    }
  g_free (text_info);
}







/* WINDOW FUNCTION */

/* PUBLIC :
 * IglooEdit 
 * STATIC :
 * IGLOO_EDIT_text_change 
 * IGLOO_EDIT_key_press
 * IGLOO_EDIT_create_menu 
 * IGLOO_EDIT_save_set_sensitive
 *
 */

#define IglooEdit(a) IGLOO_EDIT (a, FALSE)
#define IglooEdit_remote(a) IGLOO_EDIT (a, TRUE)

void
IGLOO_EDIT (char *filename, char REXEC)
{
  GtkWidget *vbox;
  GtkWidget *hbox;
  GtkWidget *frame;
  TEXTinfo *text_info = g_malloc0 (sizeof (TEXTinfo));

  text_info->edit_window = gtk_window_new (GTK_WINDOW_DIALOG);
  text_info->edit_text = gtk_text_new (NULL, NULL);
  text_info->edit_size_label = gtk_label_new (" ");
  text_info->edit_pos_label = gtk_label_new (REXEC ? "" : "   COL: 000");
  text_info->edit_status_label = gtk_label_new (" ");
  text_info->REXEC = REXEC;
  gtk_widget_set_usize (GTK_WIDGET (text_info->edit_window), 600, 500);
  gtk_window_position (GTK_WINDOW (text_info->edit_window), GTK_WIN_POS_CENTER);
  gtk_window_set_title (GTK_WINDOW (text_info->edit_window), "IglooEdit");
  gtk_container_border_width (GTK_CONTAINER (text_info->edit_window), 0);
  gtk_window_set_policy (GTK_WINDOW (text_info->edit_window), TRUE, TRUE, FALSE);
  gtk_window_set_transient_for (GTK_WINDOW (text_info->edit_window), GTK_WINDOW (window));
  gtk_widget_realize (text_info->edit_window);

  vbox = v_box (text_info->edit_window, FALSE, 0, 0);

  IGLOO_EDIT_create_menu (vbox, text_info);
  gtk_accel_group_attach (text_info->edit_accel, GTK_OBJECT (text_info->edit_window));
  gtk_accel_group_attach (text_info->edit_accel, GTK_OBJECT (text_info->edit_text));

  IGLOO_EDIT_create_toolbar (text_info->edit_window, vbox, text_info);

  gtk_widget_set_name (text_info->edit_text, "EditText");
  create_text_area (text_info->edit_text, vbox);
  gtk_text_set_editable (GTK_TEXT (text_info->edit_text), TRUE);


  frame = create_frame (vbox, NULL, FALSE, TRUE, GTK_SHADOW_NONE);
  hbox = h_box (frame, FALSE, 0, 0);

  gtk_box_pack_start (GTK_BOX (hbox), text_info->edit_size_label, FALSE, FALSE, 0);
  gtk_widget_show (text_info->edit_size_label);

  gtk_box_pack_start (GTK_BOX (hbox), text_info->edit_pos_label, FALSE, FALSE, 0);
  gtk_widget_show (text_info->edit_pos_label);

  gtk_box_pack_end (GTK_BOX (hbox), text_info->edit_status_label, FALSE, FALSE, 0);
  gtk_widget_show (text_info->edit_status_label);

  gtk_widget_show (text_info->edit_window);

  if (REXEC)
    gtk_window_set_modal (GTK_WINDOW (text_info->edit_window), TRUE);
  else
    PROCESS_EVENTS;

  gtk_signal_connect (GTK_OBJECT (text_info->edit_window), "delete_event",
		      (GtkSignalFunc) IGLOO_EDIT_delete_event, text_info);


  gtk_signal_connect (GTK_OBJECT (text_info->edit_window), "destroy",
		      (GtkSignalFunc) IGLOO_EDIT_destroy_window, text_info);


  gtk_signal_connect (GTK_OBJECT (text_info->edit_text), "changed",
		      GTK_SIGNAL_FUNC (IGLOO_EDIT_text_change), text_info);

  gtk_signal_connect_after (GTK_OBJECT (text_info->edit_text), "key_press_event",
			 GTK_SIGNAL_FUNC (IGLOO_EDIT_key_press), text_info);

  gtk_signal_connect_after (GTK_OBJECT (text_info->edit_text), "button_press_event",
			 GTK_SIGNAL_FUNC (IGLOO_EDIT_key_press), text_info);

  if (filename != NULL)
    {
      strcpy (text_info->name, filename);
      IGLOO_EDIT_load_file (text_info);
    }
  else
    IGLOO_EDIT_new (NULL, text_info);

  if (REXEC)
    gtk_main ();

}



static void
IGLOO_EDIT_text_change (GtkWidget * widget, TEXTinfo * text_info)
{
  if (!text_info->modified)
    {
      text_info->modified = TRUE;
      IGLOO_EDIT_show_status (text_info);
    }
  IGLOO_EDIT_show_size (text_info);
}

static void
IGLOO_EDIT_key_press (GtkWidget * widget, GdkEventKey * event, TEXTinfo * text_info)
{
  IGLOO_EDIT_show_pos (text_info);
}






static void
IGLOO_EDIT_create_menu (GtkWidget * vbox, TEXTinfo * text_info)
{
  GtkWidget *menu;
  GtkWidget *handle_box;
  GtkWidget *menu_bar;
  GtkWidget *menu_item;

#define EDIT_ACCEL(x,y,z)  gtk_widget_add_accelerator (x, "activate", text_info->edit_accel, y, z, GTK_ACCEL_VISIBLE );
  text_info->edit_accel = gtk_accel_group_get_default ();

  this_handle_box = handle_box = gtk_handle_box_new ();
  gtk_box_pack_start (GTK_BOX (vbox), handle_box, FALSE, FALSE, 0);
  gtk_widget_show (handle_box);

  menu_bar = gtk_menu_bar_new ();
  gtk_container_add (GTK_CONTAINER (handle_box), menu_bar);
  gtk_widget_show (menu_bar);


  /* FILE MENU */
  menu = create_sub_menu (menu_bar, "File ", FALSE);

  menu_tearoff (menu);
  menu_item = create_menu_item (menu, "New", TRUE, GTK_SIGNAL_FUNC (IGLOO_EDIT_new), text_info);
  EDIT_ACCEL (menu_item, 'N', GDK_CONTROL_MASK);
  menu_item = create_menu_item (menu, "Open ...", TRUE, GTK_SIGNAL_FUNC (IGLOO_EDIT_open), text_info);
  EDIT_ACCEL (menu_item, 'O', GDK_CONTROL_MASK);
  menu_separator (menu);
  text_info->menu_save = create_menu_item (menu, "Save", TRUE, GTK_SIGNAL_FUNC (IGLOO_EDIT_save), text_info);
  EDIT_ACCEL (text_info->menu_save, 'S', GDK_CONTROL_MASK);
  create_menu_item (menu, "Save As ...", TRUE, GTK_SIGNAL_FUNC (IGLOO_EDIT_save_as), text_info);
  menu_separator (menu);
  menu_item = create_menu_item (menu, "Quit IglooEdit  ", TRUE, GTK_SIGNAL_FUNC (IGLOO_EDIT_quit), text_info);
  EDIT_ACCEL (menu_item, 'Q', GDK_CONTROL_MASK);
  menu_separator (menu);
  menu_separator (menu);

  /* EDIT MENU */
  menu = create_sub_menu (menu_bar, "Edit ", FALSE);

  menu_tearoff (menu);
  menu_item = create_menu_item (menu, "Cut", TRUE, GTK_SIGNAL_FUNC (text_cut_to_clipboard), text_info->edit_text);
  EDIT_ACCEL (menu_item, 'X', GDK_CONTROL_MASK);
  menu_item = create_menu_item (menu, "Copy to Clipboard  ", TRUE, GTK_SIGNAL_FUNC (text_copy_to_clipboard), text_info->edit_text);
  EDIT_ACCEL (menu_item, 'C', GDK_CONTROL_MASK);
  menu_item = create_menu_item (menu, "Paste from Clipboard ", TRUE, GTK_SIGNAL_FUNC (text_paste_from_clipboard), text_info->edit_text);
  EDIT_ACCEL (menu_item, 'V', GDK_CONTROL_MASK);
  menu_separator (menu);
  menu_item = create_menu_item (menu, "Select All", TRUE, GTK_SIGNAL_FUNC (text_select_all), text_info->edit_text);
  EDIT_ACCEL (menu_item, 'A', GDK_CONTROL_MASK);
  menu_separator (menu);
  menu_separator (menu);

  /* HELP MENU */
  menu = create_sub_menu (menu_bar, "Help ", TRUE);

  menu_tearoff (menu);
  create_menu_item (menu, "About  ", TRUE, GTK_SIGNAL_FUNC (create_about_window), NULL);
  menu_separator (menu);
  create_menu_item (menu, "License  ", TRUE, GTK_SIGNAL_FUNC (doc_show_text_file_from_widget), GINT_TO_POINTER (DOC_COPYING));
  menu_separator (menu);
  menu_separator (menu);
}



static void
IGLOO_EDIT_create_toolbar (GtkWidget * window, GtkWidget * vbox, TEXTinfo * text_info)
{
#include "pixmaps/IglooEdit_new.xpm"
#include "pixmaps/IglooEdit_load.xpm"
#include "pixmaps/IglooEdit_save.xpm"
#include "pixmaps/IglooEdit_copy.xpm"
#include "pixmaps/IglooEdit_paste.xpm"
#include "pixmaps/IglooEdit_quit.xpm"

  GtkWidget *toolbar;
  GtkWidget *handle_box;

  handle_box = gtk_handle_box_new ();
  gtk_box_pack_start (GTK_BOX (vbox), handle_box, FALSE, FALSE, 0);
  gtk_widget_show (handle_box);

  toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
  gtk_container_add (GTK_CONTAINER (handle_box), toolbar);
  gtk_widget_show (toolbar);

  gtk_toolbar_set_space_size (GTK_TOOLBAR (toolbar), 12);
  gtk_container_border_width (GTK_CONTAINER (toolbar), 2);
  gtk_toolbar_set_button_relief (GTK_TOOLBAR (toolbar), GTK_RELIEF_NONE);

  gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), "New", " Create a new file ", "", new_pixmap (window, IglooEdit_new_xpm),
			   GTK_SIGNAL_FUNC (IGLOO_EDIT_new), text_info);

  gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));

  gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), "Open", " Open a file ", "", new_pixmap (window, IglooEdit_load_xpm),
			   GTK_SIGNAL_FUNC (IGLOO_EDIT_open), text_info);

  text_info->toolbar_save =
    gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), "Save", " Save current edited file ", "", new_pixmap (window, IglooEdit_save_xpm),
			     GTK_SIGNAL_FUNC (IGLOO_EDIT_save), text_info);

  gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));

  gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), "Copy", " Copy to clipboard ", "", new_pixmap (window, IglooEdit_copy_xpm),
	    GTK_SIGNAL_FUNC (text_copy_to_clipboard), text_info->edit_text);

  gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), "Paste", " Paste from clipboard ", "", new_pixmap (window, IglooEdit_paste_xpm),
	 GTK_SIGNAL_FUNC (text_paste_from_clipboard), text_info->edit_text);

  gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));

  gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), "Quit", " Quit IglooEdit ", "", new_pixmap (window, IglooEdit_quit_xpm),
			   GTK_SIGNAL_FUNC (IGLOO_EDIT_quit), text_info);


}




static void
IGLOO_EDIT_save_set_sensitive (TEXTinfo * text_info, char FLAG)
{
  gtk_widget_set_sensitive (text_info->menu_save, FLAG);
  gtk_widget_set_sensitive (text_info->toolbar_save, FLAG);
}



/* EOF */
