diff options
author | Paul Gardiner <paul@glidos.net> | 2012-05-08 14:29:37 +0100 |
---|---|---|
committer | Paul Gardiner <paul@glidos.net> | 2012-05-08 14:29:37 +0100 |
commit | 91b4f1249cd6545a791e02e1632d69164702b4a0 (patch) | |
tree | 2023f48628202e835a2110aa8e5ce0fe691ae221 | |
parent | cc0a9593eced73291c657ec80aa02137c7c3b833 (diff) | |
download | mupdf-91b4f1249cd6545a791e02e1632d69164702b4a0.tar.xz |
Forms: part of text field handling
-rw-r--r-- | apps/pdfapp.c | 9 | ||||
-rw-r--r-- | fitz/fitz-internal.h | 8 | ||||
-rw-r--r-- | fitz/fitz.h | 2 | ||||
-rw-r--r-- | pdf/mupdf-internal.h | 2 | ||||
-rw-r--r-- | pdf/pdf_form.c | 191 | ||||
-rw-r--r-- | pdf/pdf_xref.c | 2 |
6 files changed, 182 insertions, 32 deletions
diff --git a/apps/pdfapp.c b/apps/pdfapp.c index 925d9751..2f213bc4 100644 --- a/apps/pdfapp.c +++ b/apps/pdfapp.c @@ -978,9 +978,18 @@ void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int sta if (fz_pass_event(app->doc, app->page, &event)) { + fz_widget *widget; + app->nowaitcursor = 1; pdfapp_showpage(app, 1, 1, 1); app->nowaitcursor = 0; + widget = fz_get_focussed_widget(app->doc); + + if (widget && fz_widget_get_type(widget) == FZ_WIDGET_TYPE_TEXT) + { + char *text = fz_widget_text_get_text((fz_widget_text *)widget); + /* Invoke dialog for text entry */ + } } } diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h index 92896da0..4b65c754 100644 --- a/fitz/fitz-internal.h +++ b/fitz/fitz-internal.h @@ -830,13 +830,9 @@ fz_pixmap *fz_render_stroked_glyph(fz_context *ctx, fz_font*, int, fz_matrix, fz void fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, fz_matrix trm, void *gstate); /* - * Forms + * Form widgets */ -struct fz_widget -{ - int type; - fz_bbox bbox; -}; +void fz_free_widget(fz_context *ctx, fz_widget *widget); /* * Text buffer. diff --git a/fitz/fitz.h b/fitz/fitz.h index b68090cb..9ab405f3 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -2345,6 +2345,6 @@ char *fz_widget_text_get_text(fz_widget_text *tw); /* fz_widget_text_set_text: Update the text of a text widget. */ -char *fz_widget_text_set_text(fz_widget_text *tw, char *text); +void fz_widget_text_set_text(fz_widget_text *tw, char *text); #endif diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h index f501b916..db309db5 100644 --- a/pdf/mupdf-internal.h +++ b/pdf/mupdf-internal.h @@ -209,6 +209,8 @@ struct pdf_document_s pdf_obj **page_refs; pdf_lexbuf_large lexbuf; + + fz_widget *focus; }; void pdf_cache_object(pdf_document *doc, int num, int gen); diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c index 7594ed08..f24b9975 100644 --- a/pdf/pdf_form.c +++ b/pdf/pdf_form.c @@ -6,39 +6,109 @@ enum Ff_NoToggleToOff = 1 << (15-1), Ff_Radio = 1 << (16-1), Ff_Pushbutton = 1 << (17-1), - Ff_RadioInUnison = 1 << (26-1) + Ff_RadioInUnison = 1 << (26-1), + Ff_Combo = 1 << (18-1) }; -static char *get_annot_type(pdf_obj *obj) +struct fz_widget_s { - pdf_obj *type = NULL; + pdf_document *doc; + int type; + pdf_obj *obj; +}; - while (!type && obj) +struct fz_widget_text_s +{ + fz_widget super; + char *text; +}; + +static pdf_obj *get_field_entry(pdf_obj *obj, char *key) +{ + pdf_obj *fobj = NULL; + + while (!fobj && obj) { - type = pdf_dict_gets(obj, "FT"); + fobj = pdf_dict_gets(obj, key); - if (!type) + if (!fobj) obj = pdf_dict_gets(obj, "Parent"); } + return fobj; +} + +static char *get_field_type_name(pdf_obj *obj) +{ + pdf_obj *type = get_field_entry(obj, "FT"); + return type ? pdf_to_name(type) : NULL; } -static int get_annot_field_flags(pdf_obj *obj) +static int get_field_flags(pdf_obj *obj) +{ + pdf_obj *flags = get_field_entry(obj, "Ff"); + + return flags ? pdf_to_int(flags) + : 0; +} + +static int get_field_type(pdf_obj *obj) +{ + char *type = get_field_type_name(obj); + int flags = get_field_flags(obj); + + if (!strcmp(type, "Btn")) + { + if (flags & Ff_Pushbutton) + return FZ_WIDGET_TYPE_PUSHBUTTON; + else if (flags & Ff_Radio) + return FZ_WIDGET_TYPE_RADIOBUTTON; + else + return FZ_WIDGET_TYPE_CHECKBOX; + } + else if (!strcmp(type, "Tx")) + return FZ_WIDGET_TYPE_TEXT; + else if (!strcmp(type, "Ch")) + { + if (flags & Ff_Combo) + return FZ_WIDGET_TYPE_COMBOBOX; + else + return FZ_WIDGET_TYPE_LISTBOX; + } + else + return -1; +} + +static fz_widget *new_widget(pdf_document *doc, pdf_obj *obj) { - pdf_obj *flags = NULL; + fz_widget *widget = NULL; - while (!flags && obj) + fz_try(doc->ctx) { - flags = pdf_dict_gets(obj, "Ff"); + int type = get_field_type(obj); - if (!flags) - obj = pdf_dict_gets(obj, "Parent"); + switch(type) + { + case FZ_WIDGET_TYPE_TEXT: + widget = &(fz_malloc_struct(doc->ctx, fz_widget_text)->super); + break; + default: + widget = fz_malloc_struct(doc->ctx, fz_widget); + break; + } + + widget->doc = doc; + widget->type = type; + widget->obj = pdf_keep_obj(obj); + } + fz_catch(doc->ctx) + { + fz_warn(doc->ctx, "failed to load foccussed widget"); } - return flags ? pdf_to_int(flags) - : 0; + return widget; } static void toggle_check_box(pdf_document *doc, pdf_obj *obj) @@ -99,8 +169,15 @@ int pdf_pass_event(pdf_document *doc, pdf_page *page, fz_ui_event *ui_event) switch (ui_event->event.pointer.ptype) { case FZ_POINTER_DOWN: + if (doc->focus) + { + fz_free_widget(doc->ctx, doc->focus); + doc->focus = NULL; + } + if (annot) { + doc->focus = new_widget(doc, annot->obj); hp->num = pdf_to_num(annot->obj); hp->gen = pdf_to_gen(annot->obj); hp->state = HOTSPOT_POINTER_DOWN; @@ -118,22 +195,18 @@ int pdf_pass_event(pdf_document *doc, pdf_page *page, fz_ui_event *ui_event) if (annot) { - char *atype = get_annot_type(annot->obj); - int flags = get_annot_field_flags(annot->obj); - - if (!strcmp(atype, "Btn")) + switch(get_field_type(annot->obj)) { - if ((flags & (Ff_Pushbutton | Ff_Radio)) == 0) - toggle_check_box(doc, annot->obj); - + case FZ_WIDGET_TYPE_RADIOBUTTON: + case FZ_WIDGET_TYPE_CHECKBOX: /* FIXME: treating radio buttons like check boxes, for now */ - if ((flags & (Ff_Pushbutton | Ff_Radio)) == Ff_Radio) - toggle_check_box(doc, annot->obj); + toggle_check_box(doc, annot->obj); + changed = 1; + break; } } break; } - } break; } @@ -148,5 +221,73 @@ fz_rect *pdf_get_screen_update(pdf_document *doc) fz_widget *pdf_get_focussed_widget(pdf_document *doc) { - return NULL; + return doc->focus; +} + +void fz_free_widget(fz_context *ctx, fz_widget *widget) +{ + if (widget) + { + switch(widget->type) + { + case FZ_WIDGET_TYPE_TEXT: + fz_free(ctx, ((fz_widget_text *)widget)->text); + break; + } + + pdf_drop_obj(widget->obj); + fz_free(ctx, widget); + } +} + +int fz_widget_get_type(fz_widget *widget) +{ + return widget->type; +} + +char *fz_widget_text_get_text(fz_widget_text *tw) +{ + pdf_document *doc = tw->super.doc; + fz_context *ctx = doc->ctx; + pdf_obj *vobj = get_field_entry(tw->super.obj, "V"); + int len = 0; + char *buf = NULL; + fz_buffer *strmbuf = NULL; + + fz_free(ctx, tw->text); + tw->text = NULL; + + fz_var(strmbuf); + fz_try(ctx) + { + if (pdf_is_string(vobj)) + { + len = pdf_to_str_len(vobj); + buf = pdf_to_str_buf(vobj); + } + else if (pdf_is_stream(doc, pdf_to_num(vobj), pdf_to_gen(vobj))) + { + strmbuf = pdf_load_stream(doc, pdf_to_num(vobj), pdf_to_gen(vobj)); + len = fz_buffer_storage(ctx, strmbuf, &buf); + } + + if (buf) + { + tw->text = fz_malloc(ctx, len+1); + memcpy(tw->text, buf, len); + tw->text[len] = 0; + } + } + fz_catch(ctx) + { + fz_warn(ctx, "failed allocation in fz_widget_text_get_text"); + } + + fz_drop_buffer(ctx, strmbuf); + + return tw->text; +} + +void fz_widget_text_set_text(fz_widget_text *tw, char *text) +{ } diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c index ea068e27..f260dcbc 100644 --- a/pdf/pdf_xref.c +++ b/pdf/pdf_xref.c @@ -839,6 +839,8 @@ pdf_close_document(pdf_document *xref) fz_free(ctx, xref->page_refs); } + if (xref->focus) + fz_free_widget(ctx, xref->focus); if (xref->file) fz_close(xref->file); if (xref->trailer) |