/* * menu.c * This file is part of lcdexec, an LCDproc client. * * This file is released under the GNU General Public License. Refer to the * COPYING file distributed with this package. * * Copyright (c) 2002, Joris Robijn * Copyright (c) 2006, Peter Marschall */ #include #include #include #include "shared/str.h" #include "shared/report.h" #include "shared/configfile.h" #include "shared/sockets.h" #include "menu.h" /* recursively read the menu hierarchy */ MenuEntry *menu_read(MenuEntry *parent, const char *name) { static int id = 0; if (config_has_section(name)) { MenuEntry *me = calloc(1, sizeof(MenuEntry)); if (me == NULL) return NULL; // set common entries me->id = id++; me->name = strdup(name); if (me->name == NULL) { //menu_free(me); return NULL; } me->displayname = strdup(config_get_string(name, "DisplayName", 0, name)); if (me->name == NULL) { //menu_free(me); return NULL; } me->entries = NULL; me->next = NULL; me->command = NULL; if (config_get_string(name, "Entry", 0, NULL) != NULL) { MenuEntry **addr = &me->entries; const char *entryname; int index = 0; // it is a sub-menu me->type = menu; while ((entryname = config_get_string(name, "Entry", index++, NULL)) != NULL) { MenuEntry *entry = menu_read(me, entryname); if (entry == NULL) { //menu_free(me); return NULL; } *addr = entry; addr = &entry->next; } } else if (config_get_string(name, "Exec", 0, NULL) != NULL) { // it's a command to execute me->type = exec; me->command = strdup(config_get_string(name, "Exec", 0, "")); if (me->command == NULL) { //menu_free(me); return NULL; } } else { //menu_free(me); return NULL; } return me; } return NULL; } /* create LCDproc commands for the menu entry hierarchy and send it to the server */ int menu_sock_send(MenuEntry *me, MenuEntry *parent, int sock) { if ((me != NULL) && (sock > 0)) { char parent_id[12]; // set parent_id depending on the parent given if ((parent != NULL) && (parent->id != 0)) sprintf(parent_id, "%d", parent->id); else strcpy(parent_id, ""); switch (me->type) { MenuEntry *entry; case menu: // don't create a separate entry for the main menu if ((parent != NULL) && (me->id != 0)) { if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" menu \"%s\"\n", parent_id, me->id, me->displayname) < 0) return -1; } // recursively do it for the menu's sub-menus for (entry = me->entries; entry != NULL; entry = entry->next) { if (menu_sock_send(entry, me, sock) < 0) return -1; } break; case exec: if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" action \"%s\"\n", parent_id, me->id, me->displayname) < 0) return -1; if (sock_printf(sock, "menu_set_item \"%s\" \"%d\" -menu_result quit\n", parent_id, me->id) < 0) return -1; break; case unknown: default: return -1; } return 0; } return -1; } /* find menu entry by its id */ MenuEntry *menu_find_by_id(MenuEntry *me, int id) { if (me != NULL) { if (me->id == id) return me; if (me->type == menu) { MenuEntry *entry; for (entry = me->entries; entry != NULL; entry = entry->next) { MenuEntry *result = menu_find_by_id(entry, id); if (result != NULL) return result; } } } return NULL; } /* return command of a menu entry */ const char *menu_command(MenuEntry *me) { if ((me != NULL) && (me->type == exec)) return me->command; return NULL; } /* free menu entry hierarchy */ void menu_free(MenuEntry *me) { if (me != NULL) { switch (me->type) { MenuEntry *entry; case menu: for (entry = me->entries; entry != NULL; ) { MenuEntry *old = entry; entry = entry->next; old->next = NULL; menu_free(old); } me->entries = NULL; break; case exec: if (me->command != NULL) free(me->command); me->command = NULL; break; case unknown: default: break; } if (me->name != NULL) free(me->name); me->name = NULL; if (me->displayname != NULL) free(me->displayname); me->displayname = NULL; me->type = unknown; free(me); } } #if defined(DEBUG) /* dump menu entry hierarchy to screen */ void menu_dump(MenuEntry *me) { if (me != NULL) { report(RPT_DEBUG, "# menu ID: %d", me->id); report(RPT_DEBUG, "[%s]", me->name); if (me->displayname != NULL) report(RPT_DEBUG, "DisplayName=\"%s\"", me->displayname); switch (me->type) { MenuEntry *entry; case menu: for (entry = me->entries; entry != NULL; entry = entry->next) report(RPT_DEBUG, "Entry=%s", entry->name); break; case exec: report(RPT_DEBUG, "Exec=\"%s\"", me->command); break; case unknown: default: report(RPT_DEBUG, "ERROR: unknown menu entry type"); break; } report(RPT_DEBUG, ""); // recursively walk through sub-menus if (me->type == menu) { MenuEntry *entry; for (entry = me->entries; entry != NULL; entry = entry->next) menu_dump(entry); } } } #endif /* EOF */