[project @ 2004-07-19 20:40:11 by joty]

form.h (struct form_control): renamed caret_char_offset to caret_box_offset; Added caret_form_offset & length.
form.c: initialise new entries in struct form_control; form_successful_controls() : code reshuffling to improve readibility.
box.h: TABing.
box.c (box_input): init struct form_control::length.
browser.c (browser_window_input_callback): UTF-8 support. Text area code needs similar changes.

svn path=/import/netsurf/; revision=1117
This commit is contained in:
John Tytgat 2004-07-19 20:40:11 +00:00
parent f94da48139
commit c93b54b07c
5 changed files with 341 additions and 247 deletions

View File

@ -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 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; struct browser_window *bw = p1;
char status[40]; char status[40];
@ -524,7 +524,7 @@ void download_window_callback(fetch_msg msg, void *p, const char *data,
/* not possible */ /* not possible */
assert(0); assert(0);
break; break;
} }
} }
@ -881,7 +881,7 @@ void browser_window_textarea_click(struct browser_window *bw,
textarea->gadget->caret_inline_container = inline_container; textarea->gadget->caret_inline_container = inline_container;
textarea->gadget->caret_text_box = text_box; 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; textarea->gadget->caret_pixel_offset = pixel_offset;
browser_window_place_caret(bw, browser_window_place_caret(bw,
box_x + text_box->x + pixel_offset, 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 *text_box = textarea->gadget->caret_text_box;
struct box *new_br, *new_text, *t; struct box *new_br, *new_text, *t;
struct box *prev; 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 pixel_offset = textarea->gadget->caret_pixel_offset;
int dy; int dy;
int box_x, box_y; 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_inline_container = inline_container;
textarea->gadget->caret_text_box = text_box; 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; textarea->gadget->caret_pixel_offset = pixel_offset;
browser_window_place_caret(bw, browser_window_place_caret(bw,
box_x + text_box->x + pixel_offset, 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; int char_offset, pixel_offset, dx = 0;
struct box *text_box = input->children->children; struct box *text_box = input->children->children;
int uchars;
unsigned int offset;
nsfont_position_in_string(text_box->font, text_box->text, nsfont_position_in_string(text_box->font, text_box->text,
text_box->length, x - text_box->x, text_box->length, x - text_box->x,
&char_offset, &pixel_offset); &char_offset, &pixel_offset);
assert(char_offset <= text_box->length);
text_box->x = 0; text_box->x = 0;
if ((input->width < text_box->width) && 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; text_box->x = input->width - text_box->width;
dx -= text_box->x; 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; input->gadget->caret_pixel_offset = pixel_offset;
browser_window_place_caret(bw, browser_window_place_caret(bw,
box_x + text_box->x + pixel_offset, 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, void browser_window_input_callback(struct browser_window *bw,
unsigned int key, void *p) unsigned int key, void *p)
{ {
struct box *input = p; struct box *input = (struct box *)p;
struct box *text_box = input->children->children; 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 pixel_offset, dx;
int box_x, box_y; int box_x, box_y;
struct form *form = input->gadget->form; struct form* form = input->gadget->form;
char utf8[5];
unsigned int utf8_len, i;
char *text, *value;
bool changed = false; bool changed = false;
box_coords(input, &box_x, &box_y); box_coords(input, &box_x, &box_y);
if (!(key <= 0x001F || (0x007F <= key && key <= 0x009F))) { 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 */ /* 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 /* Insert key in gadget */
* UTF-8 sequences in the value get only one character in key_to_insert = (char)key;
* the password, so we can't just use char_offset in if ((utf8key = cnv_local_enc_str(&key_to_insert, 1)) == NULL)
* input->gadget->value */
text = realloc(text_box->text, text_box->length + 8);
if (!text) {
warn_user("NoMemory", 0);
return; return;
} utf8keySize = strlen(utf8key);
text_box->text = text; 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); /* Insert key in text box */
if (!value) { /* Convert space into NBSP */
warn_user("NoMemory", 0); key_to_insert = (input->gadget->type == GADGET_PASSWORD) ? '*' : (key == ' ') ? 160 : key;
if ((utf8key = cnv_local_enc_str(&key_to_insert, 1)) == NULL)
return; return;
} utf8keySize = strlen(utf8key);
input->gadget->value = value; text_box->text = xrealloc(text_box->text, text_box->length + utf8keySize + 1);
memmove(text_box->text + box_offset + utf8keySize,
memmove(input->gadget->value + char_offset + utf8_len, text_box->text + box_offset,
input->gadget->value + char_offset, text_box->length - box_offset);
text_box->length - char_offset); memcpy(text_box->text + box_offset, utf8key, utf8keySize);
for (i = 0; i != utf8_len; i++) text_box->length += utf8keySize;
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;
}
text_box->text[text_box->length] = 0; 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, text_box->width = nsfont_width(text_box->font, text_box->text,
(unsigned int)text_box->length); (unsigned int)text_box->length);
changed = true; changed = true;
} else if ((key == 8 || key == 127) && char_offset != 0) { } else if (key == 8 || key == 127) {
/* delete to left */ /* delete to left */
/** \todo delete entire UTF-8 character, handling passwords */ int prev_offset;
utf8_len = 1;
memmove(text_box->text + char_offset - utf8_len, if (box_offset == 0)
text_box->text + char_offset, return;
text_box->length - char_offset);
memmove(input->gadget->value + char_offset - utf8_len, /* Gadget */
input->gadget->value + char_offset, prev_offset = form_offset;
text_box->length - char_offset); /* Go to the previous valid UTF-8 character */
text_box->length--; while (form_offset != 0
input->gadget->value[text_box->length] = 0; && !((input->gadget->value[--form_offset] & 0x80) == 0x00 || (input->gadget->value[form_offset] & 0xC0) == 0xC0))
char_offset--; ;
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, text_box->width = nsfont_width(text_box->font, text_box->text,
(unsigned int)text_box->length); (unsigned int)text_box->length);
@ -1299,12 +1339,18 @@ void browser_window_input_callback(struct browser_window *bw,
/* Ctrl+U */ /* Ctrl+U */
text_box->text[0] = 0; text_box->text[0] = 0;
text_box->length = 0; text_box->length = 0;
box_offset = 0;
input->gadget->value[0] = 0; input->gadget->value[0] = 0;
char_offset = 0; input->gadget->length = 0;
form_offset = 0;
text_box->width = 0;
changed = true; changed = true;
} else if (key == 10 || key == 13) { } else if (key == 10 || key == 13) {
/* Return/Enter hit */ /* Return/Enter hit */
LOG(("Submit, text <%s>, gadget <%s>\n", text_box->text, input->gadget->value));
if (form) if (form)
browser_form_submit(bw, form, 0); browser_form_submit(bw, form, 0);
@ -1324,7 +1370,7 @@ void browser_window_input_callback(struct browser_window *bw,
input = next_input->box; input = next_input->box;
text_box = input->children->children; text_box = input->children->children;
box_coords(input, &box_x, &box_y); box_coords(input, &box_x, &box_y);
char_offset = 0; form_offset = box_offset = 0;
} else if (key == 11) { } else if (key == 11) {
/* Shift+Tab */ /* Shift+Tab */
@ -1342,34 +1388,49 @@ void browser_window_input_callback(struct browser_window *bw,
input = prev_input->box; input = prev_input->box;
text_box = input->children->children; text_box = input->children->children;
box_coords(input, &box_x, &box_y); box_coords(input, &box_x, &box_y);
char_offset = 0; form_offset = box_offset = 0;
} else if (key == 26) { } else if (key == 26) {
/* Ctrl+Left */ /* Ctrl+Left */
char_offset = 0; box_offset = form_offset = 0;
} else if (key == 27) { } else if (key == 27) {
/* Ctrl+Right */ /* 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 -> */ /* Right cursor -> */
/** \todo UTF-8 */ /* Text box */
utf8_len = 1; /* Go to the next valid UTF-8 character */
char_offset += utf8_len; 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 <- */ /* Left cursor <- */
/** \todo UTF-8 */ /* Text box */
utf8_len = 1; /* Go to the previous valid UTF-8 character */
char_offset -= utf8_len; 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 { } else {
return; return;
} }
pixel_offset = nsfont_width(text_box->font, text_box->text, pixel_offset = nsfont_width(text_box->font, text_box->text,
(unsigned int)char_offset); (unsigned int)box_offset);
dx = text_box->x; dx = text_box->x;
text_box->x = 0; text_box->x = 0;
if (input->width < text_box->width && input->width / 2 < pixel_offset) { 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; text_box->x = input->width - text_box->width;
} }
dx -= text_box->x; dx -= text_box->x;
input->gadget->caret_char_offset = char_offset;
input->gadget->caret_pixel_offset = pixel_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, browser_window_place_caret(bw,
box_x + text_box->x + pixel_offset, box_x + text_box->x + pixel_offset,
box_y + text_box->y, 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) { return pointer;
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;
} }
@ -1540,35 +1603,35 @@ void browser_form_submit(struct browser_window *bw, struct form *form,
data = form_url_encode(success); data = form_url_encode(success);
url = xcalloc(1, strlen(form->action) + strlen(data) + 2); url = xcalloc(1, strlen(form->action) + strlen(data) + 2);
if(form->action[strlen(form->action)-1] == '?') { if(form->action[strlen(form->action)-1] == '?') {
sprintf(url, "%s%s", form->action, data); sprintf(url, "%s%s", form->action, data);
} }
else { else {
sprintf(url, "%s?%s", form->action, data); sprintf(url, "%s?%s", form->action, data);
} }
url1 = url_join(url, base); url1 = url_join(url, base);
if (!url1) if (!url1)
break; break;
browser_window_go(bw, url1); browser_window_go(bw, url1);
break; break;
case method_POST_URLENC: case method_POST_URLENC:
data = form_url_encode(success); data = form_url_encode(success);
url = url_join(form->action, base); url = url_join(form->action, base);
if (!url) if (!url)
break; break;
browser_window_go_post(bw, url, data, 0, true); 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); url = url_join(form->action, base);
if (!url) if (!url)
break; break;
browser_window_go_post(bw, url, 0, success, true); browser_window_go_post(bw, url, 0, success, true);
break; break;
default: default:
assert(0); assert(0);
} }
form_free_successful(success); form_free_successful(success);
free(data); free(data);

View File

@ -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 box_result box_input(xmlNode *n, struct box_status *status,
struct css_style *style) struct css_style *style)
{ {
struct box* box = 0; struct box* box = NULL;
struct form_control *gadget = 0; struct form_control *gadget = NULL;
char *s, *type, *url; char *s, *type, *url;
type = (char *) xmlGetProp(n, (const xmlChar *) "type"); type = (char *) xmlGetProp(n, (const xmlChar *) "type");
@ -1219,21 +1219,20 @@ struct box_result box_input(xmlNode *n, struct box_status *status,
xmlFree(type); xmlFree(type);
return (struct box_result) {0, false, true}; return (struct box_result) {0, false, true};
} }
gadget->length = strlen(gadget->value);
} }
} else if (type && (strcasecmp(type, "checkbox") == 0 || } else if (type && (strcasecmp(type, "checkbox") == 0 ||
strcasecmp(type, "radio") == 0)) { strcasecmp(type, "radio") == 0)) {
box = box_create(style, NULL, 0, box = box_create(style, NULL, 0,
status->content->data.html.box_pool); 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) { if (!gadget) {
box_free_box(box); box_free_box(box);
xmlFree(type); xmlFree(type);
return (struct box_result) {0, false, true}; return (struct box_result) {0, false, true};
} }
gadget->box = box; gadget->box = box;
if (type[0] == 'c' || type[0] == 'C')
gadget->type = GADGET_CHECKBOX;
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "checked"))) { if ((s = (char *) xmlGetProp(n, (const xmlChar *) "checked"))) {
gadget->selected = true; gadget->selected = true;
@ -1248,6 +1247,7 @@ struct box_result box_input(xmlNode *n, struct box_status *status,
xmlFree(type); xmlFree(type);
return (struct box_result) {0, false, true}; return (struct box_result) {0, false, true};
} }
gadget->length = strlen(gadget->value);
} }
} else if (type && (strcasecmp(type, "submit") == 0 || } 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; struct box *inline_container, *inline_box;
box->type = BOX_INLINE_BLOCK; 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->box = box;
box->gadget->maxlength = 100; 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"); s = (char *) xmlGetProp(n, (const xmlChar *) "value");
box->gadget->value = strdup((s != NULL) ? s : ""); 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) if (s)
xmlFree(s); xmlFree(s);
if (box->gadget->value == NULL || box->gadget->initial_value == NULL) { if (box->gadget->value == NULL || box->gadget->initial_value == NULL) {
box_free(box); box_free(box);
return NULL; return NULL;
} }
box->gadget->length = strlen(box->gadget->value);
inline_container = box_create(0, 0, 0, inline_container = box_create(0, 0, 0,
status->content->data.html.box_pool); 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->type = BOX_INLINE;
inline_box->style_clone = 1; inline_box->style_clone = 1;
if (password) { if (password) {
box->gadget->type = GADGET_PASSWORD;
inline_box->length = strlen(box->gadget->value); inline_box->length = strlen(box->gadget->value);
inline_box->text = malloc(inline_box->length + 1); inline_box->text = malloc(inline_box->length + 1);
memset(inline_box->text, '*', inline_box->length); memset(inline_box->text, '*', inline_box->length);
inline_box->text[inline_box->length] = '\0'; inline_box->text[inline_box->length] = '\0';
} else { } else {
box->gadget->type = GADGET_TEXTBOX;
/* replace spaces/TABs with hard spaces to prevent line wrapping */ /* replace spaces/TABs with hard spaces to prevent line wrapping */
inline_box->text = cnv_space2nbsp(box->gadget->value); inline_box->text = cnv_space2nbsp(box->gadget->value);
inline_box->length = strlen(inline_box->text); inline_box->length = strlen(inline_box->text);

View File

@ -98,12 +98,12 @@ typedef enum {
/* parameters for <object> and related elements */ /* parameters for <object> and related elements */
struct object_params { struct object_params {
char* data; char* data;
char* type; char* type;
char* codetype; char* codetype;
char* codebase; char* codebase;
char* classid; char* classid;
struct plugin_params* params; struct plugin_params* params;
/* not a parameter, but stored here for convenience */ /* not a parameter, but stored here for convenience */
char* basehref; char* basehref;
char* filename; char* filename;
@ -115,12 +115,11 @@ struct object_params {
}; };
struct plugin_params { struct plugin_params {
char* name;
char* name; char* value;
char* value; char* type;
char* type; char* valuetype;
char* valuetype; struct plugin_params* next;
struct plugin_params* next;
}; };
/** Node in box tree. All dimensions are in pixels. */ /** 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. */ /** Form control data, or 0 if not a form control. */
struct form_control* gadget; 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 */ /** Background image for this box, or 0 if none */
struct content *background; struct content *background;
/** Object in this box (usually an image), or 0 if none. */ /** Object in this box (usually an image), or 0 if none. */
struct content* object; struct content* object;

View File

@ -33,19 +33,22 @@ struct form_control *form_new_control(form_control_type type)
{ {
struct form_control *control; struct form_control *control;
control = malloc(sizeof *control); if ((control = malloc(sizeof *control)) == NULL)
if (!control) return NULL;
return 0;
control->type = type; control->type = type;
control->name = 0; control->name = NULL;
control->value = 0; control->value = NULL;
control->initial_value = 0; control->initial_value = NULL;
control->disabled = false; control->disabled = false;
control->form = 0; control->form = NULL;
control->box = 0; 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->selected = false;
control->prev = 0; control->prev = NULL;
control->next = 0; control->next = NULL;
return control; 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) void form_add_control(struct form *form, struct form_control *control)
{ {
control->form = form; control->form = form;
if (form->controls) { if (form->controls != NULL) {
assert(form->last_control); assert(form->last_control);
form->last_control->next = control; form->last_control->next = control;
control->prev = form->last_control; control->prev = form->last_control;
control->next = 0; control->next = NULL;
form->last_control = control; form->last_control = control;
} else { } else {
form->controls = form->last_control = control; 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_control *control;
struct form_option *option; struct form_option *option;
struct form_successful_control sentinel, *last_success; struct form_successful_control sentinel, *last_success;
last_success = &sentinel; last_success = &sentinel;
sentinel.next = 0; sentinel.next = 0;
for (control = form->controls; control; control = control->next) { for (control = form->controls; control; control = control->next) {
struct form_successful_control *success_new; struct form_successful_control *success_new;
bool add_val;
/* ignore disabled controls */ /* ignore disabled controls */
if (control->disabled) if (control->disabled)
@ -120,93 +125,120 @@ struct form_successful_control *form_successful_controls(struct form *form,
if (!control->name) if (!control->name)
continue; continue;
/* only the activated submit button is successful */ switch (control->type) {
if (control->type == GADGET_SUBMIT && control != submit_button) case GADGET_HIDDEN:
continue; case GADGET_TEXTBOX:
case GADGET_PASSWORD:
add_val = true;
break;
/* ignore checkboxes and radio buttons which aren't selected */ case GADGET_RADIO:
if (control->type == GADGET_CHECKBOX && !control->selected) case GADGET_CHECKBOX:
continue; /* ignore checkboxes and radio buttons which
if (control->type == GADGET_RADIO && !control->selected) * aren't selected
continue; */
add_val = control->selected;
break;
/* select */ case GADGET_SELECT:
if (control->type == GADGET_SELECT) { /* select */
for (option = control->data.select.items; option; for (option = control->data.select.items;
option = option->next) { option != NULL;
if (option->selected) { option = option->next) {
success_new = xcalloc(1, sizeof(*success_new)); if (option->selected) {
success_new->file = false; success_new = xcalloc(1, sizeof(*success_new));
success_new->name = xstrdup(control->name); success_new->file = false;
success_new->value = xstrdup(option->value); success_new->name = cnv_str_local_enc(control->name);
success_new->next = 0; success_new->value = cnv_str_local_enc(option->value);
last_success->next = success_new; success_new->next = NULL;
last_success = success_new; 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 */ case GADGET_SUBMIT:
if (control->type == GADGET_TEXTAREA) { /* only the activated submit button is
success_new = xcalloc(1, sizeof(*success_new)); * successful
success_new->file = false; */
success_new->name = xstrdup(control->name); add_val = (control != submit_button) ? false : true;
success_new->value = form_textarea_value(control); break;
success_new->next = 0;
last_success->next = success_new;
last_success = success_new;
continue;
}
/* image */ case GADGET_RESET:
if (control->type == GADGET_IMAGE) { /* ignore reset */
unsigned int len = strlen(control->name) + 3; add_val = false;
/* x */ break;
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;
}
/* ignore reset */ case GADGET_FILE:
if (control->type == GADGET_RESET) /* file */
continue; 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 */ add_val = false;
if (control->type == GADGET_FILE && control->value) { break;
success_new = xcalloc(1, sizeof(*success_new));
success_new->file = true; default:
success_new->name = xstrdup(control->name); assert(0);
success_new->value = xstrdup(control->value); break;
success_new->next = 0;
last_success->next = success_new;
last_success = success_new;
continue;
} }
/* all others added if they have a value */ /* 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 = xcalloc(1, sizeof(*success_new));
success_new->file = false; success_new->file = false;
success_new->name = xstrdup(control->name); success_new->name = cnv_str_local_enc(control->name);
success_new->value = xstrdup(control->value); success_new->value = cnv_str_local_enc(control->value);
success_new->next = 0; success_new->next = NULL;
last_success->next = success_new; last_success->next = success_new;
last_success = success_new; last_success = success_new;
} }
@ -228,10 +260,10 @@ char *form_textarea_value(struct form_control *textarea)
/* find required length */ /* find required length */
for (inline_container = textarea->box->children; for (inline_container = textarea->box->children;
inline_container; inline_container != NULL;
inline_container = inline_container->next) { inline_container = inline_container->next) {
for (text_box = inline_container->children; for (text_box = inline_container->children;
text_box; text_box != NULL;
text_box = text_box->next) { text_box = text_box->next) {
len += text_box->length + 1; len += text_box->length + 1;
} }
@ -241,10 +273,10 @@ char *form_textarea_value(struct form_control *textarea)
/* construct value */ /* construct value */
s = value = xcalloc(1, len); s = value = xcalloc(1, len);
for (inline_container = textarea->box->children; for (inline_container = textarea->box->children;
inline_container; inline_container != NULL;
inline_container = inline_container->next) { inline_container = inline_container->next) {
for (text_box = inline_container->children; for (text_box = inline_container->children;
text_box; text_box != NULL;
text_box = text_box->next) { text_box = text_box->next) {
strncpy(s, text_box->text, text_box->length); strncpy(s, text_box->text, text_box->length);
s += 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; unsigned int len = 0, len1;
for (; control; control = control->next) { for (; control; control = control->next) {
char *name = curl_escape(control->name, 0); const char *name = curl_escape(control->name, 0);
char *value = curl_escape(control->value, 0); const char *value = curl_escape(control->value, 0);
len1 = len + strlen(name) + strlen(value) + 2; len1 = len + strlen(name) + strlen(value) + 2;
s = xrealloc(s, len1 + 1); s = xrealloc(s, len1 + 1);
sprintf(s + len, "%s=%s&", name, value); sprintf(s + len, "%s=%s&", name, value);
len = len1; len = len1;
curl_free(name); curl_free(name);
curl_free(value); curl_free(value);
} }
if (len) if (len)
s[len - 1] = 0; s[len - 1] = 0;

View File

@ -58,13 +58,14 @@ struct form_control {
struct box *box; struct box *box;
struct box *caret_inline_container; struct box *caret_inline_container;
struct box *caret_text_box; struct box *caret_text_box;
int caret_char_offset; unsigned int caret_box_offset, caret_form_offset;
unsigned int length;
int caret_pixel_offset; int caret_pixel_offset;
unsigned int maxlength; unsigned int maxlength;
bool selected; bool selected;
union { union {
struct { struct {
int mx, my; int mx, my;
} image; } image;
struct { struct {
int num_items; int num_items;