Files
w3m/js/w3m_events.c
2025-08-16 19:43:11 -04:00

257 lines
6.7 KiB
C

/*
* 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 <stdlib.h>
#include <string.h>
/* 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 */