source: grub-pc/trunk/fuentes/grub-core/gfxmenu/theme_loader.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 22.2 KB
Line 
1/* theme_loader.c - Theme file loader for gfxmenu.  */
2/*
3 *  GRUB  --  GRand Unified Bootloader
4 *  Copyright (C) 2008  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/file.h>
22#include <grub/misc.h>
23#include <grub/mm.h>
24#include <grub/err.h>
25#include <grub/dl.h>
26#include <grub/video.h>
27#include <grub/gui_string_util.h>
28#include <grub/bitmap.h>
29#include <grub/bitmap_scale.h>
30#include <grub/gfxwidgets.h>
31#include <grub/gfxmenu_view.h>
32#include <grub/gui.h>
33#include <grub/color.h>
34
35static grub_err_t
36parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop);
37
38/* Construct a new box widget using ABSPATTERN to find the pixmap files for
39   it, storing the new box instance at *BOXPTR.
40   PATTERN should be of the form: "(hd0,0)/somewhere/style*.png".
41   The '*' then gets substituted with the various pixmap names that the
42   box uses.  */
43static grub_err_t
44recreate_box_absolute (grub_gfxmenu_box_t *boxptr, const char *abspattern)
45{
46  char *prefix;
47  char *suffix;
48  char *star;
49  grub_gfxmenu_box_t box;
50
51  star = grub_strchr (abspattern, '*');
52  if (! star)
53    return grub_error (GRUB_ERR_BAD_ARGUMENT,
54                       "missing `*' in box pixmap pattern `%s'", abspattern);
55
56  /* Prefix:  Get the part before the '*'.  */
57  prefix = grub_malloc (star - abspattern + 1);
58  if (! prefix)
59    return grub_errno;
60
61  grub_memcpy (prefix, abspattern, star - abspattern);
62  prefix[star - abspattern] = '\0';
63
64  /* Suffix:  Everything after the '*' is the suffix.  */
65  suffix = star + 1;
66
67  box = grub_gfxmenu_create_box (prefix, suffix);
68  grub_free (prefix);
69  if (! box)
70    return grub_errno;
71
72  if (*boxptr)
73    (*boxptr)->destroy (*boxptr);
74  *boxptr = box;
75  return grub_errno;
76}
77
78
79/* Construct a new box widget using PATTERN to find the pixmap files for it,
80   storing the new widget at *BOXPTR.  PATTERN should be of the form:
81   "somewhere/style*.png".  The '*' then gets substituted with the various
82   pixmap names that the widget uses.
83
84   Important!  The value of *BOXPTR must be initialized!  It must either
85   (1) Be 0 (a NULL pointer), or
86   (2) Be a pointer to a valid 'grub_gfxmenu_box_t' instance.
87   In this case, the previous instance is destroyed.  */
88grub_err_t
89grub_gui_recreate_box (grub_gfxmenu_box_t *boxptr,
90                       const char *pattern, const char *theme_dir)
91{
92  char *abspattern;
93
94  /* Check arguments.  */
95  if (! pattern)
96    {
97      /* If no pixmap pattern is given, then just create an empty box.  */
98      if (*boxptr)
99        (*boxptr)->destroy (*boxptr);
100      *boxptr = grub_gfxmenu_create_box (0, 0);
101      return grub_errno;
102    }
103
104  if (! theme_dir)
105    return grub_error (GRUB_ERR_BAD_ARGUMENT,
106                       "styled box missing theme directory");
107
108  /* Resolve to an absolute path.  */
109  abspattern = grub_resolve_relative_path (theme_dir, pattern);
110  if (! abspattern)
111    return grub_errno;
112
113  /* Create the box.  */
114  recreate_box_absolute (boxptr, abspattern);
115  grub_free (abspattern);
116  return grub_errno;
117}
118
119static grub_err_t
120theme_get_unsigned_int_from_proportional (const char *value,
121                                          unsigned absolute_value,
122                                          unsigned int *parsed_value)
123{
124  grub_err_t err;
125  grub_fixed_signed_t frac;
126  signed pixels;
127  err = parse_proportional_spec (value, &pixels, &frac);
128  if (err != GRUB_ERR_NONE)
129    return err;
130  int result = grub_fixed_sfs_multiply (absolute_value, frac) + pixels;
131  if (result < 0)
132    result = 0;
133  *parsed_value = result;
134  return GRUB_ERR_NONE;
135}
136
137/* Set the specified property NAME on the view to the given string VALUE.
138   The caller is responsible for the lifetimes of NAME and VALUE.  */
139static grub_err_t
140theme_set_string (grub_gfxmenu_view_t view,
141                  const char *name,
142                  const char *value,
143                  const char *theme_dir,
144                  const char *filename,
145                  int line_num,
146                  int col_num)
147{
148  if (! grub_strcmp ("title-font", name))
149    view->title_font = grub_font_get (value);
150  else if (! grub_strcmp ("message-font", name))
151    view->message_font = grub_font_get (value);
152  else if (! grub_strcmp ("terminal-font", name))
153    {
154      grub_free (view->terminal_font_name);
155      view->terminal_font_name = grub_strdup (value);
156      if (! view->terminal_font_name)
157        return grub_errno;
158    }
159  else if (! grub_strcmp ("title-color", name))
160    grub_video_parse_color (value, &view->title_color);
161  else if (! grub_strcmp ("message-color", name))
162    grub_video_parse_color (value, &view->message_color);
163  else if (! grub_strcmp ("message-bg-color", name))
164    grub_video_parse_color (value, &view->message_bg_color);
165  else if (! grub_strcmp ("desktop-image", name))
166    {
167      struct grub_video_bitmap *raw_bitmap;
168      char *path;
169      path = grub_resolve_relative_path (theme_dir, value);
170      if (! path)
171        return grub_errno;
172      if (grub_video_bitmap_load (&raw_bitmap, path) != GRUB_ERR_NONE)
173        {
174          grub_free (path);
175          return grub_errno;
176        }
177      grub_free(path);
178      grub_video_bitmap_destroy (view->raw_desktop_image);
179      view->raw_desktop_image = raw_bitmap;
180    }
181  else if (! grub_strcmp ("desktop-image-scale-method", name))
182    {
183      if (! value || ! grub_strcmp ("stretch", value))
184        view->desktop_image_scale_method =
185            GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH;
186      else if (! grub_strcmp ("crop", value))
187        view->desktop_image_scale_method =
188            GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP;
189      else if (! grub_strcmp ("padding", value))
190        view->desktop_image_scale_method =
191            GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING;
192      else if (! grub_strcmp ("fitwidth", value))
193        view->desktop_image_scale_method =
194            GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH;
195      else if (! grub_strcmp ("fitheight", value))
196        view->desktop_image_scale_method =
197            GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT;
198      else
199        return grub_error (GRUB_ERR_BAD_ARGUMENT,
200                           "Unsupported scale method: %s",
201                           value);
202    }
203  else if (! grub_strcmp ("desktop-image-h-align", name))
204    {
205      if (! grub_strcmp ("left", value))
206        view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_LEFT;
207      else if (! grub_strcmp ("center", value))
208        view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER;
209      else if (! grub_strcmp ("right", value))
210        view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_RIGHT;
211      else
212        return grub_error (GRUB_ERR_BAD_ARGUMENT,
213                           "Unsupported horizontal align method: %s",
214                           value);
215    }
216  else if (! grub_strcmp ("desktop-image-v-align", name))
217    {
218      if (! grub_strcmp ("top", value))
219        view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_TOP;
220      else if (! grub_strcmp ("center", value))
221        view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER;
222      else if (! grub_strcmp ("bottom", value))
223        view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_BOTTOM;
224      else
225        return grub_error (GRUB_ERR_BAD_ARGUMENT,
226                           "Unsupported vertical align method: %s",
227                           value);
228    }
229  else if (! grub_strcmp ("desktop-color", name))
230     grub_video_parse_color (value, &view->desktop_color);
231  else if (! grub_strcmp ("terminal-box", name))
232    {
233        grub_err_t err;
234        err = grub_gui_recreate_box (&view->terminal_box, value, theme_dir);
235        if (err != GRUB_ERR_NONE)
236          return err;
237    }
238  else if (! grub_strcmp ("terminal-border", name))
239    {
240      view->terminal_border = grub_strtoul (value, 0, 10);
241      if (grub_errno)
242        return grub_errno;
243    }
244  else if (! grub_strcmp ("terminal-left", name))
245    {
246      unsigned int tmp;
247      int err = theme_get_unsigned_int_from_proportional (value,
248                                                          view->screen.width,
249                                                          &tmp);
250      if (err != GRUB_ERR_NONE)
251        return err;
252      view->terminal_rect.x = tmp;
253    }
254  else if (! grub_strcmp ("terminal-top", name))
255    {
256      unsigned int tmp;
257      int err = theme_get_unsigned_int_from_proportional (value,
258                                                          view->screen.width,
259                                                          &tmp);
260      if (err != GRUB_ERR_NONE)
261        return err;
262      view->terminal_rect.y = tmp;
263    }
264  else if (! grub_strcmp ("terminal-width", name))
265    {
266      unsigned int tmp;
267      int err = theme_get_unsigned_int_from_proportional (value,
268                                                          view->screen.width,
269                                                          &tmp);
270      if (err != GRUB_ERR_NONE)
271        return err;
272      view->terminal_rect.width = tmp;
273    }
274  else if (! grub_strcmp ("terminal-height", name))
275    {
276      unsigned int tmp;
277      int err = theme_get_unsigned_int_from_proportional (value,
278                                                          view->screen.width,
279                                                          &tmp);
280      if (err != GRUB_ERR_NONE)
281        return err;
282      view->terminal_rect.height = tmp;
283    }
284  else if (! grub_strcmp ("title-text", name))
285    {
286      grub_free (view->title_text);
287      view->title_text = grub_strdup (value);
288      if (! view->title_text)
289        return grub_errno;
290    }
291  else
292    {
293      return grub_error (GRUB_ERR_BAD_ARGUMENT,
294                         "%s:%d:%d unknown property `%s'",
295                         filename, line_num, col_num, name);
296    }
297  return grub_errno;
298}
299
300struct parsebuf
301{
302  char *buf;
303  int pos;
304  int len;
305  int line_num;
306  int col_num;
307  const char *filename;
308  char *theme_dir;
309  grub_gfxmenu_view_t view;
310};
311
312static int
313has_more (struct parsebuf *p)
314{
315  return p->pos < p->len;
316}
317
318static int
319read_char (struct parsebuf *p)
320{
321  if (has_more (p))
322    {
323      char c;
324      c = p->buf[p->pos++];
325      if (c == '\n')
326        {
327          p->line_num++;
328          p->col_num = 1;
329        }
330      else
331        {
332          p->col_num++;
333        }
334      return c;
335    }
336  else
337    return -1;
338}
339
340static int
341peek_char (struct parsebuf *p)
342{
343  if (has_more (p))
344    return p->buf[p->pos];
345  else
346    return -1;
347}
348
349static int
350is_whitespace (char c)
351{
352  return (c == ' '
353          || c == '\t'
354          || c == '\r'
355          || c == '\n'
356          || c == '\f');
357}
358
359static void
360skip_whitespace (struct parsebuf *p)
361{
362  while (has_more (p) && is_whitespace(peek_char (p)))
363    read_char (p);
364}
365
366static void
367advance_to_next_line (struct parsebuf *p)
368{
369  int c;
370
371  /* Eat characters up to the newline.  */
372  do
373    {
374      c = read_char (p);
375    }
376  while (c != -1 && c != '\n');
377}
378
379static int
380is_identifier_char (int c)
381{
382  return (c != -1
383          && (grub_isalpha(c)
384              || grub_isdigit(c)
385              || c == '_'
386              || c == '-'));
387}
388
389static char *
390read_identifier (struct parsebuf *p)
391{
392  /* Index of the first character of the identifier in p->buf.  */
393  int start;
394  /* Next index after the last character of the identifer in p->buf.  */
395  int end;
396
397  skip_whitespace (p);
398
399  /* Capture the start of the identifier.  */
400  start = p->pos;
401
402  /* Scan for the end.  */
403  while (is_identifier_char (peek_char (p)))
404    read_char (p);
405  end = p->pos;
406
407  if (end - start < 1)
408    return 0;
409
410  return grub_new_substring (p->buf, start, end);
411}
412
413static char *
414read_expression (struct parsebuf *p)
415{
416  int start;
417  int end;
418
419  skip_whitespace (p);
420  if (peek_char (p) == '"')
421    {
422      /* Read as a quoted string. 
423         The quotation marks are not included in the expression value.  */
424      /* Skip opening quotation mark.  */
425      read_char (p);
426      start = p->pos;
427      while (has_more (p) && peek_char (p) != '"')
428        read_char (p);
429      end = p->pos;
430      /* Skip the terminating quotation mark.  */
431      read_char (p);
432    }
433  else if (peek_char (p) == '(')
434    {
435      /* Read as a parenthesized string -- for tuples/coordinates.  */
436      /* The parentheses are included in the expression value.  */
437      int c;
438
439      start = p->pos;
440      do
441        {
442          c = read_char (p);
443        }
444      while (c != -1 && c != ')');
445      end = p->pos;
446    }
447  else if (has_more (p))
448    {
449      /* Read as a single word -- for numeric values or words without
450         whitespace.  */
451      start = p->pos;
452      while (has_more (p) && ! is_whitespace (peek_char (p)))
453        read_char (p);
454      end = p->pos;
455    }
456  else
457    {
458      /* The end of the theme file has been reached.  */
459      grub_error (GRUB_ERR_IO, "%s:%d:%d expression expected in theme file",
460                  p->filename, p->line_num, p->col_num);
461      return 0;
462    }
463
464  return grub_new_substring (p->buf, start, end);
465}
466
467static grub_err_t
468parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop)
469{
470  signed num;
471  const char *ptr;
472  int sig = 0;
473  *abs = 0;
474  *prop = 0;
475  ptr = value;
476  while (*ptr)
477    {
478      sig = 0;
479
480      while (*ptr == '-' || *ptr == '+')
481        {
482          if (*ptr == '-')
483            sig = !sig;
484          ptr++;
485        }
486
487      num = grub_strtoul (ptr, (char **) &ptr, 0);
488      if (grub_errno)
489        return grub_errno;
490      if (sig)
491        num = -num;
492      if (*ptr == '%')
493        {
494          *prop += grub_fixed_fsf_divide (grub_signed_to_fixed (num), 100);
495          ptr++;
496        }
497      else
498        *abs += num;
499    }
500  return GRUB_ERR_NONE;
501}
502
503
504/* Read a GUI object specification from the theme file.
505   Any components created will be added to the GUI container PARENT.  */
506static grub_err_t
507read_object (struct parsebuf *p, grub_gui_container_t parent)
508{
509  grub_video_rect_t bounds;
510
511  char *name;
512  name = read_identifier (p);
513  if (! name)
514    goto cleanup;
515
516  grub_gui_component_t component = 0;
517  if (grub_strcmp (name, "label") == 0)
518    {
519      component = grub_gui_label_new ();
520    }
521  else if (grub_strcmp (name, "image") == 0)
522    {
523      component = grub_gui_image_new ();
524    }
525  else if (grub_strcmp (name, "vbox") == 0)
526    {
527      component = (grub_gui_component_t) grub_gui_vbox_new ();
528    }
529  else if (grub_strcmp (name, "hbox") == 0)
530    {
531      component = (grub_gui_component_t) grub_gui_hbox_new ();
532    }
533  else if (grub_strcmp (name, "canvas") == 0)
534    {
535      component = (grub_gui_component_t) grub_gui_canvas_new ();
536    }
537  else if (grub_strcmp (name, "progress_bar") == 0)
538    {
539      component = grub_gui_progress_bar_new ();
540    }
541  else if (grub_strcmp (name, "circular_progress") == 0)
542    {
543      component = grub_gui_circular_progress_new ();
544    }
545  else if (grub_strcmp (name, "boot_menu") == 0)
546    {
547      component = grub_gui_list_new ();
548    }
549  else
550    {
551      /* Unknown type.  */
552      grub_error (GRUB_ERR_IO, "%s:%d:%d unknown object type `%s'",
553                  p->filename, p->line_num, p->col_num, name);
554      goto cleanup;
555    }
556
557  if (! component)
558    goto cleanup;
559
560  /* Inform the component about the theme so it can find its resources.  */
561  component->ops->set_property (component, "theme_dir", p->theme_dir);
562  component->ops->set_property (component, "theme_path", p->filename);
563
564  /* Add the component as a child of PARENT.  */
565  bounds.x = 0;
566  bounds.y = 0;
567  bounds.width = -1;
568  bounds.height = -1;
569  component->ops->set_bounds (component, &bounds);
570  parent->ops->add (parent, component);
571
572  skip_whitespace (p);
573  if (read_char (p) != '{')
574    {
575      grub_error (GRUB_ERR_IO,
576                  "%s:%d:%d expected `{' after object type name `%s'",
577                  p->filename, p->line_num, p->col_num, name);
578      goto cleanup;
579    }
580
581  while (has_more (p))
582    {
583      skip_whitespace (p);
584
585      /* Check whether the end has been encountered.  */
586      if (peek_char (p) == '}')
587        {
588          /* Skip the closing brace.  */
589          read_char (p);
590          break;
591        }
592
593      if (peek_char (p) == '#')
594        {
595          /* Skip comments.  */
596          advance_to_next_line (p);
597          continue;
598        }
599
600      if (peek_char (p) == '+')
601        {
602          /* Skip the '+'.  */
603          read_char (p);
604
605          /* Check whether this component is a container.  */
606          if (component->ops->is_instance (component, "container"))
607            {
608              /* Read the sub-object recursively and add it as a child.  */
609              if (read_object (p, (grub_gui_container_t) component) != 0)
610                goto cleanup;
611              /* After reading the sub-object, resume parsing, expecting
612                 another property assignment or sub-object definition.  */
613              continue;
614            }
615          else
616            {
617              grub_error (GRUB_ERR_IO,
618                          "%s:%d:%d attempted to add object to non-container",
619                          p->filename, p->line_num, p->col_num);
620              goto cleanup;
621            }
622        }
623
624      char *property;
625      property = read_identifier (p);
626      if (! property)
627        {
628          grub_error (GRUB_ERR_IO, "%s:%d:%d identifier expected in theme file",
629                      p->filename, p->line_num, p->col_num);
630          goto cleanup;
631        }
632
633      skip_whitespace (p);
634      if (read_char (p) != '=')
635        {
636          grub_error (GRUB_ERR_IO,
637                      "%s:%d:%d expected `=' after property name `%s'",
638                      p->filename, p->line_num, p->col_num, property);
639          grub_free (property);
640          goto cleanup;
641        }
642      skip_whitespace (p);
643
644      char *value;
645      value = read_expression (p);
646      if (! value)
647        {
648          grub_free (property);
649          goto cleanup;
650        }
651
652      /* Handle the property value.  */
653      if (grub_strcmp (property, "left") == 0)
654        parse_proportional_spec (value, &component->x, &component->xfrac);
655      else if (grub_strcmp (property, "top") == 0)
656        parse_proportional_spec (value, &component->y, &component->yfrac);
657      else if (grub_strcmp (property, "width") == 0)
658        parse_proportional_spec (value, &component->w, &component->wfrac);
659      else if (grub_strcmp (property, "height") == 0)
660        parse_proportional_spec (value, &component->h, &component->hfrac);
661      else
662        /* General property handling.  */
663        component->ops->set_property (component, property, value);
664
665      grub_free (value);
666      grub_free (property);
667      if (grub_errno != GRUB_ERR_NONE)
668        goto cleanup;
669    }
670
671cleanup:
672  grub_free (name);
673  return grub_errno;
674}
675
676static grub_err_t
677read_property (struct parsebuf *p)
678{
679  char *name;
680
681  /* Read the property name.  */
682  name = read_identifier (p);
683  if (! name)
684    {
685      advance_to_next_line (p);
686      return grub_errno;
687    }
688
689  /* Skip whitespace before separator.  */
690  skip_whitespace (p);
691
692  /* Read separator.  */
693  if (read_char (p) != ':')
694    {
695      grub_error (GRUB_ERR_IO,
696                  "%s:%d:%d missing separator after property name `%s'",
697                  p->filename, p->line_num, p->col_num, name);
698      goto done;
699    }
700
701  /* Skip whitespace after separator.  */
702  skip_whitespace (p);
703
704  /* Get the value based on its type.  */
705  if (peek_char (p) == '"')
706    {
707      /* String value (e.g., '"My string"').  */
708      char *value = read_expression (p);
709      if (! value)
710        {
711          grub_error (GRUB_ERR_IO, "%s:%d:%d missing property value",
712                      p->filename, p->line_num, p->col_num);
713          goto done;
714        }
715      /* If theme_set_string results in an error, grub_errno will be returned
716         below.  */
717      theme_set_string (p->view, name, value, p->theme_dir,
718                        p->filename, p->line_num, p->col_num);
719      grub_free (value);
720    }
721  else
722    {
723      grub_error (GRUB_ERR_IO,
724                  "%s:%d:%d property value invalid; "
725                  "enclose literal values in quotes (\")",
726                  p->filename, p->line_num, p->col_num);
727      goto done;
728    }
729
730done:
731  grub_free (name);
732  return grub_errno;
733}
734
735/* Set properties on the view based on settings from the specified
736   theme file.  */
737grub_err_t
738grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path)
739{
740  grub_file_t file;
741  struct parsebuf p;
742
743  p.view = view;
744  p.theme_dir = grub_get_dirname (theme_path);
745
746  file = grub_file_open (theme_path);
747  if (! file)
748    {
749      grub_free (p.theme_dir);
750      return grub_errno;
751    }
752
753  p.len = grub_file_size (file);
754  p.buf = grub_malloc (p.len);
755  p.pos = 0;
756  p.line_num = 1;
757  p.col_num = 1;
758  p.filename = theme_path;
759  if (! p.buf)
760    {
761      grub_file_close (file);
762      grub_free (p.theme_dir);
763      return grub_errno;
764    }
765  if (grub_file_read (file, p.buf, p.len) != p.len)
766    {
767      grub_free (p.buf);
768      grub_file_close (file);
769      grub_free (p.theme_dir);
770      return grub_errno;
771    }
772
773  if (view->canvas)
774    view->canvas->component.ops->destroy (view->canvas);
775
776  view->canvas = grub_gui_canvas_new ();
777  ((grub_gui_component_t) view->canvas)
778    ->ops->set_bounds ((grub_gui_component_t) view->canvas,
779                       &view->screen);
780
781  while (has_more (&p))
782    {
783      /* Skip comments (lines beginning with #).  */
784      if (peek_char (&p) == '#')
785        {
786          advance_to_next_line (&p);
787          continue;
788        }
789
790      /* Find the first non-whitespace character.  */
791      skip_whitespace (&p);
792
793      /* Handle the content.  */
794      if (peek_char (&p) == '+')
795        {
796          /* Skip the '+'.  */
797          read_char (&p);
798          read_object (&p, view->canvas);
799        }
800      else
801        {
802          read_property (&p);
803        }
804
805      if (grub_errno != GRUB_ERR_NONE)
806        goto fail;
807    }
808
809  /* Set the new theme path.  */
810  grub_free (view->theme_path);
811  view->theme_path = grub_strdup (theme_path);
812  goto cleanup;
813
814fail:
815  if (view->canvas)
816    {
817      view->canvas->component.ops->destroy (view->canvas);
818      view->canvas = 0;
819    }
820
821cleanup:
822  grub_free (p.buf);
823  grub_file_close (file);
824  grub_free (p.theme_dir);
825  return grub_errno;
826}
Note: See TracBrowser for help on using the repository browser.