mirror of
				https://github.com/labwc/labwc.git
				synced 2025-11-03 09:01:51 -05:00 
			
		
		
		
	
		
			
	
	
		
			175 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			175 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								#define _POSIX_C_SOURCE 200112L
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include <string.h>
							 | 
						||
| 
								 | 
							
								#include <strings.h>
							 | 
						||
| 
								 | 
							
								#include <ctype.h>
							 | 
						||
| 
								 | 
							
								#include <stdbool.h>
							 | 
						||
| 
								 | 
							
								#include <libxml/parser.h>
							 | 
						||
| 
								 | 
							
								#include <libxml/tree.h>
							 | 
						||
| 
								 | 
							
								#include <unistd.h>
							 | 
						||
| 
								 | 
							
								#include <fcntl.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "rcxml.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static bool in_keybind = false;
							 | 
						||
| 
								 | 
							
								static bool is_attribute = false;
							 | 
						||
| 
								 | 
							
								static bool verbose = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void rstrip(char *buf, const char *pattern)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									char *p = strstr(buf, pattern);
							 | 
						||
| 
								 | 
							
									if (!p)
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									*p = '\0';
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void fill_keybind(xmlNode *n, char *nodename, char *content)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									rstrip(nodename, ".keybind.keyboard");
							 | 
						||
| 
								 | 
							
									if (!strcmp(nodename, "name.action")) {
							 | 
						||
| 
								 | 
							
										; /* TODO: populate keybind with stuff */
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static bool get_bool(const char *s)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!s)
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									if (!strcasecmp(s, "yes"))
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									if (!strcasecmp(s, "true"))
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void entry(xmlNode *node, char *nodename, char *content)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!nodename)
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									rstrip(nodename, ".openbox_config");
							 | 
						||
| 
								 | 
							
									if (verbose) {
							 | 
						||
| 
								 | 
							
										if (is_attribute)
							 | 
						||
| 
								 | 
							
											printf("@");
							 | 
						||
| 
								 | 
							
										printf("%s: %s\n", nodename, content);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if (!content)
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									if (in_keybind)
							 | 
						||
| 
								 | 
							
										fill_keybind(node, nodename, content);
							 | 
						||
| 
								 | 
							
									if (!strcmp(nodename, "csd.wlroots"))
							 | 
						||
| 
								 | 
							
										rc.client_side_decorations = get_bool(content);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void keybind_begin(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									/* TODO: xcalloc struct keybind */
							 | 
						||
| 
								 | 
							
									in_keybind = true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void keybind_end(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									in_keybind = false;
							 | 
						||
| 
								 | 
							
									/* TODO: wl_list_add keybind */
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static char *nodename(xmlNode *node, char *buf, int len)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!node || !node->name)
							 | 
						||
| 
								 | 
							
										return NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Ignore superflous 'text.' in node name */
							 | 
						||
| 
								 | 
							
									if (node->parent && !strcmp((char *)node->name, "text"))
							 | 
						||
| 
								 | 
							
										node = node->parent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									buf += len;
							 | 
						||
| 
								 | 
							
									*--buf = 0;
							 | 
						||
| 
								 | 
							
									len--;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									char *p = buf;
							 | 
						||
| 
								 | 
							
									p[--len] = 0;
							 | 
						||
| 
								 | 
							
									for (;;) {
							 | 
						||
| 
								 | 
							
										const char *name = (char *)node->name;
							 | 
						||
| 
								 | 
							
										char c;
							 | 
						||
| 
								 | 
							
										while ((c = *name++) != 0) {
							 | 
						||
| 
								 | 
							
											*p++ = tolower(c);
							 | 
						||
| 
								 | 
							
											if (!--len)
							 | 
						||
| 
								 | 
							
												return buf;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										*p = 0;
							 | 
						||
| 
								 | 
							
										node = node->parent;
							 | 
						||
| 
								 | 
							
										if (!node || !node->name)
							 | 
						||
| 
								 | 
							
											return buf;
							 | 
						||
| 
								 | 
							
										*p++ = '.';
							 | 
						||
| 
								 | 
							
										if (!--len)
							 | 
						||
| 
								 | 
							
											return buf;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void process_node(xmlNode *node)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									char *content;
							 | 
						||
| 
								 | 
							
									static char buffer[256];
							 | 
						||
| 
								 | 
							
									char *name;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									content = (char *)node->content;
							 | 
						||
| 
								 | 
							
									if (xmlIsBlankNode(node))
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									name = nodename(node, buffer, sizeof(buffer));
							 | 
						||
| 
								 | 
							
									entry(node, name, content);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void xml_tree_walk(xmlNode *node);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void traverse(xmlNode *n)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									process_node(n);
							 | 
						||
| 
								 | 
							
									is_attribute = true;
							 | 
						||
| 
								 | 
							
									for (xmlAttr *attr = n->properties; attr; attr = attr->next)
							 | 
						||
| 
								 | 
							
										xml_tree_walk(attr->children);
							 | 
						||
| 
								 | 
							
									is_attribute = false;
							 | 
						||
| 
								 | 
							
									xml_tree_walk(n->children);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void xml_tree_walk(xmlNode *node)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									for (xmlNode *n = node; n && n->name; n = n->next) {
							 | 
						||
| 
								 | 
							
										if (!strcasecmp((char *)n->name, "comment"))
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										if (!strcasecmp((char *)n->name, "keybind")) {
							 | 
						||
| 
								 | 
							
											keybind_begin();
							 | 
						||
| 
								 | 
							
											traverse(n);
							 | 
						||
| 
								 | 
							
											keybind_end();
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										traverse(n);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void parse_xml(const char *filename)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									xmlDoc *d = xmlReadFile(filename, NULL, 0);
							 | 
						||
| 
								 | 
							
									if (!d) {
							 | 
						||
| 
								 | 
							
										fprintf(stderr, "fatal: error reading file '%s'\n", filename);
							 | 
						||
| 
								 | 
							
										exit(EXIT_FAILURE);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									printf("info: reading config file '%s'\n", filename);
							 | 
						||
| 
								 | 
							
									xml_tree_walk(xmlDocGetRootElement(d));
							 | 
						||
| 
								 | 
							
									xmlFreeDoc(d);
							 | 
						||
| 
								 | 
							
									xmlCleanupParser();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void rcxml_init(struct rcxml *rc)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									LIBXML_TEST_VERSION
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void rcxml_read(const char *filename)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									parse_xml(filename);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void rcxml_set_verbose(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									verbose = true;
							 | 
						||
| 
								 | 
							
								}
							 |