diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp index 2d0d172ef..503e5a5ec 100644 --- a/PowerEditor/src/Notepad_plus.cpp +++ b/PowerEditor/src/Notepad_plus.cpp @@ -1873,6 +1873,12 @@ void Notepad_plus::checkClipboard() enableCommand(IDM_EDIT_DELETE, hasSelection, MENU | TOOLBAR); enableCommand(IDM_EDIT_UPPERCASE, hasSelection, MENU); enableCommand(IDM_EDIT_LOWERCASE, hasSelection, MENU); + enableCommand(IDM_EDIT_TITLECASE_FORCE, hasSelection, MENU); + enableCommand(IDM_EDIT_TITLECASE_BLEND, hasSelection, MENU); + enableCommand(IDM_EDIT_SENTENCECASE_FORCE, hasSelection, MENU); + enableCommand(IDM_EDIT_SENTENCECASE_BLEND, hasSelection, MENU); + enableCommand(IDM_EDIT_INVERTCASE, hasSelection, MENU); + enableCommand(IDM_EDIT_RANDOMCASE, hasSelection, MENU); } void Notepad_plus::checkDocState() diff --git a/PowerEditor/src/Notepad_plus.rc b/PowerEditor/src/Notepad_plus.rc index fe8c97276..d031d18ff 100644 --- a/PowerEditor/src/Notepad_plus.rc +++ b/PowerEditor/src/Notepad_plus.rc @@ -274,8 +274,14 @@ BEGIN END POPUP "Convert Case to" BEGIN - MENUITEM "&UPPERCASE", IDM_EDIT_UPPERCASE - MENUITEM "&lowercase", IDM_EDIT_LOWERCASE + MENUITEM "&UPPERCASE", IDM_EDIT_UPPERCASE + MENUITEM "&lowercase", IDM_EDIT_LOWERCASE + MENUITEM "&Title Case", IDM_EDIT_TITLECASE_FORCE + MENUITEM "Title Case (blend)", IDM_EDIT_TITLECASE_BLEND + MENUITEM "&Sentence case", IDM_EDIT_SENTENCECASE_FORCE + MENUITEM "Sentence case (blend)", IDM_EDIT_SENTENCECASE_BLEND + MENUITEM "&iNVERTCASE", IDM_EDIT_INVERTCASE + MENUITEM "&RAnDomCaSe", IDM_EDIT_RANDOMCASE END POPUP "Line Operations" BEGIN diff --git a/PowerEditor/src/NppCommands.cpp b/PowerEditor/src/NppCommands.cpp index 82c6315a5..9f38feedf 100644 --- a/PowerEditor/src/NppCommands.cpp +++ b/PowerEditor/src/NppCommands.cpp @@ -1206,6 +1206,30 @@ void Notepad_plus::command(int id) _pEditView->convertSelectedTextToLowerCase(); break; + case IDM_EDIT_TITLECASE_FORCE: + _pEditView->convertSelectedTextToNewerCase(TITLECASE_FORCE); + break; + + case IDM_EDIT_TITLECASE_BLEND: + _pEditView->convertSelectedTextToNewerCase(TITLECASE_BLEND); + break; + + case IDM_EDIT_SENTENCECASE_FORCE: + _pEditView->convertSelectedTextToNewerCase(SENTENCECASE_FORCE); + break; + + case IDM_EDIT_SENTENCECASE_BLEND: + _pEditView->convertSelectedTextToNewerCase(SENTENCECASE_BLEND); + break; + + case IDM_EDIT_INVERTCASE: + _pEditView->convertSelectedTextToNewerCase(INVERTCASE); + break; + + case IDM_EDIT_RANDOMCASE: + _pEditView->convertSelectedTextToNewerCase(RANDOMCASE); + break; + case IDM_EDIT_BLOCK_COMMENT: doBlockComment(cm_toggle); break; @@ -2871,6 +2895,12 @@ void Notepad_plus::command(int id) case IDM_EDIT_REMOVEEMPTYLINESWITHBLANK: case IDM_EDIT_UPPERCASE: case IDM_EDIT_LOWERCASE: + case IDM_EDIT_TITLECASE_FORCE: + case IDM_EDIT_TITLECASE_BLEND: + case IDM_EDIT_SENTENCECASE_FORCE: + case IDM_EDIT_SENTENCECASE_BLEND: + case IDM_EDIT_INVERTCASE: + case IDM_EDIT_RANDOMCASE: case IDM_EDIT_BLOCK_COMMENT: case IDM_EDIT_BLOCK_COMMENT_SET: case IDM_EDIT_BLOCK_UNCOMMENT: diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp index 71839b532..c92643c9b 100644 --- a/PowerEditor/src/Parameters.cpp +++ b/PowerEditor/src/Parameters.cpp @@ -131,6 +131,12 @@ static const WinMenuKeyDefinition winKeyDefs[] = {VK_C, IDM_EDIT_COLUMNMODE, false, true, false, nullptr}, {VK_U, IDM_EDIT_UPPERCASE, true, false, true, nullptr}, {VK_U, IDM_EDIT_LOWERCASE, true, false, false, nullptr}, + {VK_U, IDM_EDIT_TITLECASE_FORCE, false, true, false, nullptr}, + {VK_U, IDM_EDIT_TITLECASE_BLEND, false, true, true, nullptr}, + {VK_U, IDM_EDIT_SENTENCECASE_FORCE, true, true, false, nullptr}, + {VK_U, IDM_EDIT_SENTENCECASE_BLEND, true, true, true, nullptr}, + {VK_NULL, IDM_EDIT_INVERTCASE, false, false, false, nullptr}, + {VK_NULL, IDM_EDIT_RANDOMCASE, false, false, false, nullptr}, {VK_Q, IDM_EDIT_BLOCK_COMMENT, true, false, false, nullptr}, {VK_K, IDM_EDIT_BLOCK_COMMENT_SET, true, false, false, nullptr}, {VK_K, IDM_EDIT_BLOCK_UNCOMMENT, true, false, true, nullptr}, diff --git a/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp b/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp index e19cb9d4c..7423acbe9 100644 --- a/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp +++ b/PowerEditor/src/ScitillaComponent/ScintillaEditView.cpp @@ -2399,7 +2399,129 @@ void ScintillaEditView::currentLinesDown() const execute(SCI_SCROLLRANGE, execute(SCI_GETSELECTIONEND), execute(SCI_GETSELECTIONSTART)); } -void ScintillaEditView::convertSelectedTextTo(bool Case) +void ScintillaEditView::changeCase(__inout wchar_t * const strWToConvert, const int & nbChars, const TextCase & caseToConvert) const +{ + if (strWToConvert == nullptr || nbChars == NULL) + return; + + switch (caseToConvert) + { + case UPPERCASE: + { + for (int i = 0; i < nbChars; ++i) + { + strWToConvert[i] = (WCHAR)(UINT_PTR)::CharUpperW((LPWSTR)strWToConvert[i]); + } + break; + } //case UPPERCASE + case LOWERCASE: + { + for (int i = 0; i < nbChars; ++i) + { + strWToConvert[i] = (WCHAR)(UINT_PTR)::CharLowerW((LPWSTR)strWToConvert[i]); + } + break; + } //case LOWERCASE + case TITLECASE_FORCE: + case TITLECASE_BLEND: + { + for (int i = 0; i < nbChars; ++i) + { + if (::IsCharAlphaW(strWToConvert[i])) + { + if ((i < 1) ? true : not ::IsCharAlphaNumericW(strWToConvert[i - 1])) + strWToConvert[i] = (WCHAR)(UINT_PTR)::CharUpperW((LPWSTR)strWToConvert[i]); + else if (caseToConvert == TITLECASE_FORCE) + strWToConvert[i] = (WCHAR)(UINT_PTR)::CharLowerW((LPWSTR)strWToConvert[i]); + //An exception + if ((i < 2) ? false : (strWToConvert[i - 1] == L'\'' && ::IsCharAlphaW(strWToConvert[i - 2]))) + strWToConvert[i] = (WCHAR)(UINT_PTR)::CharLowerW((LPWSTR)strWToConvert[i]); + } + } + break; + } //case TITLECASE + case SENTENCECASE_FORCE: + case SENTENCECASE_BLEND: + { + bool isNewSentence = true; + bool wasEolR = false; + bool wasEolN = false; + for (int i = 0; i < nbChars; ++i) + { + if (::IsCharAlphaW(strWToConvert[i])) + { + if (isNewSentence) + { + strWToConvert[i] = (WCHAR)(UINT_PTR)::CharUpperW((LPWSTR)strWToConvert[i]); + isNewSentence = false; + } + else if (caseToConvert == SENTENCECASE_FORCE) + { + strWToConvert[i] = (WCHAR)(UINT_PTR)::CharLowerW((LPWSTR)strWToConvert[i]); + } + wasEolR = false; + wasEolN = false; + //An exception + if (strWToConvert[i] == L'i' && + ((i < 1) ? false : (::iswspace(strWToConvert[i - 1]) || strWToConvert[i - 1] == L'(' || strWToConvert[i - 1] == L'"')) && + ((i + 1 == nbChars) ? false : (::iswspace(strWToConvert[i + 1]) || strWToConvert[i + 1] == L'\''))) + { + strWToConvert[i] = L'I'; + } + } + else if (strWToConvert[i] == L'.' || strWToConvert[i] == L'!' || strWToConvert[i] == L'?') + { + if ((i + 1 == nbChars) ? true : ::IsCharAlphaNumericW(strWToConvert[i + 1])) + isNewSentence = false; + else + isNewSentence = true; + } + else if (strWToConvert[i] == L'\r') + { + if (wasEolR) + isNewSentence = true; + else + wasEolR = true; + } + else if (strWToConvert[i] == L'\n') + { + if (wasEolN) + isNewSentence = true; + else + wasEolN = true; + } + } + break; + } //case SENTENCECASE + case INVERTCASE: + { + for (int i = 0; i < nbChars; ++i) + { + if (::IsCharLowerW(strWToConvert[i])) + strWToConvert[i] = (WCHAR)(UINT_PTR)::CharUpperW((LPWSTR)strWToConvert[i]); + else + strWToConvert[i] = (WCHAR)(UINT_PTR)::CharLowerW((LPWSTR)strWToConvert[i]); + } + break; + } //case INVERTCASE + case RANDOMCASE: + { + for (int i = 0; i < nbChars; ++i) + { + if (::IsCharAlphaW(strWToConvert[i])) + { + if (std::rand() & true) + strWToConvert[i] = (WCHAR)(UINT_PTR)::CharUpperW((LPWSTR)strWToConvert[i]); + else + strWToConvert[i] = (WCHAR)(UINT_PTR)::CharLowerW((LPWSTR)strWToConvert[i]); + } + } + break; + } //case RANDOMCASE + } //switch (caseToConvert) +} + +void ScintillaEditView::convertSelectedTextTo(const TextCase & caseToConvert) { unsigned int codepage = _codepage; UniMode um = getCurrentBuffer()->getUnicodeMode(); @@ -2424,13 +2546,8 @@ void ScintillaEditView::convertSelectedTextTo(bool Case) int nbChar = ::MultiByteToWideChar(codepage, 0, srcStr, len, destStr, len); - for (int j = 0 ; j < nbChar ; ++j) - { - if (Case == UPPERCASE) - destStr[j] = (wchar_t)(UINT_PTR)::CharUpperW((LPWSTR)destStr[j]); - else - destStr[j] = (wchar_t)(UINT_PTR)::CharLowerW((LPWSTR)destStr[j]); - } + changeCase(destStr, nbChar, caseToConvert); + ::WideCharToMultiByte(codepage, 0, destStr, len, srcStr, len, NULL, NULL); execute(SCI_SETTARGETRANGE, start, end); @@ -2464,13 +2581,8 @@ void ScintillaEditView::convertSelectedTextTo(bool Case) int nbChar = ::MultiByteToWideChar(codepage, 0, selectedStr, strSize, selectedStrW, strWSize); - for (int i = 0 ; i < nbChar ; ++i) - { - if (Case == UPPERCASE) - selectedStrW[i] = (WCHAR)(UINT_PTR)::CharUpperW((LPWSTR)selectedStrW[i]); - else - selectedStrW[i] = (WCHAR)(UINT_PTR)::CharLowerW((LPWSTR)selectedStrW[i]); - } + changeCase(selectedStrW, nbChar, caseToConvert); + ::WideCharToMultiByte(codepage, 0, selectedStrW, strWSize, selectedStr, strSize, NULL, NULL); execute(SCI_SETTARGETRANGE, selectionStart, selectionEnd); diff --git a/PowerEditor/src/ScitillaComponent/ScintillaEditView.h b/PowerEditor/src/ScitillaComponent/ScintillaEditView.h index ead5fef8d..c3496c015 100644 --- a/PowerEditor/src/ScitillaComponent/ScintillaEditView.h +++ b/PowerEditor/src/ScitillaComponent/ScintillaEditView.h @@ -99,9 +99,17 @@ const int CP_GREEK = 1253; const bool fold_uncollapse = true; const bool fold_collapse = false; -const bool UPPERCASE = true; -const bool LOWERCASE = false; - +enum TextCase : UCHAR +{ + UPPERCASE, + LOWERCASE, + TITLECASE_FORCE, + TITLECASE_BLEND, + SENTENCECASE_FORCE, + SENTENCECASE_BLEND, + INVERTCASE, + RANDOMCASE +}; const UCHAR MASK_FORMAT = 0x03; const UCHAR MASK_ZERO_LEADING = 0x04; @@ -518,7 +526,8 @@ public: void currentLinesUp() const; void currentLinesDown() const; - void convertSelectedTextTo(bool Case); + void changeCase(__inout wchar_t * const strWToConvert, const int & nbChars, const TextCase & caseToConvert) const; + void convertSelectedTextTo(const TextCase & caseToConvert); void setMultiSelections(const ColumnModeInfos & cmi); void convertSelectedTextToLowerCase() { @@ -537,6 +546,14 @@ public: execute(SCI_UPPERCASE); }; + void convertSelectedTextToNewerCase(const TextCase & caseToConvert) { + // if system is w2k or xp + if ((NppParameters::getInstance())->isTransparentAvailable()) + convertSelectedTextTo(caseToConvert); + else + ::MessageBox(_hSelf, TEXT("This function needs a newer OS version."), TEXT("Change Case Error"), MB_OK | MB_ICONHAND); + }; + void collapse(int level2Collapse, bool mode); void foldAll(bool mode); void fold(size_t line, bool mode); diff --git a/PowerEditor/src/menuCmdID.h b/PowerEditor/src/menuCmdID.h index 942e837d8..2499d1c1b 100644 --- a/PowerEditor/src/menuCmdID.h +++ b/PowerEditor/src/menuCmdID.h @@ -109,6 +109,12 @@ #define IDM_EDIT_LINE_DOWN (IDM_EDIT + 15) #define IDM_EDIT_UPPERCASE (IDM_EDIT + 16) #define IDM_EDIT_LOWERCASE (IDM_EDIT + 17) + #define IDM_EDIT_TITLECASE_FORCE (IDM_EDIT + 67) + #define IDM_EDIT_TITLECASE_BLEND (IDM_EDIT + 68) + #define IDM_EDIT_SENTENCECASE_FORCE (IDM_EDIT + 69) + #define IDM_EDIT_SENTENCECASE_BLEND (IDM_EDIT + 70) + #define IDM_EDIT_INVERTCASE (IDM_EDIT + 71) + #define IDM_EDIT_RANDOMCASE (IDM_EDIT + 72) #define IDM_EDIT_REMOVEEMPTYLINES (IDM_EDIT + 55) #define IDM_EDIT_REMOVEEMPTYLINESWITHBLANK (IDM_EDIT + 56) #define IDM_EDIT_BLANKLINEABOVECURRENT (IDM_EDIT + 57)