about summary refs log tree commit diff stats
path: root/src/command/commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/command/commands.c')
-rw-r--r--src/command/commands.c333
1 files changed, 311 insertions, 22 deletions
diff --git a/src/command/commands.c b/src/command/commands.c
index 7b49ad61..fa439955 100644
--- a/src/command/commands.c
+++ b/src/command/commands.c
@@ -634,12 +634,9 @@ cmd_help(gchar **args, struct cmd_help_t help)
         }
 
         cons_show("");
-
         if (help_text != NULL) {
-            int i;
-            for (i = 0; help_text[i] != NULL; i++) {
-                cons_show(help_text[i]);
-            }
+            ProfWin *console = wins_get_console();
+            ui_show_lines(console, help_text);
         } else {
             cons_show("No such command.");
         }
@@ -1788,7 +1785,7 @@ cmd_decline(gchar **args, struct cmd_help_t help)
 }
 
 gboolean
-cmd_room(gchar **args, struct cmd_help_t help)
+cmd_form(gchar **args, struct cmd_help_t help)
 {
     jabber_conn_status_t conn_status = jabber_get_connection_status();
 
@@ -1798,18 +1795,283 @@ cmd_room(gchar **args, struct cmd_help_t help)
     }
 
     win_type_t win_type = ui_current_win_type();
-    if (win_type != WIN_MUC) {
-        cons_show("Command /room only usable in chat rooms.");
+    if (win_type != WIN_MUC_CONFIG) {
+        cons_show("Command '/form' does not apply to this window.");
         return TRUE;
     }
 
-    if (g_strcmp0(args[0], "config") != 0) {
+    if ((g_strcmp0(args[0], "submit") != 0) &&
+            (g_strcmp0(args[0], "cancel") != 0) &&
+            (g_strcmp0(args[0], "show") != 0) &&
+            (g_strcmp0(args[0], "help") != 0) &&
+            (g_strcmp0(args[0], "set") != 0) &&
+            (g_strcmp0(args[0], "add") != 0) &&
+            (g_strcmp0(args[0], "remove") != 0)) {
         cons_show("Usage: %s", help.usage);
         return TRUE;
     }
 
-    if ((g_strcmp0(args[1], "accept") != 0) &&
-            (g_strcmp0(args[1], "cancel") != 0)) {
+    char *recipient = ui_current_recipient();
+    ProfWin *current = wins_get_current();
+    gchar **split_recipient = g_strsplit(recipient, " ", 2);
+    char *room = split_recipient[0];
+
+    if (g_strcmp0(args[0], "show") == 0) {
+        ui_show_form(current, room, current->form);
+        g_strfreev(split_recipient);
+        return TRUE;
+    }
+
+    if (g_strcmp0(args[0], "help") == 0) {
+        char *tag = args[1];
+        if (tag != NULL) {
+            ui_show_form_field_help(current, current->form, tag);
+        } else {
+            ui_show_form_help(current, current->form);
+
+            const gchar **help_text = NULL;
+            Command *command = g_hash_table_lookup(commands, "/form");
+
+            if (command != NULL) {
+                help_text = command->help.long_help;
+            }
+
+            ui_show_lines(current, help_text);
+        }
+        ui_current_print_line("");
+        g_strfreev(split_recipient);
+        return TRUE;
+    }
+
+    if (g_strcmp0(args[0], "submit") == 0) {
+        iq_submit_room_config(room, current->form);
+
+    }
+    if (g_strcmp0(args[0], "cancel") == 0) {
+        iq_room_config_cancel(room);
+    }
+    if (g_strcmp0(args[0], "set") == 0) {
+        char *tag = NULL;
+        char *value = NULL;
+        if (args[1] != NULL) {
+            tag = args[1];
+        } else {
+            ui_current_print_line("/room set command requires a field tag and value");
+            g_strfreev(split_recipient);
+            return TRUE;
+        }
+        if (args[2] != NULL) {
+            value = args[2];
+        } else {
+            ui_current_print_line("/room set command requires a field tag and value");
+            g_strfreev(split_recipient);
+            return TRUE;
+        }
+        if (!form_tag_exists(current->form, tag)) {
+            ui_current_print_line("Form does not contain a field with tag %s", tag);
+        } else {
+            form_field_type_t field_type = form_get_field_type(current->form, tag);
+            gboolean valid = FALSE;
+            switch (field_type) {
+            case FIELD_TEXT_SINGLE:
+            case FIELD_TEXT_PRIVATE:
+            case FIELD_JID_SINGLE:
+                form_set_value(current->form, tag, value);
+                ui_show_form_field(current, current->form, tag);
+                break;
+            case FIELD_BOOLEAN:
+                if (g_strcmp0(value, "on") == 0) {
+                    form_set_value(current->form, tag, "1");
+                    ui_show_form_field(current, current->form, tag);
+                } else if (g_strcmp0(value, "off") == 0) {
+                    form_set_value(current->form, tag, "0");
+                    ui_show_form_field(current, current->form, tag);
+                } else {
+                    ui_current_print_line("Value %s not valid for boolean field: %s", value, tag);
+                }
+                break;
+            case FIELD_LIST_SINGLE:
+                valid = form_field_contains_option(current->form, tag, value);
+                if (valid == TRUE) {
+                    form_set_value(current->form, tag, value);
+                    ui_show_form_field(current, current->form, tag);
+                } else {
+                    ui_current_print_line("Value %s not a valid option for field: %s", value, tag);
+                }
+                break;
+            default:
+                ui_current_print_line("Set command not valid for field: %s", tag);
+                break;
+            }
+        }
+    }
+
+    if (g_strcmp0(args[0], "add") == 0) {
+        char *tag = NULL;
+        char *value = NULL;
+        if (args[1] != NULL) {
+            tag = args[1];
+        } else {
+            ui_current_print_line("/room add command requires a field tag and value");
+            g_strfreev(split_recipient);
+            return TRUE;
+        }
+        if (args[2] != NULL) {
+            value = args[2];
+        } else {
+            ui_current_print_line("/room add command requires a field tag and value");
+            g_strfreev(split_recipient);
+            return TRUE;
+        }
+        if (!form_tag_exists(current->form, tag)) {
+            ui_current_print_line("Form does not contain a field with tag %s", tag);
+        } else {
+            form_field_type_t field_type = form_get_field_type(current->form, tag);
+            gboolean valid = FALSE;
+            gboolean added = FALSE;
+            switch (field_type) {
+            case FIELD_LIST_MULTI:
+                valid = form_field_contains_option(current->form, tag, value);
+                if (valid) {
+                    added = form_add_unique_value(current->form, tag, value);
+                    if (added) {
+                        ui_show_form_field(current, current->form, tag);
+                    } else {
+                        ui_current_print_line("Value %s already selected for %s", value, tag);
+                    }
+                } else {
+                    ui_current_print_line("Value %s not a valid option for field: %s", value, tag);
+                }
+                break;
+            case FIELD_TEXT_MULTI:
+                form_add_value(current->form, tag, value);
+                ui_show_form_field(current, current->form, tag);
+                break;
+            case FIELD_JID_MULTI:
+                added = form_add_unique_value(current->form, tag, value);
+                if (added) {
+                    ui_show_form_field(current, current->form, tag);
+                } else {
+                    ui_current_print_line("JID %s already exists in %s", value, tag);
+                }
+                break;
+            default:
+                ui_current_print_line("Add command not valid for field: %s", tag);
+                break;
+            }
+        }
+    }
+
+    if (g_strcmp0(args[0], "remove") == 0) {
+        char *tag = NULL;
+        char *value = NULL;
+        if (args[1] != NULL) {
+            tag = args[1];
+        } else {
+            ui_current_print_line("/room remove command requires a field tag and value");
+            g_strfreev(split_recipient);
+            return TRUE;
+        }
+        if (args[2] != NULL) {
+            value = args[2];
+        } else {
+            ui_current_print_line("/room remove command requires a field tag and value");
+            g_strfreev(split_recipient);
+            return TRUE;
+        }
+        if (!form_tag_exists(current->form, tag)) {
+            ui_current_print_line("Form does not contain a field with tag %s", tag);
+        } else {
+            form_field_type_t field_type = form_get_field_type(current->form, tag);
+            gboolean valid = FALSE;
+            gboolean removed = FALSE;
+            switch (field_type) {
+            case FIELD_LIST_MULTI:
+                valid = form_field_contains_option(current->form, tag, value);
+                if (valid == TRUE) {
+                    removed = form_remove_value(current->form, tag, value);
+                    if (removed) {
+                        ui_show_form_field(current, current->form, tag);
+                    } else {
+                        ui_current_print_line("Value %s is not currently set for %s", value, tag);
+                    }
+                } else {
+                    ui_current_print_line("Value %s not a valid option for field: %s", value, tag);
+                }
+                break;
+            case FIELD_TEXT_MULTI:
+                if (!g_str_has_prefix(value, "val")) {
+                    ui_current_print_line("No such value %s for %s", value, tag);
+                    break;
+                }
+                if (strlen(value) < 4) {
+                    ui_current_print_line("No such value %s for %s", value, tag);
+                    break;
+                }
+
+                int index = strtol(&value[3], NULL, 10);
+                if ((index < 1) || (index > form_get_value_count(current->form, tag))) {
+                    ui_current_print_line("No such value %s for %s", value, tag);
+                    break;
+                }
+
+                removed = form_remove_text_multi_value(current->form, tag, index);
+                if (removed) {
+                    ui_show_form_field(current, current->form, tag);
+                } else {
+                    ui_current_print_line("Could not remove %s from %s", value, tag);
+                }
+                break;
+            case FIELD_JID_MULTI:
+                removed = form_remove_value(current->form, tag, value);
+                if (removed) {
+                    ui_show_form_field(current, current->form, tag);
+                } else {
+                    ui_current_print_line("Field %s does not contain %s", tag, value);
+                }
+                break;
+            default:
+                ui_current_print_line("Remove command not valid for field: %s", tag);
+                break;
+            }
+        }
+    }
+
+    if ((g_strcmp0(args[0], "submit") == 0) ||
+            (g_strcmp0(args[0], "cancel") == 0)) {
+        wins_close_current();
+        current = wins_get_by_recipient(room);
+        if (current == NULL) {
+            current = wins_get_console();
+        }
+        int num = wins_get_num(current);
+        ui_switch_win(num);
+    }
+
+    g_strfreev(split_recipient);
+
+    return TRUE;
+}
+
+gboolean
+cmd_room(gchar **args, struct cmd_help_t help)
+{
+    jabber_conn_status_t conn_status = jabber_get_connection_status();
+
+    if (conn_status != JABBER_CONNECTED) {
+        cons_show("You are not currently connected.");
+        return TRUE;
+    }
+
+    win_type_t win_type = ui_current_win_type();
+    if (win_type != WIN_MUC) {
+        cons_show("Command '/room' does not apply to this window.");
+        return TRUE;
+    }
+
+    if ((g_strcmp0(args[0], "accept") != 0) &&
+            (g_strcmp0(args[0], "destroy") != 0) &&
+            (g_strcmp0(args[0], "config") != 0)) {
         cons_show("Usage: %s", help.usage);
         return TRUE;
     }
@@ -1817,26 +2079,42 @@ cmd_room(gchar **args, struct cmd_help_t help)
     char *room = ui_current_recipient();
     ProfWin *window = wins_get_by_recipient(room);
     int num = wins_get_num(window);
+
     int ui_index = num;
     if (ui_index == 10) {
         ui_index = 0;
     }
-    gboolean requires_config = muc_requires_config(room);
-    if (!requires_config) {
-        win_save_vprint(window, '!', NULL, 0, COLOUR_ROOMINFO, "", "Current room does not require configuration.");
-        return TRUE;
+
+    if (g_strcmp0(args[0], "accept") == 0) {
+        gboolean requires_config = muc_requires_config(room);
+        if (!requires_config) {
+            win_save_vprint(window, '!', NULL, 0, COLOUR_ROOMINFO, "", "Current room does not require configuration.");
+            return TRUE;
+        } else {
+            iq_confirm_instant_room(room);
+            muc_set_requires_config(room, FALSE);
+            win_save_vprint(window, '!', NULL, 0, COLOUR_ROOMINFO, "", "Room unlocked.");
+            cons_show("Room unlocked: %s (%d)", room, ui_index);
+            return TRUE;
+        }
     }
 
-    if (g_strcmp0(args[1], "accept") == 0) {
-        iq_confirm_instant_room(room);
-        muc_set_requires_config(room, FALSE);
-        win_save_vprint(window, '!', NULL, 0, COLOUR_ROOMINFO, "", "Room unlocked.");
-        cons_show("Room unlocked: %s (%d)", room, ui_index);
+    if (g_strcmp0(args[0], "destroy") == 0) {
+        iq_destroy_instant_room(room);
         return TRUE;
     }
 
-    if (g_strcmp0(args[1], "cancel") == 0) {
-        iq_destroy_instant_room(room);
+    if (g_strcmp0(args[0], "config") == 0) {
+        GString *win_title = g_string_new(room);
+        g_string_append(win_title, " config");
+        ProfWin *window = wins_get_by_recipient(win_title->str);
+        g_string_free(win_title, TRUE);
+        if (window != NULL) {
+            num = wins_get_num(window);
+            ui_switch_win(num);
+        } else {
+            iq_request_room_config_form(room);
+        }
         return TRUE;
     }
 
@@ -2238,6 +2516,17 @@ cmd_close(gchar **args, struct cmd_help_t help)
         return TRUE;
     }
 
+    // check for unsaved form
+    if (ui_win_has_unsaved_form(index)) {
+        ProfWin *window = wins_get_current();
+        if (wins_is_current(window)) {
+            ui_current_print_line("You have unsaved changes, use /form submit or /form cancel");
+        } else {
+            cons_show("Cannot close form window with unsaved changes, use /form submit or /form cancel");
+        }
+        return TRUE;
+    }
+
     // handle leaving rooms, or chat
     if (conn_status == JABBER_CONNECTED) {
         ui_close_connected_win(index);