1 /* Input field widget implementation. */
13 #include "bfu/button.h"
14 #include "bfu/dialog.h"
15 #include "bfu/inpfield.h"
16 #include "bfu/inphist.h"
17 #include "bfu/msgbox.h"
19 #include "config/kbdbind.h"
20 #include "intl/charsets.h"
21 #include "intl/gettext/libintl.h"
22 #include "osdep/osdep.h"
23 #include "session/session.h"
24 #include "terminal/draw.h"
25 #include "terminal/kbd.h"
26 #include "terminal/mouse.h"
27 #include "terminal/terminal.h"
28 #include "terminal/window.h"
29 #include "util/color.h"
30 #include "util/memlist.h"
31 #include "util/memory.h"
33 #define INPUTFIELD_HEIGHT 1
35 #define INPUTFIELD_FLOATLABEL_PADDING 1
37 #define INPUTFIELD_FLOAT_SEPARATOR ":"
38 #define INPUTFIELD_FLOAT_SEPARATOR_LEN 1
41 add_dlg_field_do(struct dialog
*dlg
, enum widget_type type
, unsigned char *label
,
42 int min
, int max
, widget_handler_T
*handler
,
43 int datalen
, void *data
,
44 struct input_history
*history
, enum inpfield_flags flags
)
46 struct widget
*widget
= &dlg
->widgets
[dlg
->number_of_widgets
++];
50 widget
->handler
= handler
;
51 widget
->datalen
= datalen
;
54 widget
->info
.field
.history
= history
;
55 widget
->info
.field
.flags
= flags
;
56 widget
->info
.field
.min
= min
;
57 widget
->info
.field
.max
= max
;
60 widget_handler_status_T
61 check_number(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
63 struct widget
*widget
= widget_data
->widget
;
68 l
= strtol(widget_data
->cdata
, &end
, 10);
70 if (errno
|| !*widget_data
->cdata
|| *end
) {
71 info_box(dlg_data
->win
->term
, 0,
72 N_("Bad number"), ALIGN_CENTER
,
73 N_("Number expected in field"));
74 return EVENT_NOT_PROCESSED
;
77 if (l
< widget
->info
.field
.min
|| l
> widget
->info
.field
.max
) {
78 info_box(dlg_data
->win
->term
, MSGBOX_FREE_TEXT
,
79 N_("Bad number"), ALIGN_CENTER
,
80 msg_text(dlg_data
->win
->term
,
81 N_("Number should be in the range from %d to %d."),
82 widget
->info
.field
.min
, widget
->info
.field
.max
));
83 return EVENT_NOT_PROCESSED
;
86 return EVENT_PROCESSED
;
89 widget_handler_status_T
90 check_nonempty(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
94 for (p
= widget_data
->cdata
; *p
; p
++)
96 return EVENT_PROCESSED
;
98 info_box(dlg_data
->win
->term
, 0,
99 N_("Bad string"), ALIGN_CENTER
,
100 N_("Empty string not allowed"));
102 return EVENT_NOT_PROCESSED
;
106 dlg_format_field(struct terminal
*term
,
107 struct widget_data
*widget_data
,
108 int x
, int *y
, int w
, int *rw
, enum format_align align
, int format_only
)
110 static int max_label_width
;
111 static int *prev_y
; /* Assert the uniqueness of y */ /* TODO: get rid of this !! --Zas */
112 unsigned char *label
= widget_data
->widget
->text
;
113 struct color_pair
*text_color
= NULL
;
115 int float_label
= widget_data
->widget
->info
.field
.flags
& (INPFIELD_FLOAT
|INPFIELD_FLOAT2
);
117 if (label
&& *label
&& float_label
) {
118 label_width
= strlen(label
);
120 int_lower_bound(&max_label_width
, label_width
);
122 max_label_width
= label_width
;
126 /* Right align the floating label up against the
128 x
+= max_label_width
- label_width
;
129 w
-= max_label_width
- label_width
;
132 if (label
&& *label
) {
133 if (!format_only
) text_color
= get_bfu_color(term
, "dialog.text");
135 dlg_format_text_do(term
, label
, x
, y
, w
, rw
, text_color
, ALIGN_LEFT
, format_only
);
138 /* XXX: We want the field and label on the same line if the terminal
139 * width allows it. */
140 if (label
&& *label
&& float_label
) {
141 if (widget_data
->widget
->info
.field
.flags
& INPFIELD_FLOAT
) {
142 (*y
) -= INPUTFIELD_HEIGHT
;
143 dlg_format_text_do(term
, INPUTFIELD_FLOAT_SEPARATOR
,
144 x
+ label_width
, y
, w
, rw
,
145 text_color
, ALIGN_LEFT
, format_only
);
146 w
-= INPUTFIELD_FLOAT_SEPARATOR_LEN
+ INPUTFIELD_FLOATLABEL_PADDING
;
147 x
+= INPUTFIELD_FLOAT_SEPARATOR_LEN
+ INPUTFIELD_FLOATLABEL_PADDING
;
150 /* FIXME: Is 5 chars for input field enough? --jonas */
151 if (label_width
< w
- 5) {
152 (*y
) -= INPUTFIELD_HEIGHT
;
158 if (rw
) int_lower_bound(rw
, int_min(w
, DIALOG_MIN_WIDTH
));
160 set_box(&widget_data
->box
, x
, *y
, w
, INPUTFIELD_HEIGHT
);
162 (*y
) += INPUTFIELD_HEIGHT
;
165 static widget_handler_status_T
166 input_field_cancel(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
168 void (*fn
)(void *) = widget_data
->widget
->data
;
169 void *data
= dlg_data
->dlg
->udata2
;
173 return cancel_dialog(dlg_data
, widget_data
);
176 static widget_handler_status_T
177 input_field_ok(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
179 void (*fn
)(void *, unsigned char *) = widget_data
->widget
->data
;
180 void *data
= dlg_data
->dlg
->udata2
;
181 unsigned char *text
= dlg_data
->widgets_data
->cdata
;
183 if (check_dialog(dlg_data
)) return EVENT_NOT_PROCESSED
;
185 if (widget_has_history(dlg_data
->widgets_data
))
186 add_to_input_history(dlg_data
->dlg
->widgets
->info
.field
.history
,
189 if (fn
) fn(data
, text
);
191 return cancel_dialog(dlg_data
, widget_data
);
195 input_field(struct terminal
*term
, struct memory_list
*ml
, int intl
,
196 unsigned char *title
,
198 unsigned char *okbutton
,
199 unsigned char *cancelbutton
,
200 void *data
, struct input_history
*history
, int l
,
201 unsigned char *def
, int min
, int max
,
202 widget_handler_T
*check
,
203 void (*fn
)(void *, unsigned char *),
204 void (*cancelfn
)(void *))
207 unsigned char *field
;
210 title
= _(title
, term
);
211 text
= _(text
, term
);
212 okbutton
= _(okbutton
, term
);
213 cancelbutton
= _(cancelbutton
, term
);
216 #define INPUT_WIDGETS_COUNT 3
217 dlg
= calloc_dialog(INPUT_WIDGETS_COUNT
, l
);
220 /* @field is automatically cleared by calloc() */
221 field
= get_dialog_offset(dlg
, INPUT_WIDGETS_COUNT
);
224 int defsize
= strlen(def
) + 1;
226 memcpy(field
, def
, (defsize
> l
) ? l
- 1 : defsize
);
230 dlg
->layouter
= generic_dialog_layouter
;
231 dlg
->layout
.fit_datalen
= 1;
234 add_dlg_field(dlg
, text
, min
, max
, check
, l
, field
, history
);
236 add_dlg_button(dlg
, okbutton
, B_ENTER
, input_field_ok
, fn
);
237 add_dlg_button(dlg
, cancelbutton
, B_ESC
, input_field_cancel
, cancelfn
);
239 add_dlg_end(dlg
, INPUT_WIDGETS_COUNT
);
241 add_to_ml(&ml
, (void *) dlg
, (void *) NULL
);
242 do_dialog(term
, dlg
, ml
);
246 input_dialog(struct terminal
*term
, struct memory_list
*ml
,
247 unsigned char *title
,
249 void *data
, struct input_history
*history
, int l
,
250 unsigned char *def
, int min
, int max
,
251 widget_handler_T
*check
,
252 void (*fn
)(void *, unsigned char *),
253 void (*cancelfn
)(void *))
255 /* [gettext_accelerator_context(input_dialog)] */
256 input_field(term
, ml
, 1, title
, text
, N_("~OK"), N_("~Cancel"),
259 check
, fn
, cancelfn
);
262 static widget_handler_status_T
263 display_field_do(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
,
266 struct terminal
*term
= dlg_data
->win
->term
;
267 struct color_pair
*color
;
268 int sel
= is_selected_widget(dlg_data
, widget_data
);
270 int len
= 0, left
= 0;
271 #endif /* CONFIG_UTF8 */
275 unsigned char *t
= widget_data
->cdata
;
276 int p
= widget_data
->info
.field
.cpos
;
278 len
= utf8_ptr2cells(t
, &t
[p
]);
279 int_bounds(&left
, len
- widget_data
->box
.width
+ 1, len
);
280 int_lower_bound(&left
, 0);
281 widget_data
->info
.field
.vpos
= utf8_cells2bytes(t
, left
, NULL
);
283 #endif /* CONFIG_UTF8 */
285 int_bounds(&widget_data
->info
.field
.vpos
,
286 widget_data
->info
.field
.cpos
- widget_data
->box
.width
+ 1,
287 widget_data
->info
.field
.cpos
);
288 int_lower_bound(&widget_data
->info
.field
.vpos
, 0);
291 color
= get_bfu_color(term
, "dialog.field");
293 draw_box(term
, &widget_data
->box
, ' ', 0, color
);
295 color
= get_bfu_color(term
, "dialog.field-text");
297 unsigned char *text
= widget_data
->cdata
+ widget_data
->info
.field
.vpos
;
301 if (term
->utf8_cp
&& !hide
)
302 len
= utf8_ptr2cells(text
, NULL
);
303 else if (term
->utf8_cp
)
304 len
= utf8_ptr2chars(text
, NULL
);
306 #endif /* CONFIG_UTF8 */
308 w
= int_min(len
, widget_data
->box
.width
);
313 w
= utf8_cells2bytes(text
, w
, NULL
);
314 #endif /* CONFIG_UTF8 */
315 draw_text(term
, widget_data
->box
.x
, widget_data
->box
.y
,
320 copy_box(&box
, &widget_data
->box
);
323 draw_box(term
, &box
, '*', 0, color
);
332 x
= widget_data
->box
.x
+ len
- left
;
334 #endif /* CONFIG_UTF8 */
335 x
= widget_data
->box
.x
+ widget_data
->info
.field
.cpos
- widget_data
->info
.field
.vpos
;
337 set_cursor(term
, x
, widget_data
->box
.y
, 0);
338 set_window_ptr(dlg_data
->win
, widget_data
->box
.x
, widget_data
->box
.y
);
341 return EVENT_PROCESSED
;
344 static widget_handler_status_T
345 display_field(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
347 return display_field_do(dlg_data
, widget_data
, 0);
350 static widget_handler_status_T
351 display_field_pass(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
353 return display_field_do(dlg_data
, widget_data
, 1);
356 static widget_handler_status_T
357 init_field(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
359 if (widget_has_history(widget_data
)) {
360 struct input_history_entry
*entry
;
362 foreach (entry
, widget_data
->widget
->info
.field
.history
->entries
) {
363 int datalen
= strlen(entry
->data
);
364 struct input_history_entry
*new_entry
;
366 /* One byte is reserved in struct input_history_entry. */
367 new_entry
= mem_alloc(sizeof(*new_entry
) + datalen
);
368 if (!new_entry
) continue;
370 memcpy(new_entry
->data
, entry
->data
, datalen
+ 1);
371 add_to_list(widget_data
->info
.field
.history
, new_entry
);
375 widget_data
->info
.field
.cpos
= strlen(widget_data
->cdata
);
376 return EVENT_PROCESSED
;
380 field_prev_history(struct widget_data
*widget_data
)
382 if (widget_has_history(widget_data
)
383 && (void *) widget_data
->info
.field
.cur_hist
->prev
!= &widget_data
->info
.field
.history
) {
384 widget_data
->info
.field
.cur_hist
= widget_data
->info
.field
.cur_hist
->prev
;
385 dlg_set_history(widget_data
);
392 field_next_history(struct widget_data
*widget_data
)
394 if (widget_has_history(widget_data
)
395 && (void *) widget_data
->info
.field
.cur_hist
!= &widget_data
->info
.field
.history
) {
396 widget_data
->info
.field
.cur_hist
= widget_data
->info
.field
.cur_hist
->next
;
397 dlg_set_history(widget_data
);
403 static widget_handler_status_T
404 mouse_field(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
406 struct term_event
*ev
= dlg_data
->term_event
;
408 if (!check_mouse_position(ev
, &widget_data
->box
))
409 return EVENT_NOT_PROCESSED
;
411 /* Handle navigation through history (if any) using up/down mouse wheel */
412 switch (get_mouse_button(ev
)) {
414 if (check_mouse_action(ev
, B_DOWN
)) {
415 if (field_prev_history(widget_data
)) {
416 select_widget(dlg_data
, widget_data
);
417 return EVENT_PROCESSED
;
420 return EVENT_NOT_PROCESSED
;
423 if (check_mouse_action(ev
, B_DOWN
)) {
424 if (field_next_history(widget_data
)) {
425 select_widget(dlg_data
, widget_data
);
426 return EVENT_PROCESSED
;
429 return EVENT_NOT_PROCESSED
;
432 /* Place text cursor at mouse position and focus the widget. */
433 widget_data
->info
.field
.cpos
= widget_data
->info
.field
.vpos
434 + ev
->info
.mouse
.x
- widget_data
->box
.x
;
435 int_upper_bound(&widget_data
->info
.field
.cpos
, strlen(widget_data
->cdata
));
437 select_widget(dlg_data
, widget_data
);
438 return EVENT_PROCESSED
;
441 static widget_handler_status_T
442 kbd_field(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
444 struct window
*win
= dlg_data
->win
;
445 struct terminal
*term
= win
->term
;
446 struct term_event
*ev
= dlg_data
->term_event
;
447 action_id_T action_id
;
449 action_id
= kbd_action(KEYMAP_EDIT
, ev
, NULL
);
451 && !action_is_anonymous_safe(KEYMAP_EDIT
, action_id
)
452 && get_cmd_opt_bool("anonymous"))
453 return EVENT_NOT_PROCESSED
;
457 if (!widget_has_history(widget_data
))
458 return EVENT_NOT_PROCESSED
;
460 if (field_prev_history(widget_data
)) {
466 if (!widget_has_history(widget_data
))
467 return EVENT_NOT_PROCESSED
;
469 if (field_next_history(widget_data
)) {
475 if (widget_data
->info
.field
.cpos
< strlen(widget_data
->cdata
)) {
478 unsigned char *next
= widget_data
->cdata
+ widget_data
->info
.field
.cpos
;
479 unsigned char *end
= strchr(next
, '\0');
481 utf8_to_unicode(&next
, end
);
482 widget_data
->info
.field
.cpos
= (int)(next
- widget_data
->cdata
);
484 #endif /* CONFIG_UTF8 */
486 widget_data
->info
.field
.cpos
++;
492 if (widget_data
->info
.field
.cpos
> 0)
493 widget_data
->info
.field
.cpos
--;
495 if (widget_data
->info
.field
.cpos
&& term
->utf8_cp
) {
496 unsigned char *t
= widget_data
->cdata
;
497 unsigned char *t2
= t
;
498 int p
= widget_data
->info
.field
.cpos
;
499 unsigned char tmp
= t
[p
];
504 widget_data
->info
.field
.cpos
= (int)(t2
- t
);
507 #endif /* CONFIG_UTF8 */
511 widget_data
->info
.field
.cpos
= 0;
515 widget_data
->info
.field
.cpos
= strlen(widget_data
->cdata
);
518 case ACT_EDIT_BACKSPACE
:
520 if (widget_data
->info
.field
.cpos
&& term
->utf8_cp
) {
521 /* XXX: stolen from src/viewer/text/form.c */
522 /* FIXME: This isn't nice. We remove last byte
523 * from UTF-8 character to detect
524 * character before it. */
525 unsigned char *text
= widget_data
->cdata
;
526 unsigned char *end
= widget_data
->cdata
+ widget_data
->info
.field
.cpos
- 1;
528 int old
= widget_data
->info
.field
.cpos
;
531 data
= utf8_to_unicode(&text
, end
);
532 if (data
== UCS_NO_CHAR
)
536 widget_data
->info
.field
.cpos
= (int)(text
- widget_data
->cdata
);
537 if (old
!= widget_data
->info
.field
.cpos
) {
540 text
= widget_data
->cdata
;
541 length
= strlen(text
+ old
) + 1;
542 memmove(text
+ widget_data
->info
.field
.cpos
, text
+ old
, length
);
546 #endif /* CONFIG_UTF8 */
547 if (widget_data
->info
.field
.cpos
) {
548 memmove(widget_data
->cdata
+ widget_data
->info
.field
.cpos
- 1,
549 widget_data
->cdata
+ widget_data
->info
.field
.cpos
,
550 strlen(widget_data
->cdata
) - widget_data
->info
.field
.cpos
+ 1);
551 widget_data
->info
.field
.cpos
--;
555 case ACT_EDIT_DELETE
:
557 int cdata_len
= strlen(widget_data
->cdata
);
559 if (widget_data
->info
.field
.cpos
>= cdata_len
) goto display_field
;
563 unsigned char *end
= widget_data
->cdata
+ cdata_len
;
564 unsigned char *text
= widget_data
->cdata
+ widget_data
->info
.field
.cpos
;
565 unsigned char *old
= text
;
567 utf8_to_unicode(&text
, end
);
570 (int)(end
- text
) + 1);
574 #endif /* CONFIG_UTF8 */
575 memmove(widget_data
->cdata
+ widget_data
->info
.field
.cpos
,
576 widget_data
->cdata
+ widget_data
->info
.field
.cpos
+ 1,
577 cdata_len
- widget_data
->info
.field
.cpos
+ 1);
581 case ACT_EDIT_KILL_TO_BOL
:
582 memmove(widget_data
->cdata
,
583 widget_data
->cdata
+ widget_data
->info
.field
.cpos
,
584 strlen(widget_data
->cdata
+ widget_data
->info
.field
.cpos
) + 1);
585 widget_data
->info
.field
.cpos
= 0;
588 case ACT_EDIT_KILL_TO_EOL
:
589 widget_data
->cdata
[widget_data
->info
.field
.cpos
] = 0;
592 case ACT_EDIT_KILL_WORD_BACK
:
594 int cdata_len
= strlen(widget_data
->cdata
);
595 int start
= widget_data
->info
.field
.cpos
;
597 while (start
> 0 && isspace(widget_data
->cdata
[start
- 1]))
599 while (start
> 0 && !isspace(widget_data
->cdata
[start
- 1]))
602 memmove(widget_data
->cdata
+ start
,
603 widget_data
->cdata
+ widget_data
->info
.field
.cpos
,
604 cdata_len
- widget_data
->info
.field
.cpos
+ 1);
606 widget_data
->info
.field
.cpos
= start
;
611 case ACT_EDIT_MOVE_BACKWARD_WORD
:
612 while (widget_data
->info
.field
.cpos
> 0 && isspace(widget_data
->cdata
[widget_data
->info
.field
.cpos
- 1]))
613 --widget_data
->info
.field
.cpos
;
614 while (widget_data
->info
.field
.cpos
> 0 && !isspace(widget_data
->cdata
[widget_data
->info
.field
.cpos
- 1]))
615 --widget_data
->info
.field
.cpos
;
619 case ACT_EDIT_MOVE_FORWARD_WORD
:
620 while (isspace(widget_data
->cdata
[widget_data
->info
.field
.cpos
]))
621 ++widget_data
->info
.field
.cpos
;
622 while (widget_data
->cdata
[widget_data
->info
.field
.cpos
] && !isspace(widget_data
->cdata
[widget_data
->info
.field
.cpos
]))
623 ++widget_data
->info
.field
.cpos
;
624 while (isspace(widget_data
->cdata
[widget_data
->info
.field
.cpos
]))
625 ++widget_data
->info
.field
.cpos
;
629 case ACT_EDIT_COPY_CLIPBOARD
:
630 /* Copy to clipboard */
631 set_clipboard_text(widget_data
->cdata
);
632 return EVENT_PROCESSED
;
634 case ACT_EDIT_CUT_CLIPBOARD
:
635 /* Cut to clipboard */
636 set_clipboard_text(widget_data
->cdata
);
637 widget_data
->cdata
[0] = 0;
638 widget_data
->info
.field
.cpos
= 0;
641 case ACT_EDIT_PASTE_CLIPBOARD
:
643 /* Paste from clipboard */
644 unsigned char *clipboard
= get_clipboard_text();
646 if (!clipboard
) goto display_field
;
648 safe_strncpy(widget_data
->cdata
, clipboard
, widget_data
->widget
->datalen
);
649 widget_data
->info
.field
.cpos
= strlen(widget_data
->cdata
);
654 case ACT_EDIT_AUTO_COMPLETE
:
655 if (!widget_has_history(widget_data
))
656 return EVENT_NOT_PROCESSED
;
658 do_tab_compl(dlg_data
, &widget_data
->info
.field
.history
);
661 case ACT_EDIT_AUTO_COMPLETE_FILE
:
662 if (!widget_has_history(widget_data
))
663 return EVENT_NOT_PROCESSED
;
665 do_tab_compl_file(dlg_data
, &widget_data
->info
.field
.history
);
668 case ACT_EDIT_AUTO_COMPLETE_UNAMBIGUOUS
:
669 if (!widget_has_history(widget_data
))
670 return EVENT_NOT_PROCESSED
;
672 do_tab_compl_unambiguous(dlg_data
, &widget_data
->info
.field
.history
);
675 case ACT_EDIT_REDRAW
:
676 redraw_terminal_cls(term
);
677 return EVENT_PROCESSED
;
680 if (check_kbd_textinput_key(ev
)) {
681 unsigned char *text
= widget_data
->cdata
;
682 int textlen
= strlen(text
);
684 /* Both get_kbd_key(ev) and @text
685 * are in the terminal's charset. */
686 const int inslen
= 1;
687 #else /* CONFIG_UTF8 */
688 const unsigned char *ins
;
691 /* get_kbd_key(ev) is UCS-4, and @text
692 * is in the terminal's charset. */
693 ins
= u2cp_no_nbsp(get_kbd_key(ev
),
694 get_terminal_codepage(term
));
695 inslen
= strlen(ins
);
696 #endif /* CONFIG_UTF8 */
698 if (textlen
>= widget_data
->widget
->datalen
- inslen
)
701 /* Shift to position of the cursor */
702 textlen
-= widget_data
->info
.field
.cpos
;
703 text
+= widget_data
->info
.field
.cpos
;
705 memmove(text
+ inslen
, text
, textlen
+ 1);
707 memcpy(text
, ins
, inslen
);
708 #else /* !CONFIG_UTF8 */
709 *text
= get_kbd_key(ev
);
710 #endif /* !CONFIG_UTF8 */
711 widget_data
->info
.field
.cpos
+= inslen
;
715 return EVENT_NOT_PROCESSED
;
718 display_widget(dlg_data
, widget_data
);
719 redraw_from_window(dlg_data
->win
);
720 return EVENT_PROCESSED
;
724 static widget_handler_status_T
725 clear_field(struct dialog_data
*dlg_data
, struct widget_data
*widget_data
)
727 widget_data
->info
.field
.cpos
= 0;
729 if (widget_data
->widget
->datalen
)
730 memset(widget_data
->cdata
, 0, widget_data
->widget
->datalen
);
732 return EVENT_PROCESSED
;
735 const struct widget_ops field_ops
= {
744 const struct widget_ops field_pass_ops
= {
757 input_line_layouter(struct dialog_data
*dlg_data
)
759 struct input_line
*input_line
= dlg_data
->dlg
->udata
;
760 struct session
*ses
= input_line
->ses
;
761 struct window
*win
= dlg_data
->win
;
762 int y
= win
->term
->height
- 1
763 - ses
->status
.show_status_bar
764 - ses
->status
.show_tabs_bar
;
766 dlg_format_field(win
->term
, dlg_data
->widgets_data
, 0,
767 &y
, win
->term
->width
, NULL
, ALIGN_LEFT
, 0);
770 static widget_handler_status_T
771 input_line_event_handler(struct dialog_data
*dlg_data
)
773 struct input_line
*input_line
= dlg_data
->dlg
->udata
;
774 input_line_handler_T handler
= input_line
->handler
;
775 enum edit_action action_id
;
776 struct widget_data
*widget_data
= dlg_data
->widgets_data
;
777 struct term_event
*ev
= dlg_data
->term_event
;
782 action_id
= kbd_action(KEYMAP_EDIT
, ev
, NULL
);
784 /* Handle some basic actions such as quiting for empty buffers */
787 case ACT_EDIT_NEXT_ITEM
:
788 case ACT_EDIT_PREVIOUS_ITEM
:
789 if (widget_has_history(widget_data
))
790 add_to_input_history(widget_data
->widget
->info
.field
.history
,
791 input_line
->buffer
, 1);
794 case ACT_EDIT_BACKSPACE
:
795 if (!*input_line
->buffer
)
796 goto cancel_input_line
;
799 case ACT_EDIT_CANCEL
:
800 goto cancel_input_line
;
806 /* First let the input field do its business */
807 kbd_field(dlg_data
, widget_data
);
812 if (ev
->info
.mouse
.y
!= dlg_data
->win
->y
) {
813 delete_window_ev(dlg_data
->win
, ev
);
814 return EVENT_PROCESSED
;
816 #endif /* CONFIG_MOUSE */
817 return EVENT_NOT_PROCESSED
;
820 /* Try to catch the redraw event initiated by the history
821 * completion and only respond if something was actually
822 * updated. Meaning we have new data in the line buffer that
823 * should be propagated to the line handler. */
824 if (!widget_has_history(widget_data
)
825 || widget_data
->info
.field
.cpos
<= 0
826 || widget_data
->info
.field
.cpos
<= strlen(input_line
->buffer
))
827 return EVENT_NOT_PROCESSED
;
832 action_id
= ACT_EDIT_REDRAW
;
836 return EVENT_NOT_PROCESSED
;
839 update_dialog_data(dlg_data
);
841 send_action_to_handler
:
842 /* Then pass it on to the specialized handler */
843 switch (handler(input_line
, action_id
)) {
844 case INPUT_LINE_CANCEL
:
846 cancel_dialog(dlg_data
, widget_data
);
849 case INPUT_LINE_REWIND
:
850 /* This is stolen kbd_field() handling for ACT_EDIT_BACKSPACE */
851 memmove(widget_data
->cdata
+ widget_data
->info
.field
.cpos
- 1,
852 widget_data
->cdata
+ widget_data
->info
.field
.cpos
,
853 strlen(widget_data
->cdata
) - widget_data
->info
.field
.cpos
+ 1);
854 widget_data
->info
.field
.cpos
--;
856 update_dialog_data(dlg_data
);
858 goto send_action_to_handler
;
860 case INPUT_LINE_PROCEED
:
864 /* Hack: We want our caller to perform its redrawing routine,
865 * even if we did process the event here. */
866 if (action_id
== ACT_EDIT_REDRAW
) return EVENT_NOT_PROCESSED
;
868 /* Completely bypass any further dialog event handling */
869 return EVENT_PROCESSED
;
873 input_field_line(struct session
*ses
, unsigned char *prompt
, void *data
,
874 struct input_history
*history
, input_line_handler_T handler
)
877 unsigned char *buffer
;
878 struct input_line
*input_line
;
882 dlg
= calloc_dialog(INPUT_LINE_WIDGETS
, sizeof(*input_line
));
885 input_line
= (void *) get_dialog_offset(dlg
, INPUT_LINE_WIDGETS
);
886 input_line
->ses
= ses
;
887 input_line
->data
= data
;
888 input_line
->handler
= handler
;
889 buffer
= input_line
->buffer
;
891 dlg
->handle_event
= input_line_event_handler
;
892 dlg
->layouter
= input_line_layouter
;
893 dlg
->layout
.only_widgets
= 1;
894 dlg
->udata
= input_line
;
896 add_dlg_field_float2(dlg
, prompt
, 0, 0, NULL
, INPUT_LINE_BUFFER_SIZE
,
899 do_dialog(ses
->tab
->term
, dlg
, getml(dlg
, (void *) NULL
));