##
## clirc -- An IRC client in Python.
## linelist.py - List of strings.
##
## Copyleft 1997-2000 Teemu Kalvas <chery@s2.org>
##

class LineList:
    def __init__( self, t ):
	self.t = t
	self.lines = 0
	self.data = ()

    def lookup( self, pos ):
	block = self.data
	while 1:
	    for bl, id in block:
		if pos < id:
		    if id == 1:
			return bl
		    block = bl
		    break
		pos = pos - id
	    else:
		return ()

    def insert( self, data, pos ):
	if not self.data:
	    if pos == 0:
		self.data = [(data, 1)]
		self.lines = 1
		return 1
	    else:
		return 0
	parent = self.data
	if len( parent ) == 2 * self.t:
	    b = parent[:self.t]
	    p = reduce( lambda x, y: x + y[1], b, 0 )
	    c = parent[self.t:]
	    self.data = [(b, p), (c, self.lines + 1 - p)]
	    if pos < p:
		parent = b
	    else:
		pos = pos - p
		parent = c
	while 1:
	    desc = 0
	    thr = len( parent ) - 1
	    for bl, id in parent:
		if pos < id or pos == id and desc == thr:
		    if id == 1:
			if pos < id:
			    parent.insert( desc, (data, 1) )
			else:
			    parent.append( (data, 1) )
			self.lines = self.lines + 1
			return 1
		    block = bl
		    break
		pos = pos - id
		desc = desc + 1
	    else:
		return 0
	    parent[desc] = parent[desc][0], parent[desc][1] + 1
	    if len( block ) == 2 * self.t:
		b = block[:self.t]
		n = reduce( lambda x, y: x + y[1], b, 0 )
		parent.insert( desc, (b, n) )
		c = block[self.t:]
		parent[desc + 1] = c, parent[desc + 1][1] - n
		if pos < n:
		    parent = b
		else:
		    pos = pos - n
		    parent = c
	    else:
		parent = block

    def append( self, data ):
	return self.insert( data, self.lines )

    def remove( self, pos ):
	if pos >= self.lines:
	    return
	block = self.data
	while 1:
	    desc = 0
	    for bl, id in block:
		if pos < id:
		    if id == 1:
			del block[desc]
			if len( self.data ) == 1:
			    self.data = self.data[0][0]
			return
		    if len( bl ) == self.t:
			if desc > 0 and len( block[desc - 1][0] ) > self.t:
			    left = block[desc - 1][0]
			    i = len( left ) - 1
			    block[desc] = [left[i]] + bl, left[i][1] + id - 1
			    block[desc - 1] = (left[:i],
					       block[desc - 1][1] - left[i][1])
			elif desc < len( block ) - 1:
			    right = block[desc + 1][0]
			    block[desc] = bl + [right[0]], id + right[0][1] - 1
			    block[desc + 1] = (right[1:],
					       block[desc +1][1] - right[0][1])
			else:
			    desc = max( 1, desc )
			    block[desc - 1:desc + 1] = \
				       [(block[desc - 1][0] + block[desc][0],
					 block[desc-1][1] + block[desc][1] -1)]
			    desc = desc - 1
		    else:
			block[desc] = bl, id - 1
		    block = block[desc][0]
		    break
		pos = pos - id
		desc = desc + 1

    def drop():
	self.remove( 0 )

## End. ##
