/*	XEditCore.h
 *
 *		This encapsulates the functionality of a TextEdit like
 *	editor, except I know about tabs, and I can deal with more than
 *	32K of text.
 */

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

  YAAF is Copyright 1997-1999 by William Woody.

  Redistribution and use in source and binary forms, with or without 
  modification, are permitted provided that the following conditions 
  are met:

  Redistributions of source code must retain the above copyright notice, 
  this list of conditions and the following disclaimer.

  Neither the name of the copyright holder or other contributors may
  be used to promote products derived from this software without
  specific written prior permission.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
  SOFTWARE.
  
  Contact:   woody@alumni.caltech.edu
  Web page:  http://www.pandawave.com/yaaf/

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

#ifndef PandaWave_XEDITCORE
#define PandaWave_XEDITCORE

#include <XHandle.h>
#include <XView.h>
#include <XDraw.h>

/************************************************************************/
/*																		*/
/*	View forwards														*/
/*																		*/
/************************************************************************/


class XGView;
class XGFont;

/************************************************************************/
/*																		*/
/*	Edit Core															*/
/*																		*/
/************************************************************************/

/*$	XGEditCore
 *
 *		Editor core. Contains the routines which are used to handle
 *	editing. Modeled after the Macintosh TextEdit API.
 */

class XGEditCore {
	public:
						XGEditCore(XGView *, XGFont *, XRect &);
						XGEditCore(XGDraw *, XRect &);
		virtual			~XGEditCore();
		
		/*
		 *	Text Access
		 */
		
		void			SetText(XGHandle *);
		XGHandle		*GetText(void)
							{
								return fText;
							}
		
		/*
		 *	Insertion point/selection code
		 */
		
		void			DoIdle(void);
		bool			DoMouseDown(XPoint, short);
		void			DoMouseMove(XPoint, short);
		void			DoMouseUp(XPoint, short);
		void			DoActivate(bool);
		void			DoSize(XRect r)
							{
								fSize = r;
								if (fWordWrap) RecalcLineStarts();
								if (!fDrawFlag && fCurView) fCurView->InvalView();
							}
		
		void			SetSelect(long x, long y)
							{
								fPixelPos = -1;
								SetSelectInternal(x,y);
							}
		void			GetSelect(long *x, long *y)
							{
								*x = fSelStart, *y = fSelEnd;
							}

		/*
		 *	Text Editing Events
		 */
		
		void			DoKey(char);
		void			DoInsert(long, char *);
		void			DoDelete(void)
							{
								/* Insert routine autodeletes as well */
								DoInsert(0,NULL);
							}
		void			DoCopy(void);
		void			DoCut(void);
		void			DoPaste(void);
		void			DoSelectAll(void);
		
		bool			CanCut(void);
		bool			CanCopy(void)
							{
								return CanCut();
							}
		bool			CanPaste(void)
							{
								return true;
							}
		bool			CanDelete(void)
							{
								return (fSelStart != fSelEnd);
							}
		
		/*
		 *	Navigation
		 */
		
		void			DoUpArrow(bool shift);
		void			DoDownArrow(bool shift);
		void			DoLeftArrow(bool shift);
		void			DoRightArrow(bool shift);

		long			GetCurLine(void);
		void			SetCurLine(long);		// line select support

		/*
		 *	Position support
		 */
		
		long			GetNumLines();
		long			GetLineOffset(long line);
		long			GetLineLength(long line);

		long			GetOffset(XPoint);
		long			FindOffset(long line, long pixel);
		long			FindLine(long offset);
		long			FindPixel(long offset);
		
		XRect			GetSize()
							{
								return fSize;
							}
		
		/*
		 *	Scroll calculation/control
		 */
		
		long			GetPixelStep(void)
							{
								return fPixelStep;
							}
		void			SetPixelStep(long p)
							{
								fPixelStep = p;
								if (!fDrawFlag && fCurView) fCurView->InvalView();
							}
		long			GetMaxWidth();
		long			GetMaxHeight();
		void			GetScrollValue(long *x, long *y)
							{
								*x = fXScroll, *y = fYScroll;
							}
		void			SetScrollValue(long x, long y);

		void			ScrollInRange(long sel = -1);
		
		/*
		 *	Display control
		 */
		
		void			DoDraw(XGDraw &draw, XRect);
		void			DoGainFocus(bool invalView = true);
		void			DoLoseFocus(bool invalView = true);
		
		/*
		 *	Internal support
		 */
		
		void			RecalcLineStarts(void);
		
		
		/*
		 *	Customization
		 */
		
		void			SetFont(XGFont *);
		bool			GetWordWrap()
							{
								return fWordWrap;
							}
		void			SetWordWrap(bool);
		long			GetTabStop()
							{
								return fTabStop;
							}
		void			SetTabStop(long tab);
		bool			GetAutoIndent()
							{
								return fAutoIndent;
							}
		void			SetAutoIndent(bool val)
							{
								fAutoIndent = val;
							}
		
		virtual bool	IsWordBreak(long, char *);
		
		bool			GetScrollPixels()
							{
								return fScrollPixels;
							}
		void			SetScrollPixels(bool val)
							{
								fScrollPixels = val;
							}
							
		void			SetXOffset(short num)
							{
								fXOffset = num;
								RecalcLineStarts();
								if (!fDrawFlag && fCurView) fCurView->InvalView();
							}
		short			GetXOffset()
							{
								return fXOffset;
							}
							
		Color			GetForeColor()
							{
								return fForeColor;
							}
		Color			GetBackColor()
							{
								return fBackColor;
							}
		void			SetForeColor(Color c)
							{
								fForeColor = c;
								if (!fDrawFlag && fCurView) fCurView->InvalView();
							}
		void			SetBackColor(Color c)
							{
								fBackColor = c;
								if (!fDrawFlag && fCurView) fCurView->InvalView();
							}
		bool			GetFieldEditor()
							{
								return fFieldEditor;
							}
		void			SetFieldEditor(bool val)
							{
								fFieldEditor = val;
								if (!fDrawFlag && fCurView) fCurView->InvalView();
							}
		bool			GetPassword()
							{
								return fPassword;
							}
		void			SetPassword(bool val)
							{
								fPassword = val;
								RecalcLineStarts();
								if (!fDrawFlag && fCurView) fCurView->InvalView();
							}
	
	private:
		bool			fScrollPixels;
		bool			fDrawFlag;
		union {
			XGView		*fCurView;
			XGDraw		*fCurDraw;
		};
		XGFont			*fCurFont;
		XRect			fSize;
		XGHandle		*fText;
		XGHandle		fStarts;
		
		long			fTickTime;
		long			fTabStop;
		bool			fWordWrap;
		bool			fAutoIndent;
		bool			fCursorState;
		bool			fDragWord;
		bool			fFieldEditor;	// field editor?
		bool			fPassword;		// password?
		
		bool			fFocus;
		
		long			fXScroll;
		long			fYScroll;
		long			fPixelStep;
		long			fSelStart;
		long			fSelEnd;
		long			fMaxXVal;
		
		long			fDragFrom;
		long			fDragTo;
		
		short			fFontHeight;
		short			fFontAscent;
		
		long			fPixelPos;
		
		short			fXOffset;
		bool			fPrevLine;
		bool			fCursorVis;		// true if cursor *may* be visible
		XPoint			fCursorPos;
		
		Color			fForeColor;
		Color			fBackColor;
		
		/*
		 *	Internal cursor routines
		 */
		
		void			ShowCursor(XGDraw &draw)
							{
								if (!fCursorState) {
									fCursorState = true;
									InvertCursor(draw);
								}
							}
		void			ClearCursor(void);
		void			HideCursor(XGDraw &draw)
							{
								if (fCursorState) {
									fCursorState = false;
									InvertCursor(draw);
								}
								fCursorVis = true;
								fCursorPos.h = -1;
							}
		void			InvertCursor(XGDraw &);
		
		/*
		 *	Drag select/word select support
		 */
		
		void			SetDragSelect(long, long);
		void			GetWordSelect(long *,long *);
		void			SetSelectInternal(long start, long end);
		
		/*
		 *	Auto inent
		 */
				
		void			DoAutoIndent(void);
		
		/*
		 *	Line drawing
		 */
		
		void			DrawLine(XGDraw &draw, long line);
		void			DrawLines(long start, long end = -1);
		
		/*
		 *	Line start recalculation core
		 */
		
		void			RecalcStarts(long start, long end, long len);

		/*
		 *	Clipboard support
		 */
		
		void			ToClipboard(XGHandle &);
		void			FromClipboard(XGHandle &);
		
		/*
		 *	Tabbed drawing support
		 */
		
		unsigned long	TextWidth(XGDraw &draw, 
								  char *line, 
								  unsigned long len, 
								  unsigned long add = 0)
							{
								return (unsigned long)draw.TabStringWidth(line,
																		  len,
																		  fTabStop,
																		  fPassword,
																		  add);
							}
		void			DrawText(XGDraw &draw, 
								 char *line, 
								 unsigned long start, 
								 unsigned long totlen)
							{
								draw.TabDrawString(line,start,totlen,fTabStop,fPassword);
							}
};

#endif // PandaWave_XGEDITCORE
