term.h 14.2 KB
Newer Older
okuji's avatar
okuji committed
1
/*
2
 *  GRUB  --  GRand Unified Bootloader
3
 *  Copyright (C) 2002,2003,2005,2007,2008,2009,2010  Free Software Foundation, Inc.
okuji's avatar
okuji committed
4
 *
5
 *  GRUB is free software: you can redistribute it and/or modify
okuji's avatar
okuji committed
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
okuji's avatar
okuji committed
8 9
 *  (at your option) any later version.
 *
10
 *  GRUB is distributed in the hope that it will be useful,
okuji's avatar
okuji committed
11 12 13 14 15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
16
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
okuji's avatar
okuji committed
17 18
 */

19 20
#ifndef GRUB_TERM_HEADER
#define GRUB_TERM_HEADER	1
okuji's avatar
okuji committed
21

22
#define GRUB_TERM_NO_KEY        0
23

24
/* Internal codes used by GRUB to represent terminal input.  */
25 26
/* Only for keys otherwise not having shifted modification.  */
#define GRUB_TERM_SHIFT         0x01000000
27 28 29 30
#define GRUB_TERM_CTRL          0x02000000
#define GRUB_TERM_ALT           0x04000000

/* Keys without associated character.  */
31 32
#define GRUB_TERM_EXTENDED      0x00800000
#define GRUB_TERM_KEY_MASK      0x00ffffff
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

#define GRUB_TERM_KEY_LEFT      (GRUB_TERM_EXTENDED | 0x4b)
#define GRUB_TERM_KEY_RIGHT     (GRUB_TERM_EXTENDED | 0x4d)
#define GRUB_TERM_KEY_UP        (GRUB_TERM_EXTENDED | 0x48)
#define GRUB_TERM_KEY_DOWN      (GRUB_TERM_EXTENDED | 0x50)
#define GRUB_TERM_KEY_HOME      (GRUB_TERM_EXTENDED | 0x47)
#define GRUB_TERM_KEY_END       (GRUB_TERM_EXTENDED | 0x4f)
#define GRUB_TERM_KEY_DC        (GRUB_TERM_EXTENDED | 0x53)
#define GRUB_TERM_KEY_PPAGE     (GRUB_TERM_EXTENDED | 0x49)
#define GRUB_TERM_KEY_NPAGE     (GRUB_TERM_EXTENDED | 0x51)
#define GRUB_TERM_KEY_F1        (GRUB_TERM_EXTENDED | 0x3b)
#define GRUB_TERM_KEY_F2        (GRUB_TERM_EXTENDED | 0x3c)
#define GRUB_TERM_KEY_F3        (GRUB_TERM_EXTENDED | 0x3d)
#define GRUB_TERM_KEY_F4        (GRUB_TERM_EXTENDED | 0x3e)
#define GRUB_TERM_KEY_F5        (GRUB_TERM_EXTENDED | 0x3f)
#define GRUB_TERM_KEY_F6        (GRUB_TERM_EXTENDED | 0x40)
#define GRUB_TERM_KEY_F7        (GRUB_TERM_EXTENDED | 0x41)
#define GRUB_TERM_KEY_F8        (GRUB_TERM_EXTENDED | 0x42)
#define GRUB_TERM_KEY_F9        (GRUB_TERM_EXTENDED | 0x43)
#define GRUB_TERM_KEY_F10       (GRUB_TERM_EXTENDED | 0x44)
#define GRUB_TERM_KEY_F11       (GRUB_TERM_EXTENDED | 0x57)
#define GRUB_TERM_KEY_F12       (GRUB_TERM_EXTENDED | 0x58)
#define GRUB_TERM_KEY_INSERT    (GRUB_TERM_EXTENDED | 0x52)
#define GRUB_TERM_KEY_CENTER    (GRUB_TERM_EXTENDED | 0x4c)
57

58 59
#define GRUB_TERM_ESC		'\e'
#define GRUB_TERM_TAB		'\t'
60
#define GRUB_TERM_BACKSPACE	'\b'
61

62 63 64 65
#define GRUB_PROGRESS_NO_UPDATE -1
#define GRUB_PROGRESS_FAST      0
#define GRUB_PROGRESS_SLOW      2

66 67
#ifndef ASM_FILE

68 69 70
#include <grub/err.h>
#include <grub/symbol.h>
#include <grub/types.h>
71
#include <grub/unicode.h>
72
#include <grub/list.h>
okuji's avatar
okuji committed
73 74 75 76 77 78

/* These are used to represent the various color states we use.  */
typedef enum
  {
    /* The color used to display all text that does not use the
       user defined colors below.  */
79
    GRUB_TERM_COLOR_STANDARD,
okuji's avatar
okuji committed
80
    /* The user defined colors for normal text.  */
81
    GRUB_TERM_COLOR_NORMAL,
okuji's avatar
okuji committed
82
    /* The user defined colors for highlighted text.  */
83
    GRUB_TERM_COLOR_HIGHLIGHT
okuji's avatar
okuji committed
84
  }
85
grub_term_color_state;
okuji's avatar
okuji committed
86 87 88 89 90 91 92 93 94 95 96

/* Flags for representing the capabilities of a terminal.  */
/* Some notes about the flags:
   - These flags are used by higher-level functions but not terminals
   themselves.
   - If a terminal is dumb, you may assume that only putchar, getkey and
   checkkey are called.
   - Some fancy features (setcolorstate, setcolor and setcursor) can be set
   to NULL.  */

/* Set when input characters shouldn't be echoed back.  */
97
#define GRUB_TERM_NO_ECHO	        (1 << 0)
okuji's avatar
okuji committed
98
/* Set when the editing feature should be disabled.  */
99
#define GRUB_TERM_NO_EDIT	        (1 << 1)
okuji's avatar
okuji committed
100
/* Set when the terminal cannot do fancy things.  */
101 102
#define GRUB_TERM_DUMB		        (1 << 2)
/* Which encoding does terminal expect stream to be.  */
103 104
#define GRUB_TERM_CODE_TYPE_SHIFT       3
#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 108
/* Expects CP-437 characters (ASCII + pseudographics).  */
#define GRUB_TERM_CODE_TYPE_CP437	                (1 << GRUB_TERM_CODE_TYPE_SHIFT)
109 110
/* UTF-8 stream in logical order. Usually used for terminals
   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)
okuji's avatar
okuji committed
116

117

118
/* Bitmasks for modifier keys returned by grub_getkeystatus.  */
119 120 121 122 123 124 125 126 127
#define GRUB_TERM_STATUS_RSHIFT	(1 << 0)
#define GRUB_TERM_STATUS_LSHIFT	(1 << 1)
#define GRUB_TERM_STATUS_RCTRL	(1 << 2)
#define GRUB_TERM_STATUS_RALT	(1 << 3)
#define GRUB_TERM_STATUS_SCROLL	(1 << 4)
#define GRUB_TERM_STATUS_NUM	(1 << 5)
#define GRUB_TERM_STATUS_CAPS	(1 << 6)
#define GRUB_TERM_STATUS_LCTRL	(1 << 8)
#define GRUB_TERM_STATUS_LALT	(1 << 9)
128

129 130 131 132 133 134 135 136
/* Menu-related geometrical constants.  */

/* The number of columns/lines between messages/borders/etc.  */
#define GRUB_TERM_MARGIN	1

/* The number of columns of scroll information.  */
#define GRUB_TERM_SCROLL_WIDTH	1

137 138
struct grub_term_input
{
139 140
  /* The next terminal.  */
  struct grub_term_input *next;
141
  struct grub_term_input **prev;
142

143 144 145 146
  /* The terminal name.  */
  const char *name;

  /* 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 161
};
typedef struct grub_term_input *grub_term_input_t;

162 163 164
/* Made in a way to fit into uint32_t and so be passed in a register.  */
struct grub_term_coordinate
{
165 166
  grub_uint16_t x;
  grub_uint16_t y;
167 168
};

169
struct grub_term_output
okuji's avatar
okuji committed
170
{
171 172
  /* The next terminal.  */
  struct grub_term_output *next;
173
  struct grub_term_output **prev;
174

okuji's avatar
okuji committed
175 176
  /* The terminal name.  */
  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 186
  void (*putchar) (struct grub_term_output *term,
		   const struct grub_unicode_glyph *c);
187 188 189

  /* Get the number of columns occupied by a given character C. C is
     encoded in Unicode.  */
190 191
  grub_size_t (*getcharwidth) (struct grub_term_output *term,
			       const struct grub_unicode_glyph *c);
192

193 194
  /* Get the screen size.  */
  struct grub_term_coordinate (*getwh) (struct grub_term_output *term);
195

okuji's avatar
okuji committed
196
  /* Get the cursor position. The return value is ((X << 8) | Y).  */
197
  struct grub_term_coordinate (*getxy) (struct grub_term_output *term);
198

okuji's avatar
okuji committed
199
  /* Go to the position (X, Y).  */
200
  void (*gotoxy) (struct grub_term_output *term,
201
		  struct grub_term_coordinate pos);
202

okuji's avatar
okuji committed
203
  /* Clear the screen.  */
204
  void (*cls) (struct grub_term_output *term);
205

okuji's avatar
okuji committed
206
  /* Set the current color to be used */
207 208
  void (*setcolorstate) (struct grub_term_output *term,
			 grub_term_color_state state);
209

okuji's avatar
okuji committed
210
  /* Turn on/off the cursor.  */
211
  void (*setcursor) (struct grub_term_output *term, int on);
okuji's avatar
okuji committed
212

213
  /* Update the screen.  */
214
  void (*refresh) (struct grub_term_output *term);
215

216 217 218
  /* gfxterm only: put in fullscreen mode.  */
  grub_err_t (*fullscreen) (void);

okuji's avatar
okuji committed
219
  /* The feature flags defined above.  */
220
  grub_uint32_t flags;
221

222 223 224 225
  /* Progress data. */
  grub_uint32_t progress_update_divisor;
  grub_uint32_t progress_update_counter;

226
  void *data;
okuji's avatar
okuji committed
227
};
228 229
typedef struct grub_term_output *grub_term_output_t;

230 231 232 233
#define GRUB_TERM_DEFAULT_NORMAL_COLOR 0x07
#define GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR 0x70
#define GRUB_TERM_DEFAULT_STANDARD_COLOR 0x07

234 235 236 237
/* Current color state.  */
extern grub_uint8_t EXPORT_VAR(grub_term_normal_color);
extern grub_uint8_t EXPORT_VAR(grub_term_highlight_color);

238 239
extern struct grub_term_output *EXPORT_VAR(grub_term_outputs_disabled);
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 245
grub_term_register_input (const char *name __attribute__ ((unused)),
			  grub_term_input_t term)
246
{
247 248 249 250 251 252
  if (grub_term_inputs)
    grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
		    GRUB_AS_LIST (term));
  else
    {
      /* 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 259 260 261 262 263 264 265
static inline void
grub_term_register_input_inactive (const char *name __attribute__ ((unused)),
				   grub_term_input_t term)
{
  grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
		  GRUB_AS_LIST (term));
}

266 267 268 269
static inline void
grub_term_register_input_active (const char *name __attribute__ ((unused)),
				 grub_term_input_t term)
{
270
  if (! term->init || term->init (term) == GRUB_ERR_NONE)
271 272 273
    grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
}

274
static inline void
275 276
grub_term_register_output (const char *name __attribute__ ((unused)),
			   grub_term_output_t term)
277
{
278 279 280 281 282 283
  if (grub_term_outputs)
    grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
		    GRUB_AS_LIST (term));
  else
    {
      /* If this is the first terminal, enable automatically.  */
284
      if (! term->init || term->init (term) == GRUB_ERR_NONE)
285 286
	grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
			GRUB_AS_LIST (term));
287
    }
288 289
}

290 291 292 293 294 295 296 297
static inline void
grub_term_register_output_inactive (const char *name __attribute__ ((unused)),
				    grub_term_output_t term)
{
  grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
		  GRUB_AS_LIST (term));
}

298 299 300 301
static inline void
grub_term_register_output_active (const char *name __attribute__ ((unused)),
				  grub_term_output_t term)
{
302
  if (! term->init || term->init (term) == GRUB_ERR_NONE)
303 304 305 306
    grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
		    GRUB_AS_LIST (term));
}

307 308 309
static inline void
grub_term_unregister_input (grub_term_input_t term)
{
310 311
  grub_list_remove (GRUB_AS_LIST (term));
  grub_list_remove (GRUB_AS_LIST (term));
312 313 314 315 316
}

static inline void
grub_term_unregister_output (grub_term_output_t term)
{
317 318
  grub_list_remove (GRUB_AS_LIST (term));
  grub_list_remove (GRUB_AS_LIST (term));
319 320
}

321 322 323 324
#define FOR_ACTIVE_TERM_INPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_inputs))
#define FOR_DISABLED_TERM_INPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_inputs_disabled))
#define FOR_ACTIVE_TERM_OUTPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_outputs))
#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 333
struct grub_term_coordinate *grub_term_save_pos (void);
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
}
okuji's avatar
okuji committed
344

345
static inline struct grub_term_coordinate
346 347
grub_term_getxy (struct grub_term_output *term)
{
348
  return term->getxy (term);
349 350 351 352 353 354
}

static inline void
grub_term_refresh (struct grub_term_output *term)
{
  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 365 366 367 368
}

static inline void 
grub_term_setcolorstate (struct grub_term_output *term, 
			 grub_term_color_state state)
{
  if (term->setcolorstate)
369
    term->setcolorstate (term, state);
370 371
}

372 373 374 375 376 377 378 379 380
static inline void
grub_setcolorstate (grub_term_color_state state)
{
  struct grub_term_output *term;
  
  FOR_ACTIVE_TERM_OUTPUTS(term)
    grub_term_setcolorstate (term, state);
}

381 382 383 384 385
/* Turn on/off the cursor.  */
static inline void 
grub_term_setcursor (struct grub_term_output *term, int on)
{
  if (term->setcursor)
386
    term->setcursor (term, on);
387 388
}

389 390 391 392
static inline void 
grub_term_cls (struct grub_term_output *term)
{
  if (term->cls)
393
    (term->cls) (term);
394 395 396 397 398 399 400
  else
    {
      grub_putcode ('\n', term);
      grub_term_refresh (term);
    }
}

401
#if HAVE_FONT_SOURCE
402

403
grub_size_t
404 405 406 407
grub_unicode_estimate_width (const struct grub_unicode_glyph *c);

#else

408
static inline grub_size_t
409 410 411 412 413 414 415 416 417
grub_unicode_estimate_width (const struct grub_unicode_glyph *c __attribute__ ((unused)))
{
  if (grub_unicode_get_comb_type (c->base))
    return 0;
  return 1;
}

#endif

418 419
#define GRUB_TERM_TAB_WIDTH 8

420
static inline grub_size_t
421 422
grub_term_getcharwidth (struct grub_term_output *term,
			const struct grub_unicode_glyph *c)
423
{
424 425 426
  if (c->base == '\t')
    return GRUB_TERM_TAB_WIDTH;

427
  if (term->getcharwidth)
428
    return term->getcharwidth (term, c);
429 430 431 432 433 434 435
  else if (((term->flags & GRUB_TERM_CODE_TYPE_MASK)
	    == GRUB_TERM_CODE_TYPE_UTF8_LOGICAL)
	   || ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
	       == GRUB_TERM_CODE_TYPE_UTF8_VISUAL)
	   || ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
	       == GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS))
    return grub_unicode_estimate_width (c);
436 437 438 439
  else
    return 1;
}

440 441 442 443 444 445 446 447 448 449
struct grub_term_autoload
{
  struct grub_term_autoload *next;
  char *name;
  char *modname;
};

extern struct grub_term_autoload *grub_term_input_autoload;
extern struct grub_term_autoload *grub_term_output_autoload;

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 461
#define GRUB_TERM_REPEAT_INTERVAL 50

462 463
#endif /* ! ASM_FILE */

464
#endif /* ! GRUB_TERM_HEADER */