Add pdf_edit_text_field_value and make mupdf-gl use it.
authorRobin Watts <[email protected]>
Mon, 26 Jul 2021 14:30:08 +0000 (15:30 +0100)
committerRobin Watts <[email protected]>
Mon, 26 Jul 2021 15:44:34 +0000 (16:44 +0100)
This allowed "format as you type" using javascript keystroke
methods.

include/mupdf/pdf/form.h
platform/gl/gl-app.h
platform/gl/gl-form.c
platform/gl/gl-input.c
source/pdf/pdf-form.c

index bee6d6d698f2f554fc9af27c17e95634925564be..ad9b91f722a639a1bffb444c3736ec17d269a330 100644 (file)
@@ -156,6 +156,7 @@ int pdf_set_field_value(fz_context *ctx, pdf_document *doc, pdf_obj *field, cons
 */
 int pdf_set_text_field_value(fz_context *ctx, pdf_widget *widget, const char *value);
 int pdf_set_choice_field_value(fz_context *ctx, pdf_widget *widget, const char *value);
+int pdf_edit_text_field_value(fz_context *ctx, pdf_widget *widget, const char *value, const char *change, int *selStart, int *selEnd, char **newvalue);
 
 typedef struct
 {
index 26c17ff60931c0b5d95afdce7cda4b1f55be6769..5be0790090a053a8a86f4afd3bc12ed892c8884a 100644 (file)
@@ -152,6 +152,7 @@ struct input
        char text[16*1024];
        char *end, *p, *q;
        int scroll;
+       pdf_widget *widget;
 };
 
 struct list
index 00c0d868519190fdf77dc1253101030b7d00672c..a6590eadab0321d031cbb181381b7f83dede9444 100644 (file)
@@ -498,6 +498,7 @@ static void tx_dialog(void)
        {
                ui_layout(T, X, NW, ui.padsize, ui.padsize);
                ui_label("%s", label);
+               tx_input.widget = tx_widget;
                is = ui_input(&tx_input, 200, tx_h);
 
                ui_layout(B, X, NW, ui.padsize, ui.padsize);
index a3fb483fcfcd093ee26dc272d2b0ee4a52d317d5..4e1ae14fe46299095aa32581d8ec0e66fe2eec75 100644 (file)
@@ -122,8 +122,28 @@ static void ui_input_delete_selection(struct input *input)
        input->p = input->q = p;
 }
 
-static void ui_input_paste(struct input *input, const char *buf, int n)
+static void ui_input_paste(struct input *input, const char *buf)
 {
+       int n = (int)strlen(buf);
+       if (input->widget)
+       {
+               char *newtext;
+               int selStart = input->p - input->text;
+               int selEnd = input->q - input->text;
+               if (pdf_edit_text_field_value(ctx, input->widget, input->text, buf, &selStart, &selEnd, &newtext))
+               {
+                       size_t len = strlen(newtext);
+                       if (len > sizeof(input->text)-1)
+                               len = sizeof(input->text)-1;
+                       memcpy(input->text, newtext, len);
+                       input->text[len] = 0;
+                       fz_free(ctx, newtext);
+                       input->p = input->text + selStart;
+                       input->q = input->p;
+                       input->end = input->text + len;
+               }
+               return;
+       }
        if (input->p != input->q)
                ui_input_delete_selection(input);
        if (input->end + n + 1 < input->text + sizeof(input->text))
@@ -163,7 +183,7 @@ static void ui_do_paste(struct input *input)
 {
        const char *buf = ui_get_clipboard();
        if (buf)
-               ui_input_paste(input, buf, (int)strlen(buf));
+               ui_input_paste(input, buf);
 }
 
 static int ui_input_key(struct input *input, int multiline)
@@ -281,7 +301,7 @@ static int ui_input_key(struct input *input, int multiline)
                        ui.focus = NULL;
                        return UI_INPUT_ACCEPT;
                }
-               ui_input_paste(input, "\n", 1);
+               ui_input_paste(input, "\n");
                break;
        case KEY_BACKSPACE:
                if (input->p != input->q)
@@ -335,9 +355,10 @@ static int ui_input_key(struct input *input, int multiline)
                        int cat = ucdn_get_general_category(ui.key);
                        if (ui.key == ' ' || (cat >= UCDN_GENERAL_CATEGORY_LL && cat < UCDN_GENERAL_CATEGORY_ZL))
                        {
-                               char buf[8];
+                               char buf[9];
                                int n = fz_runetochar(buf, ui.key);
-                               ui_input_paste(input, buf, n);
+                               buf[n] = 0;
+                               ui_input_paste(input, buf);
                        }
                }
                break;
index 5778b639f7fb2bffcd97825adff8323848a9e93f..3fbba43ce72bff69805f8fdd0dbbf573f3d490f7 100644 (file)
@@ -1149,6 +1149,52 @@ int pdf_set_text_field_value(fz_context *ctx, pdf_widget *widget, const char *up
        return rc;
 }
 
+int pdf_edit_text_field_value(fz_context *ctx, pdf_widget *widget, const char *value, const char *change, int *selStart, int *selEnd, char **result)
+{
+       pdf_document *doc = widget->page->doc;
+       pdf_keystroke_event evt = {0};
+       int rc = 1;
+
+       pdf_begin_operation(ctx, doc, "Text field keystroke");
+
+       fz_try(ctx)
+       {
+               if (!widget->ignore_trigger_events)
+               {
+                       evt.value = value;
+                       evt.change = change;
+                       evt.selStart = *selStart;
+                       evt.selEnd = *selEnd;
+                       evt.willCommit = 0;
+                       rc = pdf_annot_field_event_keystroke(ctx, doc, widget, &evt);
+                       if (rc)
+                       {
+                               *result = merge_changes(ctx, evt.newValue, evt.selStart, evt.selEnd, evt.newChange);
+                               *selStart = evt.selStart + strlen(evt.newChange);
+                               *selEnd = *selStart;
+                       }
+               }
+               else
+               {
+                       *result = merge_changes(ctx, value, *selStart, *selEnd, change);
+                       *selStart = evt.selStart + strlen(change);
+                       *selEnd = *selStart;
+               }
+       }
+       fz_always(ctx)
+       {
+               pdf_end_operation(ctx, doc);
+               fz_free(ctx, evt.newValue);
+               fz_free(ctx, evt.newChange);
+       }
+       fz_catch(ctx)
+       {
+               fz_warn(ctx, "could not process text widget keystroke");
+               rc = 0;
+       }
+       return rc;
+}
+
 int pdf_set_choice_field_value(fz_context *ctx, pdf_widget *widget, const char *new_value)
 {
        /* Choice widgets use almost the same keystroke processing as text fields. */