diff --git a/internal/buffer/backup.go b/internal/buffer/backup.go index cda7a0eb..32180c0a 100644 --- a/internal/buffer/backup.go +++ b/internal/buffer/backup.go @@ -125,7 +125,7 @@ func (b *Buffer) ApplyBackup(fsize int64) (bool, bool) { if choice%3 == 0 { // recover b.LineArray = NewLineArray(uint64(fsize), FFAuto, backup) - b.isModified = true + b.setModified() return true, true } else if choice%3 == 1 { // delete diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go index ef9d2331..00056fc0 100644 --- a/internal/buffer/buffer.go +++ b/internal/buffer/buffer.go @@ -126,20 +126,36 @@ type SharedBuffer struct { } func (b *SharedBuffer) insert(pos Loc, value []byte) { - b.isModified = true b.HasSuggestions = false b.LineArray.insert(pos, value) + b.setModified() inslines := bytes.Count(value, []byte{'\n'}) b.MarkModified(pos.Y, pos.Y+inslines) } + func (b *SharedBuffer) remove(start, end Loc) []byte { - b.isModified = true b.HasSuggestions = false + defer b.setModified() defer b.MarkModified(start.Y, end.Y) return b.LineArray.remove(start, end) } +func (b *SharedBuffer) setModified() { + if b.Type.Scratch { + return + } + + if b.Settings["fastdirty"].(bool) { + b.isModified = true + } else { + var buff [md5.Size]byte + + b.calcHash(&buff) + b.isModified = buff != b.origHash + } +} + // calcHash calculates md5 hash of all lines in the buffer func (b *SharedBuffer) calcHash(out *[md5.Size]byte) { h := md5.New() @@ -653,18 +669,7 @@ func (b *Buffer) Shared() bool { // Modified returns if this buffer has been modified since // being opened func (b *Buffer) Modified() bool { - if b.Type.Scratch { - return false - } - - if b.Settings["fastdirty"].(bool) { - return b.isModified - } - - var buff [md5.Size]byte - - b.calcHash(&buff) - return buff != b.origHash + return b.isModified } // Size returns the number of bytes in the current buffer @@ -1233,7 +1238,6 @@ func (b *Buffer) FindMatchingBrace(start Loc) (Loc, bool, bool) { func (b *Buffer) Retab() { toSpaces := b.Settings["tabstospaces"].(bool) tabsize := util.IntOpt(b.Settings["tabsize"]) - dirty := false for i := 0; i < b.LinesNum(); i++ { l := b.LineBytes(i) @@ -1254,10 +1258,9 @@ func (b *Buffer) Retab() { b.Unlock() b.MarkModified(i, i) - dirty = true } - b.isModified = dirty + b.setModified() } // ParseCursorLocation turns a cursor location like 10:5 (LINE:COL) diff --git a/internal/buffer/save.go b/internal/buffer/save.go index f3e05ad2..3c79089a 100644 --- a/internal/buffer/save.go +++ b/internal/buffer/save.go @@ -206,9 +206,7 @@ func (b *Buffer) Save() error { // AutoSave saves the buffer to its default path func (b *Buffer) AutoSave() error { - // Doing full b.Modified() check every time would be costly, due to the hash - // calculation. So use just isModified even if fastdirty is not set. - if !b.isModified { + if !b.Modified() { return nil } return b.saveToFile(b.Path, false, true) diff --git a/internal/buffer/settings.go b/internal/buffer/settings.go index ed22eae8..9c8b3ce1 100644 --- a/internal/buffer/settings.go +++ b/internal/buffer/settings.go @@ -91,7 +91,7 @@ func (b *Buffer) DoSetOptionNative(option string, nativeValue interface{}) { case "dos": b.Endings = FFDos } - b.isModified = true + b.setModified() } else if option == "syntax" { if !nativeValue.(bool) { b.ClearMatches() @@ -105,7 +105,7 @@ func (b *Buffer) DoSetOptionNative(option string, nativeValue interface{}) { b.Settings["encoding"] = "utf-8" } b.encoding = enc - b.isModified = true + b.setModified() } else if option == "readonly" && b.Type.Kind == BTDefault.Kind { b.Type.Readonly = nativeValue.(bool) } else if option == "hlsearch" {