+ if (cui->current == &cui->plugin_menu->scr)
+ nc_scr_post(cui->current);
+}
+
+static void cui_update_status(struct status *status, void *arg)
+{
+ struct cui *cui = cui_from_arg(arg);
+
+ statuslog_append_steal(cui, cui->statuslog, status);
+
+ /* Ignore status messages from the backlog */
+ if (!status->backlog)
+ nc_scr_status_printf(cui->current, "%s", status->message);
+}
+
+/*
+ * Handle a new installed plugin option and update its associated
+ * (uninstalled) menu item if it exists.
+ */
+static int cui_plugin_option_add(struct plugin_option *opt, void *arg)
+{
+ struct cui_opt_data *cod;
+ struct cui *cui = cui_from_arg(arg);
+ struct pmenu_item *item = NULL;
+ struct boot_option *dummy_opt;
+ struct device *dev;
+ unsigned int i;
+ int result;
+
+fallback:
+ /* Find uninstalled plugin by matching on plugin_file */
+ for (i = 0; i < cui->plugin_menu->item_count; i++) {
+ item = item_userptr(cui->plugin_menu->items[i]);
+ if (!item)
+ continue;
+ cod = cod_from_item(item);
+ if (!cod || !cod->pd)
+ continue;
+ if (strncmp(cod->pd->plugin_file, opt->plugin_file,
+ strlen(cod->pd->plugin_file)) == 0)
+ break;
+ }
+
+ /*
+ * If pb-plugin was run manually there may not be an associated
+ * plugin-type boot_option. Pass a fake device and option to
+ * cui_boot_option_add() so we have an item to work with.
+ */
+ if (!item || i >= cui->plugin_menu->item_count) {
+ pb_log("New plugin option %s doesn't have a source item\n",
+ opt->id);
+ dev = talloc_zero(cui, struct device);
+ dev->id = dev->name = talloc_asprintf(dev, "(unknown)");
+ dev->type = DEVICE_TYPE_UNKNOWN;
+ dummy_opt = talloc_zero(cui, struct boot_option);
+ dummy_opt->device_id = talloc_strdup(dummy_opt, dev->id);
+ dummy_opt->id = dummy_opt->name = talloc_asprintf(dummy_opt, "dummy");
+ dummy_opt->boot_image_file = talloc_strdup(dummy_opt, opt->plugin_file);
+ dummy_opt->type = DISCOVER_PLUGIN_OPTION;
+ cui_boot_option_add(dev, dummy_opt, cui);
+ goto fallback;
+ }
+
+ /*
+ * If this option was faked above move the context under
+ * the item so it is cleaned up later in cui_plugins_remove().
+ */
+ if (strcmp(cod->opt->id, "dummy") == 0 &&
+ cod->dev->type == DEVICE_TYPE_UNKNOWN) {
+ talloc_steal(item, cod->dev);
+ talloc_steal(item, cod->opt);
+ }
+
+ talloc_free(cod->name);
+ /* Name is still tabbed across */
+ cod->name = talloc_asprintf(cod, _(" %s [installed]"), opt->name);
+
+ cod->pd->opt = opt;
+ item->on_execute = NULL;
+ item->on_edit = cui_show_plugin;
+
+ if (cui->current == &cui->plugin_menu->scr)
+ nc_scr_unpost(cui->current);
+
+ /* This disconnects items array from menu. */
+ result = set_menu_items(cui->plugin_menu->ncm, NULL);
+
+ if (result == E_OK)
+ pmenu_item_update(item, cod->name);
+
+ /* Re-attach the items array. */
+ result = set_menu_items(cui->plugin_menu->ncm, cui->plugin_menu->items);
+
+ if (cui->current == &cui->plugin_menu->scr)
+ nc_scr_post(cui->current);
+
+ return result;