257 lines
6.7 KiB
C
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 */ |