+static int pmenu_item_destructor(void *arg)
+{
+ struct pmenu_item *item = arg;
+ free_item(item->nci);
+ return 0;
+}
+
+static const char *pmenu_item_label(struct pmenu_item *item, const char *name)
+{
+ static int invalid_idx;
+ unsigned int i;
+ wchar_t *tmp;
+ char *label;
+ size_t len;
+
+ len = mbstowcs(NULL, name, 0);
+
+ /* if we have an invalid multibyte sequence, create an entirely
+ * new name, indicating that we had invalid input */
+ if (len == SIZE_MAX) {
+ name = talloc_asprintf(item, _("!Invalid option %d"),
+ ++invalid_idx);
+ return name;
+ }
+
+ tmp = talloc_array(item, wchar_t, len + 1);
+ mbstowcs(tmp, name, len + 1);
+
+ /* replace anything unprintable with U+FFFD REPLACEMENT CHARACTER */
+ for (i = 0; i < len; i++) {
+ if (!iswprint(tmp[i]))
+ tmp[i] = 0xfffd;
+ }
+
+ len = wcstombs(NULL, tmp, 0);
+ label = talloc_array(item, char, len + 1);
+ wcstombs(label, tmp, len + 1);
+
+ pb_log_fn("%s\n", label);
+
+ talloc_free(tmp);
+ return label;
+}
+
+/**
+ * pmenu_item_update - Update the label of an existing pmenu_item.
+ *
+ * The item array must be disconnected prior to calling.
+ */
+int pmenu_item_update(struct pmenu_item *item, const char *name)
+{
+ const char *label;
+ ITEM *i;
+
+ if (!item || !item->nci)
+ return -1;
+
+ label = pmenu_item_label(item, name);
+
+ if (!label)
+ return -1;
+
+ i = item->nci;
+ i->name.str = label;
+ i->name.length = strncols(label);
+
+ return 0;
+}
+