ltk

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/ltk.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
Log | Files | Refs | README | LICENSE

cmd.h (5382B)


      1 /*
      2  * Copyright (c) 2023-2024 lumidify <nobody@lumidify.org>
      3  *
      4  * Permission to use, copy, modify, and/or distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #ifndef LTKD_CMD_H
     18 #define LTKD_CMD_H
     19 
     20 #include <stddef.h>
     21 
     22 #include "err.h"
     23 #include "ltkd.h"
     24 #include "widget.h"
     25 
     26 #include <ltk/ltk.h>
     27 #include <ltk/util.h>
     28 #include <ltk/color.h>
     29 #include <ltk/graphics.h>
     30 
     31 typedef struct {
     32         char *name;
     33         int (*func)(ltk_window *, ltkd_widget *, ltkd_cmd_token *, size_t, ltkd_error *);
     34         int needs_all;
     35 } ltkd_cmd_info;
     36 
     37 typedef enum {
     38 	CMDARG_IGNORE,
     39 	CMDARG_STRING, /* nul-terminated string */
     40 	CMDARG_DATA,   /* also char*, but may contain nul */
     41 	CMDARG_COLOR,
     42 	CMDARG_INT,
     43 	CMDARG_BOOL,
     44 	CMDARG_BORDERSIDES,
     45 	CMDARG_STICKY,
     46 	CMDARG_WIDGET,
     47 	CMDARG_ORIENTATION
     48 } ltkd_cmdarg_datatype;
     49 
     50 /* color needs to be destroyed by cmd handling function if it is not needed anymore */
     51 /* str must *not* be freed because it is a pointer to the original argument
     52    -> it must be copied if it needs to be kept around */
     53 typedef struct {
     54 	ltkd_cmdarg_datatype type;
     55 	/* Note: Bool and int are both integers, but they are
     56 	   separate just to make it a bit clearer (same goes for str/data) */
     57 	union {
     58 		char *str;
     59 		char *data;
     60 		ltk_color *color;
     61 		int i;
     62 		int b;
     63 		ltk_border_sides border;
     64 		ltk_sticky_mask sticky;
     65 		ltk_orientation orient;
     66 		ltkd_widget *widget;
     67 	} val;
     68 	size_t len; /* only for data */
     69 	int min, max; /* only for integers */ /* FIXME: which integer type is sensible here? */
     70 	ltk_widget_type widget_type; /* only for widgets */
     71 	int optional;
     72 	int initialized;
     73 } ltkd_cmdarg_parseinfo;
     74 
     75 /* Returns 1 on error, 0 on success */
     76 /* All optional arguments must be in one block at the end */
     77 int ltkd_parse_cmd(
     78     ltkd_cmd_token *tokens, size_t num_tokens,
     79     ltkd_cmdarg_parseinfo *parseinfo, size_t num_arg, ltkd_error *err
     80 );
     81 
     82 /* FIXME: This doesn't really need to be a macro anymore since it doesn't have to be generic for different types anymore */
     83 #define GEN_CMD_HELPERS_PROTO(func_name)									\
     84 int func_name(ltk_window *window, ltkd_cmd_token *tokens, size_t num_tokens, ltkd_error *err);
     85 
     86 
     87 #define GEN_CMD_HELPERS(func_name, widget_type, array_name)							\
     88 /* FIXME: maybe just get rid of this and rely on array already being sorted? */					\
     89 static int array_name##_sorted = 0;										\
     90 														\
     91 static int													\
     92 array_name##_search_helper(const void *keyv, const void *entryv) {						\
     93 	const char *key = (const char *)keyv;									\
     94 	ltkd_cmd_info *entry = (ltkd_cmd_info *)entryv;								\
     95 	return strcmp(key, entry->name);									\
     96 }														\
     97 														\
     98 static int													\
     99 array_name##_sort_helper(const void *entry1v, const void *entry2v) {						\
    100 	ltkd_cmd_info *entry1 = (ltkd_cmd_info *)entry1v;							\
    101 	ltkd_cmd_info *entry2 = (ltkd_cmd_info *)entry2v;							\
    102 	return strcmp(entry1->name, entry2->name);								\
    103 }														\
    104 														\
    105 int														\
    106 func_name(													\
    107     ltk_window *window,												\
    108     ltkd_cmd_token *tokens,											\
    109     size_t num_tokens,												\
    110     ltkd_error *err) {												\
    111 	if (num_tokens < 3) {											\
    112 		err->type = ERR_INVALID_NUMBER_OF_ARGUMENTS;							\
    113 		err->arg = -1;											\
    114 		return 1;											\
    115 	}													\
    116 	/* just in case */											\
    117 	if (!array_name##_sorted) {										\
    118 		qsort(												\
    119 		    array_name, LENGTH(array_name),								\
    120 		    sizeof(array_name[0]), &array_name##_sort_helper);						\
    121 		array_name##_sorted = 1;									\
    122 	}													\
    123 	if (tokens[1].contains_nul) {										\
    124 		err->type = ERR_INVALID_ARGUMENT;								\
    125 		err->arg = 1;											\
    126 		return 1;											\
    127 	} else if (tokens[2].contains_nul) {									\
    128 		err->type = ERR_INVALID_ARGUMENT;								\
    129 		err->arg = 2;											\
    130 		return 1;											\
    131 	}													\
    132 	ltkd_cmd_info *e = bsearch(										\
    133 	    tokens[2].text, array_name, LENGTH(array_name),							\
    134 	    sizeof(array_name[0]), &array_name##_search_helper							\
    135 	);													\
    136 	if (!e) {												\
    137 		err->type = ERR_INVALID_COMMAND;								\
    138 		err->arg = -1;											\
    139 		return 1;											\
    140 	}													\
    141 	if (e->needs_all) {											\
    142 		return e->func(window, NULL, tokens, num_tokens, err);						\
    143 	} else {												\
    144 		ltkd_widget *widget = ltkd_get_widget(tokens[1].text, widget_type, err);			\
    145 		if (!widget) {											\
    146 			err->arg = 1;										\
    147 			return 1;										\
    148 		}												\
    149 		int ret = e->func(window, widget, tokens + 3, num_tokens - 3, err);				\
    150 		if (ret && err->arg >= 0)									\
    151 			err->arg += 3;										\
    152 		return ret;											\
    153 	}													\
    154 	return 0; /* Well, I guess this is impossible anyways... */						\
    155 }
    156 
    157 #endif /* LTKD_CMD_H */