2 Widgets for the Midnight Commander
4 Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003,
5 2004, 2005, 2006, 2007, 2009, 2010, 2011
6 The Free Software Foundation, Inc.
9 Radek Doulik, 1994, 1995
10 Miguel de Icaza, 1994, 1995
12 Andrej Borsenkow, 1996
14 Andrew Borodin <aborodin@vmail.ru>, 2009, 2010
16 This file is part of the Midnight Commander.
18 The Midnight Commander is free software: you can redistribute it
19 and/or modify it under the terms of the GNU General Public License as
20 published by the Free Software Foundation, either version 3 of the License,
21 or (at your option) any later version.
23 The Midnight Commander is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program. If not, see <http://www.gnu.org/licenses/>.
33 * \brief Source: WInput widget
39 #include <sys/types.h>
43 #include "lib/global.h"
45 #include "lib/tty/tty.h"
46 #include "lib/tty/mouse.h"
47 #include "lib/tty/key.h" /* XCTRL and ALT macros */
48 #include "lib/fileloc.h"
50 #include "lib/strutil.h"
52 #include "lib/keybind.h" /* global_keymap_t */
53 #include "lib/widget.h"
54 #include "lib/event.h" /* mc_event_raise() */
56 #include "input_complete.h"
58 /*** global variables ****************************************************************************/
62 const global_keymap_t
*input_map
= NULL
;
64 /*** file scope macro definitions ****************************************************************/
66 #define LARGE_HISTORY_BUTTON 1
68 #ifdef LARGE_HISTORY_BUTTON
69 #define HISTORY_BUTTON_WIDTH 3
71 #define HISTORY_BUTTON_WIDTH 1
74 #define should_show_history_button(in) \
75 (in->history != NULL && in->field_width > HISTORY_BUTTON_WIDTH * 2 + 1 \
76 && in->widget.owner != NULL)
78 /*** file scope type declarations ****************************************************************/
80 /*** file scope variables ************************************************************************/
82 /* Input widgets have a global kill ring */
83 /* Pointer to killed data */
84 static char *kill_buffer
= NULL
;
86 /*** file scope functions ************************************************************************/
87 /* --------------------------------------------------------------------------------------------- */
90 get_history_length (const GList
* history
)
94 for (; history
!= NULL
; history
= g_list_previous (history
))
100 /* --------------------------------------------------------------------------------------------- */
103 draw_history_button (WInput
* in
)
106 gboolean disabled
= (((Widget
*) in
)->options
& W_DISABLED
) != 0;
108 c
= in
->history
->next
? (in
->history
->prev
? '|' : 'v') : '^';
109 widget_move (&in
->widget
, 0, in
->field_width
- HISTORY_BUTTON_WIDTH
);
110 tty_setcolor (disabled
? DISABLED_COLOR
: in
->color
[WINPUTC_HISTORY
]);
111 #ifdef LARGE_HISTORY_BUTTON
114 h
= in
->widget
.owner
;
115 tty_print_string ("[ ]");
116 widget_move (&in
->widget
, 0, in
->field_width
- HISTORY_BUTTON_WIDTH
+ 1);
122 /* --------------------------------------------------------------------------------------------- */
125 input_set_markers (WInput
* in
, long m1
)
130 /* --------------------------------------------------------------------------------------------- */
133 input_mark_cmd (WInput
* in
, gboolean mark
)
137 in
->highlight
= FALSE
;
138 input_set_markers (in
, 0);
142 in
->highlight
= TRUE
;
143 input_set_markers (in
, in
->point
);
147 /* --------------------------------------------------------------------------------------------- */
150 input_eval_marks (WInput
* in
, long *start_mark
, long *end_mark
)
154 *start_mark
= min (in
->mark
, in
->point
);
155 *end_mark
= max (in
->mark
, in
->point
);
160 *start_mark
= *end_mark
= 0;
165 /* --------------------------------------------------------------------------------------------- */
168 delete_region (WInput
* in
, int x_first
, int x_last
)
170 int first
= min (x_first
, x_last
);
171 int last
= max (x_first
, x_last
);
174 input_mark_cmd (in
, FALSE
);
176 last
= str_offset_to_pos (in
->buffer
, last
);
177 first
= str_offset_to_pos (in
->buffer
, first
);
178 len
= strlen (&in
->buffer
[last
]) + 1;
179 memmove (&in
->buffer
[first
], &in
->buffer
[last
], len
);
181 in
->need_push
= TRUE
;
184 /* --------------------------------------------------------------------------------------------- */
187 do_show_hist (WInput
* in
)
192 len
= get_history_length (in
->history
);
194 r
= history_show (&in
->history
, &in
->widget
);
197 input_assign_text (in
, r
);
201 /* Has history cleaned up or not? */
202 if (len
!= get_history_length (in
->history
))
203 in
->history_changed
= TRUE
;
206 /* --------------------------------------------------------------------------------------------- */
209 push_history (WInput
* in
, const char *text
)
211 /* input widget where urls with passwords are entered without any
213 const char *password_input_fields
[] = {
214 " Link to a remote machine ",
216 " SMB link to machine "
218 const size_t ELEMENTS
= (sizeof (password_input_fields
) / sizeof (password_input_fields
[0]));
228 for (i
= 0; i
< ELEMENTS
; i
++)
229 password_input_fields
[i
] = _(password_input_fields
[i
]);
232 t
= g_strstrip (g_strdup (text
));
235 t
= g_strdup (empty
? "" : text
);
237 if (in
->history_name
!= NULL
)
239 /* FIXME: It is the strange code. Rewrite is needed. */
241 const char *p
= in
->history_name
+ 3;
243 for (i
= 0; i
< ELEMENTS
; i
++)
244 if (strcmp (p
, password_input_fields
[i
]) == 0)
247 strip_password (t
, i
>= ELEMENTS
);
250 if (in
->history
== NULL
|| in
->history
->data
== NULL
|| strcmp (in
->history
->data
, t
) != 0 ||
253 in
->history
= list_append_unique (in
->history
, t
);
254 in
->history_changed
= TRUE
;
259 in
->need_push
= FALSE
;
262 /* --------------------------------------------------------------------------------------------- */
265 move_buffer_backward (WInput
* in
, int start
, int end
)
270 str_len
= str_length (in
->buffer
);
271 if (start
>= str_len
|| end
> str_len
+ 1)
274 pos
= str_offset_to_pos (in
->buffer
, start
);
275 len
= str_offset_to_pos (in
->buffer
, end
) - pos
;
277 for (i
= pos
; in
->buffer
[i
+ len
- 1]; i
++)
278 in
->buffer
[i
] = in
->buffer
[i
+ len
];
281 /* --------------------------------------------------------------------------------------------- */
284 insert_char (WInput
* in
, int c_code
)
292 if (input_eval_marks (in
, &m1
, &m2
))
293 delete_region (in
, m1
, m2
);
296 return MSG_NOT_HANDLED
;
298 if (in
->charpoint
>= MB_LEN_MAX
)
301 in
->charbuf
[in
->charpoint
] = c_code
;
304 res
= str_is_valid_char (in
->charbuf
, in
->charpoint
);
308 in
->charpoint
= 0; /* broken multibyte char, skip */
312 in
->need_push
= TRUE
;
313 if (strlen (in
->buffer
) + 1 + in
->charpoint
>= in
->current_max_size
)
315 /* Expand the buffer */
316 size_t new_length
= in
->current_max_size
+ in
->field_width
+ in
->charpoint
;
317 char *narea
= g_try_renew (char, in
->buffer
, new_length
);
321 in
->current_max_size
= new_length
;
325 if (strlen (in
->buffer
) + in
->charpoint
< in
->current_max_size
)
327 /* bytes from begin */
328 size_t ins_point
= str_offset_to_pos (in
->buffer
, in
->point
);
330 size_t rest_bytes
= strlen (in
->buffer
+ ins_point
);
332 for (i
= rest_bytes
+ 1; i
> 0; i
--)
333 in
->buffer
[ins_point
+ i
+ in
->charpoint
- 1] = in
->buffer
[ins_point
+ i
- 1];
335 memcpy (in
->buffer
+ ins_point
, in
->charbuf
, in
->charpoint
);
343 /* --------------------------------------------------------------------------------------------- */
346 beginning_of_line (WInput
* in
)
352 /* --------------------------------------------------------------------------------------------- */
355 end_of_line (WInput
* in
)
357 in
->point
= str_length (in
->buffer
);
361 /* --------------------------------------------------------------------------------------------- */
364 backward_char (WInput
* in
)
368 act
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
370 in
->point
-= str_cprev_noncomb_char (&act
, in
->buffer
);
374 /* --------------------------------------------------------------------------------------------- */
377 forward_char (WInput
* in
)
381 act
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
383 in
->point
+= str_cnext_noncomb_char (&act
);
387 /* --------------------------------------------------------------------------------------------- */
390 forward_word (WInput
* in
)
394 p
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
395 while (p
[0] != '\0' && (str_isspace (p
) || str_ispunct (p
)))
400 while (p
[0] != '\0' && !str_isspace (p
) && !str_ispunct (p
))
407 /* --------------------------------------------------------------------------------------------- */
410 backward_word (WInput
* in
)
412 const char *p
, *p_tmp
;
414 for (p
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
415 (p
!= in
->buffer
) && (p
[0] == '\0'); str_cprev_char (&p
), in
->point
--);
417 while (p
!= in
->buffer
)
421 if (!str_isspace (p
) && !str_ispunct (p
))
428 while (p
!= in
->buffer
)
431 if (str_isspace (p
) || str_ispunct (p
))
438 /* --------------------------------------------------------------------------------------------- */
441 backward_delete (WInput
* in
)
443 const char *act
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
449 start
= in
->point
- str_cprev_noncomb_char (&act
, in
->buffer
);
450 move_buffer_backward (in
, start
, in
->point
);
452 in
->need_push
= TRUE
;
456 /* --------------------------------------------------------------------------------------------- */
459 delete_char (WInput
* in
)
464 act
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
465 end
+= str_cnext_noncomb_char (&act
);
467 move_buffer_backward (in
, in
->point
, end
);
469 in
->need_push
= TRUE
;
472 /* --------------------------------------------------------------------------------------------- */
475 copy_region (WInput
* in
, int x_first
, int x_last
)
477 int first
= min (x_first
, x_last
);
478 int last
= max (x_first
, x_last
);
482 /* Copy selected files to clipboard */
483 mc_event_raise (MCEVENT_GROUP_FILEMANAGER
, "panel_save_curent_file_to_clip_file", NULL
);
484 /* try use external clipboard utility */
485 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_file_to_ext_clip", NULL
);
489 g_free (kill_buffer
);
491 first
= str_offset_to_pos (in
->buffer
, first
);
492 last
= str_offset_to_pos (in
->buffer
, last
);
494 kill_buffer
= g_strndup (in
->buffer
+ first
, last
- first
);
496 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_text_to_file", kill_buffer
);
497 /* try use external clipboard utility */
498 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_file_to_ext_clip", NULL
);
501 /* --------------------------------------------------------------------------------------------- */
504 kill_word (WInput
* in
)
506 int old_point
= in
->point
;
510 new_point
= in
->point
;
511 in
->point
= old_point
;
513 delete_region (in
, old_point
, new_point
);
514 in
->need_push
= TRUE
;
518 /* --------------------------------------------------------------------------------------------- */
521 back_kill_word (WInput
* in
)
523 int old_point
= in
->point
;
527 new_point
= in
->point
;
528 in
->point
= old_point
;
530 delete_region (in
, old_point
, new_point
);
531 in
->need_push
= TRUE
;
534 /* --------------------------------------------------------------------------------------------- */
539 if (kill_buffer
!= NULL
)
544 for (p
= kill_buffer
; *p
!= '\0'; p
++)
545 insert_char (in
, *p
);
550 /* --------------------------------------------------------------------------------------------- */
553 kill_line (WInput
* in
)
557 chp
= str_offset_to_pos (in
->buffer
, in
->point
);
558 g_free (kill_buffer
);
559 kill_buffer
= g_strdup (&in
->buffer
[chp
]);
560 in
->buffer
[chp
] = '\0';
564 /* --------------------------------------------------------------------------------------------- */
567 clear_line (WInput
* in
)
569 in
->need_push
= TRUE
;
570 in
->buffer
[0] = '\0';
573 in
->highlight
= FALSE
;
577 /* --------------------------------------------------------------------------------------------- */
580 ins_from_clip (WInput
* in
)
583 ev_clipboard_text_from_file_t event_data
;
585 /* try use external clipboard utility */
586 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_file_from_ext_clip", NULL
);
588 event_data
.text
= &p
;
589 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_text_from_file", &event_data
);
594 for (pp
= p
; *pp
!= '\0'; pp
++)
595 insert_char (in
, *pp
);
601 /* --------------------------------------------------------------------------------------------- */
604 hist_prev (WInput
* in
)
608 if (in
->history
== NULL
)
612 push_history (in
, in
->buffer
);
614 prev
= g_list_previous (in
->history
);
618 in
->history_changed
= TRUE
;
619 input_assign_text (in
, (char *) prev
->data
);
620 in
->need_push
= FALSE
;
624 /* --------------------------------------------------------------------------------------------- */
627 hist_next (WInput
* in
)
633 push_history (in
, in
->buffer
);
634 input_assign_text (in
, "");
638 if (in
->history
== NULL
)
641 next
= g_list_next (in
->history
);
643 input_assign_text (in
, "");
647 in
->history_changed
= TRUE
;
648 input_assign_text (in
, (char *) next
->data
);
649 in
->need_push
= FALSE
;
653 /* --------------------------------------------------------------------------------------------- */
656 port_region_marked_for_delete (WInput
* in
)
658 in
->buffer
[0] = '\0';
664 /* --------------------------------------------------------------------------------------------- */
667 input_execute_cmd (WInput
* in
, unsigned long command
)
669 cb_ret_t res
= MSG_HANDLED
;
671 /* a highlight command like shift-arrow */
672 if (command
== CK_MarkLeft
|| command
== CK_MarkRight
||
673 command
== CK_MarkToWordBegin
|| command
== CK_MarkToWordEnd
||
674 command
== CK_MarkToHome
|| command
== CK_MarkToEnd
)
678 input_mark_cmd (in
, FALSE
); /* clear */
679 input_mark_cmd (in
, TRUE
); /* marking on */
690 input_mark_cmd (in
, FALSE
);
697 beginning_of_line (in
);
708 case CK_MarkToWordBegin
:
716 case CK_MarkToWordEnd
:
723 if (input_eval_marks (in
, &m1
, &m2
))
724 delete_region (in
, m1
, m2
);
727 backward_delete (in
);
731 port_region_marked_for_delete (in
);
732 else if (in
->highlight
)
735 if (input_eval_marks (in
, &m1
, &m2
))
736 delete_region (in
, m1
, m2
);
741 case CK_DeleteToWordEnd
:
744 case CK_DeleteToWordBegin
:
748 input_mark_cmd (in
, TRUE
);
751 delete_region (in
, in
->point
, in
->mark
);
760 copy_region (in
, in
->mark
, in
->point
);
763 copy_region (in
, in
->mark
, in
->point
);
764 delete_region (in
, in
->point
, in
->mark
);
785 res
= MSG_NOT_HANDLED
;
788 if (command
!= CK_MarkLeft
&& command
!= CK_MarkRight
&&
789 command
!= CK_MarkToWordBegin
&& command
!= CK_MarkToWordEnd
&&
790 command
!= CK_MarkToHome
&& command
!= CK_MarkToEnd
)
791 in
->highlight
= FALSE
;
796 /* --------------------------------------------------------------------------------------------- */
798 /* "history_load" event handler */
800 input_load_history (const gchar
* event_group_name
, const gchar
* event_name
,
801 gpointer init_data
, gpointer data
)
803 WInput
*in
= (WInput
*) init_data
;
804 ev_history_load_save_t
*ev
= (ev_history_load_save_t
*) data
;
805 const char *def_text
;
808 (void) event_group_name
;
811 in
->history
= history_load (ev
->cfg
, in
->history_name
);
813 if (in
->init_text
== NULL
)
815 else if (in
->init_text
== INPUT_LAST_TEXT
)
817 if (in
->history
!= NULL
&& in
->history
->data
!= NULL
)
818 def_text
= (const char *) in
->history
->data
;
822 in
->init_text
= NULL
;
825 def_text
= in
->init_text
;
827 buffer_len
= strlen (def_text
);
828 buffer_len
= 1 + max ((size_t) in
->field_width
, buffer_len
);
829 in
->current_max_size
= buffer_len
;
830 if (buffer_len
> (size_t) in
->field_width
)
831 in
->buffer
= g_realloc (in
->buffer
, buffer_len
);
832 strcpy (in
->buffer
, def_text
);
833 in
->point
= str_length (in
->buffer
);
838 /* --------------------------------------------------------------------------------------------- */
840 /* "history_save" event handler */
842 input_save_history (const gchar
* event_group_name
, const gchar
* event_name
,
843 gpointer init_data
, gpointer data
)
845 WInput
*in
= (WInput
*) init_data
;
847 (void) event_group_name
;
850 if (!in
->is_password
&& (((Widget
*) in
)->owner
->ret_value
!= B_CANCEL
))
852 ev_history_load_save_t
*ev
= (ev_history_load_save_t
*) data
;
854 push_history (in
, in
->buffer
);
855 if (in
->history_changed
)
856 history_save (ev
->cfg
, in
->history_name
, in
->history
);
857 in
->history_changed
= FALSE
;
863 /* --------------------------------------------------------------------------------------------- */
866 input_destroy (WInput
* in
)
870 fprintf (stderr
, "Internal error: null Input *\n");
874 input_free_completions (in
);
877 if (in
->history
!= NULL
)
879 /* history is already saved before this moment */
880 in
->history
= g_list_first (in
->history
);
881 g_list_foreach (in
->history
, (GFunc
) g_free
, NULL
);
882 g_list_free (in
->history
);
884 g_free (in
->history_name
);
887 input_free_completions (in
);
888 g_free (in
->init_text
);
890 g_free (kill_buffer
);
894 /* --------------------------------------------------------------------------------------------- */
897 input_event (Gpm_Event
* event
, void *data
)
899 WInput
*in
= (WInput
*) data
;
901 if ((event
->type
& GPM_DOWN
) != 0)
904 input_mark_cmd (in
, FALSE
);
907 if ((event
->type
& (GPM_DOWN
| GPM_DRAG
)) != 0)
909 dlg_select_widget (in
);
911 if (event
->x
>= in
->field_width
- HISTORY_BUTTON_WIDTH
+ 1
912 && should_show_history_button (in
))
916 in
->point
= str_length (in
->buffer
);
917 if (event
->x
+ in
->term_first_shown
- 1 < str_term_width1 (in
->buffer
))
918 in
->point
= str_column_to_pos (in
->buffer
, event
->x
+ in
->term_first_shown
- 1);
920 input_update (in
, TRUE
);
922 /* A lone up mustn't do anything */
923 if (in
->highlight
&& (event
->type
& (GPM_UP
| GPM_DRAG
)) != 0)
926 if ((event
->type
& GPM_DRAG
) == 0)
927 input_mark_cmd (in
, TRUE
);
932 /* --------------------------------------------------------------------------------------------- */
933 /*** public functions ****************************************************************************/
934 /* --------------------------------------------------------------------------------------------- */
936 /** Create new instance of WInput object.
937 * @param y Y coordinate
938 * @param x X coordinate
939 * @param input_colors Array of used colors
940 * @param width Widget width
941 * @param def_text Default text filled in widget
942 * @param histname Name of history
943 * @param completion_flags Flags for specify type of completions
944 * @returns WInput object
947 input_new (int y
, int x
, const int *input_colors
, int width
, const char *def_text
,
948 const char *histname
, input_complete_t completion_flags
)
952 in
= g_new (WInput
, 1);
953 init_widget (&in
->widget
, y
, x
, 1, width
, input_callback
, input_event
);
954 in
->widget
.options
|= W_IS_INPUT
;
956 memmove (in
->color
, input_colors
, sizeof (input_colors_t
));
958 in
->field_width
= width
;
960 in
->highlight
= FALSE
;
961 in
->term_first_shown
= 0;
962 in
->disable_update
= 0;
964 in
->need_push
= TRUE
;
965 in
->is_password
= FALSE
;
968 /* in->buffer will be corrected in "history_load" event handler */
969 in
->current_max_size
= width
+ 1;
970 in
->buffer
= g_new0 (char, in
->current_max_size
);
973 in
->init_text
= (def_text
== INPUT_LAST_TEXT
) ? INPUT_LAST_TEXT
: g_strdup (def_text
);
975 in
->completions
= NULL
;
976 in
->completion_flags
= completion_flags
;
978 /* prepare to history setup */
980 in
->history_changed
= FALSE
;
981 in
->history_name
= NULL
;
982 if ((histname
!= NULL
) && (*histname
!= '\0'))
983 in
->history_name
= g_strdup (histname
);
985 /* history will be loaded later */
990 /* --------------------------------------------------------------------------------------------- */
993 input_callback (Widget
* w
, widget_msg_t msg
, int parm
)
995 WInput
*in
= (WInput
*) w
;
1001 /* subscribe to "history_load" event */
1002 mc_event_add (w
->owner
->event_group
, MCEVENT_HISTORY_LOAD
, input_load_history
, w
, NULL
);
1003 /* subscribe to "history_save" event */
1004 mc_event_add (w
->owner
->event_group
, MCEVENT_HISTORY_SAVE
, input_save_history
, w
, NULL
);
1008 if (parm
== XCTRL ('q'))
1011 v
= input_handle_char (in
, ascii_alpha_to_cntrl (tty_getch ()));
1016 /* Keys we want others to handle */
1017 if (parm
== KEY_UP
|| parm
== KEY_DOWN
|| parm
== ESC_CHAR
1018 || parm
== KEY_F (10) || parm
== '\n')
1019 return MSG_NOT_HANDLED
;
1021 /* When pasting multiline text, insert literal Enter */
1022 if ((parm
& ~KEY_M_MASK
) == '\n')
1025 v
= input_handle_char (in
, '\n');
1030 return input_handle_char (in
, parm
);
1032 case WIDGET_COMMAND
:
1033 return input_execute_cmd (in
, parm
);
1036 case WIDGET_UNFOCUS
:
1038 input_update (in
, FALSE
);
1042 widget_move (&in
->widget
, 0, str_term_width2 (in
->buffer
, in
->point
)
1043 - in
->term_first_shown
);
1046 case WIDGET_DESTROY
:
1047 /* unsubscribe from "history_load" event */
1048 mc_event_del (w
->owner
->event_group
, MCEVENT_HISTORY_LOAD
, input_load_history
, w
);
1049 /* unsubscribe from "history_save" event */
1050 mc_event_del (w
->owner
->event_group
, MCEVENT_HISTORY_SAVE
, input_save_history
, w
);
1055 return default_proc (msg
, parm
);
1059 /* --------------------------------------------------------------------------------------------- */
1061 /** Get default colors for WInput widget.
1062 * @returns default colors
1065 input_get_default_colors (void)
1067 static input_colors_t standart_colors
;
1069 standart_colors
[WINPUTC_MAIN
] = INPUT_COLOR
;
1070 standart_colors
[WINPUTC_MARK
] = INPUT_MARK_COLOR
;
1071 standart_colors
[WINPUTC_UNCHANGED
] = INPUT_UNCHANGED_COLOR
;
1072 standart_colors
[WINPUTC_HISTORY
] = INPUT_HISTORY_COLOR
;
1074 return standart_colors
;
1077 /* --------------------------------------------------------------------------------------------- */
1080 input_set_origin (WInput
* in
, int x
, int field_width
)
1083 in
->field_width
= in
->widget
.cols
= field_width
;
1084 input_update (in
, FALSE
);
1087 /* --------------------------------------------------------------------------------------------- */
1090 input_handle_char (WInput
* in
, int key
)
1093 unsigned long command
;
1095 v
= MSG_NOT_HANDLED
;
1099 input_free_completions (in
);
1100 v
= insert_char (in
, key
);
1101 input_update (in
, TRUE
);
1106 command
= keybind_lookup_keymap_command (input_map
, key
);
1108 if (command
== CK_IgnoreKey
)
1111 return MSG_NOT_HANDLED
;
1113 port_region_marked_for_delete (in
);
1114 input_free_completions (in
);
1115 v
= insert_char (in
, key
);
1119 if (command
!= CK_Complete
)
1120 input_free_completions (in
);
1121 input_execute_cmd (in
, command
);
1124 input_update (in
, TRUE
); /* needed to clear in->first */
1127 input_update (in
, TRUE
);
1131 /* --------------------------------------------------------------------------------------------- */
1133 /* This function is a test for a special input key used in complete.c */
1134 /* Returns 0 if it is not a special key, 1 if it is a non-complete key
1135 and 2 if it is a complete key */
1137 input_key_is_in_map (WInput
* in
, int key
)
1139 unsigned long command
;
1143 command
= keybind_lookup_keymap_command (input_map
, key
);
1144 if (command
== CK_IgnoreKey
)
1147 return (command
== CK_Complete
) ? 2 : 1;
1150 /* --------------------------------------------------------------------------------------------- */
1153 input_assign_text (WInput
* in
, const char *text
)
1155 input_free_completions (in
);
1156 g_free (in
->buffer
);
1157 in
->buffer
= g_strdup (text
); /* was in->buffer->text */
1158 in
->current_max_size
= strlen (in
->buffer
) + 1;
1159 in
->point
= str_length (in
->buffer
);
1161 in
->need_push
= TRUE
;
1165 /* --------------------------------------------------------------------------------------------- */
1167 /* Inserts text in input line */
1169 input_insert (WInput
* in
, const char *text
, gboolean insert_extra_space
)
1171 input_disable_update (in
);
1172 while (*text
!= '\0')
1173 input_handle_char (in
, (unsigned char) *text
++); /* unsigned extension char->int */
1174 if (insert_extra_space
)
1175 input_handle_char (in
, ' ');
1176 input_enable_update (in
);
1177 input_update (in
, TRUE
);
1180 /* --------------------------------------------------------------------------------------------- */
1183 input_set_point (WInput
* in
, int pos
)
1187 max_pos
= str_length (in
->buffer
);
1188 pos
= min (pos
, max_pos
);
1189 if (pos
!= in
->point
)
1190 input_free_completions (in
);
1193 input_update (in
, TRUE
);
1196 /* --------------------------------------------------------------------------------------------- */
1199 input_update (WInput
* in
, gboolean clear_first
)
1201 int has_history
= 0;
1207 if (should_show_history_button (in
))
1208 has_history
= HISTORY_BUTTON_WIDTH
;
1210 if (in
->disable_update
!= 0)
1213 buf_len
= str_length (in
->buffer
);
1214 pw
= str_term_width2 (in
->buffer
, in
->point
);
1216 /* Make the point visible */
1217 if ((pw
< in
->term_first_shown
) || (pw
>= in
->term_first_shown
+ in
->field_width
- has_history
))
1219 in
->term_first_shown
= pw
- (in
->field_width
/ 3);
1220 if (in
->term_first_shown
< 0)
1221 in
->term_first_shown
= 0;
1224 /* Adjust the mark */
1225 in
->mark
= min (in
->mark
, buf_len
);
1227 if (has_history
!= 0)
1228 draw_history_button (in
);
1230 if ((((Widget
*) in
)->options
& W_DISABLED
) != 0)
1231 tty_setcolor (DISABLED_COLOR
);
1233 tty_setcolor (in
->color
[WINPUTC_UNCHANGED
]);
1235 tty_setcolor (in
->color
[WINPUTC_MAIN
]);
1237 widget_move (&in
->widget
, 0, 0);
1239 if (!in
->is_password
)
1242 tty_print_string (str_term_substring (in
->buffer
, in
->term_first_shown
,
1243 in
->field_width
- has_history
));
1248 if (input_eval_marks (in
, &m1
, &m2
))
1250 tty_setcolor (in
->color
[WINPUTC_MAIN
]);
1251 cp
= str_term_substring (in
->buffer
, in
->term_first_shown
,
1252 in
->field_width
- has_history
);
1253 tty_print_string (cp
);
1254 tty_setcolor (in
->color
[WINPUTC_MARK
]);
1255 if (m1
< in
->term_first_shown
)
1257 widget_move (&in
->widget
, 0, 0);
1258 tty_print_string (str_term_substring
1259 (in
->buffer
, in
->term_first_shown
,
1260 m2
- in
->term_first_shown
));
1266 widget_move (&in
->widget
, 0, m1
- in
->term_first_shown
);
1269 (in
->field_width
- has_history
) - (str_term_width2 (in
->buffer
, m1
) -
1270 in
->term_first_shown
));
1271 tty_print_string (str_term_substring (in
->buffer
, m1
, sel_width
));
1278 cp
= str_term_substring (in
->buffer
, in
->term_first_shown
, in
->field_width
- has_history
);
1279 tty_setcolor (in
->color
[WINPUTC_MAIN
]);
1280 for (i
= 0; i
< in
->field_width
- has_history
; i
++)
1282 if (i
< (buf_len
- in
->term_first_shown
) && cp
[0] != '\0')
1283 tty_print_char ('*');
1285 tty_print_char (' ');
1287 str_cnext_char (&cp
);
1295 /* --------------------------------------------------------------------------------------------- */
1298 input_enable_update (WInput
* in
)
1300 in
->disable_update
--;
1301 input_update (in
, FALSE
);
1304 /* --------------------------------------------------------------------------------------------- */
1307 input_disable_update (WInput
* in
)
1309 in
->disable_update
++;
1312 /* --------------------------------------------------------------------------------------------- */
1315 * Cleans the input line and adds the current text to the history
1317 * @param in the input line
1320 input_clean (WInput
* in
)
1322 push_history (in
, in
->buffer
);
1323 in
->need_push
= TRUE
;
1324 in
->buffer
[0] = '\0';
1328 in
->highlight
= FALSE
;
1329 input_free_completions (in
);
1330 input_update (in
, FALSE
);
1333 /* --------------------------------------------------------------------------------------------- */
1336 input_free_completions (WInput
* in
)
1338 g_strfreev (in
->completions
);
1339 in
->completions
= NULL
;
1342 /* --------------------------------------------------------------------------------------------- */