diff --git a/desktop/browser.c b/desktop/browser.c index ed5052d22..15585460e 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -183,7 +183,7 @@ void browser_window_go_post(struct browser_window *bw, const char *url, */ void browser_window_callback(content_msg msg, struct content *c, - void *p1, void *p2, union content_msg_data data) + void *p1, void *p2, union content_msg_data data) { struct browser_window *bw = p1; char status[40]; @@ -524,7 +524,7 @@ void download_window_callback(fetch_msg msg, void *p, const char *data, /* not possible */ assert(0); break; - } + } } @@ -881,7 +881,7 @@ void browser_window_textarea_click(struct browser_window *bw, textarea->gadget->caret_inline_container = inline_container; textarea->gadget->caret_text_box = text_box; - textarea->gadget->caret_char_offset = char_offset; + textarea->gadget->caret_box_offset = textarea->gadget->caret_form_offset = char_offset; textarea->gadget->caret_pixel_offset = pixel_offset; browser_window_place_caret(bw, box_x + text_box->x + pixel_offset, @@ -906,7 +906,7 @@ void browser_window_textarea_callback(struct browser_window *bw, struct box *text_box = textarea->gadget->caret_text_box; struct box *new_br, *new_text, *t; struct box *prev; - int char_offset = textarea->gadget->caret_char_offset; + int char_offset = textarea->gadget->caret_box_offset; int pixel_offset = textarea->gadget->caret_pixel_offset; int dy; int box_x, box_y; @@ -1148,7 +1148,7 @@ void browser_window_textarea_callback(struct browser_window *bw, textarea->gadget->caret_inline_container = inline_container; textarea->gadget->caret_text_box = text_box; - textarea->gadget->caret_char_offset = char_offset; + textarea->gadget->caret_box_offset = textarea->gadget->caret_form_offset = char_offset; textarea->gadget->caret_pixel_offset = pixel_offset; browser_window_place_caret(bw, box_x + text_box->x + pixel_offset, @@ -1179,10 +1179,13 @@ void browser_window_input_click(struct browser_window* bw, { int char_offset, pixel_offset, dx = 0; struct box *text_box = input->children->children; + int uchars; + unsigned int offset; nsfont_position_in_string(text_box->font, text_box->text, text_box->length, x - text_box->x, &char_offset, &pixel_offset); + assert(char_offset <= text_box->length); text_box->x = 0; if ((input->width < text_box->width) && @@ -1193,7 +1196,31 @@ void browser_window_input_click(struct browser_window* bw, text_box->x = input->width - text_box->width; dx -= text_box->x; } - input->gadget->caret_char_offset = char_offset; + input->gadget->caret_box_offset = char_offset; + /* Update caret_form_offset */ + for (uchars = 0, offset = 0; offset < char_offset; ++uchars) { + if ((text_box->text[offset] & 0x80) == 0x00) { + ++offset; + continue; + } + assert((text_box->text[offset] & 0xC0) == 0xC0); + for (++offset; offset < char_offset && (text_box->text[offset] & 0xC0) == 0x80; ++offset) + ; + } + /* uchars is the number of real Unicode characters at the left + * side of the caret. + */ + for (offset = 0; uchars > 0 && offset < input->gadget->length; --uchars) { + if ((input->gadget->value[offset] & 0x80) == 0x00) { + ++offset; + continue; + } + assert((input->gadget->value[offset] & 0xC0) == 0xC0); + for (++offset; offset < input->gadget->length && (input->gadget->value[offset] & 0xC0) == 0x80; ++offset) + ; + } + assert(uchars == 0); + input->gadget->caret_form_offset = offset; input->gadget->caret_pixel_offset = pixel_offset; browser_window_place_caret(bw, box_x + text_box->x + pixel_offset, @@ -1213,83 +1240,96 @@ void browser_window_input_click(struct browser_window* bw, void browser_window_input_callback(struct browser_window *bw, unsigned int key, void *p) { - struct box *input = p; + struct box *input = (struct box *)p; struct box *text_box = input->children->children; - int char_offset = input->gadget->caret_char_offset; + unsigned int box_offset = input->gadget->caret_box_offset; + unsigned int form_offset = input->gadget->caret_form_offset; int pixel_offset, dx; int box_x, box_y; - struct form *form = input->gadget->form; - char utf8[5]; - unsigned int utf8_len, i; - char *text, *value; + struct form* form = input->gadget->form; bool changed = false; box_coords(input, &box_x, &box_y); if (!(key <= 0x001F || (0x007F <= key && key <= 0x009F))) { + char key_to_insert; + const char *utf8key; + size_t utf8keySize; + + /** \todo: text_box has data in UTF-8 and its length in + * bytes is not necessarily equal to number of characters. + */ + if (input->gadget->length >= input->gadget->maxlength) + return; + /* normal character insertion */ - /** \todo convert key to UTF-8 properly */ - utf8[0] = key; - utf8_len = 1; - /** \todo this is wrong for passwords, because multi-byte - * UTF-8 sequences in the value get only one character in - * the password, so we can't just use char_offset in - * input->gadget->value */ - - text = realloc(text_box->text, text_box->length + 8); - if (!text) { - warn_user("NoMemory", 0); + /* Insert key in gadget */ + key_to_insert = (char)key; + if ((utf8key = cnv_local_enc_str(&key_to_insert, 1)) == NULL) return; - } - text_box->text = text; + utf8keySize = strlen(utf8key); + input->gadget->value = xrealloc(input->gadget->value, input->gadget->length + utf8keySize + 1); + memmove(input->gadget->value + form_offset + utf8keySize, + input->gadget->value + form_offset, + input->gadget->length - form_offset); + memcpy(input->gadget->value + form_offset, utf8key, utf8keySize); + input->gadget->length += utf8keySize; + input->gadget->value[input->gadget->length] = 0; + form_offset += utf8keySize; + free((void *)utf8key); - value = realloc(input->gadget->value, text_box->length + 8); - if (!value) { - warn_user("NoMemory", 0); + /* Insert key in text box */ + /* Convert space into NBSP */ + key_to_insert = (input->gadget->type == GADGET_PASSWORD) ? '*' : (key == ' ') ? 160 : key; + if ((utf8key = cnv_local_enc_str(&key_to_insert, 1)) == NULL) return; - } - input->gadget->value = value; - - memmove(input->gadget->value + char_offset + utf8_len, - input->gadget->value + char_offset, - text_box->length - char_offset); - for (i = 0; i != utf8_len; i++) - input->gadget->value[char_offset + i] = key; - - if (input->gadget->type == GADGET_PASSWORD) { - text_box->text[text_box->length] = '*'; - text_box->length++; - char_offset++; - } else { - memmove(text_box->text + char_offset + utf8_len, - text_box->text + char_offset, - text_box->length - char_offset); - for (i = 0; i != utf8_len; i++) - text_box->text[char_offset + i] = utf8[i]; - text_box->length += utf8_len; - char_offset += utf8_len; - } + utf8keySize = strlen(utf8key); + text_box->text = xrealloc(text_box->text, text_box->length + utf8keySize + 1); + memmove(text_box->text + box_offset + utf8keySize, + text_box->text + box_offset, + text_box->length - box_offset); + memcpy(text_box->text + box_offset, utf8key, utf8keySize); + text_box->length += utf8keySize; text_box->text[text_box->length] = 0; - input->gadget->value[text_box->length] = 0; + box_offset += utf8keySize; + free((void *)utf8key); + text_box->width = nsfont_width(text_box->font, text_box->text, (unsigned int)text_box->length); - changed = true; - } else if ((key == 8 || key == 127) && char_offset != 0) { + } else if (key == 8 || key == 127) { /* delete to left */ - /** \todo delete entire UTF-8 character, handling passwords */ - utf8_len = 1; - memmove(text_box->text + char_offset - utf8_len, - text_box->text + char_offset, - text_box->length - char_offset); - memmove(input->gadget->value + char_offset - utf8_len, - input->gadget->value + char_offset, - text_box->length - char_offset); - text_box->length--; - input->gadget->value[text_box->length] = 0; - char_offset--; + int prev_offset; + + if (box_offset == 0) + return; + + /* Gadget */ + prev_offset = form_offset; + /* Go to the previous valid UTF-8 character */ + while (form_offset != 0 + && !((input->gadget->value[--form_offset] & 0x80) == 0x00 || (input->gadget->value[form_offset] & 0xC0) == 0xC0)) + ; + memmove(input->gadget->value + form_offset, + input->gadget->value + prev_offset, + input->gadget->length - prev_offset); + input->gadget->length -= prev_offset - form_offset; + input->gadget->value[input->gadget->length] = 0; + + /* Text box */ + prev_offset = box_offset; + /* Go to the previous valid UTF-8 character */ + while (box_offset != 0 + && !((text_box->text[--box_offset] & 0x80) == 0x00 || (text_box->text[box_offset] & 0xC0) == 0xC0)) + ; + memmove(text_box->text + box_offset, + text_box->text + prev_offset, + text_box->length - prev_offset); + text_box->length -= prev_offset - box_offset; + text_box->text[text_box->length] = 0; + text_box->width = nsfont_width(text_box->font, text_box->text, (unsigned int)text_box->length); @@ -1299,12 +1339,18 @@ void browser_window_input_callback(struct browser_window *bw, /* Ctrl+U */ text_box->text[0] = 0; text_box->length = 0; + box_offset = 0; + input->gadget->value[0] = 0; - char_offset = 0; + input->gadget->length = 0; + form_offset = 0; + + text_box->width = 0; changed = true; } else if (key == 10 || key == 13) { /* Return/Enter hit */ +LOG(("Submit, text <%s>, gadget <%s>\n", text_box->text, input->gadget->value)); if (form) browser_form_submit(bw, form, 0); @@ -1324,7 +1370,7 @@ void browser_window_input_callback(struct browser_window *bw, input = next_input->box; text_box = input->children->children; box_coords(input, &box_x, &box_y); - char_offset = 0; + form_offset = box_offset = 0; } else if (key == 11) { /* Shift+Tab */ @@ -1342,34 +1388,49 @@ void browser_window_input_callback(struct browser_window *bw, input = prev_input->box; text_box = input->children->children; box_coords(input, &box_x, &box_y); - char_offset = 0; + form_offset = box_offset = 0; } else if (key == 26) { /* Ctrl+Left */ - char_offset = 0; + box_offset = form_offset = 0; } else if (key == 27) { /* Ctrl+Right */ - char_offset = text_box->length; + box_offset = text_box->length; + form_offset = input->gadget->length; - } else if (key == 28 && (unsigned int)char_offset != text_box->length) { + } else if (key == 28) { /* Right cursor -> */ - /** \todo UTF-8 */ - utf8_len = 1; - char_offset += utf8_len; + /* Text box */ + /* Go to the next valid UTF-8 character */ + while (box_offset != text_box->length + && !((text_box->text[++box_offset] & 0x80) == 0x00 || (text_box->text[box_offset] & 0xC0) == 0xC0)) + ; + /* Gadget */ + /* Go to the next valid UTF-8 character */ + while (form_offset != input->gadget->length + && !((input->gadget->value[++form_offset] & 0x80) == 0x00 || (input->gadget->value[form_offset] & 0xC0) == 0xC0)) + ; - } else if (key == 29 && char_offset != 0) { + } else if (key == 29) { /* Left cursor <- */ - /** \todo UTF-8 */ - utf8_len = 1; - char_offset -= utf8_len; + /* Text box */ + /* Go to the previous valid UTF-8 character */ + while (box_offset != 0 + && !((text_box->text[--box_offset] & 0x80) == 0x00 || (text_box->text[box_offset] & 0xC0) == 0xC0)) + ; + /* Gadget */ + /* Go to the previous valid UTF-8 character */ + while (form_offset != 0 + && !((input->gadget->value[--form_offset] & 0x80) == 0x00 || (input->gadget->value[form_offset] & 0xC0) == 0xC0)) + ; } else { return; } pixel_offset = nsfont_width(text_box->font, text_box->text, - (unsigned int)char_offset); + (unsigned int)box_offset); dx = text_box->x; text_box->x = 0; if (input->width < text_box->width && input->width / 2 < pixel_offset) { @@ -1378,9 +1439,11 @@ void browser_window_input_callback(struct browser_window *bw, text_box->x = input->width - text_box->width; } dx -= text_box->x; - - input->gadget->caret_char_offset = char_offset; input->gadget->caret_pixel_offset = pixel_offset; + + input->gadget->caret_box_offset = box_offset; + input->gadget->caret_form_offset = form_offset; + browser_window_place_caret(bw, box_x + text_box->x + pixel_offset, box_y + text_box->y, @@ -1477,45 +1540,45 @@ void browser_window_form_select(struct browser_window *bw, } -gui_pointer_shape get_pointer_shape(css_cursor cursor) { +gui_pointer_shape get_pointer_shape(css_cursor cursor) +{ + gui_pointer_shape pointer; - gui_pointer_shape pointer; + switch (cursor) { + case CSS_CURSOR_CROSSHAIR: + pointer = GUI_POINTER_CROSS; + break; + case CSS_CURSOR_POINTER: + pointer = GUI_POINTER_POINT; + break; + case CSS_CURSOR_MOVE: + pointer = GUI_POINTER_MOVE; + break; + case CSS_CURSOR_E_RESIZE: + case CSS_CURSOR_W_RESIZE: + pointer = GUI_POINTER_LR; + break; + case CSS_CURSOR_N_RESIZE: + case CSS_CURSOR_S_RESIZE: + pointer = GUI_POINTER_UD; + break; + case CSS_CURSOR_NE_RESIZE: + case CSS_CURSOR_SW_RESIZE: + pointer = GUI_POINTER_LD; + break; + case CSS_CURSOR_SE_RESIZE: + case CSS_CURSOR_NW_RESIZE: + pointer = GUI_POINTER_RD; + break; + case CSS_CURSOR_TEXT: + pointer = GUI_POINTER_CARET; + break; + default: + pointer = GUI_POINTER_DEFAULT; + break; + } - switch (cursor) { - case CSS_CURSOR_CROSSHAIR: - pointer = GUI_POINTER_CROSS; - break; - case CSS_CURSOR_POINTER: - pointer = GUI_POINTER_POINT; - break; - case CSS_CURSOR_MOVE: - pointer = GUI_POINTER_MOVE; - break; - case CSS_CURSOR_E_RESIZE: - case CSS_CURSOR_W_RESIZE: - pointer = GUI_POINTER_LR; - break; - case CSS_CURSOR_N_RESIZE: - case CSS_CURSOR_S_RESIZE: - pointer = GUI_POINTER_UD; - break; - case CSS_CURSOR_NE_RESIZE: - case CSS_CURSOR_SW_RESIZE: - pointer = GUI_POINTER_LD; - break; - case CSS_CURSOR_SE_RESIZE: - case CSS_CURSOR_NW_RESIZE: - pointer = GUI_POINTER_RD; - break; - case CSS_CURSOR_TEXT: - pointer = GUI_POINTER_CARET; - break; - default: - pointer = GUI_POINTER_DEFAULT; - break; - } - - return pointer; + return pointer; } @@ -1540,35 +1603,35 @@ void browser_form_submit(struct browser_window *bw, struct form *form, data = form_url_encode(success); url = xcalloc(1, strlen(form->action) + strlen(data) + 2); if(form->action[strlen(form->action)-1] == '?') { - sprintf(url, "%s%s", form->action, data); + sprintf(url, "%s%s", form->action, data); } else { - sprintf(url, "%s?%s", form->action, data); + sprintf(url, "%s?%s", form->action, data); } url1 = url_join(url, base); if (!url1) break; browser_window_go(bw, url1); - break; + break; - case method_POST_URLENC: + case method_POST_URLENC: data = form_url_encode(success); url = url_join(form->action, base); if (!url) break; browser_window_go_post(bw, url, data, 0, true); - break; + break; - case method_POST_MULTIPART: + case method_POST_MULTIPART: url = url_join(form->action, base); if (!url) break; browser_window_go_post(bw, url, 0, success, true); - break; + break; - default: - assert(0); - } + default: + assert(0); + } form_free_successful(success); free(data); diff --git a/render/box.c b/render/box.c index d014d3be5..12b696d78 100644 --- a/render/box.c +++ b/render/box.c @@ -1179,8 +1179,8 @@ void add_option(xmlNode* n, struct form_control* current_select, const char *tex struct box_result box_input(xmlNode *n, struct box_status *status, struct css_style *style) { - struct box* box = 0; - struct form_control *gadget = 0; + struct box* box = NULL; + struct form_control *gadget = NULL; char *s, *type, *url; type = (char *) xmlGetProp(n, (const xmlChar *) "type"); @@ -1219,21 +1219,20 @@ struct box_result box_input(xmlNode *n, struct box_status *status, xmlFree(type); return (struct box_result) {0, false, true}; } + gadget->length = strlen(gadget->value); } } else if (type && (strcasecmp(type, "checkbox") == 0 || strcasecmp(type, "radio") == 0)) { box = box_create(style, NULL, 0, status->content->data.html.box_pool); - box->gadget = gadget = form_new_control(GADGET_RADIO); + box->gadget = gadget = form_new_control((type[0] == 'c' || type[0] == 'C') ? GADGET_CHECKBOX : GADGET_RADIO); if (!gadget) { box_free_box(box); xmlFree(type); return (struct box_result) {0, false, true}; } gadget->box = box; - if (type[0] == 'c' || type[0] == 'C') - gadget->type = GADGET_CHECKBOX; if ((s = (char *) xmlGetProp(n, (const xmlChar *) "checked"))) { gadget->selected = true; @@ -1248,6 +1247,7 @@ struct box_result box_input(xmlNode *n, struct box_status *status, xmlFree(type); return (struct box_result) {0, false, true}; } + gadget->length = strlen(gadget->value); } } else if (type && (strcasecmp(type, "submit") == 0 || @@ -1365,7 +1365,7 @@ struct box *box_input_text(xmlNode *n, struct box_status *status, struct box *inline_container, *inline_box; box->type = BOX_INLINE_BLOCK; - box->gadget = form_new_control(GADGET_TEXTBOX); + box->gadget = form_new_control((password) ? GADGET_PASSWORD : GADGET_TEXTBOX); box->gadget->box = box; box->gadget->maxlength = 100; @@ -1376,13 +1376,14 @@ struct box *box_input_text(xmlNode *n, struct box_status *status, s = (char *) xmlGetProp(n, (const xmlChar *) "value"); box->gadget->value = strdup((s != NULL) ? s : ""); - box->gadget->initial_value = strdup(box->gadget->value); + box->gadget->initial_value = strdup((box->gadget->value != NULL) ? box->gadget->value : ""); if (s) xmlFree(s); if (box->gadget->value == NULL || box->gadget->initial_value == NULL) { box_free(box); return NULL; } + box->gadget->length = strlen(box->gadget->value); inline_container = box_create(0, 0, 0, status->content->data.html.box_pool); @@ -1392,13 +1393,11 @@ struct box *box_input_text(xmlNode *n, struct box_status *status, inline_box->type = BOX_INLINE; inline_box->style_clone = 1; if (password) { - box->gadget->type = GADGET_PASSWORD; inline_box->length = strlen(box->gadget->value); inline_box->text = malloc(inline_box->length + 1); memset(inline_box->text, '*', inline_box->length); inline_box->text[inline_box->length] = '\0'; } else { - box->gadget->type = GADGET_TEXTBOX; /* replace spaces/TABs with hard spaces to prevent line wrapping */ inline_box->text = cnv_space2nbsp(box->gadget->value); inline_box->length = strlen(inline_box->text); diff --git a/render/box.h b/render/box.h index 58328884b..72303964b 100644 --- a/render/box.h +++ b/render/box.h @@ -98,12 +98,12 @@ typedef enum { /* parameters for and related elements */ struct object_params { - char* data; - char* type; - char* codetype; - char* codebase; - char* classid; - struct plugin_params* params; + char* data; + char* type; + char* codetype; + char* codebase; + char* classid; + struct plugin_params* params; /* not a parameter, but stored here for convenience */ char* basehref; char* filename; @@ -115,12 +115,11 @@ struct object_params { }; struct plugin_params { - - char* name; - char* value; - char* type; - char* valuetype; - struct plugin_params* next; + char* name; + char* value; + char* type; + char* valuetype; + struct plugin_params* next; }; /** Node in box tree. All dimensions are in pixels. */ @@ -207,10 +206,10 @@ struct box { /** Form control data, or 0 if not a form control. */ struct form_control* gadget; - char *usemap; /** (Image)map to use with this object, or 0 if none */ + char *usemap; /** (Image)map to use with this object, or 0 if none */ - /** Background image for this box, or 0 if none */ - struct content *background; + /** Background image for this box, or 0 if none */ + struct content *background; /** Object in this box (usually an image), or 0 if none. */ struct content* object; diff --git a/render/form.c b/render/form.c index 6b1b247df..3713071e9 100644 --- a/render/form.c +++ b/render/form.c @@ -33,19 +33,22 @@ struct form_control *form_new_control(form_control_type type) { struct form_control *control; - control = malloc(sizeof *control); - if (!control) - return 0; + if ((control = malloc(sizeof *control)) == NULL) + return NULL; control->type = type; - control->name = 0; - control->value = 0; - control->initial_value = 0; + control->name = NULL; + control->value = NULL; + control->initial_value = NULL; control->disabled = false; - control->form = 0; - control->box = 0; + control->form = NULL; + control->box = NULL; + control->caret_inline_container = NULL; + control->caret_text_box = NULL; + control->caret_box_offset = control->caret_form_offset = 0; + control->length = control->maxlength = 0; control->selected = false; - control->prev = 0; - control->next = 0; + control->prev = NULL; + control->next = NULL; return control; } @@ -57,11 +60,11 @@ struct form_control *form_new_control(form_control_type type) void form_add_control(struct form *form, struct form_control *control) { control->form = form; - if (form->controls) { + if (form->controls != NULL) { assert(form->last_control); form->last_control->next = control; control->prev = form->last_control; - control->next = 0; + control->next = NULL; form->last_control = control; } else { form->controls = form->last_control = control; @@ -106,11 +109,13 @@ struct form_successful_control *form_successful_controls(struct form *form, struct form_control *control; struct form_option *option; struct form_successful_control sentinel, *last_success; + last_success = &sentinel; sentinel.next = 0; for (control = form->controls; control; control = control->next) { struct form_successful_control *success_new; + bool add_val; /* ignore disabled controls */ if (control->disabled) @@ -120,93 +125,120 @@ struct form_successful_control *form_successful_controls(struct form *form, if (!control->name) continue; - /* only the activated submit button is successful */ - if (control->type == GADGET_SUBMIT && control != submit_button) - continue; + switch (control->type) { + case GADGET_HIDDEN: + case GADGET_TEXTBOX: + case GADGET_PASSWORD: + add_val = true; + break; - /* ignore checkboxes and radio buttons which aren't selected */ - if (control->type == GADGET_CHECKBOX && !control->selected) - continue; - if (control->type == GADGET_RADIO && !control->selected) - continue; + case GADGET_RADIO: + case GADGET_CHECKBOX: + /* ignore checkboxes and radio buttons which + * aren't selected + */ + add_val = control->selected; + break; - /* select */ - if (control->type == GADGET_SELECT) { - for (option = control->data.select.items; option; - option = option->next) { - if (option->selected) { - success_new = xcalloc(1, sizeof(*success_new)); - success_new->file = false; - success_new->name = xstrdup(control->name); - success_new->value = xstrdup(option->value); - success_new->next = 0; - last_success->next = success_new; - last_success = success_new; + case GADGET_SELECT: + /* select */ + for (option = control->data.select.items; + option != NULL; + option = option->next) { + if (option->selected) { + success_new = xcalloc(1, sizeof(*success_new)); + success_new->file = false; + success_new->name = cnv_str_local_enc(control->name); + success_new->value = cnv_str_local_enc(option->value); + success_new->next = NULL; + last_success->next = success_new; + last_success = success_new; + } } + + add_val = false; + break; + + case GADGET_TEXTAREA: + /* textarea */ + success_new = xcalloc(1, sizeof(*success_new)); + success_new->file = false; + success_new->name = cnv_str_local_enc(control->name); + success_new->value = form_textarea_value(control); + success_new->next = 0; + last_success->next = success_new; + last_success = success_new; + + add_val = false; + break; + + case GADGET_IMAGE: { + /* image */ + const size_t len = strlen(control->name) + 3; + + /* x */ + success_new = xcalloc(1, sizeof(*success_new)); + success_new->file = false; + success_new->name = xcalloc(1, len); + sprintf(success_new->name, "%s.x", control->name); + success_new->value = xcalloc(1, 20); + sprintf(success_new->value, "%i", control->data.image.mx); + success_new->next = 0; + last_success->next = success_new; + last_success = success_new; + + /* y */ + success_new = xcalloc(1, sizeof(*success_new)); + success_new->file = false; + success_new->name = xcalloc(1, len); + sprintf(success_new->name, "%s.y", control->name); + success_new->value = xcalloc(1, 20); + sprintf(success_new->value, "%i", control->data.image.my); + success_new->next = 0; + last_success->next = success_new; + last_success = success_new; + + add_val = false; + break; } - continue; - } - /* textarea */ - if (control->type == GADGET_TEXTAREA) { - success_new = xcalloc(1, sizeof(*success_new)); - success_new->file = false; - success_new->name = xstrdup(control->name); - success_new->value = form_textarea_value(control); - success_new->next = 0; - last_success->next = success_new; - last_success = success_new; - continue; - } + case GADGET_SUBMIT: + /* only the activated submit button is + * successful + */ + add_val = (control != submit_button) ? false : true; + break; - /* image */ - if (control->type == GADGET_IMAGE) { - unsigned int len = strlen(control->name) + 3; - /* x */ - success_new = xcalloc(1, sizeof(*success_new)); - success_new->file = false; - success_new->name = xcalloc(1, len); - sprintf(success_new->name, "%s.x", control->name); - success_new->value = xcalloc(1, 20); - sprintf(success_new->value, "%i", control->data.image.mx); - success_new->next = 0; - last_success->next = success_new; - last_success = success_new; - /* y */ - success_new = xcalloc(1, sizeof(*success_new)); - success_new->file = false; - success_new->name = xcalloc(1, len); - sprintf(success_new->name, "%s.y", control->name); - success_new->value = xcalloc(1, 20); - sprintf(success_new->value, "%i", control->data.image.my); - success_new->next = 0; - last_success->next = success_new; - last_success = success_new; - } + case GADGET_RESET: + /* ignore reset */ + add_val = false; + break; - /* ignore reset */ - if (control->type == GADGET_RESET) - continue; + case GADGET_FILE: + /* file */ + success_new = xcalloc(1, sizeof(*success_new)); + success_new->file = true; + success_new->name = cnv_str_local_enc(control->name); + success_new->value = cnv_str_local_enc(control->value); + success_new->next = 0; + last_success->next = success_new; + last_success = success_new; - /* file */ - if (control->type == GADGET_FILE && control->value) { - success_new = xcalloc(1, sizeof(*success_new)); - success_new->file = true; - success_new->name = xstrdup(control->name); - success_new->value = xstrdup(control->value); - success_new->next = 0; - last_success->next = success_new; - last_success = success_new; - continue; + add_val = false; + break; + + default: + assert(0); + break; } /* all others added if they have a value */ - if (control->value) { + if (add_val && control->value != NULL) { success_new = xcalloc(1, sizeof(*success_new)); success_new->file = false; - success_new->name = xstrdup(control->name); - success_new->value = xstrdup(control->value); - success_new->next = 0; + success_new->name = cnv_str_local_enc(control->name); + success_new->value = cnv_str_local_enc(control->value); + success_new->next = NULL; last_success->next = success_new; last_success = success_new; } @@ -228,10 +260,10 @@ char *form_textarea_value(struct form_control *textarea) /* find required length */ for (inline_container = textarea->box->children; - inline_container; + inline_container != NULL; inline_container = inline_container->next) { for (text_box = inline_container->children; - text_box; + text_box != NULL; text_box = text_box->next) { len += text_box->length + 1; } @@ -241,10 +273,10 @@ char *form_textarea_value(struct form_control *textarea) /* construct value */ s = value = xcalloc(1, len); for (inline_container = textarea->box->children; - inline_container; + inline_container != NULL; inline_container = inline_container->next) { for (text_box = inline_container->children; - text_box; + text_box != NULL; text_box = text_box->next) { strncpy(s, text_box->text, text_box->length); s += text_box->length; @@ -269,14 +301,14 @@ char *form_url_encode(struct form_successful_control *control) unsigned int len = 0, len1; for (; control; control = control->next) { - char *name = curl_escape(control->name, 0); - char *value = curl_escape(control->value, 0); + const char *name = curl_escape(control->name, 0); + const char *value = curl_escape(control->value, 0); len1 = len + strlen(name) + strlen(value) + 2; s = xrealloc(s, len1 + 1); sprintf(s + len, "%s=%s&", name, value); len = len1; - curl_free(name); - curl_free(value); + curl_free(name); + curl_free(value); } if (len) s[len - 1] = 0; diff --git a/render/form.h b/render/form.h index 013cb30ed..e6f77aaa7 100644 --- a/render/form.h +++ b/render/form.h @@ -58,13 +58,14 @@ struct form_control { struct box *box; struct box *caret_inline_container; struct box *caret_text_box; - int caret_char_offset; + unsigned int caret_box_offset, caret_form_offset; + unsigned int length; int caret_pixel_offset; unsigned int maxlength; bool selected; union { struct { - int mx, my; + int mx, my; } image; struct { int num_items;