home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libmocha / lm_href.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  19.0 KB  |  696 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /*
  19.  * JS reflection of the HREF and NAME Anchors in the current document.
  20.  *
  21.  * Brendan Eich, 9/8/95
  22.  */
  23. #include "lm.h"
  24. #include "pa_tags.h"
  25. #include "layout.h"    /* XXX for lo_NameList only */
  26.  
  27. enum anchor_array_slot {
  28.     ANCHOR_ARRAY_LENGTH = -1
  29. };
  30.  
  31. static JSPropertySpec anchor_array_props[] = {
  32.     {lm_length_str, ANCHOR_ARRAY_LENGTH,
  33.             JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT},
  34.     {0}
  35. };
  36.  
  37. extern JSClass lm_link_array_class;
  38.  
  39. PR_STATIC_CALLBACK(JSBool)
  40. link_array_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
  41. {
  42.     JSObjectArray *array;
  43.     MochaDecoder *decoder;
  44.     MWContext *context;
  45.     jsint count, slot;
  46.     LO_AnchorData *anchor_data;
  47.     int32 active_layer_id;
  48.  
  49.     if (!JSVAL_IS_INT(id))
  50.     return JS_TRUE;
  51.  
  52.     slot = JSVAL_TO_INT(id);
  53.  
  54.     array = JS_GetInstancePrivate(cx, obj, &lm_link_array_class, NULL);
  55.     if (!array)
  56.     return JS_TRUE;
  57.     decoder = array->decoder;
  58.     context = decoder->window_context;
  59.     if (!context) return JS_TRUE;
  60.  
  61.     LO_LockLayout();
  62.     switch (slot) {
  63.       case ANCHOR_ARRAY_LENGTH:
  64.     active_layer_id = LM_GetActiveLayer(context);
  65.     LM_SetActiveLayer(context, array->layer_id);
  66.     count = LO_EnumerateLinks(context, array->layer_id);
  67.     LM_SetActiveLayer(context, active_layer_id);
  68.     if (count > array->length)
  69.         array->length = count;
  70.     *vp = INT_TO_JSVAL(count);
  71.     break;
  72.  
  73.       default:
  74.     if (slot < 0) {
  75.         /* Don't mess with user-defined or method properties. */
  76.         LO_UnlockLayout();
  77.         return JS_TRUE;
  78.     }
  79.     if (slot >= array->length)
  80.         array->length = slot + 1;
  81.     anchor_data = LO_GetLinkByIndex(context, array->layer_id, (uint)slot);
  82.     if (anchor_data) {
  83.         *vp = OBJECT_TO_JSVAL(LM_ReflectLink(context, anchor_data, NULL,
  84.                          array->layer_id, (uint)slot));
  85.     }
  86.     break;
  87.     }
  88.     LO_UnlockLayout();
  89.     return JS_TRUE;
  90. }
  91.  
  92. PR_STATIC_CALLBACK(void)
  93. anchor_array_finalize(JSContext *cx, JSObject *obj)
  94. {
  95.     JSObjectArray *array;
  96.  
  97.     array = JS_GetPrivate(cx, obj);
  98.     if (!array)
  99.         return;
  100.     DROP_BACK_COUNT(array->decoder);
  101.     JS_free(cx, array);
  102. }
  103.  
  104. JSClass lm_link_array_class = {
  105.     "LinkArray", JSCLASS_HAS_PRIVATE,
  106.     JS_PropertyStub, JS_PropertyStub,
  107.     link_array_getProperty, link_array_getProperty, JS_EnumerateStub,
  108.     JS_ResolveStub, JS_ConvertStub, anchor_array_finalize
  109. };
  110.  
  111. PR_STATIC_CALLBACK(JSBool)
  112. LinkArray(JSContext *cx, JSObject *obj,
  113.       uint argc, jsval *argv, jsval *rval)
  114. {
  115.     return JS_TRUE;
  116. }
  117.  
  118. extern JSClass lm_anchor_array_class;
  119.  
  120. PR_STATIC_CALLBACK(JSBool)
  121. anchor_array_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
  122. {
  123.     JSObjectArray *array;
  124.     MochaDecoder *decoder;
  125.     MWContext *context;
  126.     jsint count, slot;
  127.     lo_NameList *name_rec;
  128.     int32 active_layer_id;
  129.  
  130.     if (!JSVAL_IS_INT(id))
  131.     return JS_TRUE;
  132.  
  133.     slot = JSVAL_TO_INT(id);
  134.  
  135.     array = JS_GetInstancePrivate(cx, obj, &lm_anchor_array_class, NULL);
  136.     if (!array)
  137.     return JS_TRUE;
  138.     decoder = array->decoder;
  139.     context = decoder->window_context;
  140.     if (!context) return JS_TRUE;
  141.     LO_LockLayout();
  142.     switch (slot) {
  143.       case ANCHOR_ARRAY_LENGTH:
  144.     active_layer_id = LM_GetActiveLayer(context);
  145.     LM_SetActiveLayer(context, array->layer_id);
  146.     count = LO_EnumerateNamedAnchors(context, array->layer_id);
  147.     LM_SetActiveLayer(context, active_layer_id);
  148.     if (count > array->length)
  149.         array->length = count;
  150.     *vp = INT_TO_JSVAL(count);
  151.     break;
  152.  
  153.       default:
  154.     if (slot >= array->length)
  155.         array->length = slot + 1;
  156.     name_rec = LO_GetNamedAnchorByIndex(context, array->layer_id,
  157.                                             (uint)slot);
  158.     if (name_rec) {
  159.         *vp = OBJECT_TO_JSVAL(LM_ReflectNamedAnchor(context, name_rec,
  160.                             NULL, array->layer_id,
  161.                                                         (uint)slot));
  162.     }
  163.     break;
  164.     }
  165.     LO_UnlockLayout();
  166.     return JS_TRUE;
  167. }
  168.  
  169. JSClass lm_anchor_array_class = {
  170.     "AnchorArray", JSCLASS_HAS_PRIVATE,
  171.     JS_PropertyStub, JS_PropertyStub,
  172.     anchor_array_getProperty, anchor_array_getProperty, JS_EnumerateStub,
  173.     JS_ResolveStub, JS_ConvertStub, anchor_array_finalize
  174. };
  175.  
  176. PR_STATIC_CALLBACK(JSBool)
  177. AnchorArray(JSContext *cx, JSObject *obj,
  178.         uint argc, jsval *argv, jsval *rval)
  179. {
  180.     return JS_TRUE;
  181. }
  182.  
  183. static JSObject *
  184. reflect_anchor_array(MochaDecoder *decoder, JSClass *clasp,
  185.              JSNative constructor, JSObject *document)
  186. {
  187.     JSContext *cx;
  188.     JSObject *obj, *prototype;
  189.     JSObjectArray *array;
  190.     JSDocument *doc;
  191.  
  192.     cx = decoder->js_context;
  193.     doc = JS_GetPrivate(cx, document);
  194.     if (!doc)
  195.     return NULL;
  196.  
  197.     prototype = JS_InitClass(cx, decoder->window_object, NULL,
  198.                  clasp, constructor, 0,
  199.                  anchor_array_props, NULL, NULL, NULL);
  200.     if (!prototype)
  201.     return NULL;
  202.     array = JS_malloc(cx, sizeof *array);
  203.     if (!array)
  204.     return NULL;
  205.     XP_BZERO(array, sizeof *array);
  206.     obj = JS_NewObject(cx, clasp, prototype, document);
  207.     if (!obj || !JS_SetPrivate(cx, obj, array)) {
  208.     JS_free(cx, array);
  209.     return NULL;
  210.     }
  211.     array->decoder = HOLD_BACK_COUNT(decoder);
  212.     array->layer_id = doc->layer_id;
  213.     return obj;
  214. }
  215.  
  216. JSObject *
  217. lm_GetLinkArray(MochaDecoder *decoder, JSObject *document)
  218. {
  219.     JSObject *obj;
  220.     JSDocument *doc;
  221.  
  222.     doc = JS_GetPrivate(decoder->js_context, document);
  223.     if (!doc)
  224.     return NULL;
  225.  
  226.     obj = doc->links;
  227.     if (obj)
  228.     return obj;
  229.     obj = reflect_anchor_array(decoder, &lm_link_array_class, LinkArray,
  230.                                document);
  231.     doc->links = obj;
  232.     return obj;
  233. }
  234.  
  235. JSObject *
  236. lm_GetNameArray(MochaDecoder *decoder, JSObject *document)
  237. {
  238.     JSObject *obj;
  239.     JSDocument *doc;
  240.  
  241.     doc = JS_GetPrivate(decoder->js_context, document);
  242.     if (!doc)
  243.     return NULL;
  244.  
  245.     obj = doc->anchors;
  246.     if (obj)
  247.     return obj;
  248.     obj = reflect_anchor_array(decoder, &lm_anchor_array_class, AnchorArray,
  249.                                document);
  250.     doc->anchors = obj;
  251.     return obj;
  252. }
  253.  
  254. JSObject *
  255. LM_ReflectLink(MWContext *context, LO_AnchorData *anchor_data, PA_Tag * tag,
  256.                int32 layer_id, uint index)
  257. {
  258.     JSObject *obj, *array_obj, *document;
  259.     MochaDecoder *decoder;
  260.     JSContext *cx;
  261.     JSURL *url;
  262.     lo_TopState *top_state;
  263.     PRHashTable *map;
  264.  
  265.     anchor_data = LO_GetLinkByIndex(context, layer_id, index);
  266.     if (!anchor_data)
  267.     return NULL;
  268.  
  269.     obj = anchor_data->mocha_object;
  270.     if (obj)
  271.     return obj;
  272.  
  273.     decoder = LM_GetMochaDecoder(context);
  274.     if (!decoder)
  275.     return NULL;
  276.     cx = decoder->js_context;
  277.  
  278.     top_state = lo_GetMochaTopState(context);
  279.     if (top_state->resize_reload) {
  280.         map = lm_GetIdToObjectMap(decoder);
  281.  
  282.         if (map)
  283.             obj = (JSObject *)PR_HashTableLookup(map,
  284.                              LM_GET_MAPPING_KEY(LM_LINKS, layer_id, index));
  285.         if (obj) {
  286.             anchor_data->mocha_object = obj;
  287.             LM_PutMochaDecoder(decoder);
  288.             return obj;
  289.         }
  290.     }
  291.  
  292.     /* Get the document object that will hold this link */
  293.     document = lm_GetDocumentFromLayerId(decoder, layer_id);
  294.     if (!document) {
  295.     LM_PutMochaDecoder(decoder);
  296.     return NULL;
  297.     }
  298.  
  299.     array_obj = lm_GetLinkArray(decoder, document);
  300.     if (!array_obj) {
  301.     LM_PutMochaDecoder(decoder);
  302.     return NULL;
  303.     }
  304.  
  305.     url = lm_NewURL(cx, decoder, anchor_data, document);
  306.  
  307.     if (!url) {
  308.     LM_PutMochaDecoder(decoder);
  309.     return NULL;
  310.     }
  311.     url->index = index;
  312.     url->layer_id = layer_id;
  313.     obj = url->url_object;
  314.  
  315.     /* XXX should find a name/id to pass in */
  316.     /* put it in the links array */
  317.     if (!lm_AddObjectToArray(cx, array_obj, NULL, index, obj)) {
  318.     LM_PutMochaDecoder(decoder);
  319.         return NULL;
  320.     }
  321.  
  322.     /* Put it in the index to object hash table */
  323.     map = lm_GetIdToObjectMap(decoder);
  324.     if (map)
  325.         PR_HashTableAdd(map, LM_GET_MAPPING_KEY(LM_LINKS, layer_id, index),
  326.                         obj);
  327.  
  328.     anchor_data->mocha_object = obj;
  329.     LM_PutMochaDecoder(decoder);
  330.  
  331.     /* see if there are any event handlers we need to reflect */
  332.     if(tag) {
  333.  
  334.     PA_Block onclick, onmouseover, onmouseout, onmousedown, onmouseup, ondblclick, id;
  335.  
  336.     /* don't hold the layout lock across compiles */
  337.     LO_UnlockLayout();
  338.  
  339.     onclick = lo_FetchParamValue(context, tag, PARAM_ONCLICK);
  340.     onmouseover = lo_FetchParamValue(context, tag, PARAM_ONMOUSEOVER);
  341.     onmouseout  = lo_FetchParamValue(context, tag, PARAM_ONMOUSEOUT);
  342.     onmousedown = lo_FetchParamValue(context, tag, PARAM_ONMOUSEDOWN);
  343.     onmouseup   = lo_FetchParamValue(context, tag, PARAM_ONMOUSEUP);
  344.     ondblclick  = lo_FetchParamValue(context, tag, PARAM_ONDBLCLICK);
  345.         id = lo_FetchParamValue(context, tag, PARAM_ID);
  346.  
  347.     if (onclick) {
  348.         (void) lm_CompileEventHandler(decoder, id, tag->data,
  349.                       tag->newline_count, url->url_object,
  350.                           PARAM_ONCLICK, onclick);
  351.         PA_FREE(onclick);
  352.         anchor_data->event_handler_present = TRUE;
  353.     }
  354.     if (onmouseover) {
  355.         (void) lm_CompileEventHandler(decoder, id, tag->data,
  356.                       tag->newline_count, url->url_object,
  357.                       PARAM_ONMOUSEOVER, onmouseover);
  358.         PA_FREE(onmouseover);
  359.         anchor_data->event_handler_present = TRUE;
  360.     }
  361.     if (onmouseout) {
  362.         (void) lm_CompileEventHandler(decoder, id, tag->data,
  363.                       tag->newline_count, url->url_object,
  364.                       PARAM_ONMOUSEOUT, onmouseout);
  365.         PA_FREE(onmouseout);
  366.         anchor_data->event_handler_present = TRUE;
  367.     }
  368.     if (onmousedown) {
  369.         (void) lm_CompileEventHandler(decoder, id, tag->data,
  370.                       tag->newline_count, url->url_object,
  371.                       PARAM_ONMOUSEDOWN, onmousedown);
  372.         PA_FREE(onmousedown);
  373.         anchor_data->event_handler_present = TRUE;
  374.     }
  375.     if (onmouseup) {
  376.         (void) lm_CompileEventHandler(decoder, id, tag->data,
  377.                       tag->newline_count, url->url_object,
  378.                       PARAM_ONMOUSEUP, onmouseup);
  379.         PA_FREE(onmouseup);
  380.         anchor_data->event_handler_present = TRUE;
  381.     }
  382.     if (ondblclick) {
  383.         (void) lm_CompileEventHandler(decoder, id, tag->data,
  384.                       tag->newline_count, url->url_object,
  385.                       PARAM_ONDBLCLICK, ondblclick);
  386.         PA_FREE(ondblclick);
  387.         anchor_data->event_handler_present = TRUE;
  388.     }
  389.     if (id)
  390.         PA_FREE(id);
  391.         LO_LockLayout();
  392.     }
  393.  
  394.     return obj;
  395. }
  396.  
  397. /*
  398.  * XXX chouck - the onLocate stuff hasn't been implemented yet
  399.  *              so just return JS_TRUE and go away
  400.  */
  401. JSBool
  402. LM_SendOnLocate(MWContext *context, lo_NameList *name_rec)
  403. {
  404.     JSBool ok;
  405.     JSObject *obj;
  406.     jsval result;
  407.     JSEvent *event;
  408.  
  409.     return JS_TRUE;
  410.  
  411.     obj = name_rec->mocha_object;
  412.     if (!obj)
  413.         return JS_FALSE;
  414.  
  415.     event = XP_NEW_ZAP(JSEvent);
  416.     event->type = EVENT_LOCATE;
  417.     ok = lm_SendEvent(context, obj, event, &result);
  418.     return ok;
  419. }
  420.  
  421. /* Anchor property slots. */
  422. enum anchor_slot {
  423.     ANCHOR_TEXT     = -1,
  424.     ANCHOR_NAME     = -2,
  425.     ANCHOR_X        = -3,
  426.     ANCHOR_Y        = -4
  427. };
  428.  
  429. /* Static anchor properties. */
  430. static JSPropertySpec anchor_props[] = {
  431.     {"text",        ANCHOR_TEXT,         JSPROP_ENUMERATE | JSPROP_READONLY},
  432.     {"name",        ANCHOR_NAME,         JSPROP_ENUMERATE | JSPROP_READONLY},
  433.     {"x",           ANCHOR_X,            JSPROP_ENUMERATE | JSPROP_READONLY},
  434.     {"y",           ANCHOR_Y,            JSPROP_ENUMERATE | JSPROP_READONLY},
  435.     {0}
  436. };
  437.  
  438. /* Base anchor element type. */
  439. typedef struct JSAnchor {
  440.     MochaDecoder   *decoder;
  441.     int32           layer_id;
  442.     uint            index;
  443.     JSString       *text;
  444.     JSString       *name;
  445. } JSAnchor;
  446.  
  447. extern JSClass lm_anchor_class;
  448.  
  449. PR_STATIC_CALLBACK(JSBool)
  450. anchor_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
  451. {
  452.     JSAnchor *named_anchor;
  453.     lo_NameList *name_rec;
  454.     jsint slot;
  455.  
  456.     if (!JSVAL_IS_INT(id))
  457.     return JS_TRUE;
  458.  
  459.     slot = JSVAL_TO_INT(id);
  460.  
  461.     named_anchor = JS_GetInstancePrivate(cx, obj, &lm_anchor_class, NULL);
  462.     if (!named_anchor)
  463.     return JS_TRUE;
  464.  
  465.     LO_LockLayout();
  466.     name_rec = LO_GetNamedAnchorByIndex(named_anchor->decoder->window_context,
  467.                                         named_anchor->layer_id,
  468.                                         named_anchor->index);
  469.     if (!name_rec) {
  470.     LO_UnlockLayout();
  471.         return JS_TRUE;      /* Try to handle this case gracefully. */
  472.     }
  473.  
  474.     switch (slot) {
  475.     case ANCHOR_TEXT:
  476.         if (named_anchor->text)
  477.             *vp = STRING_TO_JSVAL(named_anchor->text);
  478.     else
  479.         *vp = JSVAL_NULL;
  480.         break;
  481.  
  482.     case ANCHOR_NAME:
  483.         if (named_anchor->name)
  484.             *vp = STRING_TO_JSVAL(named_anchor->name);
  485.     else
  486.         *vp = JSVAL_NULL;
  487.         break;
  488.  
  489.     case ANCHOR_X:
  490.         *vp = INT_TO_JSVAL(name_rec->element->lo_any.x);
  491.         break;
  492.  
  493.     case ANCHOR_Y:
  494.     *vp = INT_TO_JSVAL(name_rec->element->lo_any.y);
  495.         break;
  496.  
  497.     default:
  498.         /* Don't mess with a user-defined or method property. */
  499.         break;
  500.     }
  501.     LO_UnlockLayout();
  502.     return JS_TRUE;
  503. }
  504.  
  505. PR_STATIC_CALLBACK(void)
  506. anchor_finalize(JSContext *cx, JSObject *obj)
  507. {
  508.     JSAnchor *named_anchor;
  509.     MochaDecoder *decoder;
  510.     MWContext *context;
  511.     lo_NameList *name_rec;
  512.  
  513.     named_anchor = JS_GetPrivate(cx, obj);
  514.     if (!named_anchor)
  515.         return;
  516.     decoder = named_anchor->decoder;
  517.     context = decoder->window_context;
  518.     if (context) {
  519.     LO_LockLayout();
  520.     name_rec = LO_GetNamedAnchorByIndex(context, named_anchor->layer_id,
  521.                                             named_anchor->index);
  522.     if (name_rec && name_rec->mocha_object == obj)
  523.         name_rec->mocha_object = NULL;
  524.     LO_UnlockLayout();
  525.     }
  526.     DROP_BACK_COUNT(decoder);
  527.     JS_UnlockGCThing(cx, named_anchor->text);
  528.     JS_UnlockGCThing(cx, named_anchor->name);
  529.     JS_free(cx, named_anchor);
  530. }
  531.  
  532.  
  533. /* Named anchors are read only, so there is no anchor_setProperty. */
  534. JSClass lm_anchor_class = {
  535.     "Anchor", JSCLASS_HAS_PRIVATE,
  536.     JS_PropertyStub, JS_PropertyStub, anchor_getProperty, anchor_getProperty,
  537.     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, anchor_finalize
  538. };
  539.  
  540. PR_STATIC_CALLBACK(JSBool)
  541. Anchor(JSContext *cx, JSObject *obj,
  542.      uint argc, jsval *argv, jsval *rval)
  543. {
  544.     return JS_TRUE;
  545. }
  546.  
  547. JSObject *
  548. LM_ReflectNamedAnchor(MWContext *context, lo_NameList *name_rec,
  549.                       PA_Tag * tag, int32 layer_id, uint index)
  550. {
  551.     JSObject *obj, *array_obj, *document;
  552.     MochaDecoder *decoder;
  553.     JSContext *cx;
  554.     JSObjectArray *array;
  555.     JSAnchor *named_anchor;
  556.     lo_TopState *top_state;
  557.     PRHashTable *map;
  558.     JSString *str;
  559.  
  560.     obj = name_rec->mocha_object;
  561.     if (obj)
  562.         return obj;
  563.  
  564.     decoder = LM_GetMochaDecoder(context);
  565.     if (!decoder)
  566.         return NULL;
  567.     cx = decoder->js_context;
  568.  
  569.     top_state = lo_GetMochaTopState(context);
  570.     if (top_state->resize_reload) {
  571.         map = lm_GetIdToObjectMap(decoder);
  572.  
  573.         if (map)
  574.             obj = (JSObject *)PR_HashTableLookup(map,
  575.                                          LM_GET_MAPPING_KEY(LM_NAMEDANCHORS,
  576.                                                             layer_id, index));
  577.         if (obj) {
  578.             name_rec->mocha_object = obj;
  579.             LM_PutMochaDecoder(decoder);
  580.             return obj;
  581.         }
  582.     }
  583.  
  584.     /* Get the document object that will hold this anchor */
  585.     document = lm_GetDocumentFromLayerId(decoder, layer_id);
  586.     if (!document) {
  587.     LM_PutMochaDecoder(decoder);
  588.     return NULL;
  589.     }
  590.  
  591.     array_obj = lm_GetNameArray(decoder, document);
  592.     if (!array_obj) {
  593.         LM_PutMochaDecoder(decoder);
  594.         return NULL;
  595.     }
  596.     array = JS_GetPrivate(cx, array_obj);
  597.     if (!array) {
  598.         LM_PutMochaDecoder(decoder);
  599.     return NULL;
  600.     }
  601.  
  602.     named_anchor = JS_malloc(cx, sizeof *named_anchor);
  603.     if (!named_anchor) {
  604.         LM_PutMochaDecoder(decoder);
  605.         return NULL;
  606.     }
  607.     XP_BZERO(named_anchor, sizeof *named_anchor);
  608.  
  609.     obj = JS_NewObject(cx, &lm_anchor_class, decoder->anchor_prototype,
  610.                document);
  611.  
  612.     if (!obj || !JS_SetPrivate(cx, obj, named_anchor)) {
  613.         JS_free(cx, named_anchor);
  614.         LM_PutMochaDecoder(decoder);
  615.         return NULL;
  616.     }
  617.  
  618.     /* Put obj into the document.anchors array. */
  619.     JS_DefineProperty(cx, array_obj, (char *) name_rec->name,
  620.               OBJECT_TO_JSVAL(obj), NULL, NULL,
  621.               JSPROP_ENUMERATE|JSPROP_READONLY);
  622.     JS_AliasElement(cx, array_obj, (char *) name_rec->name, index);
  623.  
  624.     /* Put it in the index to object hash table */
  625.     map = lm_GetIdToObjectMap(decoder);
  626.     if (map) {
  627.         PR_HashTableAdd(map,
  628.                         LM_GET_MAPPING_KEY(LM_NAMEDANCHORS, layer_id, index),
  629.                         obj);
  630.     }
  631.     if ((jsint) index >= array->length)
  632.     array->length = index + 1;
  633.  
  634.     named_anchor->decoder = HOLD_BACK_COUNT(decoder);
  635.     named_anchor->layer_id = layer_id;
  636.     named_anchor->index = index;
  637.     if (name_rec->element && name_rec->element->type == LO_TEXT) {
  638.     str = lm_LocalEncodingToStr(context, 
  639.                     (char *) name_rec->element->lo_text.text);
  640.     if (!str || !JS_LockGCThing(cx, str)) {
  641.         LM_PutMochaDecoder(decoder);
  642.         return NULL;
  643.     }
  644.     named_anchor->text = str;
  645.     }
  646.     str = JS_NewStringCopyZ(cx, (char *) name_rec->name);
  647.     if (!str || !JS_LockGCThing(cx, str)) {
  648.         LM_PutMochaDecoder(decoder);
  649.     return NULL;
  650.     }
  651.     named_anchor->name = str;
  652.  
  653.     name_rec->mocha_object = obj;
  654.  
  655.     /* see if there are any attributes for event handlers */
  656.     if(tag) {
  657.         PA_Block onlocate, id;
  658.  
  659.     /* don't hold the layout lock across compiles */
  660.     LO_UnlockLayout();
  661.  
  662.         onlocate = lo_FetchParamValue(context, tag, PARAM_ONLOCATE);
  663.         id = lo_FetchParamValue(context, tag, PARAM_ID);
  664.         if (onlocate) {
  665.         (void) lm_CompileEventHandler(decoder, id, tag->data,
  666.                       tag->newline_count, obj,
  667.                       PARAM_ONLOCATE, onlocate);
  668.             PA_FREE(onlocate);
  669.         }
  670.     if (id)
  671.         PA_FREE(id);
  672.     LO_LockLayout();
  673.     }
  674.  
  675.     LM_PutMochaDecoder(decoder);
  676.     return obj;
  677. }
  678.  
  679.  
  680. JSBool
  681. lm_InitAnchorClass(MochaDecoder *decoder)
  682. {
  683.     JSContext *cx;
  684.     JSObject *prototype;
  685.  
  686.     cx = decoder->js_context;
  687.     prototype = JS_InitClass(cx, decoder->window_object,
  688.                  decoder->event_receiver_prototype,
  689.                  &lm_anchor_class, Anchor, 0,
  690.                  anchor_props, NULL, NULL, NULL);
  691.     if (!prototype)
  692.     return JS_FALSE;
  693.     decoder->anchor_prototype = prototype;
  694.     return JS_TRUE;
  695. }
  696.