Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/elfmz/far2l.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelfmz <fenix1905@tut.by>2022-02-07 02:22:40 +0300
committerelfmz <fenix1905@tut.by>2022-02-07 02:22:40 +0300
commit05994fed47189c33d53515f1c5682e55e235c3ae (patch)
tree649ae4f033aedb74c405c0db4a22a70af7e7c230 /far2l/src/fileedit.cpp
parentaef68b79b183f7cbdf6d2e4f7b597b2077a47261 (diff)
editor: make save file more tolerable to no space situation
Diffstat (limited to 'far2l/src/fileedit.cpp')
-rw-r--r--far2l/src/fileedit.cpp339
1 files changed, 171 insertions, 168 deletions
diff --git a/far2l/src/fileedit.cpp b/far2l/src/fileedit.cpp
index 7fafbf39..1e0d5b96 100644
--- a/far2l/src/fileedit.cpp
+++ b/far2l/src/fileedit.cpp
@@ -1649,6 +1649,152 @@ int FileEditor::LoadFile(const wchar_t *Name,int &UserBreak)
}
//TextFormat и Codepage используются ТОЛЬКО, если bSaveAs = true!
+void FileEditor::SaveContent(const wchar_t *Name, IContentWriter *Writer, bool bSaveAs, int TextFormat, UINT codepage, bool AddSignature)
+{
+ DWORD dwSignature = 0;
+ DWORD SignLength = 0;
+ switch (codepage)
+ {
+ case CP_UTF32LE:
+ dwSignature = SIGN_UTF32LE;
+ SignLength = 4;
+ if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO);
+ break;
+ case CP_UTF32BE:
+ dwSignature = SIGN_UTF32BE;
+ SignLength = 4;
+ if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO);
+ break;
+ case CP_UTF16LE:
+ dwSignature = SIGN_UTF16LE;
+ SignLength = 2;
+ if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO);
+ break;
+ case CP_UTF16BE:
+ dwSignature = SIGN_UTF16BE;
+ SignLength = 2;
+ if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO);
+ break;
+ case CP_UTF8:
+ dwSignature = SIGN_UTF8;
+ SignLength = 3;
+ if (!bSaveAs) AddSignature = (m_AddSignature == FB_YES);
+ break;
+ }
+ if (AddSignature)
+ Writer->Write(&dwSignature,SignLength);
+
+ DWORD StartTime=WINPORT(GetTickCount)();
+ size_t LineNumber=0;
+
+ std::string tmpstr;
+ std::vector<unsigned char> tmpbuf;
+
+ for (Edit *CurPtr=m_editor->TopList; CurPtr; CurPtr=CurPtr->m_next,LineNumber++)
+ {
+ DWORD CurTime=WINPORT(GetTickCount)();
+
+ if (CurTime-StartTime>RedrawTimeout)
+ {
+ StartTime=CurTime;
+ Editor::EditorShowMsg(MSG(MEditTitle),MSG(MEditSaving),Name,(int)(LineNumber*100/m_editor->NumLastLine));
+ }
+
+ const wchar_t *SaveStr, *EndSeq;
+
+ int Length;
+
+ CurPtr->GetBinaryString(&SaveStr,&EndSeq,Length);
+
+ if (!*EndSeq && CurPtr->m_next)
+ EndSeq=*m_editor->GlobalEOL ? m_editor->GlobalEOL:DOS_EOL_fmt;
+
+ if (TextFormat && *EndSeq)
+ {
+ EndSeq=m_editor->GlobalEOL;
+ CurPtr->SetEOL(EndSeq);
+ }
+
+ int EndLength=StrLength(EndSeq);
+ if (codepage == CP_WIDE_LE)
+ {
+ if (Length)
+ Writer->Write(SaveStr,Length*sizeof(wchar_t));
+ if (EndLength)
+ Writer->Write(EndSeq,EndLength*sizeof(wchar_t));
+ }
+ else if (codepage == CP_UTF8)
+ {
+ Wide2MB(SaveStr, Length, tmpstr);
+ if (EndLength)
+ Wide2MB(EndSeq, EndLength, tmpstr, true);
+ if (!tmpstr.empty())
+ Writer->Write(tmpstr.data(),tmpstr.size());
+ }
+ else
+ {
+ if (Length)
+ {
+ const DWORD bufsize = (codepage == CP_WIDE_BE) ? Length * sizeof(wchar_t)
+ : WINPORT(WideCharToMultiByte)(codepage, 0, SaveStr, Length, nullptr, 0, nullptr, nullptr);
+ tmpbuf.resize(bufsize);
+
+ if (codepage == CP_WIDE_BE) {
+ WideReverse(SaveStr, (wchar_t *)tmpbuf.data(), Length);
+ } else
+ WINPORT(WideCharToMultiByte)(codepage, 0, SaveStr, Length, (char *)tmpbuf.data(), bufsize, nullptr, nullptr);
+
+ Writer->Write(tmpbuf.data(), bufsize);
+ }
+
+ if (EndLength)
+ {
+ const DWORD bufsize = (codepage == CP_WIDE_BE ? EndLength*sizeof(wchar_t)
+ : WINPORT(WideCharToMultiByte)(codepage, 0, EndSeq, EndLength, nullptr, 0, nullptr, nullptr));
+ tmpbuf.resize(bufsize);
+ if (codepage == CP_WIDE_BE)
+ WideReverse(EndSeq, (wchar_t *)tmpbuf.data(), EndLength);
+ else
+ WINPORT(WideCharToMultiByte)(codepage, 0, EndSeq, EndLength, (char *)tmpbuf.data(), bufsize, nullptr, nullptr);
+
+ Writer->Write(tmpbuf.data(), bufsize);
+ }
+ }
+ }
+}
+
+
+struct ContentMeasurer : IContentWriter
+{
+ INT64 MeasuredSize = 0;
+
+ virtual void Write(const void *Data, size_t Length)
+ {
+ MeasuredSize+= Length;
+ }
+};
+
+class ContentSaver : public IContentWriter
+{
+ CachedWrite CW;
+
+public:
+ ContentSaver(File &EditFile) : CW(EditFile)
+ {
+ }
+
+ virtual void Write(const void *Data, size_t Length)
+ {
+ if (!CW.Write(Data, Length))
+ throw WINPORT(GetLastError)();
+ }
+
+ void Flush()
+ {
+ if (!CW.Flush())
+ throw WINPORT(GetLastError)();
+ }
+};
int FileEditor::SaveFile(const wchar_t *Name,int Ask, bool bSaveAs, int TextFormat, UINT codepage, bool AddSignature)
{
@@ -1872,16 +2018,6 @@ int FileEditor::SaveFile(const wchar_t *Name,int Ask, bool bSaveAs, int TextForm
}
CtrlObject->Plugins.ProcessEditorEvent(EE_SAVE,nullptr);
- File EditFile;
- DWORD dwWritten=0;
- // Don't use CreationDisposition=CREATE_ALWAYS here - it's kills alternate streams
- if(!EditFile.Open(Name, GENERIC_WRITE, FILE_SHARE_READ, nullptr, Flags.Check(FFILEEDIT_NEW)?CREATE_NEW:TRUNCATE_EXISTING, FILE_ATTRIBUTE_ARCHIVE|FILE_FLAG_SEQUENTIAL_SCAN))
- {
- //_SVS(SysLogLastError();SysLog(L"Name='%ls',FileAttributes=%d",Name,FileAttributes));
- RetCode=SAVEFILE_ERROR;
- SysErrorCode=WINPORT(GetLastError)();
- goto end;
- }
m_editor->UndoSavePos=m_editor->UndoPos;
m_editor->Flags.Clear(FEDITOR_UNDOSAVEPOSLOST);
@@ -1897,176 +2033,45 @@ int FileEditor::SaveFile(const wchar_t *Name,int Ask, bool bSaveAs, int TextForm
SetCursorType(FALSE,0);
TPreRedrawFuncGuard preRedrawFuncGuard(Editor::PR_EditorShowMsg);
- DWORD dwSignature = 0;
- DWORD SignLength = 0;
- switch (codepage)
- {
- case CP_UTF32LE:
- dwSignature = SIGN_UTF32LE;
- SignLength = 4;
- if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO);
- break;
- case CP_UTF32BE:
- dwSignature = SIGN_UTF32BE;
- SignLength = 4;
- if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO);
- break;
- case CP_UTF16LE:
- dwSignature = SIGN_UTF16LE;
- SignLength = 2;
- if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO);
- break;
- case CP_UTF16BE:
- dwSignature = SIGN_UTF16BE;
- SignLength = 2;
- if (!bSaveAs) AddSignature = (m_AddSignature != FB_NO);
- break;
- case CP_UTF8:
- dwSignature = SIGN_UTF8;
- SignLength = 3;
- if (!bSaveAs) AddSignature = (m_AddSignature == FB_YES);
- break;
- }
- if (AddSignature)
- {
- if (!EditFile.Write(&dwSignature,SignLength,&dwWritten,nullptr)||dwWritten!=SignLength)
- {
- EditFile.Close();
- apiDeleteFile(Name);
- RetCode=SAVEFILE_ERROR;
- goto end;
- }
- }
-
- DWORD StartTime=WINPORT(GetTickCount)();
- size_t LineNumber=0;
- CachedWrite Cache(EditFile);
+ try {
+ ContentMeasurer cm;
+ SaveContent(Name, &cm, bSaveAs, TextFormat, codepage, AddSignature);
- std::string tmpstr;
+ try {
+ File EditFile;
+ if (!EditFile.Open(Name, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_ARCHIVE|FILE_FLAG_SEQUENTIAL_SCAN))
+ throw WINPORT(GetLastError)();
- for (Edit *CurPtr=m_editor->TopList; CurPtr; CurPtr=CurPtr->m_next,LineNumber++)
- {
- DWORD CurTime=WINPORT(GetTickCount)();
-
- if (CurTime-StartTime>RedrawTimeout)
- {
- StartTime=CurTime;
- Editor::EditorShowMsg(MSG(MEditTitle),MSG(MEditSaving),Name,(int)(LineNumber*100/m_editor->NumLastLine));
- }
-
- const wchar_t *SaveStr, *EndSeq;
-
- int Length;
-
- CurPtr->GetBinaryString(&SaveStr,&EndSeq,Length);
-
- if (!*EndSeq && CurPtr->m_next)
- EndSeq=*m_editor->GlobalEOL ? m_editor->GlobalEOL:DOS_EOL_fmt;
-
- if (TextFormat && *EndSeq)
- {
- EndSeq=m_editor->GlobalEOL;
- CurPtr->SetEOL(EndSeq);
- }
-
- int EndLength=StrLength(EndSeq);
- bool bError = false;
-
- if (codepage == CP_WIDE_LE)
- {
- if (
- (Length && !Cache.Write(SaveStr,Length*sizeof(wchar_t))) ||
- (EndLength && !Cache.Write(EndSeq,EndLength*sizeof(wchar_t)))
- )
+ if (!Flags.Check(FFILEEDIT_NEW))
{
- SysErrorCode=WINPORT(GetLastError)();
- bError = true;
- }
- }
- else if (codepage == CP_UTF8)
- {
- Wide2MB(SaveStr, Length, tmpstr);
- if (EndLength)
- Wide2MB(EndSeq, EndLength, tmpstr, true);
- if (!tmpstr.empty() && !Cache.Write(tmpstr.data(),tmpstr.size()))
- bError = true;
- }
- else
- {
- if (Length)
- {
- DWORD length = (codepage == CP_WIDE_BE) ? Length * sizeof(wchar_t) :
- WINPORT(WideCharToMultiByte)(codepage, 0, SaveStr, Length, nullptr, 0, nullptr, nullptr);
- char *SaveStrCopy=(char *)malloc(length);
-
- if (SaveStrCopy)
- {
- if (codepage == CP_WIDE_BE) {
- WideReverse(SaveStr, (wchar_t *)SaveStrCopy, Length);
- } else
- WINPORT(WideCharToMultiByte)(codepage, 0, SaveStr, Length, SaveStrCopy, length, nullptr, nullptr);
-
- if (!Cache.Write(SaveStrCopy,length))
- {
- bError = true;
- SysErrorCode=WINPORT(GetLastError)();
- }
+ if (!EditFile.SetPointer(cm.MeasuredSize, nullptr, FILE_BEGIN) || !EditFile.SetEnd())
+ throw WINPORT(GetLastError)();
- free(SaveStrCopy);
- }
- else
- bError = true;
+ EditFile.SetPointer(0, nullptr, FILE_BEGIN);
}
- if (!bError)
- {
- if (EndLength)
- {
- DWORD endlength = (codepage == CP_WIDE_BE ? EndLength*sizeof(wchar_t)
- : WINPORT(WideCharToMultiByte)(codepage, 0, EndSeq, EndLength, nullptr, 0, nullptr, nullptr));
- char *EndSeqCopy=(char *)malloc(endlength);
+ ContentSaver cs(EditFile);
+ SaveContent(Name, &cs, bSaveAs, TextFormat, codepage, AddSignature);
+ cs.Flush();
- if (EndSeqCopy)
- {
- if (codepage == CP_WIDE_BE)
- WideReverse(EndSeq, (wchar_t *)EndSeqCopy, EndLength);
- else
- WINPORT(WideCharToMultiByte)(codepage, 0, EndSeq, EndLength, EndSeqCopy, endlength, nullptr, nullptr);
+ EditFile.SetEnd();
- if (!Cache.Write(EndSeqCopy,endlength))
- {
- bError = true;
- SysErrorCode=WINPORT(GetLastError)();
- }
+ } catch (...) {
+ if (Flags.Check(FFILEEDIT_NEW))
+ apiDeleteFile(Name);
- free(EndSeqCopy);
- }
- else
- bError = true;
- }
- }
- }
-
- if (bError)
- {
- EditFile.Close();
- apiDeleteFile(Name);
- RetCode=SAVEFILE_ERROR;
- goto end;
+ throw;
}
}
-
- if(Cache.Flush())
+ catch (DWORD ErrorCode)
{
- EditFile.SetEnd();
- EditFile.Close();
+ SysErrorCode = ErrorCode;
+ RetCode = SAVEFILE_ERROR;
}
- else
+ catch (std::exception &e)
{
- SysErrorCode=WINPORT(GetLastError)();
- EditFile.Close();
- apiDeleteFile(Name);
- RetCode=SAVEFILE_ERROR;
+ SysErrorCode = ENOMEM;
+ RetCode = SAVEFILE_ERROR;
}
}
@@ -2074,8 +2079,6 @@ int FileEditor::SaveFile(const wchar_t *Name,int Ask, bool bSaveAs, int TextForm
FileHolder->OnFileEdited(Name);
}
-end:
-
if (FileUnmakeWritable)
{
FileUnmakeWritable->Unmake();