summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorPaul Gardiner <paul@glidos.net>2012-05-08 14:29:37 +0100
committerPaul Gardiner <paul@glidos.net>2012-05-08 14:29:37 +0100
commit91b4f1249cd6545a791e02e1632d69164702b4a0 (patch)
tree2023f48628202e835a2110aa8e5ce0fe691ae221 /pdf
parentcc0a9593eced73291c657ec80aa02137c7c3b833 (diff)
downloadmupdf-91b4f1249cd6545a791e02e1632d69164702b4a0.tar.xz
Forms: part of text field handling
Diffstat (limited to 'pdf')
-rw-r--r--pdf/mupdf-internal.h2
-rw-r--r--pdf/pdf_form.c191
-rw-r--r--pdf/pdf_xref.c2
3 files changed, 170 insertions, 25 deletions
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)