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

« back to all changes in this revision

Viewing changes to gfxmenu/icon_manager.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* icon_manager.c - gfxmenu icon manager.  */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 2008,2009  Free Software Foundation, Inc.
5
 
 *
6
 
 *  GRUB is free software: you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation, either version 3 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  GRUB is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include <grub/types.h>
21
 
#include <grub/misc.h>
22
 
#include <grub/mm.h>
23
 
#include <grub/err.h>
24
 
#include <grub/gui_string_util.h>
25
 
#include <grub/bitmap.h>
26
 
#include <grub/bitmap_scale.h>
27
 
#include <grub/menu.h>
28
 
#include <grub/icon_manager.h>
29
 
#include <grub/env.h>
30
 
 
31
 
/* Currently hard coded to '.png' extension.  */
32
 
static const char icon_extension[] = ".png";
33
 
 
34
 
typedef struct icon_entry
35
 
{
36
 
  char *class_name;
37
 
  struct grub_video_bitmap *bitmap;
38
 
  struct icon_entry *next;
39
 
} *icon_entry_t;
40
 
 
41
 
struct grub_gfxmenu_icon_manager
42
 
{
43
 
  char *theme_path;
44
 
  int icon_width;
45
 
  int icon_height;
46
 
 
47
 
  /* Icon cache: linked list w/ dummy head node.  */
48
 
  struct icon_entry cache;
49
 
};
50
 
 
51
 
 
52
 
/* Create a new icon manager and return a point to it.  */
53
 
grub_gfxmenu_icon_manager_t
54
 
grub_gfxmenu_icon_manager_new (void)
55
 
{
56
 
  grub_gfxmenu_icon_manager_t mgr;
57
 
  mgr = grub_malloc (sizeof (*mgr));
58
 
  if (! mgr)
59
 
    return 0;
60
 
 
61
 
  mgr->theme_path = 0;
62
 
  mgr->icon_width = 0;
63
 
  mgr->icon_height = 0;
64
 
 
65
 
  /* Initialize the dummy head node.  */
66
 
  mgr->cache.class_name = 0;
67
 
  mgr->cache.bitmap = 0;
68
 
  mgr->cache.next = 0;
69
 
 
70
 
  return mgr;
71
 
}
72
 
 
73
 
/* Destroy the icon manager MGR, freeing all resources used by it.
74
 
 
75
 
Note: Any bitmaps returned by grub_gfxmenu_icon_manager_get_icon()
76
 
are destroyed and must not be used by the caller after this function
77
 
is called.  */
78
 
void
79
 
grub_gfxmenu_icon_manager_destroy (grub_gfxmenu_icon_manager_t mgr)
80
 
{
81
 
  grub_gfxmenu_icon_manager_clear_cache (mgr);
82
 
  grub_free (mgr->theme_path);
83
 
  grub_free (mgr);
84
 
}
85
 
 
86
 
/* Clear the icon cache.  */
87
 
void
88
 
grub_gfxmenu_icon_manager_clear_cache (grub_gfxmenu_icon_manager_t mgr)
89
 
{
90
 
  icon_entry_t cur;
91
 
  icon_entry_t next;
92
 
  for (cur = mgr->cache.next; cur; cur = next)
93
 
    {
94
 
      next = cur->next;
95
 
      grub_free (cur->class_name);
96
 
      grub_video_bitmap_destroy (cur->bitmap);
97
 
      grub_free (cur);
98
 
    }
99
 
  mgr->cache.next = 0;
100
 
}
101
 
 
102
 
/* Set the theme path.  If the theme path is changed, the icon cache
103
 
   is cleared.  */
104
 
void
105
 
grub_gfxmenu_icon_manager_set_theme_path (grub_gfxmenu_icon_manager_t mgr,
106
 
                                          const char *path)
107
 
{
108
 
  /* Clear the cache if the theme path has changed.  */
109
 
  if (((mgr->theme_path == 0) != (path == 0))
110
 
      || (grub_strcmp (mgr->theme_path, path) != 0))
111
 
    grub_gfxmenu_icon_manager_clear_cache (mgr);
112
 
 
113
 
  grub_free (mgr->theme_path);
114
 
  mgr->theme_path = path ? grub_strdup (path) : 0;
115
 
}
116
 
 
117
 
/* Set the icon size.  When icons are requested from the icon manager,
118
 
   they are scaled to this size before being returned.  If the size is
119
 
   changed, the icon cache is cleared.  */
120
 
void
121
 
grub_gfxmenu_icon_manager_set_icon_size (grub_gfxmenu_icon_manager_t mgr,
122
 
                                         int width, int height)
123
 
{
124
 
  /* If the width or height is changed, we must clear the cache, since the
125
 
     scaled bitmaps are stored in the cache.  */
126
 
  if (width != mgr->icon_width || height != mgr->icon_height)
127
 
    grub_gfxmenu_icon_manager_clear_cache (mgr);
128
 
 
129
 
  mgr->icon_width = width;
130
 
  mgr->icon_height = height;
131
 
}
132
 
 
133
 
/* Try to load an icon for the specified CLASS_NAME in the directory DIR.
134
 
   Returns 0 if the icon could not be loaded, or returns a pointer to a new
135
 
   bitmap if it was successful.  */
136
 
static struct grub_video_bitmap *
137
 
try_loading_icon (grub_gfxmenu_icon_manager_t mgr,
138
 
                  const char *dir, const char *class_name)
139
 
{
140
 
  char *path;
141
 
  int l;
142
 
 
143
 
  path = grub_malloc (grub_strlen (dir) + grub_strlen (class_name)
144
 
                      + grub_strlen (icon_extension) + 3);
145
 
  if (! path)
146
 
    return 0;
147
 
 
148
 
  grub_strcpy (path, dir);
149
 
  l = grub_strlen (path);
150
 
  if (path[l-1] != '/')
151
 
    {
152
 
      path[l] = '/';
153
 
      path[l+1] = 0;
154
 
    }
155
 
  grub_strcat (path, class_name);
156
 
  grub_strcat (path, icon_extension);
157
 
 
158
 
  struct grub_video_bitmap *raw_bitmap;
159
 
  grub_video_bitmap_load (&raw_bitmap, path);
160
 
  grub_free (path);
161
 
  grub_errno = GRUB_ERR_NONE;  /* Critical to clear the error!!  */
162
 
  if (! raw_bitmap)
163
 
    return 0;
164
 
 
165
 
  struct grub_video_bitmap *scaled_bitmap;
166
 
  grub_video_bitmap_create_scaled (&scaled_bitmap,
167
 
                                   mgr->icon_width, mgr->icon_height,
168
 
                                   raw_bitmap,
169
 
                                   GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST);
170
 
  grub_video_bitmap_destroy (raw_bitmap);
171
 
  if (! scaled_bitmap)
172
 
    {
173
 
      grub_error_push ();
174
 
      grub_error (grub_errno, "failed to scale icon");
175
 
      return 0;
176
 
    }
177
 
 
178
 
  return scaled_bitmap;
179
 
}
180
 
 
181
 
/* Get the icon for the specified class CLASS_NAME.  If an icon for
182
 
   CLASS_NAME already exists in the cache, then a reference to the cached
183
 
   bitmap is returned.  If it is not cached, then it is loaded and cached.
184
 
   If no icon could be could for CLASS_NAME, then 0 is returned.  */
185
 
static struct grub_video_bitmap *
186
 
get_icon_by_class (grub_gfxmenu_icon_manager_t mgr, const char *class_name)
187
 
{
188
 
  /* First check the icon cache.  */
189
 
  icon_entry_t entry;
190
 
  for (entry = mgr->cache.next; entry; entry = entry->next)
191
 
    {
192
 
      if (grub_strcmp (entry->class_name, class_name) == 0)
193
 
        return entry->bitmap;
194
 
    }
195
 
 
196
 
  if (! mgr->theme_path)
197
 
    return 0;
198
 
 
199
 
  /* Otherwise, we search for an icon to load.  */
200
 
  char *theme_dir = grub_get_dirname (mgr->theme_path);
201
 
  char *icons_dir;
202
 
  struct grub_video_bitmap *icon;
203
 
  icon = 0;
204
 
  /* First try the theme's own icons, from "grub/themes/NAME/icons/"  */
205
 
  icons_dir = grub_resolve_relative_path (theme_dir, "icons/");
206
 
  if (icons_dir)
207
 
    {
208
 
      icon = try_loading_icon (mgr, icons_dir, class_name);
209
 
      grub_free (icons_dir);
210
 
    }
211
 
 
212
 
  grub_free (theme_dir);
213
 
  if (! icon)
214
 
    {
215
 
      const char *icondir;
216
 
 
217
 
      icondir = grub_env_get ("icondir");
218
 
      if (icondir)
219
 
        icon = try_loading_icon (mgr, icondir, class_name);
220
 
    }
221
 
 
222
 
  /* No icon was found.  */
223
 
  /* This should probably be noted in the cache, so that a search is not
224
 
     performed each time an icon for CLASS_NAME is requested.  */
225
 
  if (! icon)
226
 
    return 0;
227
 
 
228
 
  /* Insert a new cache entry for this icon.  */
229
 
  entry = grub_malloc (sizeof (*entry));
230
 
  if (! entry)
231
 
    {
232
 
      grub_video_bitmap_destroy (icon);
233
 
      return 0;
234
 
    }
235
 
  entry->class_name = grub_strdup (class_name);
236
 
  entry->bitmap = icon;
237
 
  entry->next = mgr->cache.next;
238
 
  mgr->cache.next = entry;   /* Link it into the cache.  */
239
 
  return entry->bitmap;
240
 
}
241
 
 
242
 
/* Get the best available icon for ENTRY.  Beginning with the first class
243
 
   listed in the menu entry and proceeding forward, an icon for each class
244
 
   is searched for.  The first icon found is returned.  The returned icon
245
 
   is scaled to the size specified by
246
 
   grub_gfxmenu_icon_manager_set_icon_size().
247
 
 
248
 
     Note:  Bitmaps returned by this function are destroyed when the
249
 
            icon manager is destroyed.
250
 
 */
251
 
struct grub_video_bitmap *
252
 
grub_gfxmenu_icon_manager_get_icon (grub_gfxmenu_icon_manager_t mgr,
253
 
                                    grub_menu_entry_t entry)
254
 
{
255
 
  struct grub_menu_entry_class *c;
256
 
  struct grub_video_bitmap *icon;
257
 
 
258
 
  /* Try each class in succession.  */
259
 
  icon = 0;
260
 
  for (c = entry->classes->next; c && ! icon; c = c->next)
261
 
    icon = get_icon_by_class (mgr, c->name);
262
 
  return icon;
263
 
}