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