Compare commits

..

2 Commits

Author SHA1 Message Date
heikki%netscape.com
a637f81f7f new project started
git-svn-id: svn://10.0.0.236/branches/mozilla@91184 18797224-902f-48f8-a5cc-f745e15eee43
2001-04-03 22:13:38 +00:00
(no author)
6cfadae5d1 This commit was manufactured by cvs2svn to create branch 'mozilla'.
git-svn-id: svn://10.0.0.236/branches/mozilla@8534 18797224-902f-48f8-a5cc-f745e15eee43
1998-08-26 18:36:10 +00:00
15 changed files with 102 additions and 25180 deletions

View File

@@ -1 +0,0 @@
2.0.5

File diff suppressed because it is too large Load Diff

View File

@@ -1,577 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=80: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* Mozilla Japan.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Masayuki Nakano <masayuki@d-toybox.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsQueryContentEventHandler.h"
#include "nsCOMPtr.h"
#include "nsPresContext.h"
#include "nsIPresShell.h"
#include "nsISelection.h"
#include "nsIDOMText.h"
#include "nsIDOMRange.h"
#include "nsRange.h"
#include "nsGUIEvent.h"
#include "nsICaret.h"
#include "nsFrameSelection.h"
#include "nsIFrame.h"
#include "nsIView.h"
#include "nsIContentIterator.h"
#include "nsTextFragment.h"
#include "nsTextFrame.h"
nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult);
/******************************************************************/
/* nsQueryContentEventHandler */
/******************************************************************/
nsQueryContentEventHandler::nsQueryContentEventHandler(
nsPresContext* aPresContext) :
mPresContext(aPresContext),
mPresShell(aPresContext->GetPresShell()), mSelection(nsnull),
mFirstSelectedRange(nsnull), mRootContent(nsnull)
{
}
nsresult
nsQueryContentEventHandler::Init(nsQueryContentEvent* aEvent)
{
NS_ASSERTION(aEvent, "aEvent must not be null");
if (mSelection)
return NS_OK;
aEvent->mSucceeded = PR_FALSE;
if (!mPresShell)
return NS_ERROR_NOT_AVAILABLE;
nsresult rv = mPresShell->GetSelectionForCopy(getter_AddRefs(mSelection));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(mSelection,
"GetSelectionForCopy succeeded, but the result is null");
nsCOMPtr<nsIDOMRange> firstRange;
rv = mSelection->GetRangeAt(0, getter_AddRefs(firstRange));
// This shell doesn't support selection.
if (NS_FAILED(rv))
return NS_ERROR_NOT_AVAILABLE;
mFirstSelectedRange = do_QueryInterface(firstRange);
NS_ENSURE_TRUE(mFirstSelectedRange, NS_ERROR_FAILURE);
nsINode* startNode = mFirstSelectedRange->GetStartParent();
NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
mRootContent = startNode->GetSelectionRootContent(mPresShell);
NS_ENSURE_TRUE(mRootContent, NS_ERROR_FAILURE);
aEvent->mReply.mContentsRoot = mRootContent.get();
return NS_OK;
}
static void ConvertToNativeNewlines(nsAFlatString& aString)
{
#if defined(XP_MACOSX)
aString.ReplaceSubstring(NS_LITERAL_STRING("\n"), NS_LITERAL_STRING("\r"));
#elif defined(XP_WIN)
aString.ReplaceSubstring(NS_LITERAL_STRING("\n"), NS_LITERAL_STRING("\r\n"));
#endif
}
static void ConvertToXPNewlines(nsAFlatString& aString)
{
#if defined(XP_MACOSX)
aString.ReplaceSubstring(NS_LITERAL_STRING("\r"), NS_LITERAL_STRING("\n"));
#elif defined(XP_WIN)
aString.ReplaceSubstring(NS_LITERAL_STRING("\r\n"), NS_LITERAL_STRING("\n"));
#endif
}
static void AppendString(nsAString& aString, nsIContent* aContent)
{
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
"aContent is not a text node!");
const nsTextFragment* text = aContent->GetText();
if (!text)
return;
text->AppendTo(aString);
}
static void AppendSubString(nsAString& aString, nsIContent* aContent,
PRUint32 aXPOffset, PRUint32 aXPLength)
{
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
"aContent is not a text node!");
const nsTextFragment* text = aContent->GetText();
if (!text)
return;
text->AppendTo(aString, PRInt32(aXPOffset), PRInt32(aXPLength));
}
static PRUint32 GetNativeTextLength(nsIContent* aContent)
{
nsAutoString str;
if (aContent->IsNodeOfType(nsINode::eTEXT))
AppendString(str, aContent);
else if (aContent->IsNodeOfType(nsINode::eHTML) &&
aContent->Tag() == nsGkAtoms::br)
str.Assign(PRUnichar('\n'));
ConvertToNativeNewlines(str);
return str.Length();
}
static PRUint32 ConvertToXPOffset(nsIContent* aContent, PRUint32 aNativeOffset)
{
nsAutoString str;
AppendString(str, aContent);
ConvertToNativeNewlines(str);
NS_ASSERTION(aNativeOffset <= str.Length(),
"aOffsetForNativeLF is too large!");
str.Truncate(aNativeOffset);
ConvertToXPNewlines(str);
return str.Length();
}
nsresult
nsQueryContentEventHandler::GenerateFlatTextContent(nsIRange* aRange,
nsAFlatString& aString)
{
nsCOMPtr<nsIContentIterator> iter;
nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(iter, "NS_NewContentIterator succeeded, but the result is null");
nsCOMPtr<nsIDOMRange> domRange(do_QueryInterface(aRange));
NS_ASSERTION(domRange, "aRange doesn't have nsIDOMRange!");
iter->Init(domRange);
NS_ASSERTION(aString.IsEmpty(), "aString must be empty string");
nsINode* startNode = aRange->GetStartParent();
NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
nsINode* endNode = aRange->GetEndParent();
NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE);
if (startNode == endNode && startNode->IsNodeOfType(nsINode::eTEXT)) {
nsIContent* content = static_cast<nsIContent*>(startNode);
AppendSubString(aString, content, aRange->StartOffset(),
aRange->EndOffset() - aRange->StartOffset());
ConvertToNativeNewlines(aString);
return NS_OK;
}
nsAutoString tmpStr;
for (; !iter->IsDone(); iter->Next()) {
nsIContent* content = iter->GetCurrentNode();
if (!content)
continue;
if (content->IsNodeOfType(nsINode::eTEXT)) {
if (content == startNode)
AppendSubString(aString, content, aRange->StartOffset(),
content->TextLength() - aRange->StartOffset());
else if (content == endNode)
AppendSubString(aString, content, 0, aRange->EndOffset());
else
AppendString(aString, content);
} else if (content->IsNodeOfType(nsINode::eHTML) &&
content->Tag() == nsGkAtoms::br)
aString.Append(PRUnichar('\n'));
}
ConvertToNativeNewlines(aString);
return NS_OK;
}
nsresult
nsQueryContentEventHandler::ExpandToClusterBoundary(nsIContent* aContent,
PRBool aForward,
PRUint32* aXPOffset)
{
NS_ASSERTION(*aXPOffset >= 0 && *aXPOffset <= aContent->TextLength(),
"offset is out of range.");
// XXX This method assumes that the frame boundaries must be cluster
// boundaries. It's false, but no problem now, maybe.
if (!aContent->IsNodeOfType(nsINode::eTEXT) ||
*aXPOffset == 0 || *aXPOffset == aContent->TextLength())
return NS_OK;
nsCOMPtr<nsFrameSelection> fs = mPresShell->FrameSelection();
PRInt32 offsetInFrame;
nsFrameSelection::HINT hint =
aForward ? nsFrameSelection::HINTLEFT : nsFrameSelection::HINTRIGHT;
nsIFrame* frame = fs->GetFrameForNodeOffset(aContent, PRInt32(*aXPOffset),
hint, &offsetInFrame);
if (!frame) {
// This content doesn't have any frames, we only can check surrogate pair...
const nsTextFragment* text = aContent->GetText();
NS_ENSURE_TRUE(text, NS_ERROR_FAILURE);
if (NS_IS_LOW_SURROGATE(text->CharAt(*aXPOffset)) &&
NS_IS_HIGH_SURROGATE(text->CharAt(*aXPOffset - 1)))
*aXPOffset += aForward ? 1 : -1;
return NS_OK;
}
PRInt32 startOffset, endOffset;
nsresult rv = frame->GetOffsets(startOffset, endOffset);
NS_ENSURE_SUCCESS(rv, rv);
if (*aXPOffset == PRUint32(startOffset) || *aXPOffset == PRUint32(endOffset))
return NS_OK;
if (frame->GetType() != nsGkAtoms::textFrame)
return NS_ERROR_FAILURE;
nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
PRInt32 newOffsetInFrame = offsetInFrame;
newOffsetInFrame += aForward ? -1 : 1;
textFrame->PeekOffsetCharacter(aForward, &newOffsetInFrame);
*aXPOffset = startOffset + newOffsetInFrame;
return NS_OK;
}
nsresult
nsQueryContentEventHandler::SetRangeFromFlatTextOffset(
nsIRange* aRange,
PRUint32 aNativeOffset,
PRUint32 aNativeLength,
PRBool aExpandToClusterBoundaries)
{
nsCOMPtr<nsIContentIterator> iter;
nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(iter, "NS_NewContentIterator succeeded, but the result is null");
rv = iter->Init(mRootContent);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMRange> domRange(do_QueryInterface(aRange));
NS_ASSERTION(domRange, "aRange doesn't have nsIDOMRange!");
PRUint32 nativeOffset = 0;
PRUint32 nativeEndOffset = aNativeOffset + aNativeLength;
nsIContent* content = nsnull;
for (; !iter->IsDone(); iter->Next()) {
content = iter->GetCurrentNode();
if (!content)
continue;
PRUint32 nativeTextLength;
nativeTextLength = GetNativeTextLength(content);
if (nativeTextLength == 0)
continue;
if (nativeOffset <= aNativeOffset &&
aNativeOffset < nativeOffset + nativeTextLength) {
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(content));
NS_ASSERTION(domNode, "aContent doesn't have nsIDOMNode!");
PRUint32 xpOffset =
content->IsNodeOfType(nsINode::eTEXT) ?
ConvertToXPOffset(content, aNativeOffset - nativeOffset) : 0;
if (aExpandToClusterBoundaries) {
rv = ExpandToClusterBoundary(content, PR_FALSE, &xpOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = domRange->SetStart(domNode, PRInt32(xpOffset));
NS_ENSURE_SUCCESS(rv, rv);
if (aNativeLength == 0) {
// Ensure that the end offset and the start offset are same.
rv = domRange->SetEnd(domNode, PRInt32(xpOffset));
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
}
if (nativeEndOffset <= nativeOffset + nativeTextLength) {
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(content));
NS_ASSERTION(domNode, "aContent doesn't have nsIDOMNode!");
PRUint32 xpOffset;
if (content->IsNodeOfType(nsINode::eTEXT)) {
xpOffset = ConvertToXPOffset(content, nativeEndOffset - nativeOffset);
if (aExpandToClusterBoundaries) {
rv = ExpandToClusterBoundary(content, PR_TRUE, &xpOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
} else {
// Use first position of next node, because the end node is ignored
// by ContentIterator when the offset is zero.
xpOffset = 0;
iter->Next();
if (iter->IsDone())
break;
domNode = do_QueryInterface(iter->GetCurrentNode());
}
rv = domRange->SetEnd(domNode, PRInt32(xpOffset));
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nativeOffset += nativeTextLength;
}
if (nativeOffset < aNativeOffset)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mRootContent));
NS_ASSERTION(domNode, "lastContent doesn't have nsIDOMNode!");
if (!content) {
rv = domRange->SetStart(domNode, 0);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = domRange->SetEnd(domNode, PRInt32(mRootContent->GetChildCount()));
NS_ASSERTION(NS_SUCCEEDED(rv), "nsIDOMRange::SetEnd failed");
return rv;
}
nsresult
nsQueryContentEventHandler::OnQuerySelectedText(nsQueryContentEvent* aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
NS_ASSERTION(aEvent->mReply.mString.IsEmpty(),
"The reply string must be empty");
rv = GetFlatTextOffsetOfRange(mFirstSelectedRange, &aEvent->mReply.mOffset);
NS_ENSURE_SUCCESS(rv, rv);
PRBool isCollapsed;
rv = mSelection->GetIsCollapsed(&isCollapsed);
NS_ENSURE_SUCCESS(rv, rv);
if (!isCollapsed) {
nsCOMPtr<nsIDOMRange> domRange;
rv = mSelection->GetRangeAt(0, getter_AddRefs(domRange));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(domRange, "GetRangeAt succeeded, but the result is null");
nsCOMPtr<nsIRange> range(do_QueryInterface(domRange));
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
rv = GenerateFlatTextContent(range, aEvent->mReply.mString);
NS_ENSURE_SUCCESS(rv, rv);
}
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
nsresult
nsQueryContentEventHandler::OnQueryTextContent(nsQueryContentEvent* aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
NS_ASSERTION(aEvent->mReply.mString.IsEmpty(),
"The reply string must be empty");
nsCOMPtr<nsIRange> range = new nsRange();
NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset,
aEvent->mInput.mLength, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = GenerateFlatTextContent(range, aEvent->mReply.mString);
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
nsresult
nsQueryContentEventHandler::QueryRectFor(nsQueryContentEvent* aEvent,
nsIRange* aRange,
nsICaret* aCaret)
{
PRInt32 offsetInFrame;
nsIFrame* frame;
nsresult rv = GetStartFrameAndOffset(aRange, &frame, &offsetInFrame);
NS_ENSURE_SUCCESS(rv, rv);
nsPoint posInFrame;
rv = frame->GetPointFromOffset(aRange->StartOffset(), &posInFrame);
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mReply.mRect.y = posInFrame.y;
aEvent->mReply.mRect.height = frame->GetSize().height;
if (aEvent->message == NS_QUERY_CHARACTER_RECT) {
nsPoint nextPos;
rv = frame->GetPointFromOffset(aRange->EndOffset(), &nextPos);
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mReply.mRect.x = PR_MIN(posInFrame.x, nextPos.x);
aEvent->mReply.mRect.width = PR_ABS(posInFrame.x - nextPos.x);
} else {
aEvent->mReply.mRect.x = posInFrame.x;
aEvent->mReply.mRect.width = aCaret->GetCaretRect().width;
}
// The coordinates are app units here, they will be converted to system
// coordinates by view manager.
rv = ConvertToRootViewRelativeOffset(frame, aEvent->mReply.mRect);
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
nsresult
nsQueryContentEventHandler::OnQueryCharacterRect(nsQueryContentEvent* aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIRange> range = new nsRange();
NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 1, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
if (range->Collapsed()) {
// There is no character at the offset.
return NS_OK;
}
return QueryRectFor(aEvent, range, nsnull);
}
nsresult
nsQueryContentEventHandler::OnQueryCaretRect(nsQueryContentEvent* aEvent)
{
nsresult rv = Init(aEvent);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsICaret> caret;
rv = mPresShell->GetCaret(getter_AddRefs(caret));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(caret, "GetCaret succeeded, but the result is null");
// When the selection is collapsed and the queried offset is current caret
// position, we should return the "real" caret rect.
PRBool selectionIsCollapsed;
rv = mSelection->GetIsCollapsed(&selectionIsCollapsed);
NS_ENSURE_SUCCESS(rv, rv);
if (selectionIsCollapsed) {
PRUint32 offset;
rv = GetFlatTextOffsetOfRange(mFirstSelectedRange, &offset);
NS_ENSURE_SUCCESS(rv, rv);
if (offset == aEvent->mInput.mOffset) {
PRBool isCollapsed;
rv = caret->GetCaretCoordinates(nsICaret::eTopLevelWindowCoordinates,
mSelection, &aEvent->mReply.mRect,
&isCollapsed, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mSucceeded = PR_TRUE;
return NS_OK;
}
}
// Otherwise, we should set the guessed caret rect.
nsCOMPtr<nsIRange> range = new nsRange();
NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 0, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
return QueryRectFor(aEvent, range, caret);
}
nsresult
nsQueryContentEventHandler::GetFlatTextOffsetOfRange(nsIRange* aRange,
PRUint32* aNativeOffset)
{
NS_ASSERTION(aNativeOffset, "param is invalid");
nsCOMPtr<nsIRange> prev = new nsRange();
NS_ENSURE_TRUE(prev, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIDOMRange> domPrev(do_QueryInterface(prev));
NS_ASSERTION(domPrev, "nsRange doesn't have nsIDOMRange??");
nsCOMPtr<nsIDOMNode> rootDOMNode(do_QueryInterface(mRootContent));
domPrev->SetStart(rootDOMNode, 0);
nsINode* startNode = aRange->GetStartParent();
NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
PRInt32 startOffset = aRange->StartOffset();
nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(startNode));
NS_ASSERTION(startDOMNode, "startNode doesn't have nsIDOMNode");
domPrev->SetEnd(startDOMNode, startOffset);
nsAutoString prevStr;
nsresult rv = GenerateFlatTextContent(prev, prevStr);
NS_ENSURE_SUCCESS(rv, rv);
*aNativeOffset = prevStr.Length();
return NS_OK;
}
nsresult
nsQueryContentEventHandler::GetStartFrameAndOffset(nsIRange* aRange,
nsIFrame** aFrame,
PRInt32* aOffsetInFrame)
{
NS_ASSERTION(aRange && aFrame && aOffsetInFrame, "params are invalid");
nsIContent* content = nsnull;
nsINode* node = aRange->GetStartParent();
if (node && node->IsNodeOfType(nsINode::eCONTENT))
content = static_cast<nsIContent*>(node);
NS_ASSERTION(content, "the start node doesn't have nsIContent!");
nsCOMPtr<nsFrameSelection> fs = mPresShell->FrameSelection();
*aFrame = fs->GetFrameForNodeOffset(content, aRange->StartOffset(),
fs->GetHint(), aOffsetInFrame);
NS_ENSURE_TRUE((*aFrame), NS_ERROR_FAILURE);
NS_ASSERTION((*aFrame)->GetType() == nsGkAtoms::textFrame,
"The frame is not textframe");
return NS_OK;
}
nsresult
nsQueryContentEventHandler::ConvertToRootViewRelativeOffset(nsIFrame* aFrame,
nsRect& aRect)
{
NS_ASSERTION(aFrame, "aFrame must not be null");
nsIView* view = nsnull;
nsPoint posInView;
aFrame->GetOffsetFromView(posInView, &view);
if (!view)
return NS_ERROR_FAILURE;
aRect += posInView + view->GetOffsetTo(nsnull);
return NS_OK;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,532 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* JS math package.
*/
#include "jsstddef.h"
#include "jslibmath.h"
#include <stdlib.h>
#include "jstypes.h"
#include "jslong.h"
#include "prmjtime.h"
#include "jsapi.h"
#include "jsatom.h"
#include "jscntxt.h"
#include "jsconfig.h"
#include "jslock.h"
#include "jsmath.h"
#include "jsnum.h"
#include "jsobj.h"
#ifndef M_E
#define M_E 2.7182818284590452354
#endif
#ifndef M_LOG2E
#define M_LOG2E 1.4426950408889634074
#endif
#ifndef M_LOG10E
#define M_LOG10E 0.43429448190325182765
#endif
#ifndef M_LN2
#define M_LN2 0.69314718055994530942
#endif
#ifndef M_LN10
#define M_LN10 2.30258509299404568402
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_SQRT2
#define M_SQRT2 1.41421356237309504880
#endif
#ifndef M_SQRT1_2
#define M_SQRT1_2 0.70710678118654752440
#endif
static JSConstDoubleSpec math_constants[] = {
{M_E, "E", 0, {0,0,0}},
{M_LOG2E, "LOG2E", 0, {0,0,0}},
{M_LOG10E, "LOG10E", 0, {0,0,0}},
{M_LN2, "LN2", 0, {0,0,0}},
{M_LN10, "LN10", 0, {0,0,0}},
{M_PI, "PI", 0, {0,0,0}},
{M_SQRT2, "SQRT2", 0, {0,0,0}},
{M_SQRT1_2, "SQRT1_2", 0, {0,0,0}},
{0,0,0,{0,0,0}}
};
JSClass js_MathClass = {
js_Math_str,
JSCLASS_HAS_CACHED_PROTO(JSProto_Math),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
static JSBool
math_abs(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
z = fd_fabs(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_acos(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
#if !JS_USE_FDLIBM_MATH && defined(SOLARIS) && defined(__GNUC__)
if (x < -1 || 1 < x) {
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
return JS_TRUE;
}
#endif
z = fd_acos(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_asin(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
#if !JS_USE_FDLIBM_MATH && defined(SOLARIS) && defined(__GNUC__)
if (x < -1 || 1 < x) {
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
return JS_TRUE;
}
#endif
z = fd_asin(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_atan(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
z = fd_atan(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_atan2(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, y, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
y = js_ValueToNumber(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
return JS_FALSE;
#if !JS_USE_FDLIBM_MATH && defined(_MSC_VER)
/*
* MSVC's atan2 does not yield the result demanded by ECMA when both x
* and y are infinite.
* - The result is a multiple of pi/4.
* - The sign of x determines the sign of the result.
* - The sign of y determines the multiplicator, 1 or 3.
*/
if (JSDOUBLE_IS_INFINITE(x) && JSDOUBLE_IS_INFINITE(y)) {
z = fd_copysign(M_PI / 4, x);
if (y < 0)
z *= 3;
return js_NewDoubleInRootedValue(cx, z, vp);
}
#endif
#if !JS_USE_FDLIBM_MATH && defined(SOLARIS) && defined(__GNUC__)
if (x == 0) {
if (JSDOUBLE_IS_NEGZERO(y)) {
z = fd_copysign(M_PI, x);
return js_NewDoubleInRootedValue(cx, z, vp);
}
if (y == 0) {
z = x;
return js_NewDoubleInRootedValue(cx, z, vp);
}
}
#endif
z = fd_atan2(x, y);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_ceil(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
z = fd_ceil(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_cos(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
z = fd_cos(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_exp(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
#ifdef _WIN32
if (!JSDOUBLE_IS_NaN(x)) {
if (x == *cx->runtime->jsPositiveInfinity) {
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
return JS_TRUE;
}
if (x == *cx->runtime->jsNegativeInfinity) {
*vp = JSVAL_ZERO;
return JS_TRUE;
}
}
#endif
z = fd_exp(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_floor(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
z = fd_floor(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_log(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
#if !JS_USE_FDLIBM_MATH && defined(SOLARIS) && defined(__GNUC__)
if (x < 0) {
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
return JS_TRUE;
}
#endif
z = fd_log(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_max(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z = *cx->runtime->jsNegativeInfinity;
jsval *argv;
uintN i;
if (argc == 0) {
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
return JS_TRUE;
}
argv = vp + 2;
for (i = 0; i < argc; i++) {
x = js_ValueToNumber(cx, &argv[i]);
if (JSVAL_IS_NULL(argv[i]))
return JS_FALSE;
if (JSDOUBLE_IS_NaN(x)) {
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
return JS_TRUE;
}
if (x == 0 && x == z && fd_copysign(1.0, z) == -1)
z = x;
else
z = (x > z) ? x : z;
}
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_min(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z = *cx->runtime->jsPositiveInfinity;
jsval *argv;
uintN i;
if (argc == 0) {
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
return JS_TRUE;
}
argv = vp + 2;
for (i = 0; i < argc; i++) {
x = js_ValueToNumber(cx, &argv[i]);
if (JSVAL_IS_NULL(argv[i]))
return JS_FALSE;
if (JSDOUBLE_IS_NaN(x)) {
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
return JS_TRUE;
}
if (x == 0 && x == z && fd_copysign(1.0,x) == -1)
z = x;
else
z = (x < z) ? x : z;
}
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_pow(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, y, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
y = js_ValueToNumber(cx, &vp[3]);
if (JSVAL_IS_NULL(vp[3]))
return JS_FALSE;
#if !JS_USE_FDLIBM_MATH
/*
* Because C99 and ECMA specify different behavior for pow(),
* we need to wrap the libm call to make it ECMA compliant.
*/
if (!JSDOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) {
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
return JS_TRUE;
}
/* pow(x, +-0) is always 1, even for x = NaN. */
if (y == 0) {
*vp = JSVAL_ONE;
return JS_TRUE;
}
#endif
z = fd_pow(x, y);
return js_NewNumberInRootedValue(cx, z, vp);
}
static const int64 RNG_MULTIPLIER = 0x5DEECE66DLL;
static const int64 RNG_ADDEND = 0xBLL;
static const int64 RNG_MASK = (1LL << 48) - 1;
static const jsdouble RNG_DSCALE = (1LL << 53);
/*
* Math.random() support, lifted from java.util.Random.java.
*/
static inline void
random_setSeed(JSContext *cx, int64 seed)
{
cx->rngSeed = (seed ^ RNG_MULTIPLIER) & RNG_MASK;
}
void
js_InitRandom(JSContext *cx)
{
/*
* Set the seed from current time. Since we have a RNG per context and we often bring
* up several contexts at the same time, we xor in some additional values, namely
* the context and its successor. We don't just use the context because it might be
* possible to reverse engineer the context pointer if one guesses the time right.
*/
random_setSeed(cx,
(PRMJ_Now() / 1000) ^
(int64)(cx) ^
(int64)(cx->links.next));
}
static inline uint64
random_next(JSContext *cx, int bits)
{
uint64 nextseed = cx->rngSeed * RNG_MULTIPLIER;
nextseed += RNG_ADDEND;
nextseed &= RNG_MASK;
cx->rngSeed = nextseed;
return nextseed >> (48 - bits);
}
static inline jsdouble
random_nextDouble(JSContext *cx)
{
return (jsdouble)((random_next(cx, 26) << 27) + random_next(cx, 27)) / RNG_DSCALE;
}
static JSBool
math_random(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble z = random_nextDouble(cx);
return js_NewNumberInRootedValue(cx, z, vp);
}
#if defined _WIN32 && !defined WINCE && _MSC_VER < 1400
/* Try to work around apparent _copysign bustage in VC6 and VC7. */
double
js_copysign(double x, double y)
{
jsdpun xu, yu;
xu.d = x;
yu.d = y;
xu.s.hi &= ~JSDOUBLE_HI32_SIGNBIT;
xu.s.hi |= yu.s.hi & JSDOUBLE_HI32_SIGNBIT;
return xu.d;
}
#endif
static JSBool
math_round(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
z = fd_copysign(fd_floor(x + 0.5), x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_sin(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
z = fd_sin(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_sqrt(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
z = fd_sqrt(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
static JSBool
math_tan(JSContext *cx, uintN argc, jsval *vp)
{
jsdouble x, z;
x = js_ValueToNumber(cx, &vp[2]);
if (JSVAL_IS_NULL(vp[2]))
return JS_FALSE;
z = fd_tan(x);
return js_NewNumberInRootedValue(cx, z, vp);
}
#if JS_HAS_TOSOURCE
static JSBool
math_toSource(JSContext *cx, uintN argc, jsval *vp)
{
*vp = ATOM_KEY(CLASS_ATOM(cx, Math));
return JS_TRUE;
}
#endif
static JSFunctionSpec math_static_methods[] = {
#if JS_HAS_TOSOURCE
JS_FN(js_toSource_str, math_toSource, 0, 0, 0),
#endif
JS_FN("abs", math_abs, 1, 1, 0),
JS_FN("acos", math_acos, 1, 1, 0),
JS_FN("asin", math_asin, 1, 1, 0),
JS_FN("atan", math_atan, 1, 1, 0),
JS_FN("atan2", math_atan2, 2, 2, 0),
JS_FN("ceil", math_ceil, 1, 1, 0),
JS_FN("cos", math_cos, 1, 1, 0),
JS_FN("exp", math_exp, 1, 1, 0),
JS_FN("floor", math_floor, 1, 1, 0),
JS_FN("log", math_log, 1, 1, 0),
JS_FN("max", math_max, 0, 2, 0),
JS_FN("min", math_min, 0, 2, 0),
JS_FN("pow", math_pow, 2, 2, 0),
JS_FN("random", math_random, 0, 0, 0),
JS_FN("round", math_round, 1, 1, 0),
JS_FN("sin", math_sin, 1, 1, 0),
JS_FN("sqrt", math_sqrt, 1, 1, 0),
JS_FN("tan", math_tan, 1, 1, 0),
JS_FS_END
};
JSObject *
js_InitMathClass(JSContext *cx, JSObject *obj)
{
JSObject *Math;
Math = JS_DefineObject(cx, obj, js_Math_str, &js_MathClass, NULL, 0);
if (!Math)
return NULL;
if (!JS_DefineFunctions(cx, Math, math_static_methods))
return NULL;
if (!JS_DefineConstDoubles(cx, Math, math_constants))
return NULL;
return Math;
}

View File

@@ -1,60 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998-1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* -*- Mode: C; tab-width: 8 -*-
* Copyright (C) 1998-1999 Netscape Communications Corporation, All Rights Reserved.
*/
#ifndef jsmath_h___
#define jsmath_h___
/*
* JS math functions.
*/
JS_BEGIN_EXTERN_C
extern JSClass js_MathClass;
extern JSObject *
js_InitMathClass(JSContext *cx, JSObject *obj);
extern void
js_InitRandom(JSContext *cx);
JS_END_EXTERN_C
#endif /* jsmath_h___ */

File diff suppressed because it is too large Load Diff

48
mozilla/mozilla.kdevprj Normal file
View File

@@ -0,0 +1,48 @@
# KDE Config File
[mozilla.lsm]
install_location=
dist=true
install=false
type=DATA
[Config for BinMakefileAm]
ldflags=
cxxflags=-O0 -g3 -Wall
bin_program=mozilla
[po/Makefile.am]
sub_dirs=
type=po
[LFV Groups]
Dialogs=*.kdevdlg,
Others=*,
Translations=*.po,
groups=Headers,Sources,Dialogs,Translations,Others,
Sources=*.cpp,*.c,*.cc,*.C,*.cxx,*.ec,*.ecpp,*.lxx,*.l++,*.ll,*.l,
Headers=*.h,*.hh,*.hxx,*.hpp,*.H,
[mozilla.kdevprj]
install_location=
dist=true
install=false
type=DATA
[mozilla/docs/en/Makefile.am]
sub_dirs=
type=normal
[mozilla/Makefile.am]
sub_dirs=
type=prog_main
[General]
makefiles=Makefile.am,mozilla/Makefile.am,mozilla/docs/Makefile.am,mozilla/docs/en/Makefile.am,po/Makefile.am,
version_control=CVS
author=Heikki Toivonen
project_type=normal_empty
sub_dir=mozilla/
version=0.1
project_name=Mozilla
email=heikki@netscape.com
kdevprj_version=1.2
[Makefile.am]
files=mozilla.kdevprj,mozilla.lsm,
sub_dirs=mozilla,
type=normal
[mozilla/docs/Makefile.am]
sub_dirs=
type=normal

14
mozilla/mozilla.lsm Normal file
View File

@@ -0,0 +1,14 @@
Begin3
Title: Mozilla
Version: 0.1
Entered-date:
Description:
Keywords:
Author: Heikki Toivonen <heikki@netscape.com>
Maintained-by: Heikki Toivonen <heikki@netscape.com>
Primary-site:
Home-page: http://
Original-site:
Platforms: Linux and other Unices
Copying-policy: GNU Public License
End

View File

@@ -0,0 +1,20 @@
/*
* 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 Communicator client 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):
*/

View File

@@ -0,0 +1,20 @@
/*
* 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 Communicator client 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):
*/

File diff suppressed because it is too large Load Diff