Repository: microsoft/terminal
File: src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp (C++)

Code before:
// - Create a new profile based off the default profile settings.
// Arguments:
// - <none>
// Return Value:
// - a reference to the new profile
winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::CreateNewProfile()
{
    auto newProfile{ _userDefaultProfileSettings->CreateChild() };
    _allProfiles.Append(*newProfile);

    // Give the new profile a distinct name so a guid is properly generated
    const winrt::hstring newName{ fmt::format(L"Profile {}", _allProfiles.Size()) };
    newProfile->Name(newName);

    return *newProfile;
}

// Method Description:
// - Duplicate a new profile based off another profile's settings
// Arguments:
// - source: the Profile object we are duplicating (must not be null)
// Return Value:
// - a reference to the new profile
winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::DuplicateProfile(Model::Profile source)
{
    THROW_IF_NULL_ALLOC(source);

    auto duplicated{ _userDefaultProfileSettings->CreateChild() };
    _allProfiles.Append(*duplicated);

    if (!source.Hidden())
    {
        _activeProfiles.Append(*duplicated);
    }

    const auto newName{ fmt::format(L"{} ({})", source.Name(), RS_(L"CopySuffix")) };
    duplicated->Name(winrt::hstring(newName));

    if (source.HasHidden() || source.HiddenOverrideSource() != nullptr)
    {
        duplicated->Hidden(source.Hidden());
    }
    if (source.HasIcon() || source.IconOverrideSource() != nullptr)
    {
        duplicated->Icon(source.Icon());
    }
    if (source.HasCloseOnExit() || source.CloseOnExitOverrideSource() != nullptr)
    {
        duplicated->CloseOnExit(source.CloseOnExit());
    }
    if (source.HasTabTitle() || source.TabTitleOverrideSource() != nullptr)

Review comment (bug):
this isn't quite the right error code -- it maps more closely to "we ran out of memory, because an allocation failed"

Code after:
{
    return *_userDefaultProfileSettings;
}

// Method Description:
// - Create a new profile based off the default profile settings.
// Arguments:
// - <none>
// Return Value:
// - a reference to the new profile
winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::CreateNewProfile()
{
    if (_allProfiles.Size() == std::numeric_limits<uint32_t>::max())
    {
        // Shouldn't really happen
        return nullptr;
    }

    winrt::hstring newName{};
    for (uint32_t candidateIndex = 0; candidateIndex < _allProfiles.Size() + 1; candidateIndex++)
    {
        // There is a theoretical unsigned integer wraparound, which is OK
        newName = fmt::format(L"Profile {}", _allProfiles.Size() + 1 + candidateIndex);
        if (std::none_of(begin(_allProfiles), end(_allProfiles), [&](auto&& profile) { return profile.Name() == newName; }))
        {
            break;
        }
    }

    auto newProfile{ _userDefaultProfileSettings->CreateChild() };
    newProfile->Name(newName);
    _allProfiles.Append(*newProfile);
    return *newProfile;
}

// Method Description:
// - Duplicate a new profile based off another profile's settings
// - This differs from Profile::Copy because it also copies over settings
//   that were not defined in the json (for example, settings that were
//   defined in one of the parents)
// - This will not duplicate settings that were defined in profiles.defaults
//   however, because we do not want the json blob generated from the new profile
//   to contain those settings
// Arguments:
// - source: the Profile object we are duplicating (must not be null)
// Return Value:
// - a reference to the new profile
winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::DuplicateProfile(Model::Profile source)
{
    THROW_HR_IF_NULL(E_INVALIDARG, source);