cmd.h - ltk - GUI toolkit for X11 (WIP)
HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
HTML git clone https://lumidify.org/ltk.git (encrypted, but very slow)
HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
DIR Log
DIR Files
DIR Refs
DIR README
DIR 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 */