5ffb38f69aaa8911a66bdc6f417a72666b19e514
[grub.git] / include / grub / term.h
1 /*
2  *  GRUB  --  GRand Unified Bootloader
3  *  Copyright (C) 2002,2003,2005,2007,2008,2009,2010  Free Software Foundation, Inc.
4  *
5  *  GRUB is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  GRUB is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifndef GRUB_TERM_HEADER
20 #define GRUB_TERM_HEADER        1
21
22 #define GRUB_TERM_NO_KEY        0
23
24 /* Internal codes used by GRUB to represent terminal input.  */
25 /* Only for keys otherwise not having shifted modification.  */
26 #define GRUB_TERM_SHIFT         0x01000000
27 #define GRUB_TERM_CTRL          0x02000000
28 #define GRUB_TERM_ALT           0x04000000
29
30 /* Keys without associated character.  */
31 #define GRUB_TERM_EXTENDED      0x00800000
32 #define GRUB_TERM_KEY_MASK      0x00ffffff
33
34 #define GRUB_TERM_KEY_LEFT      (GRUB_TERM_EXTENDED | 0x4b)
35 #define GRUB_TERM_KEY_RIGHT     (GRUB_TERM_EXTENDED | 0x4d)
36 #define GRUB_TERM_KEY_UP        (GRUB_TERM_EXTENDED | 0x48)
37 #define GRUB_TERM_KEY_DOWN      (GRUB_TERM_EXTENDED | 0x50)
38 #define GRUB_TERM_KEY_HOME      (GRUB_TERM_EXTENDED | 0x47)
39 #define GRUB_TERM_KEY_END       (GRUB_TERM_EXTENDED | 0x4f)
40 #define GRUB_TERM_KEY_DC        (GRUB_TERM_EXTENDED | 0x53)
41 #define GRUB_TERM_KEY_PPAGE     (GRUB_TERM_EXTENDED | 0x49)
42 #define GRUB_TERM_KEY_NPAGE     (GRUB_TERM_EXTENDED | 0x51)
43 #define GRUB_TERM_KEY_F1        (GRUB_TERM_EXTENDED | 0x3b)
44 #define GRUB_TERM_KEY_F2        (GRUB_TERM_EXTENDED | 0x3c)
45 #define GRUB_TERM_KEY_F3        (GRUB_TERM_EXTENDED | 0x3d)
46 #define GRUB_TERM_KEY_F4        (GRUB_TERM_EXTENDED | 0x3e)
47 #define GRUB_TERM_KEY_F5        (GRUB_TERM_EXTENDED | 0x3f)
48 #define GRUB_TERM_KEY_F6        (GRUB_TERM_EXTENDED | 0x40)
49 #define GRUB_TERM_KEY_F7        (GRUB_TERM_EXTENDED | 0x41)
50 #define GRUB_TERM_KEY_F8        (GRUB_TERM_EXTENDED | 0x42)
51 #define GRUB_TERM_KEY_F9        (GRUB_TERM_EXTENDED | 0x43)
52 #define GRUB_TERM_KEY_F10       (GRUB_TERM_EXTENDED | 0x44)
53 #define GRUB_TERM_KEY_F11       (GRUB_TERM_EXTENDED | 0x57)
54 #define GRUB_TERM_KEY_F12       (GRUB_TERM_EXTENDED | 0x58)
55 #define GRUB_TERM_KEY_INSERT    (GRUB_TERM_EXTENDED | 0x52)
56 #define GRUB_TERM_KEY_CENTER    (GRUB_TERM_EXTENDED | 0x4c)
57
58 #define GRUB_TERM_ESC           '\e'
59 #define GRUB_TERM_TAB           '\t'
60 #define GRUB_TERM_BACKSPACE     '\b'
61
62 #define GRUB_PROGRESS_NO_UPDATE -1
63 #define GRUB_PROGRESS_FAST      0
64 #define GRUB_PROGRESS_SLOW      2
65
66 #ifndef ASM_FILE
67
68 #include <grub/err.h>
69 #include <grub/symbol.h>
70 #include <grub/types.h>
71 #include <grub/unicode.h>
72 #include <grub/list.h>
73
74 /* These are used to represent the various color states we use.  */
75 typedef enum
76   {
77     /* The color used to display all text that does not use the
78        user defined colors below.  */
79     GRUB_TERM_COLOR_STANDARD,
80     /* The user defined colors for normal text.  */
81     GRUB_TERM_COLOR_NORMAL,
82     /* The user defined colors for highlighted text.  */
83     GRUB_TERM_COLOR_HIGHLIGHT
84   }
85 grub_term_color_state;
86
87 /* Flags for representing the capabilities of a terminal.  */
88 /* Some notes about the flags:
89    - These flags are used by higher-level functions but not terminals
90    themselves.
91    - If a terminal is dumb, you may assume that only putchar, getkey and
92    checkkey are called.
93    - Some fancy features (setcolorstate, setcolor and setcursor) can be set
94    to NULL.  */
95
96 /* Set when input characters shouldn't be echoed back.  */
97 #define GRUB_TERM_NO_ECHO               (1 << 0)
98 /* Set when the editing feature should be disabled.  */
99 #define GRUB_TERM_NO_EDIT               (1 << 1)
100 /* Set when the terminal cannot do fancy things.  */
101 #define GRUB_TERM_DUMB                  (1 << 2)
102 /* Which encoding does terminal expect stream to be.  */
103 #define GRUB_TERM_CODE_TYPE_SHIFT       3
104 #define GRUB_TERM_CODE_TYPE_MASK                (7 << GRUB_TERM_CODE_TYPE_SHIFT)
105 /* Only ASCII characters accepted.  */
106 #define GRUB_TERM_CODE_TYPE_ASCII               (0 << GRUB_TERM_CODE_TYPE_SHIFT)
107 /* Expects CP-437 characters (ASCII + pseudographics).  */
108 #define GRUB_TERM_CODE_TYPE_CP437                       (1 << GRUB_TERM_CODE_TYPE_SHIFT)
109 /* UTF-8 stream in logical order. Usually used for terminals
110    which just forward the stream to another computer.  */
111 #define GRUB_TERM_CODE_TYPE_UTF8_LOGICAL        (2 << GRUB_TERM_CODE_TYPE_SHIFT)
112 /* UTF-8 in visual order. Like UTF-8 logical but for buggy endpoints.  */
113 #define GRUB_TERM_CODE_TYPE_UTF8_VISUAL         (3 << GRUB_TERM_CODE_TYPE_SHIFT)
114 /* Glyph description in visual order.  */
115 #define GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS       (4 << GRUB_TERM_CODE_TYPE_SHIFT)
116
117
118 /* Bitmasks for modifier keys returned by grub_getkeystatus.  */
119 #define GRUB_TERM_STATUS_RSHIFT (1 << 0)
120 #define GRUB_TERM_STATUS_LSHIFT (1 << 1)
121 #define GRUB_TERM_STATUS_RCTRL  (1 << 2)
122 #define GRUB_TERM_STATUS_RALT   (1 << 3)
123 #define GRUB_TERM_STATUS_SCROLL (1 << 4)
124 #define GRUB_TERM_STATUS_NUM    (1 << 5)
125 #define GRUB_TERM_STATUS_CAPS   (1 << 6)
126 #define GRUB_TERM_STATUS_LCTRL  (1 << 8)
127 #define GRUB_TERM_STATUS_LALT   (1 << 9)
128
129 /* Menu-related geometrical constants.  */
130
131 /* The number of columns/lines between messages/borders/etc.  */
132 #define GRUB_TERM_MARGIN        1
133
134 /* The number of columns of scroll information.  */
135 #define GRUB_TERM_SCROLL_WIDTH  1
136
137 struct grub_term_input
138 {
139   /* The next terminal.  */
140   struct grub_term_input *next;
141   struct grub_term_input **prev;
142
143   /* The terminal name.  */
144   const char *name;
145
146   /* Initialize the terminal.  */
147   grub_err_t (*init) (struct grub_term_input *term);
148
149   /* Clean up the terminal.  */
150   grub_err_t (*fini) (struct grub_term_input *term);
151
152   /* Get a character if any input character is available. Otherwise return -1  */
153   int (*getkey) (struct grub_term_input *term);
154
155   /* Get keyboard modifier status.  */
156   int (*getkeystatus) (struct grub_term_input *term);
157
158   void *data;
159 };
160 typedef struct grub_term_input *grub_term_input_t;
161
162 /* Made in a way to fit into uint32_t and so be passed in a register.  */
163 struct grub_term_coordinate
164 {
165   grub_uint16_t x;
166   grub_uint16_t y;
167 };
168
169 struct grub_term_output
170 {
171   /* The next terminal.  */
172   struct grub_term_output *next;
173   struct grub_term_output **prev;
174
175   /* The terminal name.  */
176   const char *name;
177
178   /* Initialize the terminal.  */
179   grub_err_t (*init) (struct grub_term_output *term);
180
181   /* Clean up the terminal.  */
182   grub_err_t (*fini) (struct grub_term_output *term);
183
184   /* Put a character. C is encoded in Unicode.  */
185   void (*putchar) (struct grub_term_output *term,
186                    const struct grub_unicode_glyph *c);
187
188   /* Get the number of columns occupied by a given character C. C is
189      encoded in Unicode.  */
190   grub_size_t (*getcharwidth) (struct grub_term_output *term,
191                                const struct grub_unicode_glyph *c);
192
193   /* Get the screen size.  */
194   struct grub_term_coordinate (*getwh) (struct grub_term_output *term);
195
196   /* Get the cursor position. The return value is ((X << 8) | Y).  */
197   struct grub_term_coordinate (*getxy) (struct grub_term_output *term);
198
199   /* Go to the position (X, Y).  */
200   void (*gotoxy) (struct grub_term_output *term,
201                   struct grub_term_coordinate pos);
202
203   /* Clear the screen.  */
204   void (*cls) (struct grub_term_output *term);
205
206   /* Set the current color to be used */
207   void (*setcolorstate) (struct grub_term_output *term,
208                          grub_term_color_state state);
209
210   /* Turn on/off the cursor.  */
211   void (*setcursor) (struct grub_term_output *term, int on);
212
213   /* Update the screen.  */
214   void (*refresh) (struct grub_term_output *term);
215
216   /* gfxterm only: put in fullscreen mode.  */
217   grub_err_t (*fullscreen) (void);
218
219   /* The feature flags defined above.  */
220   grub_uint32_t flags;
221
222   /* Progress data. */
223   grub_uint32_t progress_update_divisor;
224   grub_uint32_t progress_update_counter;
225
226   void *data;
227 };
228 typedef struct grub_term_output *grub_term_output_t;
229
230 #define GRUB_TERM_DEFAULT_NORMAL_COLOR 0x07
231 #define GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR 0x70
232 #define GRUB_TERM_DEFAULT_STANDARD_COLOR 0x07
233
234 /* Current color state.  */
235 extern grub_uint8_t EXPORT_VAR(grub_term_normal_color);
236 extern grub_uint8_t EXPORT_VAR(grub_term_highlight_color);
237
238 extern struct grub_term_output *EXPORT_VAR(grub_term_outputs_disabled);
239 extern struct grub_term_input *EXPORT_VAR(grub_term_inputs_disabled);
240 extern struct grub_term_output *EXPORT_VAR(grub_term_outputs);
241 extern struct grub_term_input *EXPORT_VAR(grub_term_inputs);
242
243 static inline void
244 grub_term_register_input (const char *name __attribute__ ((unused)),
245                           grub_term_input_t term)
246 {
247   if (grub_term_inputs)
248     grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
249                     GRUB_AS_LIST (term));
250   else
251     {
252       /* If this is the first terminal, enable automatically.  */
253       if (! term->init || term->init (term) == GRUB_ERR_NONE)
254         grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
255     }
256 }
257
258 static inline void
259 grub_term_register_input_inactive (const char *name __attribute__ ((unused)),
260                                    grub_term_input_t term)
261 {
262   grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
263                   GRUB_AS_LIST (term));
264 }
265
266 static inline void
267 grub_term_register_input_active (const char *name __attribute__ ((unused)),
268                                  grub_term_input_t term)
269 {
270   if (! term->init || term->init (term) == GRUB_ERR_NONE)
271     grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
272 }
273
274 static inline void
275 grub_term_register_output (const char *name __attribute__ ((unused)),
276                            grub_term_output_t term)
277 {
278   if (grub_term_outputs)
279     grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
280                     GRUB_AS_LIST (term));
281   else
282     {
283       /* If this is the first terminal, enable automatically.  */
284       if (! term->init || term->init (term) == GRUB_ERR_NONE)
285         grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
286                         GRUB_AS_LIST (term));
287     }
288 }
289
290 static inline void
291 grub_term_register_output_inactive (const char *name __attribute__ ((unused)),
292                                     grub_term_output_t term)
293 {
294   grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
295                   GRUB_AS_LIST (term));
296 }
297
298 static inline void
299 grub_term_register_output_active (const char *name __attribute__ ((unused)),
300                                   grub_term_output_t term)
301 {
302   if (! term->init || term->init (term) == GRUB_ERR_NONE)
303     grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
304                     GRUB_AS_LIST (term));
305 }
306
307 static inline void
308 grub_term_unregister_input (grub_term_input_t term)
309 {
310   grub_list_remove (GRUB_AS_LIST (term));
311   grub_list_remove (GRUB_AS_LIST (term));
312 }
313
314 static inline void
315 grub_term_unregister_output (grub_term_output_t term)
316 {
317   grub_list_remove (GRUB_AS_LIST (term));
318   grub_list_remove (GRUB_AS_LIST (term));
319 }
320
321 #define FOR_ACTIVE_TERM_INPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_inputs))
322 #define FOR_DISABLED_TERM_INPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_inputs_disabled))
323 #define FOR_ACTIVE_TERM_OUTPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_outputs))
324 #define FOR_DISABLED_TERM_OUTPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_outputs_disabled))
325
326 void grub_putcode (grub_uint32_t code, struct grub_term_output *term);
327 int EXPORT_FUNC(grub_getkey) (void);
328 int EXPORT_FUNC(grub_getkey_noblock) (void);
329 void grub_cls (void);
330 void EXPORT_FUNC(grub_refresh) (void);
331 void grub_puts_terminal (const char *str, struct grub_term_output *term);
332 struct grub_term_coordinate *grub_term_save_pos (void);
333 void grub_term_restore_pos (struct grub_term_coordinate *pos);
334
335 static inline unsigned grub_term_width (struct grub_term_output *term)
336 {
337   return term->getwh(term).x ? : 80;
338 }
339
340 static inline unsigned grub_term_height (struct grub_term_output *term)
341 {
342   return term->getwh(term).y ? : 24;
343 }
344
345 static inline struct grub_term_coordinate
346 grub_term_getxy (struct grub_term_output *term)
347 {
348   return term->getxy (term);
349 }
350
351 static inline void
352 grub_term_refresh (struct grub_term_output *term)
353 {
354   if (term->refresh)
355     term->refresh (term);
356 }
357
358 static inline void
359 grub_term_gotoxy (struct grub_term_output *term, struct grub_term_coordinate pos)
360 {
361   term->gotoxy (term, pos);
362 }
363
364 static inline void 
365 grub_term_setcolorstate (struct grub_term_output *term, 
366                          grub_term_color_state state)
367 {
368   if (term->setcolorstate)
369     term->setcolorstate (term, state);
370 }
371
372 static inline void
373 grub_setcolorstate (grub_term_color_state state)
374 {
375   struct grub_term_output *term;
376   
377   FOR_ACTIVE_TERM_OUTPUTS(term)
378     grub_term_setcolorstate (term, state);
379 }
380
381 /* Turn on/off the cursor.  */
382 static inline void 
383 grub_term_setcursor (struct grub_term_output *term, int on)
384 {
385   if (term->setcursor)
386     term->setcursor (term, on);
387 }
388
389 static inline void 
390 grub_term_cls (struct grub_term_output *term)
391 {
392   if (term->cls)
393     (term->cls) (term);
394   else
395     {
396       grub_putcode ('\n', term);
397       grub_term_refresh (term);
398     }
399 }
400
401 #if HAVE_FONT_SOURCE
402
403 grub_size_t
404 grub_unicode_estimate_width (const struct grub_unicode_glyph *c);
405
406 #else
407
408 static inline grub_size_t
409 grub_unicode_estimate_width (const struct grub_unicode_glyph *c __attribute__ ((unused)))
410 {
411   if (grub_unicode_get_comb_type (c->base))
412     return 0;
413   return 1;
414 }
415
416 #endif
417
418 #define GRUB_TERM_TAB_WIDTH 8
419
420 static inline grub_size_t
421 grub_term_getcharwidth (struct grub_term_output *term,
422                         const struct grub_unicode_glyph *c)
423 {
424   if (c->base == '\t')
425     return GRUB_TERM_TAB_WIDTH;
426
427   if (term->getcharwidth)
428     return term->getcharwidth (term, c);
429   else if (((term->flags & GRUB_TERM_CODE_TYPE_MASK)
430             == GRUB_TERM_CODE_TYPE_UTF8_LOGICAL)
431            || ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
432                == GRUB_TERM_CODE_TYPE_UTF8_VISUAL)
433            || ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
434                == GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS))
435     return grub_unicode_estimate_width (c);
436   else
437     return 1;
438 }
439
440 struct grub_term_autoload
441 {
442   struct grub_term_autoload *next;
443   char *name;
444   char *modname;
445 };
446
447 extern struct grub_term_autoload *grub_term_input_autoload;
448 extern struct grub_term_autoload *grub_term_output_autoload;
449
450 static inline void
451 grub_print_spaces (struct grub_term_output *term, int number_spaces)
452 {
453   while (--number_spaces >= 0)
454     grub_putcode (' ', term);
455 }
456
457 extern void (*EXPORT_VAR (grub_term_poll_usb)) (int wait_for_completion);
458
459 #define GRUB_TERM_REPEAT_PRE_INTERVAL 400
460 #define GRUB_TERM_REPEAT_INTERVAL 50
461
462 #endif /* ! ASM_FILE */
463
464 #endif /* ! GRUB_TERM_HEADER */