/*
    ragmaan/scratchpad.c            (C) 2003 Raymond (zandbergen@home.nl)

    "ragmaan" is an anagram generator

    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-1307  USA
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <glib.h>
#include <gtk/gtk.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gettext.h"
#include "ragmaan.h"
#include "hash_func.h"
#include "search.h"
#include "db_files.h"
#include "state_stack.h"
#include "idle_task.h"
#include "scratchpad.h"

gchar *scratchpad_name = NULL;

static gboolean scratchpad_modified;

/* don't add name to window title and don't silently overwrite */
static gboolean scratchpad_name_hint_only = TRUE;

static void
scratchpad_load2 (GtkWidget * unused, GtkFileSelection * file_selector);
static void
scratchpad_save2 (GtkWidget * unused, GtkFileSelection * file_selector);
static gint scratchpad_flag_changed (GtkTextBuffer * unused1,
				     gpointer unused2);
void
scratchpad_set_modified (gboolean mod)
{
  GtkTextBuffer *tb;
  scratchpad_modified = mod;

  gtk_widget_set_sensitive (global_widgets.toolbar_button[TOOLBAR_SAVE], mod);
  tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (global_widgets.scratchpad));
  mod = gtk_text_buffer_get_char_count (tb) > 0;
  gtk_widget_set_sensitive (global_widgets.toolbar_button[TOOLBAR_NEW], mod);
}

gboolean
scratchpad_get_modified (void)
{
  return scratchpad_modified;
}

void
scratchpad_update_name (gchar * name, gboolean hint_only)
{
  gchar *title;
  gchar *base;

  if (scratchpad_name)
    g_free (scratchpad_name);
  scratchpad_name = g_strdup (name);
  scratchpad_name_hint_only = hint_only;
  if (!hint_only)
    {
      base = g_path_get_basename (name);
      title = g_strdup_printf (PACKAGE " - %s", base);
      gtk_window_set_title (GTK_WINDOW (global_widgets.main_window), title);
      g_free (base);
      g_free (title);
    }
}

GtkWidget *
new_scratchpad (void)
{
  GtkWidget *view;
  GtkWidget *sw;
  GtkTextBuffer *tb;

  sw = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
				       GTK_SHADOW_ETCHED_IN);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_widget_set_size_request (sw, 300, 200);

  view = gtk_text_view_new ();
  gtk_container_add (GTK_CONTAINER (sw), view);
  tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
  g_signal_connect (G_OBJECT (tb),
		    "changed", G_CALLBACK (scratchpad_flag_changed), NULL);
  global_widgets.scratchpad = view;
  scratchpad_set_modified (FALSE);
  return sw;
}

static gint
scratchpad_flag_changed (GtkTextBuffer * unused1, gpointer unused2)
{
  scratchpad_set_modified (TRUE);
  return TRUE;
}

void
scratchpad_printf (const gchar * fmt, ...)
{
  GtkTextBuffer *tb;
  GtkTextMark *tm;
  va_list ap;
  gchar *buf;

  va_start (ap, fmt);
  buf = g_strdup_vprintf (fmt, ap);
  tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (global_widgets.scratchpad));
  gtk_text_buffer_insert_at_cursor (tb, buf, strlen (buf));
  g_free (buf);
  tm = gtk_text_buffer_get_insert (tb);
  gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (global_widgets.scratchpad),
				tm, 0.0, TRUE, 0.0, 0.9);
}

gint
scratchpad_copy (GtkWidget * unused1, gpointer unused2)
{
  const gchar *p;
  if (!action_allowed (ALLOW_COPY))
    return FALSE;
  p =
    gtk_label_get_text (GTK_LABEL (global_widgets.intermediate_result_label));
  scratchpad_printf (" %s\n", p);
  return FALSE;
}

gint
scratchpad_clear (GtkWidget * unused1, gpointer unused2)
{
  GtkTextBuffer *tb;
  if (scratchpad_modified)
    {
      GtkWidget *dialog;
      gint response;
      dialog =
	gtk_message_dialog_new (GTK_WINDOW (global_widgets.main_window),
				GTK_DIALOG_DESTROY_WITH_PARENT,
				GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL,
				_("Erase current results?"));
      response = gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (dialog);
      if (response == GTK_RESPONSE_CANCEL)
	return TRUE;
    }
  tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (global_widgets.scratchpad));
  gtk_text_buffer_set_text (tb, "", 0);
  scratchpad_name_hint_only = TRUE;
  scratchpad_set_modified (FALSE);
  return FALSE;
}

gint
scratchpad_save (GtkWidget * unused1, gpointer unused2)
{
  if (!scratchpad_name_hint_only)
    scratchpad_save2 (NULL, NULL);
  else
    scratchpad_save_as (NULL, NULL);
  return TRUE;
}

gint
scratchpad_save_as (GtkWidget * unused1, gpointer unused2)
{
  new_file_selector (_("save results"), scratchpad_save2, scratchpad_name);
  return TRUE;
}

static void
scratchpad_save2 (GtkWidget * unused, GtkFileSelection * file_selector)
{
  int fd;
  GtkTextBuffer *tb;
  GtkTextIter a, b;
  gchar *selected_file_name, *p;
  GtkWindow *parent;
  gboolean save_as = !!file_selector;

  if (save_as)
    {
      selected_file_name =
	g_strdup (gtk_file_selection_get_filename
		  (GTK_FILE_SELECTION (file_selector)));
      parent = GTK_WINDOW (file_selector);
      fd = open (selected_file_name, O_WRONLY | O_CREAT | O_EXCL, 0622);
    }
  else
    {
      selected_file_name = g_strdup (scratchpad_name);
      parent = GTK_WINDOW (global_widgets.main_window);
      fd = open (selected_file_name, O_WRONLY | O_CREAT | O_TRUNC, 0622);
    }

  if (-1 == fd && errno == EEXIST)
    {
      gint response;
      GtkWidget *dialog;
      dialog =
	gtk_message_dialog_new (parent,
				GTK_DIALOG_DESTROY_WITH_PARENT,
				GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL,
				_("%s already exists. Overwrite?"),
				selected_file_name);
      response = gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (dialog);
      if (response == GTK_RESPONSE_CANCEL)
	{
	  g_free (selected_file_name);
	  return;
	}
      fd = open (selected_file_name, O_WRONLY, 0622);
    }
  if (-1 == fd)
    {
      GtkWidget *dialog;
      dialog =
	gtk_message_dialog_new (parent,
				GTK_DIALOG_DESTROY_WITH_PARENT,
				GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
				_("Could not create %s: %s"),
				selected_file_name, g_strerror (errno));
      g_free (selected_file_name);
      gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (GTK_WIDGET (dialog));
      return;
    }
  scratchpad_update_name (selected_file_name, FALSE);
  g_free (selected_file_name);
  if (save_as)
    gtk_widget_destroy (GTK_WIDGET (parent));
  tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (global_widgets.scratchpad));
  gtk_text_buffer_get_iter_at_offset (tb, &a, 0);
  gtk_text_buffer_get_iter_at_offset (tb, &b, 0);
  gtk_text_iter_forward_to_end (&b);
  p = gtk_text_buffer_get_text (tb, &a, &b, FALSE);
  write (fd, p, strlen (p));
  close (fd);
  scratchpad_set_modified (FALSE);
}

gint
scratchpad_load (GtkWidget * unused1, gpointer unused2)
{
  if (scratchpad_modified)
    {
      GtkWidget *dialog;
      gint response;
      dialog =
	gtk_message_dialog_new (GTK_WINDOW (global_widgets.main_window),
				GTK_DIALOG_DESTROY_WITH_PARENT,
				GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL,
				_("Current results will be lost. Continue?"));
      response = gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (dialog);
      if (response == GTK_RESPONSE_CANCEL)
	return TRUE;
    }
  new_file_selector (_("load scratchpad"), scratchpad_load2, scratchpad_name);
  return TRUE;
}

static void
scratchpad_load2 (GtkWidget * unused, GtkFileSelection * file_selector)
{
  FILE *fp;
  GtkTextBuffer *tb;
  gchar buf[100];
  GtkTextMark *tm;
  gchar *selected_file_name =
    g_strdup (gtk_file_selection_get_filename
	      (GTK_FILE_SELECTION (file_selector)));
  GtkWindow *parent = GTK_WINDOW (file_selector);

  fp = fopen (selected_file_name, "r");
  if (!fp)
    {
      GtkWidget *dialog;
      dialog =
	gtk_message_dialog_new (parent,
				GTK_DIALOG_DESTROY_WITH_PARENT,
				GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
				_("Could not open\n %s:\n%s"),
				selected_file_name, g_strerror (errno));
      g_free (selected_file_name);
      gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (GTK_WIDGET (dialog));
      return;
    }
  scratchpad_update_name (selected_file_name, FALSE);
  g_free (selected_file_name);
  /* clean up file selection dialog */
  gtk_widget_destroy (GTK_WIDGET (parent));
  tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (global_widgets.scratchpad));
  gtk_text_buffer_set_text (tb, "", 0);
  while (fgets (buf, sizeof (buf), fp))
    {
      gtk_text_buffer_insert_at_cursor (tb, buf, strlen (buf));
    }
  fclose (fp);
  tm = gtk_text_buffer_get_insert (tb);
  gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (global_widgets.scratchpad),
				tm, 0.0, TRUE, 0.0, 0.9);
  scratchpad_set_modified (FALSE);
}

