58 |
int y; |
int y; |
59 |
/* The kill buffer. */ |
/* The kill buffer. */ |
60 |
char *killed_text; |
char *killed_text; |
61 |
|
/* The flag of a completion window. */ |
62 |
|
int completion_shown; |
63 |
}; |
}; |
64 |
|
|
65 |
|
/* Used for storing completion items temporarily. */ |
66 |
|
static struct line completion_buffer; |
67 |
|
|
68 |
/* Initialize a line. */ |
/* Initialize a line. */ |
69 |
static int |
static int |
70 |
init_line (struct line *linep) |
init_line (struct line *linep) |
427 |
screen->x = 0; |
screen->x = 0; |
428 |
screen->y = 0; |
screen->y = 0; |
429 |
screen->killed_text = 0; |
screen->killed_text = 0; |
430 |
|
screen->completion_shown = 0; |
431 |
screen->lines = grub_malloc (sizeof (struct line)); |
screen->lines = grub_malloc (sizeof (struct line)); |
432 |
if (! screen->lines) |
if (! screen->lines) |
433 |
goto fail; |
goto fail; |
815 |
return 1; |
return 1; |
816 |
} |
} |
817 |
|
|
818 |
|
/* A completion hook to print items. */ |
819 |
|
static void |
820 |
|
store_completion (const char *item, grub_completion_type_t type, int count) |
821 |
|
{ |
822 |
|
char *p; |
823 |
|
|
824 |
|
if (count == 0) |
825 |
|
{ |
826 |
|
/* If this is the first time, print a label. */ |
827 |
|
const char *what; |
828 |
|
|
829 |
|
switch (type) |
830 |
|
{ |
831 |
|
case GRUB_COMPLETION_TYPE_COMMAND: |
832 |
|
what = "commands"; |
833 |
|
break; |
834 |
|
case GRUB_COMPLETION_TYPE_DEVICE: |
835 |
|
what = "devices"; |
836 |
|
break; |
837 |
|
case GRUB_COMPLETION_TYPE_FILE: |
838 |
|
what = "files"; |
839 |
|
break; |
840 |
|
case GRUB_COMPLETION_TYPE_PARTITION: |
841 |
|
what = "partitions"; |
842 |
|
break; |
843 |
|
default: |
844 |
|
what = "things"; |
845 |
|
break; |
846 |
|
} |
847 |
|
|
848 |
|
grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); |
849 |
|
grub_printf (" Possible %s are:\n ", what); |
850 |
|
} |
851 |
|
|
852 |
|
/* Make sure that the completion buffer has enough room. */ |
853 |
|
if (completion_buffer.max_len < (completion_buffer.len |
854 |
|
+ (int) grub_strlen (item) + 1 + 1)) |
855 |
|
{ |
856 |
|
grub_size_t new_len; |
857 |
|
|
858 |
|
new_len = completion_buffer.len + grub_strlen (item) + 80; |
859 |
|
p = grub_realloc (completion_buffer.buf, new_len); |
860 |
|
if (! p) |
861 |
|
{ |
862 |
|
/* Possibly not fatal. */ |
863 |
|
grub_errno = GRUB_ERR_NONE; |
864 |
|
return; |
865 |
|
} |
866 |
|
p[completion_buffer.len] = 0; |
867 |
|
completion_buffer.buf = p; |
868 |
|
completion_buffer.max_len = new_len; |
869 |
|
} |
870 |
|
|
871 |
|
p = completion_buffer.buf + completion_buffer.len; |
872 |
|
if (completion_buffer.len != 0) |
873 |
|
{ |
874 |
|
*p++ = ' '; |
875 |
|
completion_buffer.len++; |
876 |
|
} |
877 |
|
grub_strcpy (p, item); |
878 |
|
completion_buffer.len += grub_strlen (item); |
879 |
|
} |
880 |
|
|
881 |
|
static int |
882 |
|
complete (struct screen *screen, int continuous, int update) |
883 |
|
{ |
884 |
|
grub_uint16_t pos; |
885 |
|
char saved_char; |
886 |
|
struct line *linep; |
887 |
|
int restore; |
888 |
|
char *insert; |
889 |
|
static int count = -1; |
890 |
|
|
891 |
|
if (continuous) |
892 |
|
count++; |
893 |
|
else |
894 |
|
count = 0; |
895 |
|
|
896 |
|
pos = grub_getxy (); |
897 |
|
grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); |
898 |
|
|
899 |
|
completion_buffer.buf = 0; |
900 |
|
completion_buffer.len = 0; |
901 |
|
completion_buffer.max_len = 0; |
902 |
|
|
903 |
|
linep = screen->lines + screen->line; |
904 |
|
saved_char = linep->buf[screen->column]; |
905 |
|
linep->buf[screen->column] = '\0'; |
906 |
|
|
907 |
|
insert = grub_normal_do_completion (linep->buf, &restore, store_completion); |
908 |
|
|
909 |
|
linep->buf[screen->column] = saved_char; |
910 |
|
|
911 |
|
if (restore) |
912 |
|
{ |
913 |
|
char *p = completion_buffer.buf; |
914 |
|
|
915 |
|
screen->completion_shown = 1; |
916 |
|
|
917 |
|
if (p) |
918 |
|
{ |
919 |
|
int num_sections = ((completion_buffer.len + GRUB_TERM_WIDTH - 8 - 1) |
920 |
|
/ (GRUB_TERM_WIDTH - 8)); |
921 |
|
char *endp; |
922 |
|
|
923 |
|
p += (count % num_sections) * (GRUB_TERM_WIDTH - 8); |
924 |
|
endp = p + (GRUB_TERM_WIDTH - 8); |
925 |
|
|
926 |
|
if (p != completion_buffer.buf) |
927 |
|
grub_putcode (GRUB_TERM_DISP_LEFT); |
928 |
|
else |
929 |
|
grub_putchar (' '); |
930 |
|
|
931 |
|
while (*p && p < endp) |
932 |
|
grub_putchar (*p++); |
933 |
|
|
934 |
|
if (*p) |
935 |
|
grub_putcode (GRUB_TERM_DISP_RIGHT); |
936 |
|
} |
937 |
|
} |
938 |
|
|
939 |
|
grub_gotoxy (pos >> 8, pos & 0xFF); |
940 |
|
|
941 |
|
if (insert) |
942 |
|
{ |
943 |
|
insert_string (screen, insert, update); |
944 |
|
count = -1; |
945 |
|
grub_free (insert); |
946 |
|
} |
947 |
|
else if (update) |
948 |
|
grub_refresh (); |
949 |
|
|
950 |
|
grub_free (completion_buffer.buf); |
951 |
|
return 1; |
952 |
|
} |
953 |
|
|
954 |
|
/* Clear displayed completions. */ |
955 |
|
static void |
956 |
|
clear_completions (void) |
957 |
|
{ |
958 |
|
grub_uint16_t pos; |
959 |
|
int i, j; |
960 |
|
|
961 |
|
pos = grub_getxy (); |
962 |
|
grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); |
963 |
|
|
964 |
|
for (i = 0; i < 2; i++) |
965 |
|
{ |
966 |
|
for (j = 0; j < GRUB_TERM_WIDTH - 1; j++) |
967 |
|
grub_putchar (' '); |
968 |
|
grub_putchar ('\n'); |
969 |
|
} |
970 |
|
|
971 |
|
grub_gotoxy (pos >> 8, pos & 0xFF); |
972 |
|
grub_refresh (); |
973 |
|
} |
974 |
|
|
975 |
/* Execute the command list in the screen SCREEN. */ |
/* Execute the command list in the screen SCREEN. */ |
976 |
static int |
static int |
977 |
run (struct screen *screen) |
run (struct screen *screen) |
1043 |
while (1) |
while (1) |
1044 |
{ |
{ |
1045 |
int c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); |
int c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); |
1046 |
|
|
1047 |
|
if (screen->completion_shown) |
1048 |
|
{ |
1049 |
|
clear_completions (); |
1050 |
|
screen->completion_shown = 0; |
1051 |
|
} |
1052 |
|
|
1053 |
switch (c) |
switch (c) |
1054 |
{ |
{ |
1083 |
break; |
break; |
1084 |
|
|
1085 |
case '\t': /* C-i */ |
case '\t': /* C-i */ |
1086 |
/* FIXME: Completion */ |
if (! complete (screen, prev_c == c, 1)) |
1087 |
|
goto fail; |
1088 |
break; |
break; |
1089 |
|
|
1090 |
case 4: /* C-d */ |
case 4: /* C-d */ |