9fans.net/go@v0.0.5/draw/frame/frdelete.go (about)

     1  package frame
     2  
     3  import "9fans.net/go/draw"
     4  
     5  // Delete deletes from f the text between p0 and p1;
     6  // p1 points at the first rune beyond the deletion.
     7  func (f *Frame) Delete(p0, p1 int) int {
     8  	if p0 >= f.NumChars || p0 == p1 || f.B == nil {
     9  		return 0
    10  	}
    11  	if p1 > f.NumChars {
    12  		p1 = f.NumChars
    13  	}
    14  	n0 := f.findbox(0, 0, p0)
    15  	if n0 >= len(f.box) {
    16  		drawerror(f.Display, "off end in frdelete")
    17  	}
    18  	n1 := f.findbox(n0, p0, p1)
    19  	pt0 := f.ptofcharnb(p0, n0)
    20  	pt1 := f.PointOf(p1)
    21  	if f.P0 == f.P1 {
    22  		f.Tick(f.PointOf(f.P0), false)
    23  	}
    24  	nn0 := n0
    25  	ppt0 := pt0
    26  	f.modified = true
    27  
    28  	// Invariants:
    29  	//   - pt0 points to beginning, pt1 points to end
    30  	//   - n0 is box containing beginning of stuff being deleted
    31  	//   - n1, b are box containing beginning of stuff to be kept after deletion
    32  	//   - cn1 is char position of n1
    33  	//   - f.P0 and f.P1 are not adjusted until after all deletion is done
    34  	cn1 := p1
    35  	for pt1.X != pt0.X && n1 < len(f.box) {
    36  		b := &f.box[n1]
    37  		f.cklinewrap0(&pt0, b)
    38  		f.cklinewrap(&pt1, b)
    39  		n := f.canfit(pt0, b)
    40  		if n == 0 {
    41  			drawerror(f.Display, "_frcanfit==0")
    42  		}
    43  		r := draw.Rectangle{pt0, pt0}
    44  		r.Max.Y += f.Font.Height
    45  		if b.nrune > 0 {
    46  			w0 := b.wid
    47  			if n != b.nrune {
    48  				f.splitbox(n1, n)
    49  				b = &f.box[n1]
    50  			}
    51  			r.Max.X += b.wid
    52  			f.B.Draw(r, f.B, nil, pt1)
    53  			cn1 += b.nrune
    54  
    55  			// blank remainder of line
    56  			r.Min.X = r.Max.X
    57  			r.Max.X += w0 - b.wid
    58  			if r.Max.X > f.R.Max.X {
    59  				r.Max.X = f.R.Max.X
    60  			}
    61  			f.B.Draw(r, f.Cols[BACK], nil, r.Min)
    62  		} else {
    63  			r.Max.X += f.newwid0(pt0, b)
    64  			if r.Max.X > f.R.Max.X {
    65  				r.Max.X = f.R.Max.X
    66  			}
    67  			col := f.Cols[BACK]
    68  			if f.P0 <= cn1 && cn1 < f.P1 {
    69  				col = f.Cols[HIGH]
    70  			}
    71  			f.B.Draw(r, col, nil, pt0)
    72  			cn1++
    73  		}
    74  		f.advance(&pt1, b)
    75  		pt0.X += f.newwid(pt0, b)
    76  		f.box[n0] = f.box[n1]
    77  		n0++
    78  		n1++
    79  	}
    80  	if n1 == len(f.box) && pt0.X != pt1.X { // deleting last thing in window; must clean up
    81  		f.SelectPaint(pt0, pt1, f.Cols[BACK])
    82  	}
    83  	if pt1.Y != pt0.Y {
    84  		pt2 := f.ptofcharptb(32767, pt1, n1) // TODO 32767
    85  		if pt2.Y > f.R.Max.Y {
    86  			drawerror(f.Display, "frptofchar in frdelete")
    87  		}
    88  		if n1 < len(f.box) {
    89  			q0 := pt0.Y + f.Font.Height
    90  			q1 := pt1.Y + f.Font.Height
    91  			q2 := pt2.Y + f.Font.Height
    92  			if q2 > f.R.Max.Y {
    93  				q2 = f.R.Max.Y
    94  			}
    95  			f.B.Draw(draw.Rect(pt0.X, pt0.Y, pt0.X+(f.R.Max.X-pt1.X), q0), f.B, nil, pt1)
    96  			f.B.Draw(draw.Rect(f.R.Min.X, q0, f.R.Max.X, q0+(q2-q1)), f.B, nil, draw.Pt(f.R.Min.X, q1))
    97  			f.SelectPaint(draw.Pt(pt2.X, pt2.Y-(pt1.Y-pt0.Y)), pt2, f.Cols[BACK])
    98  		} else {
    99  			f.SelectPaint(pt0, pt2, f.Cols[BACK])
   100  		}
   101  	}
   102  	f.delbox(n0, n1-1)
   103  	if nn0 > 0 && f.box[nn0-1].nrune >= 0 && ppt0.X-f.box[nn0-1].wid >= f.R.Min.X {
   104  		nn0--
   105  		ppt0.X -= f.box[nn0].wid
   106  	}
   107  	if n0 < len(f.box)-1 {
   108  		n0++
   109  	}
   110  	f.clean(ppt0, nn0, n0)
   111  	if f.P1 > p1 {
   112  		f.P1 -= p1 - p0
   113  	} else if f.P1 > p0 {
   114  		f.P1 = p0
   115  	}
   116  	if f.P0 > p1 {
   117  		f.P0 -= p1 - p0
   118  	} else if f.P0 > p0 {
   119  		f.P0 = p0
   120  	}
   121  	f.NumChars -= p1 - p0
   122  	if f.P0 == f.P1 {
   123  		f.Tick(f.PointOf(f.P0), true)
   124  	}
   125  	pt0 = f.PointOf(f.NumChars)
   126  	n := f.NumLines
   127  	f.NumLines = (pt0.Y - f.R.Min.Y) / f.Font.Height
   128  	if pt0.X > f.R.Min.X {
   129  		f.NumLines++
   130  	}
   131  	return n - f.NumLines
   132  }