diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index 375a764c79..89c1e67af8 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -192,6 +192,7 @@ buildtransitive
BValue
bytearray
callbackptr
+capitalized
CANRENAME
Captureascreenshot
CAPTURECHANGED
diff --git a/src/modules/powerrename/lib/Helpers.cpp b/src/modules/powerrename/lib/Helpers.cpp
index 30447d34f8..47dafe0d82 100644
--- a/src/modules/powerrename/lib/Helpers.cpp
+++ b/src/modules/powerrename/lib/Helpers.cpp
@@ -159,6 +159,42 @@ HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR sour
{
hr = StringCchCopy(result, cchMax, source);
}
+ }
+ else if (flags & Capitalized)
+ {
+ if (!(flags & ExtensionOnly))
+ {
+ std::wstring stem = fs::path(source).stem().wstring();
+ std::wstring extension = fs::path(source).extension().wstring();
+
+ size_t stemLength = stem.length();
+
+ while (stemLength > 0 && (iswspace(stem[stemLength - 1]) || iswpunct(stem[stemLength - 1])))
+ {
+ stemLength--;
+ }
+
+ for (size_t i = 0; i < stemLength; i++)
+ {
+ if (!i || iswspace(stem[i - 1]) || iswpunct(stem[i - 1]))
+ {
+ if (iswspace(stem[i]) || iswpunct(stem[i]))
+ {
+ continue;
+ }
+ stem[i] = towupper(stem[i]);
+ }
+ else
+ {
+ stem[i] = towlower(stem[i]);
+ }
+ }
+ hr = StringCchPrintf(result, cchMax, L"%s%s", stem.c_str(), extension.c_str());
+ }
+ else
+ {
+ hr = StringCchCopy(result, cchMax, source);
+ }
}
else
{
diff --git a/src/modules/powerrename/lib/PowerRenameInterfaces.h b/src/modules/powerrename/lib/PowerRenameInterfaces.h
index c274cdb99b..c9a03b23c6 100644
--- a/src/modules/powerrename/lib/PowerRenameInterfaces.h
+++ b/src/modules/powerrename/lib/PowerRenameInterfaces.h
@@ -14,7 +14,8 @@ enum PowerRenameFlags
ExtensionOnly = 0x100,
Uppercase = 0x200,
Lowercase = 0x400,
- Titlecase = 0x800
+ Titlecase = 0x800,
+ Capitalized = 0x1000
};
enum PowerRenameFilters
diff --git a/src/modules/powerrename/lib/PowerRenameManager.cpp b/src/modules/powerrename/lib/PowerRenameManager.cpp
index bdf62fe1df..7b20b5dd52 100644
--- a/src/modules/powerrename/lib/PowerRenameManager.cpp
+++ b/src/modules/powerrename/lib/PowerRenameManager.cpp
@@ -945,7 +945,7 @@ DWORD WINAPI CPowerRenameManager::s_regexWorkerThread(_In_ void* pv)
// as nullptr so we clear the renamed column
// Except string transformation is selected.
- if (newName == nullptr && (flags & Uppercase || flags & Lowercase || flags & Titlecase))
+ if (newName == nullptr && (flags & Uppercase || flags & Lowercase || flags & Titlecase || flags & Capitalized))
{
SHStrDup(sourceName, &newName);
}
@@ -983,7 +983,7 @@ DWORD WINAPI CPowerRenameManager::s_regexWorkerThread(_In_ void* pv)
}
wchar_t transformedName[MAX_PATH] = { 0 };
- if (newNameToUse != nullptr && (flags & Uppercase || flags & Lowercase || flags & Titlecase))
+ if (newNameToUse != nullptr && (flags & Uppercase || flags & Lowercase || flags & Titlecase || flags & Capitalized))
{
winrt::check_hresult(GetTransformedFileName(transformedName, ARRAYSIZE(transformedName), newNameToUse, flags));
newNameToUse = transformedName;
diff --git a/src/modules/powerrename/ui/PowerRenameUI.base.rc b/src/modules/powerrename/ui/PowerRenameUI.base.rc
index 0369a50812..67f9fb973b 100644
--- a/src/modules/powerrename/ui/PowerRenameUI.base.rc
+++ b/src/modules/powerrename/ui/PowerRenameUI.base.rc
@@ -29,9 +29,9 @@
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/ /
/ / D i a l o g
- / /
+ / / X P O S Y P O S W I D T H H E I G H T
- I D D _ M A I N D I A L O G E X 0 , 0 , 3 6 4 , 3 4 7
+ I D D _ M A I N D I A L O G E X 0 , 0 , 3 6 4 , 3 5 9
S T Y L E D S _ S E T F O N T | D S _ F I X E D S Y S | D S _ C E N T E R | W S _ M I N I M I Z E B O X | W S _ M A X I M I Z E B O X | W S _ P O P U P | W S _ C A P T I O N | W S _ S Y S M E N U | W S _ T H I C K F R A M E
C A P T I O N " "
F O N T 8 , " M S S h e l l D l g " , 4 0 0 , 0 , 0 x 1
@@ -44,22 +44,23 @@
C O N T R O L " " , I D C _ C H E C K _ E N U M I T E M S , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 2 1 , 1 1 9 , 1 5 0 , 1 0
C O N T R O L " " , I D C _ C H E C K _ N A M E O N L Y , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 2 1 , 1 3 1 , 1 5 0 , 1 0
C O N T R O L " " , I D C _ C H E C K _ E X T E N S I O N O N L Y , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 2 1 , 1 4 3 , 1 5 0 , 1 0
- C O N T R O L " " , I D C _ C H E C K _ E X C L U D E F O L D E R S , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 8 3 , 1 5 0 , 1 0
- C O N T R O L " " , I D C _ C H E C K _ E X C L U D E F I L E S , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 9 5 , 1 5 0 , 1 0
- C O N T R O L " " , I D C _ C H E C K _ E X C L U D E S U B F O L D E R S , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 1 0 7 , 1 5 0 , 1 0
- C O N T R O L " " , I D C _ T R A N S F O R M _ U P P E R C A S E , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 1 1 9 , 1 5 0 , 1 0
- C O N T R O L " " , I D C _ T R A N S F O R M _ L O W E R C A S E , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 1 3 1 , 1 5 0 , 1 0
- C O N T R O L " " , I D C _ T R A N S F O R M _ T I T L E C A S E , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 1 4 3 , 1 5 0 , 1 0
- C O N T R O L " " , I D C _ L I S T _ P R E V I E W , " S y s L i s t V i e w 3 2 " , L V S _ R E P O R T | L V S _ A L I G N L E F T | L V S _ O W N E R D A T A | W S _ B O R D E R | W S _ T A B S T O P , 2 2 , 1 9 0 , 3 0 8 , 1 1 6
- D E F P U S H B U T T O N " " , I D _ R E N A M E , 1 7 8 , 3 2 5 , 5 0 , 1 4
- P U S H B U T T O N " " , I D _ A B O U T , 2 3 4 , 3 2 5 , 5 0 , 1 4
- P U S H B U T T O N " " , I D C A N C E L , 2 9 0 , 3 2 5 , 5 0 , 1 4
+ C O N T R O L " " , I D C _ C H E C K _ E X C L U D E F O L D E R S , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 2 1 , 1 5 5 , 1 5 0 , 1 0
+ C O N T R O L " " , I D C _ C H E C K _ E X C L U D E F I L E S , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 8 3 , 1 5 0 , 1 0
+ C O N T R O L " " , I D C _ C H E C K _ E X C L U D E S U B F O L D E R S , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 9 5 , 1 5 0 , 1 0
+ C O N T R O L " " , I D C _ T R A N S F O R M _ U P P E R C A S E , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 1 0 7 , 1 5 0 , 1 0
+ C O N T R O L " " , I D C _ T R A N S F O R M _ L O W E R C A S E , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 1 1 9 , 1 5 0 , 1 0
+ C O N T R O L " " , I D C _ T R A N S F O R M _ T I T L E C A S E , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 1 3 1 , 1 5 0 , 1 0
+ C O N T R O L " " , I D C _ T R A N S F O R M _ C A P I T A L I Z E D , " B u t t o n " , B S _ A U T O C H E C K B O X | W S _ T A B S T O P , 1 8 1 , 1 4 3 , 1 5 0 , 1 0
+ C O N T R O L " " , I D C _ L I S T _ P R E V I E W , " S y s L i s t V i e w 3 2 " , L V S _ R E P O R T | L V S _ A L I G N L E F T | L V S _ O W N E R D A T A | W S _ B O R D E R | W S _ T A B S T O P , 2 2 , 2 0 2 , 3 0 8 , 1 1 6
+ D E F P U S H B U T T O N " " , I D _ R E N A M E , 1 7 8 , 3 3 7 , 5 0 , 1 4
+ P U S H B U T T O N " " , I D _ A B O U T , 2 3 4 , 3 3 7 , 5 0 , 1 4
+ P U S H B U T T O N " " , I D C A N C E L , 2 9 0 , 3 3 7 , 5 0 , 1 4
R T E X T " " , I D C _ S E A R C H _ F O R , 2 1 , 2 3 , 7 5 , 8
R T E X T " " , I D C _ R E P L A C E _ W I T H , 2 1 , 4 0 , 7 5 , 8
- L T E X T " " , I D C _ S T A T U S _ M E S S A G E _ S E L E C T E D , 1 1 , 3 2 3 , 1 3 7 , 1 3
- L T E X T " " , I D C _ S T A T U S _ M E S S A G E _ R E N A M I N G , 1 1 , 3 3 3 , 1 3 7 , 1 3
- G R O U P B O X " " , I D C _ O P T I O N S G R O U P , 1 1 , 6 8 , 3 2 9 , 9 4
- G R O U P B O X " " , I D C _ P R E V I E W G R O U P , 1 1 , 1 7 5 , 3 2 9 , 1 4 2
+ L T E X T " " , I D C _ S T A T U S _ M E S S A G E _ S E L E C T E D , 1 1 , 3 3 5 , 1 3 7 , 1 3
+ L T E X T " " , I D C _ S T A T U S _ M E S S A G E _ R E N A M I N G , 1 1 , 3 4 5 , 1 3 7 , 1 3
+ G R O U P B O X " " , I D C _ O P T I O N S G R O U P , 1 1 , 6 8 , 3 2 9 , 1 0 6
+ G R O U P B O X " " , I D C _ P R E V I E W G R O U P , 1 1 , 1 8 7 , 3 2 9 , 1 4 2
G R O U P B O X " " , I D C _ S E A R C H R E P L A C E G R O U P , 1 1 , 7 , 3 2 9 , 5 5
E N D
diff --git a/src/modules/powerrename/ui/PowerRenameUI.cpp b/src/modules/powerrename/ui/PowerRenameUI.cpp
index c6f1245c38..7f063b49f1 100644
--- a/src/modules/powerrename/ui/PowerRenameUI.cpp
+++ b/src/modules/powerrename/ui/PowerRenameUI.cpp
@@ -39,7 +39,8 @@ FlagCheckboxMap g_flagCheckboxMap[] = {
{ ExtensionOnly, IDC_CHECK_EXTENSIONONLY },
{ Uppercase, IDC_TRANSFORM_UPPERCASE },
{ Lowercase, IDC_TRANSFORM_LOWERCASE },
- { Titlecase, IDC_TRANSFORM_TITLECASE }
+ { Titlecase, IDC_TRANSFORM_TITLECASE },
+ { Capitalized, IDC_TRANSFORM_CAPITALIZED }
};
struct RepositionMap
@@ -708,6 +709,7 @@ void CPowerRenameUI::_InitDlgText()
UpdateDlgControl(m_hwnd, IDC_CHECK_NAMEONLY, IDS_ITEM_NAME_ONLY);
UpdateDlgControl(m_hwnd, IDC_CHECK_EXTENSIONONLY, IDS_ITEM_EXTENSION_ONLY);
UpdateDlgControl(m_hwnd, IDC_TRANSFORM_TITLECASE, IDS_MAKE_TITLECASE);
+ UpdateDlgControl(m_hwnd, IDC_TRANSFORM_CAPITALIZED, IDS_MAKE_CAPITALIZED);
UpdateDlgControl(m_hwnd, ID_RENAME, IDS_RENAME_BUTTON);
UpdateDlgControl(m_hwnd, ID_ABOUT, IDS_HELP_BUTTON);
UpdateDlgControl(m_hwnd, IDCANCEL, IDS_CANCEL_BUTTON);
@@ -756,6 +758,7 @@ void CPowerRenameUI::_OnCommand(_In_ WPARAM wParam, _In_ LPARAM lParam)
case IDC_CHECK_NAMEONLY:
case IDC_TRANSFORM_UPPERCASE:
case IDC_TRANSFORM_LOWERCASE:
+ case IDC_TRANSFORM_CAPITALIZED:
case IDC_TRANSFORM_TITLECASE:
if (BN_CLICKED == HIWORD(wParam))
{
@@ -981,6 +984,7 @@ void CPowerRenameUI::_ValidateFlagCheckbox(_In_ DWORD checkBoxId)
{
Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_LOWERCASE), FALSE);
Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_TITLECASE), FALSE);
+ Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_CAPITALIZED), FALSE);
}
}
else if (checkBoxId == IDC_TRANSFORM_LOWERCASE)
@@ -989,6 +993,7 @@ void CPowerRenameUI::_ValidateFlagCheckbox(_In_ DWORD checkBoxId)
{
Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_UPPERCASE), FALSE);
Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_TITLECASE), FALSE);
+ Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_CAPITALIZED), FALSE);
}
}
else if (checkBoxId == IDC_TRANSFORM_TITLECASE)
@@ -997,6 +1002,16 @@ void CPowerRenameUI::_ValidateFlagCheckbox(_In_ DWORD checkBoxId)
{
Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_UPPERCASE), FALSE);
Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_LOWERCASE), FALSE);
+ Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_CAPITALIZED), FALSE);
+ }
+ }
+ else if (checkBoxId == IDC_TRANSFORM_CAPITALIZED)
+ {
+ if (Button_GetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_CAPITALIZED)) == BST_CHECKED)
+ {
+ Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_UPPERCASE), FALSE);
+ Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_LOWERCASE), FALSE);
+ Button_SetCheck(GetDlgItem(m_hwnd, IDC_TRANSFORM_TITLECASE), FALSE);
}
}
else if (checkBoxId == IDC_CHECK_NAMEONLY)
diff --git a/src/modules/powerrename/ui/Resources.resx b/src/modules/powerrename/ui/Resources.resx
index 28b645e29e..3eeb24bf29 100644
--- a/src/modules/powerrename/ui/Resources.resx
+++ b/src/modules/powerrename/ui/Resources.resx
@@ -175,6 +175,9 @@ Please select from the options above to show items.
Make Titlecase
+
+ Make Capitalized
+
&Rename
diff --git a/src/modules/powerrename/ui/resource.base.h b/src/modules/powerrename/ui/resource.base.h
index a79a44208c..7b99147efe 100644
--- a/src/modules/powerrename/ui/resource.base.h
+++ b/src/modules/powerrename/ui/resource.base.h
@@ -26,9 +26,10 @@
#define IDC_TRANSFORM_UPPERCASE 3019
#define IDC_TRANSFORM_LOWERCASE 3020
#define IDC_TRANSFORM_TITLECASE 3021
-#define IDC_SEARCH_FOR 3022
-#define IDC_REPLACE_WITH 3023
+#define IDC_TRANSFORM_CAPITALIZED 3022
+#define IDC_SEARCH_FOR 3023
+#define IDC_REPLACE_WITH 3024
#define IDC_STATIC -1
-#define IDR_MAINFRAME 3024
-#define IDD_MAIN 3025
+#define IDR_MAINFRAME 3025
+#define IDD_MAIN 3026
#define IDI_RENAME 2001
diff --git a/src/modules/powerrename/unittests/PowerRenameManagerTests.cpp b/src/modules/powerrename/unittests/PowerRenameManagerTests.cpp
index dad75999db..86746bbdf6 100644
--- a/src/modules/powerrename/unittests/PowerRenameManagerTests.cpp
+++ b/src/modules/powerrename/unittests/PowerRenameManagerTests.cpp
@@ -270,6 +270,16 @@ namespace PowerRenameManagerTests
RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Titlecase);
}
+ TEST_METHOD (VerifyCapitalizedTransform)
+ {
+ rename_pairs renamePairs[] = {
+ { L"foo and the to", L"Bar And The To", false, true, 0 },
+ { L"Test", L"Test_norename", false, false, 0 }
+ };
+
+ RenameHelper(renamePairs, ARRAYSIZE(renamePairs), L"foo", L"bar", SYSTEMTIME{ 2020, 7, 3, 22, 15, 6, 42, 453 }, DEFAULT_FLAGS | Capitalized);
+ }
+
TEST_METHOD (VerifyNameOnlyTransform)
{
rename_pairs renamePairs[] = {