bug 755: Fixed.
[elinks.git] / src / ecmascript / see / form.c
blobc1332ccf6c92c541f521d1cf5067f354cff2995a
1 /* The SEE form object implementation. */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
11 #include "elinks.h"
13 #include <see/see.h>
15 #include "bfu/dialog.h"
16 #include "cache/cache.h"
17 #include "cookies/cookies.h"
18 #include "dialogs/menu.h"
19 #include "dialogs/status.h"
20 #include "document/html/frames.h"
21 #include "document/document.h"
22 #include "document/forms.h"
23 #include "document/view.h"
24 #include "ecmascript/ecmascript.h"
25 #include "ecmascript/see/checktype.h"
26 #include "ecmascript/see/document.h"
27 #include "ecmascript/see/form.h"
28 #include "ecmascript/see/input.h"
29 #include "ecmascript/see/strings.h"
30 #include "ecmascript/see/window.h"
31 #include "intl/gettext/libintl.h"
32 #include "main/select.h"
33 #include "osdep/newwin.h"
34 #include "osdep/sysname.h"
35 #include "protocol/http/http.h"
36 #include "protocol/uri.h"
37 #include "session/history.h"
38 #include "session/location.h"
39 #include "session/session.h"
40 #include "session/task.h"
41 #include "terminal/tab.h"
42 #include "terminal/terminal.h"
43 #include "util/conv.h"
44 #include "util/memory.h"
45 #include "util/string.h"
46 #include "viewer/text/draw.h"
47 #include "viewer/text/form.h"
48 #include "viewer/text/link.h"
49 #include "viewer/text/vs.h"
51 static void input_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
52 static void input_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
53 static void js_input_blur(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
54 static void js_input_click(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
55 static void js_input_focus(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
56 static void js_input_select(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
57 static int input_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
58 static int input_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
59 static struct js_input *js_get_input_object(struct SEE_interpreter *, struct js_form *, int);
60 static struct js_input *js_get_form_control_object(struct SEE_interpreter *, struct js_form *, enum form_type, int);
62 static void js_form_elems_item(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
63 static void js_form_elems_namedItem(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
64 static void form_elems_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
65 static int form_elems_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
67 static void js_forms_item(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
68 static void js_forms_namedItem(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
69 static void forms_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
70 static int forms_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
72 static void form_get(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *);
73 static void form_put(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *, struct SEE_value *, int);
74 static int form_canput(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
75 static int form_hasproperty(struct SEE_interpreter *, struct SEE_object *, struct SEE_string *);
76 static void js_form_reset(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
77 static void js_form_submit(struct SEE_interpreter *, struct SEE_object *, struct SEE_object *, int, struct SEE_value **, struct SEE_value *);
80 struct SEE_objectclass js_input_object_class = {
81 "input",
82 input_get,
83 input_put,
84 input_canput,
85 input_hasproperty,
86 SEE_no_delete,
87 SEE_no_defaultvalue,
88 NULL,
89 NULL,
90 NULL,
91 NULL
94 struct SEE_objectclass js_form_elems_class = {
95 "elements",
96 form_elems_get,
97 SEE_no_put,
98 SEE_no_canput,
99 form_elems_hasproperty,
100 SEE_no_delete,
101 SEE_no_defaultvalue,
102 NULL,
103 NULL,
104 NULL,
105 NULL
108 struct SEE_objectclass js_forms_object_class = {
109 "forms",
110 forms_get,
111 SEE_no_put,
112 SEE_no_canput,
113 forms_hasproperty,
114 SEE_no_delete,
115 SEE_no_defaultvalue,
116 NULL,
117 NULL,
118 NULL,
119 NULL
122 struct SEE_objectclass js_form_class = {
123 "form",
124 form_get,
125 form_put,
126 form_canput,
127 form_hasproperty,
128 SEE_no_delete,
129 SEE_no_defaultvalue,
130 NULL,
131 NULL,
132 NULL,
133 NULL
136 struct js_input {
137 struct SEE_object object;
138 struct js_form *parent;
139 struct SEE_object *blur;
140 struct SEE_object *click;
141 struct SEE_object *focus;
142 struct SEE_object *select;
143 int form_number;
146 struct js_forms_object {
147 struct SEE_object object;
148 struct js_document_object *parent;
149 struct SEE_object *item;
150 struct SEE_object *namedItem;
153 struct js_form_elems {
154 struct SEE_object object;
155 struct js_form *parent;
156 struct SEE_object *item;
157 struct SEE_object *namedItem;
161 static void
162 input_get(struct SEE_interpreter *interp, struct SEE_object *o,
163 struct SEE_string *p, struct SEE_value *res)
165 struct global_object *g = (struct global_object *)interp;
166 struct view_state *vs = g->win->vs;
167 struct document_view *doc_view = vs->doc_view;
168 struct document *document = doc_view->document;
169 struct js_input *input = (struct js_input *)o;
170 struct js_form *parent = input->parent;
171 struct form_state *fs = &vs->form_info[input->form_number];
172 struct form_control *fc = find_form_control(document, fs);
173 int linknum;
174 struct link *link = NULL;
175 struct SEE_string *str;
177 assert(fc);
178 assert(fc->form && fs);
180 linknum = get_form_control_link(document, fc);
181 /* Hiddens have no link. */
182 if (linknum >= 0) link = &document->links[linknum];
183 SEE_SET_UNDEFINED(res);
185 if (p == s_accessKey) {
186 struct SEE_string *keystr;
187 if (!link)
188 return;
190 keystr = SEE_string_new(interp, 0);
191 if (link->accesskey)
192 append_unicode_to_SEE_string(interp, keystr,
193 link->accesskey);
194 SEE_SET_STRING(res, keystr);
195 } else if (p == s_alt) {
196 str = string_to_SEE_string(interp, fc->alt);
197 SEE_SET_STRING(res, str);
198 } else if (p == s_checked) {
199 SEE_SET_BOOLEAN(res, fs->state);
200 } else if (p == s_defaultChecked) {
201 SEE_SET_BOOLEAN(res, fc->default_state);
202 } else if (p == s_defaultValue) {
203 /* FIXME (bug 805): convert from the charset of the document */
204 str = string_to_SEE_string(interp, fc->default_value);
205 SEE_SET_STRING(res, str);
206 } else if (p == s_disabled) {
207 /* FIXME: <input readonly disabled> --pasky */
208 SEE_SET_BOOLEAN(res, fc->mode == FORM_MODE_DISABLED);
209 } else if (p == s_form) {
210 SEE_SET_OBJECT(res, (struct SEE_object *)parent);
211 } else if (p == s_maxLength) {
212 SEE_SET_NUMBER(res, fc->maxlength);
213 } else if (p == s_name) {
214 str = string_to_SEE_string(interp, fc->name);
215 SEE_SET_STRING(res, str);
216 } else if (p == s_readonly) {
217 /* FIXME: <input readonly disabled> --pasky */
218 SEE_SET_BOOLEAN(res, fc->mode == FORM_MODE_READONLY);
219 } else if (p == s_size) {
220 SEE_SET_NUMBER(res, fc->size);
221 } else if (p == s_src) {
222 if (link && link->where_img) {
223 str = string_to_SEE_string(interp, link->where_img);
224 SEE_SET_STRING(res, str);
226 } else if (p == s_tabindex) {
227 if (link) {
228 /* FIXME: This is WRONG. --pasky */
229 SEE_SET_NUMBER(res, link->number);
231 } else if (p == s_type) {
232 switch (fc->type) {
233 case FC_TEXT: str = s_text; break;
234 case FC_PASSWORD: str = s_password; break;
235 case FC_FILE: str = s_file; break;
236 case FC_CHECKBOX: str = s_checkbox; break;
237 case FC_RADIO: str = s_radio; break;
238 case FC_SUBMIT: str = s_submit; break;
239 case FC_IMAGE: str = s_image; break;
240 case FC_RESET: str = s_reset; break;
241 case FC_BUTTON: str = s_button; break;
242 case FC_HIDDEN: str = s_hidden; break;
243 case FC_SELECT: str = s_select; break;
244 default: str = NULL;
246 if (str) {
247 SEE_SET_STRING(res, str);
249 } else if (p == s_value) {
250 str = string_to_SEE_string(interp, fs->value);
251 SEE_SET_STRING(res, str);
252 } else if (p == s_selectedIndex) {
253 if (fc->type == FC_SELECT) SEE_SET_NUMBER(res, fs->state);
254 } else if (p == s_blur) {
255 SEE_SET_OBJECT(res, input->blur);
256 } else if (p == s_click) {
257 SEE_SET_OBJECT(res, input->click);
258 } else if (p == s_focus) {
259 SEE_SET_OBJECT(res, input->focus);
260 } else if (p == s_select) {
261 SEE_SET_OBJECT(res, input->select);
265 static void
266 input_put(struct SEE_interpreter *interp, struct SEE_object *o,
267 struct SEE_string *p, struct SEE_value *val, int attr)
269 struct global_object *g = (struct global_object *)interp;
270 struct view_state *vs = g->win->vs;
271 struct document_view *doc_view = vs->doc_view;
272 struct document *document = doc_view->document;
273 struct js_input *input = (struct js_input *)o;
274 struct form_state *fs = &vs->form_info[input->form_number];
275 struct form_control *fc = find_form_control(document, fs);
276 int linknum;
277 struct link *link = NULL;
278 unsigned char *string = NULL;
280 assert(fc);
281 assert(fc->form && fs);
283 linknum = get_form_control_link(document, fc);
284 /* Hiddens have no link. */
285 if (linknum >= 0) link = &document->links[linknum];
287 if (p == s_accessKey) {
288 struct SEE_value conv;
289 unicode_val_T accesskey;
291 SEE_ToString(interp, val, &conv);
292 if (conv.u.string->length)
293 accesskey = SEE_string_to_unicode(interp, conv.u.string);
294 else
295 accesskey = 0;
297 if (link)
298 link->accesskey = accesskey;
299 } else if (p == s_alt) {
300 string = SEE_value_to_unsigned_char(interp, val);
301 mem_free_set(&fc->alt, string);
302 } else if (p == s_checked) {
303 if (fc->type != FC_CHECKBOX && fc->type != FC_RADIO)
304 return;
305 fs->state = SEE_ToUint32(interp, val);
306 } else if (p == s_disabled) {
307 /* FIXME: <input readonly disabled> --pasky */
308 SEE_uint32_t boo = SEE_ToUint32(interp, val);
309 fc->mode = (boo ? FORM_MODE_DISABLED
310 : (fc->mode == FORM_MODE_READONLY ? FORM_MODE_READONLY
311 : FORM_MODE_NORMAL));
312 } else if (p == s_maxLength) {
313 string = SEE_value_to_unsigned_char(interp, val);
314 if (!string)
315 return;
316 fc->maxlength = atol(string);
317 mem_free(string);
318 } else if (p == s_name) {
319 string = SEE_value_to_unsigned_char(interp, val);
320 mem_free_set(&fc->name, string);
321 } else if (p == s_readonly) {
322 SEE_uint32_t boo = SEE_ToUint32(interp, val);
323 fc->mode = (boo ? FORM_MODE_READONLY
324 : fc->mode == FORM_MODE_DISABLED ? FORM_MODE_DISABLED
325 : FORM_MODE_NORMAL);
326 } else if (p == s_src) {
327 if (link) {
328 string = SEE_value_to_unsigned_char(interp, val);
329 mem_free_set(&link->where_img, string);
331 } else if (p == s_value) {
332 if (fc->type == FC_FILE)
333 return;
334 string = SEE_value_to_unsigned_char(interp, val);
335 mem_free_set(&fs->value, string);
336 if (fc->type == FC_TEXT || fc->type == FC_PASSWORD)
337 fs->state = strlen(fs->value);
338 } else if (p == s_selectedIndex) {
339 if (fc->type == FC_SELECT) {
340 SEE_uint32_t item = SEE_ToUint32(interp, val);
342 if (item >=0 && item < fc->nvalues) {
343 fs->state = item;
344 mem_free_set(&fs->value, stracpy(fc->values[item]));
350 static void
351 js_input_blur(struct SEE_interpreter *interp, struct SEE_object *self,
352 struct SEE_object *thisobj, int argc, struct SEE_value **argv,
353 struct SEE_value *res)
355 see_check_class(interp, thisobj, &js_input_object_class);
356 SEE_SET_BOOLEAN(res, 0);
357 /* We are a text-mode browser and there *always* has to be something
358 * selected. So we do nothing for now. (That was easy.) */
361 static void
362 js_input_click(struct SEE_interpreter *interp, struct SEE_object *self,
363 struct SEE_object *thisobj, int argc, struct SEE_value **argv,
364 struct SEE_value *res)
366 struct global_object *g = (struct global_object *)interp;
367 struct view_state *vs = g->win->vs;
368 struct document_view *doc_view = vs->doc_view;
369 struct document *document = doc_view->document;
370 struct session *ses = doc_view->session;
371 struct js_input *input = (
372 see_check_class(interp, thisobj, &js_input_object_class),
373 (struct js_input *)thisobj);
374 struct form_state *fs = &vs->form_info[input->form_number];
375 struct form_control *fc;
376 int linknum;
378 SEE_SET_BOOLEAN(res, 0);
379 assert(fs);
380 fc = find_form_control(document, fs);
381 assert(fc);
383 linknum = get_form_control_link(document, fc);
384 /* Hiddens have no link. */
385 if (linknum < 0)
386 return;
388 /* Restore old current_link afterwards? */
389 jump_to_link_number(ses, doc_view, linknum);
390 if (enter(ses, doc_view, 0) == FRAME_EVENT_REFRESH)
391 refresh_view(ses, doc_view, 0);
392 else
393 print_screen_status(ses);
396 static void
397 js_input_focus(struct SEE_interpreter *interp, struct SEE_object *self,
398 struct SEE_object *thisobj, int argc, struct SEE_value **argv,
399 struct SEE_value *res)
401 struct global_object *g = (struct global_object *)interp;
402 struct view_state *vs = g->win->vs;
403 struct document_view *doc_view = vs->doc_view;
404 struct document *document = doc_view->document;
405 struct session *ses = doc_view->session;
406 struct js_input *input = (
407 see_check_class(interp, thisobj, &js_input_object_class),
408 (struct js_input *)thisobj);
409 struct form_state *fs = &vs->form_info[input->form_number];
410 struct form_control *fc;
411 int linknum;
413 SEE_SET_BOOLEAN(res, 0);
414 assert(fs);
415 fc = find_form_control(document, fs);
416 assert(fc);
418 linknum = get_form_control_link(document, fc);
419 /* Hiddens have no link. */
420 if (linknum < 0)
421 return;
423 jump_to_link_number(ses, doc_view, linknum);
427 static void
428 js_input_select(struct SEE_interpreter *interp, struct SEE_object *self,
429 struct SEE_object *thisobj, int argc, struct SEE_value **argv,
430 struct SEE_value *res)
432 see_check_class(interp, thisobj, &js_input_object_class);
433 SEE_SET_BOOLEAN(res, 0);
434 /* We support no text selecting yet. So we do nothing for now.
435 * (That was easy, too.) */
438 static int
439 input_canput(struct SEE_interpreter *interp, struct SEE_object *o,
440 struct SEE_string *p)
442 return 1;
445 static int
446 input_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
447 struct SEE_string *p)
449 /* all unknown properties return UNDEFINED value */
450 return 1;
453 static struct js_input *
454 js_get_input_object(struct SEE_interpreter *interp, struct js_form *jsform, int num)
456 struct js_input *jsinput;
459 #if 0
460 if (fs->ecmascript_obj)
461 return fs->ecmascript_obj;
462 #endif
463 /* jsform ('form') is input's parent */
464 /* FIXME: That is NOT correct since the real containing element
465 * should be its parent, but gimme DOM first. --pasky */
466 jsinput = SEE_NEW(interp, struct js_input);
468 jsinput->object.objectclass = &js_input_object_class;
469 jsinput->object.Prototype = NULL;
471 jsinput->blur = SEE_cfunction_make(interp, js_input_blur, s_blur, 0);
472 jsinput->click = SEE_cfunction_make(interp, js_input_click, s_click, 0);
473 jsinput->focus = SEE_cfunction_make(interp, js_input_focus, s_focus, 0);
474 jsinput->select = SEE_cfunction_make(interp, js_input_select, s_select, 0);
476 jsinput->form_number = num;
477 jsinput->parent = jsform;
478 return jsinput;
481 static struct js_input *
482 js_get_form_control_object(struct SEE_interpreter *interp, struct js_form *jsform,
483 enum form_type type, int num)
485 switch (type) {
486 case FC_TEXT:
487 case FC_PASSWORD:
488 case FC_FILE:
489 case FC_CHECKBOX:
490 case FC_RADIO:
491 case FC_SUBMIT:
492 case FC_IMAGE:
493 case FC_RESET:
494 case FC_BUTTON:
495 case FC_HIDDEN:
496 case FC_SELECT:
497 return js_get_input_object(interp, jsform, num);
499 case FC_TEXTAREA:
500 /* TODO */
501 return NULL;
503 default:
504 INTERNAL("Weird fc->type %d", type);
505 return NULL;
512 static void
513 js_form_elems_item(struct SEE_interpreter *interp, struct SEE_object *self,
514 struct SEE_object *thisobj, int argc, struct SEE_value **argv,
515 struct SEE_value *res)
517 struct global_object *g = (struct global_object *)interp;
518 struct view_state *vs = g->win->vs;
519 struct document_view *doc_view = vs->doc_view;
520 struct document *document = doc_view->document;
521 struct js_form_elems *jsfe = (
522 see_check_class(interp, thisobj, &js_form_elems_class),
523 (struct js_form_elems *)thisobj);
524 struct js_form *parent_form = jsfe->parent;
525 struct form_view *fv = parent_form->fv;
526 struct form *form = find_form_by_form_view(document, fv);
527 struct form_control *fc;
528 unsigned char *string;
529 int counter = -1;
530 int index;
532 SEE_SET_UNDEFINED(res);
533 if (argc < 1)
534 return;
535 string = SEE_value_to_unsigned_char(interp, argv[0]);
536 if (!string)
537 return;
538 index = atol(string);
539 mem_free(string);
541 foreach (fc, form->items) {
542 counter++;
543 if (counter == index) {
544 struct form_state *fs = find_form_state(doc_view, fc);
546 if (fs) {
547 struct js_input *fcobj = js_get_form_control_object(interp, parent_form, fc->type, fc->g_ctrl_num);
549 if (fcobj)
550 SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
552 break;
558 static void
559 js_form_elems_namedItem(struct SEE_interpreter *interp, struct SEE_object *self,
560 struct SEE_object *thisobj, int argc, struct SEE_value **argv,
561 struct SEE_value *res)
563 struct global_object *g = (struct global_object *)interp;
564 struct view_state *vs = g->win->vs;
565 struct document_view *doc_view = vs->doc_view;
566 struct document *document = doc_view->document;
567 struct js_form_elems *jsfe = (
568 see_check_class(interp, thisobj, &js_form_elems_class),
569 (struct js_form_elems *)thisobj);
570 struct js_form *parent_form = jsfe->parent;
571 struct form_view *fv = parent_form->fv;
572 struct form *form = find_form_by_form_view(document, fv);
573 struct form_control *fc;
574 unsigned char *string;
576 SEE_SET_UNDEFINED(res);
577 if (argc < 1)
578 return;
579 string = SEE_value_to_unsigned_char(interp, argv[0]);
580 if (!string)
581 return;
583 foreach (fc, form->items) {
584 if ((fc->id && !strcasecmp(string, fc->id)) || (fc->name && !strcasecmp(string, fc->name))) {
585 struct form_state *fs = find_form_state(doc_view, fc);
587 if (fs) {
588 struct js_input *fcobj = js_get_form_control_object(interp, parent_form, fc->type, fc->g_ctrl_num);
590 if (fcobj)
591 SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
593 break;
596 mem_free(string);
599 static void
600 form_elems_get(struct SEE_interpreter *interp, struct SEE_object *o,
601 struct SEE_string *p, struct SEE_value *res)
603 struct global_object *g = (struct global_object *)interp;
604 struct view_state *vs = g->win->vs;
605 struct document_view *doc_view = vs->doc_view;
606 struct document *document = doc_view->document;
607 struct js_form_elems *jsfe = (struct js_form_elems *)o;
608 struct js_form *parent_form = jsfe->parent;
609 struct form_view *fv = parent_form->fv;
610 struct form *form = find_form_by_form_view(document, fv);
612 if (p == s_length) {
613 SEE_number_t length = list_size(&form->items);
614 SEE_SET_NUMBER(res, length);
615 } else if (p == s_item) {
616 SEE_SET_OBJECT(res, jsfe->item);
617 } else if (p == s_namedItem) {
618 SEE_SET_OBJECT(res, jsfe->namedItem);
619 } else {
620 unsigned char *string = SEE_string_to_unsigned_char(p);
621 struct SEE_value argv;
622 struct SEE_value *pargv = &argv;
624 if (!string) {
625 SEE_SET_UNDEFINED(res);
626 return;
628 SEE_SET_STRING(pargv, p);
629 if (string[0] >= '0' && string[0] <= '9') {
630 js_form_elems_item(interp, jsfe->item, o, 1,
631 &pargv, res);
632 } else {
633 js_form_elems_namedItem(interp, jsfe->namedItem, o, 1,
634 &pargv, res);
636 mem_free(string);
640 static int
641 form_elems_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
642 struct SEE_string *p)
644 /* all unknown properties return UNDEFINED value */
645 return 1;
649 static void
650 js_forms_item(struct SEE_interpreter *interp, struct SEE_object *self,
651 struct SEE_object *thisobj, int argc, struct SEE_value **argv,
652 struct SEE_value *res)
654 struct global_object *g = (struct global_object *)interp;
655 struct view_state *vs = g->win->vs;
656 struct js_forms_object *fo = (
657 see_check_class(interp, thisobj, &js_forms_object_class),
658 (struct js_forms_object *)thisobj);
659 struct js_document_object *doc = fo->parent;
660 struct form_view *fv;
661 unsigned char *string;
662 int counter = -1;
663 int index;
665 SEE_SET_UNDEFINED(res);
666 if (argc < 1)
667 return;
669 string = SEE_value_to_unsigned_char(interp, argv[0]);
670 if (!string)
671 return;
672 index = atol(string);
673 mem_free(string);
675 foreach (fv, vs->forms) {
676 counter++;
677 if (counter == index) {
678 struct js_form *obj = js_get_form_object(interp, doc, fv);
680 SEE_SET_OBJECT(res, (struct SEE_object *)obj);
681 break;
686 static void
687 js_forms_namedItem(struct SEE_interpreter *interp, struct SEE_object *self,
688 struct SEE_object *thisobj, int argc, struct SEE_value **argv,
689 struct SEE_value *res)
691 struct global_object *g = (struct global_object *)interp;
692 struct view_state *vs = g->win->vs;
693 struct document_view *doc_view = vs->doc_view;
694 struct document *document = doc_view->document;
695 struct js_forms_object *fo = (
696 see_check_class(interp, thisobj, &js_forms_object_class),
697 (struct js_forms_object *)thisobj);
698 struct js_document_object *doc = fo->parent;
699 struct form *form;
700 unsigned char *string;
702 SEE_SET_UNDEFINED(res);
703 if (argc < 1)
704 return;
706 string = SEE_value_to_unsigned_char(interp, argv[0]);
707 if (!string)
708 return;
709 foreach (form, document->forms) {
710 if (form->name && !strcasecmp(string, form->name)) {
711 struct form_view *fv = find_form_view(doc_view, form);
712 struct js_form *obj = js_get_form_object(interp,
713 doc, fv);
715 SEE_SET_OBJECT(res, (struct SEE_object *)obj);
716 break;
720 mem_free(string);
723 static void
724 forms_get(struct SEE_interpreter *interp, struct SEE_object *o,
725 struct SEE_string *p, struct SEE_value *res)
727 struct global_object *g = (struct global_object *)interp;
728 struct view_state *vs = g->win->vs;
729 struct document_view *doc_view = vs->doc_view;
730 struct document *document = doc_view->document;
731 struct js_forms_object *fo = (struct js_forms_object *)o;
733 if (p == s_length) {
734 SEE_number_t length = list_size(&document->forms);
735 SEE_SET_NUMBER(res, length);
736 } else if (p == s_item) {
737 SEE_SET_OBJECT(res, fo->item);
738 } else if (p == s_namedItem) {
739 SEE_SET_OBJECT(res, fo->namedItem);
740 } else {
741 unsigned char *string = SEE_string_to_unsigned_char(p);
742 struct SEE_value argv;
743 struct SEE_value *argv1 = &argv;
745 if (!string) {
746 SEE_SET_UNDEFINED(res);
747 return;
749 SEE_SET_STRING(argv1, p);
750 if (string[0] >= '0' && string[0] <= '9') {
751 js_forms_item(interp, fo->item, o, 1, &argv1, res);
752 } else {
753 js_forms_namedItem(interp, fo->namedItem, o, 1, &argv1, res);
755 mem_free(string);
759 static int
760 forms_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
761 struct SEE_string *p)
763 /* all unknown properties return UNDEFINED value */
764 return 1;
769 static void
770 form_get(struct SEE_interpreter *interp, struct SEE_object *o,
771 struct SEE_string *p, struct SEE_value *res)
773 struct global_object *g = (struct global_object *)interp;
774 struct view_state *vs = g->win->vs;
775 struct document_view *doc_view = vs->doc_view;
776 struct js_form *js_form = (struct js_form *)o;
777 struct form_view *fv = js_form->fv;
778 struct form *form = find_form_by_form_view(doc_view->document, fv);
779 struct SEE_string *str;
781 SEE_SET_UNDEFINED(res);
783 if (p == s_action) {
784 str = string_to_SEE_string(interp, form->action);
785 SEE_SET_STRING(res, str);
786 } else if (p == s_encoding) {
787 switch (form->method) {
788 case FORM_METHOD_GET:
789 case FORM_METHOD_POST:
790 /* "application/x-www-form-urlencoded" */
791 SEE_SET_STRING(res, s_application_);
792 break;
793 case FORM_METHOD_POST_MP:
794 /* "multipart/form-data" */
795 SEE_SET_STRING(res, s_multipart_);
796 break;
797 case FORM_METHOD_POST_TEXT_PLAIN:
798 /* "text/plain") */
799 SEE_SET_STRING(res, s_textplain);
800 break;
802 } else if (p == s_length) {
803 SEE_number_t num = list_size(&form->items);
804 SEE_SET_NUMBER(res, num);
805 } else if (p == s_method) {
806 switch (form->method) {
807 case FORM_METHOD_GET:
808 SEE_SET_STRING(res, s_GET);
809 break;
811 case FORM_METHOD_POST:
812 case FORM_METHOD_POST_MP:
813 case FORM_METHOD_POST_TEXT_PLAIN:
814 SEE_SET_STRING(res, s_POST);
815 break;
817 } else if (p == s_name) {
818 str = string_to_SEE_string(interp, form->name);
819 SEE_SET_STRING(res, str);
820 } else if (p == s_target) {
821 str = string_to_SEE_string(interp, form->target);
822 SEE_SET_STRING(res, str);
823 } else if (p == s_elements) {
824 struct js_form_elems *jsfe = SEE_NEW(interp, struct js_form_elems);
826 jsfe->object.objectclass = &js_form_elems_class;
827 jsfe->object.Prototype = NULL;
828 jsfe->parent = js_form;
829 jsfe->item = SEE_cfunction_make(interp, js_form_elems_item, s_item, 1);
830 jsfe->namedItem = SEE_cfunction_make(interp, js_form_elems_namedItem, s_namedItem, 1);
831 SEE_SET_OBJECT(res, (struct SEE_object *)jsfe);
832 } else if (p == s_submit) {
833 SEE_SET_OBJECT(res, js_form->submit);
834 } else if (p == s_reset) {
835 SEE_SET_OBJECT(res, js_form->reset);
836 } else {
837 unsigned char *string = SEE_string_to_unsigned_char(p);
838 struct form_control *fc;
840 if (!string)
841 return;
843 foreach(fc, form->items) {
844 struct js_input *fcobj = NULL;
845 struct form_state *fs;
847 if ((!fc->id || strcasecmp(string, fc->id)) && (!fc->name || strcasecmp(string, fc->name)))
848 continue;
849 fs = find_form_state(doc_view, fc);
850 if (fs) {
851 fcobj = js_get_form_control_object(interp, js_form, fc->type, fc->g_ctrl_num);
853 if (fcobj)
854 SEE_SET_OBJECT(res, (struct SEE_object *)fcobj);
856 break;
858 mem_free(string);
862 static void
863 form_put(struct SEE_interpreter *interp, struct SEE_object *o,
864 struct SEE_string *p, struct SEE_value *val, int attr)
866 struct global_object *g = (struct global_object *)interp;
867 struct view_state *vs = g->win->vs;
868 struct document_view *doc_view = vs->doc_view;
869 struct js_form *js_form = (struct js_form *)o;
870 struct form_view *fv = js_form->fv;
871 struct form *form = find_form_by_form_view(doc_view->document, fv);
872 unsigned char *string = SEE_value_to_unsigned_char(interp, val);
874 if (!string)
875 return;
877 if (p == s_action) {
878 if (form->action) {
879 ecmascript_set_action(&form->action, string);
880 } else {
881 mem_free_set(&form->action, string);
883 } else if (p == s_encoding) {
884 if (!strcasecmp(string, "application/x-www-form-urlencoded")) {
885 form->method = form->method == FORM_METHOD_GET ? FORM_METHOD_GET
886 : FORM_METHOD_POST;
887 } else if (!strcasecmp(string, "multipart/form-data")) {
888 form->method = FORM_METHOD_POST_MP;
889 } else if (!strcasecmp(string, "text/plain")) {
890 form->method = FORM_METHOD_POST_TEXT_PLAIN;
892 mem_free(string);
893 } else if (p == s_method) {
894 if (!strcasecmp(string, "GET")) {
895 form->method = FORM_METHOD_GET;
896 } else if (!strcasecmp(string, "POST")) {
897 form->method = FORM_METHOD_POST;
899 mem_free(string);
900 } else if (p == s_name) {
901 mem_free_set(&form->name, string);
902 } else if (p == s_target) {
903 mem_free_set(&form->target, string);
907 static int
908 form_canput(struct SEE_interpreter *interp, struct SEE_object *o,
909 struct SEE_string *p)
911 return 1;
914 static int
915 form_hasproperty(struct SEE_interpreter *interp, struct SEE_object *o,
916 struct SEE_string *p)
918 return 1;
921 static void
922 js_form_reset(struct SEE_interpreter *interp, struct SEE_object *self,
923 struct SEE_object *thisobj, int argc, struct SEE_value **argv,
924 struct SEE_value *res)
926 struct global_object *g = (struct global_object *)interp;
927 struct view_state *vs = g->win->vs;
928 struct document_view *doc_view = vs->doc_view;
929 struct js_form *js_form = (
930 see_check_class(interp, thisobj, &js_form_class),
931 (struct js_form *)thisobj);
932 struct form_view *fv = js_form->fv;
933 struct form *form = find_form_by_form_view(doc_view->document, fv);
935 assert(form);
937 do_reset_form(doc_view, form);
938 draw_forms(doc_view->session->tab->term, doc_view);
939 SEE_SET_BOOLEAN(res, 0);
942 static void
943 js_form_submit(struct SEE_interpreter *interp, struct SEE_object *self,
944 struct SEE_object *thisobj, int argc, struct SEE_value **argv,
945 struct SEE_value *res)
947 struct global_object *g = (struct global_object *)interp;
948 struct view_state *vs = g->win->vs;
949 struct document_view *doc_view = vs->doc_view;
950 struct session *ses = doc_view->session;
951 struct js_form *js_form = (
952 see_check_class(interp, thisobj, &js_form_class),
953 (struct js_form *)thisobj);
954 struct form_view *fv = js_form->fv;
955 struct form *form = find_form_by_form_view(doc_view->document, fv);
957 assert(form);
958 submit_given_form(ses, doc_view, form, 0);
959 SEE_SET_BOOLEAN(res, 0);
962 struct js_form *js_get_form_object(struct SEE_interpreter *interp,
963 struct js_document_object *doc, struct form_view *fv)
965 struct js_form *js_form;
967 #if 0
968 if (fv->ecmascript_obj)
969 return fv->ecmascript_obj;
970 #endif
971 /* jsdoc ('document') is fv's parent */
972 /* FIXME: That is NOT correct since the real containing element
973 * should be its parent, but gimme DOM first. --pasky */
974 js_form = SEE_NEW(interp, struct js_form);
975 js_form->object.objectclass = &js_form_class;
976 js_form->object.Prototype = NULL; /* TODO: use prototype for form */
977 js_form->parent = doc;
978 js_form->reset = SEE_cfunction_make(interp, js_form_reset, s_reset, 0);
979 js_form->submit = SEE_cfunction_make(interp, js_form_submit, s_submit, 0);
980 js_form->fv = fv;
982 fv->ecmascript_obj = js_form;
983 return js_form;
986 void
987 init_js_forms_object(struct ecmascript_interpreter *interpreter)
989 struct global_object *g = interpreter->backend_data;
990 struct SEE_interpreter *interp = &g->interp;
991 struct SEE_value v, document;
992 struct js_forms_object *forms = SEE_NEW(interp,
993 struct js_forms_object);
995 forms->object.objectclass = &js_forms_object_class;
996 forms->object.Prototype = NULL;
998 SEE_OBJECT_GET(interp, interp->Global, s_document, &document);
999 SEE_SET_OBJECT(&v, (struct SEE_object *)forms);
1000 SEE_OBJECT_PUT(interp, document.u.object, s_forms, &v, 0);
1002 forms->item = SEE_cfunction_make(interp, js_forms_item, s_item, 1);
1003 forms->namedItem = SEE_cfunction_make(interp, js_forms_namedItem,
1004 s_namedItem, 1);
1005 forms->parent = (struct js_document_object *)document.u.object;