зеркало из https://github.com/mozilla/gecko-dev.git
696 строки
18 KiB
C
696 строки
18 KiB
C
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||
|
*
|
||
|
* The contents of this file are subject to the Netscape Public License
|
||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||
|
* http://www.mozilla.org/NPL/
|
||
|
*
|
||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||
|
* for the specific language governing rights and limitations under the
|
||
|
* NPL.
|
||
|
*
|
||
|
* The Initial Developer of this code under the NPL is Netscape
|
||
|
* Communications Corporation. Portions created by Netscape are
|
||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||
|
* Reserved.
|
||
|
*/
|
||
|
/*
|
||
|
* JS reflection of the HREF and NAME Anchors in the current document.
|
||
|
*
|
||
|
* Brendan Eich, 9/8/95
|
||
|
*/
|
||
|
#include "lm.h"
|
||
|
#include "pa_tags.h"
|
||
|
#include "layout.h" /* XXX for lo_NameList only */
|
||
|
|
||
|
enum anchor_array_slot {
|
||
|
ANCHOR_ARRAY_LENGTH = -1
|
||
|
};
|
||
|
|
||
|
static JSPropertySpec anchor_array_props[] = {
|
||
|
{lm_length_str, ANCHOR_ARRAY_LENGTH,
|
||
|
JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT},
|
||
|
{0}
|
||
|
};
|
||
|
|
||
|
extern JSClass lm_link_array_class;
|
||
|
|
||
|
PR_STATIC_CALLBACK(JSBool)
|
||
|
link_array_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||
|
{
|
||
|
JSObjectArray *array;
|
||
|
MochaDecoder *decoder;
|
||
|
MWContext *context;
|
||
|
jsint count, slot;
|
||
|
LO_AnchorData *anchor_data;
|
||
|
int32 active_layer_id;
|
||
|
|
||
|
if (!JSVAL_IS_INT(id))
|
||
|
return JS_TRUE;
|
||
|
|
||
|
slot = JSVAL_TO_INT(id);
|
||
|
|
||
|
array = JS_GetInstancePrivate(cx, obj, &lm_link_array_class, NULL);
|
||
|
if (!array)
|
||
|
return JS_TRUE;
|
||
|
decoder = array->decoder;
|
||
|
context = decoder->window_context;
|
||
|
if (!context) return JS_TRUE;
|
||
|
|
||
|
LO_LockLayout();
|
||
|
switch (slot) {
|
||
|
case ANCHOR_ARRAY_LENGTH:
|
||
|
active_layer_id = LM_GetActiveLayer(context);
|
||
|
LM_SetActiveLayer(context, array->layer_id);
|
||
|
count = LO_EnumerateLinks(context, array->layer_id);
|
||
|
LM_SetActiveLayer(context, active_layer_id);
|
||
|
if (count > array->length)
|
||
|
array->length = count;
|
||
|
*vp = INT_TO_JSVAL(count);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
if (slot < 0) {
|
||
|
/* Don't mess with user-defined or method properties. */
|
||
|
LO_UnlockLayout();
|
||
|
return JS_TRUE;
|
||
|
}
|
||
|
if (slot >= array->length)
|
||
|
array->length = slot + 1;
|
||
|
anchor_data = LO_GetLinkByIndex(context, array->layer_id, (uint)slot);
|
||
|
if (anchor_data) {
|
||
|
*vp = OBJECT_TO_JSVAL(LM_ReflectLink(context, anchor_data, NULL,
|
||
|
array->layer_id, (uint)slot));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
LO_UnlockLayout();
|
||
|
return JS_TRUE;
|
||
|
}
|
||
|
|
||
|
PR_STATIC_CALLBACK(void)
|
||
|
anchor_array_finalize(JSContext *cx, JSObject *obj)
|
||
|
{
|
||
|
JSObjectArray *array;
|
||
|
|
||
|
array = JS_GetPrivate(cx, obj);
|
||
|
if (!array)
|
||
|
return;
|
||
|
DROP_BACK_COUNT(array->decoder);
|
||
|
JS_free(cx, array);
|
||
|
}
|
||
|
|
||
|
JSClass lm_link_array_class = {
|
||
|
"LinkArray", JSCLASS_HAS_PRIVATE,
|
||
|
JS_PropertyStub, JS_PropertyStub,
|
||
|
link_array_getProperty, link_array_getProperty, JS_EnumerateStub,
|
||
|
JS_ResolveStub, JS_ConvertStub, anchor_array_finalize
|
||
|
};
|
||
|
|
||
|
PR_STATIC_CALLBACK(JSBool)
|
||
|
LinkArray(JSContext *cx, JSObject *obj,
|
||
|
uint argc, jsval *argv, jsval *rval)
|
||
|
{
|
||
|
return JS_TRUE;
|
||
|
}
|
||
|
|
||
|
extern JSClass lm_anchor_array_class;
|
||
|
|
||
|
PR_STATIC_CALLBACK(JSBool)
|
||
|
anchor_array_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||
|
{
|
||
|
JSObjectArray *array;
|
||
|
MochaDecoder *decoder;
|
||
|
MWContext *context;
|
||
|
jsint count, slot;
|
||
|
lo_NameList *name_rec;
|
||
|
int32 active_layer_id;
|
||
|
|
||
|
if (!JSVAL_IS_INT(id))
|
||
|
return JS_TRUE;
|
||
|
|
||
|
slot = JSVAL_TO_INT(id);
|
||
|
|
||
|
array = JS_GetInstancePrivate(cx, obj, &lm_anchor_array_class, NULL);
|
||
|
if (!array)
|
||
|
return JS_TRUE;
|
||
|
decoder = array->decoder;
|
||
|
context = decoder->window_context;
|
||
|
if (!context) return JS_TRUE;
|
||
|
LO_LockLayout();
|
||
|
switch (slot) {
|
||
|
case ANCHOR_ARRAY_LENGTH:
|
||
|
active_layer_id = LM_GetActiveLayer(context);
|
||
|
LM_SetActiveLayer(context, array->layer_id);
|
||
|
count = LO_EnumerateNamedAnchors(context, array->layer_id);
|
||
|
LM_SetActiveLayer(context, active_layer_id);
|
||
|
if (count > array->length)
|
||
|
array->length = count;
|
||
|
*vp = INT_TO_JSVAL(count);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
if (slot >= array->length)
|
||
|
array->length = slot + 1;
|
||
|
name_rec = LO_GetNamedAnchorByIndex(context, array->layer_id,
|
||
|
(uint)slot);
|
||
|
if (name_rec) {
|
||
|
*vp = OBJECT_TO_JSVAL(LM_ReflectNamedAnchor(context, name_rec,
|
||
|
NULL, array->layer_id,
|
||
|
(uint)slot));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
LO_UnlockLayout();
|
||
|
return JS_TRUE;
|
||
|
}
|
||
|
|
||
|
JSClass lm_anchor_array_class = {
|
||
|
"AnchorArray", JSCLASS_HAS_PRIVATE,
|
||
|
JS_PropertyStub, JS_PropertyStub,
|
||
|
anchor_array_getProperty, anchor_array_getProperty, JS_EnumerateStub,
|
||
|
JS_ResolveStub, JS_ConvertStub, anchor_array_finalize
|
||
|
};
|
||
|
|
||
|
PR_STATIC_CALLBACK(JSBool)
|
||
|
AnchorArray(JSContext *cx, JSObject *obj,
|
||
|
uint argc, jsval *argv, jsval *rval)
|
||
|
{
|
||
|
return JS_TRUE;
|
||
|
}
|
||
|
|
||
|
static JSObject *
|
||
|
reflect_anchor_array(MochaDecoder *decoder, JSClass *clasp,
|
||
|
JSNative constructor, JSObject *document)
|
||
|
{
|
||
|
JSContext *cx;
|
||
|
JSObject *obj, *prototype;
|
||
|
JSObjectArray *array;
|
||
|
JSDocument *doc;
|
||
|
|
||
|
cx = decoder->js_context;
|
||
|
doc = JS_GetPrivate(cx, document);
|
||
|
if (!doc)
|
||
|
return NULL;
|
||
|
|
||
|
prototype = JS_InitClass(cx, decoder->window_object, NULL,
|
||
|
clasp, constructor, 0,
|
||
|
anchor_array_props, NULL, NULL, NULL);
|
||
|
if (!prototype)
|
||
|
return NULL;
|
||
|
array = JS_malloc(cx, sizeof *array);
|
||
|
if (!array)
|
||
|
return NULL;
|
||
|
XP_BZERO(array, sizeof *array);
|
||
|
obj = JS_NewObject(cx, clasp, prototype, document);
|
||
|
if (!obj || !JS_SetPrivate(cx, obj, array)) {
|
||
|
JS_free(cx, array);
|
||
|
return NULL;
|
||
|
}
|
||
|
array->decoder = HOLD_BACK_COUNT(decoder);
|
||
|
array->layer_id = doc->layer_id;
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
JSObject *
|
||
|
lm_GetLinkArray(MochaDecoder *decoder, JSObject *document)
|
||
|
{
|
||
|
JSObject *obj;
|
||
|
JSDocument *doc;
|
||
|
|
||
|
doc = JS_GetPrivate(decoder->js_context, document);
|
||
|
if (!doc)
|
||
|
return NULL;
|
||
|
|
||
|
obj = doc->links;
|
||
|
if (obj)
|
||
|
return obj;
|
||
|
obj = reflect_anchor_array(decoder, &lm_link_array_class, LinkArray,
|
||
|
document);
|
||
|
doc->links = obj;
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
JSObject *
|
||
|
lm_GetNameArray(MochaDecoder *decoder, JSObject *document)
|
||
|
{
|
||
|
JSObject *obj;
|
||
|
JSDocument *doc;
|
||
|
|
||
|
doc = JS_GetPrivate(decoder->js_context, document);
|
||
|
if (!doc)
|
||
|
return NULL;
|
||
|
|
||
|
obj = doc->anchors;
|
||
|
if (obj)
|
||
|
return obj;
|
||
|
obj = reflect_anchor_array(decoder, &lm_anchor_array_class, AnchorArray,
|
||
|
document);
|
||
|
doc->anchors = obj;
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
JSObject *
|
||
|
LM_ReflectLink(MWContext *context, LO_AnchorData *anchor_data, PA_Tag * tag,
|
||
|
int32 layer_id, uint index)
|
||
|
{
|
||
|
JSObject *obj, *array_obj, *document;
|
||
|
MochaDecoder *decoder;
|
||
|
JSContext *cx;
|
||
|
JSURL *url;
|
||
|
lo_TopState *top_state;
|
||
|
PRHashTable *map;
|
||
|
|
||
|
anchor_data = LO_GetLinkByIndex(context, layer_id, index);
|
||
|
if (!anchor_data)
|
||
|
return NULL;
|
||
|
|
||
|
obj = anchor_data->mocha_object;
|
||
|
if (obj)
|
||
|
return obj;
|
||
|
|
||
|
decoder = LM_GetMochaDecoder(context);
|
||
|
if (!decoder)
|
||
|
return NULL;
|
||
|
cx = decoder->js_context;
|
||
|
|
||
|
top_state = lo_GetMochaTopState(context);
|
||
|
if (top_state->resize_reload) {
|
||
|
map = lm_GetIdToObjectMap(decoder);
|
||
|
|
||
|
if (map)
|
||
|
obj = (JSObject *)PR_HashTableLookup(map,
|
||
|
LM_GET_MAPPING_KEY(LM_LINKS, layer_id, index));
|
||
|
if (obj) {
|
||
|
anchor_data->mocha_object = obj;
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return obj;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Get the document object that will hold this link */
|
||
|
document = lm_GetDocumentFromLayerId(decoder, layer_id);
|
||
|
if (!document) {
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
array_obj = lm_GetLinkArray(decoder, document);
|
||
|
if (!array_obj) {
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
url = lm_NewURL(cx, decoder, anchor_data, document);
|
||
|
|
||
|
if (!url) {
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return NULL;
|
||
|
}
|
||
|
url->index = index;
|
||
|
url->layer_id = layer_id;
|
||
|
obj = url->url_object;
|
||
|
|
||
|
/* XXX should find a name/id to pass in */
|
||
|
/* put it in the links array */
|
||
|
if (!lm_AddObjectToArray(cx, array_obj, NULL, index, obj)) {
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/* Put it in the index to object hash table */
|
||
|
map = lm_GetIdToObjectMap(decoder);
|
||
|
if (map)
|
||
|
PR_HashTableAdd(map, LM_GET_MAPPING_KEY(LM_LINKS, layer_id, index),
|
||
|
obj);
|
||
|
|
||
|
anchor_data->mocha_object = obj;
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
|
||
|
/* see if there are any event handlers we need to reflect */
|
||
|
if(tag) {
|
||
|
|
||
|
PA_Block onclick, onmouseover, onmouseout, onmousedown, onmouseup, ondblclick, id;
|
||
|
|
||
|
/* don't hold the layout lock across compiles */
|
||
|
LO_UnlockLayout();
|
||
|
|
||
|
onclick = lo_FetchParamValue(context, tag, PARAM_ONCLICK);
|
||
|
onmouseover = lo_FetchParamValue(context, tag, PARAM_ONMOUSEOVER);
|
||
|
onmouseout = lo_FetchParamValue(context, tag, PARAM_ONMOUSEOUT);
|
||
|
onmousedown = lo_FetchParamValue(context, tag, PARAM_ONMOUSEDOWN);
|
||
|
onmouseup = lo_FetchParamValue(context, tag, PARAM_ONMOUSEUP);
|
||
|
ondblclick = lo_FetchParamValue(context, tag, PARAM_ONDBLCLICK);
|
||
|
id = lo_FetchParamValue(context, tag, PARAM_ID);
|
||
|
|
||
|
if (onclick) {
|
||
|
(void) lm_CompileEventHandler(decoder, id, tag->data,
|
||
|
tag->newline_count, url->url_object,
|
||
|
PARAM_ONCLICK, onclick);
|
||
|
PA_FREE(onclick);
|
||
|
anchor_data->event_handler_present = TRUE;
|
||
|
}
|
||
|
if (onmouseover) {
|
||
|
(void) lm_CompileEventHandler(decoder, id, tag->data,
|
||
|
tag->newline_count, url->url_object,
|
||
|
PARAM_ONMOUSEOVER, onmouseover);
|
||
|
PA_FREE(onmouseover);
|
||
|
anchor_data->event_handler_present = TRUE;
|
||
|
}
|
||
|
if (onmouseout) {
|
||
|
(void) lm_CompileEventHandler(decoder, id, tag->data,
|
||
|
tag->newline_count, url->url_object,
|
||
|
PARAM_ONMOUSEOUT, onmouseout);
|
||
|
PA_FREE(onmouseout);
|
||
|
anchor_data->event_handler_present = TRUE;
|
||
|
}
|
||
|
if (onmousedown) {
|
||
|
(void) lm_CompileEventHandler(decoder, id, tag->data,
|
||
|
tag->newline_count, url->url_object,
|
||
|
PARAM_ONMOUSEDOWN, onmousedown);
|
||
|
PA_FREE(onmousedown);
|
||
|
anchor_data->event_handler_present = TRUE;
|
||
|
}
|
||
|
if (onmouseup) {
|
||
|
(void) lm_CompileEventHandler(decoder, id, tag->data,
|
||
|
tag->newline_count, url->url_object,
|
||
|
PARAM_ONMOUSEUP, onmouseup);
|
||
|
PA_FREE(onmouseup);
|
||
|
anchor_data->event_handler_present = TRUE;
|
||
|
}
|
||
|
if (ondblclick) {
|
||
|
(void) lm_CompileEventHandler(decoder, id, tag->data,
|
||
|
tag->newline_count, url->url_object,
|
||
|
PARAM_ONDBLCLICK, ondblclick);
|
||
|
PA_FREE(ondblclick);
|
||
|
anchor_data->event_handler_present = TRUE;
|
||
|
}
|
||
|
if (id)
|
||
|
PA_FREE(id);
|
||
|
LO_LockLayout();
|
||
|
}
|
||
|
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* XXX chouck - the onLocate stuff hasn't been implemented yet
|
||
|
* so just return JS_TRUE and go away
|
||
|
*/
|
||
|
JSBool
|
||
|
LM_SendOnLocate(MWContext *context, lo_NameList *name_rec)
|
||
|
{
|
||
|
JSBool ok;
|
||
|
JSObject *obj;
|
||
|
jsval result;
|
||
|
JSEvent *event;
|
||
|
|
||
|
return JS_TRUE;
|
||
|
|
||
|
obj = name_rec->mocha_object;
|
||
|
if (!obj)
|
||
|
return JS_FALSE;
|
||
|
|
||
|
event = XP_NEW_ZAP(JSEvent);
|
||
|
event->type = EVENT_LOCATE;
|
||
|
ok = lm_SendEvent(context, obj, event, &result);
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
/* Anchor property slots. */
|
||
|
enum anchor_slot {
|
||
|
ANCHOR_TEXT = -1,
|
||
|
ANCHOR_NAME = -2,
|
||
|
ANCHOR_X = -3,
|
||
|
ANCHOR_Y = -4
|
||
|
};
|
||
|
|
||
|
/* Static anchor properties. */
|
||
|
static JSPropertySpec anchor_props[] = {
|
||
|
{"text", ANCHOR_TEXT, JSPROP_ENUMERATE | JSPROP_READONLY},
|
||
|
{"name", ANCHOR_NAME, JSPROP_ENUMERATE | JSPROP_READONLY},
|
||
|
{"x", ANCHOR_X, JSPROP_ENUMERATE | JSPROP_READONLY},
|
||
|
{"y", ANCHOR_Y, JSPROP_ENUMERATE | JSPROP_READONLY},
|
||
|
{0}
|
||
|
};
|
||
|
|
||
|
/* Base anchor element type. */
|
||
|
typedef struct JSAnchor {
|
||
|
MochaDecoder *decoder;
|
||
|
int32 layer_id;
|
||
|
uint index;
|
||
|
JSString *text;
|
||
|
JSString *name;
|
||
|
} JSAnchor;
|
||
|
|
||
|
extern JSClass lm_anchor_class;
|
||
|
|
||
|
PR_STATIC_CALLBACK(JSBool)
|
||
|
anchor_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||
|
{
|
||
|
JSAnchor *named_anchor;
|
||
|
lo_NameList *name_rec;
|
||
|
jsint slot;
|
||
|
|
||
|
if (!JSVAL_IS_INT(id))
|
||
|
return JS_TRUE;
|
||
|
|
||
|
slot = JSVAL_TO_INT(id);
|
||
|
|
||
|
named_anchor = JS_GetInstancePrivate(cx, obj, &lm_anchor_class, NULL);
|
||
|
if (!named_anchor)
|
||
|
return JS_TRUE;
|
||
|
|
||
|
LO_LockLayout();
|
||
|
name_rec = LO_GetNamedAnchorByIndex(named_anchor->decoder->window_context,
|
||
|
named_anchor->layer_id,
|
||
|
named_anchor->index);
|
||
|
if (!name_rec) {
|
||
|
LO_UnlockLayout();
|
||
|
return JS_TRUE; /* Try to handle this case gracefully. */
|
||
|
}
|
||
|
|
||
|
switch (slot) {
|
||
|
case ANCHOR_TEXT:
|
||
|
if (named_anchor->text)
|
||
|
*vp = STRING_TO_JSVAL(named_anchor->text);
|
||
|
else
|
||
|
*vp = JSVAL_NULL;
|
||
|
break;
|
||
|
|
||
|
case ANCHOR_NAME:
|
||
|
if (named_anchor->name)
|
||
|
*vp = STRING_TO_JSVAL(named_anchor->name);
|
||
|
else
|
||
|
*vp = JSVAL_NULL;
|
||
|
break;
|
||
|
|
||
|
case ANCHOR_X:
|
||
|
*vp = INT_TO_JSVAL(name_rec->element->lo_any.x);
|
||
|
break;
|
||
|
|
||
|
case ANCHOR_Y:
|
||
|
*vp = INT_TO_JSVAL(name_rec->element->lo_any.y);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
/* Don't mess with a user-defined or method property. */
|
||
|
break;
|
||
|
}
|
||
|
LO_UnlockLayout();
|
||
|
return JS_TRUE;
|
||
|
}
|
||
|
|
||
|
PR_STATIC_CALLBACK(void)
|
||
|
anchor_finalize(JSContext *cx, JSObject *obj)
|
||
|
{
|
||
|
JSAnchor *named_anchor;
|
||
|
MochaDecoder *decoder;
|
||
|
MWContext *context;
|
||
|
lo_NameList *name_rec;
|
||
|
|
||
|
named_anchor = JS_GetPrivate(cx, obj);
|
||
|
if (!named_anchor)
|
||
|
return;
|
||
|
decoder = named_anchor->decoder;
|
||
|
context = decoder->window_context;
|
||
|
if (context) {
|
||
|
LO_LockLayout();
|
||
|
name_rec = LO_GetNamedAnchorByIndex(context, named_anchor->layer_id,
|
||
|
named_anchor->index);
|
||
|
if (name_rec && name_rec->mocha_object == obj)
|
||
|
name_rec->mocha_object = NULL;
|
||
|
LO_UnlockLayout();
|
||
|
}
|
||
|
DROP_BACK_COUNT(decoder);
|
||
|
JS_UnlockGCThing(cx, named_anchor->text);
|
||
|
JS_UnlockGCThing(cx, named_anchor->name);
|
||
|
JS_free(cx, named_anchor);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Named anchors are read only, so there is no anchor_setProperty. */
|
||
|
JSClass lm_anchor_class = {
|
||
|
"Anchor", JSCLASS_HAS_PRIVATE,
|
||
|
JS_PropertyStub, JS_PropertyStub, anchor_getProperty, anchor_getProperty,
|
||
|
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, anchor_finalize
|
||
|
};
|
||
|
|
||
|
PR_STATIC_CALLBACK(JSBool)
|
||
|
Anchor(JSContext *cx, JSObject *obj,
|
||
|
uint argc, jsval *argv, jsval *rval)
|
||
|
{
|
||
|
return JS_TRUE;
|
||
|
}
|
||
|
|
||
|
JSObject *
|
||
|
LM_ReflectNamedAnchor(MWContext *context, lo_NameList *name_rec,
|
||
|
PA_Tag * tag, int32 layer_id, uint index)
|
||
|
{
|
||
|
JSObject *obj, *array_obj, *document;
|
||
|
MochaDecoder *decoder;
|
||
|
JSContext *cx;
|
||
|
JSObjectArray *array;
|
||
|
JSAnchor *named_anchor;
|
||
|
lo_TopState *top_state;
|
||
|
PRHashTable *map;
|
||
|
JSString *str;
|
||
|
|
||
|
obj = name_rec->mocha_object;
|
||
|
if (obj)
|
||
|
return obj;
|
||
|
|
||
|
decoder = LM_GetMochaDecoder(context);
|
||
|
if (!decoder)
|
||
|
return NULL;
|
||
|
cx = decoder->js_context;
|
||
|
|
||
|
top_state = lo_GetMochaTopState(context);
|
||
|
if (top_state->resize_reload) {
|
||
|
map = lm_GetIdToObjectMap(decoder);
|
||
|
|
||
|
if (map)
|
||
|
obj = (JSObject *)PR_HashTableLookup(map,
|
||
|
LM_GET_MAPPING_KEY(LM_NAMEDANCHORS,
|
||
|
layer_id, index));
|
||
|
if (obj) {
|
||
|
name_rec->mocha_object = obj;
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return obj;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Get the document object that will hold this anchor */
|
||
|
document = lm_GetDocumentFromLayerId(decoder, layer_id);
|
||
|
if (!document) {
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
array_obj = lm_GetNameArray(decoder, document);
|
||
|
if (!array_obj) {
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return NULL;
|
||
|
}
|
||
|
array = JS_GetPrivate(cx, array_obj);
|
||
|
if (!array) {
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
named_anchor = JS_malloc(cx, sizeof *named_anchor);
|
||
|
if (!named_anchor) {
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return NULL;
|
||
|
}
|
||
|
XP_BZERO(named_anchor, sizeof *named_anchor);
|
||
|
|
||
|
obj = JS_NewObject(cx, &lm_anchor_class, decoder->anchor_prototype,
|
||
|
document);
|
||
|
|
||
|
if (!obj || !JS_SetPrivate(cx, obj, named_anchor)) {
|
||
|
JS_free(cx, named_anchor);
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/* Put obj into the document.anchors array. */
|
||
|
JS_DefineProperty(cx, array_obj, (char *) name_rec->name,
|
||
|
OBJECT_TO_JSVAL(obj), NULL, NULL,
|
||
|
JSPROP_ENUMERATE|JSPROP_READONLY);
|
||
|
JS_AliasElement(cx, array_obj, (char *) name_rec->name, index);
|
||
|
|
||
|
/* Put it in the index to object hash table */
|
||
|
map = lm_GetIdToObjectMap(decoder);
|
||
|
if (map) {
|
||
|
PR_HashTableAdd(map,
|
||
|
LM_GET_MAPPING_KEY(LM_NAMEDANCHORS, layer_id, index),
|
||
|
obj);
|
||
|
}
|
||
|
if ((jsint) index >= array->length)
|
||
|
array->length = index + 1;
|
||
|
|
||
|
named_anchor->decoder = HOLD_BACK_COUNT(decoder);
|
||
|
named_anchor->layer_id = layer_id;
|
||
|
named_anchor->index = index;
|
||
|
if (name_rec->element && name_rec->element->type == LO_TEXT) {
|
||
|
str = lm_LocalEncodingToStr(context,
|
||
|
(char *) name_rec->element->lo_text.text);
|
||
|
if (!str || !JS_LockGCThing(cx, str)) {
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return NULL;
|
||
|
}
|
||
|
named_anchor->text = str;
|
||
|
}
|
||
|
str = JS_NewStringCopyZ(cx, (char *) name_rec->name);
|
||
|
if (!str || !JS_LockGCThing(cx, str)) {
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return NULL;
|
||
|
}
|
||
|
named_anchor->name = str;
|
||
|
|
||
|
name_rec->mocha_object = obj;
|
||
|
|
||
|
/* see if there are any attributes for event handlers */
|
||
|
if(tag) {
|
||
|
PA_Block onlocate, id;
|
||
|
|
||
|
/* don't hold the layout lock across compiles */
|
||
|
LO_UnlockLayout();
|
||
|
|
||
|
onlocate = lo_FetchParamValue(context, tag, PARAM_ONLOCATE);
|
||
|
id = lo_FetchParamValue(context, tag, PARAM_ID);
|
||
|
if (onlocate) {
|
||
|
(void) lm_CompileEventHandler(decoder, id, tag->data,
|
||
|
tag->newline_count, obj,
|
||
|
PARAM_ONLOCATE, onlocate);
|
||
|
PA_FREE(onlocate);
|
||
|
}
|
||
|
if (id)
|
||
|
PA_FREE(id);
|
||
|
LO_LockLayout();
|
||
|
}
|
||
|
|
||
|
LM_PutMochaDecoder(decoder);
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
|
||
|
JSBool
|
||
|
lm_InitAnchorClass(MochaDecoder *decoder)
|
||
|
{
|
||
|
JSContext *cx;
|
||
|
JSObject *prototype;
|
||
|
|
||
|
cx = decoder->js_context;
|
||
|
prototype = JS_InitClass(cx, decoder->window_object,
|
||
|
decoder->event_receiver_prototype,
|
||
|
&lm_anchor_class, Anchor, 0,
|
||
|
anchor_props, NULL, NULL, NULL);
|
||
|
if (!prototype)
|
||
|
return JS_FALSE;
|
||
|
decoder->anchor_prototype = prototype;
|
||
|
return JS_TRUE;
|
||
|
}
|