/* Bluefish HTML Editor
 * rpopup.c - this file contains the right mouseclick popup
 *
 * Copyright (C) 1999-2000 Olivier Sessink
 *
 * 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 "default_include.h"

#include <string.h>
#include <ctype.h> 	/* isspace() */

#include "bluefish.h"
#include "bf_lib.h"
#include "html_diag.h" /* Ttagpop and stuff */
#include "html.h" /* the various callbacks */
#include "html_form.h" /* the various form callbacks */
#include "html_table.h" /* the various table callbacks */
#include "wml.h"
#include "images.h"
#include "document.h"

#ifdef UNDO2
#include "undo2.h" /* undo_cb */
#else
#include "undo.h"
#endif /* UNDO2 */

#include "highlight.h"

/**************************************************************************/

typedef struct {
	gint start;
	gint end;
} Ttagposition;

static void edit_tag_cb(gint pos);
static void parse_tagstring(gchar * tagstring, gint pos, gint len);
static GtkWidget *rpopup_create_menu(GdkEventButton * pevent);
static void input_tag_splitter(gpointer nothing, gpointer data);


/**************************************************************************/

/**************************************************************************/
/* returns FALSE, or the start of the tag + 1 */

/* original function Copyright (C) David A Knight */
/* changes (C) Olivier Sessink                */
gint in_tag(gchar * text, gint pos, Ttagposition *position)
{
	gint ipos = pos;
	gint len = strlen(text);

	DEBUG_MSG("in_tag, started\n");
	/* go back until start of text, or we hit a '<' or '>' */
	while ((--pos) >= 0) {
		DEBUG_MSG("in_tag, found %c\n", text[pos]);
		if (text[pos] == '<') {
			if ((pos < (len-1)) && (text[pos+1] == '?')) {
				/* php tag */
			} else {
				break;
			}
		} else if (text[pos] == '>') {
			if ((pos > 1) && (text[pos-1] == '?')) {
				/* php tag --> continue */
			} else {
				return FALSE;
			}
		}
	}
	if (pos < 0)
		return FALSE;

	position->start = pos;

	/* we have an opening, but do we have a closing? */
	while (ipos < len) {
		if (text[ipos] == '<') {
			if (((ipos+1)<len) && (text[ipos+1] == '?')) {
			/* php tag */
			} else {
				return FALSE;
			}
		}
		if (text[ipos] == '>') {
			if ((ipos>1) && (text[ipos-1] == '?')) {
				/* php tag */
			} else {
				position->end = ipos+1;
				return pos +1;
			}
		}
		ipos++;
	}
	return FALSE;
}

/*************************************************************************/

static void edit_tag_cb(gint pos)
{
	gchar *text, *tagstring;
	gint len;
	Ttagposition position = {-1, -1};

	DEBUG_MSG("edit_tag_cb, started\n");
	text = gtk_editable_get_chars(GTK_EDITABLE(GTK_TEXT(main_v->current_document->textbox)), 0, -1);
	/* gtk_editable_set_position( GTK_EDITABLE( main_v->current_document->textbox ), pos ); */
	pos = in_tag(text, pos, &position);
	if (pos) {
		DEBUG_MSG("edit_tag_cb, in_tag!\n");
		pos = position.start;
		len = position.end;
		gtk_editable_select_region(GTK_EDITABLE(main_v->current_document->textbox), pos, len);
		DEBUG_MSG("edit_tag_cb, pos=%d, len=%d, position.start=%d, position.end=%d\n", pos, len, position.start, position.end);
		DEBUG_MSG("edit_tag_cb, making tagstring\n");
		tagstring = g_strndup(&text[pos + 1], len - pos - 2);
		DEBUG_MSG("edit_tag_cb, tagstring=%s\n", tagstring);
		parse_tagstring(tagstring, pos, len);
		g_free(tagstring);
	} else {
		DEBUG_MSG("edit_tag_cb, not in_tag\n");
	}
	g_free(text);

}


/*************************************************************************/

static void parse_tagstring(gchar * tagstring, gint pos, gint len)
{
	GList *tmplist = NULL;
	gchar *tmpstring, *item, *value;
	gint count, prevtag, item_value_delimiter;
	Ttagitem *tag_item;
	Ttagpopup *tag_popup;
	gboolean in_quote, has_quotes;

	DEBUG_MSG("parse_tagstring, started, tagstring=%s\n", tagstring);

	/* parsing the values from this tag */
	tmpstring = g_strdup(tagstring);
	strip_any_whitespace(tmpstring);
	item_value_delimiter = prevtag = count = 0;
	has_quotes = in_quote = FALSE;
	while (tmpstring[count] != '\0') {

		/* spaces (delimiters) are allowed within quotes, so we have to keep track of quotes */
		if (tmpstring[count] == '"') {
			has_quotes = TRUE;
			if (in_quote) {
				in_quote = FALSE;
			} else {
				in_quote = TRUE;
			}
		}
		/* to split the item and the value we have to keep track of '=' characters */
		if (tmpstring[count] == '=') {
			item_value_delimiter = count;
		}
		/* it is a delimiter if it a space (or tab, newline), outside a quote or the last character of the string */
		if ((isspace((char)tmpstring[count]) && (in_quote == FALSE)) || (tmpstring[count + 1] == '\0')) {
			if (prevtag == (count - 1)) {
				DEBUG_MSG("parse_tagstring, two spaces!\n");
				prevtag = count;
			} else if (prevtag == 0) {
				DEBUG_MSG("parse_tagstring, this is the name of the tag itself\n");
				prevtag = count;
			} else {
				DEBUG_MSG("parse_tagstring, making split, count=%d, prevtag=%d\n", count, prevtag);
				if (item_value_delimiter > prevtag) {
					item = g_strndup(&tmpstring[prevtag + 1], item_value_delimiter - prevtag - 1);
					if (has_quotes == TRUE) {
						value = g_strndup(&tmpstring[item_value_delimiter + 2], count - item_value_delimiter - 2);
						value = trunc_on_char(value, '"');
					} else {
						value = g_strndup(&tmpstring[item_value_delimiter + 1], count - item_value_delimiter);
						g_strstrip(value);
					}
				} else {
					item = g_strndup(&tmpstring[prevtag + 1], count - prevtag);
					value = g_strdup("");
				}
				g_strdown(item);
				g_strstrip(item);
				tag_item = g_malloc(sizeof(Ttagitem));
				tag_item->item = item;
				tag_item->value = value;
				tmplist = g_list_append(tmplist, tag_item);
				DEBUG_MSG("parse_tagstring, item=%s with value=%s appended to list %p\n", item, value, tmplist);
				prevtag = count;
				has_quotes = FALSE;
			}
		}
		count++;
	}
	g_free(tmpstring);

	tag_popup = g_malloc(sizeof(Ttagpopup));
	tag_popup->taglist = tmplist;
	tag_popup->pos = pos;
	tag_popup->len = len;
	DEBUG_MSG("parse_tagstring, tag_popup->pos=%d, tag_popup->len=%d\n", tag_popup->pos, tag_popup->len);

	tmpstring = g_strdup(tagstring);
	tmpstring = trunc_on_char(tmpstring, ' ');
	g_strdown(tmpstring);
	/* identifying which tag we have */

	if (strcmp(tmpstring, "body") == 0) {
		DEBUG_MSG("parse_tagstring, identified as body_cb tag\n");
		body_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "a") == 0) {
		DEBUG_MSG("parse_tagstring, identified as anchor tag\n");
		quickanchor_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "p") == 0) {
		block_tag_edit_cb(1, NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "div") == 0) {
		block_tag_edit_cb(2, NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "span") == 0) {
		block_tag_edit_cb(3, NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "h1") == 0) {
		block_tag_edit_cb(4, NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "h2") == 0) {
		block_tag_edit_cb(5, NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "h3") == 0) {
		block_tag_edit_cb(6, NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "h4") == 0) {
		block_tag_edit_cb(7, NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "h5") == 0) {
		block_tag_edit_cb(8, NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "h6") == 0) {
		block_tag_edit_cb(9, NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "hr") == 0) {
		quickrule_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "font") == 0) {
		fontdialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "basefont") == 0) {
		basefont_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "table") == 0) {
		tabledialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "tr") == 0) {
		tablerowdialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "th") == 0) {
		tableheaddialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "td") == 0) {
		tabledatadialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "frameset") == 0) {
		framesetdialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "frame") == 0) {
		framedialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "img") == 0) {
		image_insert_dialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "form") == 0) {
		formdialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "textarea") == 0) {
		textareadialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "select") == 0) {
		selectdialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "other") == 0) {
		optiondialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "meta") == 0) {
		meta_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "card") == 0) {
		carddialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "postfield") == 0) {
		postfielddialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "setvar") == 0) {
		vardialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "go") == 0) {
		godialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "do") == 0) {
		dodialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "anchor") == 0) {
		anchordialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "access") == 0) {
		accessdialog_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "script") == 0) {
		script_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "link") == 0) {
		link_cb(NULL, tag_popup);
	} else
	if (strcmp(tmpstring, "input") == 0) {
		DEBUG_MSG("parse_tagstring, identified as INPUT tag, splitting tag!\n");
		input_tag_splitter(NULL, tag_popup);
	}
	tmplist = g_list_first(tmplist);
	while (tmplist) {
		g_free(((Ttagitem *) tmplist->data)->item);
		g_free(((Ttagitem *) tmplist->data)->value);
		g_free(tmplist->data);
		tmplist = g_list_next(tmplist);
	}
	g_list_free(tmplist);
	g_free(tag_popup);
	g_free(tmpstring);
}

/*************************************************************************/


static GtkWidget *rpopup_create_menu(GdkEventButton * pevent)
{
	GtkWidget *menu_item;
	GtkWidget *menu, *fmenu;
	gint pos;

	DEBUG_MSG("rpopup_create_menu, started\n");
	menu = gtk_menu_new();
	menu_item = gtk_menu_item_new_with_label(_("File"));
	gtk_menu_append(GTK_MENU(menu), menu_item);

	fmenu = gtk_menu_new();
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), fmenu);
	menu_item = gtk_menu_item_new_with_label(_("Save"));
	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC(file_save_cb), NULL);
	gtk_menu_append(GTK_MENU(fmenu), menu_item);
	menu_item = gtk_menu_item_new_with_label(_("Save as"));
	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC(file_save_as_cb), NULL);
	gtk_menu_append(GTK_MENU(fmenu), menu_item);
	menu_item = gtk_menu_item_new_with_label(_("Move to"));
	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC(file_move_to_cb), NULL);
	gtk_menu_append(GTK_MENU(fmenu), menu_item);
	menu_item = gtk_menu_item_new_with_label(_("Close"));
	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC(file_close_cb), NULL);
	gtk_menu_append(GTK_MENU(fmenu), menu_item);
	menu_item = gtk_menu_item_new_with_label(_("Insert"));
	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC(file_insert_cb), NULL);
	gtk_menu_append(GTK_MENU(fmenu), menu_item);

	menu_item = gtk_menu_item_new();
	gtk_menu_append(GTK_MENU(menu), menu_item);

	menu_item = gtk_menu_item_new_with_label(_("cut"));
	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC(cut_cb), NULL);
	gtk_menu_append(GTK_MENU(menu), menu_item);
	menu_item = gtk_menu_item_new_with_label(_("copy"));
	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC(copy_cb), NULL);
	gtk_menu_append(GTK_MENU(menu), menu_item);
	menu_item = gtk_menu_item_new_with_label(_("paste"));
	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC(paste_cb), NULL);
	gtk_menu_append(GTK_MENU(menu), menu_item);
	menu_item = gtk_menu_item_new_with_label(_("undo"));
	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC(undo_cb), NULL);
	gtk_menu_append(GTK_MENU(menu), menu_item);
	menu_item = gtk_menu_item_new_with_label(_("redo"));
	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC(redo_cb), NULL);
	gtk_menu_append(GTK_MENU(menu), menu_item);

	menu_item = gtk_menu_item_new_with_label(_("edit tag"));
	DEBUG_MSG("rpopup_create_menu, curdoc=%p\n", main_v->current_document);
	pos = doc_xy_to_cursor_pos(main_v->current_document, pevent->x, pevent->y);
	gtk_signal_connect_object(GTK_OBJECT(menu_item), "activate", GTK_SIGNAL_FUNC(edit_tag_cb), GINT_TO_POINTER(pos));
	gtk_menu_append(GTK_MENU(menu), menu_item);
	gtk_widget_show_all(menu);
	return menu;
}

/*************************************************************************/


void rpopup_eventh(GdkEventButton* bevent)
{
	GtkWidget *menu;

	menu = rpopup_create_menu(bevent);
	gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, bevent->button, bevent->time);
}


/*************************************************************************/

static void input_tag_splitter(gpointer nothing, gpointer data)
{
	Ttagpopup *tag_popup;
	GList *tmplist;
	gint counter = 0;
	gchar *itemvalue = NULL;

	tag_popup = (Ttagpopup *) data;
	DEBUG_MSG("input_tag_splitter, started\n");

	tmplist = g_list_first(tag_popup->taglist);
	while (tmplist) {
		if (strcasecmp((gchar *) ((Ttagitem *) (tmplist->data))->item, "type") == 0) {
			DEBUG_MSG("input_tag_splitter, found!! tmplist->data->item=%s, counter=%d\n", (gchar *) ((Ttagitem *) (tmplist->data))->item,
					  counter);
			itemvalue = g_strdup((gchar *) ((Ttagitem *) (tmplist->data))->value);
			break;
		} else {
			DEBUG_MSG("input_tag_splitter, nope.., tmplist->data->item=%s, counter=%d\n", (gchar *) ((Ttagitem *) (tmplist->data))->item,
					  counter);
		}
		counter++;
		tmplist = g_list_next(tmplist);
	}
	if (tmplist) {
		g_strdown(itemvalue);
		DEBUG_MSG("input_tag_splitter, itemvalue=%s, counter=%d\n", itemvalue, counter);
		if (strcmp(itemvalue, "submit") == 0) {
			buttondialog_cb(NULL, data);
		} else if (strcmp(itemvalue, "reset") == 0) {
			buttondialog_cb(NULL, data);
		} else if (strcmp(itemvalue, "button") == 0) {
			buttondialog_cb(NULL, data);
		} else if (strcmp(itemvalue, "text") == 0) {
			textdialog_cb(NULL, data);
		} else if (strcmp(itemvalue, "hidden") == 0) {
			hiddendialog_cb(NULL, data);
		} else if (strcmp(itemvalue, "radio") == 0) {
			radiodialog_cb(NULL, data);
		} else if (strcmp(itemvalue, "checkbox") == 0) {
			checkdialog_cb(NULL, data);
		}
		g_free(itemvalue);
	} else {
		DEBUG_MSG("input_tag_splitter, not found ?\n");
	}


}
