9fans.net/go@v0.0.7/cmd/samterm/rasp.go (about)

     1  package main
     2  
     3  func rinit(r *Rasp) {
     4  	r.nrunes = 0
     5  	r.sect = nil
     6  }
     7  
     8  func free(interface{}) {}
     9  
    10  func rclear(r *Rasp) {
    11  	var ns *Section
    12  	for s := r.sect; s != nil; s = ns {
    13  		ns = s.next
    14  		free(s.text)
    15  		free(s)
    16  	}
    17  	r.sect = nil
    18  }
    19  
    20  func rsinsert(r *Rasp, s *Section) *Section {
    21  	t := new(Section)
    22  	if r.sect == s { /* includes empty list case: r->sect==s==0 */
    23  		r.sect = t
    24  		t.next = s
    25  	} else {
    26  		u := r.sect
    27  		if u == nil {
    28  			panic("rsinsert 1")
    29  		}
    30  		for {
    31  			if u.next == s {
    32  				t.next = s
    33  				u.next = t
    34  				goto Return
    35  			}
    36  			u = u.next
    37  			if u == nil {
    38  				break
    39  			}
    40  		}
    41  		panic("rsinsert 2")
    42  	}
    43  Return:
    44  	return t
    45  }
    46  
    47  func rsdelete(r *Rasp, s *Section) {
    48  	if s == nil {
    49  		panic("rsdelete")
    50  	}
    51  	if r.sect == s {
    52  		r.sect = s.next
    53  		goto Free
    54  	}
    55  	for t := r.sect; t != nil; t = t.next {
    56  		if t.next == s {
    57  			t.next = s.next
    58  			goto Free
    59  		}
    60  	}
    61  	panic("rsdelete 2")
    62  
    63  Free:
    64  	if s.text != nil {
    65  		free(s.text)
    66  	}
    67  	free(s)
    68  
    69  }
    70  
    71  func splitsect(r *Rasp, s *Section, n0 int) {
    72  	if s == nil {
    73  		panic("splitsect")
    74  	}
    75  	rsinsert(r, s.next)
    76  	if s.text == nil {
    77  		s.next.text = nil
    78  	} else {
    79  		s.next.text = make([]rune, TBLOCKSIZE)
    80  		copy(s.next.text, s.text[n0:s.nrunes])
    81  	}
    82  	s.next.nrunes = s.nrunes - n0
    83  	s.nrunes = n0
    84  }
    85  
    86  func findsect(r *Rasp, s *Section, p int, q int) *Section {
    87  	if s == nil && p != q {
    88  		panic("findsect")
    89  	}
    90  	for ; s != nil && p+s.nrunes <= q; s = s.next {
    91  		p += s.nrunes
    92  	}
    93  	if p != q {
    94  		splitsect(r, s, q-p)
    95  		s = s.next
    96  	}
    97  	return s
    98  }
    99  
   100  func rresize(r *Rasp, a int, old int, new int) {
   101  	s := findsect(r, r.sect, 0, a)
   102  	t := findsect(r, s, a, a+old)
   103  	var ns *Section
   104  	for ; s != t; s = ns {
   105  		ns = s.next
   106  		rsdelete(r, s)
   107  	}
   108  	/* now insert the new piece before t */
   109  	if new > 0 {
   110  		ns = rsinsert(r, t)
   111  		ns.nrunes = new
   112  		ns.text = nil
   113  	}
   114  	r.nrunes += new - old
   115  }
   116  
   117  func rdata(r *Rasp, p0 int, p1 int, cp []rune) {
   118  	s := findsect(r, r.sect, 0, p0)
   119  	t := findsect(r, s, p0, p1)
   120  	var ns *Section
   121  	for ; s != t; s = ns {
   122  		ns = s.next
   123  		if s.text != nil {
   124  			panic("rdata")
   125  		}
   126  		rsdelete(r, s)
   127  	}
   128  	p1 -= p0
   129  	s = rsinsert(r, t)
   130  	s.text = make([]rune, TBLOCKSIZE)
   131  	copy(s.text, cp[:p1])
   132  	s.nrunes = p1
   133  }
   134  
   135  func rclean(r *Rasp) {
   136  	for s := r.sect; s != nil; s = s.next {
   137  		for s.next != nil && (s.text != nil) == (s.next.text != nil) {
   138  			if s.text != nil {
   139  				if s.nrunes+s.next.nrunes > TBLOCKSIZE {
   140  					break
   141  				}
   142  				copy(s.text[s.nrunes:s.nrunes+s.next.nrunes], s.next.text[:s.next.nrunes])
   143  			}
   144  			s.nrunes += s.next.nrunes
   145  			rsdelete(r, s.next)
   146  		}
   147  	}
   148  }
   149  
   150  var raspbuf []rune
   151  
   152  func rload(r *Rasp, p0 int, p1 int) []rune {
   153  	for cap(raspbuf) < p1-p0 {
   154  		raspbuf = append(raspbuf[:cap(raspbuf)], 0)
   155  	}
   156  
   157  	p := 0
   158  	s := r.sect
   159  	for ; s != nil && p+s.nrunes <= p0; s = s.next {
   160  		p += s.nrunes
   161  	}
   162  	nb := 0
   163  	for p < p1 && s != nil {
   164  		/*
   165  		 * Subtle and important.  If we are preparing to handle an 'rdata'
   166  		 * call, it's because we have an 'rresize' hole here, so the
   167  		 * screen doesn't have data for that space anyway (it got cut
   168  		 * first).  So pretend it isn't there.
   169  		 */
   170  		if s.text != nil {
   171  			n := s.nrunes - (p0 - p)
   172  			if n > p1-p0 { /* all in this section */
   173  				n = p1 - p0
   174  			}
   175  			copy(raspbuf[nb:nb+n], s.text[p0-p:])
   176  			nb += n
   177  		}
   178  		p += s.nrunes
   179  		p0 = p
   180  		s = s.next
   181  	}
   182  	return raspbuf[:nb]
   183  }
   184  
   185  func rmissing(r *Rasp, p0 int, p1 int) int {
   186  	p := 0
   187  	s := r.sect
   188  	for ; s != nil && p+s.nrunes <= p0; s = s.next {
   189  		p += s.nrunes
   190  	}
   191  	nm := 0
   192  	for p < p1 && s != nil {
   193  		if s.text == nil {
   194  			n := s.nrunes - (p0 - p)
   195  			if n > p1-p0 { /* all in this section */
   196  				n = p1 - p0
   197  			}
   198  			nm += n
   199  		}
   200  		p += s.nrunes
   201  		p0 = p
   202  		s = s.next
   203  	}
   204  	return nm
   205  }
   206  
   207  func rcontig(r *Rasp, p0 int, p1 int, text bool) int {
   208  	p := 0
   209  	s := r.sect
   210  	for ; s != nil && p+s.nrunes <= p0; s = s.next {
   211  		p += s.nrunes
   212  	}
   213  	np := 0
   214  	for p < p1 && s != nil && text == (s.text != nil) {
   215  		n := s.nrunes - (p0 - p)
   216  		if n > p1-p0 { /* all in this section */
   217  			n = p1 - p0
   218  		}
   219  		np += n
   220  		p += s.nrunes
   221  		p0 = p
   222  		s = s.next
   223  	}
   224  	return np
   225  }