/* * w3m Event System Implementation * * Basic event system for JavaScript integration. * This provides minimal event functionality for Phase 1. */ #include "fm.h" #ifdef USE_JAVASCRIPT #include "w3m_events.h" #include "w3m_javascript.h" #include "w3m_dom.h" #include #include /* Event System Management */ W3MEventSystem * w3m_events_create_system(void) { W3MEventSystem *system = GC_MALLOC(sizeof(W3MEventSystem)); if (!system) return NULL; /* Initialize listener arrays */ for (int i = 0; i < W3M_EVENT_TYPE_COUNT; i++) { system->listeners[i] = NULL; } /* Initialize event queue */ system->event_queue = NULL; system->queue_size = 0; system->queue_capacity = 0; system->processing_events = 0; return system; } void w3m_events_destroy_system(W3MEventSystem *system) { if (!system) return; /* Free event listeners */ for (int i = 0; i < W3M_EVENT_TYPE_COUNT; i++) { W3MEventListener *listener = system->listeners[i]; while (listener) { W3MEventListener *next = listener->next; if (!JS_IsNull(listener->callback)) { /* Note: We can't free the callback here as we don't have context */ } GC_free(listener); listener = next; } } /* Free event queue */ if (system->event_queue) { for (int i = 0; i < system->queue_size; i++) { w3m_events_destroy_event(system->event_queue[i]); } GC_free(system->event_queue); } GC_free(system); } /* Event Type Utilities */ W3MEventType w3m_events_string_to_type(const char *type_string) { if (!type_string) return W3M_EVENT_TYPE_COUNT; if (strcasecmp(type_string, "click") == 0) return W3M_EVENT_CLICK; if (strcasecmp(type_string, "submit") == 0) return W3M_EVENT_SUBMIT; if (strcasecmp(type_string, "load") == 0) return W3M_EVENT_LOAD; if (strcasecmp(type_string, "unload") == 0) return W3M_EVENT_UNLOAD; if (strcasecmp(type_string, "focus") == 0) return W3M_EVENT_FOCUS; if (strcasecmp(type_string, "blur") == 0) return W3M_EVENT_BLUR; if (strcasecmp(type_string, "change") == 0) return W3M_EVENT_CHANGE; if (strcasecmp(type_string, "keypress") == 0) return W3M_EVENT_KEYPRESS; if (strcasecmp(type_string, "keydown") == 0) return W3M_EVENT_KEYDOWN; if (strcasecmp(type_string, "keyup") == 0) return W3M_EVENT_KEYUP; if (strcasecmp(type_string, "mouseover") == 0) return W3M_EVENT_MOUSEOVER; if (strcasecmp(type_string, "mouseout") == 0) return W3M_EVENT_MOUSEOUT; return W3M_EVENT_TYPE_COUNT; } const char * w3m_events_type_to_string(W3MEventType type) { switch (type) { case W3M_EVENT_CLICK: return "click"; case W3M_EVENT_SUBMIT: return "submit"; case W3M_EVENT_LOAD: return "load"; case W3M_EVENT_UNLOAD: return "unload"; case W3M_EVENT_FOCUS: return "focus"; case W3M_EVENT_BLUR: return "blur"; case W3M_EVENT_CHANGE: return "change"; case W3M_EVENT_KEYPRESS: return "keypress"; case W3M_EVENT_KEYDOWN: return "keydown"; case W3M_EVENT_KEYUP: return "keyup"; case W3M_EVENT_MOUSEOVER: return "mouseover"; case W3M_EVENT_MOUSEOUT: return "mouseout"; default: return "unknown"; } } /* Event Management */ W3MEvent * w3m_events_create_event(W3MEventType type, W3MElement *target) { W3MEvent *event = GC_MALLOC(sizeof(W3MEvent)); if (!event) return NULL; event->type = type; event->type_string = w3m_events_type_to_string(type); event->target = target; event->currentTarget = target; event->bubbles = 1; event->cancelable = 1; event->defaultPrevented = 0; event->propagationStopped = 0; /* Initialize event data */ memset(&event->data, 0, sizeof(event->data)); event->js_event = JS_NULL; return event; } void w3m_events_destroy_event(W3MEvent *event) { if (!event) return; /* Free any generic data */ if (event->data.generic.data) { GC_free(event->data.generic.data); } GC_free(event); } /* Event Listener Management */ void w3m_events_add_listener(W3MEventSystem *system, W3MElement *target, const char *type, JSValue callback, int use_capture) { if (!system || !target || !type) return; W3MEventType event_type = w3m_events_string_to_type(type); if (event_type >= W3M_EVENT_TYPE_COUNT) return; W3MEventListener *listener = GC_MALLOC(sizeof(W3MEventListener)); if (!listener) return; listener->type = event_type; listener->callback = callback; listener->target = target; listener->use_capture = use_capture; /* Add to linked list */ listener->next = system->listeners[event_type]; system->listeners[event_type] = listener; } int w3m_events_has_listener(W3MEventSystem *system, W3MElement *target, const char *type) { if (!system || !target || !type) return 0; W3MEventType event_type = w3m_events_string_to_type(type); if (event_type >= W3M_EVENT_TYPE_COUNT) return 0; W3MEventListener *listener = system->listeners[event_type]; while (listener) { if (listener->target == target) { return 1; } listener = listener->next; } return 0; } /* Integration with w3m Input System (Stubs for Phase 1) */ int w3m_events_handle_click(Buffer *buf, Anchor *anchor) { /* Phase 1: Always return 0 to continue normal processing */ return 0; } int w3m_events_handle_form_submit(Buffer *buf, FormList *form) { /* Phase 1: Always return 0 to continue normal processing */ return 0; } int w3m_events_handle_key_press(Buffer *buf, int key) { /* Phase 1: Always return 0 to continue normal processing */ return 0; } void w3m_events_handle_page_load(Buffer *buf) { /* Phase 1: Execute pending scripts */ if (buf && buf->js_state) { w3m_js_execute_pending_scripts((BufferJSState *)buf->js_state); } } void w3m_events_handle_page_unload(Buffer *buf) { /* Phase 1: No action needed */ } /* JavaScript Event API Stubs */ void w3m_events_bind_to_js(W3MJSContext *ctx, W3MEventSystem *system) { /* Phase 1: Create empty addEventListener function */ if (!ctx || !system) return; /* This will be implemented in later phases */ } JSValue js_addEventListener(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { /* Phase 1: Do nothing */ return JS_UNDEFINED; } JSValue js_removeEventListener(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { /* Phase 1: Do nothing */ return JS_UNDEFINED; } #endif /* USE_JAVASCRIPT */