+/* A helper function that returns true if NAME is the name of an
+ available window. */
+
+static bool
+validate_window_name (const std::string &name)
+{
+ auto iter = known_window_types->find (name);
+ return iter != known_window_types->end ();
+}
+
+/* Implementation of the "tui new-layout" command. */
+
+static void
+tui_new_layout_command (const char *spec, int from_tty)
+{
+ std::string new_name = extract_arg (&spec);
+ if (new_name.empty ())
+ error (_("No layout name specified"));
+ if (new_name[0] == '-')
+ error (_("Layout name cannot start with '-'"));
+
+ bool is_vertical = true;
+ spec = skip_spaces (spec);
+ if (check_for_argument (&spec, "-horizontal"))
+ is_vertical = false;
+
+ std::vector<std::unique_ptr<tui_layout_split>> splits;
+ splits.emplace_back (new tui_layout_split (is_vertical));
+ std::unordered_set<std::string> seen_windows;
+ while (true)
+ {
+ spec = skip_spaces (spec);
+ if (spec[0] == '\0')
+ break;
+
+ if (spec[0] == '{')
+ {
+ is_vertical = true;
+ spec = skip_spaces (spec + 1);
+ if (check_for_argument (&spec, "-horizontal"))
+ is_vertical = false;
+ splits.emplace_back (new tui_layout_split (is_vertical));
+ continue;
+ }
+
+ bool is_close = false;
+ std::string name;
+ if (spec[0] == '}')
+ {
+ is_close = true;
+ ++spec;
+ if (splits.size () == 1)
+ error (_("Extra '}' in layout specification"));
+ }
+ else
+ {
+ name = extract_arg (&spec);
+ if (name.empty ())
+ break;
+ if (!validate_window_name (name))
+ error (_("Unknown window \"%s\""), name.c_str ());
+ if (seen_windows.find (name) != seen_windows.end ())
+ error (_("Window \"%s\" seen twice in layout"), name.c_str ());
+ }
+
+ ULONGEST weight = get_ulongest (&spec, '}');
+ if ((int) weight != weight)
+ error (_("Weight out of range: %s"), pulongest (weight));
+ if (is_close)
+ {
+ std::unique_ptr<tui_layout_split> last_split
+ = std::move (splits.back ());
+ splits.pop_back ();
+ splits.back ()->add_split (std::move (last_split), weight);
+ }
+ else
+ {
+ splits.back ()->add_window (name.c_str (), weight);
+ seen_windows.insert (name);
+ }
+ }
+ if (splits.size () > 1)
+ error (_("Missing '}' in layout specification"));
+ if (seen_windows.empty ())
+ error (_("New layout does not contain any windows"));
+ if (seen_windows.find (CMD_NAME) == seen_windows.end ())
+ error (_("New layout does not contain the \"" CMD_NAME "\" window"));
+
+ gdb::unique_xmalloc_ptr<char> cmd_name
+ = make_unique_xstrdup (new_name.c_str ());
+ std::unique_ptr<tui_layout_split> new_layout = std::move (splits.back ());
+ struct cmd_list_element *cmd
+ = add_layout_command (cmd_name.get (), new_layout.get ());
+ cmd->name_allocated = 1;
+ cmd_name.release ();
+ new_layout.release ();
+}
+