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.c (4229B)


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