#include <Xm/Xm.h>
#include <Xm/Text.h>
#include <Xm/ScrolledW.h>
#include <Xm/TextF.h>
#include <xdclass.h>

void CEdit::xd_rootwidget ( Widget xd_rootwidget )
{
    CWnd::xd_rootwidget ( xd_rootwidget );
    if ( XmIsScrolledWindow ( xd_rootwidget ) )
    {
	WidgetList children;
	Cardinal numchildren;
	int i;
	XtVaGetValues ( xd_rootwidget,
			XmNchildren, &children,
			XmNnumChildren, &numchildren,
			0);
	for ( i = 0; i < numchildren; i++ )
	    if ( XmIsText ( children[i] )
	      || XmIsTextField ( children[i] ) )
	    {
		_xd_textwidget = children[i];
		break;
	    }
    }
    else
	_xd_textwidget = _xd_rootwidget;
}

Widget CEdit::xd_textwidget ( )
{
    return _xd_textwidget;
}

BOOL CEdit::xd_enable_window(BOOL bEnable)
{
    // Enable or disable a window
    //  Return value:
    //  0 if the widget has not been created (no call to create() yet).
    //  0 if the window was previously enabled
    //  non-zero if the window was previously disabled.

    if (_xd_textwidget==NULL)
	return FALSE;
    BOOL wasdisabled=!XtIsSensitive(_xd_textwidget);
    XtSetSensitive(_xd_textwidget, bEnable);
    return wasdisabled;
}

void CEdit::Clear()
{
    // Deletes the currently selected text
    if (_xd_textwidget!=NULL)
    {
	if (XmIsText(_xd_textwidget))
	    XmTextRemove(_xd_textwidget);
	else if (XmIsTextField(_xd_textwidget))
	    XmTextFieldRemove(_xd_rootwidget);
    }
    return;
}

void CEdit::Copy()
{
    // Copies the currently selected text to the clipboard
    if (_xd_textwidget!=NULL)
    {
	if (XmIsText(_xd_textwidget))
	    XmTextCopy(_xd_textwidget,
		XtLastTimestampProcessed(XtDisplay(_xd_textwidget)));
	else if (XmIsTextField(_xd_textwidget))
	    XmTextFieldCopy(_xd_textwidget,
		XtLastTimestampProcessed(XtDisplay(_xd_textwidget)));
    }
    return;
}

void CEdit::Cut()
{

    // Deletes the currently selected text and copies it to
    // the clipboard
    if (_xd_textwidget!=NULL)
    {
	if (XmIsText(_xd_textwidget))
	    XmTextCut(_xd_textwidget,
		XtLastTimestampProcessed(XtDisplay(_xd_textwidget)));
	else if (XmIsTextField(_xd_textwidget))
	    XmTextFieldCut(_xd_textwidget,
		XtLastTimestampProcessed(XtDisplay(_xd_textwidget)));
    }
    return;
}

void CEdit::GetSel(int& nStartChar, int& nEndChar) const
{
    // Get the start and end of the selected text
    // Returns start and end as zero if there is no selected text
    Boolean has_selection;
    XmTextPosition left, right;

    if (_xd_textwidget!=NULL)
    {
	if (XmIsText(_xd_textwidget))
	    has_selection=XmTextGetSelectionPosition(_xd_textwidget, &left, &right);
	else if (XmIsTextField(_xd_textwidget))
	    has_selection=XmTextFieldGetSelectionPosition(_xd_textwidget, &left, &right);
	if (has_selection)
	{
	    nStartChar=(int)left;
	    nEndChar=(int)right;
	    return;
	}
    }
    nStartChar=nEndChar=0;
    return;
}

void CEdit::LimitText(int nChars)
{
    // Limit the number of characters that can be typed.
    // Does not limit the size of text that can be set
    // programmatically using SetWindowText().
    // A limit of zero means set the limit to its maximum value
    if (_xd_textwidget!=NULL)
	XtVaSetValues(_xd_textwidget,
	    XmNmaxLength, nChars==0 ? UINT_MAX : nChars,
	    NULL);
}

void CEdit::Paste()
{
    // Insert data from the clipboard into the text
    if (_xd_textwidget!=NULL)
    {
	if (XmIsText(_xd_textwidget))
	    XmTextPaste(_xd_textwidget);
	else if (XmIsTextField(_xd_textwidget))
	    XmTextFieldPaste(_xd_textwidget);
    }
    return;
 }

void CEdit::ReplaceSel(LPCSTR lpszNewText)
{
    // Inserts the given text to replace the current selection
    // or at the insert cursor position if there is no selection.
    Boolean has_selection;
    XmTextPosition left, right;

    if (_xd_textwidget!=NULL)
    {
	if (XmIsText(_xd_textwidget))
	{
	    has_selection=XmTextGetSelectionPosition(_xd_textwidget, &left, &right);
	    if (!has_selection)
		left=right=XmTextGetInsertionPosition(_xd_textwidget);
	    XmTextReplace(_xd_textwidget, left, right, (char *)lpszNewText);
	}
	else if (XmIsTextField(_xd_textwidget))
	{
	    has_selection=XmTextFieldGetSelectionPosition(_xd_textwidget, &left, &right);
	    if (!has_selection)
		left=right=XmTextFieldGetInsertionPosition(_xd_textwidget);
	    XmTextFieldReplace(_xd_textwidget, left, right, (char *)lpszNewText);
	}
    }
    return;

}

BOOL CEdit::SetReadOnly(BOOL bReadOnly)
{
    // Make the text non-editable
    if (_xd_textwidget==NULL)
	return 0;
    XtVaSetValues(_xd_textwidget, XmNeditable, !bReadOnly, 0);
    return 1;
}

void CEdit:: SetSel(int nStartChar, int nEndChar, BOOL bNoScroll)
{
    // Set the current selection.

    if (_xd_textwidget!=NULL)
    {
	XtVaSetValues(_xd_textwidget, XmNautoShowCursorPosition, !bNoScroll, 0);

	XmTextPosition len=XmTextGetLastPosition(_xd_textwidget);
	if (nEndChar > len)
	    nEndChar=(int)len;
	if (XmIsText(_xd_textwidget))
	    XmTextSetSelection(_xd_textwidget, nStartChar, nEndChar,
		XtLastTimestampProcessed(XtDisplay(_xd_textwidget)));
	else if (XmIsTextField(_xd_textwidget))
	    XmTextFieldSetSelection(_xd_textwidget, nStartChar, nEndChar,
		XtLastTimestampProcessed(XtDisplay(_xd_textwidget)));
    }
    return;
}

void CEdit::xd_set_window_text(LPCSTR lpszString)
{
    // Implements SetWindowText() for XmText and XmTextField.
    if (_xd_textwidget!=NULL)
    {
	if (XmIsText(_xd_textwidget))
	    XmTextSetString(_xd_textwidget, (char *)lpszString);
	else if (XmIsTextField(_xd_textwidget))
	    XmTextFieldSetString(_xd_textwidget, (char *)lpszString);
    }
    return;
}

int CEdit::xd_get_window_text(LPSTR lpszStringBuf, int nMaxCount) const
{
    // Implements GetWindowText() for XmText and XmTextField.
    // Return value:
    //  0 if the widget has not been created (no call to create() yet).
    //  The length of the text otherwise.

    if (_xd_textwidget!=NULL)
    {
	char *s;
	if (XmIsText(_xd_textwidget))
	    s=XmTextGetString(_xd_textwidget);
	else if (XmIsTextField(_xd_textwidget))
	    s=XmTextFieldGetString(_xd_textwidget);
	strncpy(lpszStringBuf, s, nMaxCount - 1);
	XtFree(s);
	lpszStringBuf[nMaxCount-1]='\0';
	return strlen(lpszStringBuf);
    }
    return 0;
}

int CEdit::xd_get_window_text_length() const
{
    // Implements GetWindowTextLength() for XmText and XmTextField
    // Return value:
    //  0 if the widget has not been created (no call to create() yet).
    //  The length of the text otherwise.

    if (_xd_textwidget!=NULL)
    {
	char *s;
	if (XmIsText(_xd_textwidget))
	    s=XmTextGetString(_xd_textwidget);
	else if (XmIsTextField(_xd_textwidget))
	    s=XmTextFieldGetString(_xd_textwidget);
	int length=strlen(s);
	XtFree(s);
	return length;
    }
    return 0;
}
