From: Colin D Bennett <colin@gibibit.com>
To: grub-devel@gnu.org
Subject: [PATCH] GSoC #05 Menu entry class attribute
Date: Sat, 30 Aug 2008 23:52:54 -0700 [thread overview]
Message-ID: <20080830235254.7cc5ad80@gamma.lan> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 480 bytes --]
This patch adds support for a 'class' attribute on menu entries. It is
somewhat of a kludge, however since currently you just append
"|class=this,that" to the menu entry title to specify the classes.
Classes are used to provide a simple and flexible way for the best
available icon to be used in a graphical menu, but there are other
possible uses for them as well. The idea originates from the CSS
(cascading style sheets) and HTML 'class' concept.
Regards,
Colin
[-- Attachment #1.2: 05_ChangeLog.txt --]
[-- Type: text/plain, Size: 506 bytes --]
2008-08-30 Colin D Bennett <colin@gibibit.com>
Support classes for menu entries by adding '|classes=x,y' to the
title.
* include/grub/menu.h (grub_menu_entry_class): New struct type.
(grub_menu_entry): Added 'classes' field.
* normal/main.c (free_menu_entry_classes): New function.
(entry_class_attr_tag): New string constant.
(ENTRY_ATTR_SEPARATOR_CHAR): New macro.
(get_classes_from_entry_title): New function.
(grub_normal_menu_addentry): Parse '|classes=x,y' from entry titles.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 05_menu-entry-class.patch --]
[-- Type: text/x-patch; name=05_menu-entry-class.patch, Size: 5883 bytes --]
=== modified file 'include/grub/menu.h'
--- include/grub/menu.h 2008-08-30 19:20:13 +0000
+++ include/grub/menu.h 2008-08-31 05:47:00 +0000
@@ -20,12 +20,24 @@
#ifndef GRUB_MENU_HEADER
#define GRUB_MENU_HEADER 1
+struct grub_menu_entry_class
+{
+ char *name;
+ struct grub_menu_entry_class *next;
+};
+
/* The menu entry. */
struct grub_menu_entry
{
/* The title name. */
const char *title;
+ /* The classes associated with the menu entry:
+ used to choose an icon or other style attributes.
+ This is a dummy head node for the linked list, so for an entry E,
+ E.classes->next is the first class if it is not NULL. */
+ struct grub_menu_entry_class *classes;
+
/* The commands associated with this menu entry. */
struct grub_script *commands;
=== modified file 'normal/main.c'
--- normal/main.c 2008-08-30 19:20:13 +0000
+++ normal/main.c 2008-08-31 05:47:00 +0000
@@ -148,14 +148,132 @@
grub_env_unset_data_slot ("menu");
}
+static void
+free_menu_entry_classes (struct grub_menu_entry_class *head)
+{
+ /* Free all the classes. */
+ while (head)
+ {
+ struct grub_menu_entry_class *next;
+
+ grub_free (head->name);
+ next = head->next;
+ grub_free (head);
+ head = next;
+ }
+}
+
+/* The tag that can be added to a menu entry's title to specify a class
+ for the UI to use in selecting an icon or other visual attributes. */
+static const char entry_class_attr_tag[] = "|class=";
+
+#define ENTRY_ATTR_SEPARATOR_CHAR ','
+
+/* Parse and strip a possible "class" attribute in the title.
+ This code is not designed to support other attributes than "class"
+ in the title since, we are planning to use a better method of
+ specifying this information in the future. The parameter TITLE is
+ modified by storing a '\0' at the appropriate location to strip the
+ class information, if it exists. The class list is stored into *HEAD. */
+static struct grub_menu_entry_class *
+get_classes_from_entry_title (char *title)
+{
+ struct grub_menu_entry_class *head;
+ char *attr_start;
+
+ head = grub_malloc (sizeof (struct grub_menu_entry_class));
+ if (! head)
+ return 0;
+ head->name = 0;
+ head->next = 0;
+
+ attr_start = grub_strstr (title, entry_class_attr_tag);
+ if (attr_start)
+ {
+ struct grub_menu_entry_class *tail;
+ const char *p;
+
+ /* Trim the properties off of the title. */
+ *attr_start = '\0';
+
+ /* Move the pointer to the beginning of the first class name. */
+ attr_start += grub_strlen (entry_class_attr_tag);
+
+ tail = head;
+ p = attr_start;
+ while (p && *p)
+ {
+ const char *q;
+ const char *end;
+ const char *next_start;
+
+ /* Skip any leading whitespace. */
+ while (*p && grub_isspace (*p))
+ p++;
+
+ /* Find the comma terminating this one ... */
+ q = grub_strchr (p, ENTRY_ATTR_SEPARATOR_CHAR);
+ /* ... or if it's the last one, find the '\0' terminator. */
+ if (q)
+ {
+ end = q - 1;
+ next_start = q + 1;
+ }
+ else
+ {
+ /* For the last class, extend it to the end. */
+ end = p + grub_strlen (p);
+ next_start = 0;
+ }
+
+ /* Trim any trailing whitespace. */
+ while (end > p && grub_isspace (*end))
+ end--;
+
+ grub_size_t len = end - p + 1;
+ /* Copy the class name into a new string. */
+ char *class_name = grub_malloc (len + 1);
+ if (! class_name)
+ {
+ free_menu_entry_classes (head);
+ return 0;
+ }
+ grub_memcpy (class_name, p, len);
+ class_name[len] = '\0';
+
+ /* Create a new class and add it at the tail of the list. */
+ struct grub_menu_entry_class *new_class;
+ new_class = grub_malloc (sizeof (struct grub_menu_entry_class));
+ if (! new_class)
+ {
+ grub_free (class_name);
+ free_menu_entry_classes (head);
+ return 0;
+ }
+ /* Fill in the new class node. */
+ new_class->name = class_name;
+ new_class->next = 0;
+ /* Link the tail to it, and make it the new tail. */
+ tail->next = new_class;
+ tail = new_class;
+
+ /* Advance the character pointer. */
+ p = next_start;
+ }
+ }
+
+ return head;
+}
+
grub_err_t
grub_normal_menu_addentry (const char *title, struct grub_script *script,
const char *sourcecode)
{
- const char *menutitle;
+ char *menutitle;
const char *menusourcecode;
grub_menu_t menu;
grub_menu_entry_t *last;
+ struct grub_menu_entry_class *classes;
menu = grub_env_get_data_slot("menu");
if (! menu)
@@ -174,6 +292,14 @@
return grub_errno;
}
+ classes = get_classes_from_entry_title (menutitle);
+ if (! classes)
+ {
+ grub_free ((void *) menutitle);
+ grub_free ((void *) menusourcecode);
+ return grub_errno;
+ }
+
/* Add the menu entry at the end of the list. */
while (*last)
last = &(*last)->next;
@@ -181,6 +307,7 @@
*last = grub_malloc (sizeof (**last));
if (! *last)
{
+ free_menu_entry_classes (classes);
grub_free ((void *) menutitle);
grub_free ((void *) menusourcecode);
return grub_errno;
@@ -188,6 +315,7 @@
(*last)->commands = script;
(*last)->title = menutitle;
+ (*last)->classes = classes;
(*last)->next = 0;
(*last)->sourcecode = menusourcecode;
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
next reply other threads:[~2008-08-31 8:39 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-31 6:52 Colin D Bennett [this message]
2008-10-05 10:07 ` [PATCH] GSoC #05 Menu entry class attribute Vesa Jääskeläinen
2008-10-13 16:35 ` [PATCH] GSoC #05 Menu entry class attribute (v2) Colin D Bennett
2009-01-31 9:19 ` Vesa Jääskeläinen
2009-01-31 17:49 ` Colin D Bennett
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080830235254.7cc5ad80@gamma.lan \
--to=colin@gibibit.com \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.