URI: 
       cmd.h - 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.h (5382B)
       ---
            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 #ifndef LTKD_CMD_H
           18 #define LTKD_CMD_H
           19 
           20 #include <stddef.h>
           21 
           22 #include "err.h"
           23 #include "ltkd.h"
           24 #include "widget.h"
           25 
           26 #include <ltk/ltk.h>
           27 #include <ltk/util.h>
           28 #include <ltk/color.h>
           29 #include <ltk/graphics.h>
           30 
           31 typedef struct {
           32         char *name;
           33         int (*func)(ltk_window *, ltkd_widget *, ltkd_cmd_token *, size_t, ltkd_error *);
           34         int needs_all;
           35 } ltkd_cmd_info;
           36 
           37 typedef enum {
           38         CMDARG_IGNORE,
           39         CMDARG_STRING, /* nul-terminated string */
           40         CMDARG_DATA,   /* also char*, but may contain nul */
           41         CMDARG_COLOR,
           42         CMDARG_INT,
           43         CMDARG_BOOL,
           44         CMDARG_BORDERSIDES,
           45         CMDARG_STICKY,
           46         CMDARG_WIDGET,
           47         CMDARG_ORIENTATION
           48 } ltkd_cmdarg_datatype;
           49 
           50 /* color needs to be destroyed by cmd handling function if it is not needed anymore */
           51 /* str must *not* be freed because it is a pointer to the original argument
           52    -> it must be copied if it needs to be kept around */
           53 typedef struct {
           54         ltkd_cmdarg_datatype type;
           55         /* Note: Bool and int are both integers, but they are
           56            separate just to make it a bit clearer (same goes for str/data) */
           57         union {
           58                 char *str;
           59                 char *data;
           60                 ltk_color *color;
           61                 int i;
           62                 int b;
           63                 ltk_border_sides border;
           64                 ltk_sticky_mask sticky;
           65                 ltk_orientation orient;
           66                 ltkd_widget *widget;
           67         } val;
           68         size_t len; /* only for data */
           69         int min, max; /* only for integers */ /* FIXME: which integer type is sensible here? */
           70         ltk_widget_type widget_type; /* only for widgets */
           71         int optional;
           72         int initialized;
           73 } ltkd_cmdarg_parseinfo;
           74 
           75 /* Returns 1 on error, 0 on success */
           76 /* All optional arguments must be in one block at the end */
           77 int ltkd_parse_cmd(
           78     ltkd_cmd_token *tokens, size_t num_tokens,
           79     ltkd_cmdarg_parseinfo *parseinfo, size_t num_arg, ltkd_error *err
           80 );
           81 
           82 /* FIXME: This doesn't really need to be a macro anymore since it doesn't have to be generic for different types anymore */
           83 #define GEN_CMD_HELPERS_PROTO(func_name)                                                                        \
           84 int func_name(ltk_window *window, ltkd_cmd_token *tokens, size_t num_tokens, ltkd_error *err);
           85 
           86 
           87 #define GEN_CMD_HELPERS(func_name, widget_type, array_name)                                                        \
           88 /* FIXME: maybe just get rid of this and rely on array already being sorted? */                                        \
           89 static int array_name##_sorted = 0;                                                                                \
           90                                                                                                                 \
           91 static int                                                                                                        \
           92 array_name##_search_helper(const void *keyv, const void *entryv) {                                                \
           93         const char *key = (const char *)keyv;                                                                        \
           94         ltkd_cmd_info *entry = (ltkd_cmd_info *)entryv;                                                                \
           95         return strcmp(key, entry->name);                                                                        \
           96 }                                                                                                                \
           97                                                                                                                 \
           98 static int                                                                                                        \
           99 array_name##_sort_helper(const void *entry1v, const void *entry2v) {                                                \
          100         ltkd_cmd_info *entry1 = (ltkd_cmd_info *)entry1v;                                                        \
          101         ltkd_cmd_info *entry2 = (ltkd_cmd_info *)entry2v;                                                        \
          102         return strcmp(entry1->name, entry2->name);                                                                \
          103 }                                                                                                                \
          104                                                                                                                 \
          105 int                                                                                                                \
          106 func_name(                                                                                                        \
          107     ltk_window *window,                                                                                                \
          108     ltkd_cmd_token *tokens,                                                                                        \
          109     size_t num_tokens,                                                                                                \
          110     ltkd_error *err) {                                                                                                \
          111         if (num_tokens < 3) {                                                                                        \
          112                 err->type = ERR_INVALID_NUMBER_OF_ARGUMENTS;                                                        \
          113                 err->arg = -1;                                                                                        \
          114                 return 1;                                                                                        \
          115         }                                                                                                        \
          116         /* just in case */                                                                                        \
          117         if (!array_name##_sorted) {                                                                                \
          118                 qsort(                                                                                                \
          119                     array_name, LENGTH(array_name),                                                                \
          120                     sizeof(array_name[0]), &array_name##_sort_helper);                                                \
          121                 array_name##_sorted = 1;                                                                        \
          122         }                                                                                                        \
          123         if (tokens[1].contains_nul) {                                                                                \
          124                 err->type = ERR_INVALID_ARGUMENT;                                                                \
          125                 err->arg = 1;                                                                                        \
          126                 return 1;                                                                                        \
          127         } else if (tokens[2].contains_nul) {                                                                        \
          128                 err->type = ERR_INVALID_ARGUMENT;                                                                \
          129                 err->arg = 2;                                                                                        \
          130                 return 1;                                                                                        \
          131         }                                                                                                        \
          132         ltkd_cmd_info *e = bsearch(                                                                                \
          133             tokens[2].text, array_name, LENGTH(array_name),                                                        \
          134             sizeof(array_name[0]), &array_name##_search_helper                                                        \
          135         );                                                                                                        \
          136         if (!e) {                                                                                                \
          137                 err->type = ERR_INVALID_COMMAND;                                                                \
          138                 err->arg = -1;                                                                                        \
          139                 return 1;                                                                                        \
          140         }                                                                                                        \
          141         if (e->needs_all) {                                                                                        \
          142                 return e->func(window, NULL, tokens, num_tokens, err);                                                \
          143         } else {                                                                                                \
          144                 ltkd_widget *widget = ltkd_get_widget(tokens[1].text, widget_type, err);                        \
          145                 if (!widget) {                                                                                        \
          146                         err->arg = 1;                                                                                \
          147                         return 1;                                                                                \
          148                 }                                                                                                \
          149                 int ret = e->func(window, widget, tokens + 3, num_tokens - 3, err);                                \
          150                 if (ret && err->arg >= 0)                                                                        \
          151                         err->arg += 3;                                                                                \
          152                 return ret;                                                                                        \
          153         }                                                                                                        \
          154         return 0; /* Well, I guess this is impossible anyways... */                                                \
          155 }
          156 
          157 #endif /* LTKD_CMD_H */