URI: 
       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 }