~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to term/gfxterm.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  GRUB  --  GRand Unified Bootloader
3
 
 *  Copyright (C) 2006,2007,2008,2009  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
 
#include <grub/term.h>
20
 
#include <grub/types.h>
21
 
#include <grub/dl.h>
22
 
#include <grub/misc.h>
23
 
#include <grub/font.h>
24
 
#include <grub/mm.h>
25
 
#include <grub/env.h>
26
 
#include <grub/video.h>
27
 
#include <grub/gfxterm.h>
28
 
#include <grub/bitmap.h>
29
 
#include <grub/command.h>
30
 
#include <grub/extcmd.h>
31
 
#include <grub/bitmap_scale.h>
32
 
#include <grub/i18n.h>
33
 
 
34
 
#define DEFAULT_VIDEO_MODE      "auto"
35
 
#define DEFAULT_BORDER_WIDTH    10
36
 
 
37
 
#define DEFAULT_STANDARD_COLOR  0x07
38
 
 
39
 
struct grub_dirty_region
40
 
{
41
 
  int top_left_x;
42
 
  int top_left_y;
43
 
  int bottom_right_x;
44
 
  int bottom_right_y;
45
 
};
46
 
 
47
 
struct grub_colored_char
48
 
{
49
 
  /* An Unicode codepoint.  */
50
 
  struct grub_unicode_glyph *code;
51
 
 
52
 
  /* Color values.  */
53
 
  grub_video_color_t fg_color;
54
 
  grub_video_color_t bg_color;
55
 
 
56
 
  /* The width of this character minus one.  */
57
 
  unsigned char width;
58
 
 
59
 
  /* The column index of this character.  */
60
 
  unsigned char index;
61
 
};
62
 
 
63
 
struct grub_virtual_screen
64
 
{
65
 
  /* Dimensions of the virtual screen in pixels.  */
66
 
  unsigned int width;
67
 
  unsigned int height;
68
 
 
69
 
  /* Offset in the display in pixels.  */
70
 
  unsigned int offset_x;
71
 
  unsigned int offset_y;
72
 
 
73
 
  /* TTY Character sizes in pixes.  */
74
 
  unsigned int normal_char_width;
75
 
  unsigned int normal_char_height;
76
 
 
77
 
  /* Virtual screen TTY size in characters.  */
78
 
  unsigned int columns;
79
 
  unsigned int rows;
80
 
 
81
 
  /* Current cursor location in characters.  */
82
 
  unsigned int cursor_x;
83
 
  unsigned int cursor_y;
84
 
 
85
 
  /* Current cursor state. */
86
 
  int cursor_state;
87
 
 
88
 
  /* Font settings. */
89
 
  grub_font_t font;
90
 
 
91
 
  /* Terminal color settings.  */
92
 
  grub_uint8_t standard_color_setting;
93
 
  grub_uint8_t term_color;
94
 
 
95
 
  /* Color settings.  */
96
 
  grub_video_color_t fg_color;
97
 
  grub_video_color_t bg_color;
98
 
  grub_video_color_t bg_color_display;
99
 
 
100
 
  /* Text buffer for virtual screen.  Contains (columns * rows) number
101
 
     of entries.  */
102
 
  struct grub_colored_char *text_buffer;
103
 
 
104
 
  int total_scroll;
105
 
};
106
 
 
107
 
struct grub_gfxterm_window
108
 
{
109
 
  unsigned x;
110
 
  unsigned y;
111
 
  unsigned width;
112
 
  unsigned height;
113
 
  int double_repaint;
114
 
};
115
 
 
116
 
static struct grub_video_render_target *render_target;
117
 
void (*grub_gfxterm_decorator_hook) (void) = NULL;
118
 
static struct grub_gfxterm_window window;
119
 
static struct grub_virtual_screen virtual_screen;
120
 
static grub_gfxterm_repaint_callback_t repaint_callback;
121
 
static int repaint_scheduled = 0;
122
 
static int repaint_was_scheduled = 0;
123
 
 
124
 
static void destroy_window (void);
125
 
 
126
 
static struct grub_video_render_target *text_layer;
127
 
 
128
 
static unsigned int bitmap_width;
129
 
static unsigned int bitmap_height;
130
 
static struct grub_video_bitmap *bitmap;
131
 
 
132
 
static struct grub_dirty_region dirty_region;
133
 
 
134
 
static void dirty_region_reset (void);
135
 
 
136
 
static int dirty_region_is_empty (void);
137
 
 
138
 
static void dirty_region_add (int x, int y,
139
 
                              unsigned int width, unsigned int height);
140
 
 
141
 
static unsigned int calculate_normal_character_width (grub_font_t font);
142
 
 
143
 
static unsigned char calculate_character_width (struct grub_font_glyph *glyph);
144
 
 
145
 
static void grub_gfxterm_refresh (struct grub_term_output *term __attribute__ ((unused)));
146
 
 
147
 
static grub_ssize_t
148
 
grub_gfxterm_getcharwidth (struct grub_term_output *term __attribute__ ((unused)),
149
 
                           const struct grub_unicode_glyph *c);
150
 
 
151
 
static void
152
 
set_term_color (grub_uint8_t term_color)
153
 
{
154
 
  struct grub_video_render_target *old_target;
155
 
 
156
 
  /* Save previous target and switch to text layer.  */
157
 
  grub_video_get_active_render_target (&old_target);
158
 
  grub_video_set_active_render_target (text_layer);
159
 
 
160
 
  /* Map terminal color to text layer compatible video colors.  */
161
 
  virtual_screen.fg_color = grub_video_map_color(term_color & 0x0f);
162
 
 
163
 
  /* Special case: use black as transparent color.  */
164
 
  if (((term_color >> 4) & 0x0f) == 0)
165
 
    {
166
 
      virtual_screen.bg_color = grub_video_map_rgba(0, 0, 0, 0);
167
 
    }
168
 
  else
169
 
    {
170
 
      virtual_screen.bg_color = grub_video_map_color((term_color >> 4) & 0x0f);
171
 
    }
172
 
 
173
 
  /* Restore previous target.  */
174
 
  grub_video_set_active_render_target (old_target);
175
 
}
176
 
 
177
 
static void
178
 
clear_char (struct grub_colored_char *c)
179
 
{
180
 
  grub_free (c->code);
181
 
  c->code = grub_unicode_glyph_from_code (' ');
182
 
  if (!c->code)
183
 
    grub_errno = GRUB_ERR_NONE;
184
 
  c->fg_color = virtual_screen.fg_color;
185
 
  c->bg_color = virtual_screen.bg_color;
186
 
  c->width = 0;
187
 
  c->index = 0;
188
 
}
189
 
 
190
 
static void
191
 
grub_virtual_screen_free (void)
192
 
{
193
 
  /* If virtual screen has been allocated, free it.  */
194
 
  if (virtual_screen.text_buffer != 0)
195
 
    grub_free (virtual_screen.text_buffer);
196
 
 
197
 
  /* Reset virtual screen data.  */
198
 
  grub_memset (&virtual_screen, 0, sizeof (virtual_screen));
199
 
 
200
 
  /* Free render targets.  */
201
 
  grub_video_delete_render_target (text_layer);
202
 
  text_layer = 0;
203
 
}
204
 
 
205
 
static grub_err_t
206
 
grub_virtual_screen_setup (unsigned int x, unsigned int y,
207
 
                           unsigned int width, unsigned int height,
208
 
                           const char *font_name)
209
 
{
210
 
  unsigned int i;
211
 
 
212
 
  /* Free old virtual screen.  */
213
 
  grub_virtual_screen_free ();
214
 
 
215
 
  /* Initialize with default data.  */
216
 
  virtual_screen.font = grub_font_get (font_name);
217
 
  if (!virtual_screen.font)
218
 
    return grub_error (GRUB_ERR_BAD_FONT,
219
 
                       "no font loaded");
220
 
  virtual_screen.width = width;
221
 
  virtual_screen.height = height;
222
 
  virtual_screen.offset_x = x;
223
 
  virtual_screen.offset_y = y;
224
 
  virtual_screen.normal_char_width =
225
 
    calculate_normal_character_width (virtual_screen.font);
226
 
  virtual_screen.normal_char_height =
227
 
    grub_font_get_max_char_height (virtual_screen.font);
228
 
  virtual_screen.cursor_x = 0;
229
 
  virtual_screen.cursor_y = 0;
230
 
  virtual_screen.cursor_state = 1;
231
 
  virtual_screen.total_scroll = 0;
232
 
 
233
 
  /* Calculate size of text buffer.  */
234
 
  virtual_screen.columns = virtual_screen.width / virtual_screen.normal_char_width;
235
 
  virtual_screen.rows = virtual_screen.height / virtual_screen.normal_char_height;
236
 
 
237
 
  /* Allocate memory for text buffer.  */
238
 
  virtual_screen.text_buffer =
239
 
    (struct grub_colored_char *) grub_malloc (virtual_screen.columns
240
 
                                              * virtual_screen.rows
241
 
                                              * sizeof (*virtual_screen.text_buffer));
242
 
  if (grub_errno != GRUB_ERR_NONE)
243
 
    return grub_errno;
244
 
 
245
 
  /* Create new render target for text layer.  */
246
 
  grub_video_create_render_target (&text_layer,
247
 
                                   virtual_screen.width,
248
 
                                   virtual_screen.height,
249
 
                                   GRUB_VIDEO_MODE_TYPE_RGB
250
 
                                   | GRUB_VIDEO_MODE_TYPE_ALPHA);
251
 
  if (grub_errno != GRUB_ERR_NONE)
252
 
    return grub_errno;
253
 
 
254
 
  /* As we want to have colors compatible with rendering target,
255
 
     we can only have those after mode is initialized.  */
256
 
  grub_video_set_active_render_target (text_layer);
257
 
 
258
 
  virtual_screen.standard_color_setting = DEFAULT_STANDARD_COLOR;
259
 
 
260
 
  virtual_screen.term_color = GRUB_TERM_DEFAULT_NORMAL_COLOR;
261
 
 
262
 
  set_term_color (virtual_screen.term_color);
263
 
 
264
 
  grub_video_set_active_render_target (render_target);
265
 
 
266
 
  virtual_screen.bg_color_display = grub_video_map_rgba(0, 0, 0, 0);
267
 
 
268
 
  /* Clear out text buffer. */
269
 
  for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
270
 
    {
271
 
      virtual_screen.text_buffer[i].code = 0;
272
 
      clear_char (&(virtual_screen.text_buffer[i]));
273
 
    }
274
 
 
275
 
  return grub_errno;
276
 
}
277
 
 
278
 
void
279
 
grub_gfxterm_schedule_repaint (void)
280
 
{
281
 
  repaint_scheduled = 1;
282
 
}
283
 
 
284
 
grub_err_t
285
 
grub_gfxterm_set_window (struct grub_video_render_target *target,
286
 
                         int x, int y, int width, int height,
287
 
                         int double_repaint,
288
 
                         const char *font_name, int border_width)
289
 
{
290
 
  /* Clean up any prior instance.  */
291
 
  destroy_window ();
292
 
 
293
 
  /* Set the render target.  */
294
 
  render_target = target;
295
 
 
296
 
  /* Create virtual screen.  */
297
 
  if (grub_virtual_screen_setup (border_width, border_width, 
298
 
                                 width - 2 * border_width, 
299
 
                                 height - 2 * border_width, 
300
 
                                 font_name) 
301
 
      != GRUB_ERR_NONE)
302
 
    {
303
 
      return grub_errno;
304
 
    }
305
 
 
306
 
  /* Set window bounds.  */
307
 
  window.x = x;
308
 
  window.y = y;
309
 
  window.width = width;
310
 
  window.height = height;
311
 
  window.double_repaint = double_repaint;
312
 
 
313
 
  dirty_region_reset ();
314
 
  grub_gfxterm_schedule_repaint ();
315
 
 
316
 
  return grub_errno;
317
 
}
318
 
 
319
 
grub_err_t
320
 
grub_gfxterm_fullscreen (void)
321
 
{
322
 
  const char *font_name;
323
 
  struct grub_video_mode_info mode_info;
324
 
  grub_video_color_t color;
325
 
  grub_err_t err;
326
 
  int double_redraw;
327
 
 
328
 
  err = grub_video_get_info (&mode_info);
329
 
  /* Figure out what mode we ended up.  */
330
 
  if (err)
331
 
    return err;
332
 
 
333
 
  grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
334
 
 
335
 
  double_redraw = mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
336
 
    && !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
337
 
 
338
 
  /* Make sure screen is black.  */
339
 
  color = grub_video_map_rgb (0, 0, 0);
340
 
  grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
341
 
  if (double_redraw)
342
 
    {
343
 
      grub_video_swap_buffers ();
344
 
      grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
345
 
    }
346
 
  bitmap = 0;
347
 
 
348
 
  /* Select the font to use.  */
349
 
  font_name = grub_env_get ("gfxterm_font");
350
 
  if (! font_name)
351
 
    font_name = "";   /* Allow fallback to any font.  */
352
 
 
353
 
  grub_gfxterm_decorator_hook = NULL;
354
 
 
355
 
  return grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY,
356
 
                                  0, 0, mode_info.width, mode_info.height,
357
 
                                  double_redraw,
358
 
                                  font_name, DEFAULT_BORDER_WIDTH);
359
 
}
360
 
 
361
 
static grub_err_t
362
 
grub_gfxterm_term_init (struct grub_term_output *term __attribute__ ((unused)))
363
 
{
364
 
  char *tmp;
365
 
  grub_err_t err;
366
 
  const char *modevar;
367
 
 
368
 
  /* Parse gfxmode environment variable if set.  */
369
 
  modevar = grub_env_get ("gfxmode");
370
 
  if (! modevar || *modevar == 0)
371
 
    err = grub_video_set_mode (DEFAULT_VIDEO_MODE,
372
 
                               GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
373
 
  else
374
 
    {
375
 
      tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
376
 
      if (!tmp)
377
 
        return grub_errno;
378
 
      err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
379
 
      grub_free (tmp);
380
 
    }
381
 
 
382
 
  if (err)
383
 
    return err;
384
 
 
385
 
  err = grub_gfxterm_fullscreen ();
386
 
  if (err)
387
 
    grub_video_restore ();
388
 
 
389
 
  return err;
390
 
}
391
 
 
392
 
static void
393
 
destroy_window (void)
394
 
{
395
 
  if (bitmap)
396
 
    {
397
 
      grub_video_bitmap_destroy (bitmap);
398
 
      bitmap = 0;
399
 
    }
400
 
 
401
 
  repaint_callback = 0;
402
 
  grub_virtual_screen_free ();
403
 
}
404
 
 
405
 
static grub_err_t
406
 
grub_gfxterm_term_fini (struct grub_term_output *term __attribute__ ((unused)))
407
 
{
408
 
  destroy_window ();
409
 
  grub_video_restore ();
410
 
 
411
 
  /* Clear error state.  */
412
 
  grub_errno = GRUB_ERR_NONE;
413
 
  return GRUB_ERR_NONE;
414
 
}
415
 
 
416
 
static void
417
 
redraw_screen_rect (unsigned int x, unsigned int y,
418
 
                    unsigned int width, unsigned int height)
419
 
{
420
 
  grub_video_color_t color;
421
 
  grub_video_rect_t saved_view;
422
 
 
423
 
  grub_video_set_active_render_target (render_target);
424
 
  /* Save viewport and set it to our window.  */
425
 
  grub_video_get_viewport ((unsigned *) &saved_view.x, 
426
 
                           (unsigned *) &saved_view.y, 
427
 
                           (unsigned *) &saved_view.width, 
428
 
                           (unsigned *) &saved_view.height);
429
 
  grub_video_set_viewport (window.x, window.y, window.width, window.height);
430
 
 
431
 
  if (bitmap)
432
 
    {
433
 
      /* Render bitmap as background.  */
434
 
      grub_video_blit_bitmap (bitmap, GRUB_VIDEO_BLIT_REPLACE, x, y,
435
 
                              x, y,
436
 
                              width, height);
437
 
 
438
 
      /* If bitmap is smaller than requested blit area, use background
439
 
         color.  */
440
 
      color = virtual_screen.bg_color_display;
441
 
 
442
 
      /* Fill right side of the bitmap if needed.  */
443
 
      if ((x + width >= bitmap_width) && (y < bitmap_height))
444
 
        {
445
 
          int w = (x + width) - bitmap_width;
446
 
          int h = height;
447
 
          unsigned int tx = x;
448
 
 
449
 
          if (y + height >= bitmap_height)
450
 
            {
451
 
              h = bitmap_height - y;
452
 
            }
453
 
 
454
 
          if (bitmap_width > tx)
455
 
            {
456
 
              tx = bitmap_width;
457
 
            }
458
 
 
459
 
          /* Render background layer.  */
460
 
          grub_video_fill_rect (color, tx, y, w, h);
461
 
        }
462
 
 
463
 
      /* Fill bottom side of the bitmap if needed.  */
464
 
      if (y + height >= bitmap_height)
465
 
        {
466
 
          int h = (y + height) - bitmap_height;
467
 
          unsigned int ty = y;
468
 
 
469
 
          if (bitmap_height > ty)
470
 
            {
471
 
              ty = bitmap_height;
472
 
            }
473
 
 
474
 
          /* Render background layer.  */
475
 
          grub_video_fill_rect (color, x, ty, width, h);
476
 
        }
477
 
 
478
 
      /* Render text layer as blended.  */
479
 
      grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, x, y,
480
 
                                     x - virtual_screen.offset_x,
481
 
                                     y - virtual_screen.offset_y,
482
 
                                     width, height);
483
 
    }
484
 
  else
485
 
    {
486
 
      /* Render background layer.  */
487
 
      color = virtual_screen.bg_color_display;
488
 
      grub_video_fill_rect (color, x, y, width, height);
489
 
 
490
 
      /* Render text layer as replaced (to get texts background color).  */
491
 
      grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_REPLACE, x, y,
492
 
                                     x - virtual_screen.offset_x,
493
 
                                     y - virtual_screen.offset_y,
494
 
                                     width, height);
495
 
    }
496
 
 
497
 
  /* Restore saved viewport.  */
498
 
  grub_video_set_viewport (saved_view.x, saved_view.y,
499
 
                           saved_view.width, saved_view.height);
500
 
  grub_video_set_active_render_target (render_target);
501
 
  
502
 
  if (repaint_callback)
503
 
    repaint_callback (x, y, width, height);
504
 
}
505
 
 
506
 
static void
507
 
dirty_region_reset (void)
508
 
{
509
 
  dirty_region.top_left_x = -1;
510
 
  dirty_region.top_left_y = -1;
511
 
  dirty_region.bottom_right_x = -1;
512
 
  dirty_region.bottom_right_y = -1;
513
 
  repaint_was_scheduled = 0;
514
 
}
515
 
 
516
 
static int
517
 
dirty_region_is_empty (void)
518
 
{
519
 
  if ((dirty_region.top_left_x == -1)
520
 
      || (dirty_region.top_left_y == -1)
521
 
      || (dirty_region.bottom_right_x == -1)
522
 
      || (dirty_region.bottom_right_y == -1))
523
 
    return 1;
524
 
  return 0;
525
 
}
526
 
 
527
 
static void
528
 
dirty_region_add (int x, int y, unsigned int width, unsigned int height)
529
 
{
530
 
  if ((width == 0) || (height == 0))
531
 
    return;
532
 
 
533
 
  if (repaint_scheduled)
534
 
    {
535
 
      x = virtual_screen.offset_x;
536
 
      y = virtual_screen.offset_y;
537
 
      width = virtual_screen.width;
538
 
      height = virtual_screen.height;
539
 
      repaint_scheduled = 0;
540
 
      repaint_was_scheduled = 1;
541
 
    }
542
 
 
543
 
  if (dirty_region_is_empty ())
544
 
    {
545
 
      dirty_region.top_left_x = x;
546
 
      dirty_region.top_left_y = y;
547
 
      dirty_region.bottom_right_x = x + width - 1;
548
 
      dirty_region.bottom_right_y = y + height - 1;
549
 
    }
550
 
  else
551
 
    {
552
 
      if (x < dirty_region.top_left_x)
553
 
        dirty_region.top_left_x = x;
554
 
      if (y < dirty_region.top_left_y)
555
 
        dirty_region.top_left_y = y;
556
 
      if ((x + (int)width - 1) > dirty_region.bottom_right_x)
557
 
        dirty_region.bottom_right_x = x + width - 1;
558
 
      if ((y + (int)height - 1) > dirty_region.bottom_right_y)
559
 
        dirty_region.bottom_right_y = y + height - 1;
560
 
    }
561
 
}
562
 
 
563
 
static void
564
 
dirty_region_add_virtualscreen (void)
565
 
{
566
 
  /* Mark virtual screen as dirty.  */
567
 
  dirty_region_add (virtual_screen.offset_x, virtual_screen.offset_y,
568
 
                    virtual_screen.width, virtual_screen.height);
569
 
}
570
 
 
571
 
 
572
 
static void
573
 
dirty_region_redraw (void)
574
 
{
575
 
  int x;
576
 
  int y;
577
 
  int width;
578
 
  int height;
579
 
 
580
 
  if (dirty_region_is_empty ())
581
 
    return;
582
 
 
583
 
  x = dirty_region.top_left_x;
584
 
  y = dirty_region.top_left_y;
585
 
 
586
 
  width = dirty_region.bottom_right_x - x + 1;
587
 
  height = dirty_region.bottom_right_y - y + 1;
588
 
 
589
 
  if (repaint_was_scheduled && grub_gfxterm_decorator_hook)
590
 
    grub_gfxterm_decorator_hook ();
591
 
 
592
 
  redraw_screen_rect (x, y, width, height);
593
 
}
594
 
 
595
 
static inline void
596
 
paint_char (unsigned cx, unsigned cy)
597
 
{
598
 
  struct grub_colored_char *p;
599
 
  struct grub_font_glyph *glyph;
600
 
  grub_video_color_t color;
601
 
  grub_video_color_t bgcolor;
602
 
  unsigned int x;
603
 
  unsigned int y;
604
 
  int ascent;
605
 
  unsigned int height;
606
 
  unsigned int width;
607
 
 
608
 
  if (cy + virtual_screen.total_scroll >= virtual_screen.rows)
609
 
    return;
610
 
 
611
 
  /* Find out active character.  */
612
 
  p = (virtual_screen.text_buffer
613
 
       + cx + (cy * virtual_screen.columns));
614
 
 
615
 
  p -= p->index;
616
 
 
617
 
  /* Get glyph for character.  */
618
 
  glyph = grub_font_construct_glyph (virtual_screen.font, p->code);
619
 
  if (!glyph)
620
 
    {
621
 
      grub_errno = GRUB_ERR_NONE;
622
 
      return;
623
 
    }
624
 
  ascent = grub_font_get_ascent (virtual_screen.font);
625
 
 
626
 
  width = virtual_screen.normal_char_width * calculate_character_width(glyph);
627
 
  height = virtual_screen.normal_char_height;
628
 
 
629
 
  color = p->fg_color;
630
 
  bgcolor = p->bg_color;
631
 
 
632
 
  x = cx * virtual_screen.normal_char_width;
633
 
  y = (cy + virtual_screen.total_scroll) * virtual_screen.normal_char_height;
634
 
 
635
 
  /* Render glyph to text layer.  */
636
 
  grub_video_set_active_render_target (text_layer);
637
 
  grub_video_fill_rect (bgcolor, x, y, width, height);
638
 
  grub_font_draw_glyph (glyph, color, x, y + ascent);
639
 
  grub_video_set_active_render_target (render_target);
640
 
 
641
 
  /* Mark character to be drawn.  */
642
 
  dirty_region_add (virtual_screen.offset_x + x, virtual_screen.offset_y + y,
643
 
                    width, height);
644
 
  grub_free (glyph);
645
 
}
646
 
 
647
 
static inline void
648
 
write_char (void)
649
 
{
650
 
  paint_char (virtual_screen.cursor_x, virtual_screen.cursor_y);
651
 
}
652
 
 
653
 
static inline void
654
 
draw_cursor (int show)
655
 
{
656
 
  unsigned int x;
657
 
  unsigned int y;
658
 
  unsigned int width;
659
 
  unsigned int height;
660
 
  grub_video_color_t color;
661
 
  
662
 
  write_char ();
663
 
 
664
 
  if (!show)
665
 
    return;
666
 
 
667
 
  if (virtual_screen.cursor_y + virtual_screen.total_scroll
668
 
      >= virtual_screen.rows)
669
 
    return;
670
 
 
671
 
  /* Determine cursor properties and position on text layer. */
672
 
  x = virtual_screen.cursor_x * virtual_screen.normal_char_width;
673
 
  width = virtual_screen.normal_char_width;
674
 
  color = virtual_screen.fg_color;
675
 
  y = ((virtual_screen.cursor_y + virtual_screen.total_scroll)
676
 
       * virtual_screen.normal_char_height
677
 
       + grub_font_get_ascent (virtual_screen.font));
678
 
  height = 2;
679
 
  
680
 
  /* Render cursor to text layer.  */
681
 
  grub_video_set_active_render_target (text_layer);
682
 
  grub_video_fill_rect (color, x, y, width, height);
683
 
  grub_video_set_active_render_target (render_target);
684
 
  
685
 
  /* Mark cursor to be redrawn.  */
686
 
  dirty_region_add (virtual_screen.offset_x + x,
687
 
                    virtual_screen.offset_y + y,
688
 
                    width, height);
689
 
}
690
 
 
691
 
static void
692
 
real_scroll (void)
693
 
{
694
 
  unsigned int i, j, was_scroll;
695
 
  grub_video_color_t color;
696
 
 
697
 
  if (!virtual_screen.total_scroll)
698
 
    return;
699
 
 
700
 
  /* If we have bitmap, re-draw screen, otherwise scroll physical screen too.  */
701
 
  if (bitmap)
702
 
    {
703
 
      /* Scroll physical screen.  */
704
 
      grub_video_set_active_render_target (text_layer);
705
 
      color = virtual_screen.bg_color;
706
 
      grub_video_scroll (color, 0, -virtual_screen.normal_char_height
707
 
                         * virtual_screen.total_scroll);
708
 
 
709
 
      /* Mark virtual screen to be redrawn.  */
710
 
      dirty_region_add_virtualscreen ();
711
 
    }
712
 
  else
713
 
    {
714
 
      grub_video_rect_t saved_view;
715
 
 
716
 
      /* Remove cursor.  */
717
 
      draw_cursor (0);
718
 
 
719
 
      grub_video_set_active_render_target (render_target);
720
 
 
721
 
      i = window.double_repaint ? 2 : 1;
722
 
 
723
 
      color = virtual_screen.bg_color;
724
 
 
725
 
      while (i--)
726
 
        {
727
 
          /* Save viewport and set it to our window.  */
728
 
          grub_video_get_viewport ((unsigned *) &saved_view.x, 
729
 
                                   (unsigned *) &saved_view.y, 
730
 
                                   (unsigned *) &saved_view.width, 
731
 
                                   (unsigned *) &saved_view.height);
732
 
 
733
 
          grub_video_set_viewport (window.x, window.y, window.width,
734
 
                                   window.height);
735
 
 
736
 
          /* Clear new border area.  */
737
 
          grub_video_fill_rect (color,
738
 
                                virtual_screen.offset_x,
739
 
                                virtual_screen.offset_y,
740
 
                                virtual_screen.width,
741
 
                                virtual_screen.normal_char_height
742
 
                                * virtual_screen.total_scroll);
743
 
 
744
 
          grub_video_set_active_render_target (render_target);
745
 
          dirty_region_redraw ();
746
 
 
747
 
          /* Scroll physical screen.  */
748
 
          grub_video_scroll (color, 0, -virtual_screen.normal_char_height
749
 
                             * virtual_screen.total_scroll);
750
 
 
751
 
          /* Restore saved viewport.  */
752
 
          grub_video_set_viewport (saved_view.x, saved_view.y,
753
 
                                   saved_view.width, saved_view.height);
754
 
 
755
 
          if (i)
756
 
            grub_video_swap_buffers ();
757
 
        }
758
 
      dirty_region_reset ();
759
 
 
760
 
      /* Scroll physical screen.  */
761
 
      grub_video_set_active_render_target (text_layer);
762
 
      color = virtual_screen.bg_color;
763
 
      grub_video_scroll (color, 0, -virtual_screen.normal_char_height
764
 
                         * virtual_screen.total_scroll);
765
 
 
766
 
      grub_video_set_active_render_target (render_target);
767
 
 
768
 
    }
769
 
 
770
 
  was_scroll = virtual_screen.total_scroll;
771
 
  virtual_screen.total_scroll = 0;
772
 
 
773
 
  if (was_scroll > virtual_screen.rows)
774
 
    was_scroll = virtual_screen.rows;
775
 
 
776
 
  /* Draw shadow part.  */
777
 
  for (i = virtual_screen.rows - was_scroll;
778
 
       i < virtual_screen.rows; i++)
779
 
    for (j = 0; j < virtual_screen.columns; j++)
780
 
      paint_char (j, i);
781
 
 
782
 
  /* Draw cursor if visible.  */
783
 
  if (virtual_screen.cursor_state)
784
 
    draw_cursor (1);
785
 
 
786
 
  if (repaint_callback)
787
 
    repaint_callback (window.x, window.y, window.width, window.height);
788
 
}
789
 
 
790
 
static void
791
 
scroll_up (void)
792
 
{
793
 
  unsigned int i;
794
 
 
795
 
  /* Clear first line in text buffer.  */
796
 
  for (i = 0;
797
 
       i < virtual_screen.columns;
798
 
       i++)
799
 
    {
800
 
      virtual_screen.text_buffer[i].code = 0;
801
 
      clear_char (&(virtual_screen.text_buffer[i]));
802
 
    }
803
 
 
804
 
  /* Scroll text buffer with one line to up.  */
805
 
  grub_memmove (virtual_screen.text_buffer,
806
 
                virtual_screen.text_buffer + virtual_screen.columns,
807
 
                sizeof (*virtual_screen.text_buffer)
808
 
                * virtual_screen.columns
809
 
                * (virtual_screen.rows - 1));
810
 
 
811
 
  /* Clear last line in text buffer.  */
812
 
  for (i = virtual_screen.columns * (virtual_screen.rows - 1);
813
 
       i < virtual_screen.columns * virtual_screen.rows;
814
 
       i++)
815
 
    {
816
 
      virtual_screen.text_buffer[i].code = 0;
817
 
      clear_char (&(virtual_screen.text_buffer[i]));
818
 
    }
819
 
 
820
 
  virtual_screen.total_scroll++;
821
 
}
822
 
 
823
 
static void
824
 
grub_gfxterm_putchar (struct grub_term_output *term,
825
 
                      const struct grub_unicode_glyph *c)
826
 
{
827
 
  if (c->base == '\a')
828
 
    /* FIXME */
829
 
    return;
830
 
 
831
 
  /* Erase current cursor, if any.  */
832
 
  if (virtual_screen.cursor_state)
833
 
    draw_cursor (0);
834
 
 
835
 
  if (c->base == '\b' || c->base == '\n' || c->base == '\r')
836
 
    {
837
 
      switch (c->base)
838
 
        {
839
 
        case '\b':
840
 
          if (virtual_screen.cursor_x > 0)
841
 
            virtual_screen.cursor_x--;
842
 
          break;
843
 
 
844
 
        case '\n':
845
 
          if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
846
 
            scroll_up ();
847
 
          else
848
 
            virtual_screen.cursor_y++;
849
 
          break;
850
 
 
851
 
        case '\r':
852
 
          virtual_screen.cursor_x = 0;
853
 
          break;
854
 
        }
855
 
    }
856
 
  else
857
 
    {
858
 
      struct grub_colored_char *p;
859
 
      unsigned char char_width;
860
 
 
861
 
      /* Calculate actual character width for glyph. This is number of
862
 
         times of normal_font_width.  */
863
 
      char_width = grub_gfxterm_getcharwidth (term, c);
864
 
 
865
 
      /* If we are about to exceed line length, wrap to next line.  */
866
 
      if (virtual_screen.cursor_x + char_width > virtual_screen.columns)
867
 
        {
868
 
          if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
869
 
            scroll_up ();
870
 
          else
871
 
            virtual_screen.cursor_y++;
872
 
        }
873
 
 
874
 
      /* Find position on virtual screen, and fill information.  */
875
 
      p = (virtual_screen.text_buffer +
876
 
           virtual_screen.cursor_x +
877
 
           virtual_screen.cursor_y * virtual_screen.columns);
878
 
      grub_free (p->code);
879
 
      p->code = grub_unicode_glyph_dup (c);
880
 
      if (!p->code)
881
 
        grub_errno = GRUB_ERR_NONE;
882
 
      p->fg_color = virtual_screen.fg_color;
883
 
      p->bg_color = virtual_screen.bg_color;
884
 
      p->width = char_width - 1;
885
 
      p->index = 0;
886
 
 
887
 
      /* If we have large glyph, add fixup info.  */
888
 
      if (char_width > 1)
889
 
        {
890
 
          unsigned i;
891
 
 
892
 
          for (i = 1; i < char_width; i++)
893
 
            {
894
 
              grub_free (p[i].code);
895
 
              p[i].code = grub_unicode_glyph_from_code (' ');
896
 
              if (!p[i].code)
897
 
                grub_errno = GRUB_ERR_NONE;
898
 
              p[i].width = char_width - 1;
899
 
              p[i].index = i;
900
 
            }
901
 
        }
902
 
 
903
 
      /* Draw glyph.  */
904
 
      write_char ();
905
 
 
906
 
      /* Make sure we scroll screen when needed and wrap line correctly.  */
907
 
      virtual_screen.cursor_x += char_width;
908
 
      if (virtual_screen.cursor_x >= virtual_screen.columns)
909
 
        {
910
 
          virtual_screen.cursor_x = 0;
911
 
 
912
 
          if (virtual_screen.cursor_y >= virtual_screen.rows - 1)
913
 
            scroll_up ();
914
 
          else
915
 
            virtual_screen.cursor_y++;
916
 
        }
917
 
    }
918
 
 
919
 
  /* Redraw cursor if it should be visible.  */
920
 
  /* Note: This will redraw the character as well, which means that the
921
 
     above call to write_char is redundant when the cursor is showing.  */
922
 
  if (virtual_screen.cursor_state)
923
 
    draw_cursor (1);
924
 
}
925
 
 
926
 
/* Use ASCII characters to determine normal character width.  */
927
 
static unsigned int
928
 
calculate_normal_character_width (grub_font_t font)
929
 
{
930
 
  struct grub_font_glyph *glyph;
931
 
  unsigned int width = 0;
932
 
  unsigned int i;
933
 
 
934
 
  /* Get properties of every printable ASCII character.  */
935
 
  for (i = 32; i < 127; i++)
936
 
    {
937
 
      glyph = grub_font_get_glyph (font, i);
938
 
 
939
 
      /* Skip unknown characters.  Should never happen on normal conditions.  */
940
 
      if (! glyph)
941
 
        continue;
942
 
 
943
 
      if (glyph->device_width > width)
944
 
        width = glyph->device_width;
945
 
    }
946
 
 
947
 
  return width;
948
 
}
949
 
 
950
 
static unsigned char
951
 
calculate_character_width (struct grub_font_glyph *glyph)
952
 
{
953
 
  if (! glyph || glyph->device_width == 0)
954
 
    return 1;
955
 
 
956
 
  return (glyph->device_width
957
 
          + (virtual_screen.normal_char_width - 1))
958
 
         / virtual_screen.normal_char_width;
959
 
}
960
 
 
961
 
static grub_ssize_t
962
 
grub_gfxterm_getcharwidth (struct grub_term_output *term __attribute__ ((unused)),
963
 
                           const struct grub_unicode_glyph *c)
964
 
{
965
 
  int dev_width;
966
 
  dev_width = grub_font_get_constructed_device_width (virtual_screen.font, c);
967
 
 
968
 
  if (dev_width == 0)
969
 
    return 1;
970
 
 
971
 
  return (dev_width + (virtual_screen.normal_char_width - 1))
972
 
    / virtual_screen.normal_char_width;
973
 
}
974
 
 
975
 
static grub_uint16_t
976
 
grub_virtual_screen_getwh (struct grub_term_output *term __attribute__ ((unused)))
977
 
{
978
 
  return (virtual_screen.columns << 8) | virtual_screen.rows;
979
 
}
980
 
 
981
 
static grub_uint16_t
982
 
grub_virtual_screen_getxy (struct grub_term_output *term __attribute__ ((unused)))
983
 
{
984
 
  return ((virtual_screen.cursor_x << 8) | virtual_screen.cursor_y);
985
 
}
986
 
 
987
 
static void
988
 
grub_gfxterm_gotoxy (struct grub_term_output *term __attribute__ ((unused)),
989
 
                     grub_uint8_t x, grub_uint8_t y)
990
 
{
991
 
  if (x >= virtual_screen.columns)
992
 
    x = virtual_screen.columns - 1;
993
 
 
994
 
  if (y >= virtual_screen.rows)
995
 
    y = virtual_screen.rows - 1;
996
 
 
997
 
  /* Erase current cursor, if any.  */
998
 
  if (virtual_screen.cursor_state)
999
 
    draw_cursor (0);
1000
 
 
1001
 
  virtual_screen.cursor_x = x;
1002
 
  virtual_screen.cursor_y = y;
1003
 
 
1004
 
  /* Draw cursor if visible.  */
1005
 
  if (virtual_screen.cursor_state)
1006
 
    draw_cursor (1);
1007
 
}
1008
 
 
1009
 
static void
1010
 
grub_virtual_screen_cls (struct grub_term_output *term __attribute__ ((unused)))
1011
 
{
1012
 
  grub_uint32_t i;
1013
 
 
1014
 
  for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++)
1015
 
    clear_char (&(virtual_screen.text_buffer[i]));
1016
 
 
1017
 
  virtual_screen.cursor_x = virtual_screen.cursor_y = 0;
1018
 
}
1019
 
 
1020
 
static void
1021
 
grub_gfxterm_cls (struct grub_term_output *term)
1022
 
{
1023
 
  grub_video_color_t color;
1024
 
 
1025
 
  /* Clear virtual screen.  */
1026
 
  grub_virtual_screen_cls (term);
1027
 
 
1028
 
  /* Clear text layer.  */
1029
 
  grub_video_set_active_render_target (text_layer);
1030
 
  color = virtual_screen.bg_color;
1031
 
  grub_video_fill_rect (color, 0, 0,
1032
 
                        virtual_screen.width, virtual_screen.height);
1033
 
  grub_video_set_active_render_target (render_target);
1034
 
 
1035
 
  /* Mark virtual screen to be redrawn.  */
1036
 
  dirty_region_add_virtualscreen ();
1037
 
 
1038
 
  grub_gfxterm_refresh (term);
1039
 
}
1040
 
 
1041
 
static void
1042
 
grub_virtual_screen_setcolorstate (struct grub_term_output *term,
1043
 
                                   grub_term_color_state state)
1044
 
{
1045
 
  switch (state)
1046
 
    {
1047
 
    case GRUB_TERM_COLOR_STANDARD:
1048
 
      virtual_screen.term_color = virtual_screen.standard_color_setting;
1049
 
      break;
1050
 
 
1051
 
    case GRUB_TERM_COLOR_NORMAL:
1052
 
      virtual_screen.term_color = term->normal_color;
1053
 
      break;
1054
 
 
1055
 
    case GRUB_TERM_COLOR_HIGHLIGHT:
1056
 
      virtual_screen.term_color = term->highlight_color;
1057
 
      break;
1058
 
 
1059
 
    default:
1060
 
      break;
1061
 
    }
1062
 
 
1063
 
  /* Change color to virtual terminal.  */
1064
 
  set_term_color (virtual_screen.term_color);
1065
 
}
1066
 
 
1067
 
static void
1068
 
grub_gfxterm_setcursor (struct grub_term_output *term __attribute__ ((unused)),
1069
 
                        int on)
1070
 
{
1071
 
  if (virtual_screen.cursor_state != on)
1072
 
    {
1073
 
      if (virtual_screen.cursor_state)
1074
 
        draw_cursor (0);
1075
 
      else
1076
 
        draw_cursor (1);
1077
 
 
1078
 
      virtual_screen.cursor_state = on;
1079
 
    }
1080
 
}
1081
 
 
1082
 
static void
1083
 
grub_gfxterm_refresh (struct grub_term_output *term __attribute__ ((unused)))
1084
 
{
1085
 
  real_scroll ();
1086
 
 
1087
 
  /* Redraw only changed regions.  */
1088
 
  dirty_region_redraw ();
1089
 
 
1090
 
  grub_video_swap_buffers ();
1091
 
 
1092
 
  if (window.double_repaint)
1093
 
    dirty_region_redraw ();
1094
 
  dirty_region_reset ();
1095
 
}
1096
 
 
1097
 
void 
1098
 
grub_gfxterm_set_repaint_callback (grub_gfxterm_repaint_callback_t func)
1099
 
{
1100
 
  repaint_callback = func;
1101
 
}
1102
 
 
1103
 
/* Option array indices.  */
1104
 
#define BACKGROUND_CMD_ARGINDEX_MODE 0
1105
 
 
1106
 
static const struct grub_arg_option background_image_cmd_options[] =
1107
 
  {
1108
 
    {"mode", 'm', 0, "Background image mode.", "stretch|normal",
1109
 
     ARG_TYPE_STRING},
1110
 
    {0, 0, 0, 0, 0, 0}
1111
 
  };
1112
 
 
1113
 
static grub_err_t
1114
 
grub_gfxterm_background_image_cmd (grub_extcmd_t cmd __attribute__ ((unused)),
1115
 
                                   int argc,
1116
 
                                   char **args)
1117
 
{
1118
 
  struct grub_arg_list *state = cmd->state;
1119
 
 
1120
 
  /* Check that we have video adapter active.  */
1121
 
  if (grub_video_get_info(NULL) != GRUB_ERR_NONE)
1122
 
    return grub_errno;
1123
 
 
1124
 
  /* Destroy existing background bitmap if loaded.  */
1125
 
  if (bitmap)
1126
 
    {
1127
 
      grub_video_bitmap_destroy (bitmap);
1128
 
      bitmap = 0;
1129
 
 
1130
 
      /* Mark whole screen as dirty.  */
1131
 
      dirty_region_add (0, 0, window.width, window.height);
1132
 
    }
1133
 
 
1134
 
  /* If filename was provided, try to load that.  */
1135
 
  if (argc >= 1)
1136
 
    {
1137
 
      /* Try to load new one.  */
1138
 
      grub_video_bitmap_load (&bitmap, args[0]);
1139
 
      if (grub_errno != GRUB_ERR_NONE)
1140
 
        return grub_errno;
1141
 
 
1142
 
      /* Determine if the bitmap should be scaled to fit the screen.  */
1143
 
      if (!state[BACKGROUND_CMD_ARGINDEX_MODE].set
1144
 
          || grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_MODE].arg,
1145
 
                          "stretch") == 0)
1146
 
          {
1147
 
            if (window.width != grub_video_bitmap_get_width (bitmap)
1148
 
                || window.height != grub_video_bitmap_get_height (bitmap))
1149
 
              {
1150
 
                struct grub_video_bitmap *scaled_bitmap;
1151
 
                grub_video_bitmap_create_scaled (&scaled_bitmap,
1152
 
                                                 window.width, 
1153
 
                                                 window.height,
1154
 
                                                 bitmap,
1155
 
                                                 GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
1156
 
                if (grub_errno == GRUB_ERR_NONE)
1157
 
                  {
1158
 
                    /* Replace the original bitmap with the scaled one.  */
1159
 
                    grub_video_bitmap_destroy (bitmap);
1160
 
                    bitmap = scaled_bitmap;
1161
 
                  }
1162
 
              }
1163
 
          }
1164
 
 
1165
 
      /* If bitmap was loaded correctly, display it.  */
1166
 
      if (bitmap)
1167
 
        {
1168
 
          /* Determine bitmap dimensions.  */
1169
 
          bitmap_width = grub_video_bitmap_get_width (bitmap);
1170
 
          bitmap_height = grub_video_bitmap_get_height (bitmap);
1171
 
 
1172
 
          /* Mark whole screen as dirty.  */
1173
 
          dirty_region_add (0, 0, window.width, window.height);
1174
 
        }
1175
 
    }
1176
 
 
1177
 
  /* All was ok.  */
1178
 
  grub_errno = GRUB_ERR_NONE;
1179
 
  return grub_errno;
1180
 
}
1181
 
 
1182
 
static struct grub_term_output grub_video_term =
1183
 
  {
1184
 
    .name = "gfxterm",
1185
 
    .init = grub_gfxterm_term_init,
1186
 
    .fini = grub_gfxterm_term_fini,
1187
 
    .putchar = grub_gfxterm_putchar,
1188
 
    .getcharwidth = grub_gfxterm_getcharwidth,
1189
 
    .getwh = grub_virtual_screen_getwh,
1190
 
    .getxy = grub_virtual_screen_getxy,
1191
 
    .gotoxy = grub_gfxterm_gotoxy,
1192
 
    .cls = grub_gfxterm_cls,
1193
 
    .setcolorstate = grub_virtual_screen_setcolorstate,
1194
 
    .setcursor = grub_gfxterm_setcursor,
1195
 
    .refresh = grub_gfxterm_refresh,
1196
 
    .flags = GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS,
1197
 
    .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
1198
 
    .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
1199
 
    .next = 0
1200
 
  };
1201
 
 
1202
 
static grub_extcmd_t background_image_cmd_handle;
1203
 
 
1204
 
GRUB_MOD_INIT(gfxterm)
1205
 
{
1206
 
  grub_term_register_output ("gfxterm", &grub_video_term);
1207
 
  background_image_cmd_handle =
1208
 
    grub_register_extcmd ("background_image",
1209
 
                          grub_gfxterm_background_image_cmd,
1210
 
                          GRUB_COMMAND_FLAG_BOTH,
1211
 
                          N_("[-m (stretch|normal)] FILE"),
1212
 
                          N_("Load background image for active terminal."),
1213
 
                          background_image_cmd_options);
1214
 
}
1215
 
 
1216
 
GRUB_MOD_FINI(gfxterm)
1217
 
{
1218
 
  grub_unregister_extcmd (background_image_cmd_handle);
1219
 
  grub_term_unregister_output (&grub_video_term);
1220
 
}