static JSBool url_get_coord(JSContext *cx, JSURL *url, jsint slot, jsval *vp) { int32 coord; LO_AnchorData *anchor_data; MWContext *context; LO_LockLayout(); context = url->url_decoder->window_context; anchor_data = LO_GetLinkByIndex(context, url->layer_id, url->index); if (anchor_data && anchor_data->element) { switch (slot) { case URL_X: coord = anchor_data->element->lo_any.x; break; case URL_Y: coord = anchor_data->element->lo_any.y; break; default: LO_UnlockLayout(); return JS_FALSE; } *vp = INT_TO_JSVAL(coord); LO_UnlockLayout(); return JS_TRUE; } *vp = JSVAL_NULL; LO_UnlockLayout(); return JS_TRUE; }
url_finalize(JSContext *cx, JSObject *obj) { JSURL *url; MochaDecoder *decoder; MWContext *context; LO_AnchorData *anchor_data; url = JS_GetPrivate(cx, obj); if (!url) return; decoder = url->url_decoder; if (url->index != URL_NOT_INDEXED) { context = decoder->window_context; if (context) { LO_LockLayout(); anchor_data = LO_GetLinkByIndex(context, url->layer_id, url->index); if (anchor_data && anchor_data->mocha_object == obj) anchor_data->mocha_object = NULL; LO_UnlockLayout(); } } DROP_BACK_COUNT(decoder); JS_RemoveRoot(cx, &url->href); JS_RemoveRoot(cx, &url->target); JS_RemoveRoot(cx, &url->text); XP_DELETE(url); }
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; }
url_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { JSURL *url; const char *href, *name, *checked_href; char *new_href, *prop_name; JSBool free_href; jsval tmp; JSString *str; MWContext *context; LO_AnchorData *anchor_data; JSBool ok; jsint slot; url = JS_GetInstancePrivate(cx, obj, &lm_url_class, NULL); if (!url) { url = JS_GetInstancePrivate(cx, obj, &lm_location_class, NULL); if (!url) return JS_TRUE; } /* If the property is setting an event handler we find out now so * that we can tell the front end to send the event. */ if (JSVAL_IS_STRING(id)) { prop_name = JS_GetStringBytes(JSVAL_TO_STRING(id)); if (XP_STRCASECMP(prop_name, lm_onClick_str) == 0 || XP_STRCASECMP(prop_name, lm_onMouseDown_str) == 0 || XP_STRCASECMP(prop_name, lm_onMouseOver_str) == 0 || XP_STRCASECMP(prop_name, lm_onMouseOut_str) == 0 || XP_STRCASECMP(prop_name, lm_onMouseUp_str) == 0) { context = url->url_decoder->window_context; if (context) { anchor_data = LO_GetLinkByIndex(context, url->layer_id, url->index); if (anchor_data) anchor_data->event_handler_present = TRUE; } } return JS_TRUE; } XP_ASSERT(JSVAL_IS_INT(id)); slot = JSVAL_TO_INT(id); if (slot < 0) { /* Don't mess with user-defined or method properties. */ return JS_TRUE; } if (!JSVAL_IS_STRING(*vp) && !JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp)) { return JS_FALSE; } ok = JS_TRUE; switch (slot) { case URL_HREF: url->href = JSVAL_TO_STRING(*vp); href = JS_GetStringBytes(url->href); free_href = JS_FALSE; break; case URL_PROTOCOL: case URL_HOST: case URL_HOSTNAME: case URL_PORT: case URL_PATHNAME: case URL_HASH: case URL_SEARCH: /* a component property changed -- recompute href. */ new_href = NULL; #define GET_SLOT(aslot, ptmp) { \ if (aslot == slot) { \ *(ptmp) = *vp; \ } else { \ if (!JS_GetElement(cx, obj, aslot, ptmp)) { \ if (new_href) XP_FREE(new_href); \ return JS_FALSE; \ } \ } \ } #define ADD_SLOT(aslot, separator) { \ GET_SLOT(aslot, &tmp); \ name = JS_GetStringBytes(JSVAL_TO_STRING(tmp)); \ if (*name) { \ if (separator) StrAllocCat(new_href, separator); \ StrAllocCat(new_href, name); \ } \ } GET_SLOT(URL_PROTOCOL, &tmp); StrAllocCopy(new_href, JS_GetStringBytes(JSVAL_TO_STRING(tmp))); if (slot == URL_HOST) { ADD_SLOT(URL_HOST, "//"); } else { ADD_SLOT(URL_HOSTNAME, "//"); ADD_SLOT(URL_PORT, ":"); } ADD_SLOT(URL_PATHNAME, NULL); ADD_SLOT(URL_HASH, NULL); ADD_SLOT(URL_SEARCH, NULL); if (!new_href) { JS_ReportOutOfMemory(cx); return JS_FALSE; } free_href = JS_TRUE; href = new_href; str = JS_NewStringCopyZ(cx, href); if (!str) { ok = JS_FALSE; goto out; } url->href = str; break; case URL_TARGET: url->target = JSVAL_TO_STRING(*vp); if (url->index != URL_NOT_INDEXED) { context = url->url_decoder->window_context; if (context) { anchor_data = LO_GetLinkByIndex(context, url->layer_id, url->index); if (anchor_data) { name = JS_GetStringBytes(url->target); if (!lm_CheckWindowName(cx, name)) return JS_FALSE; if (!lm_SaveParamString(cx, &anchor_data->target, name)) return JS_FALSE; } } } /* Note early return, to bypass href update and freeing. */ return JS_TRUE; default: /* Don't mess with a user-defined property. */ return ok; } if (url->index != URL_NOT_INDEXED) { context = url->url_decoder->window_context; if (context) { anchor_data = LO_GetLinkByIndex(context, url->layer_id, url->index); if (anchor_data) { checked_href = lm_CheckURL(cx, href, JS_FALSE); if (!checked_href || !lm_SaveParamString(cx, &anchor_data->anchor, checked_href)) { ok = JS_FALSE; goto out; } XP_FREE((char *)checked_href); } } } out: if (free_href && href) XP_FREE((char *)href); return ok; }
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; }