cmd.c - 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.c (5164B)
---
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 #include "cmd.h"
18
19 #include <string.h>
20
21 #include "err.h"
22 #include "ltkd.h"
23 #include "widget.h"
24
25 #include <ltk/ltk.h>
26 #include <ltk/util.h>
27 #include <ltk/color.h>
28 #include <ltk/graphics.h>
29
30 int
31 ltkd_parse_cmd(
32 ltkd_cmd_token *tokens, size_t num_tokens,
33 ltkd_cmdarg_parseinfo *parseinfo, size_t num_arg, ltkd_error *err) {
34 const char *errstr = NULL;
35 ltk_renderdata *renderdata = ltk_get_renderer();
36 if (num_tokens > num_arg || (num_tokens < num_arg && !parseinfo[num_tokens].optional)) {
37 err->type = ERR_INVALID_NUMBER_OF_ARGUMENTS;
38 err->arg = -1;
39 return 1;
40 }
41 size_t i = 0;
42 for (; i < num_tokens; i++) {
43 if (parseinfo[i].type != CMDARG_DATA && tokens[i].contains_nul) {
44 err->type = ERR_INVALID_ARGUMENT;
45 err->arg = i;
46 goto error;
47 }
48 switch (parseinfo[i].type) {
49 case CMDARG_INT:
50 parseinfo[i].val.i = ltk_strtonum(tokens[i].text, parseinfo[i].min, parseinfo[i].max, &errstr);
51 if (errstr) {
52 err->type = ERR_INVALID_ARGUMENT;
53 err->arg = i;
54 goto error;
55 }
56 parseinfo[i].initialized = 1;
57 break;
58 case CMDARG_STICKY:
59 parseinfo[i].val.sticky = LTK_STICKY_NONE;
60 for (const char *c = tokens[i].text; *c != '\0'; c++) {
61 switch (*c) {
62 case 't':
63 parseinfo[i].val.sticky |= LTK_STICKY_TOP;
64 break;
65 case 'b':
66 parseinfo[i].val.sticky |= LTK_STICKY_BOTTOM;
67 break;
68 case 'r':
69 parseinfo[i].val.sticky |= LTK_STICKY_RIGHT;
70 break;
71 case 'l':
72 parseinfo[i].val.sticky |= LTK_STICKY_LEFT;
73 break;
74 case 'w':
75 parseinfo[i].val.sticky |= LTK_STICKY_SHRINK_WIDTH;
76 break;
77 case 'h':
78 parseinfo[i].val.sticky |= LTK_STICKY_SHRINK_HEIGHT;
79 break;
80 case 'p':
81 parseinfo[i].val.sticky |= LTK_STICKY_PRESERVE_ASPECT_RATIO;
82 break;
83 default:
84 err->type = ERR_INVALID_ARGUMENT;
85 err->arg = i;
86 goto error;
87 }
88 }
89 parseinfo[i].initialized = 1;
90 break;
91 case CMDARG_WIDGET:
92 parseinfo[i].val.widget = ltkd_get_widget(tokens[i].text, parseinfo[i].widget_type, err);
93 if (!parseinfo[i].val.widget) {
94 err->arg = i;
95 goto error;
96 }
97 parseinfo[i].initialized = 1;
98 break;
99 case CMDARG_STRING:
100 parseinfo[i].val.str = tokens[i].text;
101 parseinfo[i].initialized = 1;
102 break;
103 case CMDARG_DATA:
104 parseinfo[i].val.data = tokens[i].text;
105 parseinfo[i].initialized = 1;
106 parseinfo[i].len = tokens[i].len;
107 break;
108 case CMDARG_COLOR:
109 if (!(parseinfo[i].val.color = ltk_color_create(renderdata, tokens[i].text))) {
110 /* FIXME: this could fail even if the argument is fine */
111 err->type = ERR_INVALID_ARGUMENT;
112 err->arg = i;
113 goto error;
114 }
115 parseinfo[i].initialized = 1;
116 break;
117 case CMDARG_BOOL:
118 if (strcmp(tokens[i].text, "true") == 0) {
119 parseinfo[i].val.b = 1;
120 } else if (strcmp(tokens[i].text, "false") == 0) {
121 parseinfo[i].val.b = 0;
122 } else {
123 err->type = ERR_INVALID_ARGUMENT;
124 err->arg = i;
125 goto error;
126 }
127 parseinfo[i].initialized = 1;
128 break;
129 case CMDARG_ORIENTATION:
130 if (strcmp(tokens[i].text, "horizontal") == 0) {
131 parseinfo[i].val.orient = LTK_HORIZONTAL;
132 } else if (strcmp(tokens[i].text, "vertical") == 0) {
133 parseinfo[i].val.orient = LTK_VERTICAL;
134 } else {
135 err->type = ERR_INVALID_ARGUMENT;
136 err->arg = i;
137 goto error;
138 }
139 parseinfo[i].initialized = 1;
140 break;
141 case CMDARG_BORDERSIDES:
142 parseinfo[i].val.border = LTK_BORDER_NONE;
143 for (const char *c = tokens[i].text; *c != '\0'; c++) {
144 switch (*c) {
145 case 't':
146 parseinfo[i].val.border |= LTK_BORDER_TOP;
147 break;
148 case 'b':
149 parseinfo[i].val.border |= LTK_BORDER_BOTTOM;
150 break;
151 case 'l':
152 parseinfo[i].val.border |= LTK_BORDER_LEFT;
153 break;
154 case 'r':
155 parseinfo[i].val.border |= LTK_BORDER_RIGHT;
156 break;
157 default:
158 err->type = ERR_INVALID_ARGUMENT;
159 err->arg = i;
160 goto error;
161 }
162 }
163 parseinfo[i].initialized = 1;
164 break;
165 case CMDARG_IGNORE:
166 parseinfo[i].initialized = 1;
167 break;
168 default:
169 ltkd_fatal("Invalid command argument type. This should not happen.\n");
170 /* TODO: ltk_assert(0); */
171 }
172 }
173 for (; i < num_arg; i++) {
174 parseinfo[i].initialized = 0;
175 }
176 return 0;
177 error:
178 for (; i-- > 0;) {
179 if (parseinfo[i].type == CMDARG_COLOR) {
180 ltk_color_destroy(renderdata, parseinfo[i].val.color);
181 }
182 parseinfo[i].initialized = 0;
183 }
184 return 1;
185 }