From 2724e0ddbb1e7349fd9c23711d6b4e9535bcf1ba Mon Sep 17 00:00:00 2001 From: Don Ho Date: Thu, 30 Nov 2023 15:11:46 +0100 Subject: [PATCH] Make RTL per document & remembered across the sessions This commit adds the ability of RTL/LTR per document (tab), and memorizes RTL setting of each file in the session.xml. It also adds an attribute "editZoneRTL" in localization XML file. if "RTL" attribute is present and its value is "yes", then user can add "editZoneRTL" attribute beside, and set the value of the attribute in question to "no", so Notepad++ GUI will be RTL, but Scintilla zone will be LTR by opening files. Of course, user can set any direction they want afterward, and what they have set on document will be remembered across the sessions. Fix #9665, fix #9950, fix #14385, close #14431 --- PowerEditor/installer/nativeLang/english.xml | 2 +- .../nativeLang/english_customizable.xml | 2 +- PowerEditor/installer/nativeLang/french.xml | 3 +- .../nativeLang/taiwaneseMandarin.xml | 3 +- PowerEditor/src/Notepad_plus.cpp | 7 +---- PowerEditor/src/NppCommands.cpp | 15 --------- PowerEditor/src/NppIO.cpp | 17 ++++++++++ PowerEditor/src/Parameters.cpp | 7 +++++ PowerEditor/src/Parameters.h | 2 +- PowerEditor/src/ScintillaComponent/Buffer.cpp | 3 ++ PowerEditor/src/ScintillaComponent/Buffer.h | 5 +++ .../ScintillaComponent/ScintillaEditView.cpp | 31 +++++++++++++++++-- PowerEditor/src/localization.cpp | 28 ++++++++++++++--- PowerEditor/src/localization.h | 14 ++++++--- 14 files changed, 101 insertions(+), 38 deletions(-) diff --git a/PowerEditor/installer/nativeLang/english.xml b/PowerEditor/installer/nativeLang/english.xml index 9ea1da979..17641599a 100644 --- a/PowerEditor/installer/nativeLang/english.xml +++ b/PowerEditor/installer/nativeLang/english.xml @@ -1505,7 +1505,7 @@ NOTE: Choosing not to create the placeholders or closing them later, your manual Would you like to create those placeholders? NOTE: Choosing not to create the placeholders or closing them later, your session WILL BE MODIFIED ON EXIT! We suggest you backup your "session.xml" now."/> - + diff --git a/PowerEditor/installer/nativeLang/english_customizable.xml b/PowerEditor/installer/nativeLang/english_customizable.xml index 1c5a597d6..d904b4044 100644 --- a/PowerEditor/installer/nativeLang/english_customizable.xml +++ b/PowerEditor/installer/nativeLang/english_customizable.xml @@ -1505,7 +1505,7 @@ NOTE: Choosing not to create the placeholders or closing them later, your manual Would you like to create those placeholders? NOTE: Choosing not to create the placeholders or closing them later, your session WILL BE MODIFIED ON EXIT! We suggest you backup your "session.xml" now."/> - + diff --git a/PowerEditor/installer/nativeLang/french.xml b/PowerEditor/installer/nativeLang/french.xml index 558f28323..732501c16 100644 --- a/PowerEditor/installer/nativeLang/french.xml +++ b/PowerEditor/installer/nativeLang/french.xml @@ -1505,7 +1505,8 @@ Notez que si vous choisissez de ne pas créer d'espaces réservés ou de les fer Voulez-vous créer des espaces réservés pour eux ? NOTE : Si vous choisissez de ne pas créer d'espaces réservés ou de les fermer plus tard, votre fichier de session sera modifié à la sortie. Nous vous suggérons de faire une sauvegarde du fichier de session "session.xml" maintenant."/> - + + diff --git a/PowerEditor/installer/nativeLang/taiwaneseMandarin.xml b/PowerEditor/installer/nativeLang/taiwaneseMandarin.xml index 712c6a8a9..33fac89b2 100644 --- a/PowerEditor/installer/nativeLang/taiwaneseMandarin.xml +++ b/PowerEditor/installer/nativeLang/taiwaneseMandarin.xml @@ -1390,7 +1390,8 @@ 你想為它們創建佔位欄嗎? 請注意,如果你選擇不創建佔位欄或稍後關閉它們,工作階段檔案將在 Notepad++ 關閉時被修改。我們建議你現在備份工作階段檔案 "session.xml" 。"/> - + + diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp index ac77c24b2..fd56ac18b 100644 --- a/PowerEditor/src/Notepad_plus.cpp +++ b/PowerEditor/src/Notepad_plus.cpp @@ -864,12 +864,6 @@ LRESULT Notepad_plus::init(HWND hwnd) _mainEditView.getFocus(); - if (_nativeLangSpeaker.isRTL()) - { - _mainEditView.changeTextDirection(true); - _subEditView.changeTextDirection(true); - } - return TRUE; } @@ -6227,6 +6221,7 @@ void Notepad_plus::getCurrentOpenedFiles(Session & session, bool includUntitledD sfi._isMonitoring = buf->isMonitoringOn(); sfi._individualTabColour = docTab[k]->getIndividualTabColour(static_cast(i)); + sfi._isRTL = buf->isRTL(); _invisibleEditView.execute(SCI_SETDOCPOINTER, 0, buf->getDocument()); size_t maxLine = static_cast(_invisibleEditView.execute(SCI_GETLINECOUNT)); diff --git a/PowerEditor/src/NppCommands.cpp b/PowerEditor/src/NppCommands.cpp index 825d49188..d3b0ebdca 100644 --- a/PowerEditor/src/NppCommands.cpp +++ b/PowerEditor/src/NppCommands.cpp @@ -3839,28 +3839,13 @@ void Notepad_plus::command(int id) return; } - if (toRTL && (NppParameters::getInstance()).getNppGUI()._writeTechnologyEngine == directWriteTechnology) - { - _nativeLangSpeaker.messageBox("RTLvsDirectWrite", - _pPublicInterface->getHSelf(), - TEXT("RTL is not compatible with Direct Write mode. Please disable DirectWrite mode in MISC. section of Preferences dialog, restart Notepad++, and try this command again."), - TEXT("Cannot run RTL"), - MB_OK | MB_APPLMODAL); - - return; - } - _pEditView->changeTextDirection(toRTL); - _pNonEditView->changeTextDirection(toRTL); // Wrap then !wrap to fix problem of mirror characters bool isWraped = _pEditView->isWrap(); _pEditView->wrap(!isWraped); _pEditView->wrap(isWraped); - _pNonEditView->wrap(!isWraped); - _pNonEditView->wrap(isWraped); - if (_pDocMap) { _pDocMap->changeTextDirection(toRTL); diff --git a/PowerEditor/src/NppIO.cpp b/PowerEditor/src/NppIO.cpp index 440fd377f..531d598de 100644 --- a/PowerEditor/src/NppIO.cpp +++ b/PowerEditor/src/NppIO.cpp @@ -2119,6 +2119,17 @@ bool Notepad_plus::loadSession(Session & session, bool isSnapshotMode, const wch int mainIndex2Update = -1; + // no session + if (!session.nbMainFiles() && !session.nbSubFiles()) + { + Buffer* buf = getCurrentBuffer(); + if (nppParam.getNativeLangSpeaker()->isRTL() && nppParam.getNativeLangSpeaker()->isEditZoneRTL()) + buf->setRTL(true); + + _mainEditView.changeTextDirection(buf->isRTL()); + return true; + } + for (size_t i = 0; i < session.nbMainFiles() ; ) { const TCHAR *pFn = session._mainViewFiles[i]._fileName.c_str(); @@ -2212,6 +2223,10 @@ bool Notepad_plus::loadSession(Session & session, bool isSnapshotMode, const wch if (isSnapshotMode && session._mainViewFiles[i]._backupFilePath != TEXT("") && PathFileExists(session._mainViewFiles[i]._backupFilePath.c_str())) buf->setDirty(true); + buf->setRTL(session._mainViewFiles[i]._isRTL); + if (i == 0 && session._activeMainIndex == 0) + _mainEditView.changeTextDirection(buf->isRTL()); + _mainDocTab.setIndividualTabColour(lastOpened, session._mainViewFiles[i]._individualTabColour); //Force in the document so we can add the markers @@ -2340,6 +2355,8 @@ bool Notepad_plus::loadSession(Session & session, bool isSnapshotMode, const wch if (isSnapshotMode && session._subViewFiles[k]._backupFilePath != TEXT("") && PathFileExists(session._subViewFiles[k]._backupFilePath.c_str())) buf->setDirty(true); + buf->setRTL(session._subViewFiles[k]._isRTL); + _subDocTab.setIndividualTabColour(lastOpened, session._subViewFiles[k]._individualTabColour); //Force in the document so we can add the markers diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp index d9f407e34..b060b2118 100644 --- a/PowerEditor/src/Parameters.cpp +++ b/PowerEditor/src/Parameters.cpp @@ -2425,6 +2425,12 @@ bool NppParameters::getSessionFromXmlTree(TiXmlDocument *pSessionDoc, Session& s sfi._individualTabColour = _wtoi(intStrTabColour); } + const TCHAR* rtlStr = (childNode->ToElement())->Attribute(TEXT("RTL")); + if (rtlStr) + { + sfi._isRTL = _wcsicmp(TEXT("yes"), rtlStr) == 0; + } + for (TiXmlNode *markNode = childNode->FirstChildElement(TEXT("Mark")); markNode; markNode = markNode->NextSibling(TEXT("Mark"))) @@ -3588,6 +3594,7 @@ void NppParameters::writeSession(const Session & session, const TCHAR *fileName) (fileNameNode->ToElement())->SetAttribute(TEXT("originalFileLastModifTimestamp"), static_cast(viewSessionFiles[i]._originalFileLastModifTimestamp.dwLowDateTime)); (fileNameNode->ToElement())->SetAttribute(TEXT("originalFileLastModifTimestampHigh"), static_cast(viewSessionFiles[i]._originalFileLastModifTimestamp.dwHighDateTime)); (fileNameNode->ToElement())->SetAttribute(TEXT("tabColourId"), static_cast(viewSessionFiles[i]._individualTabColour)); + (fileNameNode->ToElement())->SetAttribute(TEXT("RTL"), viewSessionFiles[i]._isRTL ? TEXT("yes") : TEXT("no")); // docMap (fileNameNode->ToElement())->SetAttribute(TEXT("mapFirstVisibleDisplayLine"), _i64tot(static_cast(viewSessionFiles[i]._mapPos._firstVisibleDisplayLine), szInt64, 10)); diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h index 725600573..004eb5b32 100644 --- a/PowerEditor/src/Parameters.h +++ b/PowerEditor/src/Parameters.h @@ -210,7 +210,7 @@ struct sessionFileInfo : public Position bool _isUserReadOnly = false; bool _isMonitoring = false; int _individualTabColour = -1; - + bool _isRTL = false; std::wstring _backupFilePath; FILETIME _originalFileLastModifTimestamp {}; diff --git a/PowerEditor/src/ScintillaComponent/Buffer.cpp b/PowerEditor/src/ScintillaComponent/Buffer.cpp index 280a2747f..d239a0333 100644 --- a/PowerEditor/src/ScintillaComponent/Buffer.cpp +++ b/PowerEditor/src/ScintillaComponent/Buffer.cpp @@ -86,6 +86,9 @@ Buffer::Buffer(FileManager * pManager, BufferID id, Document doc, DocFileStatus // reset after initialization _canNotify = true; + + if (nppParamInst.getNativeLangSpeaker()->isRTL() && nppParamInst.getNativeLangSpeaker()->isEditZoneRTL()) + _isRTL = true; } diff --git a/PowerEditor/src/ScintillaComponent/Buffer.h b/PowerEditor/src/ScintillaComponent/Buffer.h index 4143094e2..9c7671fbd 100644 --- a/PowerEditor/src/ScintillaComponent/Buffer.h +++ b/PowerEditor/src/ScintillaComponent/Buffer.h @@ -342,6 +342,9 @@ public: return _docColorId; }; + bool isRTL() const { return _isRTL; }; + void setRTL(bool isRTL) { _isRTL = isRTL; }; + private: int indexOfReference(const ScintillaEditView * identifier) const; @@ -420,4 +423,6 @@ private: std::mutex _reloadFromDiskRequestGuard; bool _isInaccessible = false; + + bool _isRTL = false; }; diff --git a/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp b/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp index 541e94cf0..af836108b 100644 --- a/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp +++ b/PowerEditor/src/ScintillaComponent/ScintillaEditView.cpp @@ -20,6 +20,7 @@ #include #include "ScintillaEditView.h" #include "Parameters.h" +#include "localization.h" #include "Sorters.h" #include "verifySignedfile.h" #include "ILexer.h" @@ -319,8 +320,7 @@ void ScintillaEditView::init(HINSTANCE hInst, HWND hPere) if (hNtdllModule) isWINE = ::GetProcAddress(hNtdllModule, "wine_get_version"); - if (isWINE || // There is a performance issue under WINE when DirectWright is ON, so we turn it off if user uses Notepad++ under WINE - isTextDirectionRTL()) // RTL is not compatible with Direct Write Technology + if (isWINE) // There is a performance issue under WINE when DirectWright is ON, so we turn it off if user uses Notepad++ under WINE nppGui._writeTechnologyEngine = defaultTechnology; if (nppGui._writeTechnologyEngine == directWriteTechnology) @@ -2228,6 +2228,9 @@ void ScintillaEditView::activateBuffer(BufferID buffer, bool force) int enabledCH = svp._isChangeHistoryEnabled ? (SC_CHANGE_HISTORY_ENABLED | SC_CHANGE_HISTORY_MARKERS) : SC_CHANGE_HISTORY_DISABLED; execute(SCI_SETCHANGEHISTORY, enabledCH); + if (isTextDirectionRTL() != buffer->isRTL()) + changeTextDirection(buffer->isRTL()); + return; //all done } @@ -4214,6 +4217,27 @@ bool ScintillaEditView::isTextDirectionRTL() const void ScintillaEditView::changeTextDirection(bool isRTL) { + if (isTextDirectionRTL() == isRTL) + return; + + NppParameters& nppParamInst = NppParameters::getInstance(); + if (isRTL && nppParamInst.getNppGUI()._writeTechnologyEngine == directWriteTechnology) // RTL is not compatible with Direct Write Technology + { + static bool theWarningIsGiven = false; + + if (!theWarningIsGiven) + { + (nppParamInst.getNativeLangSpeaker())->messageBox("RTLvsDirectWrite", + getHSelf(), + TEXT("RTL is not compatible with Direct Write mode. Please disable DirectWrite mode in MISC. section of Preferences dialog, and restart Notepad++."), + TEXT("Cannot run RTL"), + MB_OK | MB_APPLMODAL); + + theWarningIsGiven = true; + } + return; + } + long exStyle = static_cast(::GetWindowLongPtr(_hSelf, GWL_EXSTYLE)); exStyle = isRTL ? (exStyle | WS_EX_LAYOUTRTL) : (exStyle & (~WS_EX_LAYOUTRTL)); ::SetWindowLongPtr(_hSelf, GWL_EXSTYLE, exStyle); @@ -4246,6 +4270,9 @@ void ScintillaEditView::changeTextDirection(bool isRTL) execute(SCI_ASSIGNCMDKEY, SCK_LEFT + (SCMOD_CTRL << 16), SCI_WORDLEFT); execute(SCI_ASSIGNCMDKEY, SCK_LEFT + ((SCMOD_SHIFT + SCMOD_CTRL) << 16), SCI_WORDLEFTEXTEND); } + + Buffer* buf = getCurrentBuffer(); + buf->setRTL(isRTL); } generic_string ScintillaEditView::getEOLString() const diff --git a/PowerEditor/src/localization.cpp b/PowerEditor/src/localization.cpp index 7c31222dd..d8560bee0 100644 --- a/PowerEditor/src/localization.cpp +++ b/PowerEditor/src/localization.cpp @@ -122,12 +122,30 @@ void NativeLangSpeaker::init(TiXmlDocumentA *nativeLangDocRootA, bool loadIfEngl { TiXmlElementA *element = _nativeLangA->ToElement(); const char *rtl = element->Attribute("RTL"); - if (rtl) - _isRTL = (strcmp(rtl, "yes") == 0); - else - _isRTL = false; - // get original file name (defined by Notpad++) from the attribute + if (rtl) + { + _isRTL = (strcmp(rtl, "yes") == 0); + + if (_isRTL) + { + const char* editZoneRtl = element->Attribute("editZoneRTL"); + if (editZoneRtl) + _isEditZoneRTL = !(strcmp(editZoneRtl, "no") == 0); + else + _isEditZoneRTL = true; + } + else + _isEditZoneRTL = false; + } + else + { + _isRTL = false; + _isEditZoneRTL = false; + } + + + // get original file name (defined by Notpad++) from the attribute _fileName = element->Attribute("filename"); if (!loadIfEnglish && _fileName && stricmp("english.xml", _fileName) == 0) diff --git a/PowerEditor/src/localization.h b/PowerEditor/src/localization.h index 62a70fded..68105c6dd 100644 --- a/PowerEditor/src/localization.h +++ b/PowerEditor/src/localization.h @@ -39,7 +39,6 @@ public: class NativeLangSpeaker { public: - NativeLangSpeaker():_nativeLangA(NULL), _nativeLangEncoding(CP_ACP), _isRTL(false), _fileName(NULL){}; void init(TiXmlDocumentA *nativeLangDocRootA, bool loadIfEnglish = false); void changeConfigLang(HWND hDlg); void changeLangTabContextMenu(HMENU hCM); @@ -66,6 +65,10 @@ public: return _isRTL; }; + bool isEditZoneRTL() const { + return _isEditZoneRTL; + }; + const char * getFileName() const { return _fileName; }; @@ -92,10 +95,11 @@ public: int messageBox(const char *msgBoxTagName, HWND hWnd, const TCHAR *message, const TCHAR *title, int msgBoxType, int intInfo = 0, const TCHAR *strInfo = NULL); private: - TiXmlNodeA *_nativeLangA; - int _nativeLangEncoding; - bool _isRTL; - const char *_fileName; + TiXmlNodeA *_nativeLangA = nullptr; + int _nativeLangEncoding = CP_ACP; + bool _isRTL = false; // for Notepad++ GUI + bool _isEditZoneRTL = false; // for Scitilla + const char *_fileName = nullptr; std::map _shortcutMenuEntryNameMap; };