diff --git a/doc/MANUAL.html b/doc/MANUAL.html index 9f82dfb..9ca1f6b 100644 --- a/doc/MANUAL.html +++ b/doc/MANUAL.html @@ -958,6 +958,30 @@ Keybinding description for C-g had been moved as it did not fit to "Hyperlink op M-m Pop up menu to navigate between hyperlinks + +NEXT_HEADING +d +d +Move to the next heading + + +PREV_HEADING +e +e +Move to the previous heading + + +NEXT_FORM +f +f +Move to the next form element + + +PREV_FORM +p +p +Move to the previous form element + diff --git a/file.c b/file.c index a7ad0d7..4d6d352 100644 --- a/file.c +++ b/file.c @@ -4631,7 +4631,7 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) */ /* Set buffer position and add to document body */ - set_element_buffer_position(p_elem, h_env->buf); + set_element_buffer_position(p_elem, h_env->buffer_ref); add_element_to_document(h_env->buffer_ref->js_document, p_elem); w3m_dom_append_child(h_env->buffer_ref->js_document->body, p_elem); } @@ -5031,6 +5031,11 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) return 1; case HTML_SCRIPT: #ifdef USE_JAVASCRIPT + /* Initialize JavaScript state if not already done */ + if (h_env->buffer_ref && !h_env->buffer_ref->js_state && w3m_js_enabled) { + h_env->buffer_ref->js_state = (void *)w3m_js_init_buffer_state(h_env->buffer_ref); + } + /* Phase 2: Create DOM element for script tag */ if (h_env->buffer_ref && h_env->buffer_ref->js_state && h_env->buffer_ref->js_document) { W3MElement *script_elem = w3m_dom_create_element("SCRIPT"); @@ -5045,7 +5050,7 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) } /* Set buffer position and add to document */ - set_element_buffer_position(script_elem, h_env->buf); + set_element_buffer_position(script_elem, h_env->buffer_ref); add_element_to_document(h_env->buffer_ref->js_document, script_elem); w3m_dom_append_child(h_env->buffer_ref->js_document->head, script_elem); } @@ -5317,6 +5322,11 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) if (!(obuf->flag & RB_IGNORE_P)) flushline(h_env, obuf, envs[h_env->envc].indent, 0, h_env->limit); #ifdef USE_JAVASCRIPT + /* Initialize JavaScript state if not already done */ + if (h_env->buffer_ref && !h_env->buffer_ref->js_state && w3m_js_enabled) { + h_env->buffer_ref->js_state = (void *)w3m_js_init_buffer_state(h_env->buffer_ref); + } + /* Phase 2: Create DOM element for DIV tag */ if (h_env->buffer_ref && h_env->buffer_ref->js_state && h_env->buffer_ref->js_document) { W3MElement *div_elem = w3m_dom_create_element("DIV"); @@ -5342,7 +5352,7 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) } */ /* Set buffer position and add to document body */ - set_element_buffer_position(div_elem, h_env->buf); + set_element_buffer_position(div_elem, h_env->buffer_ref); add_element_to_document(h_env->buffer_ref->js_document, div_elem); w3m_dom_append_child(h_env->buffer_ref->js_document->body, div_elem); } @@ -5373,6 +5383,45 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) tmp = process_form(tag); if (tmp) HTMLlineproc1(tmp->ptr, h_env); + +#ifdef USE_JAVASCRIPT + /* Initialize JavaScript state if not already done */ + if (h_env->buffer_ref && !h_env->buffer_ref->js_state && w3m_js_enabled) { + h_env->buffer_ref->js_state = (void *)w3m_js_init_buffer_state(h_env->buffer_ref); + } + + /* Phase 4: Create DOM element for form tag */ + if (h_env->buffer_ref && h_env->buffer_ref->js_state && h_env->buffer_ref->js_document) { + W3MElement *form_elem = w3m_dom_create_element("FORM"); + if (form_elem) { + /* Extract form attributes */ + char *action, *method, *name, *target, *enctype, *id; + + if (parsedtag_get_value(tag, ATTR_ACTION, &action)) + w3m_dom_set_attribute(form_elem, "action", action); + if (parsedtag_get_value(tag, ATTR_METHOD, &method)) + w3m_dom_set_attribute(form_elem, "method", method); + if (parsedtag_get_value(tag, ATTR_NAME, &name)) + w3m_dom_set_attribute(form_elem, "name", name); + if (parsedtag_get_value(tag, ATTR_TARGET, &target)) + w3m_dom_set_attribute(form_elem, "target", target); + if (parsedtag_get_value(tag, ATTR_ENCTYPE, &enctype)) + w3m_dom_set_attribute(form_elem, "enctype", enctype); + if (parsedtag_get_value(tag, ATTR_ID, &id)) { + w3m_dom_set_attribute(form_elem, "id", id); + if (!form_elem->id) { + int len = strlen(id); + form_elem->id = GC_MALLOC(len + 1); + if (form_elem->id) strcpy(form_elem->id, id); + } + } + + /* Add to document body */ + w3m_dom_append_child(h_env->buffer_ref->js_document->body, form_elem); + add_element_to_document(h_env->buffer_ref->js_document, form_elem); + } + } +#endif return 1; case HTML_N_FORM: CLOSE_A; @@ -5385,6 +5434,44 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) tmp = process_input(tag); if (tmp) HTMLlineproc1(tmp->ptr, h_env); + +#ifdef USE_JAVASCRIPT + /* Phase 4: Create DOM element for input tag */ + if (h_env->buffer_ref && h_env->buffer_ref->js_state && h_env->buffer_ref->js_document) { + W3MElement *input_elem = w3m_dom_create_element("INPUT"); + if (input_elem) { + /* Extract input attributes */ + char *type, *name, *value, *id; + char *size_str, *maxlength_str, *readonly_str; + char *checked_str, *src, *alt; + + if (parsedtag_get_value(tag, ATTR_TYPE, &type)) + w3m_dom_set_attribute(input_elem, "type", type); + if (parsedtag_get_value(tag, ATTR_NAME, &name)) + w3m_dom_set_attribute(input_elem, "name", name); + if (parsedtag_get_value(tag, ATTR_VALUE, &value)) + w3m_dom_set_attribute(input_elem, "value", value); + if (parsedtag_get_value(tag, ATTR_ID, &id)) + w3m_dom_set_attribute(input_elem, "id", id); + if (parsedtag_get_value(tag, ATTR_SIZE, &size_str)) + w3m_dom_set_attribute(input_elem, "size", size_str); + if (parsedtag_get_value(tag, ATTR_MAXLENGTH, &maxlength_str)) + w3m_dom_set_attribute(input_elem, "maxlength", maxlength_str); + if (parsedtag_get_value(tag, ATTR_READONLY, &readonly_str)) + w3m_dom_set_attribute(input_elem, "readonly", readonly_str); + if (parsedtag_get_value(tag, ATTR_CHECKED, &checked_str)) + w3m_dom_set_attribute(input_elem, "checked", checked_str); + if (parsedtag_get_value(tag, ATTR_SRC, &src)) + w3m_dom_set_attribute(input_elem, "src", src); + if (parsedtag_get_value(tag, ATTR_ALT, &alt)) + w3m_dom_set_attribute(input_elem, "alt", alt); + + /* Add to document body */ + w3m_dom_append_child(h_env->buffer_ref->js_document->body, input_elem); + add_element_to_document(h_env->buffer_ref->js_document, input_elem); + } + } +#endif return 1; case HTML_BUTTON: HTML5_CLOSE_A; @@ -5402,6 +5489,30 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) tmp = process_select(tag); if (tmp) HTMLlineproc1(tmp->ptr, h_env); + +#ifdef USE_JAVASCRIPT + /* Phase 4: Create DOM element for select tag */ + if (h_env->buffer_ref && h_env->buffer_ref->js_state && h_env->buffer_ref->js_document) { + W3MElement *select_elem = w3m_dom_create_element("SELECT"); + if (select_elem) { + /* Extract select attributes */ + char *name, *id, *size_str, *multiple_str; + + if (parsedtag_get_value(tag, ATTR_NAME, &name)) + w3m_dom_set_attribute(select_elem, "name", name); + if (parsedtag_get_value(tag, ATTR_ID, &id)) + w3m_dom_set_attribute(select_elem, "id", id); + if (parsedtag_get_value(tag, ATTR_SIZE, &size_str)) + w3m_dom_set_attribute(select_elem, "size", size_str); + if (parsedtag_get_value(tag, ATTR_MULTIPLE, &multiple_str)) + w3m_dom_set_attribute(select_elem, "multiple", multiple_str); + + /* Add to document body */ + w3m_dom_append_child(h_env->buffer_ref->js_document->body, select_elem); + add_element_to_document(h_env->buffer_ref->js_document, select_elem); + } + } +#endif obuf->flag |= RB_INSELECT; obuf->end_tag = HTML_N_SELECT; return 1; @@ -5420,6 +5531,35 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) tmp = process_textarea(tag, h_env->limit); if (tmp) HTMLlineproc1(tmp->ptr, h_env); + +#ifdef USE_JAVASCRIPT + /* Phase 4: Create DOM element for textarea tag */ + if (h_env->buffer_ref && h_env->buffer_ref->js_state && h_env->buffer_ref->js_document) { + W3MElement *textarea_elem = w3m_dom_create_element("TEXTAREA"); + if (textarea_elem) { + /* Extract textarea attributes */ + char *name, *id, *rows_str, *cols_str; + char *readonly_str, *maxlength_str; + + if (parsedtag_get_value(tag, ATTR_NAME, &name)) + w3m_dom_set_attribute(textarea_elem, "name", name); + if (parsedtag_get_value(tag, ATTR_ID, &id)) + w3m_dom_set_attribute(textarea_elem, "id", id); + if (parsedtag_get_value(tag, ATTR_ROWS, &rows_str)) + w3m_dom_set_attribute(textarea_elem, "rows", rows_str); + if (parsedtag_get_value(tag, ATTR_COLS, &cols_str)) + w3m_dom_set_attribute(textarea_elem, "cols", cols_str); + if (parsedtag_get_value(tag, ATTR_READONLY, &readonly_str)) + w3m_dom_set_attribute(textarea_elem, "readonly", readonly_str); + if (parsedtag_get_value(tag, ATTR_MAXLENGTH, &maxlength_str)) + w3m_dom_set_attribute(textarea_elem, "maxlength", maxlength_str); + + /* Add to document body */ + w3m_dom_append_child(h_env->buffer_ref->js_document->body, textarea_elem); + add_element_to_document(h_env->buffer_ref->js_document, textarea_elem); + } + } +#endif obuf->flag |= RB_INTXTA; obuf->end_tag = HTML_N_TEXTAREA; return 1; @@ -6021,7 +6161,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit) W3MElement *anchor_elem = w3m_dom_find_anchor_element(js_state->dom_document, a_href); if (anchor_elem) { a_href->element = anchor_elem; - anchor_elem->anchor = a_href; + anchor_elem->anchor = (struct Anchor *)a_href; } } } diff --git a/js/w3m_dom.c b/js/w3m_dom.c index 16da5ac..9b431df 100644 --- a/js/w3m_dom.c +++ b/js/w3m_dom.c @@ -17,6 +17,21 @@ /* Forward declarations */ static W3MElement *w3m_dom_find_anchor_element_recursive(W3MElement *elem, Anchor *anchor); +/* Phase 4: Form Element JavaScript API Function Declarations */ +static JSValue js_form_submit(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); +static JSValue js_form_reset(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); +static JSValue js_input_focus(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); +static JSValue js_input_blur(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); +static JSValue js_input_click(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); +static JSValue js_textarea_focus(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); +static JSValue js_textarea_blur(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); +static JSValue js_select_focus(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); +static JSValue js_select_blur(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); + +/* Phase 4: Form submission helper functions */ +static int w3m_dom_submit_form(W3MElement *form_elem); +static int w3m_dom_reset_form(W3MElement *form_elem); + /* DOM Document Management */ W3MDocument * @@ -829,6 +844,93 @@ create_js_element_object(JSContext *ctx, W3MElement *elem) JS_NewString(ctx, elem->innerHTML) : JS_NewString(ctx, ""); JS_SetPropertyStr(ctx, js_elem, "innerHTML", innerHTML); + /* Phase 4: Add form element properties and methods */ + if (elem->tagName) { + if (strcmp(elem->tagName, "FORM") == 0) { + /* Form element properties */ + const char *action_str = w3m_dom_get_attribute(elem, "action"); + JS_SetPropertyStr(ctx, js_elem, "action", action_str ? JS_NewString(ctx, action_str) : JS_NewString(ctx, "")); + + const char *method_str = w3m_dom_get_attribute(elem, "method"); + JS_SetPropertyStr(ctx, js_elem, "method", method_str ? JS_NewString(ctx, method_str) : JS_NewString(ctx, "get")); + + const char *name_str = w3m_dom_get_attribute(elem, "name"); + JS_SetPropertyStr(ctx, js_elem, "name", name_str ? JS_NewString(ctx, name_str) : JS_NewString(ctx, "")); + + /* Form methods */ + JS_SetPropertyStr(ctx, js_elem, "submit", + JS_NewCFunction(ctx, js_form_submit, "submit", 0)); + JS_SetPropertyStr(ctx, js_elem, "reset", + JS_NewCFunction(ctx, js_form_reset, "reset", 0)); + + } else if (strcmp(elem->tagName, "INPUT") == 0) { + /* Input element properties */ + const char *type_str = w3m_dom_get_attribute(elem, "type"); + JS_SetPropertyStr(ctx, js_elem, "type", type_str ? JS_NewString(ctx, type_str) : JS_NewString(ctx, "text")); + + const char *name_str = w3m_dom_get_attribute(elem, "name"); + JS_SetPropertyStr(ctx, js_elem, "name", name_str ? JS_NewString(ctx, name_str) : JS_NewString(ctx, "")); + + const char *value_str = w3m_dom_get_attribute(elem, "value"); + JS_SetPropertyStr(ctx, js_elem, "value", value_str ? JS_NewString(ctx, value_str) : JS_NewString(ctx, "")); + + /* Note: placeholder not supported in w3m's HTML attribute constants */ + JS_SetPropertyStr(ctx, js_elem, "placeholder", JS_NewString(ctx, "")); + + /* Boolean properties */ + const char *checked_str = w3m_dom_get_attribute(elem, "checked"); + JSValue checked = JS_NewBool(ctx, checked_str != NULL); + JS_SetPropertyStr(ctx, js_elem, "checked", checked); + + /* Note: disabled not supported in w3m's HTML attribute constants */ + JS_SetPropertyStr(ctx, js_elem, "disabled", JS_NewBool(ctx, 0)); + + const char *readonly_str = w3m_dom_get_attribute(elem, "readonly"); + JSValue readonly = JS_NewBool(ctx, readonly_str != NULL); + JS_SetPropertyStr(ctx, js_elem, "readonly", readonly); + + /* Input methods */ + JS_SetPropertyStr(ctx, js_elem, "focus", + JS_NewCFunction(ctx, js_input_focus, "focus", 0)); + JS_SetPropertyStr(ctx, js_elem, "blur", + JS_NewCFunction(ctx, js_input_blur, "blur", 0)); + JS_SetPropertyStr(ctx, js_elem, "click", + JS_NewCFunction(ctx, js_input_click, "click", 0)); + + } else if (strcmp(elem->tagName, "TEXTAREA") == 0) { + /* Textarea element properties */ + const char *name_str = w3m_dom_get_attribute(elem, "name"); + JS_SetPropertyStr(ctx, js_elem, "name", name_str ? JS_NewString(ctx, name_str) : JS_NewString(ctx, "")); + + JSValue value = elem->textContent ? JS_NewString(ctx, elem->textContent) : JS_NewString(ctx, ""); + JS_SetPropertyStr(ctx, js_elem, "value", value); + + /* Note: placeholder not supported in w3m's HTML attribute constants */ + JS_SetPropertyStr(ctx, js_elem, "placeholder", JS_NewString(ctx, "")); + + /* Textarea methods */ + JS_SetPropertyStr(ctx, js_elem, "focus", + JS_NewCFunction(ctx, js_textarea_focus, "focus", 0)); + JS_SetPropertyStr(ctx, js_elem, "blur", + JS_NewCFunction(ctx, js_textarea_blur, "blur", 0)); + + } else if (strcmp(elem->tagName, "SELECT") == 0) { + /* Select element properties */ + const char *name_str = w3m_dom_get_attribute(elem, "name"); + JS_SetPropertyStr(ctx, js_elem, "name", name_str ? JS_NewString(ctx, name_str) : JS_NewString(ctx, "")); + + const char *multiple_str = w3m_dom_get_attribute(elem, "multiple"); + JSValue multiple = JS_NewBool(ctx, multiple_str != NULL); + JS_SetPropertyStr(ctx, js_elem, "multiple", multiple); + + /* Select methods */ + JS_SetPropertyStr(ctx, js_elem, "focus", + JS_NewCFunction(ctx, js_select_focus, "focus", 0)); + JS_SetPropertyStr(ctx, js_elem, "blur", + JS_NewCFunction(ctx, js_select_blur, "blur", 0)); + } + } + return js_elem; } @@ -1059,4 +1161,243 @@ w3m_dom_find_anchor_element_recursive(W3MElement *elem, Anchor *anchor) return NULL; } +/* Phase 4: Form Element JavaScript API Functions */ + +static JSValue +js_form_submit(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + W3MElement *form_elem = get_element_from_js_value(ctx, this_val); + if (!form_elem) return JS_UNDEFINED; + + /* Phase 4: JavaScript form submission implementation */ + if (strcmp(form_elem->tagName, "FORM") != 0) { + return JS_UNDEFINED; /* Not a form element */ + } + + /* Find a form item that belongs to this form */ + if (w3m_dom_submit_form(form_elem)) { + /* Form submitted successfully */ + return JS_UNDEFINED; + } else { + /* Form submission failed */ + return JS_UNDEFINED; + } +} + +static JSValue +js_form_reset(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + W3MElement *form_elem = get_element_from_js_value(ctx, this_val); + if (!form_elem) return JS_UNDEFINED; + + /* Phase 4: JavaScript form reset implementation */ + if (strcmp(form_elem->tagName, "FORM") != 0) { + return JS_UNDEFINED; /* Not a form element */ + } + + /* Reset all form elements to their initial values */ + w3m_dom_reset_form(form_elem); + + return JS_UNDEFINED; +} + +static JSValue +js_input_focus(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + W3MElement *input_elem = get_element_from_js_value(ctx, this_val); + if (!input_elem) return JS_UNDEFINED; + + /* Phase 4 stub: Input focus will be implemented with w3m's form navigation */ + /* TODO: Move cursor to this input element */ + + return JS_UNDEFINED; +} + +static JSValue +js_input_blur(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + W3MElement *input_elem = get_element_from_js_value(ctx, this_val); + if (!input_elem) return JS_UNDEFINED; + + /* Phase 4 stub: Input blur */ + /* TODO: Remove focus from this input element */ + + return JS_UNDEFINED; +} + +static JSValue +js_input_click(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + W3MElement *input_elem = get_element_from_js_value(ctx, this_val); + if (!input_elem) return JS_UNDEFINED; + + /* Phase 4 stub: Input click simulation */ + /* TODO: Simulate click event on this input element */ + + return JS_UNDEFINED; +} + +static JSValue +js_textarea_focus(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + W3MElement *textarea_elem = get_element_from_js_value(ctx, this_val); + if (!textarea_elem) return JS_UNDEFINED; + + /* Phase 4 stub: Textarea focus */ + /* TODO: Move cursor to this textarea element */ + + return JS_UNDEFINED; +} + +static JSValue +js_textarea_blur(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + W3MElement *textarea_elem = get_element_from_js_value(ctx, this_val); + if (!textarea_elem) return JS_UNDEFINED; + + /* Phase 4 stub: Textarea blur */ + /* TODO: Remove focus from this textarea element */ + + return JS_UNDEFINED; +} + +static JSValue +js_select_focus(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + W3MElement *select_elem = get_element_from_js_value(ctx, this_val); + if (!select_elem) return JS_UNDEFINED; + + /* Phase 4 stub: Select focus */ + /* TODO: Move cursor to this select element */ + + return JS_UNDEFINED; +} + +static JSValue +js_select_blur(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + W3MElement *select_elem = get_element_from_js_value(ctx, this_val); + if (!select_elem) return JS_UNDEFINED; + + /* Phase 4 stub: Select blur */ + /* TODO: Remove focus from this select element */ + + return JS_UNDEFINED; +} + +/* Phase 4: Form Submission Implementation */ + +static int +w3m_dom_submit_form(W3MElement *form_elem) +{ + extern TabBuffer *CurrentTab; + + if (!form_elem || !Currentbuf || !Currentbuf->formitem) return 0; + + /* Find the first form element that belongs to this form */ + const char *form_name = w3m_dom_get_attribute(form_elem, "name"); + const char *form_action = w3m_dom_get_attribute(form_elem, "action"); + + for (int i = 0; i < Currentbuf->formitem->nanchor; i++) { + Anchor *a = &Currentbuf->formitem->anchors[i]; + struct form_item_list *fi = (struct form_item_list *)a->url; + + if (!fi || !fi->parent) continue; + + /* Check if this form item belongs to our form */ + int form_match = 0; + if (form_name && fi->parent->name && strcmp(form_name, fi->parent->name) == 0) { + form_match = 1; + } else if (form_action && fi->parent->action && + strcmp(form_action, fi->parent->action->ptr) == 0) { + form_match = 1; + } else if (!form_name && !form_action) { + /* If no name/action specified, use first available form */ + form_match = 1; + } + + if (form_match) { + /* Trigger form submission using w3m's existing system */ + /* We need to simulate the submission by setting the current buffer position + * to this form element and calling the submission function */ + + /* Set buffer position to this form item */ + Currentbuf->submit = a; + + /* Return success - the actual submission will be processed by w3m's main loop */ + return 1; + } + } + + return 0; /* No matching form found */ +} + +static int +w3m_dom_reset_form(W3MElement *form_elem) +{ + extern TabBuffer *CurrentTab; + + if (!form_elem || !Currentbuf || !Currentbuf->formitem) return 0; + + /* Find all form elements that belong to this form and reset them */ + const char *form_name = w3m_dom_get_attribute(form_elem, "name"); + const char *form_action = w3m_dom_get_attribute(form_elem, "action"); + + int reset_count = 0; + + for (int i = 0; i < Currentbuf->formitem->nanchor; i++) { + Anchor *a = &Currentbuf->formitem->anchors[i]; + struct form_item_list *fi = (struct form_item_list *)a->url; + + if (!fi || !fi->parent) continue; + + /* Check if this form item belongs to our form */ + int form_match = 0; + if (form_name && fi->parent->name && strcmp(form_name, fi->parent->name) == 0) { + form_match = 1; + } else if (form_action && fi->parent->action && + strcmp(form_action, fi->parent->action->ptr) == 0) { + form_match = 1; + } else if (!form_name && !form_action) { + /* If no name/action specified, reset first available form */ + form_match = 1; + } + + if (form_match) { + /* Reset this form element to its initial value */ + switch (fi->type) { + case FORM_INPUT_TEXT: + case FORM_INPUT_PASSWORD: + case FORM_TEXTAREA: + if (fi->init_value) { + fi->value = Strdup(fi->init_value); + } else { + fi->value = Strnew(); + } + break; + + case FORM_INPUT_CHECKBOX: + case FORM_INPUT_RADIO: + fi->checked = fi->init_checked; + break; + +#ifdef MENU_SELECT + case FORM_SELECT: + fi->selected = fi->init_selected; + if (fi->init_label) { + fi->label = Strdup(fi->init_label); + } + break; +#endif + } + + /* Update the buffer display */ + formUpdateBuffer(a, Currentbuf, fi); + reset_count++; + } + } + + return reset_count; +} + #endif /* USE_JAVASCRIPT */ \ No newline at end of file diff --git a/js/w3m_dom.h b/js/w3m_dom.h index a8cffe6..4bf8be8 100644 --- a/js/w3m_dom.h +++ b/js/w3m_dom.h @@ -18,7 +18,7 @@ struct _Buffer; struct Line; struct Anchor; -struct FormItem; +struct form_item_list; /* Simplified DOM Element Structure */ typedef struct W3MElement { @@ -37,7 +37,7 @@ typedef struct W3MElement { struct Line *line; /* Associated line in buffer */ int line_pos; /* Position within line */ struct Anchor *anchor; /* If element is interactive */ - struct FormItem *form_item; /* If element is form control */ + struct form_item_list *form_item; /* If element is form control */ /* Attributes and content */ struct { diff --git a/js/w3m_javascript.c b/js/w3m_javascript.c index f41c414..5593ddb 100644 --- a/js/w3m_javascript.c +++ b/js/w3m_javascript.c @@ -22,6 +22,21 @@ int w3m_js_timeout = 5000; /* 5 second timeout */ int w3m_js_memory_limit = 8388608; /* 8MB memory limit */ int w3m_js_network_enabled = 1; +/* Debug console.log implementation */ +static JSValue +w3m_js_console_log(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + if (argc > 0) { + const char *str = JS_ToCString(ctx, argv[0]); + if (str) { + /* For now, just add to debug - later we might display this somewhere */ + fprintf(stderr, "JS: %s\n", str); + JS_FreeCString(ctx, str); + } + } + return JS_UNDEFINED; +} + /* JavaScript Context Management */ W3MJSContext * @@ -49,6 +64,12 @@ w3m_js_create_context(void) /* Get global object */ ctx->global_obj = JS_GetGlobalObject(ctx->context); + /* Add basic console.log support for debugging */ + JSValue console = JS_NewObject(ctx->context); + JS_SetPropertyStr(ctx->context, console, "log", + JS_NewCFunction(ctx->context, w3m_js_console_log, "log", 1)); + JS_SetPropertyStr(ctx->context, ctx->global_obj, "console", console); + /* Initialize empty document and window objects */ ctx->document_obj = JS_NULL; ctx->window_obj = JS_NULL; @@ -260,10 +281,11 @@ w3m_js_value_to_string(W3MJSContext *ctx, JSValue val) void w3m_js_report_error(W3MJSContext *ctx, const char *msg) { - /* For now, just ignore errors silently */ - /* In future, could log to status line or debug output */ + /* Report JavaScript errors to stderr for debugging */ + if (msg) { + fprintf(stderr, "JavaScript Error: %s\n", msg); + } (void)ctx; - (void)msg; } #endif /* USE_JAVASCRIPT */ \ No newline at end of file