+ return result;
+}
+
+
+/*********************************************************************
+ *
+ * Function : current_actions_to_html
+ *
+ * Description : Converts a curren action spec to a <br> separated HTML
+ * text in which each action is linked to its chapter in
+ * the user manual.
+ *
+ * Parameters :
+ * 1 : csp = Client state (for config)
+ * 2 : action = Current action spec to be converted
+ *
+ * Returns : A string. Caller must free it.
+ * NULL on out-of-memory error.
+ *
+ *********************************************************************/
+char *current_action_to_html(const struct client_state *csp,
+ const struct current_action_spec *action)
+{
+ unsigned long flags = action->flags;
+ struct list_entry * lst;
+ char *result = strdup_or_die("");
+ char *active = strdup_or_die("");
+ char *inactive = strdup_or_die("");
+
+#define DEFINE_ACTION_BOOL(__name, __bit) \
+ if (flags & __bit) \
+ { \
+ string_append(&active, "\n<br>+"); \
+ string_join(&active, add_help_link(__name, csp->config)); \
+ } \
+ else \
+ { \
+ string_append(&inactive, "\n<br>-"); \
+ string_join(&inactive, add_help_link(__name, csp->config)); \
+ }
+
+#define DEFINE_ACTION_STRING(__name, __bit, __index) \
+ if (flags & __bit) \
+ { \
+ string_append(&active, "\n<br>+"); \
+ string_join(&active, add_help_link(__name, csp->config)); \
+ string_append(&active, "{"); \
+ string_join(&active, html_encode(action->string[__index])); \
+ string_append(&active, "}"); \
+ } \
+ else \
+ { \
+ string_append(&inactive, "\n<br>-"); \
+ string_join(&inactive, add_help_link(__name, csp->config)); \
+ }
+
+#define DEFINE_ACTION_MULTI(__name, __index) \
+ lst = action->multi[__index]->first; \
+ if (lst == NULL) \
+ { \
+ string_append(&inactive, "\n<br>-"); \
+ string_join(&inactive, add_help_link(__name, csp->config)); \
+ } \
+ else \
+ { \
+ while (lst) \
+ { \
+ string_append(&active, "\n<br>+"); \
+ string_join(&active, add_help_link(__name, csp->config)); \
+ string_append(&active, "{"); \
+ string_join(&active, html_encode(lst->str)); \
+ string_append(&active, "}"); \
+ lst = lst->next; \
+ } \
+ }
+
+#define DEFINE_ACTION_ALIAS 0 /* No aliases for output */
+
+#include "actionlist.h"
+
+#undef DEFINE_ACTION_MULTI
+#undef DEFINE_ACTION_STRING
+#undef DEFINE_ACTION_BOOL
+#undef DEFINE_ACTION_ALIAS
+
+ if (active != NULL)
+ {
+ string_append(&result, active);
+ freez(active);
+ }
+ string_append(&result, "\n<br>");
+ if (inactive != NULL)
+ {
+ string_append(&result, inactive);
+ freez(inactive);
+ }
+ return result;
+}
+
+
+/*********************************************************************
+ *
+ * Function : action_to_line_of_text
+ *
+ * Description : Converts a action spec to a single text line
+ * listing the enabled actions.
+ *
+ * Parameters :
+ * 1 : action = Current action spec to be converted
+ *
+ * Returns : A string. Caller must free it.
+ * Out-of-memory errors are fatal.
+ *
+ *********************************************************************/
+char *actions_to_line_of_text(const struct current_action_spec *action)
+{
+ char buffer[200];
+ struct list_entry *lst;
+ char *active;
+ const unsigned long flags = action->flags;
+
+ active = strdup_or_die("");
+
+#define DEFINE_ACTION_BOOL(__name, __bit) \
+ if (flags & __bit) \
+ { \
+ snprintf(buffer, sizeof(buffer), "+%s ", __name); \
+ string_append(&active, buffer); \
+ } \
+
+#define DEFINE_ACTION_STRING(__name, __bit, __index) \
+ if (flags & __bit) \
+ { \
+ snprintf(buffer, sizeof(buffer), "+%s{%s} ", \
+ __name, action->string[__index]); \
+ string_append(&active, buffer); \
+ } \
+
+#define DEFINE_ACTION_MULTI(__name, __index) \
+ lst = action->multi[__index]->first; \
+ while (lst != NULL) \
+ { \
+ snprintf(buffer, sizeof(buffer), "+%s{%s} ", \
+ __name, lst->str); \
+ string_append(&active, buffer); \
+ lst = lst->next; \
+ } \
+
+#define DEFINE_ACTION_ALIAS 0 /* No aliases for output */
+
+#include "actionlist.h"
+
+#undef DEFINE_ACTION_MULTI
+#undef DEFINE_ACTION_STRING
+#undef DEFINE_ACTION_BOOL
+#undef DEFINE_ACTION_ALIAS
+
+ if (active == NULL)
+ {
+ log_error(LOG_LEVEL_FATAL, "Out of memory in action_to_line_of_text()");
+ }