From 7a6768b029df2ed8f09004648841fe64a83d6326 Mon Sep 17 00:00:00 2001 From: Alan Kilborn Date: Wed, 12 Jun 2024 19:57:16 -0400 Subject: [PATCH] Add Backspace unident option Fix #15180, close #15277 --- PowerEditor/installer/nativeLang/english.xml | 1 + .../nativeLang/english_customizable.xml | 1 + PowerEditor/src/NppBigSwitch.cpp | 3 +- PowerEditor/src/Parameters.cpp | 16 +++- PowerEditor/src/Parameters.h | 8 +- .../ScintillaComponent/ScintillaEditView.cpp | 22 +++-- .../src/WinControls/Preference/preference.rc | 2 +- .../WinControls/Preference/preferenceDlg.cpp | 95 ++++++++++++++----- PowerEditor/src/resource.h | 4 +- 9 files changed, 111 insertions(+), 41 deletions(-) diff --git a/PowerEditor/installer/nativeLang/english.xml b/PowerEditor/installer/nativeLang/english.xml index ebf54e536..aa4ef2ea6 100644 --- a/PowerEditor/installer/nativeLang/english.xml +++ b/PowerEditor/installer/nativeLang/english.xml @@ -1106,6 +1106,7 @@ Translation note: + diff --git a/PowerEditor/installer/nativeLang/english_customizable.xml b/PowerEditor/installer/nativeLang/english_customizable.xml index 288507d06..731ecfcbd 100644 --- a/PowerEditor/installer/nativeLang/english_customizable.xml +++ b/PowerEditor/installer/nativeLang/english_customizable.xml @@ -1106,6 +1106,7 @@ Translation note: + diff --git a/PowerEditor/src/NppBigSwitch.cpp b/PowerEditor/src/NppBigSwitch.cpp index ad5fd1d7f..d57e5eedc 100644 --- a/PowerEditor/src/NppBigSwitch.cpp +++ b/PowerEditor/src/NppBigSwitch.cpp @@ -3624,8 +3624,7 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa } break; - case NPPM_INTERNAL_SETTING_TAB_REPLCESPACE: - case NPPM_INTERNAL_SETTING_TAB_SIZE: + case NPPM_INTERNAL_SET_TAB_SETTINGS: { _pEditView->setTabSettings(_pEditView->getCurrentBuffer()->getCurrentLang()); break; diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp index 469758938..785479501 100644 --- a/PowerEditor/src/Parameters.cpp +++ b/PowerEditor/src/Parameters.cpp @@ -4726,8 +4726,9 @@ void NppParameters::feedKeyWordsParameters(TiXmlNode *node) _langList[_nbLang]->setCommentEnd(element->Attribute(TEXT("commentEnd"))); int tabSettings; - if (element->Attribute(TEXT("tabSettings"), &tabSettings)) - _langList[_nbLang]->setTabInfo(tabSettings); + const TCHAR* tsVal = element->Attribute(TEXT("tabSettings"), &tabSettings); + const TCHAR* buVal = element->Attribute(TEXT("backspaceUnindent")); + _langList[_nbLang]->setTabInfo(tsVal ? tabSettings : -1, buVal && !lstrcmp(buVal, TEXT("yes"))); for (TiXmlNode *kwNode = langNode->FirstChildElement(TEXT("Keywords")); kwNode ; @@ -5308,6 +5309,10 @@ void NppParameters::feedGUIParameters(TiXmlNode *node) val = element->Attribute(TEXT("replaceBySpace")); if (val) _nppGUI._tabReplacedBySpace = (!lstrcmp(val, TEXT("yes"))); + + val = element->Attribute(TEXT("backspaceUnindent")); + if (val) + _nppGUI._backspaceUnindent = (!lstrcmp(val, TEXT("yes"))); } else if (!lstrcmp(nm, TEXT("Caret"))) @@ -7249,13 +7254,15 @@ void NppParameters::createXmlTreeFromGUIParams() GUIConfigElement->InsertEndChild(TiXmlText(pStr)); } - // + // { TiXmlElement *GUIConfigElement = (newGUIRoot->InsertEndChild(TiXmlElement(TEXT("GUIConfig"))))->ToElement(); GUIConfigElement->SetAttribute(TEXT("name"), TEXT("TabSetting")); const TCHAR *pStr = _nppGUI._tabReplacedBySpace ? TEXT("yes") : TEXT("no"); GUIConfigElement->SetAttribute(TEXT("replaceBySpace"), pStr); GUIConfigElement->SetAttribute(TEXT("size"), _nppGUI._tabSize); + pStr = _nppGUI._backspaceUnindent ? TEXT("yes") : TEXT("no"); + GUIConfigElement->SetAttribute(TEXT("backspaceUnindent"), pStr); } // @@ -8389,7 +8396,7 @@ std::wstring NppParameters::writeStyles(LexerStylerArray & lexersStylers, StyleA } -bool NppParameters::insertTabInfo(const TCHAR *langName, int tabInfo) +bool NppParameters::insertTabInfo(const TCHAR* langName, int tabInfo, bool backspaceUnindent) { if (!_pXmlDoc) return false; TiXmlNode *langRoot = (_pXmlDoc->FirstChild(TEXT("NotepadPlus")))->FirstChildElement(TEXT("Languages")); @@ -8402,6 +8409,7 @@ bool NppParameters::insertTabInfo(const TCHAR *langName, int tabInfo) if (nm && lstrcmp(langName, nm) == 0) { childNode->ToElement()->SetAttribute(TEXT("tabSettings"), tabInfo); + childNode->ToElement()->SetAttribute(TEXT("backspaceUnindent"), backspaceUnindent ? TEXT("yes") : TEXT("no")); _pXmlDoc->SaveFile(); return true; } diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h index 4a531e492..eb1c7a784 100644 --- a/PowerEditor/src/Parameters.h +++ b/PowerEditor/src/Parameters.h @@ -793,6 +793,7 @@ struct NppGUI final int _tabSize = 4; bool _tabReplacedBySpace = false; + bool _backspaceUnindent = false; bool _finderLinesAreCurrentlyWrapped = false; bool _finderPurgeBeforeEverySearch = false; @@ -1041,6 +1042,7 @@ struct Lang final bool _isTabReplacedBySpace = false; int _tabSize = -1; + bool _isBackspaceUnindent = false; Lang() { @@ -1070,13 +1072,15 @@ struct Lang final _pCommentEnd = commentEnd; } - void setTabInfo(int tabInfo) + void setTabInfo(int tabInfo, bool isBackspaceUnindent) { if (tabInfo != -1 && tabInfo & MASK_TabSize) { _isTabReplacedBySpace = (tabInfo & MASK_ReplaceBySpc) != 0; _tabSize = tabInfo & MASK_TabSize; } + + _isBackspaceUnindent = isBackspaceUnindent; } const TCHAR * getDefaultExtList() const { @@ -1537,7 +1541,7 @@ public: void createXmlTreeFromGUIParams(); std::wstring writeStyles(LexerStylerArray & lexersStylers, StyleArray & globalStylers); // return "" if saving file succeeds, otherwise return the new saved file path - bool insertTabInfo(const TCHAR *langName, int tabInfo); + bool insertTabInfo(const TCHAR* langName, int tabInfo, bool backspaceUnindent); LexerStylerArray & getLStylerArray() {return _lexerStylerVect;}; StyleArray & getGlobalStylers() {return _widgetStyleArray;}; diff --git a/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp b/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp index 2bed802bb..748e22b5f 100644 --- a/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp +++ b/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp @@ -2049,6 +2049,7 @@ void ScintillaEditView::defineDocType(LangType typeDoc) { setSpecialStyle(*pStyle); } + setTabSettings(NppParameters::getInstance().getLangFromID(typeDoc)); if (svp._indentGuideLineShow) @@ -4117,25 +4118,30 @@ void ScintillaEditView::runMarkers(bool doHide, size_t searchStart, bool endOfDo } -void ScintillaEditView::setTabSettings(Lang *lang) +void ScintillaEditView::setTabSettings(Lang* lang) { if (lang && lang->_tabSize != -1 && lang->_tabSize != 0) { if (lang->_langID == L_JAVASCRIPT) { - Lang *ljs = NppParameters::getInstance().getLangFromID(L_JS); + Lang* ljs = NppParameters::getInstance().getLangFromID(L_JS); execute(SCI_SETTABWIDTH, ljs->_tabSize > 0 ? ljs->_tabSize : lang->_tabSize); execute(SCI_SETUSETABS, !ljs->_isTabReplacedBySpace); - return; + execute(SCI_SETBACKSPACEUNINDENTS, ljs->_isBackspaceUnindent); + } + else + { + execute(SCI_SETTABWIDTH, lang->_tabSize); + execute(SCI_SETUSETABS, !lang->_isTabReplacedBySpace); + execute(SCI_SETBACKSPACEUNINDENTS, lang->_isBackspaceUnindent); } - execute(SCI_SETTABWIDTH, lang->_tabSize); - execute(SCI_SETUSETABS, !lang->_isTabReplacedBySpace); } - else + else { - const NppGUI & nppgui = NppParameters::getInstance().getNppGUI(); - execute(SCI_SETTABWIDTH, nppgui._tabSize > 0 ? nppgui._tabSize : 4); + const NppGUI& nppgui = NppParameters::getInstance().getNppGUI(); + execute(SCI_SETTABWIDTH, nppgui._tabSize > 0 ? nppgui._tabSize : 4); execute(SCI_SETUSETABS, !nppgui._tabReplacedBySpace); + execute(SCI_SETBACKSPACEUNINDENTS, nppgui._backspaceUnindent); } } diff --git a/PowerEditor/src/WinControls/Preference/preference.rc b/PowerEditor/src/WinControls/Preference/preference.rc index bc301bc16..2e02d9eaa 100644 --- a/PowerEditor/src/WinControls/Preference/preference.rc +++ b/PowerEditor/src/WinControls/Preference/preference.rc @@ -291,7 +291,7 @@ BEGIN LTEXT "Indent using:",IDC_INDENTUSING_STATIC,259,118,135,8 CONTROL "Tab character",IDC_RADIO_USINGTAB,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,264,130,165,10 CONTROL "Space character(s)",IDC_RADIO_REPLACEBYSPACE,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,264,143,165,10 - //CONTROL "Backspace key unindents instead of removing single space",IDC_CHECK_BACKSPACEUNINDENT,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,258,158,180,21 + CONTROL "Backspace key unindents instead of removing single space",IDC_CHECK_BACKSPACEUNINDENT,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,258,158,180,21 END diff --git a/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp b/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp index f7f9671ae..cda0b004b 100644 --- a/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp +++ b/PowerEditor/src/WinControls/Preference/preferenceDlg.cpp @@ -3163,6 +3163,7 @@ intptr_t CALLBACK LanguageSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA ::SetDlgItemInt(_hSelf, IDC_EDIT_TABSIZEVAL, nppGUI._tabSize, FALSE); ::SendDlgItemMessage(_hSelf, IDC_RADIO_REPLACEBYSPACE, BM_SETCHECK, nppGUI._tabReplacedBySpace, 0); ::SendDlgItemMessage(_hSelf, IDC_RADIO_USINGTAB, BM_SETCHECK, !nppGUI._tabReplacedBySpace, 0); + ::SendDlgItemMessage(_hSelf, IDC_CHECK_BACKSPACEUNINDENT, BM_SETCHECK, nppGUI._backspaceUnindent, 0); ::SendDlgItemMessage(_hSelf, IDC_LIST_TABSETTNG, LB_ADDSTRING, 0, reinterpret_cast(TEXT("[Default]"))); const int nbLang = nppParam.getNbLang(); @@ -3270,33 +3271,36 @@ intptr_t CALLBACK LanguageSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA { Lang* lang = nppParam.getLangFromIndex(index - 1); if (!lang) return FALSE; + bool useDefaultTab = (lang->_tabSize == -1 || lang->_tabSize == 0); ::SendMessage(::GetDlgItem(_hSelf, IDC_CHECK_DEFAULTTABVALUE), BM_SETCHECK, useDefaultTab, 0); - int size = useDefaultTab ? nppGUI._tabSize : lang->_tabSize; - ::SetDlgItemInt(_hSelf, IDC_EDIT_TABSIZEVAL, size, FALSE); - ::SendMessage(::GetDlgItem(_hSelf, IDC_RADIO_REPLACEBYSPACE), BM_SETCHECK, useDefaultTab ? nppGUI._tabReplacedBySpace : lang->_isTabReplacedBySpace, 0); - ::SendMessage(::GetDlgItem(_hSelf, IDC_RADIO_USINGTAB), BM_SETCHECK, useDefaultTab ? !nppGUI._tabReplacedBySpace : !lang->_isTabReplacedBySpace, 0); + ::SetDlgItemInt(_hSelf, IDC_EDIT_TABSIZEVAL, + useDefaultTab ? nppGUI._tabSize : lang->_tabSize, FALSE); + ::SendMessage(::GetDlgItem(_hSelf, IDC_RADIO_REPLACEBYSPACE), BM_SETCHECK, + useDefaultTab ? nppGUI._tabReplacedBySpace : lang->_isTabReplacedBySpace, 0); + ::SendMessage(::GetDlgItem(_hSelf, IDC_RADIO_USINGTAB), BM_SETCHECK, + useDefaultTab ? !nppGUI._tabReplacedBySpace : !lang->_isTabReplacedBySpace, 0); + ::SendMessage(::GetDlgItem(_hSelf, IDC_CHECK_BACKSPACEUNINDENT), BM_SETCHECK, + useDefaultTab ? nppGUI._backspaceUnindent : lang->_isBackspaceUnindent, 0); + + ::EnableWindow(::GetDlgItem(_hSelf, IDC_EDIT_TABSIZEVAL), !useDefaultTab); ::EnableWindow(::GetDlgItem(_hSelf, IDC_RADIO_REPLACEBYSPACE), !useDefaultTab); ::EnableWindow(::GetDlgItem(_hSelf, IDC_RADIO_USINGTAB), !useDefaultTab); - ::EnableWindow(::GetDlgItem(_hSelf, IDC_EDIT_TABSIZEVAL), !useDefaultTab); - - if (!useDefaultTab) - { - ::SetDlgItemInt(_hSelf, IDC_EDIT_TABSIZEVAL, lang->_tabSize, FALSE); - ::SendMessage(::GetDlgItem(_hSelf, IDC_RADIO_REPLACEBYSPACE), BM_SETCHECK, lang->_isTabReplacedBySpace, 0); - ::SendMessage(::GetDlgItem(_hSelf, IDC_RADIO_USINGTAB), BM_SETCHECK, !lang->_isTabReplacedBySpace, 0); - } + ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_BACKSPACEUNINDENT), !useDefaultTab); } else { ::SetDlgItemInt(_hSelf, IDC_EDIT_TABSIZEVAL, nppGUI._tabSize, FALSE); - ::EnableWindow(::GetDlgItem(_hSelf, IDC_RADIO_REPLACEBYSPACE), TRUE); - ::EnableWindow(::GetDlgItem(_hSelf, IDC_RADIO_USINGTAB), TRUE); - ::EnableWindow(::GetDlgItem(_hSelf, IDC_EDIT_TABSIZEVAL), TRUE); ::SendMessage(::GetDlgItem(_hSelf, IDC_RADIO_REPLACEBYSPACE), BM_SETCHECK, nppGUI._tabReplacedBySpace, 0); ::SendMessage(::GetDlgItem(_hSelf, IDC_RADIO_USINGTAB), BM_SETCHECK, !nppGUI._tabReplacedBySpace, 0); + ::SendMessage(::GetDlgItem(_hSelf, IDC_CHECK_BACKSPACEUNINDENT), BM_SETCHECK, nppGUI._backspaceUnindent, 0); + + ::EnableWindow(::GetDlgItem(_hSelf, IDC_EDIT_TABSIZEVAL), TRUE); + ::EnableWindow(::GetDlgItem(_hSelf, IDC_RADIO_REPLACEBYSPACE), TRUE); + ::EnableWindow(::GetDlgItem(_hSelf, IDC_RADIO_USINGTAB), TRUE); + ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_BACKSPACEUNINDENT), TRUE); } redrawDlgItem(IDC_TABSIZE_STATIC); @@ -3367,14 +3371,14 @@ intptr_t CALLBACK LanguageSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA lang->_tabSize = tabSize; // write in langs.xml - nppParam.insertTabInfo(lang->getLangName(), lang->getTabInfo()); + nppParam.insertTabInfo(lang->getLangName(), lang->getTabInfo(), lang->_isBackspaceUnindent); } else { nppGUI._tabSize = tabSize; } - ::SendMessage(::GetParent(_hParent), NPPM_INTERNAL_SETTING_TAB_SIZE, 0, 0); + ::SendMessage(::GetParent(_hParent), NPPM_INTERNAL_SET_TAB_SETTINGS, 0, 0); return TRUE; } @@ -3583,8 +3587,10 @@ intptr_t CALLBACK LanguageSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA case IDC_RADIO_USINGTAB: { bool isTabReplacedBySpace = BST_CHECKED == ::SendMessage(::GetDlgItem(_hSelf, IDC_RADIO_REPLACEBYSPACE), BM_GETCHECK, 0, 0); + auto index = ::SendDlgItemMessage(_hSelf, IDC_LIST_TABSETTNG, LB_GETCURSEL, 0, 0); if (index == LB_ERR) return FALSE; + if (index != 0) { Lang *lang = nppParam.getLangFromIndex(index - 1); @@ -3606,13 +3612,55 @@ intptr_t CALLBACK LanguageSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA lang->_isTabReplacedBySpace = isTabReplacedBySpace; // write in langs.xml - nppParam.insertTabInfo(lang->getLangName(), lang->getTabInfo()); + nppParam.insertTabInfo(lang->getLangName(), lang->getTabInfo(), lang->_isBackspaceUnindent); } else { nppGUI._tabReplacedBySpace = isTabReplacedBySpace; } - ::SendMessage(::GetParent(_hParent), NPPM_INTERNAL_SETTING_TAB_REPLCESPACE, 0, 0); + + ::SendMessage(::GetParent(_hParent), NPPM_INTERNAL_SET_TAB_SETTINGS, 0, 0); + + return TRUE; + } + + case IDC_CHECK_BACKSPACEUNINDENT: + { + bool isBackspaceUnindent = BST_CHECKED == ::SendMessage(::GetDlgItem(_hSelf, IDC_CHECK_BACKSPACEUNINDENT), BM_GETCHECK, 0, 0); + + auto index = ::SendDlgItemMessage(_hSelf, IDC_LIST_TABSETTNG, LB_GETCURSEL, 0, 0); + if (index == LB_ERR) return FALSE; + + if (index != 0) + { + Lang* lang = nppParam.getLangFromIndex(index - 1); + if (!lang) return FALSE; + if (!lang->_tabSize || lang->_tabSize == -1) + lang->_tabSize = nppGUI._tabSize; + + if (lang->_langID == L_JS) + { + Lang* ljs = nppParam.getLangFromID(L_JAVASCRIPT); + ljs->_isBackspaceUnindent = isBackspaceUnindent; + } + else if (lang->_langID == L_JAVASCRIPT) + { + Lang* ljavascript = nppParam.getLangFromID(L_JS); + ljavascript->_isBackspaceUnindent = isBackspaceUnindent; + } + + lang->_isBackspaceUnindent = isBackspaceUnindent; + + // write in langs.xml + nppParam.insertTabInfo(lang->getLangName(), lang->getTabInfo(), lang->_isBackspaceUnindent); + } + else + { + nppGUI._backspaceUnindent = isBackspaceUnindent; + } + + ::SendMessage(::GetParent(_hParent), NPPM_INTERNAL_SET_TAB_SETTINGS, 0, 0); + return TRUE; } @@ -3627,21 +3675,24 @@ intptr_t CALLBACK LanguageSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARA if (!lang) return FALSE; - //- Set tab setting in choosed language + //- Set tab setting in chosen language lang->_tabSize = useDefaultTab ? 0 : nppGUI._tabSize; lang->_isTabReplacedBySpace = useDefaultTab ? false : nppGUI._tabReplacedBySpace; + lang->_isBackspaceUnindent = useDefaultTab ? false : nppGUI._backspaceUnindent; //- set visual effect ::SetDlgItemInt(_hSelf, IDC_EDIT_TABSIZEVAL, useDefaultTab ? nppGUI._tabSize : lang->_tabSize, FALSE); setChecked(IDC_RADIO_REPLACEBYSPACE, useDefaultTab ? nppGUI._tabReplacedBySpace : lang->_isTabReplacedBySpace); setChecked(IDC_RADIO_USINGTAB, useDefaultTab ? !nppGUI._tabReplacedBySpace : !lang->_isTabReplacedBySpace); + setChecked(IDC_CHECK_BACKSPACEUNINDENT, useDefaultTab ? nppGUI._backspaceUnindent : lang->_isBackspaceUnindent); + ::EnableWindow(::GetDlgItem(_hSelf, IDC_EDIT_TABSIZEVAL), !useDefaultTab); ::EnableWindow(::GetDlgItem(_hSelf, IDC_RADIO_REPLACEBYSPACE), !useDefaultTab); ::EnableWindow(::GetDlgItem(_hSelf, IDC_RADIO_USINGTAB), !useDefaultTab); - ::EnableWindow(::GetDlgItem(_hSelf, IDC_EDIT_TABSIZEVAL), !useDefaultTab); + ::EnableWindow(::GetDlgItem(_hSelf, IDC_CHECK_BACKSPACEUNINDENT), !useDefaultTab); // write in langs.xml if (useDefaultTab) - nppParam.insertTabInfo(lang->getLangName(), -1); + nppParam.insertTabInfo(lang->getLangName(), -1, false); redrawDlgItem(IDC_TABSIZE_STATIC); redrawDlgItem(IDC_INDENTUSING_STATIC); diff --git a/PowerEditor/src/resource.h b/PowerEditor/src/resource.h index 975ca3840..60d05b97b 100644 --- a/PowerEditor/src/resource.h +++ b/PowerEditor/src/resource.h @@ -616,8 +616,8 @@ #define NPPM_INTERNAL_PLUGINSHORTCUTMOTIFIED (NOTEPADPLUS_USER_INTERNAL + 26) #define NPPM_INTERNAL_SCINTILLAFINDERCLEARALL (NOTEPADPLUS_USER_INTERNAL + 27) #define NPPM_INTERNAL_CHANGETABBARICONSET (NOTEPADPLUS_USER_INTERNAL + 28) - #define NPPM_INTERNAL_SETTING_TAB_REPLCESPACE (NOTEPADPLUS_USER_INTERNAL + 29) - #define NPPM_INTERNAL_SETTING_TAB_SIZE (NOTEPADPLUS_USER_INTERNAL + 30) + #define NPPM_INTERNAL_SET_TAB_SETTINGS (NOTEPADPLUS_USER_INTERNAL + 29) + //#define NPPM_INTERNAL_SETTING_TAB_SIZE (NOTEPADPLUS_USER_INTERNAL + 30) #define NPPM_INTERNAL_RELOADSTYLERS (NOTEPADPLUS_USER_INTERNAL + 31) #define NPPM_INTERNAL_DOCORDERCHANGED (NOTEPADPLUS_USER_INTERNAL + 32) #define NPPM_INTERNAL_SETMULTISELCTION (NOTEPADPLUS_USER_INTERNAL + 33)