netscape-revival
sun-java/awt.bad/macos/MTextAreaPeer.cp
//##############################################################################
//##############################################################################
//
// File: MTextAreaPeer.cp
// Author: Dan Clifford
//
// Copyright © 1995-1996, Netscape Communications Corporation
//
//##############################################################################
//##############################################################################
#include "MToolkit.h"
#include <Types.h>
#include <Memory.h>
#include <LButton.h>
#include <LStdControl.h>
#include <LView.h>
extern "C" {
#include <stdlib.h>
#include "native.h"
#include "typedefs_md.h"
#include "java_awt_Color.h"
#include "java_awt_Font.h"
#include "java_awt_Component.h"
#include "java_awt_TextComponent.h"
#include "sun_awt_macos_MTextAreaPeer.h"
#include "sun_awt_macos_MComponentPeer.h"
};
#include "MTextAreaPeer.h"
#include "MCanvasPeer.h"
#include "UTextTraits.h"
#include "LMacGraphics.h"
#include "MToolkit.h"
#ifdef UNICODE_FONTLIST
#include "MComponentPeer.h"
#endif
enum {
kMScrollTextComponentPeerPPobID = 4096,
kTextAreaMaxCharacters = 16384,
kTextAreaScrollBarWidth = 16,
kTextAreaHorizMarginSize = 4,
kMinimumEnclosedFrameWidth = 500,
kMinimumTextAreaDimension = 16
};
//##############################################################################
//##############################################################################
#pragma mark MComponentPeer IMPLEMENTATION
#pragma mark -
MTextAreaPeer::
MTextAreaPeer(LStream *inStream):
LView(inStream)
{
}
MTextAreaPeer::
~MTextAreaPeer()
{
DisposeJavaDataForPane(this);
}
Boolean
MTextAreaPeer::FocusDraw()
{
Boolean shouldRefocus = ShouldRefocusAWTPane(this);
Boolean result = false;
result = inherited::FocusDraw();
if (shouldRefocus && result)
PreparePeerGrafPort(PaneToPeer(this), NULL);
ForeColor(blackColor);
return result;
}
void
MTextAreaPeer::DrawSelf()
{
Rect eraseRect;
// Erase the area where the grow box should be.
CalcLocalFrameRect(eraseRect);
eraseRect.top = eraseRect.bottom - kTextAreaScrollBarWidth;
eraseRect.left = eraseRect.right - kTextAreaScrollBarWidth;
::EraseRect(&eraseRect);
}
LView*
MTextAreaPeer::CreateMTextAreaPeerStream(LStream *inStream)
{
return new MTextAreaPeer(inStream);
}
MTextEditPeer::
MTextEditPeer(LStream *inStream):
LTextEdit(inStream)
{
}
MTextEditPeer::
~MTextEditPeer()
{
}
LView*
MTextEditPeer::CreateMTextEditPeerStream(LStream *inStream)
{
return new MTextEditPeer(inStream);
}
void
MTextEditPeer::BeTarget()
{
inherited::BeTarget();
SetJavaTarget(PaneToPeer(this));
MToolkitExecutJavaDynamicMethod(PaneToPeer(this), "gotFocus", "()V");
}
void
MTextEditPeer::SetEditable(Boolean editable)
{
if (editable)
mTextAttributes |= textAttr_Editable;
else
mTextAttributes &= ~textAttr_Editable;
}
Boolean
MTextEditPeer::FocusDraw()
{
Classsun_awt_macos_MComponentPeer *componentPeer;
RGBColor foreColor, backColor;
SetSuperCommander(GetContainerWindow(this));
Boolean result = inherited::FocusDraw();
componentPeer = unhand(PaneToPeer(this));
// Set up the foreground and background colors as well as
// the font, style and size information for the port.
::PenNormal();
if (componentPeer->mForeColor != NULL) {
foreColor = ConvertAWTToMacColor(componentPeer->mForeColor);
::RGBForeColor(&foreColor);
}
if (componentPeer->mBackColor != NULL) {
backColor = ConvertAWTToMacColor(componentPeer->mBackColor);
::RGBBackColor(&backColor);
}
#ifdef UNICODE_FONTLIST
int16 encoding = intl_GetWindowEncoding(PaneToPeer(this));
SetUpTextITraits(componentPeer->mFont, componentPeer->mSize, componentPeer->mStyle, encoding);
if((componentPeer->mFont != 0) && (! UEncoding::IsMacRoman(encoding)))
this->SetTextTraitsID(UEncoding::GetTextTextTraitsID(encoding));
#else
SetUpTextITraits(componentPeer->mFont, componentPeer->mSize, componentPeer->mStyle);
#endif
return result;
}
void
MTextEditPeer::DrawSelf()
{
Rect eraseRect;
// Erase the text pane in the background color
// first.
CalcLocalFrameRect(eraseRect);
::EraseRect(&eraseRect);
// Draw the text.
inherited::DrawSelf();
}
void
MTextEditPeer::DontBeTarget()
{
inherited::DontBeTarget();
MToolkitExecutJavaDynamicMethod(PaneToPeer(this), "lostFocus", "()V");
SetJavaTarget(NULL);
}
//##############################################################################
//##############################################################################
void sun_awt_macos_MTextAreaPeer_create(struct Hsun_awt_macos_MTextAreaPeer *textAreaPeerHandle, struct Hsun_awt_macos_MComponentPeer *hostPeerHandle)
{
Classsun_awt_macos_MTextAreaPeer *textAreaPeer = (Classsun_awt_macos_MTextAreaPeer*)unhand(textAreaPeerHandle);
Classjava_awt_TextComponent *textAreaTarget = (Classjava_awt_TextComponent*)unhand(textAreaPeer->target);
LView *superView = (LView *)PeerToPane(hostPeerHandle);
long x = textAreaTarget->x,
y = textAreaTarget->y,
width = textAreaTarget->width,
height = textAreaTarget->height;
// Create the text area and its containing scrollbars
// from a PPob resource.
LPane::SetDefaultView(superView);
LCommander::SetDefaultCommander(GetContainerWindow(superView));
LView *scrolledTextAreaPane = NULL;
try {
scrolledTextAreaPane = (LView *)UReanimator::ReadObjects('PPob', kMScrollTextComponentPeerPPobID);
}
catch (...) {
SignalError(0, JAVAPKG "OutOfMemoryError", 0);
return;
}
if (width < kMinimumTextAreaDimension)
width = kMinimumTextAreaDimension;
if (height < kMinimumTextAreaDimension)
height = kMinimumTextAreaDimension;
OverlapBindToTopLevelFrame((struct Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle, hostPeerHandle, &x, &y, &width, &height);
// Install the new text area in its super pane.
scrolledTextAreaPane->PlaceInSuperFrameAt(x, y, false);
scrolledTextAreaPane->ResizeFrameTo(width, height, false);
scrolledTextAreaPane->FinishCreate();
scrolledTextAreaPane->Enable();
scrolledTextAreaPane->Activate();
// Finish things upÉ
MTextEditPeer *textEditPane = (MTextEditPeer *)scrolledTextAreaPane->FindPaneByID(MTextEditPeer::class_ID);
UInt32 enclosedPaneWidth = width - kTextAreaScrollBarWidth - kTextAreaHorizMarginSize;
if (enclosedPaneWidth < kMinimumEnclosedFrameWidth)
enclosedPaneWidth = kMinimumEnclosedFrameWidth;
textEditPane->ResizeImageTo(enclosedPaneWidth, height, false);
textEditPane->SetUserCon((long)textAreaPeerHandle);
textEditPane->SetEditable(textAreaTarget->editable);
scrolledTextAreaPane->SetUserCon((long)textAreaPeerHandle);
scrolledTextAreaPane->SetPaneID(MTextAreaPeer::class_ID);
textAreaPeer->mOwnerPane = (long)scrolledTextAreaPane;
textAreaPeer->mRecalculateClip = true;
textEditPane->SetPaneID(MTextEditPeer::class_ID);
ClearCachedAWTRefocusPane();
}
void sun_awt_macos_MTextAreaPeer_setEditable(struct Hsun_awt_macos_MTextAreaPeer *textComponentPeerObjectHandle, long editable)
{
LView *scrollTextAreaPane = (LView *)PeerToPane((Hsun_awt_macos_MComponentPeer *)textComponentPeerObjectHandle);
MTextEditPeer *textAreaPane;
if (scrollTextAreaPane == NULL)
return;
textAreaPane = (MTextEditPeer *)scrollTextAreaPane->FindPaneByID(MTextEditPeer::class_ID);
textAreaPane->SetEditable(editable);
}
void sun_awt_macos_MTextAreaPeer_select(struct Hsun_awt_macos_MTextAreaPeer *textAreaPeerHandle, long from, long to)
{
LView *scrollTextAreaPane = (LView *)PeerToPane((Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle);
MTextEditPeer *textAreaPane;
TEHandle textEditHandle;
if (scrollTextAreaPane == NULL)
return;
textAreaPane = (MTextEditPeer *)scrollTextAreaPane->FindPaneByID(MTextEditPeer::class_ID);
textAreaPane->FocusDraw();
textEditHandle = textAreaPane->GetMacTEH();
return;
#ifdef UNICODE_FONTLIST
// we need to convert the parameter from and to from characer length to byte count
CharsHandle textHandle = (**textEditHandle).hText; // DONT CALL TEGETTEXT!
HLock((Handle)textHandle);
unsigned char *textPtr = (unsigned char*) *textHandle;
long realfrom, realto;
short encoding = intl_GetWindowEncoding((Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle);
realfrom = INTL_TextCharLenToByteCount(encoding, textPtr, from);
realto = realfrom + INTL_TextCharLenToByteCount(encoding, (textPtr+realfrom), (to-from));
HUnlock((Handle)textHandle);
::TESetSelect(realfrom, realto, textEditHandle);
#else
::TESetSelect(from, to, textEditHandle);
#endif
LCommander::SwitchTarget(textAreaPane);
}
long sun_awt_macos_MTextAreaPeer_getSelectionStart(struct Hsun_awt_macos_MTextAreaPeer *textAreaPeerHandle)
{
LView *scrollTextAreaPane = (LView *)PeerToPane((Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle);
MTextEditPeer *textAreaPane;
TEHandle textEditHandle;
if (scrollTextAreaPane == NULL)
return 0;
textAreaPane = (MTextEditPeer *)scrollTextAreaPane->FindPaneByID(MTextEditPeer::class_ID);
textEditHandle = textAreaPane->GetMacTEH();
#ifdef UNICODE_FONTLIST
// we need to convert byte count back to character length
long startByte = (**textEditHandle).selStart;
CharsHandle textHandle = (**textEditHandle).hText;
HLock((Handle)textHandle);
unsigned char *textPtr = (unsigned char*) *textHandle;
short encoding = intl_GetWindowEncoding((Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle);
long startCharLen = INTL_TextByteCountToCharLen(encoding, textPtr, startByte);
HUnlock((Handle)textHandle);
return startCharLen;
#else
return (**textEditHandle).selStart;
#endif
}
long sun_awt_macos_MTextAreaPeer_getSelectionEnd(struct Hsun_awt_macos_MTextAreaPeer *textAreaPeerHandle)
{
LView *scrollTextAreaPane = (LView *)PeerToPane((Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle);
MTextEditPeer *textAreaPane;
TEHandle textEditHandle;
if (scrollTextAreaPane == NULL)
return 0;
textAreaPane = (MTextEditPeer *)scrollTextAreaPane->FindPaneByID(MTextEditPeer::class_ID);
textEditHandle = textAreaPane->GetMacTEH();
#ifdef UNICODE_FONTLIST
// we need to convert byte count back to character length
long endByte = (**textEditHandle).selEnd;
CharsHandle textHandle = (**textEditHandle).hText; // DONT CALL TEGETTEXT!
HLock((Handle)textHandle);
unsigned char *textPtr = (unsigned char*) *textHandle;
short encoding = intl_GetWindowEncoding((Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle);
long endCharLen = INTL_TextByteCountToCharLen(encoding, textPtr, endByte);
HUnlock((Handle)textHandle);
return endCharLen;
#else
return (**textEditHandle).selEnd;
#endif
}
void sun_awt_macos_MTextAreaPeer_setText(struct Hsun_awt_macos_MTextAreaPeer *textAreaPeerHandle, struct Hjava_lang_String *string)
{
sun_awt_macos_MTextAreaPeer_replaceText(textAreaPeerHandle, string, 0, 99999);
}
struct Hjava_lang_String *sun_awt_macos_MTextAreaPeer_getText(struct Hsun_awt_macos_MTextAreaPeer *textAreaPeerHandle)
{
LView *scrollTextAreaPane = (LView *)PeerToPane((Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle);
TEHandle textEditHandle;
CharsHandle textHandle;
char *textPtr;
long textSize;
struct Hjava_lang_String *resultString;
MTextEditPeer *textAreaPane;
if (scrollTextAreaPane == NULL)
return makeJavaString("", 0);
textAreaPane = (MTextEditPeer *)scrollTextAreaPane->FindPaneByID(MTextEditPeer::class_ID);
LMSetToolScratch(textAreaPane);
textEditHandle = textAreaPane->GetMacTEH();
LMSetApplScratch(textEditHandle);
textHandle = (**textEditHandle).hText;
textSize = GetHandleSize(textHandle);
HLock((Handle)textHandle);
textPtr = *textHandle;
ReturnsToNewLines(textPtr, textSize);
#ifdef UNICODE_FONTLIST
short encoding = intl_GetWindowEncoding((Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle);
resultString = intl_makeJavaString(encoding, textPtr, textSize);
#else
resultString = makeJavaString(textPtr, textSize);
#endif
NewLinesToReturns(textPtr, textSize);
HUnlock((Handle)textHandle);
return resultString;
}
void sun_awt_macos_MTextAreaPeer_replaceText(struct Hsun_awt_macos_MTextAreaPeer *textAreaPeerHandle, struct Hjava_lang_String *textToReplaceWith, long start, long end)
{
LView *scrollTextAreaPane = (LView *)PeerToPane((Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle);
long replaceTextLength;
char *newCString;
MTextEditPeer *textAreaPane;
if (scrollTextAreaPane == NULL)
return;
textAreaPane = (MTextEditPeer *)scrollTextAreaPane->FindPaneByID(MTextEditPeer::class_ID);
#ifdef UNICODE_FONTLIST
short encoding = intl_GetWindowEncoding((Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle);
newCString = intl_allocCString(encoding, textToReplaceWith);
#else
newCString = allocCString(textToReplaceWith);
#endif
// To prevent horrible infinite recursions on out-of-memory
// errors, silently fail on errors.
exceptionClear(EE());
if (newCString != NULL) {
TEHandle textEditHandle;
CharsHandle currentContents;
char *newTempBuffer;
long newSize,
currentSize;
replaceTextLength = strlen(newCString);
textEditHandle = textAreaPane->GetMacTEH();
currentContents = (**textEditHandle).hText;
currentSize = GetHandleSize(currentContents);
#ifdef UNICODE_FONTLIST
// we need to convert start and end from character length to byte count
CharsHandle textHandle = (**textEditHandle).hText; // DONT CALL TEGETTEXT!
HLock((Handle)textHandle);
unsigned char *textPtr = (unsigned char*) *textHandle;
short encoding = intl_GetWindowEncoding((Hsun_awt_macos_MComponentPeer *)textAreaPeerHandle);
if(start != 0)
start = INTL_TextCharLenToByteCount(encoding, textPtr, start);
if(end != 99999)
end = INTL_TextCharLenToByteCount(encoding, textPtr, end);
HUnlock((Handle)textHandle);
#endif
if (start > currentSize)
start = currentSize;
if (end > currentSize)
end = currentSize;
if (start < 0)
start = 0;
if (end < 0)
end = 0;
if (end < start)
end = start;
long firstSegment = start,
lastSegment = currentSize - end;
newSize = firstSegment + replaceTextLength + lastSegment;
newTempBuffer = (char *)malloc(newSize);
if (newTempBuffer != NULL) {
// Munge the existing text to add the new text.
BlockMoveData(*currentContents, newTempBuffer, firstSegment);
BlockMoveData(newCString, newTempBuffer + firstSegment, replaceTextLength);
BlockMoveData(*currentContents + end, newTempBuffer + firstSegment + replaceTextLength, lastSegment);
// Convert all the new lines to CRs, and set the new text.
NewLinesToReturns(newTempBuffer + firstSegment, replaceTextLength);
// If the new text is longer than our limit, cut
// some text off of the beginning.
if (newSize > kTextAreaMaxCharacters) {
UInt32 truncationAmount = newSize - kTextAreaMaxCharacters;
BlockMoveData(newTempBuffer + truncationAmount, newTempBuffer, kTextAreaMaxCharacters);
newSize = kTextAreaMaxCharacters;
}
::TESetText((Ptr)newTempBuffer, newSize, textEditHandle);
::TECalText(textEditHandle);
textAreaPane->AdjustImageToText();
free(newTempBuffer);
// If we are inserting at the end of the current text, or
// completely replacing it, make sure to scroll to end
// of the text.
Rect tempRect;
if (lastSegment == 0) {
SDimension32 imageSize;
SInt32 whereToScroll;
textAreaPane->CalcLocalFrameRect(tempRect);
textAreaPane->GetImageSize(imageSize);
if (tempRect.bottom <= tempRect.top)
whereToScroll = 0;
else
whereToScroll = imageSize.height - (tempRect.bottom - tempRect.top);
LView::OutOfFocus(NULL);
textAreaPane->ScrollImageTo(0, (whereToScroll < 0) ? 0 : whereToScroll, false);
}
// Invalidate the text area, minus the scrollbars
// so that the text is re-drawn.
// dkc 2/7/96
if (textAreaPane->FocusDraw())
textAreaPane->Draw(NULL);
}
free(newCString);
}
}
void sun_awt_macos_MTextAreaPeer_insertText(struct Hsun_awt_macos_MTextAreaPeer *textAreaPeerHandle, struct Hjava_lang_String *textToInsert, long position)
{
sun_awt_macos_MTextAreaPeer_replaceText(textAreaPeerHandle, textToInsert, position, position);
}
void sun_awt_macos_MTextAreaPeer_reshape(struct Hsun_awt_macos_MTextAreaPeer *componentPeerHandle, long x, long y, long width, long height)
{
LView *scrolledTextAreaPane = (LView *)PeerToPane((Hsun_awt_macos_MComponentPeer *)componentPeerHandle);
MTextEditPeer *textAreaPane;
if (scrolledTextAreaPane == NULL)
return;
if (width < kMinimumTextAreaDimension)
width = kMinimumTextAreaDimension;
if (height < kMinimumTextAreaDimension)
height = kMinimumTextAreaDimension;
textAreaPane = (MTextEditPeer *)scrolledTextAreaPane->FindPaneByID(MTextEditPeer::class_ID);
if (textAreaPane == NULL)
return;
OverlapBindToTopLevelFrame((struct Hsun_awt_macos_MComponentPeer *)componentPeerHandle, NULL, &x, &y, &width, &height);
UInt32 enclosedPaneWidth = width - kTextAreaScrollBarWidth - kTextAreaHorizMarginSize;
if (enclosedPaneWidth < kMinimumEnclosedFrameWidth)
enclosedPaneWidth = kMinimumEnclosedFrameWidth;
textAreaPane->ResizeImageTo(enclosedPaneWidth, height, false);
sun_awt_macos_MComponentPeer_pReshape((struct Hsun_awt_macos_MComponentPeer *)componentPeerHandle, x, y, width, height);
}