744 lines
20 KiB
C++
744 lines
20 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
#include "nsTextWidget.h"
|
|
#include <ToolUtils.h>
|
|
#include <Appearance.h>
|
|
#include <memory>
|
|
|
|
using std::auto_ptr;
|
|
|
|
#if TARGET_CARBON || (UNIVERSAL_INTERFACES_VERSION >= 0x0330)
|
|
#include <ControlDefinitions.h>
|
|
#endif
|
|
|
|
NS_IMPL_ADDREF(nsTextWidget);
|
|
NS_IMPL_RELEASE(nsTextWidget);
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
// ¥ NOTE ABOUT MENU HANDLING ¥
|
|
//
|
|
// The definitions below, as well as the NS_MENU_SELECTED code in
|
|
// DispatchEvent() are temporary hacks only. They require the menu
|
|
// resources to be created under Contructor with the standard
|
|
// PowerPlant menu IDs. All that will go away because:
|
|
// - nsTextWidget will be rewritten as an XP widget by the Editor team.
|
|
// - menu handling will be rewritten by the XPApp team.
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include <Scrap.h>
|
|
|
|
typedef SInt32 MessageT;
|
|
typedef PRUint32 Uint32;
|
|
const MessageT cmd_Cut = 12; // nil
|
|
const MessageT cmd_Copy = 13; // nil
|
|
const MessageT cmd_Paste = 14; // nil
|
|
const MessageT cmd_Clear = 15; // nil
|
|
const MessageT cmd_SelectAll = 16; // nil
|
|
|
|
enum
|
|
{
|
|
menu_Apple = 128,
|
|
menu_File,
|
|
menu_Edit
|
|
};
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
nsTextWidget::nsTextWidget() : nsMacControl(), nsITextWidget(), Repeater()
|
|
{
|
|
NS_INIT_REFCNT();
|
|
WIDGET_SET_CLASSNAME("nsTextWidget");
|
|
SetControlType(kControlEditTextProc);
|
|
mIsPassword = PR_FALSE;
|
|
mIsReadOnly = PR_FALSE;
|
|
|
|
AcceptFocusOnClick(PR_TRUE);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
nsTextWidget::~nsTextWidget()
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_IMETHODIMP nsTextWidget::Create(nsIWidget *aParent,
|
|
const nsRect &aRect,
|
|
EVENT_CALLBACK aHandleEventFunction,
|
|
nsIDeviceContext *aContext,
|
|
nsIAppShell *aAppShell,
|
|
nsIToolkit *aToolkit,
|
|
nsWidgetInitData *aInitData)
|
|
{
|
|
if (aInitData)
|
|
{
|
|
nsTextWidgetInitData* initData = (nsTextWidgetInitData*)aInitData;
|
|
if (initData->mIsPassword)
|
|
{
|
|
SetControlType(kControlEditTextPasswordProc);
|
|
mIsPassword = PR_TRUE;
|
|
}
|
|
else if (mIsReadOnly)
|
|
{
|
|
SetControlType(kControlStaticTextProc);
|
|
mIsReadOnly = PR_TRUE;
|
|
}
|
|
}
|
|
|
|
Inherited::Create(aParent, aRect, aHandleEventFunction,
|
|
aContext, aAppShell, aToolkit, aInitData);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
// Destroy
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// The repeater in this widget needs to use out of band notification
|
|
// to sever its ties with the nsTimer. If we just rely on the
|
|
// dtor to do it, it will never get called because the nsTimer holds a ref to
|
|
// this object.
|
|
//
|
|
NS_IMETHODIMP
|
|
nsTextWidget::Destroy()
|
|
{
|
|
Inherited::Destroy();
|
|
if (mRepeating) RemoveFromRepeatList();
|
|
if (mIdling) RemoveFromIdleList();
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_INTERFACE_MAP_BEGIN(nsTextWidget)
|
|
NS_INTERFACE_MAP_ENTRY(nsITextWidget)
|
|
NS_INTERFACE_MAP_END_INHERITING(Inherited)
|
|
|
|
#pragma mark -
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
PRBool nsTextWidget::DispatchMouseEvent(nsMouseEvent &aEvent)
|
|
{
|
|
PRBool eventHandled = nsWindow::DispatchMouseEvent(aEvent); // we don't want the 'Inherited' nsMacControl behavior
|
|
|
|
EventRecord* theOSEvent;
|
|
|
|
if ((! eventHandled) && (mControl != nsnull))
|
|
{
|
|
switch (aEvent.message)
|
|
{
|
|
case NS_MOUSE_LEFT_DOUBLECLICK:
|
|
case NS_MOUSE_LEFT_BUTTON_DOWN:
|
|
Point thePoint;
|
|
thePoint.h = aEvent.point.x;
|
|
thePoint.v = aEvent.point.y;
|
|
|
|
short theModifiers;
|
|
theOSEvent = (EventRecord*)aEvent.nativeMsg;
|
|
if (theOSEvent)
|
|
{
|
|
theModifiers = theOSEvent->modifiers;
|
|
}
|
|
else
|
|
{
|
|
if (aEvent.isShift) theModifiers = shiftKey;
|
|
if (aEvent.isControl) theModifiers |= controlKey;
|
|
if (aEvent.isAlt) theModifiers |= optionKey;
|
|
}
|
|
StartDraw();
|
|
::HandleControlClick(mControl, thePoint, theModifiers, nil);
|
|
EndDraw();
|
|
eventHandled = PR_TRUE;
|
|
break;
|
|
|
|
case NS_MOUSE_ENTER:
|
|
SetCursor(eCursor_select);
|
|
break;
|
|
|
|
case NS_MOUSE_EXIT:
|
|
SetCursor(eCursor_standard);
|
|
break;
|
|
}
|
|
}
|
|
return (eventHandled);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// DispatchWindowEvent
|
|
//
|
|
// Handle the following events: keys, focus, edit menu commands.
|
|
// The strategy for key events is to use the native OS event
|
|
// when it exists, otherwise use the Raptor nsKeyEvent.
|
|
//-------------------------------------------------------------------------
|
|
PRBool nsTextWidget::DispatchWindowEvent(nsGUIEvent &aEvent)
|
|
{
|
|
// filter cursor keys
|
|
PRBool passKeyEvent = PR_TRUE;
|
|
switch (aEvent.message)
|
|
{
|
|
case NS_KEY_DOWN:
|
|
case NS_KEY_UP:
|
|
{
|
|
// hack: if Enter is pressed, pass Return
|
|
nsKeyEvent* keyEvent = (nsKeyEvent*)&aEvent;
|
|
|
|
#if 0
|
|
// this hack is no longer needed, since Enter is being mapped to
|
|
// VK_RETURN in the event handler
|
|
if (keyEvent->keyCode == kEnterCharCode)
|
|
keyEvent->keyCode = NS_VK_RETURN;
|
|
#endif
|
|
|
|
// is this hack really needed?
|
|
EventRecord* theOSEvent = (EventRecord*)aEvent.nativeMsg;
|
|
if (theOSEvent && ((theOSEvent->message & charCodeMask) == kEnterCharCode))
|
|
theOSEvent->message = (theOSEvent->message & ~charCodeMask) + kReturnCharCode;
|
|
|
|
switch (keyEvent->keyCode)
|
|
{
|
|
// case NS_VK_PAGE_UP:
|
|
// case NS_VK_PAGE_DOWN:
|
|
case NS_VK_END:
|
|
case NS_VK_HOME:
|
|
case NS_VK_LEFT:
|
|
case NS_VK_UP:
|
|
case NS_VK_RIGHT:
|
|
case NS_VK_DOWN:
|
|
passKeyEvent = PR_FALSE;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// dispatch the message
|
|
PRBool eventHandled = PR_FALSE;
|
|
if (passKeyEvent)
|
|
eventHandled = Inherited::DispatchWindowEvent(aEvent);
|
|
|
|
// handle the message here if nobody else processed it already
|
|
if ((! eventHandled) && (mControl != nsnull))
|
|
{
|
|
switch (aEvent.message)
|
|
{
|
|
case NS_MENU_SELECTED:
|
|
{
|
|
nsMenuEvent* menuEvent = (nsMenuEvent*)&aEvent;
|
|
long menuID = HiWord(menuEvent->mCommand);
|
|
long menuItem = LoWord(menuEvent->mCommand);
|
|
switch (menuID)
|
|
{
|
|
case menu_Edit:
|
|
{
|
|
switch (menuItem)
|
|
{
|
|
// case cmd_Undo:
|
|
|
|
case cmd_Cut:
|
|
case cmd_Copy:
|
|
{
|
|
PRUint32 startSel = 0, endSel = 0;
|
|
GetSelection ( &startSel, &endSel );
|
|
if ( startSel != endSel ) {
|
|
const Uint32 selectionLen = endSel - startSel;
|
|
|
|
// extract out the selection into a different nsString so
|
|
// we can keep it unicode as long as possible
|
|
PRUint32 unused = 0;
|
|
nsString str, selection;
|
|
GetText(str, 0, unused );
|
|
str.Mid(selection, startSel, selectionLen);
|
|
|
|
// now |selection| holds the current selection in unicode.
|
|
// We need to convert it to a c-string for MacOS.
|
|
auto_ptr<char> cRepOfSelection(new char[selectionLen + 1]);
|
|
selection.ToCString(cRepOfSelection.get(), selectionLen + 1);
|
|
|
|
// copy it to the scrapMgr
|
|
#if TARGET_CARBON
|
|
::ClearCurrentScrap();
|
|
ScrapRef scrap;
|
|
::GetCurrentScrap(&scrap);
|
|
::PutScrapFlavor(scrap, 'TEXT', 0L /* ??? */, selectionLen, cRepOfSelection.get());
|
|
#else
|
|
::ZeroScrap();
|
|
::PutScrap ( selectionLen, 'TEXT', cRepOfSelection.get() );
|
|
#endif
|
|
// if we're cutting, remove the text from the widget
|
|
if ( menuItem == cmd_Cut ) {
|
|
unused = 0;
|
|
str.Cut ( startSel, selectionLen );
|
|
SetText ( str, unused );
|
|
SetSelection(startSel, startSel);
|
|
}
|
|
} // if there is a selection
|
|
eventHandled = PR_TRUE;
|
|
break;
|
|
}
|
|
|
|
case cmd_Paste:
|
|
{
|
|
long scrapOffset;
|
|
Handle scrapH = ::NewHandle(0);
|
|
#if TARGET_CARBON
|
|
ScrapRef scrap;
|
|
OSStatus err;
|
|
err = ::GetCurrentScrap(&scrap);
|
|
if (err != noErr) return NS_ERROR_FAILURE;
|
|
err = ::GetScrapFlavorSize(scrap, 'TEXT', &scrapOffset);
|
|
// XXX uhh.. i don't think this is right..
|
|
long scrapLen = scrapOffset;
|
|
if ( scrapOffset > 0 )
|
|
#else
|
|
long scrapLen = ::GetScrap(scrapH, 'TEXT', &scrapOffset);
|
|
if (scrapLen > 0)
|
|
#endif
|
|
{
|
|
::HLock(scrapH);
|
|
|
|
// truncate to the first line
|
|
char* cr = strchr((char*)*scrapH, '\r');
|
|
if (cr != nil)
|
|
scrapLen = cr - *scrapH;
|
|
|
|
// paste text
|
|
nsString str;
|
|
str.AssignWithConversion((char*)*scrapH, scrapLen);
|
|
PRUint32 startSel, endSel;
|
|
GetSelection(&startSel, &endSel);
|
|
PRUint32 outSize;
|
|
InsertText(str, startSel, endSel, outSize);
|
|
startSel += str.Length();
|
|
SetSelection(startSel, startSel);
|
|
|
|
::HUnlock(scrapH);
|
|
}
|
|
::DisposeHandle(scrapH);
|
|
eventHandled = PR_TRUE;
|
|
break;
|
|
}
|
|
case cmd_Clear:
|
|
{
|
|
nsString str;
|
|
PRUint32 outSize;
|
|
SetText(str, outSize);
|
|
eventHandled = PR_TRUE;
|
|
break;
|
|
}
|
|
case cmd_SelectAll:
|
|
{
|
|
SelectAll();
|
|
eventHandled = PR_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
} // case NS_MENU_SELECTED
|
|
|
|
case NS_GOTFOCUS:
|
|
{
|
|
StartDraw();
|
|
ActivateControl(mControl);
|
|
OSErr err = SetKeyboardFocus(mWindowPtr, mControl, kControlFocusNextPart);
|
|
nsRect rect = mBounds;
|
|
rect.x = rect.y = 0;
|
|
Rect macRect;
|
|
nsRectToMacRect(rect, macRect);
|
|
::InsetRect(&macRect, 2, 2);
|
|
::DrawThemeFocusRect(&macRect, true);
|
|
EndDraw();
|
|
StartIdling();
|
|
break;
|
|
}
|
|
|
|
case NS_LOSTFOCUS:
|
|
{
|
|
StopIdling();
|
|
StartDraw();
|
|
OSErr err = SetKeyboardFocus(mWindowPtr, mControl, kControlFocusNoPart);
|
|
nsRect rect = mBounds;
|
|
rect.x = rect.y = 0;
|
|
Rect macRect;
|
|
nsRectToMacRect(rect, macRect);
|
|
::InsetRect(&macRect, 2, 2);
|
|
::DrawThemeFocusRect(&macRect, false);
|
|
DeactivateControl(mControl);
|
|
EndDraw();
|
|
break;
|
|
}
|
|
|
|
case NS_KEY_DOWN:
|
|
{
|
|
char theChar;
|
|
unsigned short theKey;
|
|
unsigned short theModifiers;
|
|
EventRecord* theOSEvent = (EventRecord*)aEvent.nativeMsg;
|
|
nsKeyEvent* keyEvent = (nsKeyEvent*)&aEvent;
|
|
if (theOSEvent)
|
|
{
|
|
theChar = (theOSEvent->message & charCodeMask);
|
|
theKey = (theOSEvent->message & keyCodeMask) >> 8;
|
|
theModifiers = theOSEvent->modifiers;
|
|
}
|
|
else
|
|
{
|
|
theChar = keyEvent->keyCode;
|
|
theKey = 0; // what else?
|
|
if (keyEvent->isShift) theModifiers = shiftKey;
|
|
if (keyEvent->isControl) theModifiers |= controlKey;
|
|
if (keyEvent->isAlt) theModifiers |= optionKey;
|
|
|
|
}
|
|
if (theChar != NS_VK_RETURN) // don't pass Return: nsTextWidget is a single line editor
|
|
{
|
|
StartDraw();
|
|
::HandleControlKey(mControl, theKey, theChar, theModifiers);
|
|
EndDraw();
|
|
eventHandled = PR_TRUE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return (eventHandled);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
PRBool nsTextWidget::OnPaint(nsPaintEvent &aEvent)
|
|
{
|
|
Inherited::OnPaint(aEvent);
|
|
|
|
/* draw a box.*/
|
|
if (mVisible && mIsReadOnly)
|
|
{
|
|
nsRect ctlRect = mBounds;
|
|
ctlRect.x = ctlRect.y = 0;
|
|
//ctlRect.Deflate(1, 1);
|
|
mTempRenderingContext->SetColor(NS_RGB(0, 0, 0));
|
|
mTempRenderingContext->DrawRect(ctlRect);
|
|
}
|
|
|
|
return PR_FALSE;
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::SetPassword(PRBool aIsPassword)
|
|
{
|
|
nsresult theResult = NS_OK;
|
|
|
|
// note: it is assumed that we can't have a read-only password field
|
|
if (aIsPassword != mIsPassword)
|
|
{
|
|
mIsPassword = aIsPassword;
|
|
short newControlType = (aIsPassword ? kControlEditTextPasswordProc : kControlEditTextProc);
|
|
SetControlType(newControlType);
|
|
|
|
theResult = CreateOrReplaceMacControl(newControlType);
|
|
}
|
|
return theResult;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::SetReadOnly(PRBool aReadOnlyFlag, PRBool& aOldFlag)
|
|
{
|
|
nsresult theResult = NS_OK;
|
|
|
|
// note: it is assumed that we can't have a read-only password field
|
|
aOldFlag = mIsReadOnly;
|
|
if (aReadOnlyFlag != mIsReadOnly)
|
|
{
|
|
mIsReadOnly = aReadOnlyFlag;
|
|
short newControlType = (aReadOnlyFlag ? kControlStaticTextProc : kControlEditTextProc);
|
|
SetControlType(newControlType);
|
|
|
|
theResult = CreateOrReplaceMacControl(newControlType);
|
|
}
|
|
return theResult;
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::SetMaxTextLength(PRUint32 aChars)
|
|
{
|
|
//¥TODO: install a kControlEditTextKeyFilterTag proc
|
|
return NS_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::GetText(nsString& aTextBuffer, PRUint32 /*aBufferSize*/, PRUint32& aSize)
|
|
{
|
|
if (!mControl)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
ResType textTag = (mIsPassword ? kControlEditTextPasswordTag : kControlEditTextTextTag);
|
|
|
|
Size textSize;
|
|
::GetControlDataSize(mControl, kControlNoPart, textTag, &textSize);
|
|
|
|
char* str = new char[textSize];
|
|
if (str)
|
|
{
|
|
::GetControlData(mControl, kControlNoPart, textTag, textSize, (Ptr)str, &textSize);
|
|
aTextBuffer.SetLength(0);
|
|
aTextBuffer.AppendWithConversion(str, textSize);
|
|
aSize = textSize;
|
|
delete [] str;
|
|
}
|
|
else
|
|
{
|
|
aSize = 0;
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// Assumes aSize is |out| only and does not yet have a value.
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::SetText(const nsString& aText, PRUint32& outSize)
|
|
{
|
|
outSize = aText.Length();
|
|
const unsigned int bufferSize = outSize + 1; // add 1 for null
|
|
|
|
if (!mControl)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
|
auto_ptr<char> str ( new char[bufferSize] );
|
|
if ( str.get() )
|
|
{
|
|
ResType textTag = (mIsPassword ? kControlEditTextPasswordTag : kControlEditTextTextTag);
|
|
aText.ToCString(str.get(), bufferSize);
|
|
::SetControlData(mControl, kControlNoPart, textTag, outSize, (Ptr)str.get());
|
|
Invalidate(PR_FALSE);
|
|
}
|
|
else
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::InsertText(const nsString &aText, PRUint32 aStartPos, PRUint32 aEndPos, PRUint32& aSize)
|
|
{
|
|
if (!mControl)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
Size textSize;
|
|
::GetControlDataSize(mControl, kControlNoPart, kControlEditTextTextTag, &textSize);
|
|
|
|
nsString textStr;
|
|
PRUint32 outTextSize;
|
|
nsresult retVal = GetText(textStr, textSize, outTextSize);
|
|
if (retVal != NS_OK)
|
|
return retVal;
|
|
|
|
if ((aStartPos == -1L) && (aEndPos == -1L))
|
|
{
|
|
textStr.Append(aText);
|
|
}
|
|
else
|
|
{
|
|
if ((PRInt32)aStartPos < 0)
|
|
aStartPos = 0;
|
|
if ((PRInt32)aEndPos < 0)
|
|
aStartPos = 0;
|
|
if (aEndPos < aStartPos)
|
|
aEndPos = aStartPos;
|
|
textStr.Cut(aStartPos, aEndPos - aStartPos);
|
|
textStr.Insert(aText, aStartPos);
|
|
}
|
|
|
|
aSize = textStr.Length();
|
|
return (SetText(textStr, aSize));
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::RemoveText()
|
|
{
|
|
if (!mControl)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
StartDraw();
|
|
::SetControlData(mControl, kControlNoPart, kControlEditTextTextTag, 0, (Ptr)"");
|
|
EndDraw();
|
|
return NS_OK;
|
|
}
|
|
|
|
#pragma mark -
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::SelectAll()
|
|
{
|
|
if (!mControl)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
Size textSize;
|
|
::GetControlDataSize(mControl, kControlNoPart, kControlEditTextTextTag, &textSize);
|
|
|
|
return (SetSelection(0, textSize));
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::SetSelection(PRUint32 aStartSel, PRUint32 aEndSel)
|
|
{
|
|
if (!mControl)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
ControlEditTextSelectionRec textSelectionRec;
|
|
textSelectionRec.selStart = aStartSel;
|
|
textSelectionRec.selEnd = aEndSel;
|
|
|
|
StartDraw();
|
|
::SetControlData(mControl, kControlNoPart, kControlEditTextSelectionTag,
|
|
sizeof(textSelectionRec), (Ptr)&textSelectionRec);
|
|
EndDraw();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::GetSelection(PRUint32 *aStartSel, PRUint32 *aEndSel)
|
|
{
|
|
if (!mControl)
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
ControlEditTextSelectionRec textSelectionRec;
|
|
|
|
Size dataSize = sizeof(textSelectionRec);
|
|
::GetControlData(mControl, kControlNoPart, kControlEditTextSelectionTag,
|
|
dataSize, (Ptr)&textSelectionRec, &dataSize);
|
|
|
|
*aStartSel = textSelectionRec.selStart;
|
|
*aEndSel = textSelectionRec.selEnd;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::SetCaretPosition(PRUint32 aPosition)
|
|
{
|
|
return(SetSelection(aPosition, aPosition));
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
NS_METHOD nsTextWidget::GetCaretPosition(PRUint32& aPos)
|
|
{
|
|
PRUint32 startSel, endSel;
|
|
nsresult retVal = GetSelection(&startSel, &endSel);
|
|
aPos = startSel;
|
|
return retVal;
|
|
}
|
|
|
|
#pragma mark -
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void nsTextWidget::RepeatAction(const EventRecord& inMacEvent)
|
|
{
|
|
if (mControl)
|
|
{
|
|
StartDraw();
|
|
// This should really live in the window but
|
|
// we have to set the graphic environment
|
|
IdleControls(mWindowPtr);
|
|
EndDraw();
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void nsTextWidget::GetRectForMacControl(nsRect &outRect)
|
|
{
|
|
outRect = mBounds;
|
|
outRect.x = outRect.y = 0;
|
|
// inset to make space for border
|
|
if (mIsReadOnly)
|
|
outRect.Deflate(1, 1);
|
|
else
|
|
outRect.Deflate(4, 4);
|
|
}
|
|
|