tcmd.h - ltk - Socket-based GUI for X11 (WIP)
HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
HTML git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
tcmd.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 */