#include "global.h"
#include "comm.h"
#include "edit.h"
#include "file.h"
#include "icon.h"
#include "memory.h"
#include "options.h"
#include "rsc.h"
#include "text.h"
#include "clipbrd.h"

/* exportierte Variablen ***************************************************/
GLOBAL RING		clip_text;
GLOBAL PATH		clip_dir;


/****** DEFINES ************************************************************/

#define MAX_UNDO	5
#define END_UNDO	-1

/* loake Variablen *********************************************************/
LOCAL BOOLEAN	clip_dirty;
LOCAL PATH		clip_name;

LOCAL WORD	undo[MAX_UNDO];
LOCAL WORD	undo_anz;
LOCAL RING	undo_text;
LOCAL WORD	undo_ptr;

LOCAL UBYTE	save_col[MAX_LINE_LEN];		/* Gerettete Zeile fr Undo */
LOCAL WORD	save_len;
LOCAL WORD	save_xpos;

LOCAL BOOLEAN	last_was_bin = FALSE;

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

GLOBAL VOID clr_undo(VOID)
{
	undo_ptr = -1;
	undo_anz = 0;
}

GLOBAL BOOLEAN any_undo(VOID)
{
	if (undo_anz && undo[undo_anz-1]==END_UNDO)
		return TRUE;
	return FALSE;
}

GLOBAL BOOLEAN test_col_anders(VOID)
{
	WORD i;

	if (undo_anz == 0)
		return FALSE;
	if (undo[undo_anz-1] == COL_ANDERS)
		return TRUE;
	if (undo[undo_anz-1] != END_UNDO)
		return FALSE;
	for (i = 0; i < undo_anz; i++)
		if (undo[i]==END_UNDO)
			break;
	if (i > 0 && i < undo_anz)
		return (undo[i-1] == COL_ANDERS);
	return FALSE;
}

GLOBAL VOID end_undo_seq(VOID)
{
	WORD	i;

	undo_ptr = -1;
	if (undo_anz==0 || undo[undo_anz-1]==END_UNDO)
		return;
	for (i=0; i<undo_anz; i++)
		if (undo[i]==END_UNDO)
		{
			i++;
			undo_anz -= i;
			memcpy(undo, undo+i, (short) sizeof(WORD) * undo_anz);
			break;
		}
	add_undo(END_UNDO);
}

GLOBAL VOID add_undo(WORD undo_op)
{
	if (undo_anz<MAX_UNDO && (undo_anz==0 || undo[undo_anz-1]!=undo_op))
		undo[undo_anz++] = undo_op;
}

GLOBAL WORD get_undo(VOID)
{
	WORD i;

	if (undo_anz==0)
		return NO_UNDO;
	if (undo_ptr<0)
	{
		for (i=0; i<undo_anz; i++)
			if (undo[i]==END_UNDO) break;
		if (i==undo_anz) return NO_UNDO;
		undo_ptr = i;
	}
	undo_ptr--;
	if (undo_ptr<0)
		return NO_UNDO;
	return undo[undo_ptr];
}

GLOBAL VOID undo_takes_text(RINGP r)
{
	kill_textring(&undo_text);
	undo_text = *r;
	FIRST(r)->vorg = &undo_text.head;
	LAST(r)->nachf = &undo_text.tail;
}

GLOBAL RINGP get_undo_text(VOID)
{
	return &undo_text;
}

/*
 * UNDO fr eine Zeile
*/
GLOBAL VOID get_undo_col(TEXTP t_ptr)
{
	if (!test_col_anders() || t_ptr->ypos!=undo_y)
	{
		undo_y = t_ptr->ypos;
		save_len = t_ptr->cursor_line->len;
		memcpy(save_col, TEXT(t_ptr->cursor_line), save_len);
		save_xpos = t_ptr->xpos;
	}
	add_undo(COL_ANDERS);
}

GLOBAL VOID do_undo_col(TEXTP t_ptr, WORD undo)
{
	ZEILEP	undo_col;
	UBYTE		help[MAX_LINE_LEN];
	UBYTE	 	*str;
	WORD		length;

	if (undo == COL_ANDERS)
	{
		undo_col = get_line(&t_ptr->text,undo_y);
		length = undo_col->len;
		memcpy(help, TEXT(undo_col), length);

		str = REALLOC(&undo_col,0,save_len-length);
		memcpy(str, save_col, save_len);

		memcpy(save_col, help, length);
		save_len = length;

		t_ptr->moved++;
		make_chg(t_ptr->link,LINE_CHANGE,undo_y);
		make_chg(t_ptr->link,POS_CHANGE,0); 			/* wg. moved */
		t_ptr->xpos = save_xpos;
		t_ptr->cursor_line = undo_col;
		add_undo(COL_ANDERS);
	}
}


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

GLOBAL VOID save_clip(VOID)		/* nur wegschreiben */
{
	if (clip_on_disk && clip_dirty)
	{
Debug("save_clip()\n");
		scrap_clear();
		save_datei(clip_name, &clip_text, FALSE);
		send_clip_change();
		clip_dirty = FALSE;
	}
}

GLOBAL VOID load_clip(VOID)		/* nur laden */
{
	/*
	 * Nur neu laden, wenn letzter Copy von qed bereits weggeschrieben wurde,
	 * ansonsten sind die aktuellen Klembrett-Daten noch in clip_text.
	*/
	if (clip_on_disk && !clip_dirty)
	{
Debug("load_clip()\n");
		free_textring(&clip_text);
		if (last_was_bin)
			clip_text.ending = binmode;
		if (load_datei(clip_name, &clip_text, FALSE, NULL) != 0)
			free_textring(&clip_text);
	}
}


GLOBAL VOID clip_takes_text(RINGP r)
{
	kill_textring(&clip_text);
	clip_text = *r;
	last_was_bin = (r->ending == binmode);
	FIRST(r)->vorg = &clip_text.head;
	LAST(r)->nachf = &clip_text.tail;
	clip_dirty = TRUE;
}

GLOBAL VOID clip_add_text(RINGP r)
{
	ZEILEP	col;

	col = LAST(&clip_text);			/* letzte Zeile */
	col->nachf = FIRST(r);
	FIRST(r)->vorg = col;
	LAST(r)->nachf = &clip_text.tail;
	LAST(&clip_text) = LAST(r);
	clip_text.lines += r->lines;
	col_concate(&col);
	clip_text.lines--;
	clip_dirty = TRUE;
}

GLOBAL VOID init_clipbrd(VOID)
{
	PATH		s;
	UBYTE		*str;

	scrp_read (clip_dir);									/* Scrap-Directory lesen */
	if (clip_dir[0] == EOS)									/* Noch keines gesetzt */
	{
		if ((str=getenv("SCRAPDIR"))!=NULL && *str!=EOS)
			strcpy(clip_dir, str);

		else if ((str=getenv("CLIPBRD"))!=NULL && *str!=EOS)
			strcpy(clip_dir, str);

		else
		{
			WORD drive;

			strcpy (clip_dir, "A:\\CLIPBRD\\");
			drive = get_first_drive();
			if (drive > 0)
				clip_dir[0] = 'A' + (UBYTE) drive;
		}
		scrp_write (clip_dir);								/* Scrap-Directory setzen */
	}
	make_normalpath(clip_dir,FALSE);
	if (!path_exist (clip_dir))
	{
		if (clip_dir[0]=='A' || clip_dir[0]=='B' ||
		    clip_dir[0]=='a' || clip_dir[0]=='b')
			clip_dir[0] = EOS;						/* Kein Klemmbrett auf Disketten! */
		else
		{
			strcpy (s, clip_dir);
			s[strlen(s)-1] = EOS;					/* Backslash lschen */
			if (Dcreate(s) != 0)
			{
				note(1, NOSCRAP);
				clip_dir[0] = EOS;					/* Kein Klemmbrett */
			}
		}
	}
	init_textring(&clip_text);
	clip_dirty = FALSE;

	if (clip_dir[0] == EOS)
		clip_on_disk = FALSE;
	else
	{
		strcpy(clip_name, clip_dir);
		strcat(clip_name, "scrap.txt");
	}

	init_textring(&undo_text);
	clr_undo();
}
