ltk

Socket-based GUI for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

cmd.h (4170B)


      1 #ifndef LTK_CMD_H
      2 #define LTK_CMD_H
      3 
      4 #include "ltk.h"
      5 
      6 typedef enum {
      7 	CMDARG_IGNORE,
      8 	CMDARG_STRING, /* nul-terminated string */
      9 	CMDARG_DATA,   /* also char*, but may contain nul */
     10 	CMDARG_COLOR,
     11 	CMDARG_INT,
     12 	CMDARG_BOOL,
     13 	CMDARG_BORDERSIDES,
     14 	CMDARG_STICKY,
     15 	CMDARG_WIDGET,
     16 	CMDARG_ORIENTATION
     17 } ltk_cmdarg_datatype;
     18 
     19 /* color needs to be destroyed by cmd handling function if it is not needed anymore */
     20 /* str must *not* be freed because it is a pointer to the original argument
     21    -> it must be copied if it needs to be kept around */
     22 typedef struct {
     23 	ltk_cmdarg_datatype type;
     24 	/* Note: Bool and int are both integers, but they are
     25 	   separate just to make it a bit clearer (same goes for str/data) */
     26 	union {
     27 		char *str;
     28 		char *data;
     29 		ltk_color color;
     30 		int i;
     31 		int b;
     32 		ltk_border_sides border;
     33 		ltk_sticky_mask sticky;
     34 		ltk_orientation orient;
     35 		ltk_widget *widget;
     36 	} val;
     37 	size_t len; /* only for data */
     38 	int min, max; /* only for integers */ /* FIXME: which integer type is sensible here? */
     39 	ltk_widget_type widget_type; /* only for widgets */
     40 	int optional;
     41 	int initialized;
     42 } ltk_cmdarg_parseinfo;
     43 
     44 /* Returns 1 on error, 0 on success */
     45 /* All optional arguments must be in one block at the end */
     46 int ltk_parse_cmd(
     47     ltk_window *window, ltk_cmd_token *tokens, size_t num_tokens,
     48     ltk_cmdarg_parseinfo *parseinfo, size_t num_arg, ltk_error *err
     49 );
     50 
     51 #define GEN_CMD_HELPERS_PROTO(func_name)									\
     52 int func_name(ltk_window *window, ltk_cmd_token *tokens, size_t num_tokens, ltk_error *err);
     53 
     54 
     55 #define GEN_CMD_HELPERS(func_name, widget_type, widget_typename, array_name, entry_type)			\
     56 /* FIXME: maybe just get rid of this and rely on array already being sorted? */					\
     57 static int array_name##_sorted = 0;										\
     58 														\
     59 static int													\
     60 array_name##_search_helper(const void *keyv, const void *entryv) {						\
     61 	const char *key = (const char *)keyv;									\
     62 	entry_type *entry = (entry_type *)entryv;								\
     63 	return strcmp(key, entry->name);									\
     64 }														\
     65 														\
     66 static int													\
     67 array_name##_sort_helper(const void *entry1v, const void *entry2v) {						\
     68 	entry_type *entry1 = (entry_type *)entry1v;								\
     69 	entry_type *entry2 = (entry_type *)entry2v;								\
     70 	return strcmp(entry1->name, entry2->name);								\
     71 }														\
     72 														\
     73 int														\
     74 func_name(													\
     75     ltk_window *window,												\
     76     ltk_cmd_token *tokens,											\
     77     size_t num_tokens,												\
     78     ltk_error *err) {												\
     79 	if (num_tokens < 3) {											\
     80 		err->type = ERR_INVALID_NUMBER_OF_ARGUMENTS;							\
     81 		err->arg = -1;											\
     82 		return 1;											\
     83 	}													\
     84 	/* just in case */											\
     85 	if (!array_name##_sorted) {										\
     86 		qsort(												\
     87 		    array_name, LENGTH(array_name),								\
     88 		    sizeof(array_name[0]), &array_name##_sort_helper);						\
     89 		array_name##_sorted = 1;									\
     90 	}													\
     91 	if (tokens[1].contains_nul) {										\
     92 		err->type = ERR_INVALID_ARGUMENT;								\
     93 		err->arg = 1;											\
     94 		return 1;											\
     95 	} else if (tokens[2].contains_nul) {									\
     96 		err->type = ERR_INVALID_ARGUMENT;								\
     97 		err->arg = 2;											\
     98 		return 1;											\
     99 	}													\
    100 	entry_type *e = bsearch(										\
    101 	    tokens[2].text, array_name, LENGTH(array_name),							\
    102 	    sizeof(array_name[0]), &array_name##_search_helper							\
    103 	);													\
    104 	if (!e) {												\
    105 		err->type = ERR_INVALID_COMMAND;								\
    106 		err->arg = -1;											\
    107 		return 1;											\
    108 	}													\
    109 	if (e->needs_all) {											\
    110 		return e->func(window, NULL, tokens, num_tokens, err);						\
    111 	} else {												\
    112 		widget_typename *widget = (widget_typename *)ltk_get_widget(tokens[1].text, widget_type, err);	\
    113 		if (!widget) {											\
    114 			err->arg = 1;										\
    115 			return 1;										\
    116 		}												\
    117 		int ret = e->func(window, widget, tokens + 3, num_tokens - 3, err);				\
    118 		if (ret && err->arg >= 0)									\
    119 			err->arg += 3;										\
    120 		return ret;											\
    121 	}													\
    122 	return 0; /* Well, I guess this is impossible anyways... */						\
    123 }
    124 
    125 #endif /* LTK_CMD_H */