cmd.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 */