diff --git a/PowerEditor/installer/nativeLang/english.xml b/PowerEditor/installer/nativeLang/english.xml index 2e356b507..b8a2d0a4c 100644 --- a/PowerEditor/installer/nativeLang/english.xml +++ b/PowerEditor/installer/nativeLang/english.xml @@ -1280,7 +1280,12 @@ You can define several column markers by using white space to separate the diffe - + + + + + + diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp index f3910e473..217e203bc 100644 --- a/PowerEditor/src/Parameters.cpp +++ b/PowerEditor/src/Parameters.cpp @@ -2525,7 +2525,6 @@ void NppParameters::feedColumnEditorParameters(TiXmlNode *node) _columnEditParam._repeatNum = val; strVal = (childNode->ToElement())->Attribute(TEXT("formatChoice")); - if (strVal) { if (lstrcmp(strVal, TEXT("hex")) == 0) @@ -2534,13 +2533,23 @@ void NppParameters::feedColumnEditorParameters(TiXmlNode *node) _columnEditParam._formatChoice = 2; else if (lstrcmp(strVal, TEXT("bin")) == 0) _columnEditParam._formatChoice = 3; - else // "bin" + else // "dec" _columnEditParam._formatChoice = 0; } - const TCHAR* boolStr = (childNode->ToElement())->Attribute(TEXT("leadingZeros")); - if (boolStr) - _columnEditParam._isLeadingZeros = (lstrcmp(TEXT("yes"), boolStr) == 0); + strVal = (childNode->ToElement())->Attribute(TEXT("leadingChoice")); + if (strVal) + { + _columnEditParam._leadingChoice = ColumnEditorParam::noneLeading; + if (lstrcmp(strVal, TEXT("zeros")) == 0) + { + _columnEditParam._leadingChoice = ColumnEditorParam::zeroLeading; + } + else if (lstrcmp(strVal, TEXT("spaces")) == 0) + { + _columnEditParam._leadingChoice = ColumnEditorParam::spaceLeading; + } + } } void NppParameters::feedFindHistoryParameters(TiXmlNode *node) @@ -4102,8 +4111,6 @@ bool NppParameters::writeColumnEditorSettings() const (numberNode.ToElement())->SetAttribute(TEXT("initial"), _columnEditParam._initialNum); (numberNode.ToElement())->SetAttribute(TEXT("increase"), _columnEditParam._increaseNum); (numberNode.ToElement())->SetAttribute(TEXT("repeat"), _columnEditParam._repeatNum); - (numberNode.ToElement())->SetAttribute(TEXT("leadingZeros"), _columnEditParam._isLeadingZeros ? L"yes" : L"no"); - wstring format = TEXT("dec"); if (_columnEditParam._formatChoice == 1) format = TEXT("hex"); @@ -4112,10 +4119,14 @@ bool NppParameters::writeColumnEditorSettings() const else if (_columnEditParam._formatChoice == 3) format = TEXT("bin"); (numberNode.ToElement())->SetAttribute(TEXT("formatChoice"), format); + wstring leading = TEXT("none"); + if (_columnEditParam._leadingChoice == ColumnEditorParam::zeroLeading) + leading = TEXT("zeros"); + else if (_columnEditParam._leadingChoice == ColumnEditorParam::spaceLeading) + leading = TEXT("spaces"); + (numberNode.ToElement())->SetAttribute(TEXT("leadingChoice"), leading); (columnEditorRootNode.ToElement())->InsertEndChild(numberNode); - - // (Re)Insert the Project Panel root (nppRoot->ToElement())->InsertEndChild(columnEditorRootNode); return true; diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h index 513d5f3d0..f2f8ffb08 100644 --- a/PowerEditor/src/Parameters.h +++ b/PowerEditor/src/Parameters.h @@ -1209,6 +1209,8 @@ struct FindHistory final struct ColumnEditorParam final { + enum leadingChoice : UCHAR { noneLeading, zeroLeading, spaceLeading }; + bool _mainChoice = true; // true (1): text false (0): number std::wstring _insertedTextContent; @@ -1216,8 +1218,8 @@ struct ColumnEditorParam final int _initialNum = -1; int _increaseNum = -1; int _repeatNum = -1; - bool _isLeadingZeros = false; int _formatChoice = 0; // 0:Dec 1:Hex 2:Oct 3:Bin + leadingChoice _leadingChoice = noneLeading; }; class LocalizationSwitcher final diff --git a/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp b/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp index f5d2bc018..c39b4cdf8 100644 --- a/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp +++ b/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp @@ -3221,64 +3221,90 @@ bool ScintillaEditView::expandWordSelection() return false; } -TCHAR * int2str(TCHAR *str, int strLen, int number, int base, int nbChiffre, bool isZeroLeading) +TCHAR* int2str(TCHAR* str, int strLen, int number, int base, int nbDigits, ColumnEditorParam::leadingChoice lead) { - if (nbChiffre >= strLen) return NULL; - constexpr size_t bufSize = 64; - TCHAR f[bufSize] = { '\0' }; - TCHAR fStr[2] = TEXT("d"); - if (base == 16) - fStr[0] = 'X'; - else if (base == 8) - fStr[0] = 'o'; - else if (base == 2) + if (nbDigits >= strLen) return NULL; + + if (base == 2) { const unsigned int MASK_ULONG_BITFORT = 0x80000000; int nbBits = sizeof(unsigned int) * 8; - int nbBit2Shift = (nbChiffre >= nbBits)?nbBits:(nbBits - nbChiffre); + int nbBit2Shift = (nbDigits >= nbBits) ? nbBits : (nbBits - nbDigits); unsigned long mask = MASK_ULONG_BITFORT >> nbBit2Shift; int i = 0; - for (; mask > 0 ; ++i) + for (; mask > 0; ++i) { - str[i] = (mask & number)?'1':'0'; + str[i] = (mask & number) ? '1' : '0'; mask >>= 1; } str[i] = '\0'; - } + // str is now leading zero padded - if (!isZeroLeading) - { - if (base == 2) + if (lead == ColumnEditorParam::spaceLeading) { - TCHAR *j = str; - for ( ; *j != '\0' ; ++j) - if (*j == '1') + // replace leading zeros with spaces + for (TCHAR* j = str; *j != '\0'; ++j) + { + if ((*j == '1') || (*(j + 1) == '\0')) + { break; - wcscpy_s(str, strLen, j); + } + else + { + *j = ' '; + } + } } - else + else if (lead != ColumnEditorParam::zeroLeading) { - // use sprintf or swprintf instead of wsprintf - // to make octal format work - swprintf(f, bufSize, TEXT("%%%s"), fStr); - swprintf(str, strLen, f, number); + // left-align within the field width, i.e. pad on right with space + + // first, remove leading zeros + for (TCHAR* j = str; *j != '\0'; ++j) + { + if (*j == '1' || *(j + 1) == '\0') + { + wcscpy_s(str, strLen, j); + break; + } + } + // add trailing spaces to pad out to field width + int i = lstrlen(str); + for (; i < nbDigits; ++i) + { + str[i] = ' '; + } + str[i] = '\0'; } - int i = lstrlen(str); - for ( ; i < nbChiffre ; ++i) - str[i] = ' '; - str[i] = '\0'; } else { - if (base != 2) + constexpr size_t bufSize = 64; + TCHAR f[bufSize] = { '\0' }; + + TCHAR fStr[2] = TEXT("d"); + if (base == 16) + fStr[0] = 'X'; + else if (base == 8) + fStr[0] = 'o'; + + if (lead == ColumnEditorParam::zeroLeading) { - // use sprintf or swprintf instead of wsprintf - // to make octal format work - swprintf(f, bufSize, TEXT("%%.%d%s"), nbChiffre, fStr); - swprintf(str, strLen, f, number); + swprintf(f, bufSize, TEXT("%%.%d%s"), nbDigits, fStr); } - // else already done. + else if (lead == ColumnEditorParam::spaceLeading) + { + swprintf(f, bufSize, TEXT("%%%d%s"), nbDigits, fStr); + } + else + { + // left-align within the field width, i.e. pad on right with space + swprintf(f, bufSize, TEXT("%%-%d%s"), nbDigits, fStr); + } + // use swprintf (or sprintf) instead of wsprintf to make octal format work! + swprintf(str, strLen, f, number); } + return str; } @@ -3358,7 +3384,7 @@ void ScintillaEditView::columnReplace(ColumnModeInfos & cmi, const TCHAR *str) } } -void ScintillaEditView::columnReplace(ColumnModeInfos & cmi, int initial, int incr, int repeat, UCHAR format) +void ScintillaEditView::columnReplace(ColumnModeInfos & cmi, int initial, int incr, int repeat, UCHAR format, ColumnEditorParam::leadingChoice lead) { assert(repeat > 0); @@ -3372,14 +3398,10 @@ void ScintillaEditView::columnReplace(ColumnModeInfos & cmi, int initial, int in // 0000 00 10 : Oct BASE_08 // 0000 00 11 : Bin BASE_02 - // 0000 01 00 : 0 leading - //Defined in ScintillaEditView.h : //const UCHAR MASK_FORMAT = 0x03; - //const UCHAR MASK_ZERO_LEADING = 0x04; UCHAR f = format & MASK_FORMAT; - bool isZeroLeading = (MASK_ZERO_LEADING & format) != 0; int base = 10; if (f == BASE_16) @@ -3429,7 +3451,7 @@ void ScintillaEditView::columnReplace(ColumnModeInfos & cmi, int initial, int in cmi[i]._selLpos += totalDiff; cmi[i]._selRpos += totalDiff; - int2str(str, stringSize, numbers.at(i), base, kib, isZeroLeading); + int2str(str, stringSize, numbers.at(i), base, kib, lead); const bool hasVirtualSpc = cmi[i]._nbVirtualAnchorSpc > 0; if (hasVirtualSpc) // if virtual space is present, then insert space diff --git a/PowerEditor/src/ScintillaComponent/ScintillaEditView.h b/PowerEditor/src/ScintillaComponent/ScintillaEditView.h index edec00c72..43b4ebc9b 100644 --- a/PowerEditor/src/ScintillaComponent/ScintillaEditView.h +++ b/PowerEditor/src/ScintillaComponent/ScintillaEditView.h @@ -106,7 +106,6 @@ enum TextCase : UCHAR }; const UCHAR MASK_FORMAT = 0x03; -const UCHAR MASK_ZERO_LEADING = 0x04; const UCHAR BASE_10 = 0x00; // Dec const UCHAR BASE_16 = 0x01; // Hex const UCHAR BASE_08 = 0x02; // Oct @@ -169,7 +168,7 @@ const std::vector> g_nonPrintingChars = int getNbDigits(int aNum, int base); //HMODULE loadSciLexerDll(); -TCHAR * int2str(TCHAR *str, int strLen, int number, int base, int nbChiffre, bool isZeroLeading); +TCHAR* int2str(TCHAR* str, int strLen, int number, int base, int nbDigits, ColumnEditorParam::leadingChoice lead); typedef LRESULT (WINAPI *CallWindowProcFunc) (WNDPROC,HWND,UINT,WPARAM,LPARAM); @@ -601,7 +600,7 @@ public: ColumnModeInfos getColumnModeSelectInfo(); void columnReplace(ColumnModeInfos & cmi, const TCHAR *str); - void columnReplace(ColumnModeInfos & cmi, int initial, int incr, int repeat, UCHAR format); + void columnReplace(ColumnModeInfos & cmi, int initial, int incr, int repeat, UCHAR format, ColumnEditorParam::leadingChoice lead); void clearIndicator(int indicatorNumber) { size_t docStart = 0; diff --git a/PowerEditor/src/ScintillaComponent/columnEditor.cpp b/PowerEditor/src/ScintillaComponent/columnEditor.cpp index 92df6536b..945bcffa6 100644 --- a/PowerEditor/src/ScintillaComponent/columnEditor.cpp +++ b/PowerEditor/src/ScintillaComponent/columnEditor.cpp @@ -54,8 +54,19 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR if (colEditParam._repeatNum != -1) ::SetDlgItemInt(_hSelf, IDC_COL_REPEATNUM_EDIT, colEditParam._repeatNum, FALSE); - ::SendDlgItemMessage(_hSelf, IDC_COL_LEADZERO_CHECK, BM_SETCHECK, colEditParam._isLeadingZeros, 0); - + ::SendDlgItemMessage(_hSelf, IDC_COL_LEADING_COMBO, CB_ADDSTRING, 0, reinterpret_cast(TEXT("None"))); + ::SendDlgItemMessage(_hSelf, IDC_COL_LEADING_COMBO, CB_ADDSTRING, 0, reinterpret_cast(TEXT("Zeros"))); + ::SendDlgItemMessage(_hSelf, IDC_COL_LEADING_COMBO, CB_ADDSTRING, 0, reinterpret_cast(TEXT("Spaces"))); + WPARAM curSel = 0; + switch (colEditParam._leadingChoice) + { + case ColumnEditorParam::noneLeading: { curSel = 0; break; } + case ColumnEditorParam::zeroLeading : { curSel = 1; break; } + case ColumnEditorParam::spaceLeading : { curSel = 2; break; } + default : { curSel = 0; break; } + } + ::SendMessage(::GetDlgItem(_hSelf, IDC_COL_LEADING_COMBO), CB_SETCURSEL, curSel, 0); + int format = IDC_COL_DEC_RADIO; if (colEditParam._formatChoice == 1) format = IDC_COL_HEX_RADIO; @@ -230,7 +241,7 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR if (colInfos.size() > 0) { std::sort(colInfos.begin(), colInfos.end(), SortInPositionOrder()); - (*_ppEditView)->columnReplace(colInfos, initialNumber, increaseNumber, repeat, format); + (*_ppEditView)->columnReplace(colInfos, initialNumber, increaseNumber, repeat, format, getLeading()); std::sort(colInfos.begin(), colInfos.end(), SortInSelectOrder()); (*_ppEditView)->setMultiSelections(colInfos); } @@ -266,9 +277,7 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR int lineAllocatedLen = 1024; TCHAR *line = new TCHAR[lineAllocatedLen]; - UCHAR f = format & MASK_FORMAT; - bool isZeroLeading = (MASK_ZERO_LEADING & format) != 0; int base = 10; if (f == BASE_16) @@ -303,7 +312,7 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR // // Calcule generic_string // - int2str(str, stringSize, numbers.at(i - cursorLine), base, nb, isZeroLeading); + int2str(str, stringSize, numbers.at(i - cursorLine), base, nb, getLeading()); if (lineEndCol < cursorCol) { @@ -356,14 +365,6 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR return TRUE; } - case IDC_COL_LEADZERO_CHECK: - { - ColumnEditorParam& colEditParam = NppParameters::getInstance()._columnEditParam; - bool isLeadingZeros = (BST_CHECKED == ::SendDlgItemMessage(_hSelf, IDC_COL_LEADZERO_CHECK, BM_GETCHECK, 0, 0)); - colEditParam._isLeadingZeros = isLeadingZeros; - return TRUE; - } - default : { switch (HIWORD(wParam)) @@ -427,6 +428,17 @@ intptr_t CALLBACK ColumnEditorDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR } } break; + + case CBN_SELCHANGE: + { + if (LOWORD(wParam) == IDC_COL_LEADING_COMBO) + { + ColumnEditorParam& colEditParam = NppParameters::getInstance()._columnEditParam; + colEditParam._leadingChoice = getLeading(); + return TRUE; + } + } + break; } break; } @@ -455,7 +467,8 @@ void ColumnEditorDlg::switchTo(bool toText) ::EnableWindow(::GetDlgItem(_hSelf, IDC_COL_HEX_RADIO), !toText); ::EnableWindow(::GetDlgItem(_hSelf, IDC_COL_OCT_RADIO), !toText); ::EnableWindow(::GetDlgItem(_hSelf, IDC_COL_BIN_RADIO), !toText); - ::EnableWindow(::GetDlgItem(_hSelf, IDC_COL_LEADZERO_CHECK), !toText); + ::EnableWindow(::GetDlgItem(_hSelf, IDC_COL_LEADING_STATIC), !toText); + ::EnableWindow(::GetDlgItem(_hSelf, IDC_COL_LEADING_COMBO), !toText); ::SetFocus(toText?hText:hNum); @@ -472,7 +485,6 @@ void ColumnEditorDlg::switchTo(bool toText) UCHAR ColumnEditorDlg::getFormat() { - bool isLeadingZeros = (BST_CHECKED == ::SendDlgItemMessage(_hSelf, IDC_COL_LEADZERO_CHECK, BM_GETCHECK, 0, 0)); UCHAR f = 0; // Dec by default if (BST_CHECKED == ::SendDlgItemMessage(_hSelf, IDC_COL_HEX_RADIO, BM_GETCHECK, 0, 0)) f = 1; @@ -480,5 +492,31 @@ UCHAR ColumnEditorDlg::getFormat() f = 2; else if (BST_CHECKED == ::SendDlgItemMessage(_hSelf, IDC_COL_BIN_RADIO, BM_GETCHECK, 0, 0)) f = 3; - return (f | (isLeadingZeros?MASK_ZERO_LEADING:0)); + return f; } + +ColumnEditorParam::leadingChoice ColumnEditorDlg::getLeading() +{ + ColumnEditorParam::leadingChoice leading = ColumnEditorParam::noneLeading; + int curSel = static_cast(::SendDlgItemMessage(_hSelf, IDC_COL_LEADING_COMBO, CB_GETCURSEL, 0, 0)); + switch (curSel) + { + case 0: + default: + { + leading = ColumnEditorParam::noneLeading; + break; + } + case 1: + { + leading = ColumnEditorParam::zeroLeading; + break; + } + case 2: + { + leading = ColumnEditorParam::spaceLeading; + break; + } + } + return leading; +} \ No newline at end of file diff --git a/PowerEditor/src/ScintillaComponent/columnEditor.h b/PowerEditor/src/ScintillaComponent/columnEditor.h index 4167e4e3c..8ed43851b 100644 --- a/PowerEditor/src/ScintillaComponent/columnEditor.h +++ b/PowerEditor/src/ScintillaComponent/columnEditor.h @@ -18,6 +18,7 @@ #include "columnEditor_rc.h" #include "StaticDialog.h" +#include "Parameters.h" class ScintillaEditView; @@ -45,6 +46,7 @@ public : virtual void display(bool toShow = true) const; void switchTo(bool toText); UCHAR getFormat(); + ColumnEditorParam::leadingChoice getLeading(); protected : virtual intptr_t CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam); diff --git a/PowerEditor/src/ScintillaComponent/columnEditor.rc b/PowerEditor/src/ScintillaComponent/columnEditor.rc index 7699faa27..4472de962 100644 --- a/PowerEditor/src/ScintillaComponent/columnEditor.rc +++ b/PowerEditor/src/ScintillaComponent/columnEditor.rc @@ -33,19 +33,20 @@ BEGIN RTEXT "&Initial number :",IDC_COL_INITNUM_STATIC,15,91,76,8 EDITTEXT IDC_COL_INITNUM_EDIT,95,89,38,12,ES_NUMBER - RTEXT "Increase b&y :",IDC_COL_INCRNUM_STATIC,16,112,75,8 - EDITTEXT IDC_COL_INCREASENUM_EDIT,95,110,38,12,ES_NUMBER + RTEXT "Increase b&y :",IDC_COL_INCRNUM_STATIC,16,108,75,8 + EDITTEXT IDC_COL_INCREASENUM_EDIT,95,106,38,12,ES_NUMBER - RTEXT "&Repeat :",IDC_COL_REPEATNUM_STATIC,16,133,75,8 - EDITTEXT IDC_COL_REPEATNUM_EDIT,95,131,38,12,ES_NUMBER + RTEXT "&Repeat :",IDC_COL_REPEATNUM_STATIC,16,125,75,8 + EDITTEXT IDC_COL_REPEATNUM_EDIT,95,123,38,12,ES_NUMBER - CONTROL "Leading &zeros", IDC_COL_LEADZERO_CHECK,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,140,133,70,10 - - CONTROL "&Dec",IDC_COL_DEC_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,30,169,70,10 - CONTROL "&Hex",IDC_COL_HEX_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,124,169,70,10 - CONTROL "&Oct",IDC_COL_OCT_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,30,188,70,10 - CONTROL "&Bin",IDC_COL_BIN_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,124,188,70,10 - GROUPBOX "Format",IDC_COL_FORMAT_GRP_STATIC,20,153,188,54,BS_CENTER + RTEXT "&Leading :",IDC_COL_LEADING_STATIC,16,142,75,8 + COMBOBOX IDC_COL_LEADING_COMBO,95,140,100,30,CBS_DROPDOWNLIST | WS_TABSTOP + + CONTROL "&Dec",IDC_COL_DEC_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,30,175,70,10 + CONTROL "&Hex",IDC_COL_HEX_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,124,175,70,10 + CONTROL "&Oct",IDC_COL_OCT_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,30,189,70,10 + CONTROL "&Bin",IDC_COL_BIN_RADIO,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,124,189,70,10 + GROUPBOX "Format",IDC_COL_FORMAT_GRP_STATIC,20,163,188,44,BS_CENTER DEFPUSHBUTTON "OK",IDOK,145,13,70,14,BS_NOTIFY PUSHBUTTON "Cancel",IDCANCEL,145,36,70,14,BS_NOTIFY END diff --git a/PowerEditor/src/ScintillaComponent/columnEditor_rc.h b/PowerEditor/src/ScintillaComponent/columnEditor_rc.h index 13a948b04..f875512dc 100644 --- a/PowerEditor/src/ScintillaComponent/columnEditor_rc.h +++ b/PowerEditor/src/ScintillaComponent/columnEditor_rc.h @@ -33,8 +33,8 @@ #define IDC_COL_FORMAT_GRP_STATIC (IDD_COLUMNEDIT + 12) #define IDC_COL_NUM_RADIO (IDD_COLUMNEDIT + 13) #define IDC_COL_TEXT_EDIT (IDD_COLUMNEDIT + 14) - #define IDC_COL_LEADZERO_CHECK (IDD_COLUMNEDIT + 15) #define IDC_COL_REPEATNUM_STATIC (IDD_COLUMNEDIT + 16) #define IDC_COL_REPEATNUM_EDIT (IDD_COLUMNEDIT + 17) - + #define IDC_COL_LEADING_STATIC (IDD_COLUMNEDIT + 18) + #define IDC_COL_LEADING_COMBO (IDD_COLUMNEDIT + 19) #endif// COLUMNEDITOR_RC_H