/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1991 by Olaf 'Olsen' Barthel & MXM
 *
 *	Name .....: StringHook.c
 *	Created ..: Wednesday 06-Feb-91 12:35
 *	Revision .: 0
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	06-Feb-91       Olsen           Created this file!
 *
 * $Revision Header ********************************************************/

#include "TermGlobal.h"

	/* HookEntry():
	 *
	 *	Call a hook function.
	 */

ULONG __saveds __asm
HookEntry(register __a0 struct Hook *HookPtr,register __a2 APTR Object,register __a1 APTR Message)
{
	return(HookPtr -> h_SubEntry(HookPtr,Object,Message));
}

	/* InitHook(struct Hook *Hook,APTR HookCode):
	 *
	 *	Set up a call back routine (hook).
	 */

VOID
InitHook(struct Hook *Hook,APTR HookCode)
{
	Hook -> h_Entry		= HookEntry;
	Hook -> h_SubEntry	= HookCode;
	Hook -> h_Data		= 0;
}

	/* ClipServer():
	 *
	 *	Quiet background process which saves data to the clipboard
	 *	or fills a buffer with fresh clipboard data.
	 */

VOID __saveds
ClipServer()
{
	if(ClipPort = CreateMsgPort())
	{
		ULONG		 Mask;
		struct Message	*ClipMsg;
		UBYTE		*Buffer;
		BYTE		 Terminated = FALSE;

		Signal(ThisProcess,SIGBREAKF_CTRL_C);

		while(!Terminated)
		{
			Mask = Wait(SIGBREAKF_CTRL_C | (1 << ClipPort -> mp_SigBit));

			if(Mask & SIGBREAKF_CTRL_C)
				Terminated = TRUE;

			if(Mask & (1 << ClipPort -> mp_SigBit))
			{
				while(ClipMsg = GetMsg(ClipPort))
				{
					Buffer = ClipMsg -> mn_Node . ln_Name;

					if(Buffer[0])
						SaveClip(Buffer,strlen(Buffer));
					else
					{
						WORD Len = LoadClip(Buffer,256);

						Buffer[Len] = 0;
					}

					ReplyMsg(ClipMsg);
				}
			}
		}

		DeleteMsgPort(ClipPort);
	}

	Forbid();

	ClipProcess = NULL;

	Signal(ThisProcess,SIGBREAKF_CTRL_C);
}

	/* CommandKey(struct Hook *Hook,struct SGWork *Work,ULONG *Msg):
	 *
	 *	This routine is called whenever input passes through
	 *	a `term' string gadget. It releases the currently
	 *	active string gadget as soon as the Right-Amiga-key is
	 *	pressed (user is about to select a menu item).
	 */

VOID
CommandKey(struct Hook *Hook,struct SGWork *Work,ULONG *Msg)
{
	if(Msg[0] == SGH_KEY)
	{
			/* Simple: activate the next gadget if
			 * return is pressed in the current one.
			 */

		if(Work -> Actions & SGA_END)
			Work -> Actions |= SGA_NEXTACTIVE;

			/* This looks like a built-in command. */

		if(Work -> IEvent -> ie_Qualifier & IEQUALIFIER_RCOMMAND)
		{
				/* Amiga+C = Copy contents of string
				 *           gadget to the clipboard.
				 */

			if(Work -> Code == 'c')
			{
				Work -> Actions &= ~SGA_USE;
				Work -> Actions |= SGA_BEEP;

					/* Valid buffer contents? */

				if(Work -> PrevBuffer[0])
				{
					struct MsgPort *ReplyPort;

						/* Post a message... */

					if(ReplyPort = CreateMsgPort())
					{
						struct Message ClipMessage;

						ClipMessage . mn_Node . ln_Name	= Work -> PrevBuffer;
						ClipMessage . mn_ReplyPort	= ReplyPort;
						ClipMessage . mn_Length		= sizeof(struct Message);

						PutMsg(ClipPort,&ClipMessage);

						WaitPort(ReplyPort);

						GetMsg(ReplyPort);

						DeleteMsgPort(ReplyPort);

						Work -> Actions &= ~SGA_BEEP;
					}
				}

				return;
			}

				/* Amiga+V = Insert current clipboard
				 *           contents at cursor position.
				 */

			if(Work -> Code == 'v')
			{
				Work -> Actions &= ~SGA_USE;
				Work -> Actions |= SGA_BEEP;

					/* Don't paste to integer gadgets
					 * (it could confuse Intuition if
					 *  the buffer contained non-numeric
					 *  symbols...).
					 */

				if(!(Work -> Gadget -> Activation & GACT_LONGINT))
				{
					struct MsgPort *ReplyPort;

						/* Post a message... */

					if(ReplyPort = CreateMsgPort())
					{
						STATIC UBYTE	Buffer[2048];
						struct Message	ClipMessage;

						Buffer[0] = 0;

						ClipMessage . mn_Node . ln_Name	= &Buffer[0];
						ClipMessage . mn_ReplyPort	= ReplyPort;
						ClipMessage . mn_Length		= sizeof(struct Message);

						PutMsg(ClipPort,&ClipMessage);

						WaitPort(ReplyPort);

						GetMsg(ReplyPort);

						DeleteMsgPort(ReplyPort);

							/* Anything in the buffer? */

						if(Buffer[0])
						{
							WORD Len = strlen(Buffer);

								/* Insert as many characters as we can. */

							while(Len > 0 && Work -> NumChars + Len > Work -> StringInfo -> MaxChars)
								Len--;

								/* Any characters left? */

							if(Len > 0)
							{
								STATIC UBYTE OtherBuffer[2048];

									/* Provide null-termination. */

								Buffer[Len] = 0;

									/* Set up undo buffer correctly. */

								if(Work -> StringInfo -> UndoBuffer)
									strcpy(Work -> StringInfo -> UndoBuffer,Work -> PrevBuffer);

								Work -> StringInfo -> UndoPos = --Work -> BufferPos;

									/* Save the characters before the cursor. */

								if(Work -> BufferPos)
									CopyMem(Work -> PrevBuffer,OtherBuffer,Work -> BufferPos);

									/* Provide null-termination. */

								OtherBuffer[Work -> BufferPos] = 0;

									/* Append the clipboard data. */

								strcat(OtherBuffer,Buffer);

									/* Append the characters following the cursor. */

								strcat(OtherBuffer,&Work -> PrevBuffer[Work -> BufferPos]);

									/* = new work buffer. */

								strcpy(Work -> WorkBuffer,OtherBuffer);

									/* Fiddle with some cursor data. */

								Work -> BufferPos += Len;
								Work -> NumChars	+= Len;

									/* And that's it... */

								Work -> Actions	|= SGA_USE;
								Work -> EditOp	 = EO_BIGCHANGE;

								Work -> Actions &= ~SGA_BEEP;
							}
						}
						else
							Work -> Actions &= ~SGA_BEEP;
					}
				}

				return;
			}
		}

		if((Work -> IEvent -> ie_Qualifier & AMIGARIGHT) && Work -> IEvent -> ie_Code < 96)
		{
			if(!(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) && (Work -> IEvent -> ie_Code == KEYCODE_X || Work -> IEvent -> ie_Code == KEYCODE_Q))
				return;
			else
			{
				Work -> Actions |= (SGA_END|SGA_REUSE);
				Work -> Actions &= ~(SGA_USE|SGA_BEEP);

				CommandWindow = Work -> GadgetInfo -> gi_Window;
				CommandGadget = Work -> Gadget;
			}
		}

			/* The user pressed the cursor-right key to
			 * move the cursor to the next word in the buffer.
			 */

		if(Work -> IEvent -> ie_Code == CURSORRIGHT && (Work -> IEvent -> ie_Qualifier & IEQUALIFIER_CONTROL))
		{
			if(Work -> BufferPos != Work -> NumChars)
			{
				WORD i,Position = -1;

				for(i = Work -> BufferPos ; i < Work -> NumChars ; i++)
				{
					if(Work -> WorkBuffer[i] == ' ')
					{
						for( ; i < Work -> NumChars ; i++)
						{
							if(Work -> WorkBuffer[i] != ' ')
							{
								Position = i;
								break;
							}
						}

						break;
					}
				}

				if(Position != -1)
					Work -> BufferPos = Position;
				else
					Work -> BufferPos = Work -> NumChars;

				Work -> EditOp = EO_MOVECURSOR;
			}
		}

			/* The user pressed the cursor-right key to
			 * move the cursor to the previous word in the buffer.
			 */

		if(Work -> IEvent -> ie_Code == CURSORLEFT && (Work -> IEvent -> ie_Qualifier & IEQUALIFIER_CONTROL))
		{
			if(Work -> BufferPos)
			{
				WORD i,Position = -1;

				for(i = Work -> BufferPos ; i >= 0 ; i--)
				{
					if(Work -> WorkBuffer[i] != ' ')
					{
						Position = i;
						break;
					}
				}

				if(Position == -1)
					Position = 0;

				if(Position)
				{
					i = Position;

					Position = -1;

					for( ; i >= 0 ; i--)
					{
						if(Work -> WorkBuffer[i] == ' ')
						{
							Position = i + 1;
							break;
						}
					}
				}

				if(Position != -1)
					Work -> BufferPos = Position;
				else
					Work -> BufferPos = 0;

				Work -> EditOp = EO_MOVECURSOR;
			}
		}
	}
}
