1 /** 2 * @file 3 * A collection of config items 4 * 5 * @authors 6 * Copyright (C) 2017-2018 Richard Russon <rich@flatcap.org> 7 * 8 * @copyright 9 * This program is free software: you can redistribute it and/or modify it under 10 * the terms of the GNU General Public License as published by the Free Software 11 * Foundation, either version 2 of the License, or (at your option) any later 12 * version. 13 * 14 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17 * details. 18 * 19 * You should have received a copy of the GNU General Public License along with 20 * this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 #ifndef MUTT_CONFIG_SET_H 24 #define MUTT_CONFIG_SET_H 25 26 #include <stdbool.h> 27 #include <stdint.h> 28 #include <stdio.h> 29 30 struct Buffer; 31 struct ConfigSet; 32 struct HashElem; 33 34 /* Config Set Results */ 35 #define CSR_SUCCESS 0 ///< Action completed successfully 36 #define CSR_ERR_CODE 1 ///< Problem with the code 37 #define CSR_ERR_UNKNOWN 2 ///< Unrecognised config item 38 #define CSR_ERR_INVALID 3 ///< Value hasn't been set 39 40 /* Flags for CSR_SUCCESS */ 41 #define CSR_SUC_INHERITED (1 << 4) ///< Value is inherited 42 #define CSR_SUC_EMPTY (1 << 5) ///< Value is empty/unset 43 #define CSR_SUC_WARNING (1 << 6) ///< Notify the user of a warning 44 #define CSR_SUC_NO_CHANGE (1 << 7) ///< The value hasn't changed 45 46 /* Flags for CSR_INVALID */ 47 #define CSR_INV_TYPE (1 << 4) ///< Value is not valid for the type 48 #define CSR_INV_VALIDATOR (1 << 5) ///< Value was rejected by the validator 49 #define CSV_INV_NOT_IMPL (1 << 6) ///< Operation not permitted for the type 50 51 #define CSR_RESULT_MASK 0x0F 52 #define CSR_RESULT(x) ((x) & CSR_RESULT_MASK) 53 54 #define IP (intptr_t) 55 56 /** 57 * @defgroup cfg_def_api Config Definition API 58 * 59 * Config item definition 60 * 61 * Every config variable that NeoMutt supports is backed by a ConfigDef. 62 */ 63 struct ConfigDef 64 { 65 const char *name; ///< User-visible name 66 uint32_t type; ///< Variable type, e.g. #DT_STRING 67 intptr_t initial; ///< Initial value 68 intptr_t data; ///< Extra variable data 69 70 /** 71 * @defgroup cfg_def_validator validator() 72 * @ingroup cfg_def_api 73 * 74 * validator - Validate a config variable 75 * @param cs Config items 76 * @param cdef Config definition 77 * @param value Native value 78 * @param err Message for the user 79 * @retval #CSR_SUCCESS Success 80 * @retval #CSR_ERR_INVALID Failure 81 */ 82 int (*validator)(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err); 83 84 const char *docs; ///< One-liner description 85 intptr_t var; ///< Storage for the variable 86 }; 87 88 /** 89 * @defgroup cfg_type_api Config Type API 90 * 91 * Type definition for a config item 92 * 93 * Each config item has a type which is defined by a set of callback functions. 94 */ 95 struct ConfigSetType 96 { 97 int type; ///< Data type, e.g. #DT_STRING 98 const char *name; ///< Name of the type, e.g. "String" 99 100 /** 101 * @defgroup cfg_type_string_set string_set() 102 * @ingroup cfg_type_api 103 * 104 * string_set - Set a config item by string 105 * @param cs Config items 106 * @param var Variable to set (may be NULL) 107 * @param cdef Variable definition 108 * @param value Value to set (may be NULL) 109 * @param err Buffer for error messages (may be NULL) 110 * @retval num Result, e.g. #CSR_SUCCESS 111 * 112 * If var is NULL, then the config item's initial value will be set. 113 * 114 * **Contract** 115 * - @a cs is not NULL 116 * - @a cdef is not NULL 117 */ 118 int (*string_set)(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef, const char *value, struct Buffer *err); 119 120 /** 121 * @defgroup cfg_type_string_get string_get() 122 * @ingroup cfg_type_api 123 * 124 * string_get - Get a config item as a string 125 * @param cs Config items 126 * @param var Variable to get (may be NULL) 127 * @param cdef Variable definition 128 * @param result Buffer for results or error messages 129 * @retval num Result, e.g. #CSR_SUCCESS 130 * 131 * If var is NULL, then the config item's initial value will be returned. 132 * 133 * **Contract** 134 * - @a cs is not NULL 135 * - @a cdef is not NULL 136 * - @a result is not NULL 137 */ 138 int (*string_get)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *result); 139 140 /** 141 * @defgroup cfg_type_native_set native_set() 142 * @ingroup cfg_type_api 143 * 144 * native_set - Set a config item by string 145 * @param cs Config items 146 * @param var Variable to set 147 * @param cdef Variable definition 148 * @param value Native pointer/value to set 149 * @param err Buffer for error messages (may be NULL) 150 * @retval num Result, e.g. #CSR_SUCCESS 151 * 152 * **Contract** 153 * - @a cs is not NULL 154 * - @a var is not NULL 155 * - @a cdef is not NULL 156 */ 157 int (*native_set)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err); 158 159 /** 160 * @defgroup cfg_type_native_get native_get() 161 * @ingroup cfg_type_api 162 * 163 * native_get - Get a string from a config item 164 * @param cs Config items 165 * @param var Variable to get 166 * @param cdef Variable definition 167 * @param err Buffer for error messages (may be NULL) 168 * @retval intptr_t Config item string 169 * @retval INT_MIN Error 170 * 171 * **Contract** 172 * - @a cs is not NULL 173 * - @a var is not NULL 174 * - @a cdef is not NULL 175 */ 176 intptr_t (*native_get)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err); 177 178 /** 179 * @defgroup cfg_type_string_plus_equals string_plus_equals() 180 * @ingroup cfg_type_api 181 * 182 * string_plus_equals - Add to a config item by string 183 * @param cs Config items 184 * @param var Variable to set 185 * @param cdef Variable definition 186 * @param value Value to set 187 * @param err Buffer for error messages (may be NULL) 188 * @retval num Result, e.g. #CSR_SUCCESS 189 * 190 * **Contract** 191 * - @a cs is not NULL 192 * - @a var is not NULL 193 * - @a cdef is not NULL 194 */ 195 int (*string_plus_equals)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, const char *value, struct Buffer *err); 196 197 /** 198 * @defgroup cfg_type_string_minus_equals string_minus_equals() 199 * @ingroup cfg_type_api 200 * 201 * string_minus_equals - Remove from a config item as a string 202 * @param cs Config items 203 * @param var Variable to set 204 * @param cdef Variable definition 205 * @param value Value to set 206 * @param err Buffer for error messages (may be NULL) 207 * @retval num Result, e.g. #CSR_SUCCESS 208 * 209 * **Contract** 210 * - @a cs is not NULL 211 * - @a var is not NULL 212 * - @a cdef is not NULL 213 */ 214 int (*string_minus_equals)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, const char *value, struct Buffer *err); 215 216 /** 217 * @defgroup cfg_type_reset reset() 218 * @ingroup cfg_type_api 219 * 220 * reset - Reset a config item to its initial value 221 * @param cs Config items 222 * @param var Variable to reset 223 * @param cdef Variable definition 224 * @param err Buffer for error messages (may be NULL) 225 * @retval num Result, e.g. #CSR_SUCCESS 226 * 227 * **Contract** 228 * - @a cs is not NULL 229 * - @a var is not NULL 230 * - @a cdef is not NULL 231 */ 232 int (*reset)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err); 233 234 /** 235 * @defgroup cfg_type_destroy destroy() 236 * @ingroup cfg_type_api 237 * 238 * destroy - Destroy a config item 239 * @param cs Config items 240 * @param var Variable to destroy 241 * @param cdef Variable definition 242 * 243 * **Contract** 244 * - @a cs is not NULL 245 * - @a var is not NULL 246 * - @a cdef is not NULL 247 */ 248 void (*destroy)(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef); 249 }; 250 251 /** 252 * struct ConfigSet - Container for lots of config items 253 * 254 * The config items are stored in a HashTable so that their names can be looked 255 * up efficiently. Each config item is represented by a HashElem. Once 256 * created, this HashElem is static and may be used for the lifetime of the 257 * ConfigSet. 258 */ 259 struct ConfigSet 260 { 261 struct HashTable *hash; ///< HashTable storing the config items 262 struct ConfigSetType types[18]; ///< All the defined config types 263 }; 264 265 struct ConfigSet *cs_new(size_t size); 266 void cs_free(struct ConfigSet **ptr); 267 268 struct HashElem * cs_get_base (struct HashElem *he); 269 struct HashElem * cs_get_elem (const struct ConfigSet *cs, const char *name); 270 const struct ConfigSetType *cs_get_type_def(const struct ConfigSet *cs, unsigned int type); 271 272 bool cs_register_type (struct ConfigSet *cs, const struct ConfigSetType *cst); 273 bool cs_register_variables(const struct ConfigSet *cs, struct ConfigDef vars[], uint32_t flags); 274 struct HashElem *cs_inherit_variable (const struct ConfigSet *cs, struct HashElem *parent, const char *name); 275 void cs_uninherit_variable(const struct ConfigSet *cs, const char *name); 276 277 int cs_he_initial_get (const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result); 278 int cs_he_initial_set (const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err); 279 intptr_t cs_he_native_get (const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err); 280 int cs_he_native_set (const struct ConfigSet *cs, struct HashElem *he, intptr_t value, struct Buffer *err); 281 int cs_he_reset (const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err); 282 int cs_he_string_get (const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result); 283 int cs_he_string_minus_equals (const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err); 284 int cs_he_string_plus_equals (const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err); 285 int cs_he_string_set (const struct ConfigSet *cs, struct HashElem *he, const char *value, struct Buffer *err); 286 287 int cs_str_initial_get (const struct ConfigSet *cs, const char *name, struct Buffer *result); 288 int cs_str_initial_set (const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err); 289 intptr_t cs_str_native_get (const struct ConfigSet *cs, const char *name, struct Buffer *err); 290 int cs_str_native_set (const struct ConfigSet *cs, const char *name, intptr_t value, struct Buffer *err); 291 int cs_str_reset (const struct ConfigSet *cs, const char *name, struct Buffer *err); 292 int cs_str_string_get (const struct ConfigSet *cs, const char *name, struct Buffer *result); 293 int cs_str_string_minus_equals(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err); 294 int cs_str_string_plus_equals (const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err); 295 int cs_str_string_set (const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err); 296 297 #endif /* MUTT_CONFIG_SET_H */ 298