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,
808 gpointer init_data, 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,
837 gpointer init_data, 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 {
846 ev_history_load_save_t *ev = (ev_history_load_save_t *) data;
847
848 input_push_history (in);
849 if (in->history.changed)
850 mc_config_history_save (ev->cfg, in->history.name, in->history.list);
851 in->history.changed = FALSE;
852 }
853
854 return TRUE;
855 }
856
857
858
859 static void
860 input_destroy (WInput *in)
861 {
862 input_complete_free (in);
863
864
865 if (in->history.list != NULL)
866 {
867
868 in->history.list = g_list_first (in->history.list);
869 g_list_free_full (in->history.list, g_free);
870 }
871 g_free (in->history.name);
872 g_string_free (in->buffer, TRUE);
873 MC_PTR_FREE (kill_buffer);
874 }
875
876
877
878
879
880
881 static int
882 input_screen_to_point (const WInput *in, int x)
883 {
884 x += in->term_first_shown;
885
886 if (x < 0)
887 return 0;
888
889 if (x < str_term_width1 (in->buffer->str))
890 return str_column_to_pos (in->buffer->str, x);
891
892 return str_length (in->buffer->str);
893 }
894
895
896
897 static void
898 input_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
899 {
900
901 static int prev_point = 0;
902 WInput *in = INPUT (w);
903
904 switch (msg)
905 {
906 case MSG_MOUSE_DOWN:
907 widget_select (w);
908
909 if (event->x >= w->rect.cols - HISTORY_BUTTON_WIDTH && should_show_history_button (in))
910 do_show_hist (in);
911 else
912 {
913 in->first = FALSE;
914 input_mark_cmd (in, FALSE);
915 input_set_point (in, input_screen_to_point (in, event->x));
916
917 prev_point = in->point;
918 }
919 break;
920
921 case MSG_MOUSE_DRAG:
922
923 if (in->mark < 0)
924 in->mark = prev_point;
925
926 input_set_point (in, input_screen_to_point (in, event->x));
927 break;
928
929 default:
930
931 if (in->mark == in->point)
932 input_mark_cmd (in, FALSE);
933 break;
934 }
935 }
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951 WInput *
952 input_new (int y, int x, const int *colors, int width, const char *def_text,
953 const char *histname, input_complete_t completion_flags)
954 {
955 WRect r = { y, x, 1, width };
956 WInput *in;
957 Widget *w;
958
959 in = g_new (WInput, 1);
960 w = WIDGET (in);
961 widget_init (w, &r, input_callback, input_mouse_callback);
962 w->options |= WOP_SELECTABLE | WOP_IS_INPUT | WOP_WANT_CURSOR;
963 w->keymap = input_map;
964
965 in->color = colors;
966 in->first = TRUE;
967 in->mark = -1;
968 in->term_first_shown = 0;
969 in->disable_update = 0;
970 in->is_password = FALSE;
971 in->strip_password = FALSE;
972
973
974 in->buffer = g_string_sized_new (width);
975
976
977 in->completions = NULL;
978 in->completion_flags = completion_flags;
979
980 in->init_from_history = (def_text == INPUT_LAST_TEXT);
981
982 if (in->init_from_history || def_text == NULL)
983 def_text = "";
984
985 input_assign_text (in, def_text);
986
987
988 in->history.list = NULL;
989 in->history.current = NULL;
990 in->history.changed = FALSE;
991 in->history.name = NULL;
992 if ((histname != NULL) && (*histname != '\0'))
993 in->history.name = g_strdup (histname);
994
995
996 in->label = NULL;
997
998 return in;
999 }
1000
1001
1002
1003 cb_ret_t
1004 input_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
1005 {
1006 WInput *in = INPUT (w);
1007 WDialog *h = DIALOG (w->owner);
1008 cb_ret_t v;
1009
1010 switch (msg)
1011 {
1012 case MSG_INIT:
1013
1014 mc_event_add (h->event_group, MCEVENT_HISTORY_LOAD, input_load_history, w, NULL);
1015
1016 mc_event_add (h->event_group, MCEVENT_HISTORY_SAVE, input_save_history, w, NULL);
1017 if (in->label != NULL)
1018 widget_set_state (WIDGET (in->label), WST_DISABLED, widget_get_state (w, WST_DISABLED));
1019 return MSG_HANDLED;
1020
1021 case MSG_KEY:
1022 if (parm == XCTRL ('q'))
1023 {
1024 quote = TRUE;
1025 v = input_handle_char (in, ascii_alpha_to_cntrl (tty_getch ()));
1026 quote = FALSE;
1027 return v;
1028 }
1029
1030
1031 if (parm == KEY_UP || parm == KEY_DOWN || parm == ESC_CHAR
1032 || parm == KEY_F (10) || parm == '\n')
1033 return MSG_NOT_HANDLED;
1034
1035
1036 if ((parm & ~KEY_M_MASK) == '\n')
1037 {
1038 quote = TRUE;
1039 v = input_handle_char (in, '\n');
1040 quote = FALSE;
1041 return v;
1042 }
1043
1044 return input_handle_char (in, parm);
1045
1046 case MSG_ACTION:
1047 return input_execute_cmd (in, parm);
1048
1049 case MSG_DRAW:
1050 input_update (in, FALSE);
1051 return MSG_HANDLED;
1052
1053 case MSG_ENABLE:
1054 case MSG_DISABLE:
1055 if (in->label != NULL)
1056 widget_set_state (WIDGET (in->label), WST_DISABLED, msg == MSG_DISABLE);
1057 return MSG_HANDLED;
1058
1059 case MSG_CURSOR:
1060 widget_gotoyx (in, 0, str_term_width2 (in->buffer->str, in->point) - in->term_first_shown);
1061 return MSG_HANDLED;
1062
1063 case MSG_DESTROY:
1064
1065 mc_event_del (h->event_group, MCEVENT_HISTORY_LOAD, input_load_history, w);
1066
1067 mc_event_del (h->event_group, MCEVENT_HISTORY_SAVE, input_save_history, w);
1068 input_destroy (in);
1069 return MSG_HANDLED;
1070
1071 default:
1072 return widget_default_callback (w, sender, msg, parm, data);
1073 }
1074 }
1075
1076
1077
1078 void
1079 input_set_default_colors (void)
1080 {
1081 input_colors[WINPUTC_MAIN] = INPUT_COLOR;
1082 input_colors[WINPUTC_MARK] = INPUT_MARK_COLOR;
1083 input_colors[WINPUTC_UNCHANGED] = INPUT_UNCHANGED_COLOR;
1084 input_colors[WINPUTC_HISTORY] = INPUT_HISTORY_COLOR;
1085 }
1086
1087
1088
1089 cb_ret_t
1090 input_handle_char (WInput *in, int key)
1091 {
1092 cb_ret_t v;
1093 long command;
1094
1095 if (quote)
1096 {
1097 input_complete_free (in);
1098 v = insert_char (in, key);
1099 input_update (in, TRUE);
1100 quote = FALSE;
1101 return v;
1102 }
1103
1104 command = widget_lookup_key (WIDGET (in), key);
1105 if (command == CK_IgnoreKey)
1106 {
1107 if (key > 255)
1108 return MSG_NOT_HANDLED;
1109 if (in->first)
1110 port_region_marked_for_delete (in);
1111 input_complete_free (in);
1112 v = insert_char (in, key);
1113 input_update (in, TRUE);
1114 }
1115 else
1116 {
1117 gboolean keep_first;
1118
1119 if (command != CK_Complete)
1120 input_complete_free (in);
1121 input_execute_cmd (in, command);
1122 v = MSG_HANDLED;
1123
1124
1125 keep_first = in->first && (command == CK_History || command == CK_Complete);
1126 input_update (in, !keep_first);
1127 }
1128
1129 return v;
1130 }
1131
1132
1133
1134 void
1135 input_assign_text (WInput *in, const char *text)
1136 {
1137 if (text == NULL)
1138 text = "";
1139
1140 input_complete_free (in);
1141 in->mark = -1;
1142 in->need_push = TRUE;
1143 in->charpoint = 0;
1144 g_string_assign (in->buffer, text);
1145 in->point = str_length (in->buffer->str);
1146 input_update (in, TRUE);
1147 }
1148
1149
1150
1151
1152 void
1153 input_insert (WInput *in, const char *text, gboolean insert_extra_space)
1154 {
1155 input_disable_update (in);
1156 while (*text != '\0')
1157 input_handle_char (in, (unsigned char) *text++);
1158 if (insert_extra_space)
1159 input_handle_char (in, ' ');
1160 input_enable_update (in);
1161 input_update (in, TRUE);
1162 }
1163
1164
1165
1166 void
1167 input_set_point (WInput *in, int pos)
1168 {
1169 int max_pos;
1170
1171 max_pos = str_length (in->buffer->str);
1172 pos = MIN (pos, max_pos);
1173 if (pos != in->point)
1174 input_complete_free (in);
1175 in->point = pos;
1176 in->charpoint = 0;
1177 input_update (in, TRUE);
1178 }
1179
1180
1181
1182 void
1183 input_update (WInput *in, gboolean clear_first)
1184 {
1185 Widget *wi = WIDGET (in);
1186 const WRect *w = &wi->rect;
1187 int has_history = 0;
1188 int buf_len;
1189 const char *cp;
1190 int pw;
1191
1192 if (in->disable_update != 0)
1193 return;
1194
1195
1196 if (wi->owner == NULL || !widget_get_state (WIDGET (wi->owner), WST_ACTIVE))
1197 return;
1198
1199 if (clear_first)
1200 in->first = FALSE;
1201
1202 if (should_show_history_button (in))
1203 has_history = HISTORY_BUTTON_WIDTH;
1204
1205 buf_len = str_length (in->buffer->str);
1206
1207
1208 in->mark = MIN (in->mark, buf_len);
1209
1210 pw = str_term_width2 (in->buffer->str, in->point);
1211
1212
1213 if ((pw < in->term_first_shown) || (pw >= in->term_first_shown + w->cols - has_history))
1214 {
1215 in->term_first_shown = pw - (w->cols / 3);
1216 if (in->term_first_shown < 0)
1217 in->term_first_shown = 0;
1218 }
1219
1220 if (has_history != 0)
1221 draw_history_button (in);
1222
1223 if (widget_get_state (wi, WST_DISABLED))
1224 tty_setcolor (DISABLED_COLOR);
1225 else if (in->first)
1226 tty_setcolor (in->color[WINPUTC_UNCHANGED]);
1227 else
1228 tty_setcolor (in->color[WINPUTC_MAIN]);
1229
1230 widget_gotoyx (in, 0, 0);
1231
1232 if (!in->is_password)
1233 {
1234 if (in->mark < 0)
1235 tty_print_string (str_term_substring (in->buffer->str, in->term_first_shown,
1236 w->cols - has_history));
1237 else
1238 {
1239 long m1, m2;
1240
1241 if (input_eval_marks (in, &m1, &m2))
1242 {
1243 tty_setcolor (in->color[WINPUTC_MAIN]);
1244 cp = str_term_substring (in->buffer->str, in->term_first_shown,
1245 w->cols - has_history);
1246 tty_print_string (cp);
1247 tty_setcolor (in->color[WINPUTC_MARK]);
1248 if (m1 < in->term_first_shown)
1249 {
1250 widget_gotoyx (in, 0, 0);
1251 m1 = in->term_first_shown;
1252 m2 -= m1;
1253 }
1254 else
1255 {
1256 int buf_width;
1257
1258 widget_gotoyx (in, 0, m1 - in->term_first_shown);
1259 buf_width = str_term_width2 (in->buffer->str, m1);
1260 m2 = MIN (m2 - m1,
1261 (w->cols - has_history) - (buf_width - in->term_first_shown));
1262 }
1263
1264 tty_print_string (str_term_substring (in->buffer->str, m1, m2));
1265 }
1266 }
1267 }
1268 else
1269 {
1270 int i;
1271
1272 cp = str_term_substring (in->buffer->str, in->term_first_shown, w->cols - has_history);
1273 tty_setcolor (in->color[WINPUTC_MAIN]);
1274 for (i = 0; i < w->cols - has_history; i++)
1275 {
1276 if (i < (buf_len - in->term_first_shown) && cp[0] != '\0')
1277 tty_print_char ('*');
1278 else
1279 tty_print_char (' ');
1280 if (cp[0] != '\0')
1281 str_cnext_char (&cp);
1282 }
1283 }
1284 }
1285
1286
1287
1288 void
1289 input_enable_update (WInput *in)
1290 {
1291 in->disable_update--;
1292 input_update (in, FALSE);
1293 }
1294
1295
1296
1297 void
1298 input_disable_update (WInput *in)
1299 {
1300 in->disable_update++;
1301 }
1302
1303
1304
1305
1306
1307
1308
1309
1310 void
1311 input_clean (WInput *in)
1312 {
1313 input_push_history (in);
1314 in->need_push = TRUE;
1315 g_string_set_size (in->buffer, 0);
1316 in->point = 0;
1317 in->charpoint = 0;
1318 in->mark = -1;
1319 input_complete_free (in);
1320 input_update (in, FALSE);
1321 }
1322
1323