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

  1. /* -*- Mode: C++; tab-width: 8; 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.  
  20. /*
  21.  * JS event class.
  22.  */
  23. #include "lm.h"
  24. #include "lo_ele.h"
  25. #include "pa_tags.h"
  26. #include "xp.h"
  27. #include "prbit.h"
  28. #include "prtypes.h"
  29. #include "mkhelp.h"        /* For onhelp support */
  30. #include "jsapi.h"        /* For onhelp support */
  31.  
  32. static JSEventNames event_names[] = {
  33.     /* ordered by log2(event_bit) */
  34.     {"mousedown",    "MouseDown"},
  35.     {"mouseup",        "MouseUp"},
  36.     {"mouseover",    "MouseOver"},
  37.     {"mouseout",    "MouseOut"},
  38.     {"mousemove",    "MouseMove"},
  39.     {"mousedrag",    "MouseDrag"},
  40.     {"click",        "Click"},
  41.     {"dblclick",    "DblClick"},
  42.     {"keydown",        "KeyDown"},
  43.     {"keyup",        "KeyUp"},
  44.     {"keypress",    "KeyPress"},
  45.     {"dragdrop",    "DragDrop"},
  46.     {"focus",        "Focus"},
  47.     {"blur",        "Blur"},
  48.     {"select",        "Select"},
  49.     {"change",        "Change"},
  50.     {"reset",        "Reset"},
  51.     {"submit",        "Submit"},
  52.     {"scroll",        "Scroll"},
  53.     {"load",        "Load"},
  54.     {"unload",        "Unload"},
  55.     {"xferdone",    "XferDone"},
  56.     {"abort",        "Abort"},
  57.     {"error",        "Error"},
  58.     {"locate",        "Locate"},
  59.     {"move",        "Move"},
  60.     {"resize",        "Resize"},
  61.     {"forward",        "Forward"},
  62.     {"help",        "Help"},
  63.     {"back",        "Back"},
  64. };
  65.  
  66. #define NUM_EVENTS      (sizeof event_names / sizeof event_names[0])
  67.  
  68. static JSConstDoubleSpec event_constants[] = {
  69.     {EVENT_ALT_MASK             , "ALT_MASK"},
  70.     {EVENT_CONTROL_MASK         , "CONTROL_MASK"},
  71.     {EVENT_SHIFT_MASK           , "SHIFT_MASK"},
  72.     {EVENT_META_MASK            , "META_MASK"},
  73.     {EVENT_MOUSEDOWN        , "MOUSEDOWN"},
  74.     {EVENT_MOUSEUP        , "MOUSEUP"},
  75.     {EVENT_MOUSEOVER        , "MOUSEOVER"},
  76.     {EVENT_MOUSEOUT        , "MOUSEOUT"},
  77.     {EVENT_MOUSEMOVE        , "MOUSEMOVE"},
  78.     {EVENT_MOUSEDRAG        , "MOUSEDRAG"},
  79.     {EVENT_CLICK        , "CLICK"},
  80.     {EVENT_DBLCLICK        , "DBLCLICK"},
  81.     {EVENT_KEYDOWN        , "KEYDOWN"},
  82.     {EVENT_KEYUP        , "KEYUP"},
  83.     {EVENT_KEYPRESS        , "KEYPRESS"},
  84.     {EVENT_DRAGDROP        , "DRAGDROP"},
  85.     {EVENT_FOCUS        , "FOCUS"},
  86.     {EVENT_BLUR            , "BLUR"},
  87.     {EVENT_SELECT        , "SELECT"},
  88.     {EVENT_CHANGE        , "CHANGE"},
  89.     {EVENT_RESET        , "RESET"},
  90.     {EVENT_SUBMIT        , "SUBMIT"},
  91.     {EVENT_SCROLL        , "SCROLL"},
  92.     {EVENT_LOAD            , "LOAD"},
  93.     {EVENT_UNLOAD        , "UNLOAD"},
  94.     {EVENT_XFER_DONE        , "XFER_DONE"},
  95.     {EVENT_ABORT        , "ABORT"},
  96.     {EVENT_ERROR        , "ERROR"},
  97.     {EVENT_LOCATE        , "LOCATE"},
  98.     {EVENT_MOVE            , "MOVE"},
  99.     {EVENT_RESIZE        , "RESIZE"},
  100.     {EVENT_FORWARD        , "FORWARD"},
  101.     {EVENT_HELP            , "HELP"},
  102.     {EVENT_BACK            , "BACK"},
  103.     {0, 0}
  104. };
  105.  
  106. const char *
  107. lm_EventName(uint32 event_bit)
  108. {
  109.     uint index = (uint)PR_CeilingLog2(event_bit);
  110.  
  111.     if (index >= NUM_EVENTS)
  112.     return "unknown event";
  113.     return event_names[index].lowerName;
  114. }
  115.  
  116. JSEventNames *
  117. lm_GetEventNames(uint32 event_bit)
  118. {
  119.     uint index = (uint)PR_CeilingLog2(event_bit);
  120.  
  121.     if (index >= NUM_EVENTS)
  122.     return NULL;
  123.     return &event_names[index];
  124. }
  125.  
  126. uint32
  127. lm_FindEventInMWContext(MWContext *context)
  128. {
  129.     int i;
  130.     XP_List *kids;
  131.     MWContext *kid;
  132.     uint32 events;
  133.  
  134.  
  135.     if (!context->grid_children)
  136.         return context->event_bit;
  137.  
  138.     events = 0;
  139.  
  140.     if ((kids = context->grid_children) != NULL) {
  141.     for (i = 1; ((kid = XP_ListGetObjectNum(kids, i)) != NULL); i++) {
  142.         events |= lm_FindEventInMWContext(kid);
  143.         }
  144.     }
  145.     return events;
  146. }
  147.  
  148. XP_Bool
  149. LM_EventCaptureCheck(MWContext * context, uint32 current_event) {
  150.  
  151.     if (context->event_bit & current_event)
  152.     return TRUE;
  153.     if (context->grid_parent)
  154.     return LM_EventCaptureCheck(context->grid_parent, current_event);
  155.     return FALSE;
  156. }
  157.  
  158. enum event_tinyid {
  159.     EVENT_TYPE        = -1,
  160.     EVENT_X        = -2,
  161.     EVENT_Y        = -3,
  162.     EVENT_LAYERX    = -4,
  163.     EVENT_LAYERY    = -5,
  164.     EVENT_WHICH        = -6,
  165.     EVENT_MODIFIERS    = -7,
  166.     EVENT_DATA        = -8,
  167.     EVENT_DOCX        = -9,
  168.     EVENT_DOCY        = -10,
  169.     EVENT_SCREENX    = -11,
  170.     EVENT_SCREENY    = -12,
  171.     EVENT_OBJECT    = -13
  172. };
  173.  
  174. static JSPropertySpec event_props[] = {
  175.     {"type"        , EVENT_TYPE,        JSPROP_ENUMERATE},
  176.     {"x"        , EVENT_X,        JSPROP_ENUMERATE},
  177.     {"y"        , EVENT_Y,        JSPROP_ENUMERATE},
  178.     {"width"        , EVENT_X,        JSPROP_ENUMERATE},
  179.     {"height"        , EVENT_Y,        JSPROP_ENUMERATE},
  180.     {"layerX"        , EVENT_LAYERX,        JSPROP_ENUMERATE},
  181.     {"layerY"        , EVENT_LAYERY,        JSPROP_ENUMERATE},
  182.     {"which"        , EVENT_WHICH,        JSPROP_ENUMERATE},
  183.     {"modifiers"    , EVENT_MODIFIERS,    JSPROP_ENUMERATE},
  184.     {"data"        , EVENT_DATA,        JSPROP_ENUMERATE},
  185.     {"pageX"        , EVENT_DOCX,        JSPROP_ENUMERATE},
  186.     {"pageY"        , EVENT_DOCY,        JSPROP_ENUMERATE},
  187.     {"screenX"        , EVENT_SCREENX,    JSPROP_ENUMERATE},
  188.     {"screenY"        , EVENT_SCREENY,    JSPROP_ENUMERATE},
  189.     {"target"        , EVENT_OBJECT,        JSPROP_ENUMERATE},
  190.     {0}
  191. };
  192.  
  193. extern JSClass lm_event_class;
  194.  
  195. PR_STATIC_CALLBACK(JSBool)
  196. event_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
  197. {
  198.     JSEvent *event;
  199.     JSString *str;
  200.     char ** urlArray;
  201.     jsval urlVal;
  202.     JSObject *array;
  203.     jsint slot;
  204.  
  205.     if (!JSVAL_IS_INT(id))
  206.     return JS_TRUE;
  207.  
  208.     event = JS_GetInstancePrivate(cx, obj, &lm_event_class, NULL);
  209.     if (!event)
  210.     return JS_TRUE;
  211.  
  212.     if (!JSVAL_IS_INT(id))
  213.     return JS_TRUE;
  214.  
  215.     /*
  216.      * You might think the following would make a real nice
  217.      *   switch() statement.  But if you make it into one be
  218.      *   ready to battle the Win16 internal compiler error
  219.      *   demons.
  220.      */
  221.     if (JSVAL_TO_INT(id) == EVENT_TYPE) {
  222.     str = JS_NewStringCopyZ(cx, lm_EventName(event->type));
  223.     if (!str)
  224.         return JS_FALSE;
  225.     *vp = STRING_TO_JSVAL(str);
  226.     }
  227.     else if ((JSVAL_TO_INT(id) == EVENT_X) || (JSVAL_TO_INT(id) == EVENT_LAYERX)) {
  228.     * vp = INT_TO_JSVAL(event->x);
  229.     }
  230.     else if ((JSVAL_TO_INT(id) == EVENT_Y) || (JSVAL_TO_INT(id) == EVENT_LAYERY)){
  231.     * vp = INT_TO_JSVAL(event->y);
  232.     }
  233.     else if (JSVAL_TO_INT(id) == EVENT_DOCX) {
  234.     * vp = INT_TO_JSVAL(event->docx);
  235.     }
  236.     else if (JSVAL_TO_INT(id) == EVENT_DOCY) {
  237.     * vp = INT_TO_JSVAL(event->docy);
  238.     }
  239.     else if (JSVAL_TO_INT(id) == EVENT_SCREENX) {
  240.     * vp = INT_TO_JSVAL(event->screenx);
  241.     }
  242.     else if (JSVAL_TO_INT(id) == EVENT_SCREENY) {
  243.     * vp = INT_TO_JSVAL(event->screeny);
  244.     }
  245.     else if (JSVAL_TO_INT(id) == EVENT_WHICH) {
  246.     if (event->type == EVENT_HELP) {
  247.         /* For onHelp events, the which parameter holds the
  248.            URL of the help topic, as given in the pHelpInfo
  249.            field of the MWContext associated with this window. */
  250.         MWContext    *context;
  251.  
  252.         context = event->ce.context;
  253.         if (context->pHelpInfo) {
  254.         char         *topicID;
  255.         JSString    *topicStr;
  256.  
  257.         topicID = ((HelpInfoStruct *) (context->pHelpInfo))->topicURL;
  258.         topicStr = JS_NewStringCopyZ(cx, topicID);
  259.  
  260.         * vp = STRING_TO_JSVAL(topicStr);
  261.  
  262.         }
  263.         else {
  264.         JSString    *topicStr;
  265.  
  266.         topicStr = JS_NewStringCopyZ(cx, "about:blank"); /* Do not localize */
  267.         * vp = STRING_TO_JSVAL(topicStr);
  268.         }
  269.  
  270.     }
  271.     else {
  272.         * vp = INT_TO_JSVAL(event->which);
  273.     }
  274.     }
  275.     else if (JSVAL_TO_INT(id) == EVENT_MODIFIERS) {
  276.     * vp = INT_TO_JSVAL(event->modifiers);
  277.     }
  278.  
  279.     else if (JSVAL_TO_INT(id) == EVENT_OBJECT) {
  280.     if (event->object)
  281.         * vp = OBJECT_TO_JSVAL(event->object);
  282.     }
  283.  
  284.     else if (JSVAL_TO_INT(id) == EVENT_DATA) {
  285.     if (event->type == EVENT_DRAGDROP) {
  286.         if (lm_CanAccessTarget(cx, JSTARGET_UNIVERSAL_BROWSER_READ)) {
  287.         array = JS_NewArrayObject(cx, 0, NULL);
  288.         if (!array)
  289.             return JS_FALSE;
  290.  
  291.         urlArray = (char**)event->data;
  292.         if (!urlArray)
  293.             return JS_TRUE;
  294.         for (slot=0; slot<(jsint)event->dataSize; slot++) {
  295.             str = JS_NewStringCopyZ(cx, urlArray[slot]);
  296.             if (!str)
  297.             return JS_FALSE;
  298.             urlVal = STRING_TO_JSVAL(str);
  299.             if (!JS_SetElement(cx, array, slot, &urlVal))
  300.             return JS_FALSE;
  301.         }
  302.  
  303.         *vp = OBJECT_TO_JSVAL(array);                     
  304.         }
  305.     }
  306.     }
  307.  
  308.     return JS_TRUE;
  309.  
  310. }
  311.  
  312. static JSBool
  313. GetUint32(JSContext *cx, jsval v, uint32 *uip)
  314. {
  315.     jsdouble d;
  316.  
  317.     if (!JS_ValueToNumber(cx, v, &d))
  318.     return JS_FALSE;
  319.     *uip = (uint32)d;
  320.     return JS_TRUE;
  321. }
  322.  
  323. PR_STATIC_CALLBACK(JSBool)
  324. event_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
  325. {
  326.     JSEvent *event;
  327.     jsint slot, i;
  328.     JSString *str;
  329.     const char *name;
  330.     uint32 temp;
  331.  
  332.     if (!JSVAL_IS_INT(id))
  333.     return JS_TRUE;
  334.  
  335.     event = JS_GetInstancePrivate(cx, obj, &lm_event_class, NULL);
  336.     if (!event)
  337.     return JS_TRUE;
  338.  
  339.     slot = JSVAL_TO_INT(id);
  340.  
  341.     if (slot==EVENT_TYPE) {
  342.     if (!JSVAL_IS_STRING(*vp) || !(str = JS_ValueToString(cx, *vp)))
  343.         return JS_FALSE;
  344.     name = JS_GetStringBytes(str);
  345.     for (i = 0; i < NUM_EVENTS; i++) {
  346.         if (!XP_STRCASECMP(event_names[i].lowerName, name))
  347.         event->type = PR_BIT(i);
  348.     }
  349.     }
  350.     else if ((slot==EVENT_X) || (slot==EVENT_LAYERX))
  351.     return JS_ValueToInt32(cx, *vp, &event->x);
  352.     else if ((slot==EVENT_Y) ||    (slot==EVENT_LAYERY))
  353.     return JS_ValueToInt32(cx, *vp, &event->y);
  354.     else if (slot==EVENT_DOCX)
  355.     return JS_ValueToInt32(cx, *vp, &event->docx);
  356.     else if (slot==EVENT_DOCY)
  357.     return JS_ValueToInt32(cx, *vp, &event->docy);
  358.     else if (slot==EVENT_SCREENX)
  359.     return JS_ValueToInt32(cx, *vp, &event->screenx);
  360.     else if (slot==EVENT_SCREENY)
  361.     return JS_ValueToInt32(cx, *vp, &event->screeny);
  362.     else if (slot==EVENT_WHICH)
  363.     return GetUint32(cx, *vp, &event->which);
  364.     else if (slot==EVENT_MODIFIERS)
  365.     GetUint32(cx, *vp, &temp);
  366.     event->modifiers = temp;
  367.     return JS_TRUE;
  368.     /* Win16 hack */
  369.     /*else if (slot==EVENT_DATA) {
  370.     GetUint32(cx, *vp, &temp);
  371.     event->data = temp;
  372.     return JS_TRUE;
  373.     } */
  374.  
  375.     return JS_TRUE;
  376. }
  377.  
  378. PR_STATIC_CALLBACK(void)
  379. event_finalize(JSContext *cx, JSObject *obj)
  380. {
  381.     JSEvent *event;
  382.  
  383.     event = JS_GetPrivate(cx, obj);
  384.     if (!event)
  385.     return;
  386.     DROP_BACK_COUNT(event->decoder);
  387.     JS_free(cx, event);
  388. }
  389.  
  390. JSClass lm_event_class = {
  391.     "Event", JSCLASS_HAS_PRIVATE,
  392.     JS_PropertyStub,  JS_PropertyStub,  event_getProperty,  event_setProperty,
  393.     JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,     event_finalize
  394. };
  395.  
  396.  
  397. static JSBool
  398. InitEventObject(JSContext *cx, JSObject *obj, JSEvent *pEvent)
  399.  
  400. {
  401.     MochaDecoder *decoder;
  402.  
  403.     XP_ASSERT(JS_InstanceOf(cx, obj, &lm_event_class, NULL));
  404.  
  405.     if (!JS_SetPrivate(cx, obj, pEvent)) {
  406.     JS_free(cx, pEvent);
  407.     return JS_FALSE;
  408.     }
  409.  
  410.     decoder = JS_GetPrivate(cx, JS_GetGlobalObject(cx));
  411.     pEvent->decoder = HOLD_BACK_COUNT(decoder);
  412.     pEvent->saved = JS_TRUE;
  413.     return JS_TRUE;
  414. }
  415.  
  416. PR_STATIC_CALLBACK(JSBool)
  417. lm_Event(JSContext *cx, JSObject *obj, uint argc, jsval *argv, jsval *rval)
  418. {
  419.     JSEvent *pEvent;
  420.  
  421.     if (!JS_InstanceOf(cx, obj, &lm_event_class, argv))
  422.     return JS_FALSE;
  423.  
  424.     pEvent = JS_malloc(cx, sizeof(JSEvent));
  425.     if (!pEvent)
  426.     return JS_FALSE;
  427.     XP_BZERO(pEvent, sizeof(JSEvent));
  428.  
  429.     /*  Need to decide what arguments can be used */
  430.  
  431.     if (!InitEventObject(cx, obj, pEvent))
  432.     return JS_FALSE;
  433.     *rval = OBJECT_TO_JSVAL(obj);
  434.     return JS_TRUE;
  435. }
  436.  
  437. static JSClass event_receiver_class = {
  438.     "EventReceiver", 0,
  439.     JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
  440.     JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub
  441. };
  442.  
  443. PR_STATIC_CALLBACK(JSBool)
  444. EventReceiver(JSContext *cx, JSObject *obj, uint argc, jsval *argv, jsval *rval)
  445. {
  446.     return JS_TRUE;
  447. }
  448.  
  449. PR_STATIC_CALLBACK(JSBool)
  450. event_receiver_handle_event(JSContext *cx, JSObject *obj,
  451.                 uint argc, jsval *argv, jsval *rval)
  452. {
  453.     JSObject *eventObj;
  454.  
  455.     if (argc != 1)
  456.     return JS_TRUE;
  457.  
  458.     if (!JSVAL_IS_OBJECT(argv[0]) &&
  459.     !JS_ConvertValue(cx, argv[0], JSTYPE_OBJECT, &argv[0]))
  460.     return JS_FALSE;
  461.  
  462.     eventObj = JSVAL_TO_OBJECT(argv[0]);
  463.     if (!JS_InstanceOf(cx, eventObj, &lm_event_class, argv))
  464.     return JS_FALSE;
  465.  
  466.     return lm_HandleEvent(cx, obj, eventObj, JSVAL_NULL, rval);
  467. }
  468.  
  469. static JSFunctionSpec event_receiver_methods[] = {
  470.     {"handleEvent",     event_receiver_handle_event,       1},
  471.     {0}
  472. };
  473.  
  474. static JSClass event_capturer_class = {
  475.     "EventCapturer", 0,
  476.     JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
  477.     JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub
  478. };
  479.  
  480. PR_STATIC_CALLBACK(JSBool)
  481. EventCapturer(JSContext *cx, JSObject *obj, uint argc, jsval *argv, jsval *rval)
  482. {
  483.     return JS_TRUE;
  484. }
  485.  
  486. PR_STATIC_CALLBACK(JSBool)
  487. event_capturer_route_event(JSContext *cx, JSObject *obj,
  488.                uint argc, jsval *argv, jsval *rval)
  489. {
  490.     JSObject *eventObj;
  491.     JSEvent *event;
  492.  
  493.     if (argc != 1)
  494.     return JS_TRUE;
  495.  
  496.     if (!JSVAL_IS_OBJECT(argv[0]) &&
  497.     !JS_ConvertValue(cx, argv[0], JSTYPE_OBJECT, &argv[0]))
  498.     return JS_FALSE;
  499.  
  500.     eventObj = JSVAL_TO_OBJECT(argv[0]);
  501.     if (!(event = JS_GetInstancePrivate (cx, eventObj, &lm_event_class, argv)))
  502.     return JS_FALSE;
  503.  
  504.     /* Routing objects to themselves causes infinite recursion.
  505.      * And that's a big no-no.
  506.      */
  507.     if (event->object == obj)
  508.     return JS_TRUE;
  509.  
  510.     if (!event->object || !event->decoder || !event->decoder->window_context)
  511.     return JS_TRUE;
  512.     return lm_FindEventHandler(event->decoder->window_context,
  513.                    event->object, eventObj, JSVAL_NULL,
  514.                    rval);
  515. }
  516.  
  517. PR_STATIC_CALLBACK(JSBool)
  518. event_capturer_capture_events(JSContext *cx, JSObject *obj,
  519.          uint argc, jsval *argv, jsval *rval)
  520. {
  521.     return JS_TRUE;
  522. }
  523.  
  524. PR_STATIC_CALLBACK(JSBool)
  525. event_capturer_release_events(JSContext *cx, JSObject *obj,
  526.          uint argc, jsval *argv, jsval *rval)
  527. {
  528.     return JS_TRUE;
  529. }
  530.  
  531. static JSFunctionSpec event_capturer_methods[] = {
  532.     {"routeEvent",    event_capturer_route_event,        1},
  533.     {"captureEvents",   event_capturer_capture_events,       1},
  534.     {"releaseEvents",   event_capturer_release_events,     1},
  535.     {0}
  536. };
  537.  
  538. JSBool
  539. lm_InitEventClasses(MochaDecoder *decoder)
  540. {
  541.     JSContext *cx;
  542.     JSObject *prototype, *ctor;
  543.  
  544.     cx = decoder->js_context;
  545.  
  546.     prototype = JS_InitClass(cx, decoder->window_object, NULL, &lm_event_class,
  547.                  lm_Event, 0, event_props, NULL, NULL, NULL);
  548.  
  549.     if (!prototype|| !(ctor = JS_GetConstructor(cx, prototype)))
  550.     return JS_FALSE;
  551.  
  552.     if (!JS_DefineConstDoubles(cx, ctor, event_constants))
  553.     return JS_FALSE;
  554.  
  555.     decoder->event_prototype = prototype;
  556.  
  557.     prototype = JS_InitClass(cx, decoder->window_object, NULL,
  558.                  &event_receiver_class, EventReceiver, 0,
  559.                  NULL, event_receiver_methods, NULL, NULL);
  560.  
  561.     if (!prototype)
  562.     return JS_FALSE;
  563.     decoder->event_receiver_prototype = prototype;
  564.  
  565.     prototype = JS_InitClass(cx, decoder->window_object,
  566.                  decoder->event_receiver_prototype,
  567.                  &event_capturer_class, EventCapturer, 0,
  568.                  NULL, event_capturer_methods, NULL, NULL);
  569.  
  570.  
  571.     if (!prototype)
  572.     return JS_FALSE;
  573.     decoder->event_capturer_prototype = prototype;
  574.     return JS_TRUE;
  575. }
  576.  
  577.  
  578. JSObject *
  579. lm_NewEventObject(MochaDecoder * decoder, JSEvent *pEvent)
  580. {
  581.     JSContext * cx;
  582.     JSObject *obj;
  583.  
  584.     cx = decoder->js_context;
  585.     obj = JS_NewObject(cx, &lm_event_class, decoder->event_prototype, 0);
  586.     if (!obj)
  587.     return NULL;
  588.     if (!InitEventObject(cx, obj, pEvent))
  589.     return NULL;
  590.     return obj;
  591. }
  592.