s4:dns_server: no-op dns updates with ACCESS_DENIED should be ignored
[samba.git] / source3 / utils / regedit_valuelist.c
index 4922cdb388f3d66dd1936337f5ac892d4819189d..78ea3fad72b6e56fd676831453bcde645d0c8558 100644 (file)
@@ -17,6 +17,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "includes.h"
+#include "regedit.h"
 #include "regedit_valuelist.h"
 #include "regedit_list.h"
 #include "lib/registry/registry.h"
@@ -54,21 +56,26 @@ static const char *vl_get_column_header(const void *data, unsigned col)
 
 static const void *vl_get_first_row(const void *data)
 {
-       const struct value_list *vl = data;
+       const struct value_list *vl;
 
-       if (vl && vl->nvalues) {
-               return &vl->values[0];
+       if (data) {
+               vl = talloc_get_type_abort(data, struct value_list);
+               if (vl->nvalues) {
+                       return &vl->values[0];
+               }
        }
+
        return NULL;
 }
 
 static const void *vl_get_next_row(const void *data, const void *row)
 {
-       const struct value_list *vl = data;
+       const struct value_list *vl;
        const struct value_item *value = row;
 
-       SMB_ASSERT(vl != NULL);
+       SMB_ASSERT(data != NULL);
        SMB_ASSERT(value != NULL);
+       vl = talloc_get_type_abort(data, struct value_list);
        if (value == &vl->values[vl->nvalues - 1]) {
                return NULL;
        }
@@ -78,11 +85,12 @@ static const void *vl_get_next_row(const void *data, const void *row)
 
 static const void *vl_get_prev_row(const void *data, const void *row)
 {
-       const struct value_list *vl = data;
+       const struct value_list *vl;
        const struct value_item *value = row;
 
-       SMB_ASSERT(vl != NULL);
+       SMB_ASSERT(data != NULL);
        SMB_ASSERT(value != NULL);
+       vl = talloc_get_type_abort(data, struct value_list);
        if (value == &vl->values[0]) {
                return NULL;
        }
@@ -161,11 +169,11 @@ fail:
        return NULL;
 }
 
-void value_list_set_selected(struct value_list *vl, bool select)
+void value_list_set_selected(struct value_list *vl, bool reverse)
 {
        attr_t attr = A_NORMAL;
 
-       if (select) {
+       if (reverse) {
                attr = A_REVERSE;
        }
        mvwchgat(vl->window, 0, HEADING_X, 5, attr, 0, NULL);
@@ -177,7 +185,14 @@ void value_list_resize(struct value_list *vl, int nlines, int ncols,
        WINDOW *nwin, *nsub;
 
        nwin = newwin(nlines, ncols, begin_y, begin_x);
+       if (nwin == NULL) {
+               return;
+       }
        nsub = subwin(nwin, nlines - 2, ncols - 2, begin_y + 1, begin_x + 1);
+       if (nsub == NULL) {
+               delwin(nwin);
+               return;
+       }
        replace_panel(vl->panel, nwin);
        delwin(vl->sub);
        delwin(vl->window);
@@ -275,7 +290,7 @@ static WERROR append_data_summary(TALLOC_CTX *ctx, struct value_item *vitem)
                }
                tmp = talloc_asprintf(ctx, "(%u) ", (unsigned)len);
                if (tmp == NULL) {
-                       return WERR_NOMEM;
+                       return WERR_NOT_ENOUGH_MEMORY;
                }
                for (i = 0; i < len; ++i) {
                        if (!string_is_printable(a[i])) {
@@ -294,7 +309,7 @@ static WERROR append_data_summary(TALLOC_CTX *ctx, struct value_item *vitem)
                                                             (unsigned)i, val);
                        }
                        if (tmp == NULL) {
-                               return WERR_NOMEM;
+                               return WERR_NOT_ENOUGH_MEMORY;
                        }
                }
                break;
@@ -309,7 +324,7 @@ static WERROR append_data_summary(TALLOC_CTX *ctx, struct value_item *vitem)
        }
 
        if (tmp == NULL) {
-               return WERR_NOMEM;
+               return WERR_NOT_ENOUGH_MEMORY;
        }
 
        vitem->value = tmp;
@@ -322,7 +337,8 @@ static int vitem_cmp(struct value_item *a, struct value_item *b)
        return strcmp(a->value_name, b->value_name);
 }
 
-WERROR value_list_load(struct value_list *vl, struct registry_key *key)
+/* load only the value names into memory to enable searching */
+WERROR value_list_load_quick(struct value_list *vl, struct registry_key *key)
 {
        uint32_t nvalues;
        uint32_t idx;
@@ -340,7 +356,7 @@ WERROR value_list_load(struct value_list *vl, struct registry_key *key)
 
        new_items = talloc_zero_array(vl, struct value_item, nvalues);
        if (new_items == NULL) {
-               return WERR_NOMEM;
+               return WERR_NOT_ENOUGH_MEMORY;
        }
 
        for (idx = 0; idx < nvalues; ++idx) {
@@ -353,18 +369,28 @@ WERROR value_list_load(struct value_list *vl, struct registry_key *key)
                        talloc_free(new_items);
                        return rv;
                }
+       }
+
+       TYPESAFE_QSORT(new_items, nvalues, vitem_cmp);
+       vl->nvalues = nvalues;
+       vl->values = new_items;
+
+       return rv;
+}
+
+/* sync up the UI with the list */
+WERROR value_list_sync(struct value_list *vl)
+{
+       uint32_t idx;
+       WERROR rv;
 
-               rv = append_data_summary(new_items, vitem);
+       for (idx = 0; idx < vl->nvalues; ++idx) {
+               rv = append_data_summary(vl->values, &vl->values[idx]);
                if (!W_ERROR_IS_OK(rv)) {
-                       talloc_free(new_items);
                        return rv;
                }
        }
 
-       TYPESAFE_QSORT(new_items, nvalues, vitem_cmp);
-
-       vl->nvalues = nvalues;
-       vl->values = new_items;
        rv = multilist_set_data(vl->list, vl);
        if (W_ERROR_IS_OK(rv)) {
                multilist_refresh(vl->list);
@@ -373,12 +399,97 @@ WERROR value_list_load(struct value_list *vl, struct registry_key *key)
        return rv;
 }
 
+WERROR value_list_load(struct value_list *vl, struct registry_key *key)
+{
+       WERROR rv;
+
+       rv = value_list_load_quick(vl, key);
+       if (!W_ERROR_IS_OK(rv)) {
+               return rv;
+       }
+
+       rv = value_list_sync(vl);
+
+       return rv;
+}
+
+struct value_item *value_list_find_next_item(struct value_list *vl,
+                                            struct value_item *vitem,
+                                            const char *s,
+                                            regedit_search_match_fn_t match)
+{
+       struct value_item *end;
+
+       if (!vl->values) {
+               return NULL;
+       }
+
+       if (vitem) {
+               ++vitem;
+       } else {
+               vitem = &vl->values[0];
+       }
+
+       for (end = &vl->values[vl->nvalues]; vitem < end; ++vitem) {
+               if (match(vitem->value_name, s)) {
+                       return vitem;
+               }
+       }
+
+       return NULL;
+}
+
+struct value_item *value_list_find_prev_item(struct value_list *vl,
+                                            struct value_item *vitem,
+                                            const char *s,
+                                            regedit_search_match_fn_t match)
+{
+       struct value_item *end;
+
+       if (!vl->values) {
+               return NULL;
+       }
+
+       if (vitem) {
+               --vitem;
+       } else {
+               vitem = &vl->values[vl->nvalues - 1];
+       }
+
+       for (end = &vl->values[-1]; vitem > end; --vitem) {
+               if (match(vitem->value_name, s)) {
+                       return vitem;
+               }
+       }
+
+       return NULL;
+}
+
 struct value_item *value_list_get_current_item(struct value_list *vl)
 {
        return discard_const_p(struct value_item,
                               multilist_get_current_row(vl->list));
 }
 
+void value_list_set_current_item_by_name(struct value_list *vl,
+                                        const char *name)
+{
+       size_t i;
+
+       for (i = 0; i < vl->nvalues; ++i) {
+               if (strequal(vl->values[i].value_name, name)) {
+                       multilist_set_current_row(vl->list, &vl->values[i]);
+                       return;
+               }
+       }
+}
+
+void value_list_set_current_item(struct value_list *vl,
+                                const struct value_item *item)
+{
+       multilist_set_current_row(vl->list, item);
+}
+
 void value_list_driver(struct value_list *vl, int c)
 {
        multilist_driver(vl->list, c);