This source file includes following definitions.
- get_history_length
- draw_history_button
- input_mark_cmd
- input_eval_marks
- do_show_hist
- input_history_strip_password
- input_push_history
- move_buffer_backward
- beginning_of_line
- end_of_line
- backward_char
- forward_char
- forward_word
- backward_word
- backward_delete
- copy_region
- delete_region
- insert_char
- delete_char
- kill_word
- back_kill_word
- yank
- kill_line
- clear_line
- ins_from_clip
- hist_prev
- hist_next
- port_region_marked_for_delete
- input_execute_cmd
- input_load_history
- input_save_history
- input_destroy
- input_screen_to_point
- input_mouse_callback
- input_new
- input_callback
- input_set_default_colors
- input_handle_char
- input_assign_text
- input_insert
- input_set_point
- input_update
- input_enable_update
- input_disable_update
- input_clean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #include <config.h>
36
37 #include <stdlib.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40
41 #include "lib/global.h"
42
43 #include "lib/tty/tty.h"
44 #include "lib/tty/key.h"
45 #include "lib/fileloc.h"
46 #include "lib/skin.h"
47 #include "lib/strutil.h"
48 #include "lib/util.h"
49 #include "lib/widget.h"
50 #include "lib/event.h"
51 #include "lib/mcconfig.h"
52
53
54
55 gboolean quote = FALSE;
56
57 const global_keymap_t *input_map = NULL;
58
59
60 input_colors_t input_colors;
61
62
63
64 #define LARGE_HISTORY_BUTTON 1
65
66 #ifdef LARGE_HISTORY_BUTTON
67 #define HISTORY_BUTTON_WIDTH 3
68 #else
69 #define HISTORY_BUTTON_WIDTH 1
70 #endif
71
72 #define should_show_history_button(in) \
73 (in->history.list != NULL && WIDGET (in)->rect.cols > HISTORY_BUTTON_WIDTH * 2 + 1 \
74 && WIDGET (in)->owner != NULL)
75
76
77
78
79
80
81
82
83
84 static char *kill_buffer = NULL;
85
86
87
88
89
90 static size_t
91 get_history_length (GList *history)
92 {
93 size_t len = 0;
94
95 for (; history != NULL; history = g_list_previous (history))
96 len++;
97
98 return len;
99 }
100
101
102
103 static void
104 draw_history_button (WInput *in)
105 {
106 char c;
107 gboolean disabled;
108
109 if (g_list_next (in->history.current) == NULL)
110 c = '^';
111 else if (g_list_previous (in->history.current) == NULL)
112 c = 'v';
113 else
114 c = '|';
115
116 widget_gotoyx (in, 0, WIDGET (in)->rect.cols - HISTORY_BUTTON_WIDTH);
117 disabled = widget_get_state (WIDGET (in), WST_DISABLED);
118 tty_setcolor (disabled ? DISABLED_COLOR : in->color[WINPUTC_HISTORY]);
119
120 #ifdef LARGE_HISTORY_BUTTON
121 tty_print_string ("[ ]");
122 widget_gotoyx (in, 0, WIDGET (in)->rect.cols - HISTORY_BUTTON_WIDTH + 1);
123 #endif
124
125 tty_print_char (c);
126 }
127
128
129
130 static void
131 input_mark_cmd (WInput *in, gboolean mark)
132 {
133 in->mark = mark ? in->point : -1;
134 }
135
136
137
138 static gboolean
139 input_eval_marks (WInput *in, long *start_mark, long *end_mark)
140 {
141 if (in->mark >= 0)
142 {
143 *start_mark = MIN (in->mark, in->point);
144 *end_mark = MAX (in->mark, in->point);
145 return TRUE;
146 }
147
148 *start_mark = *end_mark = -1;
149 return FALSE;
150 }
151
152
153
154 static void
155 do_show_hist (WInput *in)
156 {
157 size_t len;
158 history_descriptor_t hd;
159
160 len = get_history_length (in->history.list);
161
162 history_descriptor_init (&hd, WIDGET (in)->rect.y, WIDGET (in)->rect.x, in->history.list,
163 g_list_position (in->history.list, in->history.list));
164 history_show (&hd);
165
166
167
168 in->history.list = hd.list;
169 in->history.current = in->history.list;
170 if (hd.text != NULL)
171 {
172 input_assign_text (in, hd.text);
173 g_free (hd.text);
174 }
175
176
177 if (len != get_history_length (in->history.list))
178 in->history.changed = TRUE;
179 }
180
181
182
183
184
185
186
187
188
189 static char *
190 input_history_strip_password (char *url)
191 {
192 char *at, *delim, *colon;
193
194 at = strrchr (url, '@');
195 if (at == NULL)
196 return g_strdup (url);
197
198
199
200 delim = strstr (url, VFS_PATH_URL_DELIMITER);
201 if (delim != NULL)
202 colon = strchr (delim + strlen (VFS_PATH_URL_DELIMITER), ':');
203 else
204 colon = strchr (url, ':');
205
206
207
208 if (colon != NULL && colon > at)
209 colon = NULL;
210
211 if (colon == NULL)
212 return g_strdup (url);
213 *colon = '\0';
214
215 return g_strconcat (url, at, (char *) NULL);
216 }
217
218
219
220 static void
221 input_push_history (WInput *in)
222 {
223 char *t;
224 gboolean empty;
225
226 t = g_strstrip (input_get_text (in));
227 empty = *t == '\0';
228 if (!empty)
229 {
230 g_free (t);
231 t = input_get_text (in);
232
233 if (in->history.name != NULL && in->strip_password)
234 {
235
236
237
238
239
240 char *url_with_stripped_password;
241
242 url_with_stripped_password = input_history_strip_password (t);
243 g_free (t);
244 t = url_with_stripped_password;
245 }
246 }
247
248 if (in->history.list == NULL || in->history.list->data == NULL
249 || strcmp (in->history.list->data, t) != 0 || in->history.changed)
250 {
251 in->history.list = list_append_unique (in->history.list, t);
252 in->history.current = in->history.list;
253 in->history.changed = TRUE;
254 }
255 else
256 g_free (t);
257
258 in->need_push = FALSE;
259 }
260
261
262
263 static void
264 move_buffer_backward (WInput *in, int start, int end)
265 {
266 int str_len;
267
268 str_len = str_length (in->buffer->str);
269 if (start >= str_len || end > str_len + 1)
270 return;
271
272 start = str_offset_to_pos (in->buffer->str, start);
273 end = str_offset_to_pos (in->buffer->str, end);
274 g_string_erase (in->buffer, start, end - start);
275 }
276
277
278
279 static void
280 beginning_of_line (WInput *in)
281 {
282 in->point = 0;
283 in->charpoint = 0;
284 }
285
286
287
288 static void
289 end_of_line (WInput *in)
290 {
291 in->point = str_length (in->buffer->str);
292 in->charpoint = 0;
293 }
294
295
296
297 static void
298 backward_char (WInput *in)
299 {
300 if (in->point > 0)
301 {
302 const char *act;
303
304 act = in->buffer->str + str_offset_to_pos (in->buffer->str, in->point);
305 in->point -= str_cprev_noncomb_char (&act, in->buffer->str);
306 }
307
308 in->charpoint = 0;
309 }
310
311
312
313 static void
314 forward_char (WInput *in)
315 {
316 const char *act;
317
318 act = in->buffer->str + str_offset_to_pos (in->buffer->str, in->point);
319 if (act[0] != '\0')
320 in->point += str_cnext_noncomb_char (&act);
321 in->charpoint = 0;
322 }
323
324
325
326 static void
327 forward_word (WInput *in)
328 {
329 const char *p;
330
331 p = in->buffer->str + str_offset_to_pos (in->buffer->str, in->point);
332
333 for (; p[0] != '\0' && (str_isspace (p) || str_ispunct (p)); in->point++)
334 str_cnext_char (&p);
335
336 for (; p[0] != '\0' && !str_isspace (p) && !str_ispunct (p); in->point++)
337 str_cnext_char (&p);
338 }
339
340
341
342 static void
343 backward_word (WInput *in)
344 {
345 const char *p;
346
347 p = in->buffer->str + str_offset_to_pos (in->buffer->str, in->point);
348
349 for (; p != in->buffer->str; in->point--)
350 {
351 const char *p_tmp;
352
353 p_tmp = p;
354 str_cprev_char (&p);
355 if (!str_isspace (p) && !str_ispunct (p))
356 {
357 p = p_tmp;
358 break;
359 }
360 }
361
362 for (; p != in->buffer->str; in->point--)
363 {
364 str_cprev_char (&p);
365 if (str_isspace (p) || str_ispunct (p))
366 break;
367 }
368 }
369
370
371
372 static void
373 backward_delete (WInput *in)
374 {
375 const char *act;
376 int start;
377
378 if (in->point == 0)
379 return;
380
381 act = in->buffer->str + str_offset_to_pos (in->buffer->str, in->point);
382 start = in->point - str_cprev_noncomb_char (&act, in->buffer->str);
383 move_buffer_backward (in, start, in->point);
384 in->charpoint = 0;
385 in->need_push = TRUE;
386 in->point = start;
387 }
388
389
390
391 static void
392 copy_region (WInput *in, int start, int end)
393 {
394 int first = MIN (start, end);
395 int last = MAX (start, end);
396
397 if (last == first)
398 {
399
400 mc_event_raise (MCEVENT_GROUP_FILEMANAGER, "panel_save_current_file_to_clip_file", NULL);
401
402 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_file_to_ext_clip", NULL);
403 return;
404 }
405
406 g_free (kill_buffer);
407
408 first = str_offset_to_pos (in->buffer->str, first);
409 last = str_offset_to_pos (in->buffer->str, last);
410
411 kill_buffer = g_strndup (in->buffer->str + first, last - first);
412
413 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_text_to_file", kill_buffer);
414
415 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_file_to_ext_clip", NULL);
416 }
417
418
419
420 static void
421 delete_region (WInput *in, int start, int end)
422 {
423 int first = MIN (start, end);
424 int last = MAX (start, end);
425
426 input_mark_cmd (in, FALSE);
427 in->point = first;
428 move_buffer_backward (in, first, last);
429 in->charpoint = 0;
430 in->need_push = TRUE;
431 }
432
433
434
435 static cb_ret_t
436 insert_char (WInput *in, int c_code)
437 {
438 int res;
439 long m1, m2;
440 size_t ins_point;
441
442 if (input_eval_marks (in, &m1, &m2))
443 delete_region (in, m1, m2);
444
445 if (c_code == -1)
446 return MSG_NOT_HANDLED;
447
448 if (in->charpoint >= MB_LEN_MAX)
449 return MSG_HANDLED;
450
451 in->charbuf[in->charpoint] = c_code;
452 in->charpoint++;
453
454 res = str_is_valid_char (in->charbuf, in->charpoint);
455 if (res < 0)
456 {
457 if (res != -2)
458 in->charpoint = 0;
459 return MSG_HANDLED;
460 }
461
462 in->need_push = TRUE;
463 ins_point = str_offset_to_pos (in->buffer->str, in->point);
464 g_string_insert_len (in->buffer, ins_point, in->charbuf, in->charpoint);
465 in->point++;
466 in->charpoint = 0;
467
468 return MSG_HANDLED;
469 }
470
471
472
473 static void
474 delete_char (WInput *in)
475 {
476 const char *act;
477 int end;
478
479 act = in->buffer->str + str_offset_to_pos (in->buffer->str, in->point);
480 end = in->point + str_cnext_noncomb_char (&act);
481 move_buffer_backward (in, in->point, end);
482 in->charpoint = 0;
483 in->need_push = TRUE;
484 }
485
486
487
488 static void
489 kill_word (WInput *in)
490 {
491 int old_point = in->point;
492 int new_point;
493
494 forward_word (in);
495 new_point = in->point;
496 in->point = old_point;
497
498 delete_region (in, old_point, new_point);
499 in->need_push = TRUE;
500 in->charpoint = 0;
501 }
502
503
504
505 static void
506 back_kill_word (WInput *in)
507 {
508 int old_point = in->point;
509 int new_point;
510
511 backward_word (in);
512 new_point = in->point;
513 in->point = old_point;
514
515 delete_region (in, old_point, new_point);
516 in->need_push = TRUE;
517 }
518
519
520
521 static void
522 yank (WInput *in)
523 {
524 if (kill_buffer != NULL)
525 {
526 char *p;
527
528 in->charpoint = 0;
529 for (p = kill_buffer; *p != '\0'; p++)
530 insert_char (in, *p);
531 in->charpoint = 0;
532 }
533 }
534
535
536
537 static void
538 kill_line (WInput *in)
539 {
540 int chp;
541
542 chp = str_offset_to_pos (in->buffer->str, in->point);
543 g_free (kill_buffer);
544 kill_buffer = g_strndup (in->buffer->str + chp, in->buffer->len - chp);
545 g_string_set_size (in->buffer, chp);
546 in->charpoint = 0;
547 }
548
549
550
551 static void
552 clear_line (WInput *in)
553 {
554 in->need_push = TRUE;
555 g_string_set_size (in->buffer, 0);
556 in->point = 0;
557 in->mark = -1;
558 in->charpoint = 0;
559 }
560
561
562
563 static void
564 ins_from_clip (WInput *in)
565 {
566 char *p = NULL;
567 ev_clipboard_text_from_file_t event_data = { NULL, FALSE };
568
569
570 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_file_from_ext_clip", NULL);
571
572 event_data.text = &p;
573 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_text_from_file", &event_data);
574 if (event_data.ret)
575 {
576 char *pp;
577
578 for (pp = p; *pp != '\0'; pp++)
579 insert_char (in, *pp);
580
581 g_free (p);
582 }
583 }
584
585
586
587 static void
588 hist_prev (WInput *in)
589 {
590 GList *prev;
591
592 if (in->history.list == NULL)
593 return;
594
595 if (in->need_push)
596 input_push_history (in);
597
598 prev = g_list_previous (in->history.current);
599 if (prev != NULL)
600 {
601 input_assign_text (in, (char *) prev->data);
602 in->history.current = prev;
603 in->history.changed = TRUE;
604 in->need_push = FALSE;
605 }
606 }
607
608
609
610 static void
611 hist_next (WInput *in)
612 {
613 GList *next;
614
615 if (in->need_push)
616 {
617 input_push_history (in);
618 input_assign_text (in, "");
619 return;
620 }
621
622 if (in->history.list == NULL)
623 return;
624
625 next = g_list_next (in->history.current);
626 if (next == NULL)
627 {
628 input_assign_text (in, "");
629 in->history.current = in->history.list;
630 }
631 else
632 {
633 input_assign_text (in, (char *) next->data);
634 in->history.current = next;
635 in->history.changed = TRUE;
636 in->need_push = FALSE;
637 }
638 }
639
640
641
642 static void
643 port_region_marked_for_delete (WInput *in)
644 {
645 g_string_set_size (in->buffer, 0);
646 in->point = 0;
647 in->first = FALSE;
648 in->charpoint = 0;
649 }
650
651
652
653 static cb_ret_t
654 input_execute_cmd (WInput *in, long command)
655 {
656 cb_ret_t res = MSG_HANDLED;
657
658 switch (command)
659 {
660 case CK_MarkLeft:
661 case CK_MarkRight:
662 case CK_MarkToWordBegin:
663 case CK_MarkToWordEnd:
664 case CK_MarkToHome:
665 case CK_MarkToEnd:
666
667 if (in->mark < 0)
668 {
669 input_mark_cmd (in, FALSE);
670 input_mark_cmd (in, TRUE);
671 }
672 break;
673 case CK_WordRight:
674 case CK_WordLeft:
675 case CK_Right:
676 case CK_Left:
677 if (in->mark >= 0)
678 input_mark_cmd (in, FALSE);
679 break;
680 default:
681 break;
682 }
683
684 switch (command)
685 {
686 case CK_Home:
687 case CK_MarkToHome:
688 beginning_of_line (in);
689 break;
690 case CK_End:
691 case CK_MarkToEnd:
692 end_of_line (in);
693 break;
694 case CK_Left:
695 case CK_MarkLeft:
696 backward_char (in);
697 break;
698 case CK_WordLeft:
699 case CK_MarkToWordBegin:
700 backward_word (in);
701 break;
702 case CK_Right:
703 case CK_MarkRight:
704 forward_char (in);
705 break;
706 case CK_WordRight:
707 case CK_MarkToWordEnd:
708 forward_word (in);
709 break;
710 case CK_BackSpace:
711 {
712 long m1, m2;
713
714 if (input_eval_marks (in, &m1, &m2))
715 delete_region (in, m1, m2);
716 else
717 backward_delete (in);
718 }
719 break;
720 case CK_Delete:
721 if (in->first)
722 port_region_marked_for_delete (in);
723 else
724 {
725 long m1, m2;
726
727 if (input_eval_marks (in, &m1, &m2))
728 delete_region (in, m1, m2);
729 else
730 delete_char (in);
731 }
732 break;
733 case CK_DeleteToWordEnd:
734 kill_word (in);
735 break;
736 case CK_DeleteToWordBegin:
737 back_kill_word (in);
738 break;
739 case CK_Mark:
740 input_mark_cmd (in, TRUE);
741 break;
742 case CK_Remove:
743 delete_region (in, in->point, MAX (in->mark, 0));
744 break;
745 case CK_DeleteToEnd:
746 kill_line (in);
747 break;
748 case CK_Clear:
749 clear_line (in);
750 break;
751 case CK_Store:
752 copy_region (in, MAX (in->mark, 0), in->point);
753 break;
754 case CK_Cut:
755 {
756 long m;
757
758 m = MAX (in->mark, 0);
759 copy_region (in, m, in->point);
760 delete_region (in, in->point, m);
761 }
762 break;
763 case CK_Yank:
764 yank (in);
765 break;
766 case CK_Paste:
767 ins_from_clip (in);
768 break;
769 case CK_HistoryPrev:
770 hist_prev (in);
771 break;
772 case CK_HistoryNext:
773 hist_next (in);
774 break;
775 case CK_History:
776 do_show_hist (in);
777 break;
778 case CK_Complete:
779 input_complete (in);
780 break;
781 default:
782 res = MSG_NOT_HANDLED;
783 }
784
785 switch (command)
786 {
787 case CK_MarkLeft:
788 case CK_MarkRight:
789 case CK_MarkToWordBegin:
790 case CK_MarkToWordEnd:
791 case CK_MarkToHome:
792 case CK_MarkToEnd:
793
794 break;
795 default:
796 in->mark = -1;
797 break;
798 }
799
800 return res;
801 }
802
803
804
805
806 static gboolean
807 input_load_history (const gchar *event_group_name, const gchar *event_name, gpointer init_data,
808 gpointer data)
809 {
810 WInput *in = INPUT (init_data);
811 ev_history_load_save_t *ev = (ev_history_load_save_t *) data;
812
813 (void) event_group_name;
814 (void) event_name;
815
816 in->history.list = mc_config_history_load (ev->cfg, in->history.name);
817 in->history.current = in->history.list;
818
819 if (in->init_from_history)
820 {
821 const char *def_text = "";
822
823 if (in->history.list != NULL && in->history.list->data != NULL)
824 def_text = (const char *) in->history.list->data;
825
826 input_assign_text (in, def_text);
827 }
828
829 return TRUE;
830 }
831
832
833
834
835 static gboolean
836 input_save_history (const gchar *event_group_name, const gchar *event_name, gpointer init_data,
837 gpointer data)
838 {
839 WInput *in = INPUT (init_data);
840
841 (void) event_group_name;
842 (void) event_name;
843
844 if (!in->is_password && (DIALOG (WIDGET (in)->owner)->ret_value != B_CANCEL))
845 input_push_history (in);
846
847
848 if (in->history.changed)
849 {
850 const ev_history_load_save_t *ev = (ev_history_load_save_t *) data;
851
852 mc_config_history_save (ev->cfg, in->history.name, in->history.list);
853 }
854
855 in->history.changed = FALSE;
856
857 return TRUE;
858 }
859
860
861
862 static void
863 input_destroy (WInput *in)
864 {
865 input_complete_free (in);
866
867
868 if (in->history.list != NULL)
869 {
870
871 in->history.list = g_list_first (in->history.list);
872 g_list_free_full (in->history.list, g_free);
873 }
874 g_free (in->history.name);
875 g_string_free (in->buffer, TRUE);
876 MC_PTR_FREE (kill_buffer);
877 }
878
879
880
881
882
883
884 static int
885 input_screen_to_point (const WInput *in, int x)
886 {
887 x += in->term_first_shown;
888
889 if (x < 0)
890 return 0;
891
892 if (x < str_term_width1 (in->buffer->str))
893 return str_column_to_pos (in->buffer->str, x);
894
895 return str_length (in->buffer->str);
896 }
897
898
899
900 static void
901 input_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
902 {
903
904 static int prev_point = 0;
905 WInput *in = INPUT (w);
906
907 switch (msg)
908 {
909 case MSG_MOUSE_DOWN:
910 widget_select (w);
911
912 if (event->x >= w->rect.cols - HISTORY_BUTTON_WIDTH && should_show_history_button (in))
913 do_show_hist (in);
914 else
915 {
916 in->first = FALSE;
917 input_mark_cmd (in, FALSE);
918 input_set_point (in, input_screen_to_point (in, event->x));
919
920 prev_point = in->point;
921 }
922 break;
923
924 case MSG_MOUSE_DRAG:
925
926 if (in->mark < 0)
927 in->mark = prev_point;
928
929 input_set_point (in, input_screen_to_point (in, event->x));
930 break;
931
932 default:
933
934 if (in->mark == in->point)
935 input_mark_cmd (in, FALSE);
936 break;
937 }
938 }
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954 WInput *
955 input_new (int y, int x, const int *colors, int width, const char *def_text, const char *histname,
956 input_complete_t completion_flags)
957 {
958 WRect r = { y, x, 1, width };
959 WInput *in;
960 Widget *w;
961
962 in = g_new (WInput, 1);
963 w = WIDGET (in);
964 widget_init (w, &r, input_callback, input_mouse_callback);
965 w->options |= WOP_SELECTABLE | WOP_IS_INPUT | WOP_WANT_CURSOR;
966 w->keymap = input_map;
967
968 in->color = colors;
969 in->first = TRUE;
970 in->mark = -1;
971 in->term_first_shown = 0;
972 in->disable_update = 0;
973 in->is_password = FALSE;
974 in->strip_password = FALSE;
975
976
977 in->buffer = g_string_sized_new (width);
978
979
980 in->completions = NULL;
981 in->completion_flags = completion_flags;
982
983 in->init_from_history = (def_text == INPUT_LAST_TEXT);
984
985 if (in->init_from_history || def_text == NULL)
986 def_text = "";
987
988 input_assign_text (in, def_text);
989
990
991 in->history.list = NULL;
992 in->history.current = NULL;
993 in->history.changed = FALSE;
994 in->history.name = NULL;
995 if ((histname != NULL) && (*histname != '\0'))
996 in->history.name = g_strdup (histname);
997
998
999 in->label = NULL;
1000
1001 return in;
1002 }
1003
1004
1005
1006 cb_ret_t
1007 input_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
1008 {
1009 WInput *in = INPUT (w);
1010 WDialog *h = DIALOG (w->owner);
1011 cb_ret_t v;
1012
1013 switch (msg)
1014 {
1015 case MSG_INIT:
1016
1017 mc_event_add (h->event_group, MCEVENT_HISTORY_LOAD, input_load_history, w, NULL);
1018
1019 mc_event_add (h->event_group, MCEVENT_HISTORY_SAVE, input_save_history, w, NULL);
1020 if (in->label != NULL)
1021 widget_set_state (WIDGET (in->label), WST_DISABLED, widget_get_state (w, WST_DISABLED));
1022 return MSG_HANDLED;
1023
1024 case MSG_KEY:
1025 if (parm == XCTRL ('q'))
1026 {
1027 quote = TRUE;
1028 v = input_handle_char (in, ascii_alpha_to_cntrl (tty_getch ()));
1029 quote = FALSE;
1030 return v;
1031 }
1032
1033
1034 if (parm == KEY_UP || parm == KEY_DOWN || parm == ESC_CHAR || parm == KEY_F (10)
1035 || parm == '\n')
1036 return MSG_NOT_HANDLED;
1037
1038
1039 if ((parm & ~KEY_M_MASK) == '\n')
1040 {
1041 quote = TRUE;
1042 v = input_handle_char (in, '\n');
1043 quote = FALSE;
1044 return v;
1045 }
1046
1047 return input_handle_char (in, parm);
1048
1049 case MSG_ACTION:
1050 return input_execute_cmd (in, parm);
1051
1052 case MSG_DRAW:
1053 input_update (in, FALSE);
1054 return MSG_HANDLED;
1055
1056 case MSG_ENABLE:
1057 case MSG_DISABLE:
1058 if (in->label != NULL)
1059 widget_set_state (WIDGET (in->label), WST_DISABLED, msg == MSG_DISABLE);
1060 return MSG_HANDLED;
1061
1062 case MSG_CURSOR:
1063 widget_gotoyx (in, 0, str_term_width2 (in->buffer->str, in->point) - in->term_first_shown);
1064 return MSG_HANDLED;
1065
1066 case MSG_DESTROY:
1067
1068 mc_event_del (h->event_group, MCEVENT_HISTORY_LOAD, input_load_history, w);
1069
1070 mc_event_del (h->event_group, MCEVENT_HISTORY_SAVE, input_save_history, w);
1071 input_destroy (in);
1072 return MSG_HANDLED;
1073
1074 default:
1075 return widget_default_callback (w, sender, msg, parm, data);
1076 }
1077 }
1078
1079
1080
1081 void
1082 input_set_default_colors (void)
1083 {
1084 input_colors[WINPUTC_MAIN] = INPUT_COLOR;
1085 input_colors[WINPUTC_MARK] = INPUT_MARK_COLOR;
1086 input_colors[WINPUTC_UNCHANGED] = INPUT_UNCHANGED_COLOR;
1087 input_colors[WINPUTC_HISTORY] = INPUT_HISTORY_COLOR;
1088 }
1089
1090
1091
1092 cb_ret_t
1093 input_handle_char (WInput *in, int key)
1094 {
1095 cb_ret_t v;
1096 long command;
1097
1098 if (quote)
1099 {
1100 input_complete_free (in);
1101 v = insert_char (in, key);
1102 input_update (in, TRUE);
1103 quote = FALSE;
1104 return v;
1105 }
1106
1107 command = widget_lookup_key (WIDGET (in), key);
1108 if (command == CK_IgnoreKey)
1109 {
1110 if (key > 255)
1111 return MSG_NOT_HANDLED;
1112 if (in->first)
1113 port_region_marked_for_delete (in);
1114 input_complete_free (in);
1115 v = insert_char (in, key);
1116 input_update (in, TRUE);
1117 }
1118 else
1119 {
1120 gboolean keep_first;
1121
1122 if (command != CK_Complete)
1123 input_complete_free (in);
1124 input_execute_cmd (in, command);
1125 v = MSG_HANDLED;
1126
1127
1128 keep_first = in->first && (command == CK_History || command == CK_Complete);
1129 input_update (in, !keep_first);
1130 }
1131
1132 return v;
1133 }
1134
1135
1136
1137 void
1138 input_assign_text (WInput *in, const char *text)
1139 {
1140 if (text == NULL)
1141 text = "";
1142
1143 input_complete_free (in);
1144 in->mark = -1;
1145 in->need_push = TRUE;
1146 in->charpoint = 0;
1147 g_string_assign (in->buffer, text);
1148 in->point = str_length (in->buffer->str);
1149 input_update (in, TRUE);
1150 }
1151
1152
1153
1154
1155 void
1156 input_insert (WInput *in, const char *text, gboolean insert_extra_space)
1157 {
1158 input_disable_update (in);
1159 while (*text != '\0')
1160 input_handle_char (in, (unsigned char) *text++);
1161 if (insert_extra_space)
1162 input_handle_char (in, ' ');
1163 input_enable_update (in);
1164 input_update (in, TRUE);
1165 }
1166
1167
1168
1169 void
1170 input_set_point (WInput *in, int pos)
1171 {
1172 int max_pos;
1173
1174 max_pos = str_length (in->buffer->str);
1175 pos = MIN (pos, max_pos);
1176 if (pos != in->point)
1177 input_complete_free (in);
1178 in->point = pos;
1179 in->charpoint = 0;
1180 input_update (in, TRUE);
1181 }
1182
1183
1184
1185 void
1186 input_update (WInput *in, gboolean clear_first)
1187 {
1188 Widget *wi = WIDGET (in);
1189 const WRect *w = &wi->rect;
1190 int has_history = 0;
1191 int buf_len;
1192 const char *cp;
1193 int pw;
1194
1195 if (in->disable_update != 0)
1196 return;
1197
1198
1199 if (wi->owner == NULL || !widget_get_state (WIDGET (wi->owner), WST_ACTIVE))
1200 return;
1201
1202 if (clear_first)
1203 in->first = FALSE;
1204
1205 if (should_show_history_button (in))
1206 has_history = HISTORY_BUTTON_WIDTH;
1207
1208 buf_len = str_length (in->buffer->str);
1209
1210
1211 in->mark = MIN (in->mark, buf_len);
1212
1213 pw = str_term_width2 (in->buffer->str, in->point);
1214
1215
1216 if ((pw < in->term_first_shown) || (pw >= in->term_first_shown + w->cols - has_history))
1217 {
1218 in->term_first_shown = pw - (w->cols / 3);
1219 if (in->term_first_shown < 0)
1220 in->term_first_shown = 0;
1221 }
1222
1223 if (has_history != 0)
1224 draw_history_button (in);
1225
1226 if (widget_get_state (wi, WST_DISABLED))
1227 tty_setcolor (DISABLED_COLOR);
1228 else if (in->first)
1229 tty_setcolor (in->color[WINPUTC_UNCHANGED]);
1230 else
1231 tty_setcolor (in->color[WINPUTC_MAIN]);
1232
1233 widget_gotoyx (in, 0, 0);
1234
1235 if (!in->is_password)
1236 {
1237 if (in->mark < 0)
1238 tty_print_string (
1239 str_term_substring (in->buffer->str, in->term_first_shown, w->cols - has_history));
1240 else
1241 {
1242 long m1, m2;
1243
1244 if (input_eval_marks (in, &m1, &m2))
1245 {
1246 tty_setcolor (in->color[WINPUTC_MAIN]);
1247 cp = str_term_substring (in->buffer->str, in->term_first_shown,
1248 w->cols - has_history);
1249 tty_print_string (cp);
1250 tty_setcolor (in->color[WINPUTC_MARK]);
1251 if (m1 < in->term_first_shown)
1252 {
1253 widget_gotoyx (in, 0, 0);
1254 m1 = in->term_first_shown;
1255 m2 -= m1;
1256 }
1257 else
1258 {
1259 int buf_width;
1260
1261 widget_gotoyx (in, 0, m1 - in->term_first_shown);
1262 buf_width = str_term_width2 (in->buffer->str, m1);
1263 m2 =
1264 MIN (m2 - m1, (w->cols - has_history) - (buf_width - in->term_first_shown));
1265 }
1266
1267 tty_print_string (str_term_substring (in->buffer->str, m1, m2));
1268 }
1269 }
1270 }
1271 else
1272 {
1273 int i;
1274
1275 cp = str_term_substring (in->buffer->str, in->term_first_shown, w->cols - has_history);
1276 tty_setcolor (in->color[WINPUTC_MAIN]);
1277 for (i = 0; i < w->cols - has_history; i++)
1278 {
1279 if (i < (buf_len - in->term_first_shown) && cp[0] != '\0')
1280 tty_print_char ('*');
1281 else
1282 tty_print_char (' ');
1283 if (cp[0] != '\0')
1284 str_cnext_char (&cp);
1285 }
1286 }
1287 }
1288
1289
1290
1291 void
1292 input_enable_update (WInput *in)
1293 {
1294 in->disable_update--;
1295 input_update (in, FALSE);
1296 }
1297
1298
1299
1300 void
1301 input_disable_update (WInput *in)
1302 {
1303 in->disable_update++;
1304 }
1305
1306
1307
1308
1309
1310
1311
1312
1313 void
1314 input_clean (WInput *in)
1315 {
1316 input_push_history (in);
1317 in->need_push = TRUE;
1318 g_string_set_size (in->buffer, 0);
1319 in->point = 0;
1320 in->charpoint = 0;
1321 in->mark = -1;
1322 input_complete_free (in);
1323 input_update (in, FALSE);
1324 }
1325
1326