core: use GRUB_TERM_ definitions when handling term characters
[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 /* Hex value is used for ESC, since '\e' is nonstandard */
59 #define GRUB_TERM_ESC           0x1b
60 #define GRUB_TERM_TAB           '\t'
61 #define GRUB_TERM_BACKSPACE     '\b'
62
63 #define GRUB_PROGRESS_NO_UPDATE -1
64 #define GRUB_PROGRESS_FAST      0
65 #define GRUB_PROGRESS_SLOW      2
66
67 #ifndef ASM_FILE
68
69 #include <grub/err.h>
70 #include <grub/symbol.h>
71 #include <grub/types.h>
72 #include <grub/unicode.h>
73 #include <grub/list.h>
74
75 /* These are used to represent the various color states we use.  */
76 typedef enum
77   {
78     /* The color used to display all text that does not use the
79        user defined colors below.  */
80     GRUB_TERM_COLOR_STANDARD,
81     /* The user defined colors for normal text.  */
82     GRUB_TERM_COLOR_NORMAL,
83     /* The user defined colors for highlighted text.  */
84     GRUB_TERM_COLOR_HIGHLIGHT
85   }
86 grub_term_color_state;
87
88 /* Flags for representing the capabilities of a terminal.  */
89 /* Some notes about the flags:
90    - These flags are used by higher-level functions but not terminals
91    themselves.
92    - If a terminal is dumb, you may assume that only putchar, getkey and
93    checkkey are called.
94    - Some fancy features (setcolorstate, setcolor and setcursor) can be set
95    to NULL.  */
96
97 /* Set when input characters shouldn't be echoed back.  */
98 #define GRUB_TERM_NO_ECHO               (1 << 0)
99 /* Set when the editing feature should be disabled.  */
100 #define GRUB_TERM_NO_EDIT               (1 << 1)
101 /* Set when the terminal cannot do fancy things.  */
102 #define GRUB_TERM_DUMB                  (1 << 2)
103 /* Which encoding does terminal expect stream to be.  */
104 #define GRUB_TERM_CODE_TYPE_SHIFT       3
105 #define GRUB_TERM_CODE_TYPE_MASK                (7 << GRUB_TERM_CODE_TYPE_SHIFT)
106 /* Only ASCII characters accepted.  */
107 #define GRUB_TERM_CODE_TYPE_ASCII               (0 << GRUB_TERM_CODE_TYPE_SHIFT)
108 /* Expects CP-437 characters (ASCII + pseudographics).  */
109 #define GRUB_TERM_CODE_TYPE_CP437                       (1 << GRUB_TERM_CODE_TYPE_SHIFT)
110 /* UTF-8 stream in logical order. Usually used for terminals
111    which just forward the stream to another computer.  */
112 #define GRUB_TERM_CODE_TYPE_UTF8_LOGICAL        (2 << GRUB_TERM_CODE_TYPE_SHIFT)
113 /* UTF-8 in visual order. Like UTF-8 logical but for buggy endpoints.  */
114 #define GRUB_TERM_CODE_TYPE_UTF8_VISUAL         (3 << GRUB_TERM_CODE_TYPE_SHIFT)
115 /* Glyph description in visual order.  */
116 #define GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS       (4 << GRUB_TERM_CODE_TYPE_SHIFT)
117
118
119 /* Bitmasks for modifier keys returned by grub_getkeystatus.  */
120 #define GRUB_TERM_STATUS_RSHIFT (1 << 0)
121 #define GRUB_TERM_STATUS_LSHIFT (1 << 1)
122 #define GRUB_TERM_STATUS_RCTRL  (1 << 2)
123 #define GRUB_TERM_STATUS_RALT   (1 << 3)
124 #define GRUB_TERM_STATUS_SCROLL (1 << 4)
125 #define GRUB_TERM_STATUS_NUM    (1 << 5)
126 #define GRUB_TERM_STATUS_CAPS   (1 << 6)
127 #define GRUB_TERM_STATUS_LCTRL  (1 << 8)
128 #define GRUB_TERM_STATUS_LALT   (1 << 9)
129
130 /* Menu-related geometrical constants.  */
131
132 /* The number of columns/lines between messages/borders/etc.  */
133 #define GRUB_TERM_MARGIN        1
134
135 /* The number of columns of scroll information.  */
136 #define GRUB_TERM_SCROLL_WIDTH  1
137
138 struct grub_term_input
139 {
140   /* The next terminal.  */
141   struct grub_term_input *next;
142   struct grub_term_input **prev;
143
144   /* The terminal name.  */
145   const char *name;
146
147   /* Initialize the terminal.  */
148   grub_err_t (*init) (struct grub_term_input *term);
149
150   /* Clean up the terminal.  */
151   grub_err_t (*fini) (struct grub_term_input *term);
152
153   /* Get a character if any input character is available. Otherwise return -1  */
154   int (*getkey) (struct grub_term_input *term);
155
156   /* Get keyboard modifier status.  */
157   int (*getkeystatus) (struct grub_term_input *term);
158
159   void *data;
160 };
161 typedef struct grub_term_input *grub_term_input_t;
162
163 /* Made in a way to fit into uint32_t and so be passed in a register.  */
164 struct grub_term_coordinate
165 {
166   grub_uint16_t x;
167   grub_uint16_t y;
168 };
169
170 struct grub_term_output
171 {
172   /* The next terminal.  */
173   struct grub_term_output *next;
174   struct grub_term_output **prev;
175
176   /* The terminal name.  */
177   const char *name;
178
179   /* Initialize the terminal.  */
180   grub_err_t (*init) (struct grub_term_output *term);
181
182   /* Clean up the terminal.  */
183   grub_err_t (*fini) (struct grub_term_output *term);
184
185   /* Put a character. C is encoded in Unicode.  */
186   void (*putchar) (struct grub_term_output *term,
187                    const struct grub_unicode_glyph *c);
188
189   /* Get the number of columns occupied by a given character C. C is
190      encoded in Unicode.  */
191   grub_size_t (*getcharwidth) (struct grub_term_output *term,
192                                const struct grub_unicode_glyph *c);
193
194   /* Get the screen size.  */
195   struct grub_term_coordinate (*getwh) (struct grub_term_output *term);
196
197   /* Get the cursor position. The return value is ((X << 8) | Y).  */
198   struct grub_term_coordinate (*getxy) (struct grub_term_output *term);
199
200   /* Go to the position (X, Y).  */
201   void (*gotoxy) (struct grub_term_output *term,
202                   struct grub_term_coordinate pos);
203
204   /* Clear the screen.  */
205   void (*cls) (struct grub_term_output *term);
206
207   /* Set the current color to be used */
208   void (*setcolorstate) (struct grub_term_output *term,
209                          grub_term_color_state state);
210
211   /* Turn on/off the cursor.  */
212   void (*setcursor) (struct grub_term_output *term, int on);
213
214   /* Update the screen.  */
215   void (*refresh) (struct grub_term_output *term);
216
217   /* gfxterm only: put in fullscreen mode.  */
218   grub_err_t (*fullscreen) (void);
219
220   /* The feature flags defined above.  */
221   grub_uint32_t flags;
222
223   /* Progress data. */
224   grub_uint32_t progress_update_divisor;
225   grub_uint32_t progress_update_counter;
226
227   void *data;
228 };
229 typedef struct grub_term_output *grub_term_output_t;
230
231 #define GRUB_TERM_DEFAULT_NORMAL_COLOR 0x07
232 #define GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR 0x70
233 #define GRUB_TERM_DEFAULT_STANDARD_COLOR 0x07
234
235 /* Current color state.  */
236 extern grub_uint8_t EXPORT_VAR(grub_term_normal_color);
237 extern grub_uint8_t EXPORT_VAR(grub_term_highlight_color);
238
239 extern struct grub_term_output *EXPORT_VAR(grub_term_outputs_disabled);
240 extern struct grub_term_input *EXPORT_VAR(grub_term_inputs_disabled);
241 extern struct grub_term_output *EXPORT_VAR(grub_term_outputs);
242 extern struct grub_term_input *EXPORT_VAR(grub_term_inputs);
243
244 static inline void
245 grub_term_register_input (const char *name __attribute__ ((unused)),
246                           grub_term_input_t term)
247 {
248   if (grub_term_inputs)
249     grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
250                     GRUB_AS_LIST (term));
251   else
252     {
253       /* If this is the first terminal, enable automatically.  */
254       if (! term->init || term->init (term) == GRUB_ERR_NONE)
255         grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
256     }
257 }
258
259 static inline void
260 grub_term_register_input_inactive (const char *name __attribute__ ((unused)),
261                                    grub_term_input_t term)
262 {
263   grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
264                   GRUB_AS_LIST (term));
265 }
266
267 static inline void
268 grub_term_register_input_active (const char *name __attribute__ ((unused)),
269                                  grub_term_input_t term)
270 {
271   if (! term->init || term->init (term) == GRUB_ERR_NONE)
272     grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
273 }
274
275 static inline void
276 grub_term_register_output (const char *name __attribute__ ((unused)),
277                            grub_term_output_t term)
278 {
279   if (grub_term_outputs)
280     grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
281                     GRUB_AS_LIST (term));
282   else
283     {
284       /* If this is the first terminal, enable automatically.  */
285       if (! term->init || term->init (term) == GRUB_ERR_NONE)
286         grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
287                         GRUB_AS_LIST (term));
288     }
289 }
290
291 static inline void
292 grub_term_register_output_inactive (const char *name __attribute__ ((unused)),
293                                     grub_term_output_t term)
294 {
295   grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
296                   GRUB_AS_LIST (term));
297 }
298
299 static inline void
300 grub_term_register_output_active (const char *name __attribute__ ((unused)),
301                                   grub_term_output_t term)
302 {
303   if (! term->init || term->init (term) == GRUB_ERR_NONE)
304     grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
305                     GRUB_AS_LIST (term));
306 }
307
308 static inline void
309 grub_term_unregister_input (grub_term_input_t term)
310 {
311   grub_list_remove (GRUB_AS_LIST (term));
312   grub_list_remove (GRUB_AS_LIST (term));
313 }
314
315 static inline void
316 grub_term_unregister_output (grub_term_output_t term)
317 {
318   grub_list_remove (GRUB_AS_LIST (term));
319   grub_list_remove (GRUB_AS_LIST (term));
320 }
321
322 #define FOR_ACTIVE_TERM_INPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_inputs))
323 #define FOR_DISABLED_TERM_INPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_inputs_disabled))
324 #define FOR_ACTIVE_TERM_OUTPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_outputs))
325 #define FOR_DISABLED_TERM_OUTPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_outputs_disabled))
326
327 void grub_putcode (grub_uint32_t code, struct grub_term_output *term);
328 int EXPORT_FUNC(grub_getkey) (void);
329 int EXPORT_FUNC(grub_getkey_noblock) (void);
330 void grub_cls (void);
331 void EXPORT_FUNC(grub_refresh) (void);
332 void grub_puts_terminal (const char *str, struct grub_term_output *term);
333 struct grub_term_coordinate *grub_term_save_pos (void);
334 void grub_term_restore_pos (struct grub_term_coordinate *pos);
335
336 static inline unsigned grub_term_width (struct grub_term_output *term)
337 {
338   return term->getwh(term).x ? : 80;
339 }
340
341 static inline unsigned grub_term_height (struct grub_term_output *term)
342 {
343   return term->getwh(term).y ? : 24;
344 }
345
346 static inline struct grub_term_coordinate
347 grub_term_getxy (struct grub_term_output *term)
348 {
349   return term->getxy (term);
350 }
351
352 static inline void
353 grub_term_refresh (struct grub_term_output *term)
354 {
355   if (term->refresh)
356     term->refresh (term);
357 }
358
359 static inline void
360 grub_term_gotoxy (struct grub_term_output *term, struct grub_term_coordinate pos)
361 {
362   term->gotoxy (term, pos);
363 }
364
365 static inline void 
366 grub_term_setcolorstate (struct grub_term_output *term, 
367                          grub_term_color_state state)
368 {
369   if (term->setcolorstate)
370     term->setcolorstate (term, state);
371 }
372
373 static inline void
374 grub_setcolorstate (grub_term_color_state state)
375 {
376   struct grub_term_output *term;
377   
378   FOR_ACTIVE_TERM_OUTPUTS(term)
379     grub_term_setcolorstate (term, state);
380 }
381
382 /* Turn on/off the cursor.  */
383 static inline void 
384 grub_term_setcursor (struct grub_term_output *term, int on)
385 {
386   if (term->setcursor)
387     term->setcursor (term, on);
388 }
389
390 static inline void 
391 grub_term_cls (struct grub_term_output *term)
392 {
393   if (term->cls)
394     (term->cls) (term);
395   else
396     {
397       grub_putcode ('\n', term);
398       grub_term_refresh (term);
399     }
400 }
401
402 #if HAVE_FONT_SOURCE
403
404 grub_size_t
405 grub_unicode_estimate_width (const struct grub_unicode_glyph *c);
406
407 #else
408
409 static inline grub_size_t
410 grub_unicode_estimate_width (const struct grub_unicode_glyph *c __attribute__ ((unused)))
411 {
412   if (grub_unicode_get_comb_type (c->base))
413     return 0;
414   return 1;
415 }
416
417 #endif
418
419 #define GRUB_TERM_TAB_WIDTH 8
420
421 static inline grub_size_t
422 grub_term_getcharwidth (struct grub_term_output *term,
423                         const struct grub_unicode_glyph *c)
424 {
425   if (c->base == '\t')
426     return GRUB_TERM_TAB_WIDTH;
427
428   if (term->getcharwidth)
429     return term->getcharwidth (term, c);
430   else if (((term->flags & GRUB_TERM_CODE_TYPE_MASK)
431             == GRUB_TERM_CODE_TYPE_UTF8_LOGICAL)
432            || ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
433                == GRUB_TERM_CODE_TYPE_UTF8_VISUAL)
434            || ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
435                == GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS))
436     return grub_unicode_estimate_width (c);
437   else
438     return 1;
439 }
440
441 struct grub_term_autoload
442 {
443   struct grub_term_autoload *next;
444   char *name;
445   char *modname;
446 };
447
448 extern struct grub_term_autoload *grub_term_input_autoload;
449 extern struct grub_term_autoload *grub_term_output_autoload;
450
451 static inline void
452 grub_print_spaces (struct grub_term_output *term, int number_spaces)
453 {
454   while (--number_spaces >= 0)
455     grub_putcode (' ', term);
456 }
457
458 extern void (*EXPORT_VAR (grub_term_poll_usb)) (int wait_for_completion);
459
460 #define GRUB_TERM_REPEAT_PRE_INTERVAL 400
461 #define GRUB_TERM_REPEAT_INTERVAL 50
462
463 #endif /* ! ASM_FILE */
464
465 #endif /* ! GRUB_TERM_HEADER */