From 20ea5ea00fce47a834421d87d800226a5b7441cd Mon Sep 17 00:00:00 2001 From: Phil Mellor Date: Mon, 30 Dec 2002 22:56:30 +0000 Subject: [project @ 2002-12-30 22:56:30 by monkeyson] Forms are now interactive - user can manipulate checkbox, radio, text, textarea, select elements. svn path=/import/netsurf/; revision=76 --- desktop/browser.c | 147 +++++++++++++++++-- desktop/browser.h | 18 ++- desktop/gui.h | 3 +- render/box.c | 315 +++++++++++++++++++++++++++++++++++++--- render/box.h | 44 +++++- render/layout.c | 12 +- riscos/gui.c | 421 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- riscos/gui.h | 3 +- 8 files changed, 911 insertions(+), 52 deletions(-) diff --git a/desktop/browser.c b/desktop/browser.c index 7c1ce1226..be8cd1e0e 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -1,5 +1,5 @@ /** - * $Id: browser.c,v 1.18 2002/12/30 21:14:29 bursa Exp $ + * $Id: browser.c,v 1.19 2002/12/30 22:56:30 monkeyson Exp $ */ #include "netsurf/riscos/font.h" @@ -18,14 +18,6 @@ #include #include -struct box_selection -{ - struct box* box; - int actual_x; - int actual_y; - int plot_index; -}; - void browser_window_text_selection(struct browser_window* bw, int click_x, int click_y, int click_type); void browser_window_clear_text_selection(struct browser_window* bw); void browser_window_change_text_selection(struct browser_window* bw, struct box_position* new_start, struct box_position* new_end); @@ -181,7 +173,7 @@ void content_html_reformat(struct content* c, int width) c->data.html.fonts = font_new_set(); LOG(("XML to box")); - xml_to_box(c->data.html.markup, c->data.html.style, c->data.html.stylesheet, &selector, 0, c->data.html.layout, 0, 0, c->data.html.fonts, 0, 0); + xml_to_box(c->data.html.markup, c->data.html.style, c->data.html.stylesheet, &selector, 0, c->data.html.layout, 0, 0, c->data.html.fonts, 0, 0, 0, 0, &c->data.html.elements); LOG(("Layout document")); layout_document(c->data.html.layout->children, (unsigned long)width); @@ -519,7 +511,14 @@ int browser_window_message(struct browser_window* bw, struct browser_message* ms bw->future_content->main_fetch = NULL; previous_safety = gui_window_set_redraw_safety(bw->window, UNSAFE); if (bw->current_content != NULL) + { + int gc; + for (gc = 0; gc < bw->current_content->data.html.elements.numGadgets; gc++) + { + gui_remove_gadget(bw->current_content->data.html.elements.gadgets[gc]); + } cache_free(bw->current_content); + } bw->current_content = bw->future_content; bw->future_content = NULL; browser_window_reformat(bw); @@ -536,6 +535,131 @@ int browser_window_message(struct browser_window* bw, struct browser_message* ms return 0; } +void clear_radio_gadgets(struct browser_window* bw, struct box* box, struct gui_gadget* group) +{ + struct box* c; + if (box == NULL) + return; + if (box->gadget != 0) + { + if (box->gadget->type == GADGET_RADIO && box->gadget->name != 0 && box->gadget != group) + { + if (strcmp(box->gadget->name, group->name) == 0) + { + if (box->gadget->data.radio.selected) + { + box->gadget->data.radio.selected = 0; + gui_redraw_gadget(bw, box->gadget); + } + } + } + } + for (c = box->children; c != 0; c = c->next) + if (c->type != BOX_FLOAT_LEFT && c->type != BOX_FLOAT_RIGHT) + clear_radio_gadgets(bw, c, group); + + for (c = box->float_children; c != 0; c = c->next_float) + clear_radio_gadgets(bw, c, group); +} + +void gui_redraw_gadget2(struct browser_window* bw, struct box* box, struct gui_gadget* g, int x, int y) +{ + struct box* c; + + if (box->gadget == g) + { + gui_window_redraw(bw->window, x + box->x, y + box->y, x + box->x + box->width, y+box->y + box->height); + } + + for (c = box->children; c != 0; c = c->next) + if (c->type != BOX_FLOAT_LEFT && c->type != BOX_FLOAT_RIGHT) + gui_redraw_gadget2(bw, c, g, box->x + x, box->y + y); + + for (c = box->float_children; c != 0; c = c->next_float) + gui_redraw_gadget2(bw, c, g, box->x + x, box->y + y); +} + +void gui_redraw_gadget(struct browser_window* bw, struct gui_gadget* g) +{ + gui_redraw_gadget2(bw, bw->current_content->data.html.layout->children, g, 0, 0); +} + +void browser_window_gadget_select(struct browser_window* bw, struct gui_gadget* g, int item) +{ + struct formoption* o; + int count; + + count = 0; + o = g->data.select.items; + while (o != NULL) + { + if (g->data.select.multiple == 0) + o->selected = 0; + if (count == item) + o->selected = !(o->selected); + o = o->next; + count++; + } + + gui_redraw_gadget(bw, g); +} + +int browser_window_gadget_click(struct browser_window* bw, int click_x, int click_y) +{ + struct box_selection* click_boxes; + int found, plot_index; + int i; + + found = 0; + click_boxes = NULL; + plot_index = 0; + + box_under_area(bw->current_content->data.html.layout->children, + click_x, click_y, 0, 0, &click_boxes, &found, &plot_index); + + if (found == 0) + return 0; + + for (i = found - 1; i >= 0; i--) + { + if (click_boxes[i].box->type == BOX_INLINE && click_boxes[i].box->gadget != 0) + { + struct gui_gadget* g = click_boxes[i].box->gadget; + + /* gadget clicked */ + switch (g->type) + { + case GADGET_SELECT: + gui_gadget_combo(bw, g, click_x, click_y); + break; + case GADGET_CHECKBOX: + g->data.checkbox.selected = !g->data.checkbox.selected; + gui_redraw_gadget(bw, g); + break; + case GADGET_RADIO: + clear_radio_gadgets(bw, bw->current_content->data.html.layout->children, g); + g->data.radio.selected = -1; + gui_redraw_gadget(bw, g); + break; + case GADGET_ACTIONBUTTON: + g->data.actionbutt.pressed = -1; + gui_redraw_gadget(bw, g); + break; + case GADGET_TEXTAREA: + gui_edit_textarea(bw, g); + break; + case GADGET_TEXTBOX: + gui_edit_textbox(bw, g); + break; + } + + xfree(click_boxes); + return 1; + } + } + xfree(click_boxes); +} + int browser_window_action(struct browser_window* bw, struct browser_action* act) { switch (act->type) @@ -544,6 +668,7 @@ int browser_window_action(struct browser_window* bw, struct browser_action* act) browser_window_follow_link(bw, act->data.mouse.x, act->data.mouse.y, 0); break; case act_MOUSE_CLICK: + return browser_window_gadget_click(bw, act->data.mouse.x, act->data.mouse.y); break; case act_CLEAR_SELECTION: browser_window_text_selection(bw, act->data.mouse.x, act->data.mouse.y, 0); @@ -560,6 +685,8 @@ int browser_window_action(struct browser_window* bw, struct browser_action* act) case act_FOLLOW_LINK_NEW_WINDOW: browser_window_follow_link(bw, act->data.mouse.x, act->data.mouse.y, 2); break; + case act_GADGET_SELECT: + browser_window_gadget_select(bw, act->data.gadget_select.g, act->data.gadget_select.item); default: break; } diff --git a/desktop/browser.h b/desktop/browser.h index 50fc3faf7..9da3b1811 100644 --- a/desktop/browser.h +++ b/desktop/browser.h @@ -1,5 +1,5 @@ /** - * $Id: browser.h,v 1.4 2002/11/02 22:28:05 bursa Exp $ + * $Id: browser.h,v 1.5 2002/12/30 22:56:30 monkeyson Exp $ */ #ifndef _NETSURF_DESKTOP_BROWSER_H_ @@ -60,6 +60,7 @@ struct content int selected; /* 0 = unselected, 1 = selected */ } text_selection; struct font_set* fonts; + struct page_elements elements; } html; } data; struct fetch* main_fetch; @@ -124,7 +125,8 @@ struct browser_action enum { act_UNKNOWN, act_MOUSE_AT, act_MOUSE_CLICK, act_START_NEW_SELECTION, act_ALTER_SELECTION, act_CLEAR_SELECTION, - act_FOLLOW_LINK, act_FOLLOW_LINK_NEW_WINDOW + act_FOLLOW_LINK, act_FOLLOW_LINK_NEW_WINDOW, + act_GADGET_SELECT } type; union { struct { @@ -132,9 +134,21 @@ struct browser_action int y; action_buttons buttons; } mouse; + struct { + struct gui_gadget* g; + int item; + } gadget_select; } data; }; +struct box_selection +{ + struct box* box; + int actual_x; + int actual_y; + int plot_index; +}; + /* public functions */ struct browser_window* create_browser_window(int flags, int width, int height); diff --git a/desktop/gui.h b/desktop/gui.h index 6a6335d1a..4e6c7975a 100644 --- a/desktop/gui.h +++ b/desktop/gui.h @@ -1,5 +1,5 @@ /** - * $Id: gui.h,v 1.2 2002/10/15 10:41:12 monkeyson Exp $ + * $Id: gui.h,v 1.3 2002/12/30 22:56:30 monkeyson Exp $ */ #ifndef _NETSURF_DESKTOP_GUI_H_ @@ -45,4 +45,5 @@ int gui_file_to_filename(char* location, char* actual_filename, int size); void gui_window_start_throbber(gui_window* g); void gui_window_stop_throbber(gui_window* g); +void gui_gadget_combo(struct browser_window* bw, struct gui_gadget* g, int mx, int my); #endif diff --git a/render/box.c b/render/box.c index e6726b02b..65694810b 100644 --- a/render/box.c +++ b/render/box.c @@ -1,5 +1,5 @@ /** - * $Id: box.c,v 1.24 2002/12/30 02:06:03 monkeyson Exp $ + * $Id: box.c,v 1.25 2002/12/30 22:56:30 monkeyson Exp $ */ #include @@ -19,7 +19,7 @@ * internal functions */ -struct box* box_gui_gadget(xmlNode * n, struct css_style* style); +struct box* input(xmlNode * n, struct css_style* style, struct form* current_form); void box_add_child(struct box * parent, struct box * child); struct box * box_create(xmlNode * node, box_type type, struct css_style * style, @@ -30,7 +30,9 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, struct css_selector ** selector, unsigned int depth, struct box * parent, struct box * inline_container, const char *href, struct font_set *fonts, - struct gui_gadget* current_select, struct formoption* current_option); + struct gui_gadget* current_select, struct formoption* current_option, + struct gui_gadget* current_textarea, struct form* current_form, + struct page_elements* elements); struct css_style * box_get_style(struct css_stylesheet * stylesheet, struct css_style * parent_style, xmlNode * n, struct css_selector * selector, unsigned int depth); void box_normalise_block(struct box *block); @@ -129,11 +131,14 @@ void xml_to_box(xmlNode * n, struct css_style * parent_style, struct css_selector ** selector, unsigned int depth, struct box * parent, struct box * inline_container, const char *href, struct font_set *fonts, - struct gui_gadget* current_select, struct formoption* current_option) + struct gui_gadget* current_select, struct formoption* current_option, + struct gui_gadget* current_textarea, struct form* current_form, + struct page_elements* elements) { LOG(("node %p", n)); convert_xml_to_box(n, parent_style, stylesheet, - selector, depth, parent, inline_container, href, fonts, current_select, current_option); + selector, depth, parent, inline_container, href, fonts, current_select, current_option, + current_textarea, current_form, elements); LOG(("normalising")); box_normalise_block(parent->children); } @@ -149,7 +154,9 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, struct css_selector ** selector, unsigned int depth, struct box * parent, struct box * inline_container, const char *href, struct font_set *fonts, - struct gui_gadget* current_select, struct formoption* current_option) + struct gui_gadget* current_select, struct formoption* current_option, + struct gui_gadget* current_textarea, struct form* current_form, + struct page_elements* elements) { struct box * box; struct box * inline_container_c; @@ -184,10 +191,20 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, } } - if (n->type == XML_TEXT_NODE || + if (n->type == XML_ELEMENT_NODE && (strcmp((const char *) n->name, "form") == 0)) + { + struct form* form = box_form(n); + if (form != NULL) + { + current_form = form; + add_form_element(elements, form); + } + } + else if (n->type == XML_TEXT_NODE || (n->type == XML_ELEMENT_NODE && (strcmp((const char *) n->name, "input") == 0)) || (n->type == XML_ELEMENT_NODE && (strcmp((const char *) n->name, "select") == 0)) || (n->type == XML_ELEMENT_NODE && (strcmp((const char *) n->name, "option") == 0)) || + (n->type == XML_ELEMENT_NODE && (strcmp((const char *) n->name, "textarea") == 0)) || (n->type == XML_ELEMENT_NODE && (strcmp((const char *) n->name, "img") == 0)) || (n->type == XML_ELEMENT_NODE && (style->float_ == CSS_FLOAT_LEFT || style->float_ == CSS_FLOAT_RIGHT))) { @@ -199,9 +216,14 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, } if (n->type == XML_TEXT_NODE) { LOG2("TEXT NODE"); - if (current_option != 0) + if (current_textarea != 0) { char* thistext = squash_whitespace(tolat1(n->content)); + textarea_addtext(current_textarea, thistext); + } + else if (current_option != 0) + { + char* thistext = (tolat1(n->content)); LOG2("adding to option"); option_addtext(current_option, thistext); LOG2("freeing thistext"); @@ -224,25 +246,41 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, } } else if (strcmp((const char *) n->name, "img") == 0) { LOG2(("image")); - box = box_image(n, parent_style); + box = box_image(n, parent_style, href); + if (box != NULL) + { + box_add_child(inline_container, box); + add_img_element(elements, box->img); + } + } else if (strcmp((const char *) n->name, "textarea") == 0) { + LOG2(("textarea")); + box = box_textarea(n, parent_style, current_form); if (box != NULL) + { box_add_child(inline_container, box); + current_textarea = box->gadget; + add_gadget_element(elements, box->gadget); + } } else if (strcmp((const char *) n->name, "select") == 0) { LOG2(("select")); - box = box_select(n, parent_style); + box = box_select(n, parent_style, current_form); if (box != NULL) { box_add_child(inline_container, box); current_select = box->gadget; + add_gadget_element(elements, box->gadget); } } else if (strcmp((const char *) n->name, "option") == 0) { LOG2(("option")); current_option = box_option(n, parent_style, current_select); } else if (strcmp((const char *) n->name, "input") == 0) { LOG2(("input")); - box = box_gui_gadget(n, parent_style); + box = box_input(n, parent_style, current_form, elements); if (box != NULL) + { box_add_child(inline_container, box); + add_gadget_element(elements, box->gadget); + } } else { LOG2(("float")); box = box_create(0, BOX_FLOAT_LEFT, 0, href); @@ -264,14 +302,16 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, for (c = n->children; c != 0; c = c->next) inline_container_c = convert_xml_to_box(c, style, stylesheet, selector, depth + 1, box, inline_container_c, - href, fonts, current_select, current_option); + href, fonts, current_select, current_option, + current_textarea, current_form, elements); inline_container = 0; break; case CSS_DISPLAY_INLINE: /* inline elements get no box, but their children do */ for (c = n->children; c != 0; c = c->next) inline_container = convert_xml_to_box(c, style, stylesheet, selector, depth + 1, parent, inline_container, - href, fonts, current_select, current_option); + href, fonts, current_select, current_option, + current_textarea, current_form, elements); break; case CSS_DISPLAY_TABLE: box = box_create(n, BOX_TABLE, style, href); @@ -279,7 +319,8 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, for (c = n->children; c != 0; c = c->next) convert_xml_to_box(c, style, stylesheet, selector, depth + 1, box, 0, - href, fonts, current_select, current_option); + href, fonts, current_select, current_option, + current_textarea, current_form, elements); inline_container = 0; break; case CSS_DISPLAY_TABLE_ROW_GROUP: @@ -291,7 +332,8 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, for (c = n->children; c != 0; c = c->next) inline_container_c = convert_xml_to_box(c, style, stylesheet, selector, depth + 1, box, inline_container_c, - href, fonts, current_select, current_option); + href, fonts, current_select, current_option, + current_textarea, current_form, elements); inline_container = 0; break; case CSS_DISPLAY_TABLE_ROW: @@ -300,7 +342,8 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, for (c = n->children; c != 0; c = c->next) convert_xml_to_box(c, style, stylesheet, selector, depth + 1, box, 0, - href, fonts, current_select, current_option); + href, fonts, current_select, current_option, + current_textarea, current_form, elements); inline_container = 0; break; case CSS_DISPLAY_TABLE_CELL: @@ -315,7 +358,8 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, for (c = n->children; c != 0; c = c->next) inline_container_c = convert_xml_to_box(c, style, stylesheet, selector, depth + 1, box, inline_container_c, - href, fonts, current_select, current_option); + href, fonts, current_select, current_option, + current_textarea, current_form, elements); inline_container = 0; break; default: @@ -735,6 +779,55 @@ void box_normalise_inline_container(struct box *cont) } +void gadget_free(struct gui_gadget* g) +{ + struct formoption* o; + + if (g->name != 0) + xfree(g->name); + + switch (g->type) + { + case GADGET_HIDDEN: + if (g->data.hidden.value != 0) + xfree(g->data.hidden.value); + break; + case GADGET_RADIO: + if (g->data.checkbox.value != 0) + xfree(g->data.radio.value); + break; + case GADGET_CHECKBOX: + if (g->data.checkbox.value != 0) + xfree(g->data.checkbox.value); + break; + case GADGET_TEXTAREA: + if (g->data.textarea.text != 0) + xfree(g->data.textarea.text); + break; + case GADGET_TEXTBOX: + gui_remove_gadget(g); + if (g->data.textbox.text != 0) + xfree(g->data.textbox.text); + break; + case GADGET_ACTIONBUTTON: + if (g->data.actionbutt.label != 0) + xfree(g->data.actionbutt.label); + break; + case GADGET_SELECT: + o = g->data.select.items; + while (o != NULL) + { + if (o->text != 0) + xfree(o->text); + if (o->value != 0) + xfree(o->value); + xfree(o); + o = o->next; + } + break; + } +} + /** * free a box tree recursively */ @@ -754,7 +847,7 @@ void box_free(struct box *box) // free(box->style); if (box->gadget != 0) { - /* gadget_free(box->gadget); */ + gadget_free(box->gadget); free((void*)box->gadget); } @@ -775,12 +868,12 @@ void box_free(struct box *box) } } -struct box* box_image(xmlNode * n, struct css_style* style) +struct box* box_image(xmlNode * n, struct css_style* style, char* href) { struct box* box = 0; char* s; - box = box_create(n, BOX_INLINE, style, NULL); + box = box_create(n, BOX_INLINE, style, href); box->img = xcalloc(1, sizeof(struct img)); box->text = 0; @@ -811,7 +904,47 @@ struct box* box_image(xmlNode * n, struct css_style* style) return box; } -struct box* box_select(xmlNode * n, struct css_style* style) +struct box* box_textarea(xmlNode* n, struct css_style* style, struct form* current_form) +{ + struct box* box = 0; + char* s; + + LOG2("creating box"); + box = box_create(n, BOX_INLINE, style, NULL); + LOG2("creating gadget"); + box->gadget = xcalloc(1, sizeof(struct gui_gadget)); + box->gadget->type = GADGET_TEXTAREA; + box->gadget->form = current_form; + + box->text = 0; + box->length = 0; + box->font = 0; + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "cols"))) + { + box->gadget->data.textarea.cols = atoi(s); + free(s); + } + else + box->gadget->data.textarea.cols = 40; + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "rows"))) + { + box->gadget->data.textarea.rows = atoi(s); + free(s); + } + else + box->gadget->data.textarea.rows = 16; + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "name"))) + { + box->gadget->name = s; + } + + return box; +} + +struct box* box_select(xmlNode * n, struct css_style* style, struct form* current_form) { struct box* box = 0; char* s; @@ -821,6 +954,7 @@ struct box* box_select(xmlNode * n, struct css_style* style) LOG2("creating gadget"); box->gadget = xcalloc(1, sizeof(struct gui_gadget)); box->gadget->type = GADGET_SELECT; + box->gadget->form = current_form; box->text = 0; box->length = 0; @@ -834,6 +968,14 @@ struct box* box_select(xmlNode * n, struct css_style* style) else box->gadget->data.select.size = 1; + if ((s = (char *) xmlGetProp(n, (xmlChar *) "multiple"))) { + box->gadget->data.select.multiple = 1; + } + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "name"))) { + box->gadget->name = s; + } + box->gadget->data.select.items = NULL; box->gadget->data.select.numitems = 0; /* to do: multiple, name */ @@ -844,7 +986,9 @@ struct box* box_select(xmlNode * n, struct css_style* style) struct formoption* box_option(xmlNode* n, struct css_style* style, struct gui_gadget* current_select) { struct formoption* option; + char* s; assert(current_select != 0); + LOG2("realloc option"); if (current_select->data.select.items == 0) { @@ -862,11 +1006,35 @@ struct formoption* box_option(xmlNode* n, struct css_style* style, struct gui_ga } /* TO DO: set selected / value here */ + if ((s = (char *) xmlGetProp(n, (xmlChar *) "selected"))) { + option->selected = -1; + free(s); + } + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "value"))) { + option->value = s; + } LOG2("returning"); return option; } +void textarea_addtext(struct gui_gadget* textarea, char* text) +{ + assert (textarea != 0); + assert (text != 0); + + if (textarea->data.textarea.text == 0) + { + textarea->data.textarea.text = strdup(text); + } + else + { + textarea->data.textarea.text = xrealloc(textarea->data.textarea.text, strlen(textarea->data.textarea.text) + strlen(text) + 1); + strcat(textarea->data.textarea.text, text); + } +} + void option_addtext(struct formoption* option, char* text) { assert(option != 0); @@ -887,7 +1055,7 @@ void option_addtext(struct formoption* option, char* text) return; } -struct box* box_gui_gadget(xmlNode * n, struct css_style* style) +struct box* box_input(xmlNode * n, struct css_style* style, struct form* current_form, struct page_elements* elements) { struct box* box = 0; char* s; @@ -895,6 +1063,53 @@ struct box* box_gui_gadget(xmlNode * n, struct css_style* style) if ((type = (char *) xmlGetProp(n, (xmlChar *) "type"))) { + if (strcmp(type, "hidden") == 0) + { + struct gui_gadget* g = xcalloc(1, sizeof(struct gui_gadget)); + g->type = GADGET_HIDDEN; + g->form = current_form; + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "value"))) { + g->data.hidden.value = s; + } + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "name"))) { + g->name = s; + } + } + if (strcmp(type, "checkbox") == 0 || strcmp(type, "radio") == 0) + { + box = box_create(n, BOX_INLINE, style, NULL); + box->gadget = xcalloc(1, sizeof(struct gui_gadget)); + if (type[0] == 'c') + box->gadget->type = GADGET_CHECKBOX; + else + box->gadget->type = GADGET_RADIO; + box->gadget->form = current_form; + + box->text = 0; + box->length = 0; + box->font = 0; + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "checked"))) { + if (type[0] == 'c') + box->gadget->data.checkbox.selected = -1; + else + box->gadget->data.radio.selected = -1; + free(s); + } + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "value"))) { + if (type[0] == 'c') + box->gadget->data.checkbox.value = s; + else + box->gadget->data.radio.value = s; + } + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "name"))) { + box->gadget->name = s; + } + } if (strcmp(type, "submit") == 0 || strcmp(type, "reset") == 0) { //style->display = CSS_DISPLAY_BLOCK; @@ -902,6 +1117,7 @@ struct box* box_gui_gadget(xmlNode * n, struct css_style* style) box = box_create(n, BOX_INLINE, style, NULL); box->gadget = xcalloc(1, sizeof(struct gui_gadget)); box->gadget->type = GADGET_ACTIONBUTTON; + box->gadget->form = current_form; box->text = 0; box->length = 0; @@ -915,6 +1131,10 @@ struct box* box_gui_gadget(xmlNode * n, struct css_style* style) box->gadget->data.actionbutt.label = strdup(type); box->gadget->data.actionbutt.label[0] = toupper(type[0]); } + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "name"))) { + box->gadget->name = s; + } } if (strcmp(type, "text") == 0 || strcmp(type, "password") == 0) { @@ -923,12 +1143,13 @@ struct box* box_gui_gadget(xmlNode * n, struct css_style* style) box = box_create(n, BOX_INLINE, style, NULL); box->gadget = xcalloc(1, sizeof(struct gui_gadget)); box->gadget->type = GADGET_TEXTBOX; + box->gadget->form = current_form; box->text = 0; box->length = 0; box->font = 0; - box->gadget->data.textbox.maxlength = 255; + box->gadget->data.textbox.maxlength = 32; if ((s = (char *) xmlGetProp(n, (xmlChar *) "maxlength"))) { box->gadget->data.textbox.maxlength = atoi(s); free(s); @@ -948,8 +1169,56 @@ struct box* box_gui_gadget(xmlNode * n, struct css_style* style) free(s); } + if ((s = (char *) xmlGetProp(n, (xmlChar *) "name"))) { + box->gadget->name = s; + } } free(type); } return box; } + +struct form* box_form(xmlNode* n) +{ + struct form* form; + char* s; + + form = xcalloc(1, sizeof(struct form*)); + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "action"))) { + form->action = s; + } + + if ((s = (char *) xmlGetProp(n, (xmlChar *) "method"))) { + if (strcmp(s, "get") == 0) + form->action = method_GET; + else if (strcmp(s, "post") == 0) + form->action = method_POST; + xfree(s); + } + + return form; +} + +void add_form_element(struct page_elements* pe, struct form* f) +{ + pe->forms = xrealloc(pe->forms, (pe->numForms + 1) * sizeof(struct form*)); + pe->forms[pe->numForms] = f; + pe->numForms++; +} + +void add_gadget_element(struct page_elements* pe, struct gadget* g) +{ + pe->gadgets = xrealloc(pe->gadgets, (pe->numGadgets + 1) * sizeof(struct gui_gadget*)); + pe->gadgets[pe->numGadgets] = g; + pe->numGadgets++; +} + +void add_img_element(struct page_elements* pe, struct img* i) +{ + pe->images = xrealloc(pe->images, (pe->numImages + 1) * sizeof(struct img*)); + pe->images[pe->numImages] = i; + pe->numImages++; +} + + diff --git a/render/box.h b/render/box.h index e978662ad..eb6589118 100644 --- a/render/box.h +++ b/render/box.h @@ -1,5 +1,5 @@ /** - * $Id: box.h,v 1.14 2002/12/30 02:06:03 monkeyson Exp $ + * $Id: box.h,v 1.15 2002/12/30 22:56:30 monkeyson Exp $ */ #ifndef _NETSURF_RENDER_BOX_H_ @@ -35,9 +35,14 @@ struct formoption { }; struct gui_gadget { - enum { GADGET_HIDDEN = 0, GADGET_TEXTBOX, GADGET_RADIO, GADGET_OPTION, + enum { GADGET_HIDDEN = 0, GADGET_TEXTBOX, GADGET_RADIO, GADGET_CHECKBOX, GADGET_SELECT, GADGET_TEXTAREA, GADGET_ACTIONBUTTON } type; + char* name; + struct form* form; union { + struct { + char* value; + } hidden; struct { int maxlength; char* text; @@ -45,6 +50,7 @@ struct gui_gadget { } textbox; struct { char* label; + int pressed; } actionbutt; struct { int numitems; @@ -52,6 +58,19 @@ struct gui_gadget { int size; int multiple; } select; + struct { + int selected; + char* value; + } checkbox; + struct { + int selected; + char* value; + } radio; + struct { + int cols; + int rows; + char* text; + } textarea; } data; }; @@ -85,6 +104,23 @@ struct box { struct img* img; }; +struct form +{ + char* action; /* url */ + enum {method_GET, method_POST} method; +}; + +struct page_elements +{ + struct form** forms; + struct gui_gadget** gadgets; + struct img** images; + int numForms; + int numGadgets; + int numImages; +}; + + #define UNKNOWN_WIDTH ULONG_MAX #define UNKNOWN_MAX_WIDTH ULONG_MAX @@ -96,7 +132,9 @@ void xml_to_box(xmlNode * n, struct css_style * parent_style, struct css_stylesh struct css_selector ** selector, unsigned int depth, struct box * parent, struct box * inline_container, const char *href, struct font_set *fonts, - struct gui_gadget* current_select, struct formoption* current_option); + struct gui_gadget* current_select, struct formoption* current_option, + struct gui_gadget* current_textarea, struct form* current_form, + struct page_elements* elements); void box_dump(struct box * box, unsigned int depth); void box_free(struct box *box); diff --git a/render/layout.c b/render/layout.c index db1432c78..3015d8eeb 100644 --- a/render/layout.c +++ b/render/layout.c @@ -1,5 +1,5 @@ /** - * $Id: layout.c,v 1.29 2002/12/30 02:06:03 monkeyson Exp $ + * $Id: layout.c,v 1.30 2002/12/30 22:56:30 monkeyson Exp $ */ #include @@ -127,6 +127,9 @@ int gadget_width(struct gui_gadget* gadget) /* should use wimp_textop via a gui wraper for these */ switch (gadget->type) { + case GADGET_CHECKBOX: + case GADGET_RADIO: + return 22; case GADGET_TEXTBOX: return gadget->data.textbox.size * 8; case GADGET_ACTIONBUTTON: @@ -141,6 +144,8 @@ int gadget_width(struct gui_gadget* gadget) current = current->next; } return max; + case GADGET_TEXTAREA: + return gadget->data.textarea.cols * 8 + 8; default: assert(0); } @@ -151,12 +156,17 @@ int gadget_height(struct gui_gadget* gadget) { switch (gadget->type) { + case GADGET_CHECKBOX: + case GADGET_RADIO: + return 22; case GADGET_TEXTBOX: return 28; case GADGET_ACTIONBUTTON: return 28; case GADGET_SELECT: return 28; + case GADGET_TEXTAREA: + return gadget->data.textarea.rows * 16 + 8; default: assert(0); } diff --git a/riscos/gui.c b/riscos/gui.c index 552388701..cf37e5798 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -1,5 +1,5 @@ /** - * $Id: gui.c,v 1.11 2002/12/30 02:06:03 monkeyson Exp $ + * $Id: gui.c,v 1.12 2002/12/30 22:56:30 monkeyson Exp $ */ #include "netsurf/riscos/font.h" @@ -192,6 +192,9 @@ wimp_menu* current_menu; int current_menu_x, current_menu_y; gui_window* current_gui; +wimp_menu* combo_menu; +struct gui_gadget* current_gadget; + void ro_gui_create_menu(wimp_menu* menu, int x, int y, gui_window* g) { current_menu = menu; @@ -208,7 +211,7 @@ ro_theme* current_theme = NULL; char* BROWSER_VALIDATION = "\0"; const char* task_name = "NetSurf"; -const wimp_MESSAGE_LIST(1) task_messages = { {0} }; +const wimp_MESSAGE_LIST(3) task_messages = { {message_DATA_SAVE, message_DATA_LOAD, 0} }; wimp_t task_handle; wimp_i ro_gui_iconbar_i; @@ -467,6 +470,8 @@ void ro_gui_window_redraw_box(gui_window* g, struct box * box, signed long x, si const char * const noname = ""; const char * name = noname; char *text; + char* select_text; + struct formoption* opt; switch (box->type) { @@ -524,12 +529,26 @@ void ro_gui_window_redraw_box(gui_window* g, struct box * box, signed long x, si switch (box->gadget->type) { - case GADGET_TEXTBOX: + case GADGET_TEXTAREA: icon.flags = wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); + icon.data.indirected_text.text = box->gadget->data.textarea.text; + icon.data.indirected_text.size = strlen(box->gadget->data.textarea.text); + icon.data.indirected_text.validation = "R7;L"; + fprintf(stderr, "writing GADGET TEXTAREA\n"); + wimp_plot_icon(&icon); + break; + + + case GADGET_TEXTBOX: + icon.flags = wimp_ICON_TEXT | wimp_ICON_BORDER | + wimp_ICON_VCENTRED | wimp_ICON_FILLED | + wimp_ICON_INDIRECTED | + (wimp_COLOUR_DARK_GREY << wimp_ICON_FG_COLOUR_SHIFT) | + (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); icon.data.indirected_text.text = box->gadget->data.textbox.text; icon.data.indirected_text.size = box->gadget->data.textbox.maxlength; icon.data.indirected_text.validation = " "; @@ -541,11 +560,19 @@ void ro_gui_window_redraw_box(gui_window* g, struct box * box, signed long x, si icon.flags = wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED | wimp_ICON_FILLED | wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED | - (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | - (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT); + (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT); icon.data.indirected_text.text = box->gadget->data.actionbutt.label; icon.data.indirected_text.size = strlen(box->gadget->data.actionbutt.label); - icon.data.indirected_text.validation = "R5,3"; + if (box->gadget->data.actionbutt.pressed) + { + icon.data.indirected_text.validation = "R2"; + icon.flags |= (wimp_COLOUR_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT); + } + else + { + icon.data.indirected_text.validation = "R1"; + icon.flags |= (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT); + } fprintf(stderr, "writing GADGET ACTION\n"); wimp_plot_icon(&icon); break; @@ -556,13 +583,55 @@ void ro_gui_window_redraw_box(gui_window* g, struct box * box, signed long x, si wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT); - icon.data.indirected_text.text = box->gadget->data.select.items->text; - icon.data.indirected_text.size = strlen(box->gadget->data.select.items->text); + select_text = 0; + opt = box->gadget->data.select.items; + while (opt != NULL) + { + if (opt->selected) + { + if (select_text == 0) + select_text = opt->text; + else + select_text = ""; + } + opt = opt->next; + } + if (select_text == 0) + select_text = ""; + icon.data.indirected_text.text = select_text; + icon.data.indirected_text.size = strlen(icon.data.indirected_text.text); icon.data.indirected_text.validation = "R2"; fprintf(stderr, "writing GADGET ACTION\n"); wimp_plot_icon(&icon); break; + case GADGET_CHECKBOX: + icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE | + wimp_ICON_VCENTRED | wimp_ICON_HCENTRED | + wimp_ICON_INDIRECTED; + icon.data.indirected_text_and_sprite.text = "\0"; + if (box->gadget->data.checkbox.selected) + icon.data.indirected_text_and_sprite.validation = "Sopton;"; + else + icon.data.indirected_text_and_sprite.validation = "Soptoff;"; + icon.data.indirected_text_and_sprite.size = 1; + wimp_plot_icon(&icon); + break; + + case GADGET_RADIO: + icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE | + wimp_ICON_VCENTRED | wimp_ICON_HCENTRED | + wimp_ICON_INDIRECTED; + icon.data.indirected_text_and_sprite.text = "\0"; + if (box->gadget->data.radio.selected) + icon.data.indirected_text_and_sprite.validation = "Sradioon;"; + else + icon.data.indirected_text_and_sprite.validation = "Sradiooff;"; + icon.data.indirected_text_and_sprite.size = 1; + wimp_plot_icon(&icon); + break; + + } } @@ -1165,6 +1234,16 @@ void ro_gui_window_click(gui_window* g, wimp_pointer* pointer) { if (g->data.browser.bw->current_content->type == CONTENT_HTML) { + if (pointer->buttons == wimp_CLICK_SELECT) + { + msg.type = act_MOUSE_CLICK; + msg.data.mouse.x = x; + msg.data.mouse.y = y; + msg.data.mouse.buttons = act_BUTTON_NORMAL; + if (browser_window_action(g->data.browser.bw, &msg) == 1) + return; + msg.type = act_UNKNOWN; + } if (pointer->buttons == wimp_CLICK_SELECT && g->data.browser.bw->current_content->data.html.text_selection.selected == 1) msg.type = act_CLEAR_SELECTION; else if (pointer->buttons == wimp_CLICK_ADJUST && g->data.browser.bw->current_content->data.html.text_selection.selected == 1) @@ -1338,6 +1417,11 @@ void gui_multitask(void) case wimp_USER_MESSAGE : case wimp_USER_MESSAGE_RECORDED : case wimp_USER_MESSAGE_ACKNOWLEDGE: + fprintf(stderr, "MESSAGE %d (%x) HAS ARRIVED\n", block.message.action); + if (block.message.action == message_DATA_SAVE) + ro_msg_datasave(&(block.message)); + else if (block.message.action == message_DATA_LOAD) + ro_msg_dataload(&(block.message)); if (block.message.action == message_QUIT) netsurf_quit = 1; else @@ -1349,6 +1433,28 @@ void gui_multitask(void) } +/* +void ro_gui_keypress(wimp_key* key) +{ + gui_window* g; + + if (key == NULL) + return; + + g = ro_lookup_gui_toolbar_from_w(key->w); + if (g != NULL) + if (block.message.action == message_QUIT) + netsurf_quit = 1; + else + ro_gui_poll_queue(event, &block); + break; + default: + break; + } + +} +*/ + void ro_gui_keypress(wimp_key* key) { gui_window* g; @@ -1398,7 +1504,15 @@ void ro_gui_menu_selection(wimp_selection* selection) } fprintf(stderr, "\n"); - if (current_menu == (wimp_menu*) &netsurf_iconbar_menu) + if (current_menu == combo_menu && selection->items[0] >= 0) + { + struct browser_action msg; + msg.type = act_GADGET_SELECT; + msg.data.gadget_select.g= current_gadget; + msg.data.gadget_select.item = selection->items[0]; + browser_window_action(current_gui->data.browser.bw, &msg); + } + else if (current_menu == (wimp_menu*) &netsurf_iconbar_menu) { if (selection->items[0] == 1) netsurf_quit = 1; @@ -1446,7 +1560,12 @@ void ro_gui_menu_selection(wimp_selection* selection) } if (pointer.buttons == wimp_CLICK_ADJUST) - ro_gui_create_menu(current_menu, current_menu_x, current_menu_y, current_gui); + { + if (current_menu == combo_menu) + gui_gadget_combo(current_gui->data.browser.bw, current_gadget, current_menu_x, current_menu_y); + else + ro_gui_create_menu(current_menu, current_menu_x, current_menu_y, current_gui); + } } void gui_poll(void) @@ -1569,7 +1688,12 @@ void gui_poll(void) case wimp_USER_MESSAGE : case wimp_USER_MESSAGE_RECORDED : case wimp_USER_MESSAGE_ACKNOWLEDGE: - if (block.message.action == message_QUIT) + fprintf(stderr, "MESSAGE %d (%x) HAS ARRIVED\n", block.message.action); + if (block.message.action == message_DATA_SAVE) + ro_msg_datasave(&(block.message)); + else if (block.message.action == message_DATA_LOAD) + ro_msg_dataload(&(block.message)); + else if (block.message.action == message_QUIT) netsurf_quit = 1; break; } @@ -1636,3 +1760,278 @@ void gui_window_stop_throbber(gui_window* g) g->throbber = 0; wimp_set_icon_state(g->data.browser.toolbar, ro_theme_icon(current_theme, THEME_TOOLBAR, "TOOLBAR_THROBBER"), 0, 0); } + +void gui_gadget_combo(struct browser_window* bw, struct gui_gadget* g, int mx, int my) +{ + int count = 0; + struct formoption* o; + wimp_pointer pointer; + + if (combo_menu != NULL) + xfree(combo_menu); + + o = g->data.select.items; + while (o != NULL) + { + count++; + o = o->next; + } + + combo_menu = xcalloc(1, sizeof(wimp_menu_entry) * count + offsetof(wimp_menu, entries)); + + combo_menu->title_data.indirected_text.text = "Select"; + combo_menu->title_fg = wimp_COLOUR_BLACK; + combo_menu->title_bg = wimp_COLOUR_LIGHT_GREY; + combo_menu->work_fg = wimp_COLOUR_BLACK; + combo_menu->work_bg = wimp_COLOUR_WHITE; + combo_menu->width = 0; + combo_menu->height = wimp_MENU_ITEM_HEIGHT; + combo_menu->gap = wimp_MENU_ITEM_GAP; + + o = g->data.select.items; + count = 0; + while (o != NULL) + { + combo_menu->entries[count].menu_flags = 0; + if (count == 0) + combo_menu->entries[count].menu_flags = wimp_MENU_TITLE_INDIRECTED; + if (o->selected) + combo_menu->entries[count].menu_flags |= wimp_MENU_TICKED; + if (o->next == NULL) + combo_menu->entries[count].menu_flags |= wimp_MENU_LAST; + + combo_menu->entries[count].sub_menu = wimp_NO_SUB_MENU; + combo_menu->entries[count].icon_flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | wimp_ICON_FILLED | wimp_ICON_VCENTRED | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT) | (wimp_BUTTON_MENU_ICON << wimp_ICON_BUTTON_TYPE_SHIFT); + combo_menu->entries[count].data.indirected_text.text = o->text; + combo_menu->entries[count].data.indirected_text.validation = "\0"; + combo_menu->entries[count].data.indirected_text.size = strlen(o->text); + count++; + o = o->next; + } + + wimp_get_pointer_info(&pointer); + //wimp_create_menu(combo_menu, pointer.pos.x - 64, pointer.pos.y); + current_gadget = g; + ro_gui_create_menu(combo_menu, pointer.pos.x - 64, pointer.pos.y, bw->window); +} + +void gui_edit_textarea(struct browser_window* bw, struct gui_gadget* g) +{ + FILE* file; + + system("cdir .NetSurf"); + file = fopen(".NetSurf.TextArea", "w"); + if (g->data.textarea.text != 0) + fprintf(file, "%s", g->data.textarea.text); + fclose(file); + + system("settype .NetSurf.TextArea FFF"); + system("filer_run .NetSurf.TextArea"); +} + +struct msg_datasave { + wimp_w w; + wimp_i i; + os_coord pos; + int size; + int filetype; + char leafname[212]; +}; + +typedef struct msg_datasave msg_datasave; + +void ro_msg_datasave(wimp_message* block) +{ + gui_window* gui; + struct browser_window* bw; + msg_datasave* data; + int x,y; + struct box_selection* click_boxes; + int found, plot_index; + int i; + int done = 0; + wimp_window_state state; + + data = (msg_datasave*)block->data.reserved; + + gui = ro_lookup_gui_from_w(data->w); + if (gui == NULL) + return; + + bw = gui->data.browser.bw; + + state.w = data->w; + wimp_get_window_state(&state); + x = browser_x_units(window_x_units(data->pos.x, &state)); + y = browser_y_units(window_y_units(data->pos.y, &state)); + + found = 0; + click_boxes = NULL; + plot_index = 0; + + box_under_area(bw->current_content->data.html.layout->children, + x, y, 0, 0, &click_boxes, &found, &plot_index); + + if (found == 0) + return 0; + + for (i = found - 1; i >= 0; i--) + { + if (click_boxes[i].box->gadget != NULL) + { + if (click_boxes[i].box->gadget->type == GADGET_TEXTAREA && data->filetype == 0xFFF) + { + /* load the text in! */ + fprintf(stderr, "REPLYING TO MESSAGE MATE\n"); + block->action = message_DATA_SAVE_ACK; + block->your_ref = block->my_ref; + block->my_ref = 0; + strcpy(block->data.reserved[24], ""); + wimp_send_message(wimp_USER_MESSAGE, block, block->sender); + } + } + } + + xfree(click_boxes); +} + +void ro_msg_dataload(wimp_message* block) +{ + gui_window* gui; + struct browser_window* bw; + msg_datasave* data; + int x,y; + struct box_selection* click_boxes; + int found, plot_index; + int i; + int done = 0; + wimp_window_state state; + + data = (msg_datasave*)block->data.reserved; + + gui = ro_lookup_gui_from_w(data->w); + if (gui == NULL) + return; + + bw = gui->data.browser.bw; + + state.w = data->w; + wimp_get_window_state(&state); + x = browser_x_units(window_x_units(data->pos.x, &state)); + y = browser_y_units(window_y_units(data->pos.y, &state)); + + found = 0; + click_boxes = NULL; + plot_index = 0; + + box_under_area(bw->current_content->data.html.layout->children, + x, y, 0, 0, &click_boxes, &found, &plot_index); + + if (found == 0) + return 0; + + for (i = found - 1; i >= 0; i--) + { + if (click_boxes[i].box->gadget != NULL) + { + if (click_boxes[i].box->gadget->type == GADGET_TEXTAREA && data->filetype == 0xFFF) + { + /* load the text in! */ + if (click_boxes[i].box->gadget->data.textarea.text != 0) + xfree(click_boxes[i].box->gadget->data.textarea.text); + click_boxes[i].box->gadget->data.textarea.text = load(data->leafname); + gui_redraw_gadget(bw, click_boxes[i].box->gadget); + } + } + } + + xfree(click_boxes); + +} + +struct browser_window* current_textbox_bw; +struct gui_gadget* current_textbox = 0; +wimp_w current_textbox_w; +wimp_i current_textbox_i; + +void gui_set_gadget_extent(struct box* box, int x, int y, os_box* extent, struct gui_gadget* g) +{ + struct box* c; + if (box->gadget == g) + { + extent->x0 = x + box->x * 2; + extent->y0 = y - box->y * 2 - box->height * 2; + extent->x1 = x + box->x * 2 + box->width * 2; + extent->y1 = y - box->y * 2; + return; + } + for (c = box->children; c != 0; c = c->next) + if (c->type != BOX_FLOAT_LEFT && c->type != BOX_FLOAT_RIGHT) + gui_set_gadget_extent(c, x + box->x * 2, y - box->y * 2, extent, g); + + for (c = box->float_children; c != 0; c = c->next_float) + gui_set_gadget_extent(c, x + box->x * 2, y - box->y * 2, extent, g); +} + +void gui_edit_textbox(struct browser_window* bw, struct gui_gadget* g) +{ + wimp_icon_create icon; + wimp_pointer pointer; + wimp_window_state state; + int pointer_x; + int letter_x; + int textbox_x; + int offset; + + wimp_get_pointer_info(&pointer); + + if (current_textbox != 0) + { + wimp_delete_icon(current_textbox_w, current_textbox_i); + gui_redraw_gadget(current_textbox_bw, current_textbox); + } + + current_textbox_bw = bw; + current_textbox_w = bw->window->data.browser.window; + + icon.w = current_textbox_w; + gui_set_gadget_extent(bw->current_content->data.html.layout->children, 0, 0, &icon.icon.extent, g); + fprintf(stderr, "ICON EXTENT %d %d %d %d\n", icon.icon.extent.x0, icon.icon.extent.y0, icon.icon.extent.x1, icon.icon.extent.y1); + icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_BORDER | + wimp_ICON_VCENTRED | wimp_ICON_FILLED | + wimp_ICON_INDIRECTED | + (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | + (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT) | + (wimp_BUTTON_WRITABLE << wimp_ICON_BUTTON_TYPE_SHIFT); + icon.icon.data.indirected_text.text = g->data.textbox.text; + icon.icon.data.indirected_text.size = g->data.textbox.maxlength; + icon.icon.data.indirected_text.validation = " "; + current_textbox_i = wimp_create_icon(&icon); + current_textbox = g; + gui_redraw_gadget(bw, current_textbox); + + state.w = current_textbox_w; + wimp_get_window_state(&state); + pointer_x = window_x_units(pointer.pos.x, &state); + textbox_x = icon.icon.extent.x0; + offset = strlen(g->data.textbox.text); + while (offset > 0) + { + letter_x = wimptextop_string_width(g->data.textbox.text, offset); + if (letter_x < pointer_x - textbox_x) + break; + offset--; + } + + wimp_set_caret_position(current_textbox_w, current_textbox_i, 0,0,-1, offset); +} + +void gui_remove_gadget(struct gui_gadget* g) +{ + if (g == current_textbox && g != 0) + { + wimp_delete_icon(current_textbox_w, current_textbox_i); + gui_redraw_gadget(current_textbox_bw, current_textbox); + current_textbox = 0; + } +} diff --git a/riscos/gui.h b/riscos/gui.h index 2ef75af0a..14716eac8 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -1,5 +1,5 @@ /** - * $Id: gui.h,v 1.2 2002/10/15 10:41:12 monkeyson Exp $ + * $Id: gui.h,v 1.3 2002/12/30 22:56:30 monkeyson Exp $ */ #ifndef _NETSURF_RISCOS_GUI_H_ @@ -47,5 +47,6 @@ void ro_gui_window_click(gui_window* g, wimp_pointer* mouse); void ro_gui_window_open(gui_window* g, wimp_open* open); void ro_gui_window_redraw(gui_window* g, wimp_draw* redraw); //void ro_gui_window_keypress(gui_window* g, wimp_key* key); +void gui_remove_gadget(struct gui_gadget* g); #endif -- cgit v1.2.3