View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0002872 | Wishes | User Menu | public | 2014-12-01 08:58 | 2015-07-08 20:32 |
| Reporter | Maximus | Assigned To | DrKnS | ||
| Priority | normal | Severity | minor | Reproducibility | always |
| Status | closed | Resolution | fixed | ||
| Product Version | 3.0 | ||||
| Fixed in Version | 3.0 | ||||
| Summary | 0002872: Не ломать кодовую страницу файла FarMenu.ini | ||||
| Description | Мне удобно держать FarMenu.ini в UTF-8. Например, удобно изменения в гите смотреть. Фар такой файл нормально читает, но при любых изменениях через интерфейс - пересохраняет в CP_UNICODE. Приходится каждый раз его открывать в редакторе (с проблемами кодировки) и пересохранять в UTF-8. | ||||
| Tags | No tags attached. | ||||
| Build | 4351 | ||||
|
|
0001-Implement-CachedWrite-WriteStr-considering-requested.patch (2,540 bytes)
From 652083cbb2575163edb15618d92fed587754c1e6 Mon Sep 17 00:00:00 2001
From: Maximus5 <ConEmu.Maximus5@gmail.com>
Date: Fri, 28 Nov 2014 20:03:44 +0300
Subject: [PATCH 1/2] Implement CachedWrite::WriteStr considering requested
codepage
---
unicode_far/cache.cpp | 37 +++++++++++++++++++++++++++++++++++--
unicode_far/cache.hpp | 4 +++-
2 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/unicode_far/cache.cpp b/unicode_far/cache.cpp
index 6645a29..fa3ed2e 100644
--- a/unicode_far/cache.cpp
+++ b/unicode_far/cache.cpp
@@ -188,11 +188,12 @@ bool CachedRead::FillBuffer()
return Result;
}
-CachedWrite::CachedWrite(api::File& file):
+CachedWrite::CachedWrite(api::File& file, uintptr_t codepage):
file(file),
Buffer(0x10000),
FreeSize(Buffer.size()),
- Flushed(false)
+ Flushed(false),
+ codepage(codepage)
{
}
@@ -233,6 +234,38 @@ bool CachedWrite::Write(LPCVOID Data, size_t DataSize)
return Result;
}
+bool CachedWrite::WriteStr(const wchar_t* SaveStr, size_t Length)
+{
+ if (!Length)
+ return true;
+
+ if (codepage == CP_UNICODE)
+ {
+ return Write(SaveStr, Length*sizeof(wchar_t));
+ }
+ else
+ {
+ auto SwapBytes = [](const wchar_t* src, char* dst, size_t count)
+ {
+ return _swab(reinterpret_cast<char*>(const_cast<wchar_t*>(src)), dst, static_cast<int>(count));
+ };
+
+ DWORD length = (codepage == CP_REVERSEBOM?static_cast<DWORD>(Length*sizeof(wchar_t)):WideCharToMultiByte(codepage, 0, SaveStr, Length, nullptr, 0, nullptr, nullptr));
+ char_ptr SaveStrCopy(length);
+
+ if (SaveStrCopy)
+ {
+ if (codepage == CP_REVERSEBOM)
+ SwapBytes(SaveStr, SaveStrCopy.get(), length);
+ else
+ WideCharToMultiByte(codepage, 0, SaveStr, Length, SaveStrCopy.get(), length, nullptr, nullptr);
+
+ return Write(SaveStrCopy.get(),length);
+ }
+ }
+ return false;
+}
+
bool CachedWrite::Flush()
{
if (!Flushed)
diff --git a/unicode_far/cache.hpp b/unicode_far/cache.hpp
index 75fa6ad..c0fadba 100644
--- a/unicode_far/cache.hpp
+++ b/unicode_far/cache.hpp
@@ -57,9 +57,10 @@ private:
class CachedWrite: NonCopyable
{
public:
- CachedWrite(api::File& file);
+ CachedWrite(api::File& file, uintptr_t codepage = CP_UNICODE);
~CachedWrite();
bool Write(LPCVOID Data, size_t DataSize);
+ bool WriteStr(const wchar_t* SaveStr, size_t Length);
bool Flush();
private:
@@ -67,4 +68,5 @@ private:
std::vector<BYTE> Buffer;
size_t FreeSize;
bool Flushed;
+ uintptr_t codepage;
};
--
1.9.4.msysgit.2
|
|
|
0002-Don-t-break-FarMenu.ini-s-codepage-saved-by-user.patch (5,549 bytes)
From ef85be261321d03c1214f78570696ba2339aede4 Mon Sep 17 00:00:00 2001
From: Maximus5 <ConEmu.Maximus5@gmail.com>
Date: Fri, 28 Nov 2014 20:04:01 +0300
Subject: [PATCH 2/2] Don't break FarMenu.ini's codepage saved by user
---
unicode_far/usermenu.cpp | 66 +++++++++++++++++++++++++++++++++++-------------
unicode_far/usermenu.hpp | 1 +
2 files changed, 50 insertions(+), 17 deletions(-)
diff --git a/unicode_far/usermenu.cpp b/unicode_far/usermenu.cpp
index 45e5d1d..b150869 100644
--- a/unicode_far/usermenu.cpp
+++ b/unicode_far/usermenu.cpp
@@ -129,24 +129,24 @@ static void MenuListToFile(const UserMenu::menu_container& Menu, CachedWrite& CW
{
std::for_each(CONST_RANGE(Menu, i)
{
- CW.Write(i.strHotKey.data(), static_cast<DWORD>(i.strHotKey.size()*sizeof(WCHAR)));
- CW.Write(L": ", 3*sizeof(WCHAR));
- CW.Write(i.strLabel.data(), static_cast<DWORD>(i.strLabel.size()*sizeof(WCHAR)));
- CW.Write(L"\r\n", 2*sizeof(WCHAR));
+ CW.WriteStr(i.strHotKey.data(), static_cast<DWORD>(i.strHotKey.size()));
+ CW.WriteStr(L": ", 3);
+ CW.WriteStr(i.strLabel.data(), static_cast<DWORD>(i.strLabel.size()));
+ CW.WriteStr(L"\r\n", 2);
if (i.Submenu)
{
- CW.Write(L"{\r\n", 3*sizeof(WCHAR));
+ CW.WriteStr(L"{\r\n", 3);
MenuListToFile(i.Menu, CW);
- CW.Write(L"}\r\n", 3*sizeof(WCHAR));
+ CW.WriteStr(L"}\r\n", 3);
}
else
{
std::for_each(CONST_RANGE(i.Commands, str)
{
- CW.Write(L" ", 4*sizeof(WCHAR));
- CW.Write(str.data(), static_cast<DWORD>(str.size()*sizeof(WCHAR)));
- CW.Write(L"\r\n", 2*sizeof(WCHAR));
+ CW.WriteStr(L" ", 4);
+ CW.WriteStr(str.data(), static_cast<DWORD>(str.size()));
+ CW.WriteStr(L"\r\n", 2);
});
}
});
@@ -216,7 +216,8 @@ static void MenuFileToList(UserMenu::menu_container& Menu, GetFileString& GetStr
UserMenu::UserMenu(bool MenuType):
m_MenuMode(MM_LOCAL),
m_MenuModified(false),
- m_ItemChanged(false)
+ m_ItemChanged(false),
+ m_MenuCP(CP_UNICODE)
{
ProcessUserMenu(MenuType, string());
}
@@ -224,7 +225,8 @@ UserMenu::UserMenu(bool MenuType):
UserMenu::UserMenu(const string& MenuFileName):
m_MenuMode(MM_LOCAL),
m_MenuModified(false),
- m_ItemChanged(false)
+ m_ItemChanged(false),
+ m_MenuCP(CP_UNICODE)
{
ProcessUserMenu(false, MenuFileName);
}
@@ -238,6 +240,8 @@ void UserMenu::SaveMenu(const string& MenuFileName)
if (m_MenuModified)
{
DWORD FileAttr=api::GetFileAttributes(MenuFileName);
+ uintptr_t MenuCP = CP_UNICODE;
+ api::File MenuFile;
if (FileAttr != INVALID_FILE_ATTRIBUTES)
{
@@ -252,15 +256,41 @@ void UserMenu::SaveMenu(const string& MenuFileName)
if (FileAttr & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))
api::SetFileAttributes(MenuFileName,FILE_ATTRIBUTE_NORMAL);
+
+ if (MenuFile.Open(MenuFileName,GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING))
+ {
+ if (!GetFileFormat(MenuFile, MenuCP))
+ MenuCP = CP_UNICODE;
+ else
+ m_MenuCP = MenuCP;
+ MenuFile.Close();
+ }
}
// Don't use CreationDisposition=CREATE_ALWAYS here - it kills alternate streams
- api::File MenuFile;
if (MenuFile.Open(MenuFileName,GENERIC_WRITE, FILE_SHARE_READ, nullptr, FileAttr==INVALID_FILE_ATTRIBUTES?CREATE_NEW:TRUNCATE_EXISTING))
{
- CachedWrite CW(MenuFile);
- WCHAR Data = SIGN_UNICODE;
- CW.Write(&Data, 1*sizeof(WCHAR));
+ DWORD dwSignature = 0;
+ size_t SignLength = 0, SignWritten;
+ switch (MenuCP)
+ {
+ case CP_UNICODE:
+ dwSignature = SIGN_UNICODE;
+ SignLength=2;
+ break;
+ case CP_REVERSEBOM:
+ dwSignature = SIGN_REVERSEBOM;
+ SignLength=2;
+ break;
+ case CP_UTF8:
+ dwSignature = SIGN_UTF8;
+ SignLength=3;
+ break;
+ }
+ if (SignLength)
+ MenuFile.Write(&dwSignature,SignLength,SignWritten,nullptr);
+
+ CachedWrite CW(MenuFile, MenuCP);
MenuListToFile(m_Menu, CW);
CW.Flush();
UINT64 Size = 0;
@@ -268,7 +298,7 @@ void UserMenu::SaveMenu(const string& MenuFileName)
MenuFile.Close();
// ���� ���� FarMenu.ini ����, �� ������ ���
- if (Size<3) // 2 for BOM
+ if (Size<=SignLength)
{
api::DeleteFile(MenuFileName);
}
@@ -357,6 +387,8 @@ void UserMenu::ProcessUserMenu(bool MenuType, const string& MenuFileName)
uintptr_t MenuCP;
if (!GetFileFormat(MenuFile, MenuCP))
MenuCP = CP_OEMCP;
+ else
+ m_MenuCP = MenuCP;
GetFileString GetStr(MenuFile, MenuCP);
MenuFileToList(m_Menu, GetStr);
@@ -648,7 +680,7 @@ int UserMenu::ProcessSingleMenu(std::list<UserMenuItem>& Menu, int MenuPos, std:
{
auto OldTitle = std::make_unique<ConsoleTitle>();
SaveMenu(MenuFileName);
- auto ShellEditor = FileEditor::create(MenuFileName, CP_UNICODE, FFILEEDIT_DISABLEHISTORY, -1, -1, nullptr);
+ auto ShellEditor = FileEditor::create(MenuFileName, m_MenuCP, FFILEEDIT_DISABLEHISTORY, -1, -1, nullptr);
OldTitle.reset();
Global->WindowManager->ExecuteModal(ShellEditor);
if (!ShellEditor->IsFileChanged() || (!MenuFile.Open(MenuFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING)))
diff --git a/unicode_far/usermenu.hpp b/unicode_far/usermenu.hpp
index 1034e2e..251aeb6 100644
--- a/unicode_far/usermenu.hpp
+++ b/unicode_far/usermenu.hpp
@@ -57,5 +57,6 @@ private:
MENUMODE m_MenuMode;
bool m_MenuModified;
bool m_ItemChanged;
+ uintptr_t m_MenuCP;
menu_container m_Menu;
};
--
1.9.4.msysgit.2
|
|
|
может быть просто всегда сохранять в UTF-8 ? |
|
|
Я за. А кому-то понадобится KOI8-R. Не? |
|
|
<off> KOI-8 понадобится M$ :-) У них до сих пор в клиенте Outlook эта кодировка дефолтовая. </off> |
|
|
Голосую за (хоть за сохранение кодировки, хоть за UTF-8 всегда). Столкнулся, как только включил некоторые свои файлы меню в гит. |
|
|
4351. Новое меню сохраняется в UTF-8. Сохранённое в каком-нибудь более другом юникоде таким и останется. Сохранённое не в юникоде при любом изменении пересохранится в UTF-8. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2014-12-01 08:58 | Maximus | New Issue | |
| 2014-12-01 09:03 | Maximus | File Added: 0001-Implement-CachedWrite-WriteStr-considering-requested.patch | |
| 2014-12-01 09:03 | Maximus | File Added: 0002-Don-t-break-FarMenu.ini-s-codepage-saved-by-user.patch | |
| 2014-12-01 11:20 | 2useven10 | Note Added: 0013292 | |
| 2014-12-01 11:24 | Maximus | Note Added: 0013293 | |
| 2014-12-01 11:51 | DrKnS | Assigned To | => DrKnS |
| 2014-12-01 11:51 | DrKnS | Status | new => assigned |
| 2014-12-01 12:58 | vskirdin | Note Added: 0013294 | |
| 2015-04-15 15:03 | NightRoman | Note Added: 0013635 | |
| 2015-04-15 20:18 | DrKnS | Note Added: 0013636 | |
| 2015-04-15 20:18 | DrKnS | Status | assigned => feedback |
| 2015-07-08 20:32 | DrKnS | Build | => 4351 |
| 2015-07-08 20:32 | DrKnS | Status | feedback => closed |
| 2015-07-08 20:32 | DrKnS | Resolution | open => fixed |
| 2015-07-08 20:32 | DrKnS | Fixed in Version | => 3.0 |