1 /* Widgets for the Midnight Commander
3 Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003,
4 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
6 Authors: 1994, 1995 Radek Doulik
7 1994, 1995 Miguel de Icaza
11 2009, 2010 Andrew Borodin
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 * \brief Source: WInput widget
36 #include <sys/types.h>
40 #include "lib/global.h"
42 #include "lib/tty/tty.h"
43 #include "lib/tty/mouse.h"
44 #include "lib/tty/key.h" /* XCTRL and ALT macros */
45 #include "lib/fileloc.h"
47 #include "lib/strutil.h"
49 #include "lib/keybind.h" /* global_keymap_t */
50 #include "lib/widget.h"
51 #include "lib/event.h" /* mc_event_raise() */
53 #include "input_complete.h"
55 /*** global variables ****************************************************************************/
59 const global_keymap_t
*input_map
= NULL
;
61 /*** file scope macro definitions ****************************************************************/
63 #define LARGE_HISTORY_BUTTON 1
65 #ifdef LARGE_HISTORY_BUTTON
66 #define HISTORY_BUTTON_WIDTH 3
68 #define HISTORY_BUTTON_WIDTH 1
71 #define should_show_history_button(in) \
72 (in->history != NULL && in->field_width > HISTORY_BUTTON_WIDTH * 2 + 1 \
73 && in->widget.owner != NULL)
75 /*** file scope type declarations ****************************************************************/
77 /*** file scope variables ************************************************************************/
79 /* Input widgets have a global kill ring */
80 /* Pointer to killed data */
81 static char *kill_buffer
= NULL
;
83 /*** file scope functions ************************************************************************/
84 /* --------------------------------------------------------------------------------------------- */
87 get_history_length (const GList
*history
)
91 for (; history
!= NULL
; history
= g_list_previous (history
))
97 /* --------------------------------------------------------------------------------------------- */
100 draw_history_button (WInput
* in
)
103 gboolean disabled
= (((Widget
*) in
)->options
& W_DISABLED
) != 0;
105 c
= in
->history
->next
? (in
->history
->prev
? '|' : 'v') : '^';
106 widget_move (&in
->widget
, 0, in
->field_width
- HISTORY_BUTTON_WIDTH
);
107 tty_setcolor (disabled
? DISABLED_COLOR
: in
->color
[WINPUTC_HISTORY
]);
108 #ifdef LARGE_HISTORY_BUTTON
111 h
= in
->widget
.owner
;
112 tty_print_string ("[ ]");
113 widget_move (&in
->widget
, 0, in
->field_width
- HISTORY_BUTTON_WIDTH
+ 1);
119 /* --------------------------------------------------------------------------------------------- */
122 input_set_markers (WInput
* in
, long m1
)
127 /* --------------------------------------------------------------------------------------------- */
130 input_mark_cmd (WInput
* in
, gboolean mark
)
134 in
->highlight
= FALSE
;
135 input_set_markers (in
, 0);
139 in
->highlight
= TRUE
;
140 input_set_markers (in
, in
->point
);
144 /* --------------------------------------------------------------------------------------------- */
147 input_eval_marks (WInput
* in
, long *start_mark
, long *end_mark
)
151 *start_mark
= min (in
->mark
, in
->point
);
152 *end_mark
= max (in
->mark
, in
->point
);
157 *start_mark
= *end_mark
= 0;
162 /* --------------------------------------------------------------------------------------------- */
165 delete_region (WInput
* in
, int x_first
, int x_last
)
167 int first
= min (x_first
, x_last
);
168 int last
= max (x_first
, x_last
);
171 input_mark_cmd (in
, FALSE
);
173 last
= str_offset_to_pos (in
->buffer
, last
);
174 first
= str_offset_to_pos (in
->buffer
, first
);
175 len
= strlen (&in
->buffer
[last
]) + 1;
176 memmove (&in
->buffer
[first
], &in
->buffer
[last
], len
);
178 in
->need_push
= TRUE
;
181 /* --------------------------------------------------------------------------------------------- */
184 do_show_hist (WInput
* in
)
189 len
= get_history_length (in
->history
);
191 r
= history_show (&in
->history
, &in
->widget
);
194 input_assign_text (in
, r
);
198 /* Has history cleaned up or not? */
199 if (len
!= get_history_length (in
->history
))
200 in
->history_changed
= TRUE
;
203 /* --------------------------------------------------------------------------------------------- */
206 push_history (WInput
* in
, const char *text
)
208 /* input widget where urls with passwords are entered without any
210 const char *password_input_fields
[] = {
211 " Link to a remote machine ",
213 " SMB link to machine "
215 const size_t ELEMENTS
= (sizeof (password_input_fields
) / sizeof (password_input_fields
[0]));
225 for (i
= 0; i
< ELEMENTS
; i
++)
226 password_input_fields
[i
] = _(password_input_fields
[i
]);
229 t
= g_strstrip (g_strdup (text
));
232 t
= g_strdup (empty
? "" : text
);
234 if (in
->history_name
!= NULL
)
236 /* FIXME: It is the strange code. Rewrite is needed. */
238 const char *p
= in
->history_name
+ 3;
240 for (i
= 0; i
< ELEMENTS
; i
++)
241 if (strcmp (p
, password_input_fields
[i
]) == 0)
244 strip_password (t
, i
>= ELEMENTS
);
247 if (in
->history
== NULL
|| in
->history
->data
== NULL
|| strcmp (in
->history
->data
, t
) != 0 ||
250 in
->history
= list_append_unique (in
->history
, t
);
251 in
->history_changed
= TRUE
;
256 in
->need_push
= FALSE
;
259 /* --------------------------------------------------------------------------------------------- */
262 move_buffer_backward (WInput
* in
, int start
, int end
)
267 str_len
= str_length (in
->buffer
);
268 if (start
>= str_len
|| end
> str_len
+ 1)
271 pos
= str_offset_to_pos (in
->buffer
, start
);
272 len
= str_offset_to_pos (in
->buffer
, end
) - pos
;
274 for (i
= pos
; in
->buffer
[i
+ len
- 1]; i
++)
275 in
->buffer
[i
] = in
->buffer
[i
+ len
];
278 /* --------------------------------------------------------------------------------------------- */
281 insert_char (WInput
* in
, int c_code
)
289 if (input_eval_marks (in
, &m1
, &m2
))
290 delete_region (in
, m1
, m2
);
293 return MSG_NOT_HANDLED
;
295 if (in
->charpoint
>= MB_LEN_MAX
)
298 in
->charbuf
[in
->charpoint
] = c_code
;
301 res
= str_is_valid_char (in
->charbuf
, in
->charpoint
);
305 in
->charpoint
= 0; /* broken multibyte char, skip */
309 in
->need_push
= TRUE
;
310 if (strlen (in
->buffer
) + 1 + in
->charpoint
>= in
->current_max_size
)
312 /* Expand the buffer */
313 size_t new_length
= in
->current_max_size
+ in
->field_width
+ in
->charpoint
;
314 char *narea
= g_try_renew (char, in
->buffer
, new_length
);
318 in
->current_max_size
= new_length
;
322 if (strlen (in
->buffer
) + in
->charpoint
< in
->current_max_size
)
324 /* bytes from begin */
325 size_t ins_point
= str_offset_to_pos (in
->buffer
, in
->point
);
327 size_t rest_bytes
= strlen (in
->buffer
+ ins_point
);
329 for (i
= rest_bytes
+ 1; i
> 0; i
--)
330 in
->buffer
[ins_point
+ i
+ in
->charpoint
- 1] = in
->buffer
[ins_point
+ i
- 1];
332 memcpy (in
->buffer
+ ins_point
, in
->charbuf
, in
->charpoint
);
340 /* --------------------------------------------------------------------------------------------- */
343 beginning_of_line (WInput
* in
)
349 /* --------------------------------------------------------------------------------------------- */
352 end_of_line (WInput
* in
)
354 in
->point
= str_length (in
->buffer
);
358 /* --------------------------------------------------------------------------------------------- */
361 backward_char (WInput
* in
)
365 act
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
367 in
->point
-= str_cprev_noncomb_char (&act
, in
->buffer
);
371 /* --------------------------------------------------------------------------------------------- */
374 forward_char (WInput
* in
)
378 act
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
380 in
->point
+= str_cnext_noncomb_char (&act
);
384 /* --------------------------------------------------------------------------------------------- */
387 forward_word (WInput
* in
)
391 p
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
392 while (p
[0] != '\0' && (str_isspace (p
) || str_ispunct (p
)))
397 while (p
[0] != '\0' && !str_isspace (p
) && !str_ispunct (p
))
404 /* --------------------------------------------------------------------------------------------- */
407 backward_word (WInput
* in
)
409 const char *p
, *p_tmp
;
411 for (p
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
412 (p
!= in
->buffer
) && (p
[0] == '\0'); str_cprev_char (&p
), in
->point
--);
414 while (p
!= in
->buffer
)
418 if (!str_isspace (p
) && !str_ispunct (p
))
425 while (p
!= in
->buffer
)
428 if (str_isspace (p
) || str_ispunct (p
))
435 /* --------------------------------------------------------------------------------------------- */
438 backward_delete (WInput
* in
)
440 const char *act
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
446 start
= in
->point
- str_cprev_noncomb_char (&act
, in
->buffer
);
447 move_buffer_backward (in
, start
, in
->point
);
449 in
->need_push
= TRUE
;
453 /* --------------------------------------------------------------------------------------------- */
456 delete_char (WInput
* in
)
461 act
= in
->buffer
+ str_offset_to_pos (in
->buffer
, in
->point
);
462 end
+= str_cnext_noncomb_char (&act
);
464 move_buffer_backward (in
, in
->point
, end
);
466 in
->need_push
= TRUE
;
469 /* --------------------------------------------------------------------------------------------- */
472 copy_region (WInput
* in
, int x_first
, int x_last
)
474 int first
= min (x_first
, x_last
);
475 int last
= max (x_first
, x_last
);
479 /* Copy selected files to clipboard */
480 mc_event_raise (MCEVENT_GROUP_FILEMANAGER
, "panel_save_curent_file_to_clip_file", NULL
);
481 /* try use external clipboard utility */
482 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_file_to_ext_clip", NULL
);
486 g_free (kill_buffer
);
488 first
= str_offset_to_pos (in
->buffer
, first
);
489 last
= str_offset_to_pos (in
->buffer
, last
);
491 kill_buffer
= g_strndup (in
->buffer
+ first
, last
- first
);
493 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_text_to_file", kill_buffer
);
494 /* try use external clipboard utility */
495 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_file_to_ext_clip", NULL
);
498 /* --------------------------------------------------------------------------------------------- */
501 kill_word (WInput
* in
)
503 int old_point
= in
->point
;
507 new_point
= in
->point
;
508 in
->point
= old_point
;
510 delete_region (in
, old_point
, new_point
);
511 in
->need_push
= TRUE
;
515 /* --------------------------------------------------------------------------------------------- */
518 back_kill_word (WInput
* in
)
520 int old_point
= in
->point
;
524 new_point
= in
->point
;
525 in
->point
= old_point
;
527 delete_region (in
, old_point
, new_point
);
528 in
->need_push
= TRUE
;
531 /* --------------------------------------------------------------------------------------------- */
536 if (kill_buffer
!= NULL
)
541 for (p
= kill_buffer
; *p
!= '\0'; p
++)
542 insert_char (in
, *p
);
547 /* --------------------------------------------------------------------------------------------- */
550 kill_line (WInput
* in
)
554 chp
= str_offset_to_pos (in
->buffer
, in
->point
);
555 g_free (kill_buffer
);
556 kill_buffer
= g_strdup (&in
->buffer
[chp
]);
557 in
->buffer
[chp
] = '\0';
561 /* --------------------------------------------------------------------------------------------- */
564 clear_line (WInput
* in
)
566 in
->need_push
= TRUE
;
567 in
->buffer
[0] = '\0';
570 in
->highlight
= FALSE
;
574 /* --------------------------------------------------------------------------------------------- */
577 ins_from_clip (WInput
* in
)
580 ev_clipboard_text_from_file_t event_data
;
582 /* try use external clipboard utility */
583 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_file_from_ext_clip", NULL
);
585 event_data
.text
= &p
;
586 mc_event_raise (MCEVENT_GROUP_CORE
, "clipboard_text_from_file", &event_data
);
591 for (pp
= p
; *pp
!= '\0'; pp
++)
592 insert_char (in
, *pp
);
598 /* --------------------------------------------------------------------------------------------- */
601 hist_prev (WInput
* in
)
605 if (in
->history
== NULL
)
609 push_history (in
, in
->buffer
);
611 prev
= g_list_previous (in
->history
);
615 in
->history_changed
= TRUE
;
616 input_assign_text (in
, (char *) prev
->data
);
617 in
->need_push
= FALSE
;
621 /* --------------------------------------------------------------------------------------------- */
624 hist_next (WInput
* in
)
630 push_history (in
, in
->buffer
);
631 input_assign_text (in
, "");
635 if (in
->history
== NULL
)
638 next
= g_list_next (in
->history
);
640 input_assign_text (in
, "");
644 in
->history_changed
= TRUE
;
645 input_assign_text (in
, (char *) next
->data
);
646 in
->need_push
= FALSE
;
650 /* --------------------------------------------------------------------------------------------- */
653 port_region_marked_for_delete (WInput
* in
)
655 in
->buffer
[0] = '\0';
661 /* --------------------------------------------------------------------------------------------- */
664 input_execute_cmd (WInput
* in
, unsigned long command
)
666 cb_ret_t res
= MSG_HANDLED
;
668 /* a highlight command like shift-arrow */
669 if (command
== CK_MarkLeft
|| command
== CK_MarkRight
||
670 command
== CK_MarkToWordBegin
|| command
== CK_MarkToWordEnd
||
671 command
== CK_MarkToHome
|| command
== CK_MarkToEnd
)
675 input_mark_cmd (in
, FALSE
); /* clear */
676 input_mark_cmd (in
, TRUE
); /* marking on */
687 input_mark_cmd (in
, FALSE
);
694 beginning_of_line (in
);
705 case CK_MarkToWordBegin
:
713 case CK_MarkToWordEnd
:
720 if (input_eval_marks (in
, &m1
, &m2
))
721 delete_region (in
, m1
, m2
);
724 backward_delete (in
);
728 port_region_marked_for_delete (in
);
729 else if (in
->highlight
)
732 if (input_eval_marks (in
, &m1
, &m2
))
733 delete_region (in
, m1
, m2
);
738 case CK_DeleteToWordEnd
:
741 case CK_DeleteToWordBegin
:
745 input_mark_cmd (in
, TRUE
);
748 delete_region (in
, in
->point
, in
->mark
);
757 copy_region (in
, in
->mark
, in
->point
);
760 copy_region (in
, in
->mark
, in
->point
);
761 delete_region (in
, in
->point
, in
->mark
);
782 res
= MSG_NOT_HANDLED
;
785 if (command
!= CK_MarkLeft
&& command
!= CK_MarkRight
&&
786 command
!= CK_MarkToWordBegin
&& command
!= CK_MarkToWordEnd
&&
787 command
!= CK_MarkToHome
&& command
!= CK_MarkToEnd
)
788 in
->highlight
= FALSE
;
793 /* --------------------------------------------------------------------------------------------- */
795 /* "history_load" event handler */
797 input_load_history (const gchar
* event_group_name
, const gchar
* event_name
,
798 gpointer init_data
, gpointer data
)
800 WInput
*in
= (WInput
*) init_data
;
801 ev_history_load_save_t
*ev
= (ev_history_load_save_t
*) data
;
802 const char *def_text
;
805 (void) event_group_name
;
808 in
->history
= history_load (ev
->cfg
, in
->history_name
);
810 if (in
->init_text
== NULL
)
812 else if (in
->init_text
== INPUT_LAST_TEXT
)
814 if (in
->history
!= NULL
&& in
->history
->data
!= NULL
)
815 def_text
= (const char *) in
->history
->data
;
819 in
->init_text
= NULL
;
822 def_text
= in
->init_text
;
824 buffer_len
= strlen (def_text
);
825 buffer_len
= 1 + max ((size_t) in
->field_width
, buffer_len
);
826 in
->current_max_size
= buffer_len
;
827 if (buffer_len
> (size_t) in
->field_width
)
828 in
->buffer
= g_realloc (in
->buffer
, buffer_len
);
829 strcpy (in
->buffer
, def_text
);
830 in
->point
= str_length (in
->buffer
);
835 /* --------------------------------------------------------------------------------------------- */
837 /* "history_save" event handler */
839 input_save_history (const gchar
* event_group_name
, const gchar
* event_name
,
840 gpointer init_data
, gpointer data
)
842 WInput
*in
= (WInput
*) init_data
;
844 (void) event_group_name
;
847 if (!in
->is_password
&& (((Widget
*) in
)->owner
->ret_value
!= B_CANCEL
))
849 ev_history_load_save_t
*ev
= (ev_history_load_save_t
*) data
;
851 push_history (in
, in
->buffer
);
852 if (in
->history_changed
)
853 history_save (ev
->cfg
, in
->history_name
, in
->history
);
854 in
->history_changed
= FALSE
;
860 /* --------------------------------------------------------------------------------------------- */
863 input_destroy (WInput
* in
)
867 fprintf (stderr
, "Internal error: null Input *\n");
871 input_free_completions (in
);
874 if (in
->history
!= NULL
)
876 /* history is already saved before this moment */
877 in
->history
= g_list_first (in
->history
);
878 g_list_foreach (in
->history
, (GFunc
) g_free
, NULL
);
879 g_list_free (in
->history
);
881 g_free (in
->history_name
);
884 input_free_completions (in
);
885 g_free (in
->init_text
);
887 g_free (kill_buffer
);
891 /* --------------------------------------------------------------------------------------------- */
894 input_event (Gpm_Event
* event
, void *data
)
896 WInput
*in
= (WInput
*) data
;
898 if ((event
->type
& GPM_DOWN
) != 0)
901 input_mark_cmd (in
, FALSE
);
904 if ((event
->type
& (GPM_DOWN
| GPM_DRAG
)) != 0)
906 dlg_select_widget (in
);
908 if (event
->x
>= in
->field_width
- HISTORY_BUTTON_WIDTH
+ 1
909 && should_show_history_button (in
))
913 in
->point
= str_length (in
->buffer
);
914 if (event
->x
+ in
->term_first_shown
- 1 < str_term_width1 (in
->buffer
))
915 in
->point
= str_column_to_pos (in
->buffer
, event
->x
+ in
->term_first_shown
- 1);
917 input_update (in
, TRUE
);
919 /* A lone up mustn't do anything */
920 if (in
->highlight
&& (event
->type
& (GPM_UP
| GPM_DRAG
)) != 0)
923 if ((event
->type
& GPM_DRAG
) == 0)
924 input_mark_cmd (in
, TRUE
);
929 /* --------------------------------------------------------------------------------------------- */
930 /*** public functions ****************************************************************************/
931 /* --------------------------------------------------------------------------------------------- */
933 /** Create new instance of WInput object.
934 * @param y Y coordinate
935 * @param x X coordinate
936 * @param input_colors Array of used colors
937 * @param width Widget width
938 * @param def_text Default text filled in widget
939 * @param histname Name of history
940 * @param completion_flags Flags for specify type of completions
941 * @returns WInput object
944 input_new (int y
, int x
, const int *input_colors
, int width
, const char *def_text
,
945 const char *histname
, input_complete_t completion_flags
)
949 in
= g_new (WInput
, 1);
950 init_widget (&in
->widget
, y
, x
, 1, width
, input_callback
, input_event
);
951 in
->widget
.options
|= W_IS_INPUT
;
953 memmove (in
->color
, input_colors
, sizeof (input_colors_t
));
955 in
->field_width
= width
;
957 in
->highlight
= FALSE
;
958 in
->term_first_shown
= 0;
959 in
->disable_update
= 0;
961 in
->need_push
= TRUE
;
962 in
->is_password
= FALSE
;
965 /* in->buffer will be corrected in "history_load" event handler */
966 in
->current_max_size
= width
+ 1;
967 in
->buffer
= g_new0 (char, in
->current_max_size
);
970 in
->init_text
= (def_text
== INPUT_LAST_TEXT
) ? INPUT_LAST_TEXT
: g_strdup (def_text
);
972 in
->completions
= NULL
;
973 in
->completion_flags
= completion_flags
;
975 /* prepare to history setup */
977 in
->history_changed
= FALSE
;
978 in
->history_name
= NULL
;
979 if ((histname
!= NULL
) && (*histname
!= '\0'))
980 in
->history_name
= g_strdup (histname
);
982 /* history will be loaded later */
987 /* --------------------------------------------------------------------------------------------- */
990 input_callback (Widget
* w
, widget_msg_t msg
, int parm
)
992 WInput
*in
= (WInput
*) w
;
998 /* subscribe to "history_load" event */
999 mc_event_add (w
->owner
->event_group
, MCEVENT_HISTORY_LOAD
, input_load_history
, w
, NULL
);
1000 /* subscribe to "history_save" event */
1001 mc_event_add (w
->owner
->event_group
, MCEVENT_HISTORY_SAVE
, input_save_history
, w
, NULL
);
1005 if (parm
== XCTRL ('q'))
1008 v
= input_handle_char (in
, ascii_alpha_to_cntrl (tty_getch ()));
1013 /* Keys we want others to handle */
1014 if (parm
== KEY_UP
|| parm
== KEY_DOWN
|| parm
== ESC_CHAR
1015 || parm
== KEY_F (10) || parm
== '\n')
1016 return MSG_NOT_HANDLED
;
1018 /* When pasting multiline text, insert literal Enter */
1019 if ((parm
& ~KEY_M_MASK
) == '\n')
1022 v
= input_handle_char (in
, '\n');
1027 return input_handle_char (in
, parm
);
1029 case WIDGET_COMMAND
:
1030 return input_execute_cmd (in
, parm
);
1033 case WIDGET_UNFOCUS
:
1035 input_update (in
, FALSE
);
1039 widget_move (&in
->widget
, 0, str_term_width2 (in
->buffer
, in
->point
)
1040 - in
->term_first_shown
);
1043 case WIDGET_DESTROY
:
1044 /* unsubscribe from "history_load" event */
1045 mc_event_del (w
->owner
->event_group
, MCEVENT_HISTORY_LOAD
, input_load_history
, w
);
1046 /* unsubscribe from "history_save" event */
1047 mc_event_del (w
->owner
->event_group
, MCEVENT_HISTORY_SAVE
, input_save_history
, w
);
1052 return default_proc (msg
, parm
);
1056 /* --------------------------------------------------------------------------------------------- */
1058 /** Get default colors for WInput widget.
1059 * @returns default colors
1062 input_get_default_colors (void)
1064 static input_colors_t standart_colors
;
1066 standart_colors
[WINPUTC_MAIN
] = INPUT_COLOR
;
1067 standart_colors
[WINPUTC_MARK
] = INPUT_MARK_COLOR
;
1068 standart_colors
[WINPUTC_UNCHANGED
] = INPUT_UNCHANGED_COLOR
;
1069 standart_colors
[WINPUTC_HISTORY
] = INPUT_HISTORY_COLOR
;
1071 return standart_colors
;
1074 /* --------------------------------------------------------------------------------------------- */
1077 input_set_origin (WInput
* in
, int x
, int field_width
)
1080 in
->field_width
= in
->widget
.cols
= field_width
;
1081 input_update (in
, FALSE
);
1084 /* --------------------------------------------------------------------------------------------- */
1087 input_handle_char (WInput
* in
, int key
)
1090 unsigned long command
;
1092 v
= MSG_NOT_HANDLED
;
1096 input_free_completions (in
);
1097 v
= insert_char (in
, key
);
1098 input_update (in
, TRUE
);
1103 command
= keybind_lookup_keymap_command (input_map
, key
);
1105 if (command
== CK_IgnoreKey
)
1108 return MSG_NOT_HANDLED
;
1110 port_region_marked_for_delete (in
);
1111 input_free_completions (in
);
1112 v
= insert_char (in
, key
);
1116 if (command
!= CK_Complete
)
1117 input_free_completions (in
);
1118 input_execute_cmd (in
, command
);
1121 input_update (in
, TRUE
); /* needed to clear in->first */
1124 input_update (in
, TRUE
);
1128 /* --------------------------------------------------------------------------------------------- */
1130 /* This function is a test for a special input key used in complete.c */
1131 /* Returns 0 if it is not a special key, 1 if it is a non-complete key
1132 and 2 if it is a complete key */
1134 input_key_is_in_map (WInput
* in
, int key
)
1136 unsigned long command
;
1140 command
= keybind_lookup_keymap_command (input_map
, key
);
1141 if (command
== CK_IgnoreKey
)
1144 return (command
== CK_Complete
) ? 2 : 1;
1147 /* --------------------------------------------------------------------------------------------- */
1150 input_assign_text (WInput
* in
, const char *text
)
1152 input_free_completions (in
);
1153 g_free (in
->buffer
);
1154 in
->buffer
= g_strdup (text
); /* was in->buffer->text */
1155 in
->current_max_size
= strlen (in
->buffer
) + 1;
1156 in
->point
= str_length (in
->buffer
);
1158 in
->need_push
= TRUE
;
1162 /* --------------------------------------------------------------------------------------------- */
1164 /* Inserts text in input line */
1166 input_insert (WInput
* in
, const char *text
, gboolean insert_extra_space
)
1168 input_disable_update (in
);
1169 while (*text
!= '\0')
1170 input_handle_char (in
, (unsigned char) *text
++); /* unsigned extension char->int */
1171 if (insert_extra_space
)
1172 input_handle_char (in
, ' ');
1173 input_enable_update (in
);
1174 input_update (in
, TRUE
);
1177 /* --------------------------------------------------------------------------------------------- */
1180 input_set_point (WInput
* in
, int pos
)
1184 max_pos
= str_length (in
->buffer
);
1185 pos
= min (pos
, max_pos
);
1186 if (pos
!= in
->point
)
1187 input_free_completions (in
);
1190 input_update (in
, TRUE
);
1193 /* --------------------------------------------------------------------------------------------- */
1196 input_update (WInput
* in
, gboolean clear_first
)
1198 int has_history
= 0;
1204 if (should_show_history_button (in
))
1205 has_history
= HISTORY_BUTTON_WIDTH
;
1207 if (in
->disable_update
!= 0)
1210 buf_len
= str_length (in
->buffer
);
1211 pw
= str_term_width2 (in
->buffer
, in
->point
);
1213 /* Make the point visible */
1214 if ((pw
< in
->term_first_shown
) || (pw
>= in
->term_first_shown
+ in
->field_width
- has_history
))
1216 in
->term_first_shown
= pw
- (in
->field_width
/ 3);
1217 if (in
->term_first_shown
< 0)
1218 in
->term_first_shown
= 0;
1221 /* Adjust the mark */
1222 in
->mark
= min (in
->mark
, buf_len
);
1224 if (has_history
!= 0)
1225 draw_history_button (in
);
1227 if ((((Widget
*) in
)->options
& W_DISABLED
) != 0)
1228 tty_setcolor (DISABLED_COLOR
);
1230 tty_setcolor (in
->color
[WINPUTC_UNCHANGED
]);
1232 tty_setcolor (in
->color
[WINPUTC_MAIN
]);
1234 widget_move (&in
->widget
, 0, 0);
1236 if (!in
->is_password
)
1239 tty_print_string (str_term_substring (in
->buffer
, in
->term_first_shown
,
1240 in
->field_width
- has_history
));
1245 if (input_eval_marks (in
, &m1
, &m2
))
1247 tty_setcolor (in
->color
[WINPUTC_MAIN
]);
1248 cp
= str_term_substring (in
->buffer
, in
->term_first_shown
,
1249 in
->field_width
- has_history
);
1250 tty_print_string (cp
);
1251 tty_setcolor (in
->color
[WINPUTC_MARK
]);
1252 if (m1
< in
->term_first_shown
)
1254 widget_move (&in
->widget
, 0, 0);
1255 tty_print_string (str_term_substring
1256 (in
->buffer
, in
->term_first_shown
,
1257 m2
- in
->term_first_shown
));
1263 widget_move (&in
->widget
, 0, m1
- in
->term_first_shown
);
1266 (in
->field_width
- has_history
) - (str_term_width2 (in
->buffer
, m1
) -
1267 in
->term_first_shown
));
1268 tty_print_string (str_term_substring (in
->buffer
, m1
, sel_width
));
1275 cp
= str_term_substring (in
->buffer
, in
->term_first_shown
, in
->field_width
- has_history
);
1276 for (i
= 0; i
< in
->field_width
- has_history
; i
++)
1280 tty_setcolor (in
->color
[WINPUTC_MAIN
]);
1281 tty_print_char ((cp
[0] != '\0') ? '*' : ' ');
1284 str_cnext_char (&cp
);
1292 /* --------------------------------------------------------------------------------------------- */
1295 input_enable_update (WInput
* in
)
1297 in
->disable_update
--;
1298 input_update (in
, FALSE
);
1301 /* --------------------------------------------------------------------------------------------- */
1304 input_disable_update (WInput
* in
)
1306 in
->disable_update
++;
1309 /* --------------------------------------------------------------------------------------------- */
1312 * Cleans the input line and adds the current text to the history
1314 * @param in the input line
1317 input_clean (WInput
* in
)
1319 push_history (in
, in
->buffer
);
1320 in
->need_push
= TRUE
;
1321 in
->buffer
[0] = '\0';
1325 in
->highlight
= FALSE
;
1326 input_free_completions (in
);
1327 input_update (in
, FALSE
);
1330 /* --------------------------------------------------------------------------------------------- */
1333 input_free_completions (WInput
* in
)
1335 g_strfreev (in
->completions
);
1336 in
->completions
= NULL
;
1339 /* --------------------------------------------------------------------------------------------- */