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
This commit is contained in:
Don Ho 2023-11-30 15:11:46 +01:00
parent ffc0ed2516
commit 2724e0ddbb
14 changed files with 101 additions and 38 deletions

View File

@ -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."/>
<RTLvsDirectWrite title="Cannot run RTL" message="RTL is not compatible with DirectWrite mode. Please disable DirectWrite mode in MISC. section of Preferences dialog, restart Notepad++, and try this command again."/>
<RTLvsDirectWrite title="Cannot run RTL" message="RTL is not compatible with DirectWrite mode. Please disable DirectWrite mode in MISC. section of Preferences dialog, and restart Notepad++."/>
<FileMemoryAllocationFailed title="Exception: File memory allocation failed" message="There is probably not enough contiguous free memory for the file being loaded by Notepad++."/><!-- HowToReproduce: Try to open multiple files with total size > ~700MB in the x86 Notepad++ (it will depend on the PC memory configuration and the current system memory usage...). -->
</MessageBox>
<ClipboardHistory>

View File

@ -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 &quot;session.xml&quot; now."/>
<RTLvsDirectWrite title="Cannot run RTL" message="RTL is not compatible with DirectWrite mode. Please disable DirectWrite mode in MISC. section of Preferences dialog, restart Notepad++, and try this command again."/>
<RTLvsDirectWrite title="Cannot run RTL" message="RTL is not compatible with DirectWrite mode. Please disable DirectWrite mode in MISC. section of Preferences dialog, and restart Notepad++."/>
<FileMemoryAllocationFailed title="Exception: File memory allocation failed" message="There is probably not enough contiguous free memory for the file being loaded by Notepad++."/><!-- HowToReproduce: Try to open multiple files with total size > ~700MB in the x86 Notepad++ (it will depend on the PC memory configuration and the current system memory usage...). -->
</MessageBox>
<ClipboardHistory>

View File

@ -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 &quot;session.xml&quot; maintenant."/>
<RTLvsDirectWrite title="Exécution de la commande &quot;Texte de droite à gauche&quot; impossible" message="&quot;Texte de droite à gauche&quot; n'est pas compatible avec le mode &quot;DirectWrite&quot;. Veuillez désactiver ce mode dans la section &quot;Divers&quot; du dialogue Préférences, redémarer Notepad++, pour exécuter la commande de nouveau."/>
<RTLvsDirectWrite title="Exécution de la commande &quot;Texte de droite à gauche&quot; impossible" message="&quot;Texte de droite à gauche&quot; n'est pas compatible avec le mode &quot;DirectWrite&quot;. Veuillez désactiver ce mode dans la section &quot;Divers&quot; du dialogue Préférences, et redémarer Notepad++."/>
<FileMemoryAllocationFailed title="Exception : échec de l'allocation de mémoire du fichier" message="Il n'y a probablement pas assez de mémoire libre contiguë pour le fichier chargé par Notepad++."/>
</MessageBox>
<ClipboardHistory>
<PanelTitle name="Historique du presse-papier"/>

View File

@ -1390,7 +1390,8 @@
你想為它們創建佔位欄嗎?
請注意,如果你選擇不創建佔位欄或稍後關閉它們,工作階段檔案將在 Notepad++ 關閉時被修改。我們建議你現在備份工作階段檔案 &quot;session.xml&quot; 。"/>
<RTLvsDirectWrite title="無法執行「文字由右至左」指令" message="「文字由右至左」指令與「直接寫入」模式不相容。 請在偏好設定對話框的「其他」中停用「直接寫入」模式,然後重新​​啟動 Notepad++,重試此指令。"/>
<RTLvsDirectWrite title="無法執行「文字由右至左」指令" message="「文字由右至左」指令與「直接寫入」模式不相容。 請在偏好設定對話框的「其他」中停用「直接寫入」模式,然後重新​​啟動 Notepad++ 。"/>
<FileMemoryAllocationFailed title="例外狀況:檔案記憶體分配失敗" message="可能沒有足夠的連續可用記憶體供 Notepad++ 載入檔案。"/>
</MessageBox>
<ClipboardHistory>
<PanelTitle name="剪貼簿記錄"/>

View File

@ -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<int>(i));
sfi._isRTL = buf->isRTL();
_invisibleEditView.execute(SCI_SETDOCPOINTER, 0, buf->getDocument());
size_t maxLine = static_cast<size_t>(_invisibleEditView.execute(SCI_GETLINECOUNT));

View File

@ -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);

View File

@ -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

View File

@ -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<int32_t>(viewSessionFiles[i]._originalFileLastModifTimestamp.dwLowDateTime));
(fileNameNode->ToElement())->SetAttribute(TEXT("originalFileLastModifTimestampHigh"), static_cast<int32_t>(viewSessionFiles[i]._originalFileLastModifTimestamp.dwHighDateTime));
(fileNameNode->ToElement())->SetAttribute(TEXT("tabColourId"), static_cast<int32_t>(viewSessionFiles[i]._individualTabColour));
(fileNameNode->ToElement())->SetAttribute(TEXT("RTL"), viewSessionFiles[i]._isRTL ? TEXT("yes") : TEXT("no"));
// docMap
(fileNameNode->ToElement())->SetAttribute(TEXT("mapFirstVisibleDisplayLine"), _i64tot(static_cast<LONGLONG>(viewSessionFiles[i]._mapPos._firstVisibleDisplayLine), szInt64, 10));

View File

@ -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 {};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -20,6 +20,7 @@
#include <windowsx.h>
#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<long>(::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

View File

@ -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)

View File

@ -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<std::string, std::wstring> _shortcutMenuEntryNameMap;
};