📄 form.c
字号:
ulonghexcat(p, NULL, (int) data.source[i], 2, '0', 0); add_to_string(&go, p); } } } done_string(&data); uri = get_uri(go.source, 0); done_string(&go); if (uri) uri->form = 1; return uri;}#undef BOUNDARY_LENGTHenum frame_event_statussubmit_form(struct session *ses, struct document_view *doc_view, int do_reload){ goto_current_link(ses, doc_view, do_reload); return FRAME_EVENT_OK;}voidsubmit_given_form(struct session *ses, struct document_view *doc_view, struct form *form){ struct document *document = doc_view->document; int link; for (link = 0; link < document->nlinks; link++) { struct form_control *fc = get_link_form_control(&document->links[link]); if (fc && fc->form == form) { doc_view->vs->current_link = link; submit_form(ses, doc_view, 0); return; } }}voidauto_submit_form(struct session *ses){ struct document *document = ses->doc_view->document; if (!list_empty(document->forms)) submit_given_form(ses, ses->doc_view, document->forms.next);}/* menu_func */static voidset_file_form_state(struct terminal *term, void *filename_, void *fs_){ unsigned char *filename = filename_; struct form_state *fs = fs_; /* The menu code doesn't free the filename data */ mem_free_set(&fs->value, filename); fs->state = strlen(filename); redraw_terminal(term);}/* menu_func */static voidfile_form_menu(struct terminal *term, void *path_, void *fs_){ unsigned char *path = path_; struct form_state *fs = fs_; /* FIXME: It doesn't work for ../../ */#if 0 int valuelen = strlen(fs->value); int pathlen = strlen(path); int no_elevator = 0; /* Don't add elevators for subdirs menus */ /* It is not perfect at all because fs->value is not updated for each * newly opened file menu. Maybe it should be dropped. */ for (; valuelen < pathlen; valuelen++) { if (dir_sep(path[valuelen - 1])) { no_elevator = 1; break; } }#endif auto_complete_file(term, 0 /* no_elevator */, path, set_file_form_state, file_form_menu, fs);}enum frame_event_statusfield_op(struct session *ses, struct document_view *doc_view, struct link *link, struct term_event *ev){ struct form_control *fc; struct form_state *fs; enum edit_action action; unsigned char *text; int length; enum frame_event_status status = FRAME_EVENT_REFRESH; assert(ses && doc_view && link && ev); if_assert_failed return FRAME_EVENT_OK; fc = get_link_form_control(link); assertm(fc, "link has no form control"); if_assert_failed return FRAME_EVENT_OK; if (fc->mode == FORM_MODE_DISABLED || ev->ev != EVENT_KBD) return FRAME_EVENT_IGNORED; action = kbd_action(KEYMAP_EDIT, ev, NULL); if (ses->insert_mode == INSERT_MODE_OFF) { if (action == ACT_EDIT_ENTER) { ses->insert_mode = INSERT_MODE_ON; return FRAME_EVENT_REFRESH; } return FRAME_EVENT_IGNORED; } fs = find_form_state(doc_view, fc); if (!fs || !fs->value) return FRAME_EVENT_OK; switch (action) { case ACT_EDIT_LEFT: fs->state = int_max(fs->state - 1, 0); break; case ACT_EDIT_RIGHT: fs->state = int_min(fs->state + 1, strlen(fs->value)); break; case ACT_EDIT_HOME: if (fc->type == FC_TEXTAREA) { status = textarea_op_home(fs, fc); } else { fs->state = 0; } break; case ACT_EDIT_UP: if (fc->type != FC_TEXTAREA) status = FRAME_EVENT_IGNORED; else status = textarea_op_up(fs, fc); break; case ACT_EDIT_DOWN: if (fc->type != FC_TEXTAREA) status = FRAME_EVENT_IGNORED; else status = textarea_op_down(fs, fc); break; case ACT_EDIT_END: if (fc->type == FC_TEXTAREA) { status = textarea_op_end(fs, fc); } else { fs->state = strlen(fs->value); } break; case ACT_EDIT_BEGINNING_OF_BUFFER: if (fc->type == FC_TEXTAREA) { status = textarea_op_bob(fs, fc); } else { fs->state = 0; } break; case ACT_EDIT_END_OF_BUFFER: if (fc->type == FC_TEXTAREA) { status = textarea_op_eob(fs, fc); } else { fs->state = strlen(fs->value); } break; case ACT_EDIT_OPEN_EXTERNAL: if (form_field_is_readonly(fc)) status = FRAME_EVENT_IGNORED; else if (fc->type == FC_TEXTAREA) textarea_edit(0, ses->tab->term, fs, doc_view, link); break; case ACT_EDIT_COPY_CLIPBOARD: set_clipboard_text(fs->value); status = FRAME_EVENT_OK; break; case ACT_EDIT_CUT_CLIPBOARD: set_clipboard_text(fs->value); if (!form_field_is_readonly(fc)) fs->value[0] = 0; fs->state = 0; break; case ACT_EDIT_PASTE_CLIPBOARD: if (form_field_is_readonly(fc)) break; text = get_clipboard_text(); if (!text) break; length = strlen(text); if (length <= fc->maxlength) { unsigned char *v = mem_realloc(fs->value, length + 1); if (v) { fs->value = v; memmove(v, text, length + 1); fs->state = strlen(fs->value); } } mem_free(text); break; case ACT_EDIT_ENTER: if (fc->type == FC_TEXTAREA) { status = textarea_op_enter(fs, fc); break; } /* Set status to ok if either it is not possible to * submit the form or the posting fails. */ /* FIXME: We should maybe have ACT_EDIT_ENTER_RELOAD */ if ((has_form_submit(fc->form) && !get_opt_bool("document.browse.forms.auto_submit")) || goto_current_link(ses, doc_view, 0)) { if (ses->insert_mode == INSERT_MODE_ON) ses->insert_mode = INSERT_MODE_OFF; status = FRAME_EVENT_OK; } break; case ACT_EDIT_BACKSPACE: if (form_field_is_readonly(fc)) { status = FRAME_EVENT_IGNORED; break; } if (!fs->state) { status = FRAME_EVENT_OK; break; } length = strlen(fs->value + fs->state) + 1; text = fs->value + fs->state; memmove(text - 1, text, length); fs->state--; break; case ACT_EDIT_DELETE: if (form_field_is_readonly(fc)) { status = FRAME_EVENT_IGNORED; break; } length = strlen(fs->value); if (fs->state >= length) { status = FRAME_EVENT_OK; break; } text = fs->value + fs->state; memmove(text, text + 1, length - fs->state); break; case ACT_EDIT_KILL_TO_BOL: if (form_field_is_readonly(fc)) { status = FRAME_EVENT_IGNORED; break; } if (fs->state <= 0) { status = FRAME_EVENT_OK; break; } text = memrchr(fs->value, ASCII_LF, fs->state); if (text) { /* Leave the new-line character if it does not * immediately precede the cursor. */ if (text != &fs->value[fs->state - 1]) text++; } else { text = fs->value; } length = strlen(fs->value + fs->state) + 1; memmove(text, fs->value + fs->state, length); fs->state = (int) (text - fs->value); break; case ACT_EDIT_KILL_TO_EOL: if (form_field_is_readonly(fc)) { status = FRAME_EVENT_IGNORED; break; } if (!fs->value[fs->state]) { status = FRAME_EVENT_OK; break; } text = strchr(fs->value + fs->state, ASCII_LF); if (!text) { fs->value[fs->state] = '\0'; break; } if (fs->value[fs->state] == ASCII_LF) ++text; memmove(fs->value + fs->state, text, strlen(text) + 1); break; case ACT_EDIT_AUTO_COMPLETE: if (fc->type != FC_FILE || form_field_is_readonly(fc)) { status = FRAME_EVENT_IGNORED; break; } file_form_menu(ses->tab->term, fs->value, fs); break; case ACT_EDIT_CANCEL: if (ses->insert_mode == INSERT_MODE_ON) ses->insert_mode = INSERT_MODE_OFF; else status = FRAME_EVENT_IGNORED; break; case ACT_EDIT_REDRAW: redraw_terminal_cls(ses->tab->term); status = FRAME_EVENT_OK; break; default: if (!check_kbd_textinput_key(ev)) { status = FRAME_EVENT_IGNORED; break; } if (form_field_is_readonly(fc) || strlen(fs->value) >= fc->maxlength || !insert_in_string(&fs->value, fs->state, "?", 1)) { status = FRAME_EVENT_OK; break; } fs->value[fs->state++] = get_kbd_key(ev); break; } return status;}unsigned char *get_form_label(struct form_control *fc){ assert(fc->form); switch (fc->type) { case FC_RESET: return N_("Reset form"); case FC_BUTTON: return N_("Harmless button"); case FC_HIDDEN: return NULL; case FC_SUBMIT: case FC_IMAGE: if (!fc->form->action) return NULL; if (fc->form->method == FORM_METHOD_GET) return N_("Submit form to"); return N_("Post form to"); case FC_RADIO: return N_("Radio button"); case FC_CHECKBOX: return N_("Checkbox"); case FC_SELECT: return N_("Select field"); case FC_TEXT: return N_("Text field"); case FC_TEXTAREA: return N_("Text area"); case FC_FILE: return N_("File upload"); case FC_PASSWORD: return N_("Password field"); } return NULL;}static inline voidadd_form_attr_to_string(struct string *string, struct terminal *term, unsigned char *name, unsigned char *value){ add_to_string(string, ", "); add_to_string(string, _(name, term)); if (value) { add_char_to_string(string, ' '); add_to_string(string, value); }}unsigned char *get_form_info(struct session *ses, struct document_view *doc_view){ struct terminal *term = ses->tab->term; struct link *link = get_current_link(doc_view); struct form_control *fc; unsigned char *label, *key; struct string str; assert(link); fc = get_link_form_control(link); label = get_form_label(fc); if (!label) return NULL; if (!init_string(&str)) return NULL; add_to_string(&str, _(label, term)); if (link->type != LINK_BUTTON && fc->name && fc->name[0]) { add_form_attr_to_string(&str, term, N_("name"), fc->name); } switch (fc->type) { case FC_CHECKBOX: case FC_RADIO: { struct form_state *fs = find_form_state(doc_view, fc); if (!fs->value || !fs->value[0]) break; add_form_attr_to_string(&str, term, N_("value"), fs->value); break; } case FC_TEXT: case FC_PASSWORD: case FC_FILE: case FC_TEXTAREA: { struct uri *uri; unsigned char *uristring; if (form_field_is_readonly(fc)) { add_form_attr_to_string(&str, term, N_("read only"), NULL); } /* Should we add info about entering insert mode or add info * about submitting the form? */ if (ses->insert_mode == INSERT_MODE_OFF) { key = get_keystroke(ACT_EDIT_ENTER, KEYMAP_EDIT); if (!key) break; if (form_field_is_readonly(fc)) label = N_("press %s to navigate"); else label = N_("press %s to edit"); add_to_string(&str, " ("); add_format_to_string(&str, _(label, term), key); add_char_to_string(&str, ')'); mem_free(key); break; } if (fc->type == FC_TEXTAREA) break; assert(fc->form); if (!fc->form->action || (has_form_submit(fc->form) && !get_opt_bool("document.browse.forms.auto_submit"))) break; uri = get_uri(fc->form->action, 0); if (!uri) break; /* Add the uri with password and post info stripped */ uristring = get_uri_string(uri, URI_PUBLIC); done_uri(uri); if (!uristring) break; key = get_keystroke(ACT_EDIT_ENTER, KEYMAP_EDIT); if (!key) { mem_free(uristring); break; } if (fc->form->method == FORM_METHOD_GET) label = N_("press %s to submit to %s"); else label = N_("press %s to post to %s"); add_to_string(&str, " ("); add_format_to_string(&str, _(label, term), key, uristring); mem_free(uristring); mem_free(key); add_char_to_string(&str, ')'); break; } case FC_SUBMIT: case FC_IMAGE: add_char_to_string(&str, ' '); assert(fc->form); /* Add the uri with password and post info stripped */ add_string_uri_to_string(&str, fc->form->action, URI_PUBLIC); break; case FC_HIDDEN: case FC_RESET: case FC_BUTTON: case FC_SELECT: break; } if (link->accesskey && get_opt_bool("document.browse.accesskey.display")) { add_to_string(&str, " ("); make_keystroke(&str, link->accesskey, 0, 0); add_char_to_string(&str, ')'); } return str.source;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -