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.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 }