~ubuntu-branches/debian/sid/grub2/sid-200907171837

« back to all changes in this revision

Viewing changes to normal/menu_entry.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Millan
  • Date: 2009-07-02 13:23:51 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702132351-tanpn0ryyijp93gu
Tags: 1.96+20090702-1
* New SVN snapshot.
* rules: Remove duplicated files in sparc64-ieee1275 port.
* rules: Comment out -DGRUB_ASSUME_LINUX_HAS_FB_SUPPORT=1 setting.  We'll
  re-evaluate using it when it's more mature.  (Closes: #535026).

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#include <grub/misc.h>
22
22
#include <grub/mm.h>
23
23
#include <grub/loader.h>
24
 
#include <grub/script.h>
 
24
#include <grub/command.h>
 
25
#include <grub/parser.h>
25
26
 
26
27
enum update_mode
27
28
  {
106
107
{
107
108
  int i;
108
109
  char *p;
109
 
  
 
110
 
110
111
  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + start + 1,
111
112
               y + GRUB_TERM_FIRST_ENTRY_Y);
112
113
 
129
130
print_empty_line (int y)
130
131
{
131
132
  int i;
132
 
  
 
133
 
133
134
  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1,
134
135
               y + GRUB_TERM_FIRST_ENTRY_Y);
135
136
 
143
144
{
144
145
  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
145
146
               GRUB_TERM_FIRST_ENTRY_Y);
146
 
  
 
147
 
147
148
  if (flag)
148
149
    grub_putcode (GRUB_TERM_DISP_UP);
149
150
  else
150
151
    grub_putchar (' ');
151
152
}
152
 
          
 
153
 
153
154
/* Print a down arrow.  */
154
155
static void
155
156
print_down (int flag)
156
157
{
157
158
  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
158
159
               GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
159
 
  
 
160
 
160
161
  if (flag)
161
162
    grub_putcode (GRUB_TERM_DISP_DOWN);
162
163
  else
163
164
    grub_putchar (' ');
164
165
}
165
 
          
 
166
 
166
167
/* Draw the lines of the screen SCREEN.  */
167
168
static void
168
169
update_screen (struct screen *screen, int region_start, int region_column,
173
174
  int y;
174
175
  int i;
175
176
  struct line *linep;
176
 
  
 
177
 
177
178
  /* Check if scrolling is necessary.  */
178
179
  if (screen->y < 0 || screen->y >= GRUB_TERM_NUM_ENTRIES)
179
180
    {
181
182
        screen->y = 0;
182
183
      else
183
184
        screen->y = GRUB_TERM_NUM_ENTRIES - 1;
184
 
      
 
185
 
185
186
      region_start = 0;
186
187
      region_column = 0;
187
188
      up = 1;
202
203
           linep--;
203
204
           y -= get_logical_num_lines (linep);
204
205
        }
205
 
      
 
206
 
206
207
      if (y < 0 || i > 0)
207
208
        up_flag = 1;
208
 
      
 
209
 
209
210
      do
210
211
        {
211
212
          int column;
212
 
          
 
213
 
213
214
          for (column = 0;
214
215
               column <= linep->len && y < GRUB_TERM_NUM_ENTRIES;
215
216
               column += GRUB_TERM_ENTRY_WIDTH, y++)
216
217
            {
217
218
              if (y < 0)
218
219
                continue;
219
 
              
 
220
 
220
221
              if (i == region_start)
221
222
                {
222
223
                  if (region_column >= column
228
229
              else if (i > region_start && mode == ALL_LINES)
229
230
                print_line (linep, column, 0, y);
230
231
            }
231
 
          
 
232
 
232
233
          if (y == GRUB_TERM_NUM_ENTRIES)
233
234
            {
234
235
              if (column <= linep->len || i + 1 < screen->num_lines)
235
236
                down_flag = 1;
236
237
            }
237
 
          
 
238
 
238
239
          linep++;
239
240
          i++;
240
241
 
241
242
          if (mode == ALL_LINES && i == screen->num_lines)
242
243
            for (; y < GRUB_TERM_NUM_ENTRIES; y++)
243
244
              print_empty_line (y);
244
 
                  
 
245
 
245
246
        }
246
247
      while (y < GRUB_TERM_NUM_ENTRIES);
247
 
      
 
248
 
248
249
      /* Draw up and down arrows.  */
249
250
      if (up)
250
251
        print_up (up_flag);
251
252
      if (down)
252
253
        print_down (down_flag);
253
254
    }
254
 
  
 
255
 
255
256
  /* Place the cursor.  */
256
257
  grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1 + screen->x,
257
258
               GRUB_TERM_FIRST_ENTRY_Y + screen->y);
258
 
  
 
259
 
259
260
  grub_refresh ();
260
261
}
261
262
 
277
278
          struct line *current_linep;
278
279
          struct line *next_linep;
279
280
          int size;
280
 
          
 
281
 
281
282
          /* Make a new line.  */
282
283
          screen->num_lines++;
283
284
          screen->lines = grub_realloc (screen->lines,
294
295
 
295
296
          if (! init_line (screen->lines + screen->line + 1))
296
297
            return 0;
297
 
          
 
298
 
298
299
          /* Fold the line.  */
299
300
          current_linep = screen->lines + screen->line;
300
301
          next_linep = current_linep + 1;
301
302
          size = current_linep->len - screen->column;
302
 
              
 
303
 
303
304
          if (! ensure_space (next_linep, size))
304
305
            return 0;
305
 
          
 
306
 
306
307
          grub_memmove (next_linep->buf,
307
308
                        current_linep->buf + screen->column,
308
309
                        size);
318
319
 
319
320
          mode = ALL_LINES;
320
321
          down = 1; /* XXX not optimal.  */
321
 
          
 
322
 
322
323
          /* Move the cursor.  */
323
324
          screen->column = screen->real_column = 0;
324
325
          screen->line++;
362
363
              region_start = screen->line;
363
364
              region_column = screen->column;
364
365
            }
365
 
          
 
366
 
366
367
          if (orig_num != new_num)
367
368
            {
368
369
              mode = ALL_LINES;
377
378
          screen->x += size;
378
379
          screen->y += screen->x / GRUB_TERM_ENTRY_WIDTH;
379
380
          screen->x %= GRUB_TERM_ENTRY_WIDTH;
380
 
          
 
381
 
381
382
          s = p;
382
383
        }
383
384
    }
384
385
 
385
386
  if (update)
386
387
    update_screen (screen, region_start, region_column, 0, down, mode);
387
 
  
 
388
 
388
389
  return 1;
389
390
}
390
391
 
398
399
    for (i = 0; i < screen->num_lines; i++)
399
400
      {
400
401
        struct line *linep = screen->lines + i;
401
 
        
 
402
 
402
403
        if (linep)
403
404
          grub_free (linep->buf);
404
405
      }
455
456
forward_char (struct screen *screen, int update)
456
457
{
457
458
  struct line *linep;
458
 
  
 
459
 
459
460
  linep = screen->lines + screen->line;
460
461
  if (screen->column < linep->len)
461
462
    {
498
499
  else if (screen->line > 0)
499
500
    {
500
501
      struct line *linep;
501
 
      
 
502
 
502
503
      screen->line--;
503
504
      linep = screen->lines + screen->line;
504
505
      screen->column = linep->len;
510
511
 
511
512
  if (update)
512
513
    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
513
 
  
 
514
 
514
515
  return 1;
515
516
}
516
517
 
521
522
    {
522
523
      struct line *linep;
523
524
      int dy;
524
 
      
 
525
 
525
526
      /* How many physical lines from the current position
526
527
         to the first physical line?  */
527
528
      dy = screen->column / GRUB_TERM_ENTRY_WIDTH;
528
 
      
 
529
 
529
530
      screen->line--;
530
 
      
 
531
 
531
532
      linep = screen->lines + screen->line;
532
533
      if (linep->len < screen->real_column)
533
534
        screen->column = linep->len;
534
535
      else
535
536
        screen->column = screen->real_column;
536
 
      
 
537
 
537
538
      /* How many physical lines from the current position
538
539
         to the last physical line?  */
539
540
      dy += (linep->len / GRUB_TERM_ENTRY_WIDTH
540
541
             - screen->column / GRUB_TERM_ENTRY_WIDTH);
541
 
      
 
542
 
542
543
      screen->y -= dy + 1;
543
544
      screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
544
545
    }
551
552
 
552
553
  if (update)
553
554
    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
554
 
  
 
555
 
555
556
  return 1;
556
557
}
557
558
 
562
563
    {
563
564
      struct line *linep;
564
565
      int dy;
565
 
      
 
566
 
566
567
      /* How many physical lines from the current position
567
568
         to the last physical line?  */
568
569
      linep = screen->lines + screen->line;
569
570
      dy = (linep->len / GRUB_TERM_ENTRY_WIDTH
570
571
            - screen->column / GRUB_TERM_ENTRY_WIDTH);
571
 
      
 
572
 
572
573
      screen->line++;
573
 
      
 
574
 
574
575
      linep++;
575
576
      if (linep->len < screen->real_column)
576
577
        screen->column = linep->len;
577
578
      else
578
579
        screen->column = screen->real_column;
579
 
      
 
580
 
580
581
      /* How many physical lines from the current position
581
582
         to the first physical line?  */
582
583
      dy += screen->column / GRUB_TERM_ENTRY_WIDTH;
583
 
      
 
584
 
584
585
      screen->y += dy + 1;
585
586
      screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
586
587
    }
597
598
 
598
599
  if (update)
599
600
    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
600
 
  
 
601
 
601
602
  return 1;
602
603
}
603
604
 
610
611
 
611
612
  if (update)
612
613
    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
613
 
  
 
614
 
614
615
  return 1;
615
616
}
616
617
 
618
619
end_of_line (struct screen *screen, int update)
619
620
{
620
621
  struct line *linep;
621
 
  
 
622
 
622
623
  linep = screen->lines + screen->line;
623
624
  screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH
624
625
                - screen->column / GRUB_TERM_ENTRY_WIDTH);
627
628
 
628
629
  if (update)
629
630
    update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
630
 
  
 
631
 
631
632
  return 1;
632
633
}
633
634
 
639
640
  int start = screen->num_lines;
640
641
  int column = 0;
641
642
  int down = 0;
642
 
  
 
643
 
643
644
  linep = screen->lines + screen->line;
644
645
  if (linep->len > screen->column)
645
646
    {
646
647
      int orig_num, new_num;
647
648
 
648
649
      orig_num = get_logical_num_lines (linep);
649
 
      
 
650
 
650
651
      grub_memmove (linep->buf + screen->column,
651
652
                    linep->buf + screen->column + 1,
652
653
                    linep->len - screen->column - 1);
679
680
                    (screen->num_lines - screen->line - 2)
680
681
                    * sizeof (struct line));
681
682
      screen->num_lines--;
682
 
      
 
683
 
683
684
      mode = ALL_LINES;
684
685
      start = screen->line;
685
686
      column = screen->column;
702
703
 
703
704
  saved_column = screen->column;
704
705
  saved_line = screen->line;
705
 
  
 
706
 
706
707
  if (! backward_char (screen, 0))
707
708
    return 0;
708
709
 
720
721
  char *p;
721
722
  int size;
722
723
  int offset;
723
 
  
 
724
 
724
725
  p = screen->killed_text;
725
726
  if (! continuous && p)
726
727
    p[0] = '\0';
727
 
  
 
728
 
728
729
  linep = screen->lines + screen->line;
729
730
  size = linep->len - screen->column;
730
 
  
 
731
 
731
732
  if (p)
732
733
    offset = grub_strlen (p);
733
734
  else
734
735
    offset = 0;
735
 
      
 
736
 
736
737
  if (size > 0)
737
738
    {
738
739
      enum update_mode mode = SINGLE_LINE;
739
740
      int down = 0;
740
741
      int orig_num, new_num;
741
 
      
 
742
 
742
743
      p = grub_realloc (p, offset + size + 1);
743
744
      if (! p)
744
745
        return 0;
747
748
      p[offset + size - 1] = '\0';
748
749
 
749
750
      screen->killed_text = p;
750
 
      
 
751
 
751
752
      orig_num = get_logical_num_lines (linep);
752
753
      linep->len = screen->column;
753
754
      new_num = get_logical_num_lines (linep);
771
772
      p[offset + 1] = '\0';
772
773
 
773
774
      screen->killed_text = p;
774
 
      
 
775
 
775
776
      return delete_char (screen, update);
776
777
    }
777
 
    
 
778
 
778
779
  return 1;
779
780
}
780
781
 
791
792
open_line (struct screen *screen, int update)
792
793
{
793
794
  int saved_y = screen->y;
794
 
  
 
795
 
795
796
  if (! insert_string (screen, "\n", 0))
796
797
    return 0;
797
798
 
811
812
store_completion (const char *item, grub_completion_type_t type, int count)
812
813
{
813
814
  char *p;
814
 
  
 
815
 
815
816
  if (count == 0)
816
817
    {
817
818
      /* If this is the first time, print a label.  */
838
839
          what = "things";
839
840
          break;
840
841
        }
841
 
            
 
842
 
842
843
      grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
843
844
      grub_printf ("   Possible %s are:\n    ", what);
844
845
    }
848
849
                                   + (int) grub_strlen (item) + 1 + 1))
849
850
    {
850
851
      grub_size_t new_len;
851
 
      
 
852
 
852
853
      new_len = completion_buffer.len + grub_strlen (item) + 80;
853
854
      p = grub_realloc (completion_buffer.buf, new_len);
854
855
      if (! p)
886
887
    count++;
887
888
  else
888
889
    count = 0;
889
 
  
 
890
 
890
891
  pos = grub_getxy ();
891
892
  grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
892
 
  
 
893
 
893
894
  completion_buffer.buf = 0;
894
895
  completion_buffer.len = 0;
895
896
  completion_buffer.max_len = 0;
901
902
  insert = grub_normal_do_completion (linep->buf, &restore, store_completion);
902
903
 
903
904
  linep->buf[screen->column] = saved_char;
904
 
  
 
905
 
905
906
  if (restore)
906
907
    {
907
908
      char *p = completion_buffer.buf;
908
909
 
909
910
      screen->completion_shown = 1;
910
 
      
 
911
 
911
912
      if (p)
912
913
        {
913
914
          int num_sections = ((completion_buffer.len + GRUB_TERM_WIDTH - 8 - 1)
921
922
            grub_putcode (GRUB_TERM_DISP_LEFT);
922
923
          else
923
924
            grub_putchar (' ');
924
 
          
 
925
 
925
926
          while (*p && p < endp)
926
927
            grub_putchar (*p++);
927
 
          
 
928
 
928
929
          if (*p)
929
930
            grub_putcode (GRUB_TERM_DISP_RIGHT);
930
931
        }
931
932
    }
932
933
 
933
934
  grub_gotoxy (pos >> 8, pos & 0xFF);
934
 
  
 
935
 
935
936
  if (insert)
936
937
    {
937
938
      insert_string (screen, insert, update);
940
941
    }
941
942
  else if (update)
942
943
    grub_refresh ();
943
 
    
 
944
 
944
945
  grub_free (completion_buffer.buf);
945
946
  return 1;
946
947
}
951
952
{
952
953
  grub_uint16_t pos;
953
954
  int i, j;
954
 
  
 
955
 
955
956
  pos = grub_getxy ();
956
957
  grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
957
 
  
 
958
 
958
959
  for (i = 0; i < 2; i++)
959
960
    {
960
961
      for (j = 0; j < GRUB_TERM_WIDTH - 1; j++)
961
962
        grub_putchar (' ');
962
963
      grub_putchar ('\n');
963
964
    }
964
 
  
 
965
 
965
966
  grub_gotoxy (pos >> 8, pos & 0xFF);
966
967
  grub_refresh ();
967
968
}
970
971
static int
971
972
run (struct screen *screen)
972
973
{
973
 
  struct grub_script *parsed_script = 0;
974
974
  int currline = 0;
975
975
  char *nextline;
976
976
 
977
 
  auto grub_err_t editor_getline (char **line);
978
 
  grub_err_t editor_getline (char **line)
 
977
  auto grub_err_t editor_getline (char **line, int cont);
 
978
  grub_err_t editor_getline (char **line, int cont __attribute__ ((unused)))
979
979
    {
980
980
      struct line *linep = screen->lines + currline;
981
981
      char *p;
996
996
      linep->len = p - linep->buf;
997
997
      for (p = linep->buf; grub_isspace (*p); p++)
998
998
        ;
999
 
      *line = p;
 
999
      *line = grub_strdup (p);
1000
1000
      currline++;
1001
1001
      return 0;
1002
1002
    }
1003
 
  
 
1003
 
1004
1004
  grub_cls ();
1005
1005
  grub_printf ("  Booting a command list\n\n");
1006
1006
 
1008
1008
  /* Execute the script, line for line.  */
1009
1009
  while (currline < screen->num_lines)
1010
1010
    {
1011
 
      editor_getline (&nextline);
1012
 
      parsed_script = grub_script_parse (nextline, editor_getline);
1013
 
      if (parsed_script)
1014
 
        {
1015
 
          /* Execute the command(s).  */
1016
 
          grub_script_execute (parsed_script);
1017
 
          
1018
 
          /* The parsed script was executed, throw it away.  */
1019
 
          grub_script_free (parsed_script);
1020
 
        }
1021
 
      else
 
1011
      editor_getline (&nextline, 0);
 
1012
      if (grub_parser_get_current ()->parse_line (nextline, editor_getline))
1022
1013
        break;
1023
1014
    }
1024
1015
 
1025
1016
  if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
1026
1017
    /* Implicit execution of boot, only if something is loaded.  */
1027
 
    grub_command_execute ("boot", 0);
 
1018
    grub_command_execute ("boot", 0, 0);
1028
1019
 
1029
1020
  if (grub_errno != GRUB_ERR_NONE)
1030
1021
    {
1042
1033
{
1043
1034
  struct screen *screen;
1044
1035
  int prev_c;
1045
 
  
 
1036
 
1046
1037
  screen = make_screen (entry);
1047
1038
  if (! screen)
1048
1039
    return;
1053
1044
  update_screen (screen, 0, 0, 1, 1, ALL_LINES);
1054
1045
  grub_setcursor (1);
1055
1046
  prev_c = '\0';
1056
 
  
 
1047
 
1057
1048
  while (1)
1058
1049
    {
1059
1050
      int c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
1063
1054
          clear_completions ();
1064
1055
          screen->completion_shown = 0;
1065
1056
        }
1066
 
      
 
1057
 
1067
1058
      switch (c)
1068
1059
        {
1069
1060
        case 16: /* C-p */
1080
1071
          if (! forward_char (screen, 1))
1081
1072
            goto fail;
1082
1073
          break;
1083
 
          
 
1074
 
1084
1075
        case 2: /* C-b */
1085
1076
          if (! backward_char (screen, 1))
1086
1077
            goto fail;
1095
1086
          if (! end_of_line (screen, 1))
1096
1087
            goto fail;
1097
1088
          break;
1098
 
          
 
1089
 
1099
1090
        case '\t': /* C-i */
1100
1091
          if (! complete (screen, prev_c == c, 1))
1101
1092
            goto fail;
1102
1093
          break;
1103
 
          
 
1094
 
1104
1095
        case 4: /* C-d */
1105
1096
          if (! delete_char (screen, 1))
1106
1097
            goto fail;
1110
1101
          if (! backward_delete_char (screen, 1))
1111
1102
            goto fail;
1112
1103
          break;
1113
 
          
 
1104
 
1114
1105
        case 11: /* C-k */
1115
1106
          if (! kill_line (screen, prev_c == c, 1))
1116
1107
            goto fail;
1117
1108
          break;
1118
 
          
 
1109
 
1119
1110
        case 21: /* C-u */
1120
1111
          /* FIXME: What behavior is good for this key?  */
1121
1112
          break;
1122
 
          
 
1113
 
1123
1114
        case 25: /* C-y */
1124
1115
          if (! yank (screen, 1))
1125
1116
            goto fail;
1128
1119
        case 12: /* C-l */
1129
1120
          /* FIXME: centering.  */
1130
1121
          goto refresh;
1131
 
          
 
1122
 
1132
1123
        case 15: /* C-o */
1133
1124
          if (! open_line (screen, 1))
1134
1125
            goto fail;
1143
1134
        case '\e':
1144
1135
          destroy_screen (screen);
1145
1136
          return;
1146
 
          
 
1137
 
1147
1138
        case 3: /* C-c */
1148
1139
          grub_cmdline_run (1);
1149
1140
          goto refresh;
1150
 
          
 
1141
 
1151
1142
        case 24: /* C-x */
1152
1143
          if (! run (screen))
1153
1144
            goto fail;
1158
1149
        case 20: /* C-t */
1159
1150
          /* FIXME */
1160
1151
          break;
1161
 
          
 
1152
 
1162
1153
        default:
1163
1154
          if (grub_isprint (c))
1164
1155
            {
1177
1168
 
1178
1169
 fail:
1179
1170
  destroy_screen (screen);
1180
 
  
 
1171
 
1181
1172
  grub_cls ();
1182
1173
  grub_print_error ();
1183
1174
  grub_errno = GRUB_ERR_NONE;