- commit
- 877f0bee302d6ea47d494863769600bf002ae33e
- parent
- 4474bac87501fcbbc9336dd9dc81f0816e8e31ad
- author
- Dami <dami.etoile@gmail.com>
| M | internal/ | 26 | ++++--- |
| M | internal/ | 50 | +++++++------ |
| M | internal/ | 117 | ++++++++++++++++++------------ |
@@ -239,16 +239,7 @@ func (w *Workbook) push(st *step) {
239239 240240 // dropUnchanged removes from st what ended the step as it began.241241 func (w *Workbook) dropUnchanged(st *step) {242- for k, width := range st.widths {243- if k.s.widths[k.col] == width {244- delete(st.widths, k)245- }246- }247- for k, l := range st.lines {248- if k.s.line(k.row, k.n) == l {249- delete(st.lines, k)250- }251- }242+ st.dropUnchangedLines()252243 for l, c := range st.cells {253244 if c == nil && l.s.cells.get(l.a) == nil {254245 delete(st.cells, l)@@ -286,6 +277,21 @@ func (w *Workbook) dropUnchanged(st *step) {
286277 }287278 }288279 280+// dropUnchangedLines removes the column widths and line formats that281+// ended the step as they began.282+func (st *step) dropUnchangedLines() {283+ for k, width := range st.widths {284+ if k.s.widths[k.col] == width {285+ delete(st.widths, k)286+ }287+ }288+ for k, l := range st.lines {289+ if k.s.line(k.row, k.n) == l {290+ delete(st.lines, k)291+ }292+ }293+}294+289295 // sameName reports whether two named ranges (nil for undefined) are the290296 // same.291297 func sameName(a, b *Name) bool {@@ -97,8 +97,33 @@ func (s *Sheet) SortRange(r Rect, keys []SortKey) {
9797 rows = append(rows, a.Row)9898 }9999 }100- // Rows with a key sort to the top; the others (blank keys, and blank101- // rows) keep their order below them.100+ dst := s.sortedRows(r, rows, keys)101+ next := make(map[Addr]*Cell, len(old))102+ for a, c := range old {103+ to := Addr{Col: a.Col, Row: dst[a.Row]}104+ if to.Row != a.Row {105+ c = c.rewritten(formula.Shift(0, to.Row-a.Row))106+ }107+ next[to] = c108+ }109+ s.change("sort "+r.String(), r, func() {110+ for a := range old {111+ if next[a] == nil {112+ s.place(a, nil)113+ }114+ }115+ for a, c := range next {116+ if old[a] != c {117+ s.place(a, c)118+ }119+ }120+ })121+}122+123+// sortedRows maps each of rows, the rows of r with cells, to where the124+// sort puts it. Rows with a key sort to the top; the others (blank keys,125+// and blank rows) keep their order below them.126+func (s *Sheet) sortedRows(r Rect, rows []int, keys []SortKey) map[int]int {102127 var keyed, rest []int103128 for _, row := range rows {104129 if s.keysBlank(keys, row) {@@ -122,26 +147,7 @@ func (s *Sheet) SortRange(r Rect, keys []SortKey) {
122147 }123148 dst[row] = row + len(keyed) - n124149 }125- next := make(map[Addr]*Cell, len(old))126- for a, c := range old {127- to := Addr{Col: a.Col, Row: dst[a.Row]}128- if to.Row != a.Row {129- c = c.rewritten(formula.Shift(0, to.Row-a.Row))130- }131- next[to] = c132- }133- s.change("sort "+r.String(), r, func() {134- for a := range old {135- if next[a] == nil {136- s.place(a, nil)137- }138- }139- for a, c := range next {140- if old[a] != c {141- s.place(a, c)142- }143- }144- })150+ return dst145151 }146152 147153 // keysBlank reports whether every key of row is blank.@@ -42,60 +42,81 @@ func checkStore(t *testing.T, st *cellStore, rng *rand.Rand) {
4242 t.Helper()4343 for range 20 {4444 r := NewRect(Addr{Col: rng.IntN(45), Row: rng.IntN(80000)}, Addr{Col: rng.IntN(45), Row: rng.IntN(MaxRows)})45- var want []Addr46- for a := range st.all() {47- if r.Contains(a) {48- want = append(want, a)49- }50- }51- sortAddrs(want)52- var got []Addr53- for a := range st.inRange(r) {54- got = append(got, a)55- }56- if !slices.Equal(got, want) {57- t.Fatalf("inRange(%v): %d cells, want %d", r, len(got), len(want))58- }59- b, ok := st.bounds(r)60- if ok != (len(want) > 0) {61- t.Fatalf("bounds(%v) found %v with %d cells", r, ok, len(want))45+ checkRange(t, st, r)46+ checkFilled(t, st, r)47+ checkNextRow(t, st, rng.IntN(40), rng.IntN(MaxRows))48+ }49+}50+51+// checkRange compares inRange and bounds with the map.52+func checkRange(t *testing.T, st *cellStore, r Rect) {53+ t.Helper()54+ var want []Addr55+ for a := range st.all() {56+ if r.Contains(a) {57+ want = append(want, a)6258 }63- for _, a := range want {64- if !b.Contains(a) {65- t.Fatalf("bounds(%v) = %v misses %v", r, b, a)66- }59+ }60+ sortAddrs(want)61+ var got []Addr62+ for a := range st.inRange(r) {63+ got = append(got, a)64+ }65+ if !slices.Equal(got, want) {66+ t.Fatalf("inRange(%v): %d cells, want %d", r, len(got), len(want))67+ }68+ b, ok := st.bounds(r)69+ if ok != (len(want) > 0) {70+ t.Fatalf("bounds(%v) found %v with %d cells", r, ok, len(want))71+ }72+ for _, a := range want {73+ if !b.Contains(a) {74+ t.Fatalf("bounds(%v) = %v misses %v", r, b, a)6775 }68- if ok && (!slices.ContainsFunc(want, func(a Addr) bool { return a.Row == b.From.Row }) ||69- !slices.ContainsFunc(want, func(a Addr) bool { return a.Col == b.To.Col })) {70- t.Fatalf("bounds(%v) = %v isn't tight", r, b)76+ }77+ if ok && (!slices.ContainsFunc(want, func(a Addr) bool { return a.Row == b.From.Row }) ||78+ !slices.ContainsFunc(want, func(a Addr) bool { return a.Col == b.To.Col })) {79+ t.Fatalf("bounds(%v) = %v isn't tight", r, b)80+ }81+}82+83+// checkFilled compares the index of cells with contents with the map.84+func checkFilled(t *testing.T, st *cellStore, r Rect) {85+ t.Helper()86+ var filled []Addr87+ for a, c := range st.all() {88+ if r.Contains(a) && !c.Blank() {89+ filled = append(filled, a)7190 }72- var filled []Addr73- for a, c := range st.all() {74- if r.Contains(a) && !c.Blank() {75- filled = append(filled, a)76- }77- if st.filled.has(a) == c.Blank() {78- t.Fatalf("filled index says %v for %v", st.filled.has(a), a)79- }91+ if st.filled.has(a) == c.Blank() {92+ t.Fatalf("filled index says %v for %v", st.filled.has(a), a)8093 }81- if fb, ok := st.filled.bounds(r); ok != (len(filled) > 0) || ok && !slices.ContainsFunc(filled, func(a Addr) bool { return a.Row == fb.To.Row }) {82- t.Fatalf("filled bounds(%v) = %v %v", r, fb, ok)94+ }95+ fb, ok := st.filled.bounds(r)96+ if ok != (len(filled) > 0) || ok && !slices.ContainsFunc(filled, func(a Addr) bool { return a.Row == fb.To.Row }) {97+ t.Fatalf("filled bounds(%v) = %v %v", r, fb, ok)98+ }99+}100+101+// checkNextRow compares nextRow both ways with the map.102+func checkNextRow(t *testing.T, st *cellStore, c, row int) {103+ t.Helper()104+ next, ok := st.stored.nextRow(c, row, 1)105+ prev, okp := st.stored.nextRow(c, row, -1)106+ want1, ok1 := MaxRows, false107+ want2, ok2 := -1, false108+ for a := range st.all() {109+ if a.Col != c {110+ continue83111 }84- c, row := rng.IntN(40), rng.IntN(MaxRows)85- next, ok := st.stored.nextRow(c, row, 1)86- want1, ok1 := MaxRows, false87- prev, okp := st.stored.nextRow(c, row, -1)88- want2, ok2 := -1, false89- for a := range st.all() {90- if a.Col == c && a.Row >= row && a.Row < want1 {91- want1, ok1 = a.Row, true92- }93- if a.Col == c && a.Row <= row && a.Row > want2 {94- want2, ok2 = a.Row, true95- }112+ if a.Row >= row && a.Row < want1 {113+ want1, ok1 = a.Row, true96114 }97- if ok != ok1 || ok && next != want1 || okp != ok2 || okp && prev != want2 {98- t.Fatalf("nextRow(%d, %d) = %d %v / %d %v, want %d %v / %d %v", c, row, next, ok, prev, okp, want1, ok1, want2, ok2)115+ if a.Row <= row && a.Row > want2 {116+ want2, ok2 = a.Row, true99117 }100118 }119+ if ok != ok1 || ok && next != want1 || okp != ok2 || okp && prev != want2 {120+ t.Fatalf("nextRow(%d, %d) = %d %v / %d %v, want %d %v / %d %v", c, row, next, ok, prev, okp, want1, ok1, want2, ok2)121+ }101122 }