示例#1
0
文件: set.c 项目: kdave/neomutt
/**
 * cs_he_initial_get - Get the initial, or parent, value of a config item
 * @param cs     Config items
 * @param he     HashElem representing config item
 * @param result Buffer for results or error messages
 * @retval int Result, e.g. #CSR_SUCCESS
 *
 * If a config item is inherited from another, then this will get the parent's
 * value.  Otherwise, it will get the config item's initial value.
 */
int cs_he_initial_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
{
  if (!cs || !he)
    return CSR_ERR_CODE;

  struct Inheritance *i = NULL;
  const struct ConfigDef *cdef = NULL;
  const struct ConfigSetType *cst = NULL;

  if (he->type & DT_INHERITED)
  {
    i = he->data;
    cdef = i->parent->data;
    cst = cs_get_type_def(cs, i->parent->type);
  }
  else
  {
    cdef = he->data;
    cst = cs_get_type_def(cs, he->type);
  }

  if (!cst)
  {
    mutt_debug(LL_DEBUG1, "Variable '%s' has an invalid type %d\n", cdef->name,
               DTYPE(he->type));
    return CSR_ERR_CODE;
  }

  return cst->string_get(cs, NULL, cdef, result);
}
示例#2
0
文件: set.c 项目: darnir/neomutt
/**
 * cs_str_native_set - Natively set the value of a string config item
 * @param cs    Config items
 * @param name  Name of config item
 * @param value Native pointer/value to set
 * @param err   Buffer for error messages
 * @retval int Result, e.g. #CSR_SUCCESS
 */
int cs_str_native_set(const struct ConfigSet *cs, const char *name,
                      intptr_t value, struct Buffer *err)
{
  if (!cs || !name)
    return CSR_ERR_CODE; /* LCOV_EXCL_LINE */

  struct HashElem *he = cs_get_elem(cs, name);
  if (!he)
  {
    mutt_buffer_printf(err, "Unknown var '%s'", name);
    return CSR_ERR_UNKNOWN;
  }

  const struct ConfigDef *cdef = NULL;
  const struct ConfigSetType *cst = NULL;
  void *var = NULL;

  if (he->type & DT_INHERITED)
  {
    struct Inheritance *i = he->data;
    cdef = i->parent->data;
    var = &i->var;
    cst = cs_get_type_def(cs, i->parent->type);
  }
  else
  {
    cdef = he->data;
    var = cdef->var;
    cst = cs_get_type_def(cs, he->type);
  }

  if (!cst)
  {
    mutt_debug(LL_DEBUG1, "Variable '%s' has an invalid type %d\n", cdef->name, he->type);
    return CSR_ERR_CODE;
  }

  int rc = cst->native_set(cs, var, cdef, value, err);
  if (CSR_RESULT(rc) == CSR_SUCCESS)
  {
    if (he->type & DT_INHERITED)
      he->type = cdef->type | DT_INHERITED;
    if (!(rc & CSR_SUC_NO_CHANGE))
      cs_notify_listeners(cs, he, cdef->name, CE_SET);
  }

  return rc;
}
示例#3
0
文件: set.c 项目: kdave/neomutt
/**
 * destroy - Callback function for the Hash Table - Implements ::hashelem_free_t
 * @param type Object type, e.g. #DT_STRING
 * @param obj  Object to destroy
 * @param data ConfigSet associated with the object
 */
static void destroy(int type, void *obj, intptr_t data)
{
  if (!obj || (data == 0))
    return; /* LCOV_EXCL_LINE */

  struct ConfigSet *cs = (struct ConfigSet *) data;

  const struct ConfigSetType *cst = NULL;

  if (type & DT_INHERITED)
  {
    struct Inheritance *i = obj;
    FREE(&i->name);
    FREE(&i);
  }
  else
  {
    struct ConfigDef *cdef = obj;

    cst = cs_get_type_def(cs, type);
    if (cst && cst->destroy)
      cst->destroy(cs, cdef->var, cdef);

    /* If we allocated the initial value, clean it up */
    if (cdef->type & DT_INITIAL_SET)
      FREE(&cdef->initial);
  }
}
示例#4
0
文件: set.c 项目: kdave/neomutt
/**
 * cs_he_initial_set - Set the initial value of a config item
 * @param cs    Config items
 * @param he    HashElem representing config item
 * @param value Value to set
 * @param err   Buffer for error messages
 * @retval int Result, e.g. #CSR_SUCCESS
 */
int cs_he_initial_set(const struct ConfigSet *cs, struct HashElem *he,
                      const char *value, struct Buffer *err)
{
  if (!cs || !he)
    return CSR_ERR_CODE;

  struct ConfigDef *cdef = NULL;
  const struct ConfigSetType *cst = NULL;

  if (he->type & DT_INHERITED)
  {
    struct Inheritance *i = he->data;
    cdef = i->parent->data;
    mutt_debug(LL_DEBUG1, "Variable '%s' is inherited type\n", cdef->name);
    return CSR_ERR_CODE;
  }

  cdef = he->data;
  cst = cs_get_type_def(cs, he->type);
  if (!cst)
  {
    mutt_debug(LL_DEBUG1, "Variable '%s' has an invalid type %d\n", cdef->name, he->type);
    return CSR_ERR_CODE;
  }

  int rc = cst->string_set(cs, NULL, cdef, value, err);
  if (CSR_RESULT(rc) != CSR_SUCCESS)
    return rc;

  cs_notify_listeners(cs, he, he->key.strkey, CE_INITIAL_SET);
  return CSR_SUCCESS;
}
示例#5
0
文件: set.c 项目: kdave/neomutt
/**
 * reg_one_var - Register one config item
 * @param cs   Config items
 * @param cdef Variable definition
 * @param err  Buffer for error messages
 * @retval ptr New HashElem representing the config item
 */
static struct HashElem *reg_one_var(const struct ConfigSet *cs,
                                    struct ConfigDef *cdef, struct Buffer *err)
{
  if (!cs || !cdef)
    return NULL; /* LCOV_EXCL_LINE */

  if (cdef->type == DT_SYNONYM)
    return create_synonym(cs, cdef, err);

  const struct ConfigSetType *cst = cs_get_type_def(cs, cdef->type);
  if (!cst)
  {
    mutt_buffer_printf(err, "Variable '%s' has an invalid type %d", cdef->name, cdef->type);
    return NULL;
  }

  struct HashElem *he =
      mutt_hash_typed_insert(cs->hash, cdef->name, cdef->type, (void *) cdef);
  if (!he)
    return NULL; /* LCOV_EXCL_LINE */

  if (cst && cst->reset)
    cst->reset(cs, cdef->var, cdef, err);

  return he;
}
示例#6
0
文件: set.c 项目: kdave/neomutt
/**
 * cs_he_string_set - Set a config item by string
 * @param cs    Config items
 * @param he    HashElem representing config item
 * @param value Value to set
 * @param err   Buffer for error messages
 * @retval int Result, e.g. #CSR_SUCCESS
 */
int cs_he_string_set(const struct ConfigSet *cs, struct HashElem *he,
                     const char *value, struct Buffer *err)
{
  if (!cs || !he)
    return CSR_ERR_CODE;

  struct ConfigDef *cdef = NULL;
  const struct ConfigSetType *cst = NULL;
  void *var = NULL;

  if (he->type & DT_INHERITED)
  {
    struct Inheritance *i = he->data;
    cdef = i->parent->data;
    var = &i->var;
    cst = cs_get_type_def(cs, i->parent->type);
  }
  else
  {
    cdef = he->data;
    var = cdef->var;
    cst = cs_get_type_def(cs, he->type);
  }

  if (!cst)
  {
    mutt_debug(LL_DEBUG1, "Variable '%s' has an invalid type %d\n", cdef->name, he->type);
    return CSR_ERR_CODE;
  }

  if (!var)
    return CSR_ERR_CODE; /* LCOV_EXCL_LINE */

  int rc = cst->string_set(cs, var, cdef, value, err);
  if (CSR_RESULT(rc) != CSR_SUCCESS)
    return rc;

  if (he->type & DT_INHERITED)
  {
    struct Inheritance *i = he->data;
    he->type = i->parent->type | DT_INHERITED;
  }
  if (!(rc & CSR_SUC_NO_CHANGE))
    cs_notify_listeners(cs, he, he->key.strkey, CE_SET);
  return rc;
}
示例#7
0
文件: set.c 项目: kdave/neomutt
/**
 * cs_he_string_get - Get a config item as a string
 * @param cs     Config items
 * @param he     HashElem representing config item
 * @param result Buffer for results or error messages
 * @retval int Result, e.g. #CSR_SUCCESS
 */
int cs_he_string_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *result)
{
  if (!cs || !he)
    return CSR_ERR_CODE;

  struct Inheritance *i = NULL;
  const struct ConfigDef *cdef = NULL;
  const struct ConfigSetType *cst = NULL;
  void *var = NULL;

  if (he->type & DT_INHERITED)
  {
    i = he->data;
    cdef = i->parent->data;
    cst = cs_get_type_def(cs, i->parent->type);
  }
  else
  {
    cdef = he->data;
    cst = cs_get_type_def(cs, he->type);
  }

  if ((he->type & DT_INHERITED) && (DTYPE(he->type) != 0))
  {
    var = &i->var; /* Local value */
  }
  else
  {
    var = cdef->var; /* Normal var */
  }

  if (!cst)
  {
    mutt_debug(LL_DEBUG1, "Variable '%s' has an invalid type %d\n", cdef->name,
               DTYPE(he->type));
    return CSR_ERR_CODE;
  }

  return cst->string_get(cs, var, cdef, result);
}
示例#8
0
文件: set.c 项目: kdave/neomutt
/**
 * cs_he_native_get - Natively get the value of a HashElem config item
 * @param cs  Config items
 * @param he  HashElem representing config item
 * @param err Buffer for results or error messages
 * @retval intptr_t Native pointer/value
 */
intptr_t cs_he_native_get(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
{
  if (!cs || !he)
    return INT_MIN;

  struct Inheritance *i = NULL;
  const struct ConfigDef *cdef = NULL;
  const struct ConfigSetType *cst = NULL;
  void *var = NULL;

  if (he->type & DT_INHERITED)
  {
    i = he->data;
    cdef = i->parent->data;
    cst = cs_get_type_def(cs, i->parent->type);
  }
  else
  {
    cdef = he->data;
    cst = cs_get_type_def(cs, he->type);
  }

  if ((he->type & DT_INHERITED) && (DTYPE(he->type) != 0))
  {
    var = &i->var;
  }
  else
  {
    var = cdef->var;
  }

  if (!cst)
  {
    mutt_buffer_printf(err, "Variable '%s' has an invalid type %d", cdef->name, he->type);
    return INT_MIN;
  }

  return cst->native_get(cs, var, cdef, err);
}
示例#9
0
文件: set.c 项目: kdave/neomutt
/**
 * cs_he_reset - Reset a config item to its initial value
 * @param cs   Config items
 * @param he   HashElem representing config item
 * @param err  Buffer for error messages
 * @retval int Result, e.g. #CSR_SUCCESS
 */
int cs_he_reset(const struct ConfigSet *cs, struct HashElem *he, struct Buffer *err)
{
  if (!cs || !he)
    return CSR_ERR_CODE;

  /* An inherited var that's already pointing to its parent.
   * Return 'success', but don't send a notification. */
  if ((he->type & DT_INHERITED) && (DTYPE(he->type) == 0))
    return CSR_SUCCESS;

  const struct ConfigSetType *cst = NULL;
  const struct ConfigDef *cdef = NULL;

  int rc = CSR_SUCCESS;

  if (he->type & DT_INHERITED)
  {
    struct Inheritance *i = he->data;
    cst = cs_get_type_def(cs, i->parent->type);
    cdef = i->parent->data;

    if (cst && cst->destroy)
      cst->destroy(cs, (void **) &i->var, cdef);

    he->type = DT_INHERITED;
  }
  else
  {
    cst = cs_get_type_def(cs, he->type);
    cdef = he->data;

    if (cst)
      rc = cst->reset(cs, cdef->var, cdef, err);
  }

  if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
    cs_notify_listeners(cs, he, he->key.strkey, CE_RESET);
  return rc;
}
示例#10
0
文件: dump.c 项目: kdave/neomutt
/**
 * dump_config_neo - Dump the config in the style of NeoMutt
 * @param cs      Config items
 * @param he      HashElem representing config item
 * @param value   Current value of the config item
 * @param initial Initial value of the config item
 * @param flags   Flags, see #ConfigDumpFlags
 * @param fp      File pointer to write to
 */
void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value,
                     struct Buffer *initial, ConfigDumpFlags flags, FILE *fp)
{
  if (!he || !value || !initial || !fp)
    return;

  const char *name = he->key.strkey;

  if ((flags & CS_DUMP_ONLY_CHANGED) && (mutt_str_strcmp(value->data, initial->data) == 0))
    return;

  if (he->type == DT_SYNONYM)
  {
    const struct ConfigDef *cdef = he->data;
    const char *syn = (const char *) cdef->initial;
    fprintf(fp, "# synonym: %s -> %s\n", name, syn);
    return;
  }

  bool show_name = !(flags & CS_DUMP_HIDE_NAME);
  bool show_value = !(flags & CS_DUMP_HIDE_VALUE);

  if (show_name && show_value)
    fprintf(fp, "set ");
  if (show_name)
    fprintf(fp, "%s", name);
  if (show_name && show_value)
    fprintf(fp, " = ");
  if (show_value)
    fprintf(fp, "%s", value->data);
  if (show_name || show_value)
    fprintf(fp, "\n");

  if (flags & CS_DUMP_SHOW_DEFAULTS)
  {
    const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
    if (cst)
      fprintf(fp, "# %s %s %s\n", cst->name, name, value->data);
  }
}
示例#11
0
文件: set.c 项目: darnir/neomutt
void config_set(void)
{
  log_line(__func__);

  struct Buffer err;
  mutt_buffer_init(&err);
  err.dsize = 256;
  err.data = mutt_mem_calloc(1, err.dsize);
  mutt_buffer_reset(&err);

  struct ConfigSet *cs = cs_new(30);
  if (!TEST_CHECK(cs != NULL))
    return;

  cs_add_listener(cs, log_listener);
  cs_add_listener(cs, log_listener); /* dupe */
  cs_remove_listener(cs, log_listener);
  cs_remove_listener(cs, log_listener); /* non-existant */

  const struct ConfigSetType cst_dummy = {
    "dummy", NULL, NULL, NULL, NULL, NULL, NULL,
  };

  if (TEST_CHECK(!cs_register_type(cs, DT_STRING, &cst_dummy)))
  {
    TEST_MSG("Expected error\n");
  }
  else
  {
    TEST_MSG("This test should have failed\n");
    return;
  }

  const struct ConfigSetType cst_dummy2 = {
    "dummy2",         dummy_string_set, dummy_string_get, dummy_native_set,
    dummy_native_get, dummy_reset,      dummy_destroy,
  };

  if (TEST_CHECK(!cs_register_type(cs, 25, &cst_dummy2)))
  {
    TEST_MSG("Expected error\n");
  }
  else
  {
    TEST_MSG("This test should have failed\n");
    return;
  }

  bool_init(cs);
  bool_init(cs); /* second one should fail */

  if (TEST_CHECK(!cs_register_variables(cs, Vars, 0)))
  {
    TEST_MSG("Expected error\n");
  }
  else
  {
    TEST_MSG("This test should have failed\n");
    return;
  }

  const char *name = "Unknown";
  int result = cs_str_string_set(cs, name, "hello", &err);
  if (TEST_CHECK(CSR_RESULT(result) == CSR_ERR_UNKNOWN))
  {
    TEST_MSG("Expected error: Unknown var '%s'\n", name);
  }
  else
  {
    TEST_MSG("This should have failed 1\n");
    return;
  }

  result = cs_str_string_get(cs, name, &err);
  if (TEST_CHECK(CSR_RESULT(result) == CSR_ERR_UNKNOWN))
  {
    TEST_MSG("Expected error: Unknown var '%s'\n", name);
  }
  else
  {
    TEST_MSG("This should have failed 2\n");
    return;
  }

  result = cs_str_native_set(cs, name, IP "hello", &err);
  if (TEST_CHECK(CSR_RESULT(result) == CSR_ERR_UNKNOWN))
  {
    TEST_MSG("Expected error: Unknown var '%s'\n", name);
  }
  else
  {
    TEST_MSG("This should have failed 3\n");
    return;
  }

  intptr_t native = cs_str_native_get(cs, name, &err);
  if (TEST_CHECK(native == INT_MIN))
  {
    TEST_MSG("Expected error: Unknown var '%s'\n", name);
  }
  else
  {
    TEST_MSG("This should have failed 4\n");
    return;
  }

  struct HashElem *he = cs_get_elem(cs, "Banana");
  if (!TEST_CHECK(he != NULL))
    return;

  set_list(cs);

  const struct ConfigSetType *cst = cs_get_type_def(cs, 15);
  if (!TEST_CHECK(!cst))
    return;

  cs_free(&cs);
  FREE(&err.data);
  log_line(__func__);
}